Merge inbound to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Wed, 22 Mar 2017 17:10:01 -0700
changeset 348980 7513b3f42058e9bcf9950d4acf4647d4ad2240f0
parent 348938 08b46c736a62d3d572d67259420a093d564afd2e (current diff)
parent 348979 8b30d5f5b423e6047eff9095c6f7181c331c8972 (diff)
child 349094 89b93d310da5bc7f86ebcdb8fe580d47a610757a
push id31540
push userkwierso@gmail.com
push dateThu, 23 Mar 2017 00:10:08 +0000
treeherdermozilla-central@7513b3f42058 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.0a1
first release with
nightly linux32
7513b3f42058 / 55.0a1 / 20170323110205 / files
nightly linux64
7513b3f42058 / 55.0a1 / 20170323110205 / files
nightly mac
7513b3f42058 / 55.0a1 / 20170323030203 / files
nightly win32
7513b3f42058 / 55.0a1 / 20170323030203 / files
nightly win64
7513b3f42058 / 55.0a1 / 20170323030203 / 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 inbound to central, a=merge MozReview-Commit-ID: EQ7w1Gld1K2
browser/base/content/tabbrowser.xml
caps/nsExpandedPrincipal.cpp
caps/nsExpandedPrincipal.h
caps/nsNullPrincipal.cpp
caps/nsNullPrincipal.h
caps/nsNullPrincipalURI.cpp
caps/nsNullPrincipalURI.h
caps/nsPrincipal.cpp
caps/nsPrincipal.h
caps/nsSystemPrincipal.cpp
caps/nsSystemPrincipal.h
gfx/thebes/gfxFontconfigFonts.cpp
gfx/thebes/gfxFontconfigUtils.cpp
testing/web-platform/tests/storage/interfaces.html
--- a/accessible/base/TextAttrs.cpp
+++ b/accessible/base/TextAttrs.cpp
@@ -13,20 +13,16 @@
 #include "gfxFont.h"
 #include "nsFontMetrics.h"
 #include "nsLayoutUtils.h"
 #include "nsContainerFrame.h"
 #include "HyperTextAccessible.h"
 #include "mozilla/AppUnits.h"
 #include "mozilla/gfx/2D.h"
 
-#if defined(MOZ_WIDGET_GTK)
-#include "gfxPlatformGtk.h" // xxx - for UseFcFontList
-#endif
-
 using namespace mozilla;
 using namespace mozilla::a11y;
 
 ////////////////////////////////////////////////////////////////////////////////
 // TextAttrsMgr
 ////////////////////////////////////////////////////////////////////////////////
 
 void
@@ -647,38 +643,24 @@ TextAttrsMgr::FontWeightTextAttr::
   // When there doesn't exist a bold font in the family and so the rendering of
   // a non-bold font face is changed so that the user sees what looks like a
   // bold font, i.e. synthetic bolding is used. IsSyntheticBold method is only
   // needed on Mac, but it is "safe" to use on all platforms.  (For non-Mac
   // platforms it always return false.)
   if (font->IsSyntheticBold())
     return 700;
 
-  bool useFontEntryWeight = true;
-
-  // Under Linux, when gfxPangoFontGroup code is used,
-  // font->GetStyle()->weight will give the absolute weight requested of the
-  // font face. The gfxPangoFontGroup code uses the gfxFontEntry constructor
-  // which doesn't initialize the weight field.
-#if defined(MOZ_WIDGET_GTK)
-  useFontEntryWeight = gfxPlatformGtk::UseFcFontList();
-#endif
-
-  if (useFontEntryWeight) {
-    // On Windows, font->GetStyle()->weight will give the same weight as
-    // fontEntry->Weight(), the weight of the first font in the font group,
-    // which may not be the weight of the font face used to render the
-    // characters. On Mac, font->GetStyle()->weight will just give the same
-    // number as getComputedStyle(). fontEntry->Weight() will give the weight
-    // of the font face used.
-    gfxFontEntry *fontEntry = font->GetFontEntry();
-    return fontEntry->Weight();
-  } else {
-    return font->GetStyle()->weight;
-  }
+  // On Windows, font->GetStyle()->weight will give the same weight as
+  // fontEntry->Weight(), the weight of the first font in the font group,
+  // which may not be the weight of the font face used to render the
+  // characters. On Mac, font->GetStyle()->weight will just give the same
+  // number as getComputedStyle(). fontEntry->Weight() will give the weight
+  // of the font face used.
+  gfxFontEntry *fontEntry = font->GetFontEntry();
+  return fontEntry->Weight();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // AutoGeneratedTextAttr
 ////////////////////////////////////////////////////////////////////////////////
 TextAttrsMgr::AutoGeneratedTextAttr::
   AutoGeneratedTextAttr(HyperTextAccessible* aHyperTextAcc,
                         Accessible* aAccessible) :
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -213,27 +213,28 @@ function onIndexedDBClear() {
 }
 
 function onIndexedDBUsageCallback(request) {
   let uri = request.principal.URI;
   if (!uri.equals(gPermURI)) {
     throw new Error("Callback received for bad URI: " + uri);
   }
 
-  if (request.usage) {
+  let usage = request.result.usage;
+  if (usage) {
     if (!("DownloadUtils" in window)) {
       Components.utils.import("resource://gre/modules/DownloadUtils.jsm");
     }
 
     var status = document.getElementById("indexedDBStatus");
     var button = document.getElementById("indexedDBClear");
 
     status.value =
       gBundle.getFormattedString("indexedDBUsage",
-                                 DownloadUtils.convertByteUnits(request.usage));
+                                 DownloadUtils.convertByteUnits(usage));
     status.removeAttribute("hidden");
     button.removeAttribute("hidden");
   }
 }
 
 function fillInPluginPermissionTemplate(aPluginName, aPermissionString) {
   let permPluginTemplate = document.getElementById("permPluginTemplate").cloneNode(true);
   permPluginTemplate.setAttribute("permString", aPermissionString);
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -63,19 +63,16 @@
       <field name="mURIFixup" readonly="true">
         Components.classes["@mozilla.org/docshell/urifixup;1"]
                   .getService(Components.interfaces.nsIURIFixup);
       </field>
       <field name="_unifiedComplete" readonly="true">
          Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
                    .getService(Components.interfaces.mozIPlacesAutoComplete);
       </field>
-      <field name="AppConstants" readonly="true">
-        (Components.utils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants;
-      </field>
       <field name="mTabBox" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "tabbox");
       </field>
       <field name="mPanelContainer" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer");
       </field>
       <field name="mStringBundle">
         document.getAnonymousElementByAttribute(this, "anonid", "tbstringbundle");
@@ -103,17 +100,17 @@
       </field>
       <field name="mIsBusy">
         false
       </field>
       <field name="_outerWindowIDBrowserMap">
         new Map();
       </field>
       <field name="arrowKeysShouldWrap" readonly="true">
-        this.AppConstants.platform == "macosx";
+        AppConstants == "macosx";
       </field>
 
       <field name="_autoScrollPopup">
         null
       </field>
 
       <field name="_previewMode">
         false
@@ -2650,26 +2647,28 @@
         <body>
           <![CDATA[
             if (aTab.closing ||
                 this._windowIsClosing)
               return false;
 
             var browser = this.getBrowserForTab(aTab);
 
-            if (!aTab._pendingPermitUnload && !aAdoptedByTab && !aSkipPermitUnload) {
+            if (!aTab._pendingPermitUnload &&
+                !aSkipPermitUnload &&
+                aTab.linkedPanel &&
+                !aAdoptedByTab) {
               // We need to block while calling permitUnload() because it
               // processes the event queue and may lead to another removeTab()
               // call before permitUnload() returns.
 
               TelemetryStopwatch.start("FX_TAB_CLOSE_PERMIT_UNLOAD_TIME_MS", aTab);
 
               aTab._pendingPermitUnload = true;
-              let {permitUnload, timedOut} = aTab.linkedPanel ?
-                  browser.permitUnload() : {permitUnload: true, timedOut: false};
+              let {permitUnload, timedOut} = browser.permitUnload();
               delete aTab._pendingPermitUnload;
 
               TelemetryStopwatch.finish("FX_TAB_CLOSE_PERMIT_UNLOAD_TIME_MS", aTab);
 
               // If we were closed during onbeforeunload, we return false now
               // so we don't (try to) close the same tab again. Of course, we
               // also stop if the unload was cancelled by the user:
               if (aTab.closing || (!timedOut && !permitUnload)) {
@@ -3420,17 +3419,17 @@
         </body>
       </method>
 
       <!-- Opens a given tab to a non-remote window. -->
       <method name="openNonRemoteWindow">
         <parameter name="aTab"/>
         <body>
           <![CDATA[
-            if (!this.AppConstants.E10S_TESTING_ONLY) {
+            if (!AppConstants.E10S_TESTING_ONLY) {
               throw "This method is intended only for e10s testing!";
             }
             let url = aTab.linkedBrowser.currentURI.spec;
             return window.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no,non-remote", url);
           ]]>
         </body>
       </method>
 
@@ -4032,17 +4031,17 @@
               this.lastVisibleTab = this.visibleTab;
             },
 
             assert(cond) {
               if (!cond) {
                 dump("Assertion failure\n" + Error().stack);
 
                 // Don't break a user's browser if an assertion fails.
-                if (this.tabbrowser.AppConstants.DEBUG) {
+                if (AppConstants.DEBUG) {
                   throw new Error("Assertion failure");
                 }
               }
             },
 
             // We've decided to try to load requestedTab.
             loadRequestedTab() {
               this.assert(!this.loadTimer);
@@ -4808,17 +4807,17 @@
                 return;
               case aEvent.DOM_VK_PAGE_DOWN:
                 this.moveTabForward();
                 aEvent.preventDefault();
                 return;
             }
           }
 
-          if (this.AppConstants.platform != "macosx") {
+          if (AppConstants.platform != "macosx") {
             if (aEvent.ctrlKey && !aEvent.shiftKey && !aEvent.metaKey &&
                 aEvent.keyCode == KeyEvent.DOM_VK_F4 &&
                 !this.mCurrentTab.pinned) {
               this.removeCurrentTab({animate: true});
               aEvent.preventDefault();
             }
           }
         ]]></body>
@@ -4830,17 +4829,17 @@
           if (!aEvent.isTrusted) {
             // Don't let untrusted events mess with tabs.
             return;
           }
 
           if (aEvent.altKey)
             return;
 
-          if (this.AppConstants.platform == "macosx") {
+          if (AppConstants.platform == "macosx") {
             if (!aEvent.metaKey)
               return;
 
             var offset = 1;
             switch (aEvent.charCode) {
               case "}".charCodeAt(0):
                 offset = -1;
               case "{".charCodeAt(0):
@@ -4893,17 +4892,17 @@
                   "tabs.unmuteAudio.background.tooltip" :
                   "tabs.muteAudio.background.tooltip";
               }
 
               label = this.mStringBundle.getString(stringID);
             }
           } else {
             label = tab.getAttribute("label");
-            if (this.AppConstants.E10S_TESTING_ONLY &&
+            if (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) {
@@ -5176,17 +5175,17 @@
           Services.obs.addObserver(this, "contextual-identity-updated", false);
 
           this.mCurrentTab = this.tabContainer.firstChild;
           const nsIEventListenerService =
             Components.interfaces.nsIEventListenerService;
           let els = Components.classes["@mozilla.org/eventlistenerservice;1"]
                               .getService(nsIEventListenerService);
           els.addSystemEventListener(document, "keydown", this, false);
-          if (this.AppConstants.platform == "macosx") {
+          if (AppConstants.platform == "macosx") {
             els.addSystemEventListener(document, "keypress", this, false);
           }
           window.addEventListener("sizemodechange", this);
 
           var uniqueId = this._generateUniquePanelID();
           this.mPanelContainer.childNodes[0].id = uniqueId;
           this.mCurrentTab.linkedPanel = uniqueId;
           this.mCurrentTab.permanentKey = this.mCurrentBrowser.permanentKey;
@@ -5293,17 +5292,17 @@
             this._tabFilters.delete(tab);
             this._tabListeners.delete(tab);
           }
           const nsIEventListenerService =
             Components.interfaces.nsIEventListenerService;
           let els = Components.classes["@mozilla.org/eventlistenerservice;1"]
                               .getService(nsIEventListenerService);
           els.removeSystemEventListener(document, "keydown", this, false);
-          if (this.AppConstants.platform == "macosx") {
+          if (AppConstants.platform == "macosx") {
             els.removeSystemEventListener(document, "keypress", this, false);
           }
           window.removeEventListener("sizemodechange", this);
 
           if (gMultiProcessBrowser) {
             let messageManager = window.getGroupMessageManager("browsers");
             messageManager.removeMessageListener("DOMTitleChanged", this);
             window.messageManager.removeMessageListener("contextmenu", this);
@@ -6653,17 +6652,17 @@
         event.stopPropagation();
       ]]></handler>
 
       <handler event="keydown" group="system"><![CDATA[
         if (event.altKey || event.shiftKey)
           return;
 
         let wrongModifiers;
-        if (this.tabbrowser.AppConstants.platform == "macosx") {
+        if (AppConstants.platform == "macosx") {
           wrongModifiers = !event.metaKey;
         } else {
           wrongModifiers = !event.ctrlKey || event.metaKey;
         }
 
         if (wrongModifiers)
           return;
 
@@ -6736,17 +6735,17 @@
         let toDrag = canvas;
         let dragImageOffset = -16;
         if (gMultiProcessBrowser) {
           var context = canvas.getContext("2d");
           context.fillStyle = "white";
           context.fillRect(0, 0, canvas.width, canvas.height);
 
           let captureListener;
-          let platform = this.tabbrowser.AppConstants.platform;
+          let platform = AppConstants.platform;
           // On Windows and Mac we can update the drag image during a drag
           // using updateDragImage. On Linux, we can use a panel.
           if (platform == "win" || platform == "macosx") {
             captureListener = function() {
               dt.updateDragImage(canvas, dragImageOffset, dragImageOffset);
             }
           } else {
             // Create a panel to use it in setDragImage
@@ -7021,17 +7020,17 @@
           // resize _before_ move to ensure the window fits the new screen.  if
           // the window is too large for its screen, the window manager may do
           // automatic repositioning.
           window.resizeTo(winWidth, winHeight);
           window.moveTo(left, top);
           window.focus();
         } else {
           let props = { screenX: left, screenY: top };
-          if (this.tabbrowser.AppConstants.platform != "win") {
+          if (AppConstants.platform != "win") {
             props.outerWidth = winWidth;
             props.outerHeight = winHeight;
           }
           this.tabbrowser.replaceTabWithWindow(draggedTab, props);
         }
         event.stopPropagation();
       ]]></handler>
 
--- a/browser/components/preferences/SiteDataManager.jsm
+++ b/browser/components/preferences/SiteDataManager.jsm
@@ -78,17 +78,17 @@ this.SiteDataManager = {
 
   _updateQuota() {
     this._quotaUsageRequests = [];
     let promises = [];
     for (let site of this._sites.values()) {
       promises.push(new Promise(resolve => {
         let callback = {
           onUsageResult(request) {
-            site.quotaUsage = request.usage;
+            site.quotaUsage = request.result.usage;
             resolve();
           }
         };
         // XXX: The work of integrating localStorage into Quota Manager is in progress.
         //      After the bug 742822 and 1286798 landed, localStorage usage will be included.
         //      So currently only get indexedDB usage.
         this._quotaUsageRequests.push(
           this._qms.getUsageForPrincipal(site.perm.principal, callback));
--- a/browser/components/preferences/in-content/tests/browser_advanced_siteData.js
+++ b/browser/components/preferences/in-content/tests/browser_advanced_siteData.js
@@ -127,17 +127,17 @@ function getPersistentStoragePermStatus(
   let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
   return Services.perms.testExactPermissionFromPrincipal(principal, "persistent-storage");
 }
 
 function getQuotaUsage(origin) {
   return new Promise(resolve => {
     let uri = NetUtil.newURI(origin);
     let principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {});
-    Services.qms.getUsageForPrincipal(principal, request => resolve(request.usage));
+    Services.qms.getUsageForPrincipal(principal, request => resolve(request.result.usage));
   });
 }
 
 // XXX: The intermittent bug 1331851
 // The implementation of nsICacheStorageConsumptionObserver must be passed as weak referenced,
 // so we must hold this observer here well. If we didn't, there would be a chance that
 // in Linux debug test run the observer was released before the operation at gecko was completed
 // (may be because of a relatively quicker GC cycle or a relatively slower operation).
--- a/build/valgrind/i386-redhat-linux-gnu.sup
+++ b/build/valgrind/i386-redhat-linux-gnu.sup
@@ -14,26 +14,16 @@
 {
    Bug 793598
    Memcheck:Leak
    ...
    obj:/lib/libdbus-1.so.3.4.0
    ...
 }
 {
-   Bug 793600
-   Memcheck:Leak
-   fun:realloc
-   obj:/usr/lib/libfontconfig.so.1.4.4
-   ...
-   fun:FcDefaultSubstitute
-   fun:_ZN17gfxPangoFontGroup11MakeFontSetEP14_PangoLanguagedP9nsAutoRefI10_FcPatternE
-   ...
-}
-{
    Bug 794366
    Memcheck:Leak
    ...
    obj:/usr/lib/libgtk-x11-2.0.so.0.1800.9
    ...
 }
 {
    Bug 794368
--- a/build/valgrind/x86_64-redhat-linux-gnu.sup
+++ b/build/valgrind/x86_64-redhat-linux-gnu.sup
@@ -13,26 +13,16 @@
 }
 {
    Bug 793598
    Memcheck:Leak
    ...
    obj:/lib64/libdbus-1.so.3.4.0
    ...
 }
-{
-   Bug 793600
-   Memcheck:Leak
-   fun:realloc
-   obj:/usr/lib64/libfontconfig.so.1.4.4
-   ...
-   fun:FcDefaultSubstitute
-   fun:_ZN17gfxPangoFontGroup11MakeFontSetEP14_PangoLanguagedP9nsAutoRefI10_FcPatternE
-   ...
-}
 # Fontconfig is going fancy with its cache structure and that confuses valgrind.
 # https://bugs.freedesktop.org/show_bug.cgi?id=8215
 # https://bugs.freedesktop.org/show_bug.cgi?id=8428
 {
    Bug 1187649
    Memcheck:Leak
    match-leak-kinds: definite
    fun:realloc
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -7,302 +7,32 @@
 #include "mozilla/BasePrincipal.h"
 
 #include "nsDocShell.h"
 #ifdef MOZ_CRASHREPORTER
 #include "nsExceptionHandler.h"
 #endif
 #include "nsIAddonPolicyService.h"
 #include "nsIContentSecurityPolicy.h"
-#include "nsIEffectiveTLDService.h"
 #include "nsIObjectInputStream.h"
 #include "nsIObjectOutputStream.h"
 
-#include "nsPrincipal.h"
+#include "ContentPrincipal.h"
 #include "nsNetUtil.h"
 #include "nsIURIWithPrincipal.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsScriptSecurityManager.h"
 #include "nsServiceManagerUtils.h"
 
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/CSPDictionariesBinding.h"
-#include "mozilla/dom/quota/QuotaManager.h"
 #include "mozilla/dom/ToJSValue.h"
-#include "mozilla/dom/URLSearchParams.h"
 
 namespace mozilla {
 
-using dom::URLParams;
-
-bool OriginAttributes::sFirstPartyIsolation = false;
-bool OriginAttributes::sRestrictedOpenerAccess = false;
-
-void
-OriginAttributes::InitPrefs()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  static bool sInited = false;
-  if (!sInited) {
-    sInited = true;
-    Preferences::AddBoolVarCache(&sFirstPartyIsolation,
-                                 "privacy.firstparty.isolate");
-    Preferences::AddBoolVarCache(&sRestrictedOpenerAccess,
-                                 "privacy.firstparty.isolate.restrict_opener_access");
-  }
-}
-
-void
-OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument,
-                                      nsIURI* aURI)
-{
-  bool isFirstPartyEnabled = IsFirstPartyEnabled();
-
-  // If the pref is off or this is not a top level load, bail out.
-  if (!isFirstPartyEnabled || !aIsTopLevelDocument) {
-    return;
-  }
-
-  nsCOMPtr<nsIEffectiveTLDService> tldService =
-    do_GetService(NS_EFFECTIVETLDSERVICE_CONTRACTID);
-  MOZ_ASSERT(tldService);
-  if (!tldService) {
-    return;
-  }
-
-  nsAutoCString baseDomain;
-  nsresult rv = tldService->GetBaseDomain(aURI, 0, baseDomain);
-  if (NS_FAILED(rv)) {
-    nsAutoCString scheme;
-    rv = aURI->GetScheme(scheme);
-    NS_ENSURE_SUCCESS_VOID(rv);
-    if (scheme.EqualsLiteral("about")) {
-      baseDomain.AssignLiteral(ABOUT_URI_FIRST_PARTY_DOMAIN);
-    }
-  }
-
-  mFirstPartyDomain = NS_ConvertUTF8toUTF16(baseDomain);
-}
-
-void
-OriginAttributes::SetFirstPartyDomain(const bool aIsTopLevelDocument,
-                                      const nsACString& aDomain)
-{
-  bool isFirstPartyEnabled = IsFirstPartyEnabled();
-
-  // If the pref is off or this is not a top level load, bail out.
-  if (!isFirstPartyEnabled || !aIsTopLevelDocument) {
-    return;
-  }
-
-  mFirstPartyDomain = NS_ConvertUTF8toUTF16(aDomain);
-}
-
-void
-OriginAttributes::CreateSuffix(nsACString& aStr) const
-{
-  URLParams params;
-  nsAutoString value;
-
-  //
-  // Important: While serializing any string-valued attributes, perform a
-  // release-mode assertion to make sure that they don't contain characters that
-  // will break the quota manager when it uses the serialization for file
-  // naming.
-  //
-
-  if (mAppId != nsIScriptSecurityManager::NO_APP_ID) {
-    value.AppendInt(mAppId);
-    params.Set(NS_LITERAL_STRING("appId"), value);
-  }
-
-  if (mInIsolatedMozBrowser) {
-    params.Set(NS_LITERAL_STRING("inBrowser"), NS_LITERAL_STRING("1"));
-  }
-
-  if (mUserContextId != nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID) {
-    value.Truncate();
-    value.AppendInt(mUserContextId);
-    params.Set(NS_LITERAL_STRING("userContextId"), value);
-  }
-
-
-  if (mPrivateBrowsingId) {
-    value.Truncate();
-    value.AppendInt(mPrivateBrowsingId);
-    params.Set(NS_LITERAL_STRING("privateBrowsingId"), value);
-  }
-
-  if (!mFirstPartyDomain.IsEmpty()) {
-    MOZ_RELEASE_ASSERT(mFirstPartyDomain.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
-    params.Set(NS_LITERAL_STRING("firstPartyDomain"), mFirstPartyDomain);
-  }
-
-  aStr.Truncate();
-
-  params.Serialize(value);
-  if (!value.IsEmpty()) {
-    aStr.AppendLiteral("^");
-    aStr.Append(NS_ConvertUTF16toUTF8(value));
-  }
-
-// In debug builds, check the whole string for illegal characters too (just in case).
-#ifdef DEBUG
-  nsAutoCString str;
-  str.Assign(aStr);
-  MOZ_ASSERT(str.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
-#endif
-}
-
-void
-OriginAttributes::CreateAnonymizedSuffix(nsACString& aStr) const
-{
-  OriginAttributes attrs = *this;
-
-  if (!attrs.mFirstPartyDomain.IsEmpty()) {
-    attrs.mFirstPartyDomain.AssignLiteral("_anonymizedFirstPartyDomain_");
-  }
-
-  attrs.CreateSuffix(aStr);
-}
-
-namespace {
-
-class MOZ_STACK_CLASS PopulateFromSuffixIterator final
-  : public URLParams::ForEachIterator
-{
-public:
-  explicit PopulateFromSuffixIterator(OriginAttributes* aOriginAttributes)
-    : mOriginAttributes(aOriginAttributes)
-  {
-    MOZ_ASSERT(aOriginAttributes);
-    // If mPrivateBrowsingId is passed in as >0 and is not present in the suffix,
-    // then it will remain >0 when it should be 0 according to the suffix. Set to 0 before
-    // iterating to fix this.
-    mOriginAttributes->mPrivateBrowsingId = 0;
-  }
-
-  bool URLParamsIterator(const nsString& aName,
-                         const nsString& aValue) override
-  {
-    if (aName.EqualsLiteral("appId")) {
-      nsresult rv;
-      int64_t val  = aValue.ToInteger64(&rv);
-      NS_ENSURE_SUCCESS(rv, false);
-      NS_ENSURE_TRUE(val <= UINT32_MAX, false);
-      mOriginAttributes->mAppId = static_cast<uint32_t>(val);
-
-      return true;
-    }
-
-    if (aName.EqualsLiteral("inBrowser")) {
-      if (!aValue.EqualsLiteral("1")) {
-        return false;
-      }
-
-      mOriginAttributes->mInIsolatedMozBrowser = true;
-      return true;
-    }
-
-    if (aName.EqualsLiteral("addonId")) {
-      // No longer supported. Silently ignore so that legacy origin strings
-      // don't cause failures.
-      return true;
-    }
-
-    if (aName.EqualsLiteral("userContextId")) {
-      nsresult rv;
-      int64_t val  = aValue.ToInteger64(&rv);
-      NS_ENSURE_SUCCESS(rv, false);
-      NS_ENSURE_TRUE(val <= UINT32_MAX, false);
-      mOriginAttributes->mUserContextId  = static_cast<uint32_t>(val);
-
-      return true;
-    }
-
-    if (aName.EqualsLiteral("privateBrowsingId")) {
-      nsresult rv;
-      int64_t val = aValue.ToInteger64(&rv);
-      NS_ENSURE_SUCCESS(rv, false);
-      NS_ENSURE_TRUE(val >= 0 && val <= UINT32_MAX, false);
-      mOriginAttributes->mPrivateBrowsingId = static_cast<uint32_t>(val);
-
-      return true;
-    }
-
-    if (aName.EqualsLiteral("firstPartyDomain")) {
-      MOZ_RELEASE_ASSERT(mOriginAttributes->mFirstPartyDomain.IsEmpty());
-      mOriginAttributes->mFirstPartyDomain.Assign(aValue);
-      return true;
-    }
-
-    // No other attributes are supported.
-    return false;
-  }
-
-private:
-  OriginAttributes* mOriginAttributes;
-};
-
-} // namespace
-
-bool
-OriginAttributes::PopulateFromSuffix(const nsACString& aStr)
-{
-  if (aStr.IsEmpty()) {
-    return true;
-  }
-
-  if (aStr[0] != '^') {
-    return false;
-  }
-
-  URLParams params;
-  params.ParseInput(Substring(aStr, 1, aStr.Length() - 1));
-
-  PopulateFromSuffixIterator iterator(this);
-  return params.ForEach(iterator);
-}
-
-bool
-OriginAttributes::PopulateFromOrigin(const nsACString& aOrigin,
-                                     nsACString& aOriginNoSuffix)
-{
-  // RFindChar is only available on nsCString.
-  nsCString origin(aOrigin);
-  int32_t pos = origin.RFindChar('^');
-
-  if (pos == kNotFound) {
-    aOriginNoSuffix = origin;
-    return true;
-  }
-
-  aOriginNoSuffix = Substring(origin, 0, pos);
-  return PopulateFromSuffix(Substring(origin, pos));
-}
-
-void
-OriginAttributes::SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing)
-{
-  mPrivateBrowsingId = aInPrivateBrowsing ? 1 : 0;
-}
-
-/* static */
-bool
-OriginAttributes::IsPrivateBrowsing(const nsACString& aOrigin)
-{
-  nsAutoCString dummy;
-  OriginAttributes attrs;
-  if (NS_WARN_IF(!attrs.PopulateFromOrigin(aOrigin, dummy))) {
-    return false;
-  }
-
-  return !!attrs.mPrivateBrowsingId;
-}
-
 BasePrincipal::BasePrincipal(PrincipalKind aKind)
   : mKind(aKind)
   , mDomainSet(false)
 {}
 
 BasePrincipal::~BasePrincipal()
 {}
 
@@ -640,46 +370,46 @@ already_AddRefed<BasePrincipal>
 BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs)
 {
   // If the URI is supposed to inherit the security context of whoever loads it,
   // we shouldn't make a codebase principal for it.
   bool inheritsPrincipal;
   nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
                                     &inheritsPrincipal);
   if (NS_FAILED(rv) || inheritsPrincipal) {
-    return nsNullPrincipal::Create(aAttrs);
+    return NullPrincipal::Create(aAttrs);
   }
 
   // Check whether the URI knows what its principal is supposed to be.
   nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
   if (uriPrinc) {
     nsCOMPtr<nsIPrincipal> principal;
     uriPrinc->GetPrincipal(getter_AddRefs(principal));
     if (!principal) {
-      return nsNullPrincipal::Create(aAttrs);
+      return NullPrincipal::Create(aAttrs);
     }
     RefPtr<BasePrincipal> concrete = Cast(principal);
     return concrete.forget();
   }
 
   // Mint a codebase principal.
-  RefPtr<nsPrincipal> codebase = new nsPrincipal();
+  RefPtr<ContentPrincipal> codebase = new ContentPrincipal();
   rv = codebase->Init(aURI, aAttrs);
   NS_ENSURE_SUCCESS(rv, nullptr);
   return codebase.forget();
 }
 
 already_AddRefed<BasePrincipal>
 BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
 {
   MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
              "CreateCodebasePrincipal does not support System and Expanded principals");
 
   MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
-             "CreateCodebasePrincipal does not support nsNullPrincipal");
+             "CreateCodebasePrincipal does not support NullPrincipal");
 
   nsAutoCString originNoSuffix;
   mozilla::OriginAttributes attrs;
   if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
     return nullptr;
   }
 
   nsCOMPtr<nsIURI> uri;
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -5,197 +5,27 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_BasePrincipal_h
 #define mozilla_BasePrincipal_h
 
 #include "nsJSPrincipals.h"
 
 #include "mozilla/Attributes.h"
-#include "mozilla/dom/ChromeUtils.h"
-#include "mozilla/dom/ChromeUtilsBinding.h"
-#include "nsIScriptSecurityManager.h"
+#include "mozilla/OriginAttributes.h"
 
 class nsIContentSecurityPolicy;
 class nsIObjectOutputStream;
 class nsIObjectInputStream;
 class nsIURI;
 
-class nsExpandedPrincipal;
+class ExpandedPrincipal;
 
 namespace mozilla {
 
-// Base OriginAttributes class. This has several subclass flavors, and is not
-// directly constructable itself.
-class OriginAttributes : public dom::OriginAttributesDictionary
-{
-public:
-  OriginAttributes() {}
-
-  OriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
-  {
-    mAppId = aAppId;
-    mInIsolatedMozBrowser = aInIsolatedMozBrowser;
-  }
-
-  explicit OriginAttributes(const OriginAttributesDictionary& aOther)
-    : OriginAttributesDictionary(aOther)
-  {}
-
-  void SetFirstPartyDomain(const bool aIsTopLevelDocument, nsIURI* aURI);
-  void SetFirstPartyDomain(const bool aIsTopLevelDocument, const nsACString& aDomain);
-
-  enum {
-    STRIP_FIRST_PARTY_DOMAIN = 0x01,
-    STRIP_USER_CONTEXT_ID = 0x02,
-  };
-
-  inline void StripAttributes(uint32_t aFlags)
-  {
-    if (aFlags & STRIP_FIRST_PARTY_DOMAIN) {
-      mFirstPartyDomain.Truncate();
-    }
-
-    if (aFlags & STRIP_USER_CONTEXT_ID) {
-      mUserContextId = nsIScriptSecurityManager::DEFAULT_USER_CONTEXT_ID;
-    }
-  }
-
-  bool operator==(const OriginAttributes& aOther) const
-  {
-    return mAppId == aOther.mAppId &&
-           mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser &&
-           mUserContextId == aOther.mUserContextId &&
-           mPrivateBrowsingId == aOther.mPrivateBrowsingId &&
-           mFirstPartyDomain == aOther.mFirstPartyDomain;
-  }
-
-  bool operator!=(const OriginAttributes& aOther) const
-  {
-    return !(*this == aOther);
-  }
-
-  // Serializes/Deserializes non-default values into the suffix format, i.e.
-  // |!key1=value1&key2=value2|. If there are no non-default attributes, this
-  // returns an empty string.
-  void CreateSuffix(nsACString& aStr) const;
-
-  // Don't use this method for anything else than debugging!
-  void CreateAnonymizedSuffix(nsACString& aStr) const;
-
-  MOZ_MUST_USE bool PopulateFromSuffix(const nsACString& aStr);
-
-  // Populates the attributes from a string like
-  // |uri!key1=value1&key2=value2| and returns the uri without the suffix.
-  MOZ_MUST_USE bool PopulateFromOrigin(const nsACString& aOrigin,
-                                       nsACString& aOriginNoSuffix);
-
-  // Helper function to match mIsPrivateBrowsing to existing private browsing
-  // flags. Once all other flags are removed, this can be removed too.
-  void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
-
-  // check if "privacy.firstparty.isolate" is enabled.
-  static inline bool IsFirstPartyEnabled()
-  {
-    return sFirstPartyIsolation;
-  }
-
-  // check if the access of window.opener across different FPDs is restricted.
-  // We only restrict the access of window.opener when first party isolation
-  // is enabled and "privacy.firstparty.isolate.restrict_opener_access" is on.
-  static inline bool IsRestrictOpenerAccessForFPI()
-  {
-    // We always want to restrict window.opener if first party isolation is
-    // disabled.
-    return !sFirstPartyIsolation || sRestrictedOpenerAccess;
-  }
-
-  // returns true if the originAttributes suffix has mPrivateBrowsingId value
-  // different than 0.
-  static bool IsPrivateBrowsing(const nsACString& aOrigin);
-
-  static void InitPrefs();
-
-private:
-  static bool sFirstPartyIsolation;
-  static bool sRestrictedOpenerAccess;
-};
-
-class OriginAttributesPattern : public dom::OriginAttributesPatternDictionary
-{
-public:
-  // To convert a JSON string to an OriginAttributesPattern, do the following:
-  //
-  // OriginAttributesPattern pattern;
-  // if (!pattern.Init(aJSONString)) {
-  //   ... // handle failure.
-  // }
-  OriginAttributesPattern() {}
-
-  explicit OriginAttributesPattern(const OriginAttributesPatternDictionary& aOther)
-    : OriginAttributesPatternDictionary(aOther) {}
-
-  // Performs a match of |aAttrs| against this pattern.
-  bool Matches(const OriginAttributes& aAttrs) const
-  {
-    if (mAppId.WasPassed() && mAppId.Value() != aAttrs.mAppId) {
-      return false;
-    }
-
-    if (mInIsolatedMozBrowser.WasPassed() && mInIsolatedMozBrowser.Value() != aAttrs.mInIsolatedMozBrowser) {
-      return false;
-    }
-
-    if (mUserContextId.WasPassed() && mUserContextId.Value() != aAttrs.mUserContextId) {
-      return false;
-    }
-
-    if (mPrivateBrowsingId.WasPassed() && mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) {
-      return false;
-    }
-
-    if (mFirstPartyDomain.WasPassed() && mFirstPartyDomain.Value() != aAttrs.mFirstPartyDomain) {
-      return false;
-    }
-
-    return true;
-  }
-
-  bool Overlaps(const OriginAttributesPattern& aOther) const
-  {
-    if (mAppId.WasPassed() && aOther.mAppId.WasPassed() &&
-        mAppId.Value() != aOther.mAppId.Value()) {
-      return false;
-    }
-
-    if (mInIsolatedMozBrowser.WasPassed() &&
-        aOther.mInIsolatedMozBrowser.WasPassed() &&
-        mInIsolatedMozBrowser.Value() != aOther.mInIsolatedMozBrowser.Value()) {
-      return false;
-    }
-
-    if (mUserContextId.WasPassed() && aOther.mUserContextId.WasPassed() &&
-        mUserContextId.Value() != aOther.mUserContextId.Value()) {
-      return false;
-    }
-
-    if (mPrivateBrowsingId.WasPassed() && aOther.mPrivateBrowsingId.WasPassed() &&
-        mPrivateBrowsingId.Value() != aOther.mPrivateBrowsingId.Value()) {
-      return false;
-    }
-
-    if (mFirstPartyDomain.WasPassed() && aOther.mFirstPartyDomain.WasPassed() &&
-        mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
-      return false;
-    }
-
-    return true;
-  }
-};
-
 /*
  * Base class from which all nsIPrincipal implementations inherit. Use this for
  * default implementations and other commonalities between principal
  * implementations.
  *
  * We should merge nsJSPrincipals into this class at some point.
  */
 class BasePrincipal : public nsJSPrincipals
@@ -278,17 +108,17 @@ protected:
   // Note that this does not check OriginAttributes. Callers that depend on
   // those must call Subsumes instead.
   virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
 
   // Internal, side-effect-free check to determine whether the concrete
   // principal would allow the load ignoring any common behavior implemented in
   // BasePrincipal::CheckMayLoad.
   virtual bool MayLoadInternal(nsIURI* aURI) = 0;
-  friend class ::nsExpandedPrincipal;
+  friend class ::ExpandedPrincipal;
 
   // This function should be called as the last step of the initialization of the
   // principal objects.  It's typically called as the last step from the Init()
   // method of the child classes.
   void FinishInit();
 
   nsCOMPtr<nsIContentSecurityPolicy> mCSP;
   nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
rename from caps/nsPrincipal.cpp
rename to caps/ContentPrincipal.cpp
--- a/caps/nsPrincipal.cpp
+++ b/caps/ContentPrincipal.cpp
@@ -1,29 +1,31 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et 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/. */
 
-#include "nsPrincipal.h"
+#include "ContentPrincipal.h"
 
 #include "mozIThirdPartyUtil.h"
 #include "nscore.h"
 #include "nsScriptSecurityManager.h"
 #include "nsString.h"
 #include "nsReadableUtils.h"
 #include "pratom.h"
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsIStandardURL.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsIEffectiveTLDService.h"
 #include "nsIClassInfoImpl.h"
+#include "nsIObjectInputStream.h"
+#include "nsIObjectOutputStream.h"
 #include "nsIProtocolHandler.h"
 #include "nsError.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsNetCID.h"
 #include "jswrapper.h"
 
 #include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/ScriptSettings.h"
@@ -53,52 +55,53 @@ GetAddonPolicyService(nsresult* aRv)
   *aRv = NS_OK;
   if (!addonPolicyService) {
     addonPolicyService = do_GetService("@mozilla.org/addons/policy-service;1", aRv);
     ClearOnShutdown(&addonPolicyService);
   }
   return addonPolicyService;
 }
 
-NS_IMPL_CLASSINFO(nsPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
+NS_IMPL_CLASSINFO(ContentPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_PRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE_CI(nsPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(ContentPrincipal,
                            nsIPrincipal,
                            nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER(nsPrincipal,
+NS_IMPL_CI_INTERFACE_GETTER(ContentPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 
 // Called at startup:
 /* static */ void
-nsPrincipal::InitializeStatics()
+ContentPrincipal::InitializeStatics()
 {
   Preferences::AddBoolVarCache(&gCodeBasePrincipalSupport,
                                "signed.applets.codebase_principal_support",
                                false);
 }
 
-nsPrincipal::nsPrincipal()
+ContentPrincipal::ContentPrincipal()
   : BasePrincipal(eCodebasePrincipal)
   , mCodebaseImmutable(false)
   , mDomainImmutable(false)
   , mInitialized(false)
 {
 }
 
-nsPrincipal::~nsPrincipal()
+ContentPrincipal::~ContentPrincipal()
 {
   // let's clear the principal within the csp to avoid a tangling pointer
   if (mCSP) {
     static_cast<nsCSPContext*>(mCSP.get())->clearLoadingPrincipal();
   }
 }
 
 nsresult
-nsPrincipal::Init(nsIURI *aCodebase, const OriginAttributes& aOriginAttributes)
+ContentPrincipal::Init(nsIURI *aCodebase,
+                       const OriginAttributes& aOriginAttributes)
 {
   NS_ENSURE_STATE(!mInitialized);
   NS_ENSURE_ARG(aCodebase);
 
   mInitialized = true;
 
   // Assert that the URI we get here isn't any of the schemes that we know we
   // should not get here.  These schemes always either inherit their principal
@@ -118,23 +121,23 @@ nsPrincipal::Init(nsIURI *aCodebase, con
   mOriginAttributes = aOriginAttributes;
 
   FinishInit();
 
   return NS_OK;
 }
 
 nsresult
-nsPrincipal::GetScriptLocation(nsACString &aStr)
+ContentPrincipal::GetScriptLocation(nsACString &aStr)
 {
   return mCodebase->GetSpec(aStr);
 }
 
 nsresult
-nsPrincipal::GetOriginInternal(nsACString& aOrigin)
+ContentPrincipal::GetOriginInternal(nsACString& aOrigin)
 {
   if (!mCodebase) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsIURI> origin = NS_GetInnermostURI(mCodebase);
   if (!origin) {
     return NS_ERROR_FAILURE;
@@ -244,22 +247,22 @@ nsPrincipal::GetOriginInternal(nsACStrin
   if (pos != kNotFound) {
     aOrigin.Truncate(pos);
   }
 
   return NS_OK;
 }
 
 bool
-nsPrincipal::SubsumesInternal(nsIPrincipal* aOther,
-                              BasePrincipal::DocumentDomainConsideration aConsideration)
+ContentPrincipal::SubsumesInternal(nsIPrincipal* aOther,
+                                   BasePrincipal::DocumentDomainConsideration aConsideration)
 {
   MOZ_ASSERT(aOther);
 
-  // For nsPrincipal, Subsumes is equivalent to Equals.
+  // For ContentPrincipal, Subsumes is equivalent to Equals.
   if (aOther == this) {
     return true;
   }
 
   // If either the subject or the object has changed its principal by
   // explicitly setting document.domain then the other must also have
   // done so in order to be considered the same origin. This prevents
   // DNS spoofing based on document.domain (154930)
@@ -281,33 +284,33 @@ nsPrincipal::SubsumesInternal(nsIPrincip
   rv = aOther->GetURI(getter_AddRefs(otherURI));
   NS_ENSURE_SUCCESS(rv, false);
 
   // Compare codebases.
   return nsScriptSecurityManager::SecurityCompareURIs(mCodebase, otherURI);
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetURI(nsIURI** aURI)
+ContentPrincipal::GetURI(nsIURI** aURI)
 {
   if (mCodebaseImmutable) {
     NS_ADDREF(*aURI = mCodebase);
     return NS_OK;
   }
 
   if (!mCodebase) {
     *aURI = nullptr;
     return NS_OK;
   }
 
   return NS_EnsureSafeToReturn(mCodebase, aURI);
 }
 
 bool
-nsPrincipal::MayLoadInternal(nsIURI* aURI)
+ContentPrincipal::MayLoadInternal(nsIURI* aURI)
 {
   // See if aURI is something like a Blob URI that is actually associated with
   // a principal.
   nsCOMPtr<nsIURIWithPrincipal> uriWithPrin = do_QueryInterface(aURI);
   nsCOMPtr<nsIPrincipal> uriPrin;
   if (uriWithPrin) {
     uriWithPrin->GetPrincipal(getter_AddRefs(uriPrin));
   }
@@ -333,42 +336,42 @@ nsPrincipal::MayLoadInternal(nsIURI* aUR
       NS_RelaxStrictFileOriginPolicy(aURI, mCodebase)) {
     return true;
   }
 
   return false;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetHashValue(uint32_t* aValue)
+ContentPrincipal::GetHashValue(uint32_t* aValue)
 {
   NS_PRECONDITION(mCodebase, "Need a codebase");
 
   *aValue = nsScriptSecurityManager::HashPrincipalByOrigin(this);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetDomain(nsIURI** aDomain)
+ContentPrincipal::GetDomain(nsIURI** aDomain)
 {
   if (!mDomain) {
     *aDomain = nullptr;
     return NS_OK;
   }
 
   if (mDomainImmutable) {
     NS_ADDREF(*aDomain = mDomain);
     return NS_OK;
   }
 
   return NS_EnsureSafeToReturn(mDomain, aDomain);
 }
 
 NS_IMETHODIMP
-nsPrincipal::SetDomain(nsIURI* aDomain)
+ContentPrincipal::SetDomain(nsIURI* aDomain)
 {
   mDomain = NS_TryToMakeImmutable(aDomain);
   mDomainImmutable = URIIsImmutable(mDomain);
   mDomainSet = true;
 
   // Recompute all wrappers between compartments using this principal and other
   // non-chrome compartments.
   AutoSafeJSContext cx;
@@ -379,17 +382,17 @@ nsPrincipal::SetDomain(nsIURI* aDomain)
   success = js::RecomputeWrappers(cx, js::CompartmentsWithPrincipals(principals),
                                   js::ContentCompartmentsOnly());
   NS_ENSURE_TRUE(success, NS_ERROR_FAILURE);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetBaseDomain(nsACString& aBaseDomain)
+ContentPrincipal::GetBaseDomain(nsACString& aBaseDomain)
 {
   // For a file URI, we return the file path.
   if (NS_URIIsLocalFile(mCodebase)) {
     nsCOMPtr<nsIURL> url = do_QueryInterface(mCodebase);
 
     if (url) {
       return url->GetFilePath(aBaseDomain);
     }
@@ -414,17 +417,17 @@ nsPrincipal::GetBaseDomain(nsACString& a
   if (thirdPartyUtil) {
     return thirdPartyUtil->GetBaseDomain(mCodebase, aBaseDomain);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::GetAddonId(nsAString& aAddonId)
+ContentPrincipal::GetAddonId(nsAString& aAddonId)
 {
   if (mAddonIdCache.isSome()) {
     aAddonId.Assign(mAddonIdCache.ref());
     return NS_OK;
   }
 
   NS_ENSURE_TRUE(mCodebase, NS_ERROR_FAILURE);
 
@@ -443,17 +446,17 @@ nsPrincipal::GetAddonId(nsAString& aAddo
     mAddonIdCache.emplace();
   }
 
   aAddonId.Assign(mAddonIdCache.ref());
   return NS_OK;
 };
 
 NS_IMETHODIMP
-nsPrincipal::Read(nsIObjectInputStream* aStream)
+ContentPrincipal::Read(nsIObjectInputStream* aStream)
 {
   nsCOMPtr<nsISupports> supports;
   nsCOMPtr<nsIURI> codebase;
   nsresult rv = NS_ReadOptionalObject(aStream, true, getter_AddRefs(supports));
   if (NS_FAILED(rv)) {
     return rv;
   }
 
@@ -489,17 +492,17 @@ nsPrincipal::Read(nsIObjectInputStream* 
   }
 
   SetDomain(domain);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsPrincipal::Write(nsIObjectOutputStream* aStream)
+ContentPrincipal::Write(nsIObjectOutputStream* aStream)
 {
   NS_ENSURE_STATE(mCodebase);
   nsresult rv = NS_WriteOptionalCompoundObject(aStream, mCodebase, NS_GET_IID(nsIURI),
                                                true);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
rename from caps/nsPrincipal.h
rename to caps/ContentPrincipal.h
--- a/caps/nsPrincipal.h
+++ b/caps/ContentPrincipal.h
@@ -1,40 +1,40 @@
 /* -*- Mode: C++; 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/. */
 
-#ifndef nsPrincipal_h__
-#define nsPrincipal_h__
+#ifndef ContentPrincipal_h
+#define ContentPrincipal_h
 
 #include "nsCOMPtr.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIProtocolHandler.h"
 #include "nsNetUtil.h"
 #include "nsScriptSecurityManager.h"
 #include "mozilla/BasePrincipal.h"
 
-class nsPrincipal final : public mozilla::BasePrincipal
+class ContentPrincipal final : public mozilla::BasePrincipal
 {
 public:
   NS_DECL_NSISERIALIZABLE
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
   bool IsCodebasePrincipal() const override { return true; }
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
-  nsPrincipal();
+  ContentPrincipal();
 
   // Init() must be called before the principal is in a usable state.
   nsresult Init(nsIURI* aCodebase,
                 const mozilla::OriginAttributes& aOriginAttributes);
 
   virtual nsresult GetScriptLocation(nsACString& aStr) override;
 
   /**
@@ -45,23 +45,24 @@ public:
   nsCOMPtr<nsIURI> mDomain;
   nsCOMPtr<nsIURI> mCodebase;
   // If mCodebaseImmutable is true, mCodebase is non-null and immutable
   bool mCodebaseImmutable;
   bool mDomainImmutable;
   bool mInitialized;
 
 protected:
-  virtual ~nsPrincipal();
+  virtual ~ContentPrincipal();
 
-  bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override;
+  bool SubsumesInternal(nsIPrincipal* aOther,
+                        DocumentDomainConsideration aConsideration) override;
   bool MayLoadInternal(nsIURI* aURI) override;
 
 private:
   mozilla::Maybe<nsString> mAddonIdCache;
 };
 
 #define NS_PRINCIPAL_CONTRACTID "@mozilla.org/principal;1"
 #define NS_PRINCIPAL_CID \
 { 0x653e0e4d, 0x3ee4, 0x45fa, \
   { 0xb2, 0x72, 0x97, 0xc2, 0x0b, 0xc0, 0x1e, 0xb8 } }
 
-#endif // nsPrincipal_h__
+#endif // ContentPrincipal_h
rename from caps/nsExpandedPrincipal.cpp
rename to caps/ExpandedPrincipal.cpp
--- a/caps/nsExpandedPrincipal.cpp
+++ b/caps/ExpandedPrincipal.cpp
@@ -1,27 +1,27 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et 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/. */
 
-#include "nsExpandedPrincipal.h"
+#include "ExpandedPrincipal.h"
 #include "nsIClassInfoImpl.h"
 
 using namespace mozilla;
 
-NS_IMPL_CLASSINFO(nsExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
+NS_IMPL_CLASSINFO(ExpandedPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_EXPANDEDPRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE_CI(nsExpandedPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(ExpandedPrincipal,
                            nsIPrincipal,
                            nsIExpandedPrincipal)
-NS_IMPL_CI_INTERFACE_GETTER(nsExpandedPrincipal,
-                             nsIPrincipal,
-                             nsIExpandedPrincipal)
+NS_IMPL_CI_INTERFACE_GETTER(ExpandedPrincipal,
+                            nsIPrincipal,
+                            nsIExpandedPrincipal)
 
 struct OriginComparator
 {
   bool LessThan(nsIPrincipal* a, nsIPrincipal* b) const
   {
     nsAutoCString originA;
     nsresult rv = a->GetOrigin(originA);
     NS_ENSURE_SUCCESS(rv, false);
@@ -38,56 +38,56 @@ struct OriginComparator
     NS_ENSURE_SUCCESS(rv, false);
     nsAutoCString originB;
     rv = b->GetOrigin(originB);
     NS_ENSURE_SUCCESS(rv, false);
     return a == b;
   }
 };
 
-nsExpandedPrincipal::nsExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList,
-                                         const OriginAttributes& aAttrs)
+ExpandedPrincipal::ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList,
+                                     const OriginAttributes& aAttrs)
   : BasePrincipal(eExpandedPrincipal)
 {
-  // We force the principals to be sorted by origin so that nsExpandedPrincipal
+  // We force the principals to be sorted by origin so that ExpandedPrincipal
   // origins can have a canonical form.
   OriginComparator c;
   for (size_t i = 0; i < aWhiteList.Length(); ++i) {
     mPrincipals.InsertElementSorted(aWhiteList[i], c);
   }
   mOriginAttributes = aAttrs;
 }
 
-nsExpandedPrincipal::~nsExpandedPrincipal()
+ExpandedPrincipal::~ExpandedPrincipal()
 { }
 
-already_AddRefed<nsExpandedPrincipal>
-nsExpandedPrincipal::Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList,
-                            const OriginAttributes& aAttrs)
+already_AddRefed<ExpandedPrincipal>
+ExpandedPrincipal::Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList,
+                          const OriginAttributes& aAttrs)
 {
-  RefPtr<nsExpandedPrincipal> ep = new nsExpandedPrincipal(aWhiteList, aAttrs);
+  RefPtr<ExpandedPrincipal> ep = new ExpandedPrincipal(aWhiteList, aAttrs);
   ep->FinishInit();
   return ep.forget();
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::GetDomain(nsIURI** aDomain)
+ExpandedPrincipal::GetDomain(nsIURI** aDomain)
 {
   *aDomain = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::SetDomain(nsIURI* aDomain)
+ExpandedPrincipal::SetDomain(nsIURI* aDomain)
 {
   return NS_OK;
 }
 
 nsresult
-nsExpandedPrincipal::GetOriginInternal(nsACString& aOrigin)
+ExpandedPrincipal::GetOriginInternal(nsACString& aOrigin)
 {
   aOrigin.AssignLiteral("[Expanded Principal [");
   for (size_t i = 0; i < mPrincipals.Length(); ++i) {
     if (i != 0) {
       aOrigin.AppendLiteral(", ");
     }
 
     nsAutoCString subOrigin;
@@ -96,18 +96,18 @@ nsExpandedPrincipal::GetOriginInternal(n
     aOrigin.Append(subOrigin);
   }
 
   aOrigin.Append("]]");
   return NS_OK;
 }
 
 bool
-nsExpandedPrincipal::SubsumesInternal(nsIPrincipal* aOther,
-                                      BasePrincipal::DocumentDomainConsideration aConsideration)
+ExpandedPrincipal::SubsumesInternal(nsIPrincipal* aOther,
+                                    BasePrincipal::DocumentDomainConsideration aConsideration)
 {
   // If aOther is an ExpandedPrincipal too, we break it down into its component
   // nsIPrincipals, and check subsumes on each one.
   nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aOther);
   if (expanded) {
     nsTArray< nsCOMPtr<nsIPrincipal> >* otherList;
     expanded->GetWhiteList(&otherList);
     for (uint32_t i = 0; i < otherList->Length(); ++i){
@@ -128,73 +128,73 @@ nsExpandedPrincipal::SubsumesInternal(ns
       return true;
     }
   }
 
   return false;
 }
 
 bool
-nsExpandedPrincipal::MayLoadInternal(nsIURI* uri)
+ExpandedPrincipal::MayLoadInternal(nsIURI* uri)
 {
   for (uint32_t i = 0; i < mPrincipals.Length(); ++i){
     if (BasePrincipal::Cast(mPrincipals[i])->MayLoadInternal(uri)) {
       return true;
     }
   }
 
   return false;
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::GetHashValue(uint32_t* result)
+ExpandedPrincipal::GetHashValue(uint32_t* result)
 {
   MOZ_CRASH("extended principal should never be used as key in a hash map");
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::GetURI(nsIURI** aURI)
+ExpandedPrincipal::GetURI(nsIURI** aURI)
 {
   *aURI = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList)
+ExpandedPrincipal::GetWhiteList(nsTArray<nsCOMPtr<nsIPrincipal> >** aWhiteList)
 {
   *aWhiteList = &mPrincipals;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
+ExpandedPrincipal::GetBaseDomain(nsACString& aBaseDomain)
 {
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::GetAddonId(nsAString& aAddonId)
+ExpandedPrincipal::GetAddonId(nsAString& aAddonId)
 {
   aAddonId.Truncate();
   return NS_OK;
 };
 
 bool
-nsExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
+ExpandedPrincipal::AddonHasPermission(const nsAString& aPerm)
 {
   for (size_t i = 0; i < mPrincipals.Length(); ++i) {
     if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
       return true;
     }
   }
   return false;
 }
 
 nsresult
-nsExpandedPrincipal::GetScriptLocation(nsACString& aStr)
+ExpandedPrincipal::GetScriptLocation(nsACString& aStr)
 {
   aStr.Assign("[Expanded Principal [");
   for (size_t i = 0; i < mPrincipals.Length(); ++i) {
     if (i != 0) {
       aStr.AppendLiteral(", ");
     }
 
     nsAutoCString spec;
@@ -208,18 +208,18 @@ nsExpandedPrincipal::GetScriptLocation(n
   return NS_OK;
 }
 
 //////////////////////////////////////////
 // Methods implementing nsISerializable //
 //////////////////////////////////////////
 
 NS_IMETHODIMP
-nsExpandedPrincipal::Read(nsIObjectInputStream* aStream)
+ExpandedPrincipal::Read(nsIObjectInputStream* aStream)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
+ExpandedPrincipal::Write(nsIObjectOutputStream* aStream)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
rename from caps/nsExpandedPrincipal.h
rename to caps/ExpandedPrincipal.h
--- a/caps/nsExpandedPrincipal.h
+++ b/caps/ExpandedPrincipal.h
@@ -1,56 +1,59 @@
 /* -*- Mode: C++; 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/. */
 
-#ifndef nsExpandedPrincipal_h
-#define nsExpandedPrincipal_h
+#ifndef ExpandedPrincipal_h
+#define ExpandedPrincipal_h
 
 #include "nsCOMPtr.h"
 #include "nsJSPrincipals.h"
 #include "nsTArray.h"
 #include "nsNetUtil.h"
 #include "mozilla/BasePrincipal.h"
 
-class nsExpandedPrincipal : public nsIExpandedPrincipal
-                          , public mozilla::BasePrincipal
+class ExpandedPrincipal : public nsIExpandedPrincipal
+                        , public mozilla::BasePrincipal
 {
-  nsExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList,
-                      const mozilla::OriginAttributes& aAttrs);
+  ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList,
+                    const mozilla::OriginAttributes& aAttrs);
 
 public:
-  static already_AddRefed<nsExpandedPrincipal>
+  static already_AddRefed<ExpandedPrincipal>
   Create(nsTArray<nsCOMPtr<nsIPrincipal>>& aWhiteList,
          const mozilla::OriginAttributes& aAttrs);
 
   NS_DECL_NSIEXPANDEDPRINCIPAL
   NS_DECL_NSISERIALIZABLE
+
   NS_IMETHOD_(MozExternalRefCountType) AddRef() override { return nsJSPrincipals::AddRef(); };
   NS_IMETHOD_(MozExternalRefCountType) Release() override { return nsJSPrincipals::Release(); };
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
   virtual bool AddonHasPermission(const nsAString& aPerm) override;
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
 protected:
-  virtual ~nsExpandedPrincipal();
+  virtual ~ExpandedPrincipal();
 
-  bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override;
+  bool SubsumesInternal(nsIPrincipal* aOther,
+                        DocumentDomainConsideration aConsideration) override;
+
   bool MayLoadInternal(nsIURI* aURI) override;
 
 private:
   nsTArray< nsCOMPtr<nsIPrincipal> > mPrincipals;
 };
 
 #define NS_EXPANDEDPRINCIPAL_CONTRACTID "@mozilla.org/expandedprincipal;1"
 #define NS_EXPANDEDPRINCIPAL_CID \
 { 0xe8ee88b0, 0x5571, 0x4086, \
   { 0xa4, 0x5b, 0x39, 0xa7, 0x16, 0x90, 0x6b, 0xdb } }
 
-#endif // nsExpandedPrincipal_h
+#endif // ExpandedPrincipal_h
rename from caps/nsNullPrincipal.cpp
rename to caps/NullPrincipal.cpp
--- a/caps/nsNullPrincipal.cpp
+++ b/caps/NullPrincipal.cpp
@@ -8,191 +8,192 @@
  * This is the principal that has no rights and can't be accessed by
  * anything other than itself and chrome; null principals are not
  * same-origin with anything but themselves.
  */
 
 #include "mozilla/ArrayUtils.h"
 
 #include "nsDocShell.h"
-#include "nsNullPrincipal.h"
-#include "nsNullPrincipalURI.h"
+#include "NullPrincipal.h"
+#include "NullPrincipalURI.h"
 #include "nsMemory.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsIClassInfoImpl.h"
 #include "nsNetCID.h"
 #include "nsError.h"
 #include "nsIScriptSecurityManager.h"
-#include "nsPrincipal.h"
+#include "ContentPrincipal.h"
 #include "nsScriptSecurityManager.h"
 #include "pratom.h"
 
 using namespace mozilla;
 
-NS_IMPL_CLASSINFO(nsNullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
+NS_IMPL_CLASSINFO(NullPrincipal, nullptr, nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_NULLPRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE_CI(nsNullPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(NullPrincipal,
                            nsIPrincipal,
                            nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER(nsNullPrincipal,
+NS_IMPL_CI_INTERFACE_GETTER(NullPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 
-/* static */ already_AddRefed<nsNullPrincipal>
-nsNullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom)
+/* static */ already_AddRefed<NullPrincipal>
+NullPrincipal::CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom)
 {
-  RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
+  RefPtr<NullPrincipal> nullPrin = new NullPrincipal();
   nsresult rv = nullPrin->Init(Cast(aInheritFrom)->OriginAttributesRef());
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   return nullPrin.forget();
 }
 
-/* static */ already_AddRefed<nsNullPrincipal>
-nsNullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty)
+/* static */ already_AddRefed<NullPrincipal>
+NullPrincipal::CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty)
 {
   OriginAttributes attrs = nsDocShell::Cast(aDocShell)->GetOriginAttributes();
   attrs.SetFirstPartyDomain(aIsFirstParty, NS_LITERAL_CSTRING(NULL_PRINCIPAL_FIRST_PARTY_DOMAIN));
 
-  RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
+  RefPtr<NullPrincipal> nullPrin = new NullPrincipal();
   nsresult rv = nullPrin->Init(attrs);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
   return nullPrin.forget();
 }
 
-/* static */ already_AddRefed<nsNullPrincipal>
-nsNullPrincipal::Create(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
+/* static */ already_AddRefed<NullPrincipal>
+NullPrincipal::Create(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
 {
-  RefPtr<nsNullPrincipal> nullPrin = new nsNullPrincipal();
+  RefPtr<NullPrincipal> nullPrin = new NullPrincipal();
   nsresult rv = nullPrin->Init(aOriginAttributes, aURI);
   MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
 
   return nullPrin.forget();
 }
 
 nsresult
-nsNullPrincipal::Init(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
+NullPrincipal::Init(const OriginAttributes& aOriginAttributes, nsIURI* aURI)
 {
   mOriginAttributes = aOriginAttributes;
 
   if (aURI) {
     nsAutoCString scheme;
     nsresult rv = aURI->GetScheme(scheme);
     NS_ENSURE_SUCCESS(rv, rv);
 
     NS_ENSURE_TRUE(scheme.EqualsLiteral(NS_NULLPRINCIPAL_SCHEME),
                    NS_ERROR_NOT_AVAILABLE);
 
     mURI = aURI;
   } else {
-    mURI = nsNullPrincipalURI::Create();
+    mURI = NullPrincipalURI::Create();
     NS_ENSURE_TRUE(mURI, NS_ERROR_NOT_AVAILABLE);
   }
 
   FinishInit();
 
   return NS_OK;
 }
 
 nsresult
-nsNullPrincipal::GetScriptLocation(nsACString &aStr)
+NullPrincipal::GetScriptLocation(nsACString &aStr)
 {
   return mURI->GetSpec(aStr);
 }
 
 /**
  * nsIPrincipal implementation
  */
 
 NS_IMETHODIMP
-nsNullPrincipal::GetHashValue(uint32_t *aResult)
+NullPrincipal::GetHashValue(uint32_t *aResult)
 {
   *aResult = (NS_PTR_TO_INT32(this) >> 2);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp) {
+NullPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
+{
   // Never destroy an existing CSP on the principal.
   // This method should only be called in rare cases.
 
   MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
   if (mCSP) {
     return NS_ERROR_ALREADY_INITIALIZED;
   }
 
   mCSP = aCsp;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::GetURI(nsIURI** aURI)
+NullPrincipal::GetURI(nsIURI** aURI)
 {
   return NS_EnsureSafeToReturn(mURI, aURI);
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::GetDomain(nsIURI** aDomain)
+NullPrincipal::GetDomain(nsIURI** aDomain)
 {
   return NS_EnsureSafeToReturn(mURI, aDomain);
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::SetDomain(nsIURI* aDomain)
+NullPrincipal::SetDomain(nsIURI* aDomain)
 {
   // I think the right thing to do here is to just throw...  Silently failing
   // seems counterproductive.
   return NS_ERROR_NOT_AVAILABLE;
 }
 
 nsresult
-nsNullPrincipal::GetOriginInternal(nsACString& aOrigin)
+NullPrincipal::GetOriginInternal(nsACString& aOrigin)
 {
   return mURI->GetSpec(aOrigin);
 }
 
 bool
-nsNullPrincipal::MayLoadInternal(nsIURI* aURI)
+NullPrincipal::MayLoadInternal(nsIURI* aURI)
 {
   // Also allow the load if we are the principal of the URI being checked.
   nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
   if (uriPrinc) {
     nsCOMPtr<nsIPrincipal> principal;
     uriPrinc->GetPrincipal(getter_AddRefs(principal));
 
     if (principal == this) {
       return true;
     }
   }
 
   return false;
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::GetBaseDomain(nsACString& aBaseDomain)
+NullPrincipal::GetBaseDomain(nsACString& aBaseDomain)
 {
   // For a null principal, we use our unique uuid as the base domain.
   return mURI->GetPath(aBaseDomain);
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::GetAddonId(nsAString& aAddonId)
+NullPrincipal::GetAddonId(nsAString& aAddonId)
 {
   aAddonId.Truncate();
   return NS_OK;
 };
 
 /**
  * nsISerializable implementation
  */
 NS_IMETHODIMP
-nsNullPrincipal::Read(nsIObjectInputStream* aStream)
+NullPrincipal::Read(nsIObjectInputStream* aStream)
 {
-  // Note - nsNullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means
+  // Note - NullPrincipal use NS_GENERIC_FACTORY_CONSTRUCTOR_INIT, which means
   // that the Init() method has already been invoked by the time we deserialize.
-  // This is in contrast to nsPrincipal, which uses NS_GENERIC_FACTORY_CONSTRUCTOR,
+  // This is in contrast to ContentPrincipal, which uses NS_GENERIC_FACTORY_CONSTRUCTOR,
   // in which case ::Read needs to invoke Init().
 
   nsAutoCString spec;
   nsresult rv = aStream->ReadCString(spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIURI> uri;
   rv = NS_NewURI(getter_AddRefs(uri), spec);
@@ -205,17 +206,17 @@ nsNullPrincipal::Read(nsIObjectInputStre
   OriginAttributes attrs;
   bool ok = attrs.PopulateFromSuffix(suffix);
   NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
 
   return Init(attrs, uri);
 }
 
 NS_IMETHODIMP
-nsNullPrincipal::Write(nsIObjectOutputStream* aStream)
+NullPrincipal::Write(nsIObjectOutputStream* aStream)
 {
   NS_ENSURE_STATE(mURI);
 
   nsAutoCString spec;
   nsresult rv = mURI->GetSpec(spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = aStream->WriteStringZ(spec.get());
rename from caps/nsNullPrincipal.h
rename to caps/NullPrincipal.h
--- a/caps/nsNullPrincipal.h
+++ b/caps/NullPrincipal.h
@@ -4,18 +4,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * This is the principal that has no rights and can't be accessed by
  * anything other than itself and chrome; null principals are not
  * same-origin with anything but themselves.
  */
 
-#ifndef nsNullPrincipal_h__
-#define nsNullPrincipal_h__
+#ifndef NullPrincipal_h
+#define NullPrincipal_h
 
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsCOMPtr.h"
 #include "nsIContentSecurityPolicy.h"
 
 #include "mozilla/BasePrincipal.h"
@@ -25,62 +25,63 @@ class nsIURI;
 
 #define NS_NULLPRINCIPAL_CID \
 { 0xbd066e5f, 0x146f, 0x4472, \
   { 0x83, 0x31, 0x7b, 0xfd, 0x05, 0xb1, 0xed, 0x90 } }
 #define NS_NULLPRINCIPAL_CONTRACTID "@mozilla.org/nullprincipal;1"
 
 #define NS_NULLPRINCIPAL_SCHEME "moz-nullprincipal"
 
-class nsNullPrincipal final : public mozilla::BasePrincipal
+class NullPrincipal final : public mozilla::BasePrincipal
 {
 public:
   // This should only be used by deserialization, and the factory constructor.
   // Other consumers should use the Create and CreateWithInheritedAttributes
   // methods.
-  nsNullPrincipal()
+  NullPrincipal()
     : BasePrincipal(eNullPrincipal)
   {
   }
 
   NS_DECL_NSISERIALIZABLE
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
-  static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom);
+  static already_AddRefed<NullPrincipal> CreateWithInheritedAttributes(nsIPrincipal* aInheritFrom);
 
   // Create NullPrincipal with origin attributes from docshell.
   // If aIsFirstParty is true, and the pref 'privacy.firstparty.isolate' is also
   // enabled, the mFirstPartyDomain value of the origin attributes will be set
   // to NULL_PRINCIPAL_FIRST_PARTY_DOMAIN.
-  static already_AddRefed<nsNullPrincipal> CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false);
+  static already_AddRefed<NullPrincipal>
+  CreateWithInheritedAttributes(nsIDocShell* aDocShell, bool aIsFirstParty = false);
 
-  static already_AddRefed<nsNullPrincipal>
+  static already_AddRefed<NullPrincipal>
   Create(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes(),
          nsIURI* aURI = nullptr);
 
   nsresult Init(const mozilla::OriginAttributes& aOriginAttributes = mozilla::OriginAttributes(),
                 nsIURI* aURI = nullptr);
 
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
  protected:
-  virtual ~nsNullPrincipal() {}
+  virtual ~NullPrincipal() = default;
 
   bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration) override
   {
     return aOther == this;
   }
 
   bool MayLoadInternal(nsIURI* aURI) override;
 
   nsCOMPtr<nsIURI> mURI;
 };
 
-#endif // nsNullPrincipal_h__
+#endif // NullPrincipal_h__
rename from caps/nsNullPrincipalURI.cpp
rename to caps/NullPrincipalURI.cpp
--- a/caps/nsNullPrincipalURI.cpp
+++ b/caps/NullPrincipalURI.cpp
@@ -1,41 +1,41 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * vim: sw=2 ts=2 sts=2 expandtab
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "nsNullPrincipalURI.h"
+#include "NullPrincipalURI.h"
 
 #include "mozilla/DebugOnly.h"
 #include "mozilla/MemoryReporting.h"
 
 #include "mozilla/ipc/URIParams.h"
 
 #include "nsEscape.h"
 #include "nsCRT.h"
 #include "nsIUUIDGenerator.h"
 
 ////////////////////////////////////////////////////////////////////////////////
-//// nsNullPrincipalURI
+//// NullPrincipalURI
 
-nsNullPrincipalURI::nsNullPrincipalURI()
+NullPrincipalURI::NullPrincipalURI()
   : mPath(mPathBytes, ArrayLength(mPathBytes), ArrayLength(mPathBytes) - 1)
 {
 }
 
-nsNullPrincipalURI::nsNullPrincipalURI(const nsNullPrincipalURI& aOther)
+NullPrincipalURI::NullPrincipalURI(const NullPrincipalURI& aOther)
   : mPath(mPathBytes, ArrayLength(mPathBytes), ArrayLength(mPathBytes) - 1)
 {
   mPath.Assign(aOther.mPath);
 }
 
 nsresult
-nsNullPrincipalURI::Init()
+NullPrincipalURI::Init()
 {
   // FIXME: bug 327161 -- make sure the uuid generator is reseeding-resistant.
   nsCOMPtr<nsIUUIDGenerator> uuidgen = services::GetUUIDGenerator();
   NS_ENSURE_TRUE(uuidgen, NS_ERROR_NOT_AVAILABLE);
 
   nsID id;
   nsresult rv = uuidgen->GenerateUUIDInPlace(&id);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -46,343 +46,343 @@ nsNullPrincipalURI::Init()
 
   MOZ_ASSERT(mPath.Length() == NSID_LENGTH - 1);
   MOZ_ASSERT(strlen(mPath.get()) == NSID_LENGTH - 1);
 
   return NS_OK;
 }
 
 /* static */
-already_AddRefed<nsNullPrincipalURI>
-nsNullPrincipalURI::Create()
+already_AddRefed<NullPrincipalURI>
+NullPrincipalURI::Create()
 {
-  RefPtr<nsNullPrincipalURI> uri = new nsNullPrincipalURI();
+  RefPtr<NullPrincipalURI> uri = new NullPrincipalURI();
   nsresult rv = uri->Init();
   NS_ENSURE_SUCCESS(rv, nullptr);
   return uri.forget();
 }
 
 static NS_DEFINE_CID(kNullPrincipalURIImplementationCID,
                      NS_NULLPRINCIPALURI_IMPLEMENTATION_CID);
 
-NS_IMPL_ADDREF(nsNullPrincipalURI)
-NS_IMPL_RELEASE(nsNullPrincipalURI)
+NS_IMPL_ADDREF(NullPrincipalURI)
+NS_IMPL_RELEASE(NullPrincipalURI)
 
-NS_INTERFACE_MAP_BEGIN(nsNullPrincipalURI)
+NS_INTERFACE_MAP_BEGIN(NullPrincipalURI)
   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIURI)
   if (aIID.Equals(kNullPrincipalURIImplementationCID))
-    foundInterface = static_cast<nsIURI *>(this);
+    foundInterface = static_cast<nsIURI*>(this);
   else
   NS_INTERFACE_MAP_ENTRY(nsIURI)
   NS_INTERFACE_MAP_ENTRY(nsISizeOf)
   NS_INTERFACE_MAP_ENTRY(nsIIPCSerializableURI)
 NS_INTERFACE_MAP_END
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsIURI
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetAsciiHost(nsACString &_host)
+NullPrincipalURI::GetAsciiHost(nsACString& _host)
 {
   _host.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetAsciiHostPort(nsACString &_hostport)
+NullPrincipalURI::GetAsciiHostPort(nsACString& _hostport)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetAsciiSpec(nsACString &_spec)
+NullPrincipalURI::GetAsciiSpec(nsACString& _spec)
 {
   nsAutoCString buffer;
-  // Ignore the return value -- nsNullPrincipalURI::GetSpec() is infallible.
+  // Ignore the return value -- NullPrincipalURI::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)
+NullPrincipalURI::GetHost(nsACString& _host)
 {
   _host.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetHost(const nsACString &aHost)
+NullPrincipalURI::SetHost(const nsACString& aHost)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetHostPort(nsACString &_host)
+NullPrincipalURI::GetHostPort(nsACString& _host)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetHostPort(const nsACString &aHost)
+NullPrincipalURI::SetHostPort(const nsACString& aHost)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetHostAndPort(const nsACString &aHost)
+NullPrincipalURI::SetHostAndPort(const nsACString& aHost)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetOriginCharset(nsACString &_charset)
+NullPrincipalURI::GetOriginCharset(nsACString& _charset)
 {
   _charset.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetPassword(nsACString &_password)
+NullPrincipalURI::GetPassword(nsACString& _password)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetPassword(const nsACString &aPassword)
+NullPrincipalURI::SetPassword(const nsACString& aPassword)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetPath(nsACString &_path)
+NullPrincipalURI::GetPath(nsACString& _path)
 {
   _path = mPath;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetPath(const nsACString &aPath)
+NullPrincipalURI::SetPath(const nsACString& aPath)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetFilePath(nsACString &aFilePath)
+NullPrincipalURI::GetFilePath(nsACString& aFilePath)
 {
   aFilePath.Truncate();
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetFilePath(const nsACString &aFilePath)
+NullPrincipalURI::SetFilePath(const nsACString& aFilePath)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetQuery(nsACString &aQuery)
+NullPrincipalURI::GetQuery(nsACString& aQuery)
 {
   aQuery.Truncate();
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetQuery(const nsACString &aQuery)
+NullPrincipalURI::SetQuery(const nsACString& aQuery)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetRef(nsACString &_ref)
+NullPrincipalURI::GetRef(nsACString& _ref)
 {
   _ref.Truncate();
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetRef(const nsACString &aRef)
+NullPrincipalURI::SetRef(const nsACString& aRef)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetPrePath(nsACString &_prePath)
+NullPrincipalURI::GetPrePath(nsACString& _prePath)
 {
   _prePath = NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":");
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetPort(int32_t *_port)
+NullPrincipalURI::GetPort(int32_t* _port)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetPort(int32_t aPort)
+NullPrincipalURI::SetPort(int32_t aPort)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetScheme(nsACString &_scheme)
+NullPrincipalURI::GetScheme(nsACString& _scheme)
 {
   _scheme = NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetScheme(const nsACString &aScheme)
+NullPrincipalURI::SetScheme(const nsACString& aScheme)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetSpec(nsACString &_spec)
+NullPrincipalURI::GetSpec(nsACString& _spec)
 {
   _spec = NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":") + mPath;
   return NS_OK;
 }
 
 // result may contain unescaped UTF-8 characters
 NS_IMETHODIMP
-nsNullPrincipalURI::GetSpecIgnoringRef(nsACString &result)
+NullPrincipalURI::GetSpecIgnoringRef(nsACString& _result)
 {
-  return GetSpec(result);
+  return GetSpec(_result);
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetHasRef(bool *result)
+NullPrincipalURI::GetHasRef(bool* _result)
 {
-  *result = false;
+  *_result = false;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetSpec(const nsACString &aSpec)
+NullPrincipalURI::SetSpec(const nsACString& aSpec)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetUsername(nsACString &_username)
+NullPrincipalURI::GetUsername(nsACString& _username)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetUsername(const nsACString &aUsername)
+NullPrincipalURI::SetUsername(const nsACString& aUsername)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::GetUserPass(nsACString &_userPass)
+NullPrincipalURI::GetUserPass(nsACString& _userPass)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SetUserPass(const nsACString &aUserPass)
+NullPrincipalURI::SetUserPass(const nsACString& aUserPass)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::Clone(nsIURI **_newURI)
+NullPrincipalURI::Clone(nsIURI** _newURI)
 {
-  nsCOMPtr<nsIURI> uri = new nsNullPrincipalURI(*this);
+  nsCOMPtr<nsIURI> uri = new NullPrincipalURI(*this);
   uri.forget(_newURI);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::CloneIgnoringRef(nsIURI **_newURI)
+NullPrincipalURI::CloneIgnoringRef(nsIURI** _newURI)
 {
-  // GetRef/SetRef not supported by nsNullPrincipalURI, so
+  // GetRef/SetRef not supported by NullPrincipalURI, so
   // CloneIgnoringRef() is the same as Clone().
   return Clone(_newURI);
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::CloneWithNewRef(const nsACString& newRef, nsIURI **_newURI)
+NullPrincipalURI::CloneWithNewRef(const nsACString& newRef, nsIURI** _newURI)
 {
-  // GetRef/SetRef not supported by nsNullPrincipalURI, so
+  // GetRef/SetRef not supported by NullPrincipalURI, so
   // CloneWithNewRef() is the same as Clone().
   return Clone(_newURI);
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::Equals(nsIURI *aOther, bool *_equals)
+NullPrincipalURI::Equals(nsIURI* aOther, bool* _equals)
 {
   *_equals = false;
-  RefPtr<nsNullPrincipalURI> otherURI;
+  RefPtr<NullPrincipalURI> otherURI;
   nsresult rv = aOther->QueryInterface(kNullPrincipalURIImplementationCID,
                                        getter_AddRefs(otherURI));
   if (NS_SUCCEEDED(rv)) {
     *_equals = mPath == otherURI->mPath;
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::EqualsExceptRef(nsIURI *aOther, bool *_equals)
+NullPrincipalURI::EqualsExceptRef(nsIURI* aOther, bool* _equals)
 {
-  // GetRef/SetRef not supported by nsNullPrincipalURI, so
+  // GetRef/SetRef not supported by NullPrincipalURI, so
   // EqualsExceptRef() is the same as Equals().
   return Equals(aOther, _equals);
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::Resolve(const nsACString &aRelativePath,
-                            nsACString &_resolvedURI)
+NullPrincipalURI::Resolve(const nsACString& aRelativePath,
+                            nsACString& _resolvedURI)
 {
   _resolvedURI = aRelativePath;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsNullPrincipalURI::SchemeIs(const char *aScheme, bool *_schemeIs)
+NullPrincipalURI::SchemeIs(const char* aScheme, bool* _schemeIs)
 {
   *_schemeIs = (0 == nsCRT::strcasecmp(NS_NULLPRINCIPAL_SCHEME, aScheme));
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsIIPCSerializableURI
 
 void
-nsNullPrincipalURI::Serialize(mozilla::ipc::URIParams &aParams)
+NullPrincipalURI::Serialize(mozilla::ipc::URIParams& aParams)
 {
   aParams = mozilla::ipc::NullPrincipalURIParams();
 }
 
 bool
-nsNullPrincipalURI::Deserialize(const mozilla::ipc::URIParams &aParams)
+NullPrincipalURI::Deserialize(const mozilla::ipc::URIParams& aParams)
 {
   if (aParams.type() != mozilla::ipc::URIParams::TNullPrincipalURIParams) {
     MOZ_ASSERT_UNREACHABLE("unexpected URIParams type");
     return false;
   }
 
   nsresult rv = Init();
   NS_ENSURE_SUCCESS(rv, false);
 
   return true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// nsISizeOf
 
 size_t
-nsNullPrincipalURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+NullPrincipalURI::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 }
 
 size_t
-nsNullPrincipalURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const {
+NullPrincipalURI::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
+{
   return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
 }
-
rename from caps/nsNullPrincipalURI.h
rename to caps/NullPrincipalURI.h
--- a/caps/nsNullPrincipalURI.h
+++ b/caps/NullPrincipalURI.h
@@ -3,57 +3,57 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.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 wraps nsSimpleURI so that all calls to it are done on the main thread.
  */
 
-#ifndef __nsNullPrincipalURI_h__
-#define __nsNullPrincipalURI_h__
+#ifndef __NullPrincipalURI_h__
+#define __NullPrincipalURI_h__
 
 #include "nsIURI.h"
 #include "nsISizeOf.h"
 #include "nsString.h"
 #include "mozilla/Attributes.h"
 #include "nsIIPCSerializableURI.h"
 #include "mozilla/MemoryReporting.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsID.h"
 
 // {51fcd543-3b52-41f7-b91b-6b54102236e6}
 #define NS_NULLPRINCIPALURI_IMPLEMENTATION_CID \
   {0x51fcd543, 0x3b52, 0x41f7, \
     {0xb9, 0x1b, 0x6b, 0x54, 0x10, 0x22, 0x36, 0xe6} }
 
-class nsNullPrincipalURI final : public nsIURI
-                               , public nsISizeOf
-                               , public nsIIPCSerializableURI
+class NullPrincipalURI final : public nsIURI
+                             , public nsISizeOf
+                             , public nsIIPCSerializableURI
 {
 public:
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIURI
   NS_DECL_NSIIPCSERIALIZABLEURI
 
   // nsISizeOf
   virtual size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
   virtual size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const override;
 
   // NB: This constructor exists only for deserialization.  Everyone
   // else should call Create.
-  nsNullPrincipalURI();
+  NullPrincipalURI();
 
   // Returns null on failure.
-  static already_AddRefed<nsNullPrincipalURI> Create();
+  static already_AddRefed<NullPrincipalURI> Create();
 
 private:
-  nsNullPrincipalURI(const nsNullPrincipalURI& aOther);
+  NullPrincipalURI(const NullPrincipalURI& aOther);
 
-  ~nsNullPrincipalURI() {}
+  ~NullPrincipalURI() {}
 
   nsresult Init();
 
   char mPathBytes[NSID_LENGTH];
   nsFixedCString mPath;
 };
 
-#endif // __nsNullPrincipalURI_h__
+#endif // __NullPrincipalURI_h__
copy from caps/BasePrincipal.cpp
copy to caps/OriginAttributes.cpp
--- a/caps/BasePrincipal.cpp
+++ b/caps/OriginAttributes.cpp
@@ -1,38 +1,20 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 sw=2 et 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/. */
 
-#include "mozilla/BasePrincipal.h"
-
-#include "nsDocShell.h"
-#ifdef MOZ_CRASHREPORTER
-#include "nsExceptionHandler.h"
-#endif
-#include "nsIAddonPolicyService.h"
-#include "nsIContentSecurityPolicy.h"
+#include "mozilla/OriginAttributes.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/dom/URLSearchParams.h"
+#include "mozilla/dom/quota/QuotaManager.h"
 #include "nsIEffectiveTLDService.h"
-#include "nsIObjectInputStream.h"
-#include "nsIObjectOutputStream.h"
-
-#include "nsPrincipal.h"
-#include "nsNetUtil.h"
-#include "nsIURIWithPrincipal.h"
-#include "nsNullPrincipal.h"
-#include "nsScriptSecurityManager.h"
-#include "nsServiceManagerUtils.h"
-
-#include "mozilla/dom/ChromeUtils.h"
-#include "mozilla/dom/CSPDictionariesBinding.h"
-#include "mozilla/dom/quota/QuotaManager.h"
-#include "mozilla/dom/ToJSValue.h"
-#include "mozilla/dom/URLSearchParams.h"
+#include "nsIURI.h"
 
 namespace mozilla {
 
 using dom::URLParams;
 
 bool OriginAttributes::sFirstPartyIsolation = false;
 bool OriginAttributes::sRestrictedOpenerAccess = false;
 
@@ -293,457 +275,9 @@ OriginAttributes::IsPrivateBrowsing(cons
   OriginAttributes attrs;
   if (NS_WARN_IF(!attrs.PopulateFromOrigin(aOrigin, dummy))) {
     return false;
   }
 
   return !!attrs.mPrivateBrowsingId;
 }
 
-BasePrincipal::BasePrincipal(PrincipalKind aKind)
-  : mKind(aKind)
-  , mDomainSet(false)
-{}
-
-BasePrincipal::~BasePrincipal()
-{}
-
-NS_IMETHODIMP
-BasePrincipal::GetOrigin(nsACString& aOrigin)
-{
-  nsresult rv = GetOriginNoSuffix(aOrigin);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsAutoCString suffix;
-  rv = GetOriginSuffix(suffix);
-  NS_ENSURE_SUCCESS(rv, rv);
-  aOrigin.Append(suffix);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin)
-{
-  if (mOriginNoSuffix) {
-    return mOriginNoSuffix->ToUTF8String(aOrigin);
-  }
-  return GetOriginInternal(aOrigin);
-}
-
-bool
-BasePrincipal::Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration)
-{
-  MOZ_ASSERT(aOther);
-  MOZ_ASSERT_IF(Kind() == eCodebasePrincipal, mOriginSuffix);
-
-  // Expanded principals handle origin attributes for each of their
-  // sub-principals individually, null principals do only simple checks for
-  // pointer equality, and system principals are immune to origin attributes
-  // checks, so only do this check for codebase principals.
-  if (Kind() == eCodebasePrincipal &&
-      mOriginSuffix != Cast(aOther)->mOriginSuffix) {
-    return false;
-  }
-
-  return SubsumesInternal(aOther, aConsideration);
-}
-
-NS_IMETHODIMP
-BasePrincipal::Equals(nsIPrincipal *aOther, bool *aResult)
-{
-  NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
-
-  *aResult = FastEquals(aOther);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::EqualsConsideringDomain(nsIPrincipal *aOther, bool *aResult)
-{
-  NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
-
-  *aResult = FastEqualsConsideringDomain(aOther);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::Subsumes(nsIPrincipal *aOther, bool *aResult)
-{
-  NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
-
-  *aResult = FastSubsumes(aOther);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::SubsumesConsideringDomain(nsIPrincipal *aOther, bool *aResult)
-{
-  NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
-
-  *aResult = FastSubsumesConsideringDomain(aOther);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::SubsumesConsideringDomainIgnoringFPD(nsIPrincipal *aOther,
-                                                    bool *aResult)
-{
-  NS_ENSURE_TRUE(aOther, NS_ERROR_INVALID_ARG);
-
-  *aResult = FastSubsumesConsideringDomainIgnoringFPD(aOther);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::CheckMayLoad(nsIURI* aURI, bool aReport, bool aAllowIfInheritsPrincipal)
-{
-  // Check the internal method first, which allows us to quickly approve loads
-  // for the System Principal.
-  if (MayLoadInternal(aURI)) {
-    return NS_OK;
-  }
-
-  nsresult rv;
-  if (aAllowIfInheritsPrincipal) {
-    // If the caller specified to allow loads of URIs that inherit
-    // our principal, allow the load if this URI inherits its principal.
-    bool doesInheritSecurityContext;
-    rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
-                             &doesInheritSecurityContext);
-    if (NS_SUCCEEDED(rv) && doesInheritSecurityContext) {
-      return NS_OK;
-    }
-  }
-
-  bool fetchableByAnyone;
-  rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_FETCHABLE_BY_ANYONE, &fetchableByAnyone);
-  if (NS_SUCCEEDED(rv) && fetchableByAnyone) {
-    return NS_OK;
-  }
-
-  if (aReport) {
-    nsCOMPtr<nsIURI> prinURI;
-    rv = GetURI(getter_AddRefs(prinURI));
-    if (NS_SUCCEEDED(rv) && prinURI) {
-      nsScriptSecurityManager::ReportError(nullptr, NS_LITERAL_STRING("CheckSameOriginError"), prinURI, aURI);
-    }
-  }
-
-  return NS_ERROR_DOM_BAD_URI;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
-{
-  NS_IF_ADDREF(*aCsp = mCSP);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
-{
-  // Never destroy an existing CSP on the principal.
-  // This method should only be called in rare cases.
-
-  MOZ_ASSERT(!mCSP, "do not destroy an existing CSP");
-  if (mCSP) {
-    return NS_ERROR_ALREADY_INITIALIZED;
-  }
-
-  mCSP = aCsp;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::EnsureCSP(nsIDOMDocument* aDocument,
-                         nsIContentSecurityPolicy** aCSP)
-{
-  if (mCSP) {
-    // if there is a CSP already associated with this principal
-    // then just return that - do not overwrite it!!!
-    NS_IF_ADDREF(*aCSP = mCSP);
-    return NS_OK;
-  }
-
-  nsresult rv = NS_OK;
-  mCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Store the request context for violation reports
-  rv = aDocument ? mCSP->SetRequestContext(aDocument, nullptr)
-                 : mCSP->SetRequestContext(nullptr, this);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_IF_ADDREF(*aCSP = mCSP);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
-{
-  NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument,
-                                nsIContentSecurityPolicy** aPreloadCSP)
-{
-  if (mPreloadCSP) {
-    // if there is a speculative CSP already associated with this principal
-    // then just return that - do not overwrite it!!!
-    NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
-    return NS_OK;
-  }
-
-  nsresult rv = NS_OK;
-  mPreloadCSP = do_CreateInstance("@mozilla.org/cspcontext;1", &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // Store the request context for violation reports
-  rv = aDocument ? mPreloadCSP->SetRequestContext(aDocument, nullptr)
-                 : mPreloadCSP->SetRequestContext(nullptr, this);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_IF_ADDREF(*aPreloadCSP = mPreloadCSP);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetCspJSON(nsAString& outCSPinJSON)
-{
-  outCSPinJSON.Truncate();
-  dom::CSPPolicies jsonPolicies;
-
-  if (!mCSP) {
-    jsonPolicies.ToJSON(outCSPinJSON);
-    return NS_OK;
-  }
-  return mCSP->ToJSON(outCSPinJSON);
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetIsNullPrincipal(bool* aResult)
-{
-  *aResult = Kind() == eNullPrincipal;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetIsCodebasePrincipal(bool* aResult)
-{
-  *aResult = Kind() == eCodebasePrincipal;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetIsExpandedPrincipal(bool* aResult)
-{
-  *aResult = Kind() == eExpandedPrincipal;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetIsSystemPrincipal(bool* aResult)
-{
-  *aResult = Kind() == eSystemPrincipal;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal)
-{
-  if (NS_WARN_IF(!ToJSValue(aCx, mOriginAttributes, aVal))) {
-    return NS_ERROR_FAILURE;
-  }
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
-{
-  MOZ_ASSERT(mOriginSuffix);
-  return mOriginSuffix->ToUTF8String(aOriginAttributes);
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetAppStatus(uint16_t* aAppStatus)
-{
-  // TODO: Remove GetAppStatus.
-  *aAppStatus = nsIPrincipal::APP_STATUS_NOT_INSTALLED;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetAppId(uint32_t* aAppId)
-{
-  if (AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID) {
-    MOZ_ASSERT(false);
-    *aAppId = nsIScriptSecurityManager::NO_APP_ID;
-    return NS_OK;
-  }
-
-  *aAppId = AppId();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetUserContextId(uint32_t* aUserContextId)
-{
-  *aUserContextId = UserContextId();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId)
-{
-  *aPrivateBrowsingId = PrivateBrowsingId();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement)
-{
-  *aIsInIsolatedMozBrowserElement = IsInIsolatedMozBrowserElement();
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-BasePrincipal::GetUnknownAppId(bool* aUnknownAppId)
-{
-  *aUnknownAppId = AppId() == nsIScriptSecurityManager::UNKNOWN_APP_ID;
-  return NS_OK;
-}
-
-bool
-BasePrincipal::AddonHasPermission(const nsAString& aPerm)
-{
-  nsAutoString addonId;
-  NS_ENSURE_SUCCESS(GetAddonId(addonId), false);
-
-  if (addonId.IsEmpty()) {
-    return false;
-  }
-
-  nsCOMPtr<nsIAddonPolicyService> aps =
-    do_GetService("@mozilla.org/addons/policy-service;1");
-  NS_ENSURE_TRUE(aps, false);
-
-  bool retval = false;
-  nsresult rv = aps->AddonHasPermission(addonId, aPerm, &retval);
-  NS_ENSURE_SUCCESS(rv, false);
-  return retval;
-}
-
-already_AddRefed<BasePrincipal>
-BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs)
-{
-  // If the URI is supposed to inherit the security context of whoever loads it,
-  // we shouldn't make a codebase principal for it.
-  bool inheritsPrincipal;
-  nsresult rv = NS_URIChainHasFlags(aURI, nsIProtocolHandler::URI_INHERITS_SECURITY_CONTEXT,
-                                    &inheritsPrincipal);
-  if (NS_FAILED(rv) || inheritsPrincipal) {
-    return nsNullPrincipal::Create(aAttrs);
-  }
-
-  // Check whether the URI knows what its principal is supposed to be.
-  nsCOMPtr<nsIURIWithPrincipal> uriPrinc = do_QueryInterface(aURI);
-  if (uriPrinc) {
-    nsCOMPtr<nsIPrincipal> principal;
-    uriPrinc->GetPrincipal(getter_AddRefs(principal));
-    if (!principal) {
-      return nsNullPrincipal::Create(aAttrs);
-    }
-    RefPtr<BasePrincipal> concrete = Cast(principal);
-    return concrete.forget();
-  }
-
-  // Mint a codebase principal.
-  RefPtr<nsPrincipal> codebase = new nsPrincipal();
-  rv = codebase->Init(aURI, aAttrs);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-  return codebase.forget();
-}
-
-already_AddRefed<BasePrincipal>
-BasePrincipal::CreateCodebasePrincipal(const nsACString& aOrigin)
-{
-  MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING("[")),
-             "CreateCodebasePrincipal does not support System and Expanded principals");
-
-  MOZ_ASSERT(!StringBeginsWith(aOrigin, NS_LITERAL_CSTRING(NS_NULLPRINCIPAL_SCHEME ":")),
-             "CreateCodebasePrincipal does not support nsNullPrincipal");
-
-  nsAutoCString originNoSuffix;
-  mozilla::OriginAttributes attrs;
-  if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
-    return nullptr;
-  }
-
-  nsCOMPtr<nsIURI> uri;
-  nsresult rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
-}
-
-already_AddRefed<BasePrincipal>
-BasePrincipal::CloneStrippingUserContextIdAndFirstPartyDomain()
-{
-  OriginAttributes attrs = OriginAttributesRef();
-  attrs.StripAttributes(OriginAttributes::STRIP_USER_CONTEXT_ID |
-                        OriginAttributes::STRIP_FIRST_PARTY_DOMAIN);
-
-  nsAutoCString originNoSuffix;
-  nsresult rv = GetOriginNoSuffix(originNoSuffix);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  nsCOMPtr<nsIURI> uri;
-  rv = NS_NewURI(getter_AddRefs(uri), originNoSuffix);
-  NS_ENSURE_SUCCESS(rv, nullptr);
-
-  return BasePrincipal::CreateCodebasePrincipal(uri, attrs);
-}
-
-bool
-BasePrincipal::AddonAllowsLoad(nsIURI* aURI, bool aExplicit /* = false */)
-{
-  nsAutoString addonId;
-  NS_ENSURE_SUCCESS(GetAddonId(addonId), false);
-
-  if (addonId.IsEmpty()) {
-    return false;
-  }
-
-  nsCOMPtr<nsIAddonPolicyService> aps = do_GetService("@mozilla.org/addons/policy-service;1");
-  NS_ENSURE_TRUE(aps, false);
-
-  bool allowed = false;
-  nsresult rv = aps->AddonMayLoadURI(addonId, aURI, aExplicit, &allowed);
-  return NS_SUCCEEDED(rv) && allowed;
-}
-
-void
-BasePrincipal::FinishInit()
-{
-  // First compute the origin suffix since it's infallible.
-  nsAutoCString originSuffix;
-  mOriginAttributes.CreateSuffix(originSuffix);
-  mOriginSuffix = NS_Atomize(originSuffix);
-
-  // Then compute the origin without the suffix.
-  nsAutoCString originNoSuffix;
-  nsresult rv = GetOriginInternal(originNoSuffix);
-  if (NS_FAILED(rv)) {
-    // If GetOriginInternal fails, we will get a null atom for mOriginNoSuffix,
-    // which we deal with anywhere mOriginNoSuffix is used.
-    // Once this is made infallible we can remove those null checks.
-    mOriginNoSuffix = nullptr;
-    return;
-  }
-  mOriginNoSuffix = NS_Atomize(originNoSuffix);
-}
-
 } // namespace mozilla
copy from caps/BasePrincipal.h
copy to caps/OriginAttributes.h
--- a/caps/BasePrincipal.h
+++ b/caps/OriginAttributes.h
@@ -1,35 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef mozilla_BasePrincipal_h
-#define mozilla_BasePrincipal_h
+#ifndef mozilla_OriginAttributes_h
+#define mozilla_OriginAttributes_h
 
-#include "nsJSPrincipals.h"
-
-#include "mozilla/Attributes.h"
 #include "mozilla/dom/ChromeUtils.h"
 #include "mozilla/dom/ChromeUtilsBinding.h"
 #include "nsIScriptSecurityManager.h"
 
-class nsIContentSecurityPolicy;
-class nsIObjectOutputStream;
-class nsIObjectInputStream;
-class nsIURI;
-
-class nsExpandedPrincipal;
-
 namespace mozilla {
 
-// Base OriginAttributes class. This has several subclass flavors, and is not
-// directly constructable itself.
 class OriginAttributes : public dom::OriginAttributesDictionary
 {
 public:
   OriginAttributes() {}
 
   OriginAttributes(uint32_t aAppId, bool aInIsolatedMozBrowser)
   {
     mAppId = aAppId;
@@ -186,214 +174,11 @@ public:
         mFirstPartyDomain.Value() != aOther.mFirstPartyDomain.Value()) {
       return false;
     }
 
     return true;
   }
 };
 
-/*
- * Base class from which all nsIPrincipal implementations inherit. Use this for
- * default implementations and other commonalities between principal
- * implementations.
- *
- * We should merge nsJSPrincipals into this class at some point.
- */
-class BasePrincipal : public nsJSPrincipals
-{
-public:
-  enum PrincipalKind {
-    eNullPrincipal,
-    eCodebasePrincipal,
-    eExpandedPrincipal,
-    eSystemPrincipal
-  };
-
-  explicit BasePrincipal(PrincipalKind aKind);
-
-  enum DocumentDomainConsideration { DontConsiderDocumentDomain, ConsiderDocumentDomain};
-  bool Subsumes(nsIPrincipal* aOther, DocumentDomainConsideration aConsideration);
-
-  NS_IMETHOD GetOrigin(nsACString& aOrigin) final;
-  NS_IMETHOD GetOriginNoSuffix(nsACString& aOrigin) final;
-  NS_IMETHOD Equals(nsIPrincipal* other, bool* _retval) final;
-  NS_IMETHOD EqualsConsideringDomain(nsIPrincipal* other, bool* _retval) final;
-  NS_IMETHOD Subsumes(nsIPrincipal* other, bool* _retval) final;
-  NS_IMETHOD SubsumesConsideringDomain(nsIPrincipal* other, bool* _retval) final;
-  NS_IMETHOD SubsumesConsideringDomainIgnoringFPD(nsIPrincipal* other, bool* _retval) final;
-  NS_IMETHOD CheckMayLoad(nsIURI* uri, bool report, bool allowIfInheritsPrincipal) final;
-  NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
-  NS_IMETHOD SetCsp(nsIContentSecurityPolicy* aCsp) override;
-  NS_IMETHOD EnsureCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
-  NS_IMETHOD GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP) override;
-  NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
-  NS_IMETHOD GetCspJSON(nsAString& outCSPinJSON) override;
-  NS_IMETHOD GetIsNullPrincipal(bool* aResult) override;
-  NS_IMETHOD GetIsCodebasePrincipal(bool* aResult) override;
-  NS_IMETHOD GetIsExpandedPrincipal(bool* aResult) override;
-  NS_IMETHOD GetIsSystemPrincipal(bool* aResult) override;
-  NS_IMETHOD GetOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aVal) final;
-  NS_IMETHOD GetOriginSuffix(nsACString& aOriginSuffix) final;
-  NS_IMETHOD GetAppStatus(uint16_t* aAppStatus) final;
-  NS_IMETHOD GetAppId(uint32_t* aAppStatus) final;
-  NS_IMETHOD GetIsInIsolatedMozBrowserElement(bool* aIsInIsolatedMozBrowserElement) final;
-  NS_IMETHOD GetUnknownAppId(bool* aUnknownAppId) final;
-  NS_IMETHOD GetUserContextId(uint32_t* aUserContextId) final;
-  NS_IMETHOD GetPrivateBrowsingId(uint32_t* aPrivateBrowsingId) final;
-
-  virtual bool AddonHasPermission(const nsAString& aPerm);
-
-  virtual bool IsCodebasePrincipal() const { return false; };
-
-  static BasePrincipal* Cast(nsIPrincipal* aPrin) { return static_cast<BasePrincipal*>(aPrin); }
-  static already_AddRefed<BasePrincipal>
-  CreateCodebasePrincipal(nsIURI* aURI, const OriginAttributes& aAttrs);
-  static already_AddRefed<BasePrincipal> CreateCodebasePrincipal(const nsACString& aOrigin);
-
-  const OriginAttributes& OriginAttributesRef() final { return mOriginAttributes; }
-  uint32_t AppId() const { return mOriginAttributes.mAppId; }
-  uint32_t UserContextId() const { return mOriginAttributes.mUserContextId; }
-  uint32_t PrivateBrowsingId() const { return mOriginAttributes.mPrivateBrowsingId; }
-  bool IsInIsolatedMozBrowserElement() const { return mOriginAttributes.mInIsolatedMozBrowser; }
-
-  PrincipalKind Kind() const { return mKind; }
-
-  already_AddRefed<BasePrincipal> CloneStrippingUserContextIdAndFirstPartyDomain();
-
-  // Helper to check whether this principal is associated with an addon that
-  // allows unprivileged code to load aURI.  aExplicit == true will prevent
-  // use of all_urls permission, requiring the domain in its permissions.
-  bool AddonAllowsLoad(nsIURI* aURI, bool aExplicit = false);
-
-  // Call these to avoid the cost of virtual dispatch.
-  inline bool FastEquals(nsIPrincipal* aOther);
-  inline bool FastEqualsConsideringDomain(nsIPrincipal* aOther);
-  inline bool FastSubsumes(nsIPrincipal* aOther);
-  inline bool FastSubsumesConsideringDomain(nsIPrincipal* aOther);
-  inline bool FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther);
-
-protected:
-  virtual ~BasePrincipal();
-
-  virtual nsresult GetOriginInternal(nsACString& aOrigin) = 0;
-  // Note that this does not check OriginAttributes. Callers that depend on
-  // those must call Subsumes instead.
-  virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
-
-  // Internal, side-effect-free check to determine whether the concrete
-  // principal would allow the load ignoring any common behavior implemented in
-  // BasePrincipal::CheckMayLoad.
-  virtual bool MayLoadInternal(nsIURI* aURI) = 0;
-  friend class ::nsExpandedPrincipal;
-
-  // This function should be called as the last step of the initialization of the
-  // principal objects.  It's typically called as the last step from the Init()
-  // method of the child classes.
-  void FinishInit();
-
-  nsCOMPtr<nsIContentSecurityPolicy> mCSP;
-  nsCOMPtr<nsIContentSecurityPolicy> mPreloadCSP;
-  nsCOMPtr<nsIAtom> mOriginNoSuffix;
-  nsCOMPtr<nsIAtom> mOriginSuffix;
-  OriginAttributes mOriginAttributes;
-  PrincipalKind mKind;
-  bool mDomainSet;
-};
-
-inline bool
-BasePrincipal::FastEquals(nsIPrincipal* aOther)
-{
-  auto other = Cast(aOther);
-  if (Kind() != other->Kind()) {
-    // Principals of different kinds can't be equal.
-    return false;
-  }
-
-  // Two principals are considered to be equal if their origins are the same.
-  // If the two principals are codebase principals, their origin attributes
-  // (aka the origin suffix) must also match.
-  // If the two principals are null principals, they're only equal if they're
-  // the same object.
-  if (Kind() == eNullPrincipal || Kind() == eSystemPrincipal) {
-    return this == other;
-  }
-
-  if (mOriginNoSuffix) {
-    if (Kind() == eCodebasePrincipal) {
-      return mOriginNoSuffix == other->mOriginNoSuffix &&
-             mOriginSuffix == other->mOriginSuffix;
-    }
-
-    MOZ_ASSERT(Kind() == eExpandedPrincipal);
-    return mOriginNoSuffix == other->mOriginNoSuffix;
-  }
-
-  // If mOriginNoSuffix is null on one of our principals, we must fall back
-  // to the slow path.
-  return Subsumes(aOther, DontConsiderDocumentDomain) &&
-         other->Subsumes(this, DontConsiderDocumentDomain);
-}
-
-inline bool
-BasePrincipal::FastEqualsConsideringDomain(nsIPrincipal* aOther)
-{
-  // If neither of the principals have document.domain set, we use the fast path
-  // in Equals().  Otherwise, we fall back to the slow path below.
-  auto other = Cast(aOther);
-  if (!mDomainSet && !other->mDomainSet) {
-    return FastEquals(aOther);
-  }
-
-  return Subsumes(aOther, ConsiderDocumentDomain) &&
-         other->Subsumes(this, ConsiderDocumentDomain);
-}
-
-inline bool
-BasePrincipal::FastSubsumes(nsIPrincipal* aOther)
-{
-  // If two principals are equal, then they both subsume each other.
-  // We deal with two special cases first:
-  // Null principals only subsume each other if they are equal, and are only
-  // equal if they're the same object.
-  // Also, if mOriginNoSuffix is null, FastEquals falls back to the slow path
-  // using Subsumes, so we don't want to use it in that case to avoid an
-  // infinite recursion.
-  auto other = Cast(aOther);
-  if (Kind() == eNullPrincipal && other->Kind() == eNullPrincipal) {
-    return this == other;
-  }
-  if (mOriginNoSuffix && FastEquals(aOther)) {
-    return true;
-  }
-
-  // Otherwise, fall back to the slow path.
-  return Subsumes(aOther, DontConsiderDocumentDomain);
-}
-
-inline bool
-BasePrincipal::FastSubsumesConsideringDomain(nsIPrincipal* aOther)
-{
-  // If neither of the principals have document.domain set, we hand off to
-  // FastSubsumes() which has fast paths for some special cases. Otherwise, we fall
-  // back to the slow path below.
-  if (!mDomainSet && !Cast(aOther)->mDomainSet) {
-    return FastSubsumes(aOther);
-  }
-
-  return Subsumes(aOther, ConsiderDocumentDomain);
-}
-
-inline bool
-BasePrincipal::FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther)
-{
-  if (Kind() == eCodebasePrincipal &&
-      !dom::ChromeUtils::IsOriginAttributesEqualIgnoringFPD(
-            mOriginAttributes, Cast(aOther)->mOriginAttributes)) {
-    return false;
-  }
-
- return SubsumesInternal(aOther, ConsiderDocumentDomain);
-}
-
 } // namespace mozilla
 
-#endif /* mozilla_BasePrincipal_h */
+#endif /* mozilla_OriginAttributes_h */
rename from caps/nsSystemPrincipal.cpp
rename to caps/SystemPrincipal.cpp
--- a/caps/nsSystemPrincipal.cpp
+++ b/caps/SystemPrincipal.cpp
@@ -1,156 +1,156 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.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 privileged system principal. */
 
 #include "nscore.h"
-#include "nsSystemPrincipal.h"
+#include "SystemPrincipal.h"
 #include "nsIComponentManager.h"
 #include "nsIServiceManager.h"
 #include "nsIURL.h"
 #include "nsCOMPtr.h"
 #include "nsXPIDLString.h"
 #include "nsReadableUtils.h"
 #include "nsCRT.h"
 #include "nsString.h"
 #include "nsIClassInfoImpl.h"
 #include "nsIScriptSecurityManager.h"
 #include "pratom.h"
 
-NS_IMPL_CLASSINFO(nsSystemPrincipal, nullptr,
+NS_IMPL_CLASSINFO(SystemPrincipal, nullptr,
                   nsIClassInfo::SINGLETON | nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_SYSTEMPRINCIPAL_CID)
-NS_IMPL_QUERY_INTERFACE_CI(nsSystemPrincipal,
+NS_IMPL_QUERY_INTERFACE_CI(SystemPrincipal,
                            nsIPrincipal,
                            nsISerializable)
-NS_IMPL_CI_INTERFACE_GETTER(nsSystemPrincipal,
+NS_IMPL_CI_INTERFACE_GETTER(SystemPrincipal,
                             nsIPrincipal,
                             nsISerializable)
 
 #define SYSTEM_PRINCIPAL_SPEC "[System Principal]"
 
-already_AddRefed<nsSystemPrincipal>
-nsSystemPrincipal::Create()
+already_AddRefed<SystemPrincipal>
+SystemPrincipal::Create()
 {
-  RefPtr<nsSystemPrincipal> sp = new nsSystemPrincipal();
+  RefPtr<SystemPrincipal> sp = new SystemPrincipal();
   sp->FinishInit();
   return sp.forget();
 }
 
 nsresult
-nsSystemPrincipal::GetScriptLocation(nsACString &aStr)
+SystemPrincipal::GetScriptLocation(nsACString &aStr)
 {
     aStr.AssignLiteral(SYSTEM_PRINCIPAL_SPEC);
     return NS_OK;
 }
 
 ///////////////////////////////////////
 // Methods implementing nsIPrincipal //
 ///////////////////////////////////////
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetHashValue(uint32_t *result)
+SystemPrincipal::GetHashValue(uint32_t *result)
 {
     *result = NS_PTR_TO_INT32(this);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetURI(nsIURI** aURI)
+SystemPrincipal::GetURI(nsIURI** aURI)
 {
     *aURI = nullptr;
     return NS_OK;
 }
 
 nsresult
-nsSystemPrincipal::GetOriginInternal(nsACString& aOrigin)
+SystemPrincipal::GetOriginInternal(nsACString& aOrigin)
 {
     aOrigin.AssignLiteral(SYSTEM_PRINCIPAL_SPEC);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
+SystemPrincipal::GetCsp(nsIContentSecurityPolicy** aCsp)
 {
   *aCsp = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
+SystemPrincipal::SetCsp(nsIContentSecurityPolicy* aCsp)
 {
   // Never destroy an existing CSP on the principal.
   // This method should only be called in rare cases.
 
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument,
-                             nsIContentSecurityPolicy** aCSP)
+SystemPrincipal::EnsureCSP(nsIDOMDocument* aDocument,
+                           nsIContentSecurityPolicy** aCSP)
 {
   // CSP on a system principal makes no sense
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
+SystemPrincipal::GetPreloadCsp(nsIContentSecurityPolicy** aPreloadCSP)
 {
   *aPreloadCSP = nullptr;
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument,
-                                    nsIContentSecurityPolicy** aPreloadCSP)
+SystemPrincipal::EnsurePreloadCSP(nsIDOMDocument* aDocument,
+                                  nsIContentSecurityPolicy** aPreloadCSP)
 {
   // CSP on a system principal makes no sense
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetDomain(nsIURI** aDomain)
+SystemPrincipal::GetDomain(nsIURI** aDomain)
 {
     *aDomain = nullptr;
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::SetDomain(nsIURI* aDomain)
+SystemPrincipal::SetDomain(nsIURI* aDomain)
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetBaseDomain(nsACString& aBaseDomain)
+SystemPrincipal::GetBaseDomain(nsACString& aBaseDomain)
 {
   // No base domain for chrome.
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::GetAddonId(nsAString& aAddonId)
+SystemPrincipal::GetAddonId(nsAString& aAddonId)
 {
   aAddonId.Truncate();
   return NS_OK;
 };
 
 //////////////////////////////////////////
 // Methods implementing nsISerializable //
 //////////////////////////////////////////
 
 NS_IMETHODIMP
-nsSystemPrincipal::Read(nsIObjectInputStream* aStream)
+SystemPrincipal::Read(nsIObjectInputStream* aStream)
 {
     // no-op: CID is sufficient to identify the mSystemPrincipal singleton
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsSystemPrincipal::Write(nsIObjectOutputStream* aStream)
+SystemPrincipal::Write(nsIObjectOutputStream* aStream)
 {
     // no-op: CID is sufficient to identify the mSystemPrincipal singleton
     return NS_OK;
 }
rename from caps/nsSystemPrincipal.h
rename to caps/SystemPrincipal.h
--- a/caps/nsSystemPrincipal.h
+++ b/caps/SystemPrincipal.h
@@ -1,39 +1,39 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* The privileged system principal. */
 
-#ifndef nsSystemPrincipal_h__
-#define nsSystemPrincipal_h__
+#ifndef SystemPrincipal_h
+#define SystemPrincipal_h
 
 #include "nsIPrincipal.h"
 #include "nsJSPrincipals.h"
 
 #include "mozilla/BasePrincipal.h"
 
 #define NS_SYSTEMPRINCIPAL_CID \
 { 0x4a6212db, 0xaccb, 0x11d3, \
 { 0xb7, 0x65, 0x0, 0x60, 0xb0, 0xb6, 0xce, 0xcb }}
 #define NS_SYSTEMPRINCIPAL_CONTRACTID "@mozilla.org/systemprincipal;1"
 
 
-class nsSystemPrincipal final : public mozilla::BasePrincipal
+class SystemPrincipal final : public mozilla::BasePrincipal
 {
-  nsSystemPrincipal()
+  SystemPrincipal()
     : BasePrincipal(eSystemPrincipal)
   {
   }
 
 public:
-  static already_AddRefed<nsSystemPrincipal> Create();
+  static already_AddRefed<SystemPrincipal> Create();
 
   NS_DECL_NSISERIALIZABLE
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) override;
   NS_IMETHOD GetHashValue(uint32_t* aHashValue) override;
   NS_IMETHOD GetURI(nsIURI** aURI) override;
   NS_IMETHOD GetDomain(nsIURI** aDomain) override;
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetCsp(nsIContentSecurityPolicy** aCsp) override;
@@ -43,22 +43,23 @@ public:
   NS_IMETHOD EnsurePreloadCSP(nsIDOMDocument* aDocument, nsIContentSecurityPolicy** aCSP) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
   nsresult GetOriginInternal(nsACString& aOrigin) override;
 
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
 protected:
-  virtual ~nsSystemPrincipal(void) {}
+  virtual ~SystemPrincipal(void) {}
 
-  bool SubsumesInternal(nsIPrincipal *aOther, DocumentDomainConsideration aConsideration) override
+  bool SubsumesInternal(nsIPrincipal *aOther,
+                        DocumentDomainConsideration aConsideration) override
   {
     return true;
   }
 
   bool MayLoadInternal(nsIURI* aURI) override
   {
     return true;
   }
 };
 
-#endif // nsSystemPrincipal_h__
+#endif // SystemPrincipal_h
--- a/caps/moz.build
+++ b/caps/moz.build
@@ -20,39 +20,41 @@ XPIDL_SOURCES += [
     'nsIPrincipal.idl',
     'nsIScriptSecurityManager.idl',
 ]
 
 XPIDL_MODULE = 'caps'
 
 EXPORTS += [
     'nsJSPrincipals.h',
-    'nsNullPrincipal.h',
-    'nsNullPrincipalURI.h',
+    'NullPrincipal.h',
+    'NullPrincipalURI.h',
 ]
 
 EXPORTS.mozilla = [
-    'BasePrincipal.h'
+    'BasePrincipal.h',
+    'OriginAttributes.h',
 ]
 
 SOURCES += [
     # Compile this separately since nsExceptionHandler.h conflicts
-    # with something from nsNullPrincipal.cpp.
+    # with something from NullPrincipal.cpp.
     'BasePrincipal.cpp',
 ]
 
 UNIFIED_SOURCES += [
+    'ContentPrincipal.cpp',
     'DomainPolicy.cpp',
-    'nsExpandedPrincipal.cpp',
+    'ExpandedPrincipal.cpp',
     'nsJSPrincipals.cpp',
-    'nsNullPrincipal.cpp',
-    'nsNullPrincipalURI.cpp',
-    'nsPrincipal.cpp',
     'nsScriptSecurityManager.cpp',
-    'nsSystemPrincipal.cpp',
+    'NullPrincipal.cpp',
+    'NullPrincipalURI.cpp',
+    'OriginAttributes.cpp',
+    'SystemPrincipal.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/docshell/base',
     '/dom/base',
     '/js/xpconnect/src',
 ]
 
--- a/caps/nsIPrincipal.idl
+++ b/caps/nsIPrincipal.idl
@@ -352,22 +352,22 @@ interface nsIPrincipal : nsISerializable
 
     /**
      * Returns true iff this is the system principal.
      */
     [infallible] readonly attribute boolean isSystemPrincipal;
 };
 
 /**
- * If nsSystemPrincipal is too risky to use, but we want a principal to access
- * more than one origin, nsExpandedPrincipals letting us define an array of
- * principals it subsumes. So script with an nsExpandedPrincipals will gain
+ * If SystemPrincipal is too risky to use, but we want a principal to access
+ * more than one origin, ExpandedPrincipals letting us define an array of
+ * principals it subsumes. So script with an ExpandedPrincipals will gain
  * same origin access when at least one of its principals it contains gained
- * sameorigin acccess. An nsExpandedPrincipal will be subsumed by the system
- * principal, and by another nsExpandedPrincipal that has all its principals.
+ * sameorigin acccess. An ExpandedPrincipal will be subsumed by the system
+ * principal, and by another ExpandedPrincipal that has all its principals.
  * It is added for jetpack content-scripts to let them interact with the
  * content and a well defined set of other domains, without the risk of
  * leaking out a system principal to the content. See: Bug 734891
  */
 [uuid(f3e177Df-6a5e-489f-80a7-2dd1481471d8)]
 interface nsIExpandedPrincipal : nsISupports
 {
   /**
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -15,19 +15,18 @@
 #include "nsIServiceManager.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptContext.h"
 #include "nsIURL.h"
 #include "nsINestedURI.h"
 #include "nspr.h"
 #include "nsJSPrincipals.h"
 #include "mozilla/BasePrincipal.h"
-#include "nsSystemPrincipal.h"
-#include "nsPrincipal.h"
-#include "nsNullPrincipal.h"
+#include "SystemPrincipal.h"
+#include "NullPrincipal.h"
 #include "DomainPolicy.h"
 #include "nsXPIDLString.h"
 #include "nsCRT.h"
 #include "nsCRTGlue.h"
 #include "nsDocShell.h"
 #include "nsError.h"
 #include "nsDOMCID.h"
 #include "nsTextFormatter.h"
@@ -1136,17 +1135,17 @@ nsScriptSecurityManager::CreateCodebaseP
 NS_IMETHODIMP
 nsScriptSecurityManager::CreateNullPrincipal(JS::Handle<JS::Value> aOriginAttributes,
                                              JSContext* aCx, nsIPrincipal** aPrincipal)
 {
   OriginAttributes attrs;
   if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
       return NS_ERROR_INVALID_ARG;
   }
-  nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create(attrs);
+  nsCOMPtr<nsIPrincipal> prin = NullPrincipal::Create(attrs);
   prin.forget(aPrincipal);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsScriptSecurityManager::GetAppCodebasePrincipal(nsIURI* aURI,
                                                  uint32_t aAppId,
                                                  bool aInIsolatedMozBrowser,
@@ -1330,17 +1329,17 @@ nsresult nsScriptSecurityManager::Init()
         mozilla::services::GetStringBundleService();
     if (!bundleService)
         return NS_ERROR_FAILURE;
 
     rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Create our system principal singleton
-    RefPtr<nsSystemPrincipal> system = nsSystemPrincipal::Create();
+    RefPtr<SystemPrincipal> system = SystemPrincipal::Create();
 
     mSystemPrincipal = system;
 
     //-- Register security check callback in the JS engine
     //   Currently this is used to control access to function.caller
     sContext = danger::GetJSContext();
 
     static const JSSecurityCallbacks securityCallbacks = {
@@ -1402,23 +1401,23 @@ nsScriptSecurityManager::InitStatics()
 
     ClearOnShutdown(&gScriptSecMan);
     gScriptSecMan = ssManager;
 }
 
 // Currently this nsGenericFactory constructor is used only from FastLoad
 // (XPCOM object deserialization) code, when "creating" the system principal
 // singleton.
-nsSystemPrincipal *
+SystemPrincipal *
 nsScriptSecurityManager::SystemPrincipalSingletonConstructor()
 {
     nsIPrincipal *sysprin = nullptr;
     if (gScriptSecMan)
         NS_ADDREF(sysprin = gScriptSecMan->mSystemPrincipal);
-    return static_cast<nsSystemPrincipal*>(sysprin);
+    return static_cast<SystemPrincipal*>(sysprin);
 }
 
 struct IsWhitespace {
     static bool Test(char aChar) { return NS_IsAsciiWhitespace(aChar); };
 };
 struct IsWhitespaceOrComma {
     static bool Test(char aChar) { return aChar == ',' || NS_IsAsciiWhitespace(aChar); };
 };
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -19,17 +19,17 @@
 #include "plstr.h"
 #include "js/TypeDecls.h"
 
 #include <stdint.h>
 
 class nsCString;
 class nsIIOService;
 class nsIStringBundle;
-class nsSystemPrincipal;
+class SystemPrincipal;
 
 namespace mozilla {
 class OriginAttributes;
 } // namespace mozilla
 
 /////////////////////////////
 // nsScriptSecurityManager //
 /////////////////////////////
@@ -50,17 +50,17 @@ public:
     NS_DECL_NSIOBSERVER
 
     static nsScriptSecurityManager*
     GetScriptSecurityManager();
 
     // Invoked exactly once, by XPConnect.
     static void InitStatics();
 
-    static nsSystemPrincipal*
+    static SystemPrincipal*
     SystemPrincipalSingletonConstructor();
 
     /**
      * Utility method for comparing two URIs.  For security purposes, two URIs
      * are equivalent if their schemes, hosts, and ports (if any) match.  This
      * method returns true if aSubjectURI and aObjectURI have the same origin,
      * false otherwise.
      */
--- a/devtools/client/jsonview/main.js
+++ b/devtools/client/jsonview/main.js
@@ -45,17 +45,17 @@ var JsonView = {
 
   // Message handlers for events from child processes
 
   /**
    * Save JSON to a file needs to be implemented here
    * in the parent process.
    */
   onSave: function (message) {
-    JsonViewUtils.getTargetFile(file => {
+    JsonViewUtils.getTargetFile().then(file => {
       if (file) {
         JsonViewUtils.saveToFile(file, message.data);
       }
     });
   }
 };
 
 // Exports from this module
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -115,17 +115,17 @@
 #include "nsIFormPOSTActionChannel.h"
 #include "nsIUploadChannel.h"
 #include "nsIUploadChannel2.h"
 #include "nsIWebProgress.h"
 #include "nsILayoutHistoryState.h"
 #include "nsITimer.h"
 #include "nsISHistoryInternal.h"
 #include "nsIPrincipal.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsISHEntry.h"
 #include "nsIWindowWatcher.h"
 #include "nsIPromptFactory.h"
 #include "nsITransportSecurityInfo.h"
 #include "nsINode.h"
 #include "nsINSSErrorsService.h"
 #include "nsIApplicationCacheChannel.h"
 #include "nsIApplicationCacheContainer.h"
@@ -1496,30 +1496,30 @@ nsDocShell::LoadURI(nsIURI* aURI,
       if (principalIsExplicit) {
         return NS_ERROR_DOM_SECURITY_ERR;
       }
       // Don't inherit from the current page.  Just do the safe thing
       // and pretend that we were loaded by a nullprincipal.
       //
       // We didn't inherit OriginAttributes here as ExpandedPrincipal doesn't
       // have origin attributes.
-      principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this);
+      principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this);
       inheritPrincipal = false;
     }
   }
   if (!principalToInherit && !inheritPrincipal && !principalIsExplicit) {
     // See if there's system or chrome JS code running
     inheritPrincipal = nsContentUtils::LegacyIsCallerChromeOrNativeCode();
   }
 
   if (aLoadFlags & LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL) {
     inheritPrincipal = false;
     // If aFirstParty is true and the pref 'privacy.firstparty.isolate' is
     // enabled, we will set firstPartyDomain on the origin attributes.
-    principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(this, aFirstParty);
+    principalToInherit = NullPrincipal::CreateWithInheritedAttributes(this, aFirstParty);
   }
 
   // If the triggeringPrincipal is not passed explicitly, we first try to create
   // a principal from the referrer, since the referrer URI reflects the web origin
   // that triggered the load. If there is no referrer URI, we fall back to using
   // the SystemPrincipal. It's safe to assume that no provided triggeringPrincipal
   // and no referrer simulate a load that was triggered by the system.
   // It's important to note that this block of code needs to appear *after* the block
@@ -8122,19 +8122,19 @@ nsDocShell::CreateAboutBlankContentViewe
 
   nsCOMPtr<nsIDocumentLoaderFactory> docFactory =
     nsContentUtils::FindInternalContentViewer(NS_LITERAL_CSTRING("text/html"));
 
   if (docFactory) {
     nsCOMPtr<nsIPrincipal> principal;
     if (mSandboxFlags & SANDBOXED_ORIGIN) {
       if (aPrincipal) {
-        principal = nsNullPrincipal::CreateWithInheritedAttributes(aPrincipal);
+        principal = NullPrincipal::CreateWithInheritedAttributes(aPrincipal);
       } else {
-        principal = nsNullPrincipal::CreateWithInheritedAttributes(this);
+        principal = NullPrincipal::CreateWithInheritedAttributes(this);
       }
     } else {
       principal = aPrincipal;
     }
     // generate (about:blank) document to load
     docFactory->CreateBlankDocument(mLoadGroup, principal,
                                     getter_AddRefs(blankDoc));
     if (blankDoc) {
@@ -12404,23 +12404,23 @@ nsDocShell::AddToSessionHistory(nsIURI* 
       if (!triggeringPrincipal) {
         triggeringPrincipal = loadInfo->TriggeringPrincipal();
       }
 
       // For now keep storing just the principal in the SHEntry.
       if (!principalToInherit) {
         if (loadInfo->GetLoadingSandboxed()) {
           if (loadInfo->LoadingPrincipal()) {
-            principalToInherit = nsNullPrincipal::CreateWithInheritedAttributes(
+            principalToInherit = NullPrincipal::CreateWithInheritedAttributes(
             loadInfo->LoadingPrincipal());
           } else {
             // get the OriginAttributes
             OriginAttributes attrs;
             loadInfo->GetOriginAttributes(&attrs);
-            principalToInherit = nsNullPrincipal::Create(attrs);
+            principalToInherit = NullPrincipal::Create(attrs);
           }
         } else {
           principalToInherit = loadInfo->PrincipalToInherit();
         }
       }
     }
   }
 
@@ -12601,17 +12601,17 @@ nsDocShell::LoadHistoryEntry(nsISHEntry*
       // user prevented it). Interrupt the history load.
       return NS_OK;
     }
 
     if (!triggeringPrincipal) {
       // Ensure that we have a triggeringPrincipal.  Otherwise javascript:
       // URIs will pick it up from the about:blank page we just loaded,
       // and we don't really want even that in this case.
-      triggeringPrincipal = nsNullPrincipal::CreateWithInheritedAttributes(this);
+      triggeringPrincipal = NullPrincipal::CreateWithInheritedAttributes(this);
     }
   }
 
   /* If there is a valid postdata *and* the user pressed
    * reload or shift-reload, take user's permission before we
    * repost the data to the server.
    */
   if ((aLoadType & LOAD_CMD_RELOAD) && postData) {
@@ -14373,17 +14373,17 @@ nsDocShell::GetPrintPreview(nsIWebBrowse
 #if NS_PRINT_PREVIEW
   nsCOMPtr<nsIDocumentViewerPrint> print = do_QueryInterface(mContentViewer);
   if (!print || !print->IsInitializedForPrintPreview()) {
     // XXX: Creating a brand new content viewer to host preview every
     // time we enter here seems overwork. We could skip ahead to where
     // we QI the mContentViewer if the current URI is either about:blank
     // or about:printpreview.
     Stop(nsIWebNavigation::STOP_ALL);
-    nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::CreateWithInheritedAttributes(this);
+    nsCOMPtr<nsIPrincipal> principal = NullPrincipal::CreateWithInheritedAttributes(this);
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("about:printpreview"));
     nsresult rv = CreateAboutBlankContentViewer(principal, uri);
     NS_ENSURE_SUCCESS(rv, rv);
     // Here we manually set current URI since we have just created a
     // brand new content viewer (about:blank) to host preview.
     SetCurrentURI(uri, nullptr, true, 0);
     print = do_QueryInterface(mContentViewer);
--- a/dom/asmjscache/AsmJSCache.cpp
+++ b/dom/asmjscache/AsmJSCache.cpp
@@ -1618,28 +1618,34 @@ public:
   {
     return ASMJS;
   }
 
   nsresult
   InitOrigin(PersistenceType aPersistenceType,
              const nsACString& aGroup,
              const nsACString& aOrigin,
+             const AtomicBool& aCanceled,
              UsageInfo* aUsageInfo) override
   {
     if (!aUsageInfo) {
       return NS_OK;
     }
-    return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aUsageInfo);
+    return GetUsageForOrigin(aPersistenceType,
+                             aGroup,
+                             aOrigin,
+                             aCanceled,
+                             aUsageInfo);
   }
 
   nsresult
   GetUsageForOrigin(PersistenceType aPersistenceType,
                     const nsACString& aGroup,
                     const nsACString& aOrigin,
+                    const AtomicBool& aCanceled,
                     UsageInfo* aUsageInfo) override
   {
     QuotaManager* qm = QuotaManager::Get();
     MOZ_ASSERT(qm, "We were being called by the QuotaManager");
 
     nsCOMPtr<nsIFile> directory;
     nsresult rv = qm->GetDirectoryForOrigin(aPersistenceType, aOrigin,
                                             getter_AddRefs(directory));
@@ -1653,17 +1659,17 @@ public:
     MOZ_ASSERT(NS_SUCCEEDED(directory->Exists(&exists)) && exists);
 
     nsCOMPtr<nsISimpleEnumerator> entries;
     rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
     NS_ENSURE_SUCCESS(rv, rv);
 
     bool hasMore;
     while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-           hasMore && !aUsageInfo->Canceled()) {
+           hasMore && !aCanceled) {
       nsCOMPtr<nsISupports> entry;
       rv = entries->GetNext(getter_AddRefs(entry));
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
       NS_ENSURE_TRUE(file, NS_NOINTERFACE);
 
       int64_t fileSize;
--- a/dom/base/DOMParser.cpp
+++ b/dom/base/DOMParser.cpp
@@ -13,17 +13,17 @@
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsCRT.h"
 #include "nsStreamUtils.h"
 #include "nsContentUtils.h"
 #include "nsDOMJSUtils.h"
 #include "nsError.h"
 #include "nsPIDOMWindow.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "mozilla/LoadInfo.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/ScriptSettings.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 DOMParser::DOMParser()
@@ -340,17 +340,17 @@ DOMParser::Init(nsIPrincipal* principal,
     OriginAttributes attrs;
     mPrincipal = BasePrincipal::CreateCodebasePrincipal(mDocumentURI, attrs);
     NS_ENSURE_TRUE(mPrincipal, NS_ERROR_FAILURE);
   } else {
     if (nsContentUtils::IsSystemPrincipal(mPrincipal)) {
       // Don't give DOMParsers the system principal.  Use a null
       // principal instead.
       mOriginalPrincipalWasSystem = true;
-      mPrincipal = nsNullPrincipal::Create();
+      mPrincipal = NullPrincipal::Create();
 
       if (!mDocumentURI) {
         rv = mPrincipal->GetURI(getter_AddRefs(mDocumentURI));
         NS_ENSURE_SUCCESS(rv, rv);
       }
     }
   }
 
@@ -451,17 +451,17 @@ DOMParser::SetUpDocument(DocumentFlavor 
   // off of nsIScriptGlobalObject, but that's a yak to shave another day.
   nsCOMPtr<nsIScriptGlobalObject> scriptHandlingObject =
     do_QueryReferent(mScriptHandlingObject);
   nsresult rv;
   if (!mPrincipal) {
     NS_ENSURE_TRUE(!mAttemptedInit, NS_ERROR_NOT_INITIALIZED);
     AttemptedInitMarker marker(&mAttemptedInit);
 
-    nsCOMPtr<nsIPrincipal> prin = nsNullPrincipal::Create();
+    nsCOMPtr<nsIPrincipal> prin = NullPrincipal::Create();
     rv = Init(prin, nullptr, nullptr, scriptHandlingObject);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   NS_ASSERTION(mPrincipal, "Must have principal by now");
   NS_ASSERTION(mDocumentURI, "Must have document URI by now");
 
   return NS_NewDOMDocument(aResult, EmptyString(), EmptyString(), nullptr,
--- a/dom/base/Location.cpp
+++ b/dom/base/Location.cpp
@@ -26,17 +26,17 @@
 #include "nsDOMClassInfoID.h"
 #include "nsReadableUtils.h"
 #include "nsITextToSubURI.h"
 #include "nsJSUtils.h"
 #include "nsContentUtils.h"
 #include "nsGlobalWindow.h"
 #include "mozilla/Likely.h"
 #include "nsCycleCollectionParticipant.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "ScriptSettings.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/LocationBinding.h"
 
 namespace mozilla {
 namespace dom {
 
 static nsresult
@@ -159,17 +159,17 @@ Location::CheckURL(nsIURI* aURI, nsIDocS
       bool urisEqual = false;
       if (docOriginalURI && docCurrentURI && principalURI) {
         principalURI->Equals(docOriginalURI, &urisEqual);
       }
       if (urisEqual) {
         sourceURI = docCurrentURI;
       }
       else {
-        // Use principalURI as long as it is not an nsNullPrincipalURI.  We
+        // Use principalURI as long as it is not an NullPrincipalURI.  We
         // could add a method such as GetReferrerURI to principals to make this
         // cleaner, but given that we need to start using Source Browsing
         // Context for referrer (see Bug 960639) this may be wasted effort at
         // this stage.
         if (principalURI) {
           bool isNullPrincipalScheme;
           rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
                                      &isNullPrincipalScheme);
--- a/dom/base/ScriptSettings.cpp
+++ b/dom/base/ScriptSettings.cpp
@@ -159,17 +159,17 @@ ScriptSettingsStackEntry::~ScriptSetting
 {
   // We must have an actual JS global for the entire time this is on the stack.
   MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
 }
 
 // If the entry or incumbent global ends up being something that the subject
 // principal doesn't subsume, we don't want to use it. This never happens on
 // the web, but can happen with asymmetric privilege relationships (i.e.
-// nsExpandedPrincipal and System Principal).
+// ExpandedPrincipal and System Principal).
 //
 // The most correct thing to use instead would be the topmost global on the
 // callstack whose principal is subsumed by the subject principal. But that's
 // hard to compute, so we just substitute the global of the current
 // compartment. In practice, this is fine.
 //
 // Note that in particular things like:
 //
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -177,17 +177,17 @@
 #include "nsIWindowMediator.h"
 #include "nsIWordBreaker.h"
 #include "nsIXPConnect.h"
 #include "nsJSUtils.h"
 #include "nsLWBrkCIID.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsNodeInfoManager.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsParserCIID.h"
 #include "nsParserConstants.h"
 #include "nsPIDOMWindow.h"
 #include "nsPresContext.h"
 #include "nsPrintfCString.h"
 #include "nsReferencedElement.h"
 #include "nsSandboxFlags.h"
 #include "nsScriptSecurityManager.h"
@@ -509,17 +509,17 @@ nsContentUtils::Init()
   sSecurityManager = nsScriptSecurityManager::GetScriptSecurityManager();
   if(!sSecurityManager)
     return NS_ERROR_FAILURE;
   NS_ADDREF(sSecurityManager);
 
   sSecurityManager->GetSystemPrincipal(&sSystemPrincipal);
   MOZ_ASSERT(sSystemPrincipal);
 
-  RefPtr<nsNullPrincipal> nullPrincipal = nsNullPrincipal::Create();
+  RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create();
   if (!nullPrincipal) {
     return NS_ERROR_FAILURE;
   }
 
   nullPrincipal.forget(&sNullSubjectPrincipal);
 
   nsresult rv = CallGetService(NS_IOSERVICE_CONTRACTID, &sIOService);
   if (NS_FAILED(rv)) {
@@ -4785,17 +4785,17 @@ nsContentUtils::ParseFragmentXML(const n
 nsresult
 nsContentUtils::ConvertToPlainText(const nsAString& aSourceBuffer,
                                    nsAString& aResultBuffer,
                                    uint32_t aFlags,
                                    uint32_t aWrapCol)
 {
   nsCOMPtr<nsIURI> uri;
   NS_NewURI(getter_AddRefs(uri), "about:blank");
-  nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
+  nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
   nsCOMPtr<nsIDOMDocument> domDocument;
   nsresult rv = NS_NewDOMDocument(getter_AddRefs(domDocument),
                                   EmptyString(),
                                   EmptyString(),
                                   nullptr,
                                   uri,
                                   uri,
                                   principal,
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1573,22 +1573,22 @@ public:
   static void NotifyInstalledMenuKeyboardListener(bool aInstalling);
 
   /**
    * Returns true if aPrincipal is the system principal.
    */
   static bool IsSystemPrincipal(nsIPrincipal* aPrincipal);
 
   /**
-   * Returns true if aPrincipal is an nsExpandedPrincipal.
+   * Returns true if aPrincipal is an ExpandedPrincipal.
    */
   static bool IsExpandedPrincipal(nsIPrincipal* aPrincipal);
 
   /**
-   * Returns true if aPrincipal is the system or an nsExpandedPrincipal.
+   * Returns true if aPrincipal is the system or an ExpandedPrincipal.
    */
   static bool IsSystemOrExpandedPrincipal(nsIPrincipal* aPrincipal)
   {
     return IsSystemPrincipal(aPrincipal) || IsExpandedPrincipal(aPrincipal);
   }
 
   /**
    * Gets the system principal from the security manager.
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -101,17 +101,17 @@
 #include "nsNetUtil.h"     // for NS_NewURI
 #include "nsIInputStreamChannel.h"
 #include "nsIAuthPrompt.h"
 #include "nsIAuthPrompt2.h"
 
 #include "nsIScriptSecurityManager.h"
 #include "nsIPermissionManager.h"
 #include "nsIPrincipal.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 
 #include "nsIDOMWindow.h"
 #include "nsPIDOMWindow.h"
 #include "nsIDOMElement.h"
 #include "nsFocusManager.h"
 
 // for radio group stuff
 #include "nsIDOMHTMLInputElement.h"
@@ -2718,17 +2718,17 @@ nsDocument::InitCSP(nsIChannel* aChannel
   rv = csp->GetCSPSandboxFlags(&cspSandboxFlags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mSandboxFlags |= cspSandboxFlags;
 
   if (cspSandboxFlags & SANDBOXED_ORIGIN) {
     // If the new CSP sandbox flags do not have the allow-same-origin flag
     // reset the document principal to a null principal
-    principal = nsNullPrincipal::Create();
+    principal = NullPrincipal::Create();
     SetPrincipal(principal);
   }
 
   // ----- Enforce frame-ancestor policy on any applied policies
   nsCOMPtr<nsIDocShell> docShell(mDocumentContainer);
   if (docShell) {
     bool safeAncestry = false;
 
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -45,17 +45,17 @@
 #include "nsError.h"
 #include "nsISHistory.h"
 #include "nsISHistoryInternal.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIXULWindow.h"
 #include "nsIEditor.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsISHistory.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsGlobalWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsView.h"
 #include "GroupedSHistory.h"
 #include "PartialSHistory.h"
 
@@ -93,17 +93,17 @@
 #include "mozilla/dom/CustomEvent.h"
 
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/WebBrowserPersistLocalDocument.h"
 #include "mozilla/dom/GroupedHistoryEvent.h"
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/PromiseNativeHandler.h"
 
-#include "nsPrincipal.h"
+#include "ContentPrincipal.h"
 
 #ifdef XP_WIN
 #include "mozilla/plugins/PPluginWidgetParent.h"
 #include "../plugins/ipc/PluginWidgetParent.h"
 #endif
 
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
@@ -826,17 +826,17 @@ nsFrameLoader::ReallyStartLoadingInterna
     nsCOMPtr<nsIURI> baseURI = mOwnerContent->GetBaseURI();
     loadInfo->SetBaseURI(baseURI);
   }
   else {
     rv = mOwnerContent->NodePrincipal()->GetURI(getter_AddRefs(referrer));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
-  // Use referrer as long as it is not an nsNullPrincipalURI.
+  // Use referrer as long as it is not an NullPrincipalURI.
   // We could add a method such as GetReferrerURI to principals to make this
   // cleaner, but given that we need to start using Source Browsing Context for
   // referrer (see Bug 960639) this may be wasted effort at this stage.
   if (referrer) {
     bool isNullPrincipalScheme;
     rv = referrer->SchemeIs(NS_NULLPRINCIPAL_SCHEME, &isNullPrincipalScheme);
     if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
       loadInfo->SetReferrer(referrer);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -13072,19 +13072,24 @@ nsGlobalWindow::RunTimeoutHandler(Timeou
       handler->GetLocation(&filename, &lineNo, &dummyColumn);
 
       // New script entry point required, due to the "Create a script" sub-step of
       // http://www.whatwg.org/specs/web-apps/current-work/#timer-initialisation-steps
       nsAutoMicroTask mt;
       AutoEntryScript aes(this, reason, true);
       JS::CompileOptions options(aes.cx());
       options.setFileAndLine(filename, lineNo).setVersion(JSVERSION_DEFAULT);
+      options.setNoScriptRval(true);
       JS::Rooted<JSObject*> global(aes.cx(), FastGetGlobalJSObject());
-      nsresult rv =
-        nsJSUtils::EvaluateString(aes.cx(), script, global, options);
+      nsresult rv = NS_OK;
+      {
+        nsJSUtils::ExecutionContext exec(aes.cx(), global);
+        rv = exec.CompileAndExec(options, script);
+      }
+
       if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE) {
         abortIntervalHandler = true;
       }
     } else {
       // Hold strong ref to ourselves while we call the callback.
       nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow*>(this));
       ErrorResult rv;
       JS::Rooted<JS::Value> ignoredVal(RootingCx());
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -118,166 +118,172 @@ nsJSUtils::CompileFunction(AutoJSAPI& js
   {
     return NS_ERROR_FAILURE;
   }
 
   *aFunctionObject = JS_GetFunctionObject(fun);
   return NS_OK;
 }
 
-nsresult
-nsJSUtils::EvaluateString(JSContext* aCx,
-                          const nsAString& aScript,
-                          JS::Handle<JSObject*> aEvaluationGlobal,
-                          JS::CompileOptions& aCompileOptions,
-                          const EvaluateOptions& aEvaluateOptions,
-                          JS::MutableHandle<JS::Value> aRetValue)
+static nsresult
+EvaluationExceptionToNSResult(JSContext* aCx)
+{
+  if (JS_IsExceptionPending(aCx)) {
+    return NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW;
+  }
+  return NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE;
+}
+
+nsJSUtils::ExecutionContext::ExecutionContext(JSContext* aCx,
+                                              JS::Handle<JSObject*> aGlobal)
+  : mSamplerRAII("nsJSUtils::ExecutionContext", /* PROFILER_LABEL */
+                 js::ProfileEntry::Category::JS, __LINE__)
+  , mCx(aCx)
+  , mCompartment(aCx, aGlobal)
+  , mRetValue(aCx)
+  , mScopeChain(aCx)
+  , mRv(NS_OK)
+  , mSkip(false)
+  , mCoerceToString(false)
+#ifdef DEBUG
+  , mWantsReturnValue(false)
+  , mExpectScopeChain(false)
+#endif
 {
-  const nsPromiseFlatString& flatScript = PromiseFlatString(aScript);
-  JS::SourceBufferHolder srcBuf(flatScript.get(), aScript.Length(),
-                                JS::SourceBufferHolder::NoOwnership);
-  return EvaluateString(aCx, srcBuf, aEvaluationGlobal, aCompileOptions,
-                        aEvaluateOptions, aRetValue, nullptr);
+  MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(nsContentUtils::IsInMicroTask());
+  MOZ_ASSERT(mRetValue.isUndefined());
+
+  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aGlobal) == aGlobal);
+  if (MOZ_UNLIKELY(!xpc::Scriptability::Get(aGlobal).Allowed())) {
+    mSkip = true;
+    mRv = NS_OK;
+  }
+}
+
+void
+nsJSUtils::ExecutionContext::SetScopeChain(
+  const JS::AutoObjectVector& aScopeChain)
+{
+  if (mSkip) {
+    return;
+  }
+
+#ifdef DEBUG
+  mExpectScopeChain = true;
+#endif
+  // Now make sure to wrap the scope chain into the right compartment.
+  if (!mScopeChain.reserve(aScopeChain.length())) {
+    mSkip = true;
+    mRv = NS_ERROR_OUT_OF_MEMORY;
+    return;
+  }
+
+  for (size_t i = 0; i < aScopeChain.length(); ++i) {
+    JS::ExposeObjectToActiveJS(aScopeChain[i]);
+    mScopeChain.infallibleAppend(aScopeChain[i]);
+    if (!JS_WrapObject(mCx, mScopeChain[i])) {
+      mSkip = true;
+      mRv = NS_ERROR_OUT_OF_MEMORY;
+      return;
+    }
+  }
 }
 
 nsresult
-nsJSUtils::EvaluateString(JSContext* aCx,
-                          JS::SourceBufferHolder& aSrcBuf,
-                          JS::Handle<JSObject*> aEvaluationGlobal,
-                          JS::CompileOptions& aCompileOptions,
-                          const EvaluateOptions& aEvaluateOptions,
-                          JS::MutableHandle<JS::Value> aRetValue,
-                          void **aOffThreadToken)
+nsJSUtils::ExecutionContext::SyncAndExec(void **aOffThreadToken,
+                                         JS::MutableHandle<JSScript*> aScript)
 {
-  PROFILER_LABEL("nsJSUtils", "EvaluateString",
-    js::ProfileEntry::Category::JS);
+  if (mSkip) {
+    return mRv;
+  }
+
+  MOZ_ASSERT(!mWantsReturnValue);
+  MOZ_ASSERT(!mExpectScopeChain);
+  aScript.set(JS::FinishOffThreadScript(mCx, *aOffThreadToken));
+  *aOffThreadToken = nullptr; // Mark the token as having been finished.
+  if (!aScript || !JS_ExecuteScript(mCx, mScopeChain, aScript)) {
+    mSkip = true;
+    mRv = EvaluationExceptionToNSResult(mCx);
+    return mRv;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+nsJSUtils::ExecutionContext::CompileAndExec(JS::CompileOptions& aCompileOptions,
+                                            JS::SourceBufferHolder& aSrcBuf)
+{
+  if (mSkip) {
+    return mRv;
+  }
 
   MOZ_ASSERT_IF(aCompileOptions.versionSet,
                 aCompileOptions.version != JSVERSION_UNKNOWN);
-  MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, !aCompileOptions.noScriptRval);
-  MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext());
   MOZ_ASSERT(aSrcBuf.get());
-  MOZ_ASSERT(js::GetGlobalForObjectCrossCompartment(aEvaluationGlobal) ==
-             aEvaluationGlobal);
-  MOZ_ASSERT_IF(aOffThreadToken, aCompileOptions.noScriptRval);
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(nsContentUtils::IsInMicroTask());
-
-  // Unfortunately, the JS engine actually compiles scripts with a return value
-  // in a different, less efficient way.  Furthermore, it can't JIT them in many
-  // cases.  So we need to be explicitly told whether the caller cares about the
-  // return value.  Callers can do this by calling the other overload of
-  // EvaluateString() which calls this function with
-  // aCompileOptions.noScriptRval set to true.
-  aRetValue.setUndefined();
-
-  nsresult rv = NS_OK;
-
-  NS_ENSURE_TRUE(xpc::Scriptability::Get(aEvaluationGlobal).Allowed(), NS_OK);
-
-  bool ok = true;
-  // Scope the JSAutoCompartment so that we can later wrap the return value
-  // into the caller's cx.
-  {
-    JSAutoCompartment ac(aCx, aEvaluationGlobal);
-
-    // Now make sure to wrap the scope chain into the right compartment.
-    JS::AutoObjectVector scopeChain(aCx);
-    if (!scopeChain.reserve(aEvaluateOptions.scopeChain.length())) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-
-    for (size_t i = 0; i < aEvaluateOptions.scopeChain.length(); ++i) {
-      JS::ExposeObjectToActiveJS(aEvaluateOptions.scopeChain[i]);
-      scopeChain.infallibleAppend(aEvaluateOptions.scopeChain[i]);
-      if (!JS_WrapObject(aCx, scopeChain[i])) {
-        ok = false;
-        break;
-      }
-    }
-
-    if (ok && aOffThreadToken) {
-      JS::Rooted<JSScript*>
-        script(aCx, JS::FinishOffThreadScript(aCx, *aOffThreadToken));
-      *aOffThreadToken = nullptr; // Mark the token as having been finished.
-      if (script) {
-        ok = JS_ExecuteScript(aCx, scopeChain, script);
-      } else {
-        ok = false;
-      }
-    } else if (ok) {
-      ok = JS::Evaluate(aCx, scopeChain, aCompileOptions, aSrcBuf, aRetValue);
-    }
-
-    if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) {
-      JS::Rooted<JS::Value> value(aCx, aRetValue);
-      JSString* str = JS::ToString(aCx, value);
-      ok = !!str;
-      aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue());
-    }
+  MOZ_ASSERT(mRetValue.isUndefined());
+#ifdef DEBUG
+  mWantsReturnValue = !aCompileOptions.noScriptRval;
+#endif
+  MOZ_ASSERT(!mCoerceToString || mWantsReturnValue);
+  if (!JS::Evaluate(mCx, mScopeChain, aCompileOptions, aSrcBuf, &mRetValue)) {
+    mSkip = true;
+    mRv = EvaluationExceptionToNSResult(mCx);
+    return mRv;
   }
 
-  if (!ok) {
-    if (JS_IsExceptionPending(aCx)) {
-      rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW;
-    } else {
-      rv = NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW_UNCATCHABLE;
-    }
+  return NS_OK;
+}
 
-    if (!aCompileOptions.noScriptRval) {
-      aRetValue.setUndefined();
-    }
+nsresult
+nsJSUtils::ExecutionContext::CompileAndExec(JS::CompileOptions& aCompileOptions,
+                                            const nsAString& aScript)
+{
+  if (mSkip) {
+    return mRv;
   }
 
-  // Wrap the return value into whatever compartment aCx was in.
-  if (ok && !aCompileOptions.noScriptRval) {
-    if (!JS_WrapValue(aCx, aRetValue)) {
-      return NS_ERROR_OUT_OF_MEMORY;
-    }
-  }
-  return rv;
+  const nsPromiseFlatString& flatScript = PromiseFlatString(aScript);
+  JS::SourceBufferHolder srcBuf(flatScript.get(), aScript.Length(),
+                                JS::SourceBufferHolder::NoOwnership);
+  return CompileAndExec(aCompileOptions, srcBuf);
 }
 
 nsresult
-nsJSUtils::EvaluateString(JSContext* aCx,
-                          JS::SourceBufferHolder& aSrcBuf,
-                          JS::Handle<JSObject*> aEvaluationGlobal,
-                          JS::CompileOptions& aCompileOptions,
-                          const EvaluateOptions& aEvaluateOptions,
-                          JS::MutableHandle<JS::Value> aRetValue)
-{
-  return EvaluateString(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions,
-                        aEvaluateOptions, aRetValue, nullptr);
-}
-
-nsresult
-nsJSUtils::EvaluateString(JSContext* aCx,
-                          const nsAString& aScript,
-                          JS::Handle<JSObject*> aEvaluationGlobal,
-                          JS::CompileOptions& aCompileOptions)
+nsJSUtils::ExecutionContext::ExtractReturnValue(JS::MutableHandle<JS::Value> aRetValue)
 {
-  EvaluateOptions options(aCx);
-  aCompileOptions.setNoScriptRval(true);
-  JS::RootedValue unused(aCx);
-  return EvaluateString(aCx, aScript, aEvaluationGlobal, aCompileOptions,
-                        options, &unused);
-}
+  MOZ_ASSERT(aRetValue.isUndefined());
+  if (mSkip) {
+    // Repeat earlier result, as NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW are not
+    // failures cases.
+#ifdef DEBUG
+    mWantsReturnValue = false;
+#endif
+    return mRv;
+  }
 
-nsresult
-nsJSUtils::EvaluateString(JSContext* aCx,
-                          JS::SourceBufferHolder& aSrcBuf,
-                          JS::Handle<JSObject*> aEvaluationGlobal,
-                          JS::CompileOptions& aCompileOptions,
-                          void **aOffThreadToken)
-{
-  EvaluateOptions options(aCx);
-  aCompileOptions.setNoScriptRval(true);
-  JS::RootedValue unused(aCx);
-  return EvaluateString(aCx, aSrcBuf, aEvaluationGlobal, aCompileOptions,
-                        options, &unused, aOffThreadToken);
+  MOZ_ASSERT(mWantsReturnValue);
+#ifdef DEBUG
+  mWantsReturnValue = false;
+#endif
+  if (mCoerceToString && !mRetValue.isUndefined()) {
+    JSString* str = JS::ToString(mCx, mRetValue);
+    if (!str) {
+      // ToString can be a function call, so an exception can be raised while
+      // executing the function.
+      mSkip = true;
+      return EvaluationExceptionToNSResult(mCx);
+    }
+    mRetValue.set(JS::StringValue(str));
+  }
+
+  aRetValue.set(mRetValue);
+  return NS_OK;
 }
 
 nsresult
 nsJSUtils::CompileModule(JSContext* aCx,
                        JS::SourceBufferHolder& aSrcBuf,
                        JS::Handle<JSObject*> aEvaluationGlobal,
                        JS::CompileOptions &aCompileOptions,
                        JS::MutableHandle<JSObject*> aModule)
--- a/dom/base/nsJSUtils.h
+++ b/dom/base/nsJSUtils.h
@@ -11,16 +11,17 @@
  * This is not a generated file. It contains common utility functions 
  * invoked from the JavaScript code generated from IDL interfaces.
  * The goal of the utility functions is to cut down on the size of
  * the generated code itself.
  */
 
 #include "mozilla/Assertions.h"
 
+#include "GeckoProfiler.h"
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "js/Conversions.h"
 #include "nsString.h"
 
 class nsIScriptContext;
 class nsIScriptGlobalObject;
 
@@ -59,61 +60,104 @@ public:
                                   JS::AutoObjectVector& aScopeChain,
                                   JS::CompileOptions& aOptions,
                                   const nsACString& aName,
                                   uint32_t aArgCount,
                                   const char** aArgArray,
                                   const nsAString& aBody,
                                   JSObject** aFunctionObject);
 
-  struct MOZ_STACK_CLASS EvaluateOptions {
-    bool coerceToString;
-    JS::AutoObjectVector scopeChain;
+
+  // ExecutionContext is used to switch compartment.
+  class MOZ_STACK_CLASS ExecutionContext {
+    // Register stack annotations for the Gecko profiler.
+    mozilla::SamplerStackFrameRAII mSamplerRAII;
+
+    JSContext* mCx;
+
+    // Handles switching to our global's compartment.
+    JSAutoCompartment mCompartment;
+
+    // Set to a valid handle if a return value is expected.
+    JS::Rooted<JS::Value> mRetValue;
+
+    // Scope chain in which the execution takes place.
+    JS::AutoObjectVector mScopeChain;
+
+    // returned value forwarded when we have to interupt the execution eagerly
+    // with mSkip.
+    nsresult mRv;
+
+    // Used to skip upcoming phases in case of a failure.  In such case the
+    // result is carried by mRv.
+    bool mSkip;
 
-    explicit EvaluateOptions(JSContext* cx)
-      : coerceToString(false)
-      , scopeChain(cx)
-    {}
+    // Should the result be serialized before being returned.
+    bool mCoerceToString;
+
+#ifdef DEBUG
+    // Should we set the return value.
+    bool mWantsReturnValue;
+
+    bool mExpectScopeChain;
+#endif
+
+   public:
 
-    EvaluateOptions& setCoerceToString(bool aCoerce) {
-      coerceToString = aCoerce;
+    // Enter compartment in which the code would be executed.  The JSContext
+    // must come from an AutoEntryScript that has had
+    // TakeOwnershipOfErrorReporting() called on it.
+    ExecutionContext(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
+
+    ExecutionContext(const ExecutionContext&) = delete;
+    ExecutionContext(ExecutionContext&&) = delete;
+
+    ~ExecutionContext() {
+      // This flag is resetted, when the returned value is extracted.
+      MOZ_ASSERT(!mWantsReturnValue);
+    }
+
+    // The returned value would be converted to a string if the
+    // |aCoerceToString| is flag set.
+    ExecutionContext& SetCoerceToString(bool aCoerceToString) {
+      mCoerceToString = aCoerceToString;
       return *this;
     }
-  };
+
+    // Set the scope chain in which the code should be executed.
+    void SetScopeChain(const JS::AutoObjectVector& aScopeChain);
 
-  // aEvaluationGlobal is the global to evaluate in.  The return value
-  // will then be wrapped back into the compartment aCx is in when
-  // this function is called.  For all the EvaluateString overloads,
-  // the JSContext must come from an AutoJSAPI that has had
-  // TakeOwnershipOfErrorReporting() called on it.
-  static nsresult EvaluateString(JSContext* aCx,
-                                 const nsAString& aScript,
-                                 JS::Handle<JSObject*> aEvaluationGlobal,
-                                 JS::CompileOptions &aCompileOptions,
-                                 const EvaluateOptions& aEvaluateOptions,
-                                 JS::MutableHandle<JS::Value> aRetValue);
+    // Copy the returned value in the mutable handle argument, in case of a
+    // evaluation failure either during the execution or the conversion of the
+    // result to a string, the nsresult would be set to the corresponding result
+    // code, and the mutable handle argument would remain unchanged.
+    //
+    // The value returned in the mutable handle argument is part of the
+    // compartment given as argument to the ExecutionContext constructor. If the
+    // caller is in a different compartment, then the out-param value should be
+    // wrapped by calling |JS_WrapValue|.
+    MOZ_MUST_USE nsresult
+    ExtractReturnValue(JS::MutableHandle<JS::Value> aRetValue);
 
-  static nsresult EvaluateString(JSContext* aCx,
-                                 JS::SourceBufferHolder& aSrcBuf,
-                                 JS::Handle<JSObject*> aEvaluationGlobal,
-                                 JS::CompileOptions &aCompileOptions,
-                                 const EvaluateOptions& aEvaluateOptions,
-                                 JS::MutableHandle<JS::Value> aRetValue);
-
+    // After getting a notification that an off-thread compilation terminated,
+    // this function will synchronize the result by moving it to the main thread
+    // before starting the execution of the script.
+    //
+    // The compiled script would be returned in the |aScript| out-param.
+    MOZ_MUST_USE nsresult SyncAndExec(void **aOffThreadToken,
+                                      JS::MutableHandle<JSScript*> aScript);
 
-  static nsresult EvaluateString(JSContext* aCx,
-                                 const nsAString& aScript,
-                                 JS::Handle<JSObject*> aEvaluationGlobal,
-                                 JS::CompileOptions &aCompileOptions);
+    // Compile a script contained in a SourceBuffer, and execute it.
+    nsresult CompileAndExec(JS::CompileOptions& aCompileOptions,
+                            JS::SourceBufferHolder& aSrcBuf);
 
-  static nsresult EvaluateString(JSContext* aCx,
-                                 JS::SourceBufferHolder& aSrcBuf,
-                                 JS::Handle<JSObject*> aEvaluationGlobal,
-                                 JS::CompileOptions &aCompileOptions,
-                                 void **aOffThreadToken);
+    // Compile a script contained in a string, and execute it.
+    nsresult CompileAndExec(JS::CompileOptions& aCompileOptions,
+                            const nsAString& aScript);
+  };
 
   static nsresult CompileModule(JSContext* aCx,
                                 JS::SourceBufferHolder& aSrcBuf,
                                 JS::Handle<JSObject*> aEvaluationGlobal,
                                 JS::CompileOptions &aCompileOptions,
                                 JS::MutableHandle<JSObject*> aModule);
 
   static nsresult ModuleDeclarationInstantiation(JSContext* aCx,
@@ -124,26 +168,16 @@ public:
 
   // Returns false if an exception got thrown on aCx.  Passing a null
   // aElement is allowed; that wil produce an empty aScopeChain.
   static bool GetScopeChainForElement(JSContext* aCx,
                                       mozilla::dom::Element* aElement,
                                       JS::AutoObjectVector& aScopeChain);
 
   static void ResetTimeZone();
-
-private:
-  // Implementation for our EvaluateString bits
-  static nsresult EvaluateString(JSContext* aCx,
-                                 JS::SourceBufferHolder& aSrcBuf,
-                                 JS::Handle<JSObject*> aEvaluationGlobal,
-                                 JS::CompileOptions& aCompileOptions,
-                                 const EvaluateOptions& aEvaluateOptions,
-                                 JS::MutableHandle<JS::Value> aRetValue,
-                                 void **aOffThreadToken);
 };
 
 template<typename T>
 inline bool
 AssignJSString(JSContext *cx, T &dest, JSString *s)
 {
   size_t len = js::GetStringLength(s);
   static_assert(js::MaxStringLength < (1 << 28),
--- a/dom/base/nsNodeInfoManager.cpp
+++ b/dom/base/nsNodeInfoManager.cpp
@@ -25,17 +25,17 @@
 #include "nsGkAtoms.h"
 #include "nsComponentManagerUtils.h"
 #include "nsLayoutStatics.h"
 #include "nsBindingManager.h"
 #include "nsHashKeys.h"
 #include "nsCCUncollectableMarker.h"
 #include "nsNameSpaceManager.h"
 #include "nsDocument.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 
 using namespace mozilla;
 using mozilla::dom::NodeInfo;
 
 #include "mozilla/Logging.h"
 
 static LazyLogModule gNodeInfoManagerLeakPRLog("NodeInfoManagerLeak");
 
@@ -177,17 +177,17 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_E
 nsresult
 nsNodeInfoManager::Init(nsIDocument *aDocument)
 {
   NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
 
   NS_PRECONDITION(!mPrincipal,
                   "Being inited when we already have a principal?");
 
-  mPrincipal = nsNullPrincipal::Create();
+  mPrincipal = NullPrincipal::Create();
 
   if (aDocument) {
     mBindingManager = new nsBindingManager(aDocument);
   }
 
   mDefaultPrincipal = mPrincipal;
 
   mDocument = aDocument;
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -2147,18 +2147,16 @@ nsScriptLoader::FillCompileOptionsForReq
 
   bool isScriptElement = !aRequest->IsModuleRequest() ||
                          aRequest->AsModuleRequest()->IsTopLevel();
   aOptions->setIntroductionType(isScriptElement ? "scriptElement"
                                                 : "importedModule");
   aOptions->setFileAndLine(aRequest->mURL.get(), aRequest->mLineNo);
   aOptions->setVersion(JSVersion(aRequest->mJSVersion));
   aOptions->setIsRunOnce(true);
-  // We only need the setNoScriptRval bit when compiling off-thread here, since
-  // otherwise nsJSUtils::EvaluateString will set it up for us.
   aOptions->setNoScriptRval(true);
   if (aRequest->mHasSourceMapURL) {
     aOptions->setSourceMapURL(aRequest->mSourceMapURL.get());
   }
   if (aRequest->mOriginPrincipal) {
     nsIPrincipal* scriptPrin = nsContentUtils::ObjectPrincipal(aScopeChain);
     bool subsumes = scriptPrin->Subsumes(aRequest->mOriginPrincipal);
     aOptions->setMutedErrors(!subsumes);
@@ -2253,20 +2251,27 @@ nsScriptLoader::EvaluateScript(nsScriptL
         MOZ_ASSERT(module);
         rv = nsJSUtils::ModuleEvaluation(aes.cx(), module);
       }
     } else {
       JS::CompileOptions options(aes.cx());
       rv = FillCompileOptionsForRequest(aes, aRequest, global, &options);
 
       if (NS_SUCCEEDED(rv)) {
-        nsAutoString inlineData;
-        SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
-        rv = nsJSUtils::EvaluateString(aes.cx(), srcBuf, global, options,
-                                       aRequest->OffThreadTokenPtr());
+        {
+          nsJSUtils::ExecutionContext exec(aes.cx(), global);
+          if (aRequest->mOffThreadToken) {
+            JS::Rooted<JSScript*> script(aes.cx());
+            rv = exec.SyncAndExec(&aRequest->mOffThreadToken, &script);
+          } else {
+            nsAutoString inlineData;
+            SourceBufferHolder srcBuf = GetScriptSource(aRequest, inlineData);
+            rv = exec.CompileAndExec(options, srcBuf);
+          }
+        }
       }
     }
   }
 
   context->SetProcessingScriptTag(oldProcessingScriptTag);
   return rv;
 }
 
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -14,17 +14,17 @@
 #include "nsCSSParser.h"
 #include "nsCSSPropertyID.h"
 #include "nsUnicharInputStream.h"
 #include "nsIDOMCSSRule.h"
 #include "nsAttrName.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsNetUtil.h"
 #include "nsComponentManagerUtils.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsContentUtils.h"
 #include "nsIParserUtils.h"
 #include "nsIDocument.h"
 #include "nsQueryObject.h"
 
 using namespace mozilla;
 
 //
@@ -1517,17 +1517,17 @@ nsTreeSanitizer::InitializeStatics()
     sElementsMathML->PutEntry(*kElementsMathML[i]);
   }
 
   sAttributesMathML = new nsTHashtable<nsISupportsHashKey>(ArrayLength(kAttributesMathML));
   for (uint32_t i = 0; kAttributesMathML[i]; i++) {
     sAttributesMathML->PutEntry(*kAttributesMathML[i]);
   }
 
-  nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
+  nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
   principal.forget(&sNullPrincipal);
 }
 
 void
 nsTreeSanitizer::ReleaseStatics()
 {
   delete sElementsHTML;
   sElementsHTML = nullptr;
--- a/dom/bindings/SimpleGlobalObject.cpp
+++ b/dom/bindings/SimpleGlobalObject.cpp
@@ -5,17 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/SimpleGlobalObject.h"
 
 #include "jsapi.h"
 #include "js/Class.h"
 
 #include "nsJSPrincipals.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsThreadUtils.h"
 #include "nsContentUtils.h"
 
 #include "xpcprivate.h"
 
 #include "mozilla/dom/ScriptSettings.h"
 
 namespace mozilla {
@@ -108,17 +108,17 @@ SimpleGlobalObject::Create(GlobalType gl
            .setInvisibleToDebugger(true)
            // Put our SimpleGlobalObjects in the system zone, so we won't create
            // lots of zones for what are probably very short-lived
            // compartments.  This should help them be GCed quicker and take up
            // less memory before they're GCed.
            .setSystemZone();
 
     if (NS_IsMainThread()) {
-      nsCOMPtr<nsIPrincipal> principal = nsNullPrincipal::Create();
+      nsCOMPtr<nsIPrincipal> principal = NullPrincipal::Create();
       options.creationOptions().setTrace(xpc::TraceXPCGlobal);
       global = xpc::CreateGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
                                        nsJSPrincipals::get(principal),
                                        options);
     } else {
       global = JS_NewGlobalObject(cx, js::Jsvalify(&SimpleGlobalClass),
                                   nullptr,
                                   JS::DontFireOnNewGlobalHook, options);
--- a/dom/cache/QuotaClient.cpp
+++ b/dom/cache/QuotaClient.cpp
@@ -11,46 +11,48 @@
 #include "mozilla/dom/quota/UsageInfo.h"
 #include "mozilla/ipc/BackgroundParent.h"
 #include "nsIFile.h"
 #include "nsISimpleEnumerator.h"
 #include "nsThreadUtils.h"
 
 namespace {
 
+using mozilla::Atomic;
 using mozilla::dom::ContentParentId;
 using mozilla::dom::cache::Manager;
 using mozilla::dom::quota::Client;
 using mozilla::dom::quota::PersistenceType;
 using mozilla::dom::quota::QuotaManager;
 using mozilla::dom::quota::UsageInfo;
 using mozilla::ipc::AssertIsOnBackgroundThread;
 
 static nsresult
-GetBodyUsage(nsIFile* aDir, UsageInfo* aUsageInfo)
+GetBodyUsage(nsIFile* aDir, const Atomic<bool>& aCanceled,
+             UsageInfo* aUsageInfo)
 {
   nsCOMPtr<nsISimpleEnumerator> entries;
   nsresult rv = aDir->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   bool hasMore;
   while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore &&
-         !aUsageInfo->Canceled()) {
+         !aCanceled) {
     nsCOMPtr<nsISupports> entry;
     rv = entries->GetNext(getter_AddRefs(entry));
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
 
     bool isDir;
     rv = file->IsDirectory(&isDir);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     if (isDir) {
-      rv = GetBodyUsage(file, aUsageInfo);
+      rv = GetBodyUsage(file, aCanceled, aUsageInfo);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
       continue;
     }
 
     int64_t fileSize;
     rv = file->GetFileSize(&fileSize);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
@@ -67,30 +69,32 @@ public:
   virtual Type
   GetType() override
   {
     return DOMCACHE;
   }
 
   virtual nsresult
   InitOrigin(PersistenceType aPersistenceType, const nsACString& aGroup,
-             const nsACString& aOrigin, UsageInfo* aUsageInfo) override
+             const nsACString& aOrigin, const AtomicBool& aCanceled,
+             UsageInfo* aUsageInfo) override
   {
     // The QuotaManager passes a nullptr UsageInfo if there is no quota being
     // enforced against the origin.
     if (!aUsageInfo) {
       return NS_OK;
     }
 
-    return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aUsageInfo);
+    return GetUsageForOrigin(aPersistenceType, aGroup, aOrigin, aCanceled,
+                             aUsageInfo);
   }
 
   virtual nsresult
   GetUsageForOrigin(PersistenceType aPersistenceType, const nsACString& aGroup,
-                    const nsACString& aOrigin,
+                    const nsACString& aOrigin, const AtomicBool& aCanceled,
                     UsageInfo* aUsageInfo) override
   {
     MOZ_DIAGNOSTIC_ASSERT(aUsageInfo);
 
     QuotaManager* qm = QuotaManager::Get();
     MOZ_DIAGNOSTIC_ASSERT(qm);
 
     nsCOMPtr<nsIFile> dir;
@@ -102,34 +106,34 @@ public:
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     nsCOMPtr<nsISimpleEnumerator> entries;
     rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     bool hasMore;
     while (NS_SUCCEEDED(rv = entries->HasMoreElements(&hasMore)) && hasMore &&
-           !aUsageInfo->Canceled()) {
+           !aCanceled) {
       nsCOMPtr<nsISupports> entry;
       rv = entries->GetNext(getter_AddRefs(entry));
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
       nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
 
       nsAutoString leafName;
       rv = file->GetLeafName(leafName);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
       bool isDir;
       rv = file->IsDirectory(&isDir);
       if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
       if (isDir) {
         if (leafName.EqualsLiteral("morgue")) {
-          rv = GetBodyUsage(file, aUsageInfo);
+          rv = GetBodyUsage(file, aCanceled, aUsageInfo);
           if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
         } else {
           NS_WARNING("Unknown Cache directory found!");
         }
 
         continue;
       }
 
--- a/dom/cache/test/mochitest/test_cache_orphaned_body.html
+++ b/dom/cache/test/mochitest/test_cache_orphaned_body.html
@@ -32,17 +32,18 @@ function clearStorage() {
   });
 }
 
 function storageUsage() {
   return new Promise(function(resolve, reject) {
     var qms = SpecialPowers.Services.qms;
     var principal = SpecialPowers.wrap(document).nodePrincipal;
     var cb = SpecialPowers.wrapCallback(function(request) {
-      resolve(request.usage, request.fileUsage);
+      var result = request.result;
+      resolve(result.usage, result.fileUsage);
     });
     qms.getUsageForPrincipal(principal, cb);
   });
 }
 
 function groupUsage() {
   return new Promise(function(resolve, reject) {
    navigator.storage.estimate().then(storageEstimation => {
--- a/dom/cache/test/mochitest/test_cache_orphaned_cache.html
+++ b/dom/cache/test/mochitest/test_cache_orphaned_cache.html
@@ -32,17 +32,18 @@ function clearStorage() {
   });
 }
 
 function storageUsage() {
   return new Promise(function(resolve, reject) {
     var qms = SpecialPowers.Services.qms;
     var principal = SpecialPowers.wrap(document).nodePrincipal;
     var cb = SpecialPowers.wrapCallback(function(request) {
-      resolve(request.usage, request.fileUsage);
+      var result = request.result;
+      resolve(result.usage, result.fileUsage);
     });
     qms.getUsageForPrincipal(principal, cb);
   });
 }
 
 function resetStorage() {
   return new Promise(function(resolve, reject) {
     var qms = SpecialPowers.Services.qms;
--- a/dom/cache/test/mochitest/test_cache_shrink.html
+++ b/dom/cache/test/mochitest/test_cache_shrink.html
@@ -32,17 +32,18 @@ function clearStorage() {
   });
 }
 
 function storageUsage() {
   return new Promise(function(resolve, reject) {
     var qms = SpecialPowers.Services.qms;
     var principal = SpecialPowers.wrap(document).nodePrincipal;
     var cb = SpecialPowers.wrapCallback(function(request) {
-      resolve(request.usage, request.fileUsage);
+      var result = request.result;
+      resolve(result.usage, result.fileUsage);
     });
     qms.getUsageForPrincipal(principal, cb);
   });
 }
 
 function resetStorage() {
   return new Promise(function(resolve, reject) {
     var qms = SpecialPowers.Services.qms;
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -374,38 +374,41 @@ NS_IMETHODIMP
 nsTextInputSelectionImpl::ScrollSelectionIntoView(
                             RawSelectionType aRawSelectionType,
                             int16_t aRegion,
                             int16_t aFlags)
 {
   if (!mFrameSelection) 
     return NS_ERROR_FAILURE; 
 
-  return mFrameSelection->ScrollSelectionIntoView(
-                            ToSelectionType(aRawSelectionType),
-                            aRegion, aFlags);
+  RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+  return frameSelection->ScrollSelectionIntoView(
+                           ToSelectionType(aRawSelectionType),
+                           aRegion, aFlags);
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::RepaintSelection(RawSelectionType aRawSelectionType)
 {
   if (!mFrameSelection)
     return NS_ERROR_FAILURE;
 
-  return mFrameSelection->RepaintSelection(ToSelectionType(aRawSelectionType));
+  RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+  return frameSelection->RepaintSelection(ToSelectionType(aRawSelectionType));
 }
 
 nsresult
 nsTextInputSelectionImpl::RepaintSelection(nsPresContext* aPresContext,
                                            SelectionType aSelectionType)
 {
   if (!mFrameSelection)
     return NS_ERROR_FAILURE;
 
-  return mFrameSelection->RepaintSelection(aSelectionType);
+  RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+  return frameSelection->RepaintSelection(aSelectionType);
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::SetCaretEnabled(bool enabled)
 {
   if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
 
   nsCOMPtr<nsIPresShell> shell = do_QueryReferent(mPresShellWeak);
@@ -482,92 +485,108 @@ nsTextInputSelectionImpl::SetCaretVisibi
   }
   return NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::PhysicalMove(int16_t aDirection, int16_t aAmount,
                                        bool aExtend)
 {
-  if (mFrameSelection)
-    return mFrameSelection->PhysicalMove(aDirection, aAmount, aExtend);
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->PhysicalMove(aDirection, aAmount, aExtend);
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::CharacterMove(bool aForward, bool aExtend)
 {
-  if (mFrameSelection)
-    return mFrameSelection->CharacterMove(aForward, aExtend);
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->CharacterMove(aForward, aExtend);
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::CharacterExtendForDelete()
 {
-  if (mFrameSelection)
-    return mFrameSelection->CharacterExtendForDelete();
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->CharacterExtendForDelete();
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::CharacterExtendForBackspace()
 {
-  if (mFrameSelection)
-    return mFrameSelection->CharacterExtendForBackspace();
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->CharacterExtendForBackspace();
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::WordMove(bool aForward, bool aExtend)
 {
-  if (mFrameSelection)
-    return mFrameSelection->WordMove(aForward, aExtend);
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->WordMove(aForward, aExtend);
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::WordExtendForDelete(bool aForward)
 {
-  if (mFrameSelection)
-    return mFrameSelection->WordExtendForDelete(aForward);
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->WordExtendForDelete(aForward);
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::LineMove(bool aForward, bool aExtend)
 {
   if (mFrameSelection)
   {
-    nsresult result = mFrameSelection->LineMove(aForward, aExtend);
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    nsresult result = frameSelection->LineMove(aForward, aExtend);
     if (NS_FAILED(result))
       result = CompleteMove(aForward,aExtend);
     return result;
   }
   return NS_ERROR_NULL_POINTER;
 }
 
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::IntraLineMove(bool aForward, bool aExtend)
 {
-  if (mFrameSelection)
-    return mFrameSelection->IntraLineMove(aForward, aExtend);
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->IntraLineMove(aForward, aExtend);
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::PageMove(bool aForward, bool aExtend)
 {
   // expected behavior for PageMove is to scroll AND move the caret
   // and to remain relative position of the caret in view. see Bug 4302.
   if (mScrollFrame)
   {
-    mFrameSelection->CommonPageMove(aForward, aExtend, mScrollFrame);
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    frameSelection->CommonPageMove(aForward, aExtend, mScrollFrame);
   }
   // After ScrollSelectionIntoView(), the pending notifications might be
   // flushed and PresShell/PresContext/Frames may be dead. See bug 418470.
   return ScrollSelectionIntoView(nsISelectionController::SELECTION_NORMAL,
                                  nsISelectionController::SELECTION_FOCUS_REGION,
                                  nsISelectionController::SCROLL_SYNCHRONOUS |
                                  nsISelectionController::SCROLL_FOR_CARET_MOVE);
 }
@@ -585,18 +604,21 @@ nsTextInputSelectionImpl::CompleteScroll
                          nsIScrollableFrame::WHOLE,
                          nsIScrollableFrame::INSTANT);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::CompleteMove(bool aForward, bool aExtend)
 {
+  NS_ENSURE_STATE(mFrameSelection);
+  RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+
   // grab the parent / root DIV for this text widget
-  nsIContent* parentDIV = mFrameSelection->GetLimiter();
+  nsIContent* parentDIV = frameSelection->GetLimiter();
   if (!parentDIV)
     return NS_ERROR_UNEXPECTED;
 
   // make the caret be either at the very beginning (0) or the very end
   int32_t offset = 0;
   CaretAssociationHint hint = CARET_ASSOCIATE_BEFORE;
   if (aForward)
   {
@@ -612,17 +634,17 @@ nsTextInputSelectionImpl::CompleteMove(b
       if (child->IsHTMLElement(nsGkAtoms::br))
       {
         --offset;
         hint = CARET_ASSOCIATE_AFTER; // for Bug 106855
       }
     }
   }
 
-  mFrameSelection->HandleClick(parentDIV, offset, offset, aExtend,
+  frameSelection->HandleClick(parentDIV, offset, offset, aExtend,
                                false, hint);
 
   // if we got this far, attempt to scroll no matter what the above result is
   return CompleteScroll(aForward);
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::ScrollPage(bool aForward)
@@ -667,18 +689,20 @@ nsTextInputSelectionImpl::ScrollCharacte
                          nsIScrollableFrame::LINES,
                          nsIScrollableFrame::SMOOTH);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::SelectAll()
 {
-  if (mFrameSelection)
-    return mFrameSelection->SelectAll();
+  if (mFrameSelection) {
+    RefPtr<nsFrameSelection> frameSelection = mFrameSelection;
+    return frameSelection->SelectAll();
+  }
   return NS_ERROR_NULL_POINTER;
 }
 
 NS_IMETHODIMP
 nsTextInputSelectionImpl::CheckVisibility(nsIDOMNode *node, int16_t startOffset, int16_t EndOffset, bool *_retval)
 {
   if (!mPresShellWeak) return NS_ERROR_NOT_INITIALIZED;
   nsresult result;
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -9342,22 +9342,24 @@ public:
 
   nsresult
   UpgradeStorageFrom1_0To2_0(nsIFile* aDirectory) override;
 
   nsresult
   InitOrigin(PersistenceType aPersistenceType,
              const nsACString& aGroup,
              const nsACString& aOrigin,
+             const AtomicBool& aCanceled,
              UsageInfo* aUsageInfo) override;
 
   nsresult
   GetUsageForOrigin(PersistenceType aPersistenceType,
                     const nsACString& aGroup,
                     const nsACString& aOrigin,
+                    const AtomicBool& aCanceled,
                     UsageInfo* aUsageInfo) override;
 
   void
   OnOriginClearCompleted(PersistenceType aPersistenceType,
                          const nsACString& aOrigin)
                          override;
 
   void
@@ -9389,23 +9391,24 @@ private:
 
   nsresult
   GetDirectory(PersistenceType aPersistenceType,
                const nsACString& aOrigin,
                nsIFile** aDirectory);
 
   nsresult
   GetDatabaseFilenames(nsIFile* aDirectory,
-                       UsageInfo* aUsageInfo,
+                       const AtomicBool& aCanceled,
                        bool aForUpgrade,
                        nsTArray<nsString>& aSubdirsToProcess,
                        nsTHashtable<nsStringHashKey>& aDatabaseFilename);
 
   nsresult
   GetUsageForDirectoryInternal(nsIFile* aDirectory,
+                               const AtomicBool& aCanceled,
                                UsageInfo* aUsageInfo,
                                bool aDatabaseFiles);
 
   // Runs on the PBackground thread. Checks to see if there's a queued
   // Maintenance to run.
   void
   ProcessMaintenanceQueue();
 };
@@ -17823,20 +17826,21 @@ QuotaClient::GetType()
 }
 
 nsresult
 QuotaClient::UpgradeStorageFrom1_0To2_0(nsIFile* aDirectory)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
 
+  AtomicBool dummy(false);
   AutoTArray<nsString, 20> subdirsToProcess;
   nsTHashtable<nsStringHashKey> databaseFilenames(20);
   nsresult rv = GetDatabaseFilenames(aDirectory,
-                                     nullptr,
+                                     /* aCanceled */ dummy,
                                      /* aForUpgrade */ true,
                                      subdirsToProcess,
                                      databaseFilenames);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   const NS_ConvertASCIItoUTF16 filesSuffix(
@@ -17919,16 +17923,17 @@ QuotaClient::UpgradeStorageFrom1_0To2_0(
 
   return NS_OK;
 }
 
 nsresult
 QuotaClient::InitOrigin(PersistenceType aPersistenceType,
                         const nsACString& aGroup,
                         const nsACString& aOrigin,
+                        const AtomicBool& aCanceled,
                         UsageInfo* aUsageInfo)
 {
   AssertIsOnIOThread();
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv =
     GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -17937,17 +17942,17 @@ QuotaClient::InitOrigin(PersistenceType 
 
   // We need to see if there are any files in the directory already. If they
   // are database files then we need to cleanup stored files (if it's needed)
   // and also get the usage.
 
   AutoTArray<nsString, 20> subdirsToProcess;
   nsTHashtable<nsStringHashKey> databaseFilenames(20);
   rv = GetDatabaseFilenames(directory,
-                            aUsageInfo,
+                            aCanceled,
                             /* aForUpgrade */ false,
                             subdirsToProcess,
                             databaseFilenames);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   const NS_ConvertASCIItoUTF16 filesSuffix(
@@ -17969,17 +17974,19 @@ QuotaClient::InitOrigin(PersistenceType 
     }
   }
 
   const NS_ConvertASCIItoUTF16 sqliteSuffix(kSQLiteSuffix,
                                             LiteralStringLength(kSQLiteSuffix));
   const NS_ConvertASCIItoUTF16 walSuffix(kSQLiteWALSuffix,
                                          LiteralStringLength(kSQLiteWALSuffix));
 
-  for (auto iter = databaseFilenames.ConstIter(); !iter.Done(); iter.Next()) {
+  for (auto iter = databaseFilenames.ConstIter();
+       !iter.Done() && !aCanceled;
+       iter.Next()) {
     auto& databaseFilename = iter.Get()->GetKey();
 
     nsCOMPtr<nsIFile> fmDirectory;
     rv = directory->Clone(getter_AddRefs(fmDirectory));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
@@ -18017,17 +18024,17 @@ QuotaClient::InitOrigin(PersistenceType 
                                     aPersistenceType,
                                     aGroup,
                                     aOrigin,
                                     TelemetryIdForFile(databaseFile));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    if (aUsageInfo && !aUsageInfo->Canceled()) {
+    if (aUsageInfo) {
       int64_t fileSize;
       rv = databaseFile->GetFileSize(&fileSize);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
       MOZ_ASSERT(fileSize >= 0);
 
@@ -18054,29 +18061,30 @@ QuotaClient::InitOrigin(PersistenceType 
 
   return NS_OK;
 }
 
 nsresult
 QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType,
                                const nsACString& aGroup,
                                const nsACString& aOrigin,
+                               const AtomicBool& aCanceled,
                                UsageInfo* aUsageInfo)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aUsageInfo);
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv =
     GetDirectory(aPersistenceType, aOrigin, getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  rv = GetUsageForDirectoryInternal(directory, aUsageInfo, true);
+  rv = GetUsageForDirectoryInternal(directory, aCanceled, aUsageInfo, true);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   return NS_OK;
 }
 
 void
@@ -18255,22 +18263,23 @@ QuotaClient::GetDirectory(PersistenceTyp
 
   directory.forget(aDirectory);
   return NS_OK;
 }
 
 nsresult
 QuotaClient::GetDatabaseFilenames(
                               nsIFile* aDirectory,
-                              UsageInfo* aUsageInfo,
+                              const AtomicBool& aCanceled,
                               bool aForUpgrade,
                               nsTArray<nsString>& aSubdirsToProcess,
                               nsTHashtable<nsStringHashKey>& aDatabaseFilenames)
 {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aDirectory);
 
   nsCOMPtr<nsISimpleEnumerator> entries;
   nsresult rv = aDirectory->GetDirectoryEntries(getter_AddRefs(entries));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   const NS_ConvertASCIItoUTF16 sqliteSuffix(kSQLiteSuffix,
@@ -18281,17 +18290,17 @@ QuotaClient::GetDatabaseFilenames(
   const NS_ConvertASCIItoUTF16 shmSuffix(kSQLiteSHMSuffix,
                                          LiteralStringLength(kSQLiteSHMSuffix));
   const NS_ConvertASCIItoUTF16 walSuffix(kSQLiteWALSuffix,
                                          LiteralStringLength(kSQLiteWALSuffix));
 
   bool hasMore;
   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
          hasMore &&
-         (!aUsageInfo || !aUsageInfo->Canceled())) {
+         !aCanceled) {
     nsCOMPtr<nsISupports> entry;
     rv = entries->GetNext(getter_AddRefs(entry));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
     MOZ_ASSERT(file);
@@ -18357,16 +18366,17 @@ QuotaClient::GetDatabaseFilenames(
     return rv;
   }
 
   return NS_OK;
 }
 
 nsresult
 QuotaClient::GetUsageForDirectoryInternal(nsIFile* aDirectory,
+                                          const AtomicBool& aCanceled,
                                           UsageInfo* aUsageInfo,
                                           bool aDatabaseFiles)
 {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(aUsageInfo);
 
   nsCOMPtr<nsISimpleEnumerator> entries;
@@ -18383,17 +18393,17 @@ QuotaClient::GetUsageForDirectoryInterna
     kSQLiteJournalSuffix,
     LiteralStringLength(kSQLiteJournalSuffix));
   const NS_ConvertASCIItoUTF16 shmSuffix(kSQLiteSHMSuffix,
                                          LiteralStringLength(kSQLiteSHMSuffix));
 
   bool hasMore;
   while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
          hasMore &&
-         !aUsageInfo->Canceled()) {
+         !aCanceled) {
     nsCOMPtr<nsISupports> entry;
     rv = entries->GetNext(getter_AddRefs(entry));
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
     MOZ_ASSERT(file);
@@ -18418,17 +18428,17 @@ QuotaClient::GetUsageForDirectoryInterna
     }
 
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (isDirectory) {
       if (aDatabaseFiles) {
-        rv = GetUsageForDirectoryInternal(file, aUsageInfo, false);
+        rv = GetUsageForDirectoryInternal(file, aCanceled, aUsageInfo, false);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       } else {
         nsString leafName;
         rv = file->GetLeafName(leafName);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
@@ -21231,18 +21241,17 @@ FactoryOp::CheckPermission(ContentParent
       mChromeWriteAccessAllowed = canWrite;
     } else {
       mChromeWriteAccessAllowed = true;
     }
 
     if (State::Initial == mState) {
       QuotaManager::GetInfoForChrome(&mSuffix, &mGroup, &mOrigin);
 
-      MOZ_ASSERT(
-        QuotaManager::IsOriginWhitelistedForPersistentStorage(mOrigin));
+      MOZ_ASSERT(QuotaManager::IsOriginInternal(mOrigin));
 
       mEnforcingQuota = false;
     }
 
     *aPermission = PermissionRequestBase::kPermissionAllowed;
     return NS_OK;
   }
 
@@ -21264,17 +21273,17 @@ FactoryOp::CheckPermission(ContentParent
                                           &origin);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   PermissionRequestBase::PermissionValue permission;
 
   if (persistenceType == PERSISTENCE_TYPE_PERSISTENT) {
-    if (QuotaManager::IsOriginWhitelistedForPersistentStorage(origin)) {
+    if (QuotaManager::IsOriginInternal(origin)) {
       permission = PermissionRequestBase::kPermissionAllowed;
     } else {
 #ifdef IDB_MOBILE
       return NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR;
 #else
       rv = PermissionRequestBase::GetCurrentPermission(principal, &permission);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
--- a/dom/indexedDB/test/file.js
+++ b/dom/indexedDB/test/file.js
@@ -215,20 +215,20 @@ function verifyWasmModule(module1, modul
   ok(code2 instanceof getGlobalForObject(code1).Uint8Array, "Instance of Uint8Array");
   ok(code1.length == code2.length, "Correct length");
   verifyBuffers(code1, code2);
   continueToNextStep();
 }
 
 function grabFileUsageAndContinueHandler(request)
 {
-  testGenerator.next(request.fileUsage);
+  testGenerator.next(request.result.fileUsage);
 }
 
-function getUsage(usageHandler)
+function getCurrentUsage(usageHandler)
 {
   let qms = SpecialPowers.Services.qms;
   let principal = SpecialPowers.wrap(document).nodePrincipal;
   let cb = SpecialPowers.wrapCallback(usageHandler);
   qms.getUsageForPrincipal(principal, cb);
 }
 
 function getFileId(file)
--- a/dom/indexedDB/test/test_file_os_delete.html
+++ b/dom/indexedDB/test/test_file_os_delete.html
@@ -13,17 +13,17 @@
   function* testSteps()
   {
     const READ_WRITE = "readwrite";
 
     const name = window.location.pathname;
 
     const objectStoreName = "Blobs";
 
-    getUsage(grabFileUsageAndContinueHandler);
+    getCurrentUsage(grabFileUsageAndContinueHandler);
     let startUsage = yield undefined;
 
     const fileData1 = {
       key: 1,
       obj: { id: 1, file: getRandomFile("random.bin", 100000) }
     };
     const fileData2 = {
       key: 2,
@@ -56,46 +56,46 @@
       request.addEventListener("error", new ExpectError("ConstraintError", true));
       request.onsuccess = unexpectedSuccessHandler;
       yield undefined;
 
       event = yield undefined;
 
       is(event.type, "success", "Got correct event type");
 
-      getUsage(grabFileUsageAndContinueHandler);
+      getCurrentUsage(grabFileUsageAndContinueHandler);
       let usage = yield undefined;
 
       is(usage, startUsage + fileData1.obj.file.size + fileData2.obj.file.size,
          "Correct file usage");
 
       let trans = db.transaction([objectStoreName], READ_WRITE);
       trans.objectStore(objectStoreName).delete(fileData1.key);
       trans.oncomplete = grabEventAndContinueHandler;
       event = yield undefined;
 
       is(event.type, "complete", "Got correct event type");
 
-      getUsage(grabFileUsageAndContinueHandler);
+      getCurrentUsage(grabFileUsageAndContinueHandler);
       usage = yield undefined;
 
       is(usage, startUsage + fileData1.obj.file.size + fileData2.obj.file.size,
          "OS files exists");
 
       fileData1.obj.file = null;
       fileData2.obj.file = null;
     }
 
     scheduleGC();
     yield undefined;
 
     // Flush pending file deletions before checking usage.
     flushPendingFileDeletions();
 
-    getUsage(grabFileUsageAndContinueHandler);
+    getCurrentUsage(grabFileUsageAndContinueHandler);
     let endUsage = yield undefined;
 
     is(endUsage, startUsage, "OS files deleted");
 
     finishTest();
   }
   </script>
   <script type="text/javascript" src="file.js"></script>
--- a/dom/indexedDB/test/unit/test_idle_maintenance.js
+++ b/dom/indexedDB/test/unit/test_idle_maintenance.js
@@ -117,18 +117,19 @@ function* testSteps()
   }
   yield undefined;
 
   info("Getting usage before maintenance");
 
   let usageBeforeMaintenance;
 
   quotaManagerService.getUsageForPrincipal(principal, (request) => {
-    ok(request.usage > 0, "Usage is non-zero");
-    usageBeforeMaintenance = request.usage;
+    let usage = request.result.usage;
+    ok(usage > 0, "Usage is non-zero");
+    usageBeforeMaintenance = usage;
     continueToNextStep();
   });
   yield undefined;
 
   info("Sending fake 'idle-daily' notification to QuotaManager");
 
   let observer = quotaManagerService.QueryInterface(Ci.nsIObserver);
   observer.observe(null, "idle-daily", "");
@@ -150,18 +151,19 @@ function* testSteps()
   setTimeout(continueToNextStep, 10000);
   yield undefined;
 
   info("Getting usage after maintenance");
 
   let usageAfterMaintenance;
 
   quotaManagerService.getUsageForPrincipal(principal, (request) => {
-    ok(request.usage > 0, "Usage is non-zero");
-    usageAfterMaintenance = request.usage;
+    let usage = request.result.usage;
+    ok(usage > 0, "Usage is non-zero");
+    usageAfterMaintenance = usage;
     continueToNextStep();
   });
   yield undefined;
 
   info("Usage before: " + usageBeforeMaintenance + ". " +
        "Usage after: " + usageAfterMaintenance);
 
   ok(usageAfterMaintenance <= usageBeforeMaintenance,
--- a/dom/indexedDB/test/unit/test_view_put_get_values.js
+++ b/dom/indexedDB/test/unit/test_view_put_get_values.js
@@ -75,17 +75,17 @@ function* testSteps()
     request = db.transaction([objectStoreName])
                 .objectStore(objectStoreName).get(viewData.key);
     request.onsuccess = continueToNextStepSync;
     yield undefined;
 
     verifyView(request.result, viewData.view);
     yield undefined;
 
-    getUsage(grabFileUsageAndContinueHandler);
+    getCurrentUsage(grabFileUsageAndContinueHandler);
     let fileUsage = yield undefined;
 
     if (external) {
       ok(fileUsage > 0, "File usage is not zero");
     } else {
       ok(fileUsage == 0, "File usage is zero");
     }
 
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -511,20 +511,20 @@ function verifyWasmModule(module1, modul
   ok(code1 instanceof Uint8Array, "Instance of Uint8Array");
   ok(code1.length == code2.length, "Correct length");
   verifyBuffers(code1, code2);
   continueToNextStep();
 }
 
 function grabFileUsageAndContinueHandler(request)
 {
-  testGenerator.next(request.fileUsage);
+  testGenerator.next(request.result.fileUsage);
 }
 
-function getUsage(usageHandler)
+function getCurrentUsage(usageHandler)
 {
   let qms = Cc["@mozilla.org/dom/quota-manager-service;1"]
               .getService(Ci.nsIQuotaManagerService);
   let principal = Cc["@mozilla.org/systemprincipal;1"]
                     .createInstance(Ci.nsIPrincipal);
   qms.getUsageForPrincipal(principal, usageHandler);
 }
 
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -53,27 +53,27 @@
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMEvent.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMWindowUtils.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsILoadInfo.h"
-#include "nsPrincipal.h"
 #include "nsIPromptFactory.h"
 #include "nsIURI.h"
 #include "nsIWindowWatcher.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIXULBrowserWindow.h"
 #include "nsIXULWindow.h"
 #include "nsIRemoteBrowser.h"
 #include "nsViewManager.h"
 #include "nsVariant.h"
 #include "nsIWidget.h"
+#include "nsNetUtil.h"
 #ifndef XP_WIN
 #include "nsJARProtocolHandler.h"
 #endif
 #include "nsPIDOMWindow.h"
 #include "nsPrintfCString.h"
 #include "nsServiceManagerUtils.h"
 #include "nsThreadUtils.h"
 #include "PermissionMessageUtils.h"
--- a/dom/json/nsJSON.cpp
+++ b/dom/json/nsJSON.cpp
@@ -17,17 +17,17 @@
 #include "nsIUnicodeDecoder.h"
 #include "nsNetUtil.h"
 #include "nsIURI.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptError.h"
 #include "nsCRTGlue.h"
 #include "nsIScriptSecurityManager.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "mozilla/Maybe.h"
 #include <algorithm>
 
 using mozilla::dom::EncodingUtils;
 
 #define JSON_STREAM_BUFSIZE 4096
 
 NS_INTERFACE_MAP_BEGIN(nsJSON)
@@ -402,17 +402,17 @@ nsJSON::DecodeInternal(JSContext* cx,
   nsCOMPtr<nsIChannel> jsonChannel;
   if (!mURI) {
     NS_NewURI(getter_AddRefs(mURI), NS_LITERAL_CSTRING("about:blank"), 0, 0 );
     if (!mURI)
       return NS_ERROR_OUT_OF_MEMORY;
   }
 
   nsresult rv;
-  nsCOMPtr<nsIPrincipal> nullPrincipal = nsNullPrincipal::Create();
+  nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create();
 
   // The ::Decode function is deprecated [Bug 675797] and the following
   // channel is never openend, so it does not matter what securityFlags
   // we pass to NS_NewInputStreamChannel here.
   rv = NS_NewInputStreamChannel(getter_AddRefs(jsonChannel),
                                 mURI,
                                 aStream,
                                 nullPrincipal,
--- a/dom/jsurl/nsJSProtocolHandler.cpp
+++ b/dom/jsurl/nsJSProtocolHandler.cpp
@@ -264,20 +264,24 @@ nsresult nsJSThunk::EvaluateScript(nsICh
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     JS::Rooted<JS::Value> v (cx, JS::UndefinedValue());
     // Finally, we have everything needed to evaluate the expression.
     JS::CompileOptions options(cx);
     options.setFileAndLine(mURL.get(), 1)
            .setVersion(JSVERSION_DEFAULT);
-    nsJSUtils::EvaluateOptions evalOptions(cx);
-    evalOptions.setCoerceToString(true);
-    rv = nsJSUtils::EvaluateString(cx, NS_ConvertUTF8toUTF16(script),
-                                   globalJSObject, options, evalOptions, &v);
+    {
+        nsJSUtils::ExecutionContext exec(cx, globalJSObject);
+        exec.SetCoerceToString(true);
+        exec.CompileAndExec(options, NS_ConvertUTF8toUTF16(script));
+        rv = exec.ExtractReturnValue(&v);
+    }
+
+    js::AssertSameCompartment(cx, v);
 
     if (NS_FAILED(rv) || !(v.isString() || v.isUndefined())) {
         return NS_ERROR_MALFORMED_URI;
     } else if (v.isUndefined()) {
         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     } else {
         MOZ_ASSERT(rv != NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW,
                    "How did we get a non-undefined return value?");
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -23,17 +23,16 @@
 #include "nsIPopupWindowManager.h"
 #include "nsIDocShell.h"
 #include "nsIDocument.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIIDNService.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
-#include "nsPrincipal.h"
 #include "nsICryptoHash.h"
 #include "nsICryptoHMAC.h"
 #include "nsIKeyModule.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIInputStream.h"
 #include "nsILineInputStream.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Types.h"
@@ -49,17 +48,17 @@
 #include "mozilla/Base64.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/media/MediaChild.h"
 #include "mozilla/media/MediaTaskUtils.h"
 #include "MediaTrackConstraints.h"
 #include "VideoUtils.h"
 #include "Latency.h"
 #include "nsProxyRelease.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "nsVariant.h"
 
 // For snprintf
 #include "mozilla/Sprintf.h"
 
 #include "nsJSUtils.h"
 #include "nsGlobalWindow.h"
 #include "nsIUUIDGenerator.h"
@@ -1150,17 +1149,17 @@ public:
         RefPtr<GetUserMediaCallbackMediaStreamListener> mListener;
         const MediaSourceEnum mSource;
         const TrackID mTrackID;
         const RefPtr<const PeerIdentity> mPeerIdentity;
       };
 
       nsCOMPtr<nsIPrincipal> principal;
       if (mPeerIdentity) {
-        principal = nsNullPrincipal::CreateWithInheritedAttributes(window->GetExtantDoc()->NodePrincipal());
+        principal = NullPrincipal::CreateWithInheritedAttributes(window->GetExtantDoc()->NodePrincipal());
       } else {
         principal = window->GetExtantDoc()->NodePrincipal();
       }
 
       // Normal case, connect the source stream to the track union stream to
       // avoid us blocking. Pass a simple TrackSourceGetter for potential
       // fake tracks. Apart from them gUM never adds tracks dynamically.
       domStream =
--- a/dom/media/MediaStreamTrack.h
+++ b/dom/media/MediaStreamTrack.h
@@ -92,17 +92,17 @@ public:
    * PrincipalChanged().
    */
   virtual CORSMode GetCORSMode() const { return CORS_NONE; }
 
   /**
    * This is used in WebRTC. A peerIdentity constrained MediaStreamTrack cannot
    * be sent across the network to anything other than a peer with the provided
    * identity. If this is set, then GetPrincipal() should return an instance of
-   * nsNullPrincipal.
+   * NullPrincipal.
    *
    * A track's PeerIdentity is immutable and will not change during the track's
    * lifetime.
    */
   virtual const PeerIdentity* GetPeerIdentity() const { return nullptr; }
 
   /**
    * MediaStreamTrack::GetLabel (see spec) calls through to here.
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -255,37 +255,16 @@ DecodedAudioDataSink::PopFrames(uint32_t
     uint32_t Rate() const { return mBuffer ? mBuffer->mRate : 0; }
     AudioDataValue* GetWritable() const { return mData; }
   private:
     const RefPtr<AudioData> mBuffer;
     const uint32_t mFrames;
     AudioDataValue* const mData;
   };
 
-  class SilentChunk : public AudioStream::Chunk {
-  public:
-    SilentChunk(uint32_t aFrames, uint32_t aChannels, uint32_t aRate)
-      : mFrames(aFrames)
-      , mChannels(aChannels)
-      , mRate(aRate)
-      , mData(MakeUnique<AudioDataValue[]>(aChannels * aFrames)) {
-      memset(mData.get(), 0, aChannels * aFrames * sizeof(AudioDataValue));
-    }
-    const AudioDataValue* Data() const { return mData.get(); }
-    uint32_t Frames() const { return mFrames; }
-    uint32_t Channels() const { return mChannels; }
-    uint32_t Rate() const { return mRate; }
-    AudioDataValue* GetWritable() const { return mData.get(); }
-  private:
-    const uint32_t mFrames;
-    const uint32_t mChannels;
-    const uint32_t mRate;
-    UniquePtr<AudioDataValue[]> mData;
-  };
-
   bool needPopping = false;
   if (!mCurrentData) {
     // No data in the queue. Return an empty chunk.
     if (!mProcessedQueue.GetSize()) {
       return MakeUnique<Chunk>();
     }
 
     // We need to update our values prior popping the processed queue in
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -1363,24 +1363,33 @@ bool
   NPN_PLUGIN_LOG(PLUGIN_LOG_NOISY,
                  ("NPN_Evaluate(npp %p, npobj %p, script <<<%s>>>) called\n",
                   npp, npobj, script->UTF8Characters));
 
   JS::CompileOptions options(cx);
   options.setFileAndLine(spec, 0)
          .setVersion(JSVERSION_DEFAULT);
   JS::Rooted<JS::Value> rval(cx);
-  nsJSUtils::EvaluateOptions evalOptions(cx);
+  JS::AutoObjectVector scopeChain(cx);
   if (obj != js::GetGlobalForObjectCrossCompartment(obj) &&
-      !evalOptions.scopeChain.append(obj)) {
+      !scopeChain.append(obj)) {
     return false;
   }
   obj = js::GetGlobalForObjectCrossCompartment(obj);
-  nsresult rv = nsJSUtils::EvaluateString(cx, utf16script, obj, options,
-                                          evalOptions, &rval);
+  nsresult rv = NS_OK;
+  {
+    nsJSUtils::ExecutionContext exec(cx, obj);
+    exec.SetScopeChain(scopeChain);
+    exec.CompileAndExec(options, utf16script);
+    rv = exec.ExtractReturnValue(&rval);
+  }
+
+  if (!JS_WrapValue(cx, &rval)) {
+    return false;
+  }
 
   return NS_SUCCEEDED(rv) &&
          (!result || JSValToNPVariant(npp, cx, rval, result));
 }
 
 bool
 _getproperty(NPP npp, NPObject* npobj, NPIdentifier property,
              NPVariant *result)
--- a/dom/plugins/base/nsPluginHost.cpp
+++ b/dom/plugins/base/nsPluginHost.cpp
@@ -89,17 +89,17 @@
 #include "nsPluginNativeWindow.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/Telemetry.h"
 #include "nsIImageLoadingContent.h"
 #include "mozilla/Preferences.h"
 #include "nsVersionComparator.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 
 #if defined(XP_WIN)
 #include "nsIWindowMediator.h"
 #include "nsIBaseWindow.h"
 #include "windows.h"
 #include "winbase.h"
 #endif
 
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -28,17 +28,17 @@
 #include "nsIDocument.h"
 #include "nsIWebNavigation.h"
 #include "nsContentUtils.h"
 #include "nsNetUtil.h"
 #include "nsPluginNativeWindow.h"
 #include "GeckoProfiler.h"
 #include "nsPluginInstanceOwner.h"
 #include "nsDataHashtable.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 
 #define BYTERANGE_REQUEST_CONTEXT 0x01020304
 
 // nsPluginByteRangeStreamListener
 
 class nsPluginByteRangeStreamListener
   : public nsIStreamListener
   , public nsIInterfaceRequestor
--- a/dom/quota/ActorsChild.cpp
+++ b/dom/quota/ActorsChild.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "ActorsChild.h"
 
 #include "nsVariant.h"
 #include "QuotaManagerService.h"
 #include "QuotaRequests.h"
+#include "QuotaResults.h"
 
 namespace mozilla {
 namespace dom {
 namespace quota {
 
 /*******************************************************************************
  * QuotaChild
  ******************************************************************************/
@@ -136,24 +137,66 @@ QuotaUsageRequestChild::HandleResponse(n
   AssertIsOnOwningThread();
   MOZ_ASSERT(NS_FAILED(aResponse));
   MOZ_ASSERT(mRequest);
 
   mRequest->SetError(aResponse);
 }
 
 void
-QuotaUsageRequestChild::HandleResponse(const UsageResponse& aResponse)
+QuotaUsageRequestChild::HandleResponse(const nsTArray<OriginUsage>& aResponse)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mRequest);
 
-  mRequest->SetResult(aResponse.usage(),
-                      aResponse.fileUsage(),
-                      aResponse.limit());
+  RefPtr<nsVariant> variant = new nsVariant();
+
+  if (aResponse.IsEmpty()) {
+    variant->SetAsEmptyArray();
+  } else {
+    nsTArray<RefPtr<UsageResult>> usageResults;
+
+    const uint32_t count = aResponse.Length();
+
+    usageResults.SetCapacity(count);
+
+    for (uint32_t index = 0; index < count; index++) {
+      auto& originUsage = aResponse[index];
+
+      RefPtr<UsageResult> usageResult = new UsageResult(originUsage.origin(),
+                                                        originUsage.persisted(),
+                                                        originUsage.usage());
+
+      usageResults.AppendElement(usageResult.forget());
+    }
+
+    variant->SetAsArray(nsIDataType::VTYPE_INTERFACE_IS,
+                        &NS_GET_IID(nsIQuotaUsageResult),
+                        usageResults.Length(),
+                        static_cast<void*>(usageResults.Elements()));
+  }
+
+  mRequest->SetResult(variant);
+}
+
+void
+QuotaUsageRequestChild::HandleResponse(const OriginUsageResponse& aResponse)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(mRequest);
+
+  RefPtr<OriginUsageResult> result =
+    new OriginUsageResult(aResponse.usage(),
+                          aResponse.fileUsage(),
+                          aResponse.limit());
+
+  RefPtr<nsVariant> variant = new nsVariant();
+  variant->SetAsInterface(NS_GET_IID(nsIQuotaOriginUsageResult), result);
+
+  mRequest->SetResult(variant);
 }
 
 void
 QuotaUsageRequestChild::ActorDestroy(ActorDestroyReason aWhy)
 {
   AssertIsOnOwningThread();
 
   if (mRequest) {
@@ -170,18 +213,22 @@ QuotaUsageRequestChild::Recv__delete__(c
   AssertIsOnOwningThread();
   MOZ_ASSERT(mRequest);
 
   switch (aResponse.type()) {
     case UsageRequestResponse::Tnsresult:
       HandleResponse(aResponse.get_nsresult());
       break;
 
-    case UsageRequestResponse::TUsageResponse:
-      HandleResponse(aResponse.get_UsageResponse());
+    case UsageRequestResponse::TAllUsageResponse:
+      HandleResponse(aResponse.get_AllUsageResponse().originUsages());
+      break;
+
+    case UsageRequestResponse::TOriginUsageResponse:
+      HandleResponse(aResponse.get_OriginUsageResponse());
       break;
 
     default:
       MOZ_CRASH("Unknown response type!");
   }
 
   return IPC_OK();
 }
--- a/dom/quota/ActorsChild.h
+++ b/dom/quota/ActorsChild.h
@@ -93,17 +93,20 @@ private:
 
   // Only destroyed by QuotaChild.
   ~QuotaUsageRequestChild();
 
   void
   HandleResponse(nsresult aResponse);
 
   void
-  HandleResponse(const UsageResponse& aResponse);
+  HandleResponse(const nsTArray<OriginUsage>& aResponse);
+
+  void
+  HandleResponse(const OriginUsageResponse& aResponse);
 
   // IPDL methods are only called by IPDL.
   virtual void
   ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual mozilla::ipc::IPCResult
   Recv__delete__(const UsageRequestResponse& aResponse) override;
 };
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -910,16 +910,17 @@ class NormalOriginOperationBase
   : public OriginOperationBase
   , public OpenDirectoryListener
 {
   RefPtr<DirectoryLock> mDirectoryLock;
 
 protected:
   Nullable<PersistenceType> mPersistenceType;
   OriginScope mOriginScope;
+  mozilla::Atomic<bool> mCanceled;
   const bool mExclusive;
 
 public:
   void
   RunImmediately()
   {
     MOZ_ASSERT(GetState() == State_Initial);
 
@@ -1037,59 +1038,113 @@ private:
 
   virtual mozilla::ipc::IPCResult
   RecvStartIdleMaintenance() override;
 
   virtual mozilla::ipc::IPCResult
   RecvStopIdleMaintenance() override;
 };
 
-class GetUsageOp final
+class QuotaUsageRequestBase
   : public NormalOriginOperationBase
   , public PQuotaUsageRequestParent
 {
+public:
+  // May be overridden by subclasses if they need to perform work on the
+  // background thread before being run.
+  virtual bool
+  Init(Quota* aQuota);
+
+protected:
+  QuotaUsageRequestBase()
+    : NormalOriginOperationBase(Nullable<PersistenceType>(),
+                                OriginScope::FromNull(),
+                                /* aExclusive */ false)
+  { }
+
+  nsresult
+  GetUsageForOrigin(QuotaManager* aQuotaManager,
+                    PersistenceType aPersistenceType,
+                    const nsACString& aGroup,
+                    const nsACString& aOrigin,
+                    UsageInfo* aUsageInfo);
+
+  // Subclasses use this override to set the IPDL response value.
+  virtual void
+  GetResponse(UsageRequestResponse& aResponse) = 0;
+
+private:
+  void
+  SendResults() override;
+
+  // IPDL methods.
+  void
+  ActorDestroy(ActorDestroyReason aWhy) override;
+
+  mozilla::ipc::IPCResult
+  RecvCancel() override;
+};
+
+class GetUsageOp final
+  : public QuotaUsageRequestBase
+{
+  nsTArray<OriginUsage> mOriginUsages;
+  nsDataHashtable<nsCStringHashKey, uint32_t> mOriginUsagesIndex;
+
+  bool mGetAll;
+
+public:
+  explicit GetUsageOp(const UsageRequestParams& aParams);
+
+private:
+  ~GetUsageOp()
+  { }
+
+  nsresult
+  TraverseRepository(QuotaManager* aQuotaManager,
+                     PersistenceType aPersistenceType);
+
+  nsresult
+  DoDirectoryWork(QuotaManager* aQuotaManager) override;
+
+  void
+  GetResponse(UsageRequestResponse& aResponse) override;
+};
+
+class GetOriginUsageOp final
+  : public QuotaUsageRequestBase
+{
   // If mGetGroupUsage is false, we use mUsageInfo to record the origin usage
   // and the file usage. Otherwise, we use it to record the group usage and the
   // limit.
   UsageInfo mUsageInfo;
 
-  const UsageParams mParams;
+  const OriginUsageParams mParams;
   nsCString mSuffix;
   nsCString mGroup;
   bool mGetGroupUsage;
 
 public:
-  explicit GetUsageOp(const UsageRequestParams& aParams);
+  explicit GetOriginUsageOp(const UsageRequestParams& aParams);
 
   MOZ_IS_CLASS_INIT bool
-  Init(Quota* aQuota);
+  Init(Quota* aQuota) override;
 
 private:
-  ~GetUsageOp()
+  ~GetOriginUsageOp()
   { }
 
   MOZ_IS_CLASS_INIT virtual nsresult
   DoInitOnMainThread() override;
 
-  nsresult
-  AddToUsage(QuotaManager* aQuotaManager,
-             PersistenceType aPersistenceType);
-
   virtual nsresult
   DoDirectoryWork(QuotaManager* aQuotaManager) override;
 
-  virtual void
-  SendResults() override;
-
-  // IPDL methods.
-  virtual void
-  ActorDestroy(ActorDestroyReason aWhy) override;
-
-  virtual mozilla::ipc::IPCResult
-  RecvCancel() override;
+  void
+  GetResponse(UsageRequestResponse& aResponse) override;
 };
 
 class QuotaRequestBase
   : public NormalOriginOperationBase
   , public PQuotaRequestParent
 {
 public:
   // May be overridden by subclasses if they need to perform work on the
@@ -4191,17 +4246,21 @@ QuotaManager::InitializeOrigin(Persisten
 
     Client::Type clientType;
     rv = Client::TypeFromText(leafName, clientType);
     if (NS_FAILED(rv)) {
       UNKNOWN_FILE_WARNING(leafName);
       return NS_ERROR_UNEXPECTED;
     }
 
-    rv = mClients[clientType]->InitOrigin(aPersistenceType, aGroup, aOrigin,
+    Atomic<bool> dummy(false);
+    rv = mClients[clientType]->InitOrigin(aPersistenceType,
+                                          aGroup,
+                                          aOrigin,
+                                          /* aCanceled */ dummy,
                                           usageInfo);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   if (trackQuota) {
     InitQuotaForOrigin(aPersistenceType, aGroup, aOrigin,
                        usageInfo->TotalUsage(), aAccessTime, aPersisted);
   }
@@ -5291,20 +5350,19 @@ QuotaManager::GetInfoForChrome(nsACStrin
   }
   if (aOrigin) {
     ChromeOrigin(*aOrigin);
   }
 }
 
 // static
 bool
-QuotaManager::IsOriginWhitelistedForPersistentStorage(const nsACString& aOrigin)
-{
-  // The first prompt and quota tracking is not required for these origins in
-  // persistent storage.
+QuotaManager::IsOriginInternal(const nsACString& aOrigin)
+{
+  // The first prompt is not required for these origins.
   if (aOrigin.EqualsLiteral(kChromeOrigin) ||
       StringBeginsWith(aOrigin, nsDependentCString(kAboutHomeOriginPrefix)) ||
       StringBeginsWith(aOrigin, nsDependentCString(kIndexedDBOriginPrefix)) ||
       StringBeginsWith(aOrigin, nsDependentCString(kResourceOriginPrefix))) {
     return true;
   }
 
   return false;
@@ -6225,49 +6283,67 @@ Quota::ActorDestroy(ActorDestroyReason a
   MOZ_ASSERT(!mActorDestroyed);
   mActorDestroyed = true;
 #endif
 }
 
 PQuotaUsageRequestParent*
 Quota::AllocPQuotaUsageRequestParent(const UsageRequestParams& aParams)
 {
-  RefPtr<GetUsageOp> actor = new GetUsageOp(aParams);
+  AssertIsOnBackgroundThread();
+  MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None);
+
+  RefPtr<QuotaUsageRequestBase> actor;
+
+  switch (aParams.type()) {
+    case UsageRequestParams::TAllUsageParams:
+      actor = new GetUsageOp(aParams);
+      break;
+
+    case UsageRequestParams::TOriginUsageParams:
+      actor = new GetOriginUsageOp(aParams);
+      break;
+
+    default:
+      MOZ_CRASH("Should never get here!");
+  }
+
+  MOZ_ASSERT(actor);
 
   // Transfer ownership to IPDL.
   return actor.forget().take();
 }
 
 mozilla::ipc::IPCResult
 Quota::RecvPQuotaUsageRequestConstructor(PQuotaUsageRequestParent* aActor,
                                          const UsageRequestParams& aParams)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(aParams.type() != UsageRequestParams::T__None);
 
-  auto* op = static_cast<GetUsageOp*>(aActor);
+  auto* op = static_cast<QuotaUsageRequestBase*>(aActor);
 
   if (NS_WARN_IF(!op->Init(this))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   op->RunImmediately();
   return IPC_OK();
 }
 
 bool
 Quota::DeallocPQuotaUsageRequestParent(PQuotaUsageRequestParent* aActor)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
 
   // Transfer ownership back from IPDL.
-  RefPtr<GetUsageOp> actor =
-    dont_AddRef(static_cast<GetUsageOp*>(aActor));
+  RefPtr<QuotaUsageRequestBase> actor =
+    dont_AddRef(static_cast<QuotaUsageRequestBase*>(aActor));
   return true;
 }
 
 PQuotaRequestParent*
 Quota::AllocPQuotaRequestParent(const RequestParams& aParams)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aParams.type() != RequestParams::T__None);
@@ -6331,16 +6407,17 @@ mozilla::ipc::IPCResult
 Quota::RecvPQuotaRequestConstructor(PQuotaRequestParent* aActor,
                                     const RequestParams& aParams)
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(aActor);
   MOZ_ASSERT(aParams.type() != RequestParams::T__None);
 
   auto* op = static_cast<QuotaRequestBase*>(aActor);
+
   if (NS_WARN_IF(!op->Init(this))) {
     return IPC_FAIL_NO_REASON(this);
   }
 
   op->RunImmediately();
   return IPC_OK();
 }
 
@@ -6409,103 +6486,67 @@ Quota::RecvStopIdleMaintenance()
     return IPC_OK();
   }
 
   quotaManager->StopIdleMaintenance();
 
   return IPC_OK();
 }
 
-GetUsageOp::GetUsageOp(const UsageRequestParams& aParams)
-  : NormalOriginOperationBase(Nullable<PersistenceType>(),
-                              OriginScope::FromNull(),
-                              /* aExclusive */ false)
-  , mParams(aParams.get_UsageParams())
-  , mGetGroupUsage(aParams.get_UsageParams().getGroupUsage())
-{
-  AssertIsOnOwningThread();
-  MOZ_ASSERT(aParams.type() == UsageRequestParams::TUsageParams);
-}
-
 bool
-GetUsageOp::Init(Quota* aQuota)
+QuotaUsageRequestBase::Init(Quota* aQuota)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aQuota);
 
-  mNeedsMainThreadInit = true;
   mNeedsQuotaManagerInit = true;
 
   return true;
 }
 
 nsresult
-GetUsageOp::DoInitOnMainThread()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-  MOZ_ASSERT(GetState() == State_Initializing);
-  MOZ_ASSERT(mNeedsMainThreadInit);
-
-  const PrincipalInfo& principalInfo = mParams.principalInfo();
-
-  nsresult rv;
-  nsCOMPtr<nsIPrincipal> principal =
-    PrincipalInfoToPrincipal(principalInfo, &rv);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  // Figure out which origin we're dealing with.
-  nsCString origin;
-  rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup,
-                                          &origin);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  mOriginScope.SetFromOrigin(origin);
-
-  return NS_OK;
-}
-
-nsresult
-GetUsageOp::AddToUsage(QuotaManager* aQuotaManager,
-                       PersistenceType aPersistenceType)
+QuotaUsageRequestBase::GetUsageForOrigin(QuotaManager* aQuotaManager,
+                                         PersistenceType aPersistenceType,
+                                         const nsACString& aGroup,
+                                         const nsACString& aOrigin,
+                                         UsageInfo* aUsageInfo)
 {
   AssertIsOnIOThread();
+  MOZ_ASSERT(aQuotaManager);
+  MOZ_ASSERT(aUsageInfo);
+  MOZ_ASSERT(aUsageInfo->TotalUsage() == 0);
 
   nsCOMPtr<nsIFile> directory;
   nsresult rv = aQuotaManager->GetDirectoryForOrigin(aPersistenceType,
-                                                     mOriginScope.GetOrigin(),
+                                                     aOrigin,
                                                      getter_AddRefs(directory));
   NS_ENSURE_SUCCESS(rv, rv);
 
   bool exists;
   rv = directory->Exists(&exists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If the directory exists then enumerate all the files inside, adding up
   // the sizes to get the final usage statistic.
-  if (exists && !mUsageInfo.Canceled()) {
+  if (exists && !mCanceled) {
     bool initialized;
 
     if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
-      initialized =
-        aQuotaManager->IsOriginInitialized(mOriginScope.GetOrigin());
+      initialized = aQuotaManager->IsOriginInitialized(aOrigin);
     } else {
       initialized = aQuotaManager->IsTemporaryStorageInitialized();
     }
 
     nsCOMPtr<nsISimpleEnumerator> entries;
     rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
     NS_ENSURE_SUCCESS(rv, rv);
 
     bool hasMore;
     while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
-           hasMore && !mUsageInfo.Canceled()) {
+           hasMore && !mCanceled) {
       nsCOMPtr<nsISupports> entry;
       rv = entries->GetNext(getter_AddRefs(entry));
       NS_ENSURE_SUCCESS(rv, rv);
 
       nsCOMPtr<nsIFile> file = do_QueryInterface(entry);
       NS_ENSURE_TRUE(file, NS_NOINTERFACE);
 
       bool isDirectory;
@@ -6557,44 +6598,319 @@ GetUsageOp::AddToUsage(QuotaManager* aQu
         continue;
       }
 
       Client* client = aQuotaManager->GetClient(clientType);
       MOZ_ASSERT(client);
 
       if (initialized) {
         rv = client->GetUsageForOrigin(aPersistenceType,
-                                       mGroup,
-                                       mOriginScope.GetOrigin(),
-                                       &mUsageInfo);
+                                       aGroup,
+                                       aOrigin,
+                                       mCanceled,
+                                       aUsageInfo);
       }
       else {
         rv = client->InitOrigin(aPersistenceType,
-                                mGroup,
-                                mOriginScope.GetOrigin(),
-                                &mUsageInfo);
+                                aGroup,
+                                aOrigin,
+                                mCanceled,
+                                aUsageInfo);
       }
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   return NS_OK;
 }
 
+void
+QuotaUsageRequestBase::SendResults()
+{
+  AssertIsOnOwningThread();
+
+  if (IsActorDestroyed()) {
+    if (NS_SUCCEEDED(mResultCode)) {
+      mResultCode = NS_ERROR_FAILURE;
+    }
+  } else {
+    if (mCanceled) {
+      mResultCode = NS_ERROR_FAILURE;
+    }
+
+    UsageRequestResponse response;
+
+    if (NS_SUCCEEDED(mResultCode)) {
+      GetResponse(response);
+    } else {
+      response = mResultCode;
+    }
+
+    Unused << PQuotaUsageRequestParent::Send__delete__(this, response);
+  }
+}
+
+void
+QuotaUsageRequestBase::ActorDestroy(ActorDestroyReason aWhy)
+{
+  AssertIsOnOwningThread();
+
+  NoteActorDestroyed();
+}
+
+mozilla::ipc::IPCResult
+QuotaUsageRequestBase::RecvCancel()
+{
+  AssertIsOnOwningThread();
+
+  if (mCanceled.exchange(true)) {
+    NS_WARNING("Canceled more than once?!");
+    return IPC_FAIL_NO_REASON(this);
+  }
+
+  return IPC_OK();
+}
+
+GetUsageOp::GetUsageOp(const UsageRequestParams& aParams)
+  : mGetAll(aParams.get_AllUsageParams().getAll())
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aParams.type() == UsageRequestParams::TAllUsageParams);
+}
+
+nsresult
+GetUsageOp::TraverseRepository(QuotaManager* aQuotaManager,
+                               PersistenceType aPersistenceType)
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(aQuotaManager);
+
+  nsresult rv;
+
+  nsCOMPtr<nsIFile> directory =
+    do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = directory->InitWithPath(aQuotaManager->GetStoragePath(aPersistenceType));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  bool exists;
+  rv = directory->Exists(&exists);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (!exists) {
+    return NS_OK;
+  }
+
+  nsCOMPtr<nsISimpleEnumerator> entries;
+  rv = directory->GetDirectoryEntries(getter_AddRefs(entries));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  bool persistent = aPersistenceType == PERSISTENCE_TYPE_PERSISTENT;
+
+  bool hasMore;
+  while (NS_SUCCEEDED((rv = entries->HasMoreElements(&hasMore))) &&
+         hasMore && !mCanceled) {
+    nsCOMPtr<nsISupports> entry;
+    rv = entries->GetNext(getter_AddRefs(entry));
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    nsCOMPtr<nsIFile> originDir = do_QueryInterface(entry);
+    MOZ_ASSERT(originDir);
+
+    bool isDirectory;
+    rv = originDir->IsDirectory(&isDirectory);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (!isDirectory) {
+      nsString leafName;
+      rv = originDir->GetLeafName(leafName);
+      if (NS_WARN_IF(NS_FAILED(rv))) {
+        return rv;
+      }
+
+      if (!IsOSMetadata(leafName)) {
+        UNKNOWN_FILE_WARNING(leafName);
+      }
+      continue;
+    }
+
+    int64_t timestamp;
+    bool persisted;
+    nsCString suffix;
+    nsCString group;
+    nsCString origin;
+    rv = aQuotaManager->GetDirectoryMetadata2WithRestore(originDir,
+                                                         persistent,
+                                                         &timestamp,
+                                                         &persisted,
+                                                         suffix,
+                                                         group,
+                                                         origin);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    if (!mGetAll && aQuotaManager->IsOriginInternal(origin)) {
+      continue;
+    }
+
+    OriginUsage* originUsage;
+
+    // We can't store pointers to OriginUsage objects in the hashtable
+    // since AppendElement() reallocates its internal array buffer as number
+    // of elements grows.
+    uint32_t index;
+    if (mOriginUsagesIndex.Get(origin, &index)) {
+      originUsage = &mOriginUsages[index];
+    } else {
+      index = mOriginUsages.Length();
+
+      originUsage = mOriginUsages.AppendElement();
+
+      originUsage->origin() = origin;
+      originUsage->persisted() = false;
+      originUsage->usage() = 0;
+
+      mOriginUsagesIndex.Put(origin, index);
+    }
+
+    if (aPersistenceType == PERSISTENCE_TYPE_DEFAULT) {
+      originUsage->persisted() = persisted;
+    }
+
+    UsageInfo usageInfo;
+    rv = GetUsageForOrigin(aQuotaManager,
+                           aPersistenceType,
+                           group,
+                           origin,
+                           &usageInfo);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    originUsage->usage() = originUsage->usage() + usageInfo.TotalUsage();
+  }
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  return NS_OK;
+}
+
 nsresult
 GetUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager)
 {
   AssertIsOnIOThread();
-  MOZ_ASSERT(mUsageInfo.TotalUsage() == 0);
 
   PROFILER_LABEL("Quota", "GetUsageOp::DoDirectoryWork",
                  js::ProfileEntry::Category::OTHER);
 
   nsresult rv;
 
+  for (const PersistenceType type : kAllPersistenceTypes) {
+    rv = TraverseRepository(aQuotaManager, type);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  }
+
+  return NS_OK;
+}
+
+void
+GetUsageOp::GetResponse(UsageRequestResponse& aResponse)
+{
+  AssertIsOnOwningThread();
+
+  aResponse = AllUsageResponse();
+
+  if (!mOriginUsages.IsEmpty()) {
+    nsTArray<OriginUsage>& originUsages =
+      aResponse.get_AllUsageResponse().originUsages();
+
+    mOriginUsages.SwapElements(originUsages);
+  }
+}
+
+GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams)
+  : mParams(aParams.get_OriginUsageParams())
+  , mGetGroupUsage(aParams.get_OriginUsageParams().getGroupUsage())
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aParams.type() == UsageRequestParams::TOriginUsageParams);
+}
+
+bool
+GetOriginUsageOp::Init(Quota* aQuota)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aQuota);
+
+  if (NS_WARN_IF(!QuotaUsageRequestBase::Init(aQuota))) {
+    return false;
+  }
+
+  mNeedsMainThreadInit = true;
+
+  return true;
+}
+
+nsresult
+GetOriginUsageOp::DoInitOnMainThread()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(GetState() == State_Initializing);
+  MOZ_ASSERT(mNeedsMainThreadInit);
+
+  const PrincipalInfo& principalInfo = mParams.principalInfo();
+
+  nsresult rv;
+  nsCOMPtr<nsIPrincipal> principal =
+    PrincipalInfoToPrincipal(principalInfo, &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  // Figure out which origin we're dealing with.
+  nsCString origin;
+  rv = QuotaManager::GetInfoFromPrincipal(principal, &mSuffix, &mGroup,
+                                          &origin);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  mOriginScope.SetFromOrigin(origin);
+
+  return NS_OK;
+}
+
+nsresult
+GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager)
+{
+  AssertIsOnIOThread();
+  MOZ_ASSERT(mUsageInfo.TotalUsage() == 0);
+
+  PROFILER_LABEL("Quota", "GetOriginUsageOp::DoDirectoryWork",
+                 js::ProfileEntry::Category::OTHER);
+
+  nsresult rv;
+
   if (mGetGroupUsage) {
     nsCOMPtr<nsIFile> directory;
 
     // Ensure origin is initialized first. It will initialize all origins for
     // temporary storage including origins belonging to our group.
     rv = aQuotaManager->EnsureOriginIsInitialized(PERSISTENCE_TYPE_TEMPORARY,
                                                   mSuffix, mGroup,
                                                   mOriginScope.GetOrigin(),
@@ -6606,82 +6922,50 @@ GetUsageOp::DoDirectoryWork(QuotaManager
     // Get cached usage and limit (the method doesn't have to stat any files).
     aQuotaManager->GetGroupUsageAndLimit(mGroup, &mUsageInfo);
 
     return NS_OK;
   }
 
   // Add all the persistent/temporary/default storage files we care about.
   for (const PersistenceType type : kAllPersistenceTypes) {
-    rv = AddToUsage(aQuotaManager, type);
+    UsageInfo usageInfo;
+    rv = GetUsageForOrigin(aQuotaManager,
+                           type,
+                           mGroup,
+                           mOriginScope.GetOrigin(),
+                           &usageInfo);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
+
+    mUsageInfo.Append(usageInfo);
   }
 
   return NS_OK;
 }
 
 void
-GetUsageOp::SendResults()
+GetOriginUsageOp::GetResponse(UsageRequestResponse& aResponse)
 {
   AssertIsOnOwningThread();
 
-  if (IsActorDestroyed()) {
-    if (NS_SUCCEEDED(mResultCode)) {
-      mResultCode = NS_ERROR_FAILURE;
-    }
+  OriginUsageResponse usageResponse;
+
+  // We'll get the group usage when mGetGroupUsage is true and get the
+  // origin usage when mGetGroupUsage is false.
+  usageResponse.usage() = mUsageInfo.TotalUsage();
+
+  if (mGetGroupUsage) {
+    usageResponse.limit() = mUsageInfo.Limit();
   } else {
-    if (mUsageInfo.Canceled()) {
-      mResultCode = NS_ERROR_FAILURE;
-    }
-
-    UsageRequestResponse response;
-
-    if (NS_SUCCEEDED(mResultCode)) {
-      UsageResponse usageResponse;
-
-      // We'll get the group usage when mGetGroupUsage is true and get the
-      // origin usage when mGetGroupUsage is false.
-      usageResponse.usage() = mUsageInfo.TotalUsage();
-
-      if (mGetGroupUsage) {
-        usageResponse.limit() = mUsageInfo.Limit();
-      } else {
-        usageResponse.fileUsage() = mUsageInfo.FileUsage();
-      }
-
-      response = usageResponse;
-    } else {
-      response = mResultCode;
-    }
-
-    Unused << PQuotaUsageRequestParent::Send__delete__(this, response);
-  }
-}
-
-void
-GetUsageOp::ActorDestroy(ActorDestroyReason aWhy)
-{
-  AssertIsOnOwningThread();
-
-  NoteActorDestroyed();
-}
-
-mozilla::ipc::IPCResult
-GetUsageOp::RecvCancel()
-{
-  AssertIsOnOwningThread();
-
-  nsresult rv = mUsageInfo.Cancel();
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return IPC_FAIL_NO_REASON(this);
-  }
-
-  return IPC_OK();
+    usageResponse.fileUsage() = mUsageInfo.FileUsage();
+  }
+
+  aResponse = usageResponse;
 }
 
 bool
 QuotaRequestBase::Init(Quota* aQuota)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aQuota);
 
@@ -8180,19 +8464,17 @@ CreateOrUpgradeDirectoryMetadataHelper::
       if (NS_FAILED(rv)) {
         originProps.mTimestamp = GetLastModifiedTime(originDir, mPersistent);
         originProps.mNeedsRestore = true;
       } else if (!isApp.IsNull()) {
         originProps.mIgnore = true;
       }
     }
     else {
-      bool persistent =
-        QuotaManager::IsOriginWhitelistedForPersistentStorage(
-                                                             originProps.mSpec);
+      bool persistent = QuotaManager::IsOriginInternal(originProps.mSpec);
       originProps.mTimestamp = GetLastModifiedTime(originDir, persistent);
     }
 
     mOriginProps.AppendElement(Move(originProps));
   }
 
   if (mOriginProps.IsEmpty()) {
     return NS_OK;
@@ -8326,19 +8608,18 @@ CreateOrUpgradeDirectoryMetadataHelper::
                                  aOriginProps.mTimestamp,
                                  aOriginProps.mSuffix,
                                  aOriginProps.mGroup,
                                  aOriginProps.mOrigin);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
-    // Move whitelisted origins to new persistent storage.
-    if (QuotaManager::IsOriginWhitelistedForPersistentStorage(
-                                                          aOriginProps.mSpec)) {
+    // Move internal origins to new persistent storage.
+    if (QuotaManager::IsOriginInternal(aOriginProps.mSpec)) {
       if (!mPermanentStorageDir) {
         mPermanentStorageDir =
           do_CreateInstance(NS_LOCAL_FILE_CONTRACTID, &rv);
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
 
         QuotaManager* quotaManager = QuotaManager::Get();
--- a/dom/quota/Client.h
+++ b/dom/quota/Client.h
@@ -26,16 +26,18 @@ class QuotaManager;
 class UsageInfo;
 
 // An abstract interface for quota manager clients.
 // Each storage API must provide an implementation of this interface in order
 // to participate in centralized quota and storage handling.
 class Client
 {
 public:
+  typedef mozilla::Atomic<bool> AtomicBool;
+
   NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
 
   enum Type {
     IDB = 0,
     //LS,
     //APPCACHE,
     ASMJS,
     DOMCACHE,
@@ -95,22 +97,24 @@ public:
   {
     return NS_OK;
   }
 
   virtual nsresult
   InitOrigin(PersistenceType aPersistenceType,
              const nsACString& aGroup,
              const nsACString& aOrigin,
+             const AtomicBool& aCanceled,
              UsageInfo* aUsageInfo) = 0;
 
   virtual nsresult
   GetUsageForOrigin(PersistenceType aPersistenceType,
                     const nsACString& aGroup,
                     const nsACString& aOrigin,
+                    const AtomicBool& aCanceled,
                     UsageInfo* aUsageInfo) = 0;
 
   virtual void
   OnOriginClearCompleted(PersistenceType aPersistenceType,
                          const nsACString& aOrigin) = 0;
 
   virtual void
   ReleaseIOThreadObjects() = 0;
--- a/dom/quota/PQuota.ipdl
+++ b/dom/quota/PQuota.ipdl
@@ -22,25 +22,31 @@ struct InitParams
 };
 
 struct InitOriginParams
 {
   PrincipalInfo principalInfo;
   PersistenceType persistenceType;
 };
 
-struct UsageParams
+struct AllUsageParams
+{
+  bool getAll;
+};
+
+struct OriginUsageParams
 {
   PrincipalInfo principalInfo;
   bool getGroupUsage;
 };
 
 union UsageRequestParams
 {
-  UsageParams;
+  AllUsageParams;
+  OriginUsageParams;
 };
 
 struct ClearOriginParams
 {
   PrincipalInfo principalInfo;
   PersistenceType persistenceType;
   bool persistenceTypeIsExplicit;
   bool clearAll;
--- a/dom/quota/PQuotaUsageRequest.ipdl
+++ b/dom/quota/PQuotaUsageRequest.ipdl
@@ -3,27 +3,40 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 include protocol PQuota;
 
 namespace mozilla {
 namespace dom {
 namespace quota {
 
-struct UsageResponse
+struct OriginUsage
+{
+  nsCString origin;
+  bool persisted;
+  uint64_t usage;
+};
+
+struct AllUsageResponse
+{
+  OriginUsage[] originUsages;
+};
+
+struct OriginUsageResponse
 {
   uint64_t usage;
   uint64_t fileUsage;
   uint64_t limit;
 };
 
 union UsageRequestResponse
 {
   nsresult;
-  UsageResponse;
+  AllUsageResponse;
+  OriginUsageResponse;
 };
 
 protocol PQuotaUsageRequest
 {
   manager PQuota;
 
 parent:
   async Cancel();
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -393,17 +393,17 @@ public:
                     nsACString* aOrigin);
 
   static void
   GetInfoForChrome(nsACString* aSuffix,
                    nsACString* aGroup,
                    nsACString* aOrigin);
 
   static bool
-  IsOriginWhitelistedForPersistentStorage(const nsACString& aOrigin);
+  IsOriginInternal(const nsACString& aOrigin);
 
   static void
   ChromeOrigin(nsACString& aOrigin);
 
   static bool
   AreOriginsEqualOnDisk(nsACString& aOrigin1,
                         nsACString& aOrigin2);
 
--- a/dom/quota/QuotaManagerService.cpp
+++ b/dom/quota/QuotaManagerService.cpp
@@ -580,28 +580,53 @@ QuotaManagerService::InitStoragesForPrin
     return rv;
   }
 
   request.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+QuotaManagerService::GetUsage(nsIQuotaUsageCallback* aCallback,
+                              bool aGetAll,
+                              nsIQuotaUsageRequest** _retval)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MOZ_ASSERT(aCallback);
+
+  RefPtr<UsageRequest> request = new UsageRequest(aCallback);
+
+  AllUsageParams params;
+
+  params.getAll() = aGetAll;
+
+  nsAutoPtr<PendingRequestInfo> info(new UsageRequestInfo(request, params));
+
+  nsresult rv = InitiateRequest(info);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  request.forget(_retval);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
 QuotaManagerService::GetUsageForPrincipal(nsIPrincipal* aPrincipal,
                                           nsIQuotaUsageCallback* aCallback,
                                           bool aGetGroupUsage,
                                           nsIQuotaUsageRequest** _retval)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(aCallback);
 
   RefPtr<UsageRequest> request = new UsageRequest(aPrincipal, aCallback);
 
-  UsageParams params;
+  OriginUsageParams params;
 
   nsresult rv = CheckedPrincipalToPrincipalInfo(aPrincipal,
                                                 params.principalInfo());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   params.getGroupUsage() = aGetGroupUsage;
--- a/dom/quota/QuotaRequests.cpp
+++ b/dom/quota/QuotaRequests.cpp
@@ -86,23 +86,29 @@ RequestBase::GetResultCode(nsresult* aRe
   if (!mHaveResultOrErrorCode) {
     return NS_ERROR_FAILURE;
   }
 
   *aResultCode = mResultCode;
   return NS_OK;
 }
 
+UsageRequest::UsageRequest(nsIQuotaUsageCallback* aCallback)
+  : mCallback(aCallback)
+  , mBackgroundActor(nullptr)
+  , mCanceled(false)
+{
+  AssertIsOnOwningThread();
+  MOZ_ASSERT(aCallback);
+}
+
 UsageRequest::UsageRequest(nsIPrincipal* aPrincipal,
                            nsIQuotaUsageCallback* aCallback)
   : RequestBase(aPrincipal)
   , mCallback(aCallback)
-  , mUsage(0)
-  , mFileUsage(0)
-  , mLimit(0)
   , mBackgroundActor(nullptr)
   , mCanceled(false)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aPrincipal);
   MOZ_ASSERT(aCallback);
 }
 
@@ -121,76 +127,51 @@ UsageRequest::SetBackgroundActor(QuotaUs
   mBackgroundActor = aBackgroundActor;
 
   if (mCanceled) {
     mBackgroundActor->SendCancel();
   }
 }
 
 void
-UsageRequest::SetResult(uint64_t aUsage, uint64_t aFileUsage, uint64_t aLimit)
+UsageRequest::SetResult(nsIVariant* aResult)
 {
   AssertIsOnOwningThread();
+  MOZ_ASSERT(aResult);
   MOZ_ASSERT(!mHaveResultOrErrorCode);
 
-  mUsage = aUsage;
-  mFileUsage = aFileUsage;
-  mLimit = aLimit;
+  mResult = aResult;
+
   mHaveResultOrErrorCode = true;
 
   FireCallback();
 }
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(UsageRequest, RequestBase, mCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(UsageRequest)
   NS_INTERFACE_MAP_ENTRY(nsIQuotaUsageRequest)
 NS_INTERFACE_MAP_END_INHERITING(RequestBase)
 
 NS_IMPL_ADDREF_INHERITED(UsageRequest, RequestBase)
 NS_IMPL_RELEASE_INHERITED(UsageRequest, RequestBase)
 
 NS_IMETHODIMP
-UsageRequest::GetUsage(uint64_t* aUsage)
+UsageRequest::GetResult(nsIVariant** aResult)
 {
   AssertIsOnOwningThread();
+  MOZ_ASSERT(aResult);
 
   if (!mHaveResultOrErrorCode) {
     return NS_ERROR_FAILURE;
   }
 
-  *aUsage = mUsage;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-UsageRequest::GetFileUsage(uint64_t* aFileUsage)
-{
-  AssertIsOnOwningThread();
-  MOZ_ASSERT(aFileUsage);
-
-  if (!mHaveResultOrErrorCode) {
-    return NS_ERROR_FAILURE;
-  }
+  MOZ_ASSERT(mResult);
 
-  *aFileUsage = mFileUsage;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-UsageRequest::GetLimit(uint64_t* aLimit)
-{
-  AssertIsOnOwningThread();
-  MOZ_ASSERT(aLimit);
-
-  if (!mHaveResultOrErrorCode) {
-    return NS_ERROR_FAILURE;
-  }
-
-  *aLimit = mLimit;
+  NS_ADDREF(*aResult = mResult);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 UsageRequest::GetCallback(nsIQuotaUsageCallback** aCallback)
 {
   AssertIsOnOwningThread();
   MOZ_ASSERT(aCallback);
--- a/dom/quota/QuotaRequests.h
+++ b/dom/quota/QuotaRequests.h
@@ -67,43 +67,41 @@ protected:
 };
 
 class UsageRequest final
   : public RequestBase
   , public nsIQuotaUsageRequest
 {
   nsCOMPtr<nsIQuotaUsageCallback> mCallback;
 
-  uint64_t mUsage;
-  uint64_t mFileUsage;
-
-  // Group Limit.
-  uint64_t mLimit;
+  nsCOMPtr<nsIVariant> mResult;
 
   QuotaUsageRequestChild* mBackgroundActor;
 
   bool mCanceled;
 
 public:
+  explicit UsageRequest(nsIQuotaUsageCallback* aCallback);
+
   UsageRequest(nsIPrincipal* aPrincipal,
                nsIQuotaUsageCallback* aCallback);
 
   void
   SetBackgroundActor(QuotaUsageRequestChild* aBackgroundActor);
 
   void
   ClearBackgroundActor()
   {
     AssertIsOnOwningThread();
 
     mBackgroundActor = nullptr;
   }
 
   void
-  SetResult(uint64_t aUsage, uint64_t aFileUsage, uint64_t aLimit);
+  SetResult(nsIVariant* aResult);
 
   NS_DECL_ISUPPORTS_INHERITED
   NS_FORWARD_NSIQUOTAREQUESTBASE(RequestBase::)
   NS_DECL_NSIQUOTAUSAGEREQUEST
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(UsageRequest, RequestBase)
 
 private:
   ~UsageRequest();
new file mode 100644
--- /dev/null
+++ b/dom/quota/QuotaResults.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "QuotaResults.h"
+
+namespace mozilla {
+namespace dom {
+namespace quota {
+
+UsageResult::UsageResult(const nsACString& aOrigin,
+                         bool aPersisted,
+                         uint64_t aUsage)
+  : mOrigin(aOrigin)
+  , mUsage(aUsage)
+  , mPersisted(aPersisted)
+{
+}
+
+NS_IMPL_ISUPPORTS(UsageResult,
+                  nsIQuotaUsageResult)
+
+NS_IMETHODIMP
+UsageResult::GetOrigin(nsACString& aOrigin)
+{
+  aOrigin = mOrigin;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UsageResult::GetPersisted(bool* aPersisted)
+{
+  MOZ_ASSERT(aPersisted);
+
+  *aPersisted = mPersisted;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+UsageResult::GetUsage(uint64_t* aUsage)
+{
+  MOZ_ASSERT(aUsage);
+
+  *aUsage = mUsage;
+  return NS_OK;
+}
+
+OriginUsageResult::OriginUsageResult(uint64_t aUsage,
+                                     uint64_t aFileUsage,
+                                     uint64_t aLimit)
+  : mUsage(aUsage)
+  , mFileUsage(aFileUsage)
+  , mLimit(aLimit)
+{
+}
+
+NS_IMPL_ISUPPORTS(OriginUsageResult,
+                  nsIQuotaOriginUsageResult)
+
+NS_IMETHODIMP
+OriginUsageResult::GetUsage(uint64_t* aUsage)
+{
+  MOZ_ASSERT(aUsage);
+
+  *aUsage = mUsage;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+OriginUsageResult::GetFileUsage(uint64_t* aFileUsage)
+{
+  MOZ_ASSERT(aFileUsage);
+
+  *aFileUsage = mFileUsage;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+OriginUsageResult::GetLimit(uint64_t* aLimit)
+{
+  MOZ_ASSERT(aLimit);
+
+  *aLimit = mLimit;
+  return NS_OK;
+}
+
+} // namespace quota
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/quota/QuotaResults.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_quota_QuotaResults_h
+#define mozilla_dom_quota_QuotaResults_h
+
+#include "nsIQuotaResults.h"
+
+namespace mozilla {
+namespace dom {
+namespace quota {
+
+class UsageResult
+  : public nsIQuotaUsageResult
+{
+  nsCString mOrigin;
+  uint64_t mUsage;
+  bool mPersisted;
+
+public:
+  UsageResult(const nsACString& aOrigin,
+              bool aPersisted,
+              uint64_t aUsage);
+
+private:
+  virtual ~UsageResult()
+  { }
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIQUOTAUSAGERESULT
+};
+
+class OriginUsageResult
+  : public nsIQuotaOriginUsageResult
+{
+  uint64_t mUsage;
+  uint64_t mFileUsage;
+  uint64_t mLimit;
+
+public:
+  OriginUsageResult(uint64_t aUsage,
+                    uint64_t aFileUsage,
+                    uint64_t aLimit);
+
+private:
+  virtual ~OriginUsageResult()
+  { }
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIQUOTAORIGINUSAGERESULT
+};
+
+} // namespace quota
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_quota_QuotaResults_h
--- a/dom/quota/StorageManager.cpp
+++ b/dom/quota/StorageManager.cpp
@@ -128,30 +128,41 @@ GetUsageForPrincipal(nsIPrincipal* aPrin
 };
 
 nsresult
 GetStorageEstimate(nsIQuotaUsageRequest* aRequest,
                    StorageEstimate& aStorageEstimate)
 {
   MOZ_ASSERT(aRequest);
 
-  uint64_t usage;
-  nsresult rv = aRequest->GetUsage(&usage);
+  nsCOMPtr<nsIVariant> result;
+  nsresult rv = aRequest->GetResult(getter_AddRefs(result));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  nsID* iid;
+  nsCOMPtr<nsISupports> supports;
+  rv = result->GetAsInterface(&iid, getter_AddRefs(supports));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
-  uint64_t limit;
-  rv = aRequest->GetLimit(&limit);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
+  free(iid);
+
+  nsCOMPtr<nsIQuotaOriginUsageResult> originUsageResult =
+    do_QueryInterface(supports);
+  MOZ_ASSERT(originUsageResult);
 
-  aStorageEstimate.mUsage.Construct() = usage;
-  aStorageEstimate.mQuota.Construct() = limit;
+  MOZ_ALWAYS_SUCCEEDS(
+    originUsageResult->GetUsage(&aStorageEstimate.mUsage.Construct()));
+
+  MOZ_ALWAYS_SUCCEEDS(
+    originUsageResult->GetLimit(&aStorageEstimate.mQuota.Construct()));
+
   return NS_OK;
 }
 
 } // namespace
 
 /*******************************************************************************
  * Local class implementations
  ******************************************************************************/
--- a/dom/quota/UsageInfo.h
+++ b/dom/quota/UsageInfo.h
@@ -13,36 +13,29 @@
 #include "mozilla/CheckedInt.h"
 
 BEGIN_QUOTA_NAMESPACE
 
 class UsageInfo
 {
 public:
   UsageInfo()
-  : mCanceled(false), mDatabaseUsage(0), mFileUsage(0), mLimit(0)
+    : mDatabaseUsage(0)
+    , mFileUsage(0)
+    , mLimit(0)
   { }
 
   virtual ~UsageInfo()
   { }
 
-  bool
-  Canceled()
+  void
+  Append(const UsageInfo& aUsageInfo)
   {
-    return mCanceled;
-  }
-
-  nsresult
-  Cancel()
-  {
-    if (mCanceled.exchange(true)) {
-      NS_WARNING("Canceled more than once?!");
-      return NS_ERROR_UNEXPECTED;
-    }
-    return NS_OK;
+    IncrementUsage(&mDatabaseUsage, aUsageInfo.mDatabaseUsage);
+    IncrementUsage(&mFileUsage, aUsageInfo.mFileUsage);
   }
 
   void
   AppendToDatabaseUsage(uint64_t aUsage)
   {
     IncrementUsage(&mDatabaseUsage, aUsage);
   }
 
@@ -99,19 +92,16 @@ public:
     value += aDelta;
     if (value.isValid()) {
       *aUsage = value.value();
     } else {
       *aUsage = UINT64_MAX;
     }
   }
 
-protected:
-  mozilla::Atomic<bool> mCanceled;
-
 private:
   uint64_t mDatabaseUsage;
   uint64_t mFileUsage;
   uint64_t mLimit;
 };
 
 END_QUOTA_NAMESPACE
 
--- a/dom/quota/moz.build
+++ b/dom/quota/moz.build
@@ -10,16 +10,17 @@ with Files("**"):
 XPCSHELL_TESTS_MANIFESTS += [
     'test/unit/xpcshell.ini'
 ]
 
 XPIDL_SOURCES += [
     'nsIQuotaCallbacks.idl',
     'nsIQuotaManagerService.idl',
     'nsIQuotaRequests.idl',
+    'nsIQuotaResults.idl',
 ]
 
 XPIDL_MODULE = 'dom_quota'
 
 EXPORTS.mozilla.dom += [
   'StorageManager.h',
 ]
 
@@ -38,16 +39,17 @@ EXPORTS.mozilla.dom.quota += [
 ]
 
 UNIFIED_SOURCES += [
     'ActorsChild.cpp',
     'ActorsParent.cpp',
     'FileStreams.cpp',
     'QuotaManagerService.cpp',
     'QuotaRequests.cpp',
+    'QuotaResults.cpp',
     'StorageManager.cpp',
 ]
 
 IPDL_SOURCES += [
     'PQuota.ipdl',
     'PQuotaRequest.ipdl',
     'PQuotaUsageRequest.ipdl',
 ]
--- a/dom/quota/nsIQuotaManagerService.idl
+++ b/dom/quota/nsIQuotaManagerService.idl
@@ -37,16 +37,31 @@ interface nsIQuotaManagerService : nsISu
    *        A string that tells what persistence type of storages will be
    *        initialized.
    */
   [must_use] nsIQuotaRequest
   initStoragesForPrincipal(in nsIPrincipal aPrincipal,
                            in ACString aPersistenceType);
 
   /**
+   * Schedules an asynchronous callback that will inspect all origins and
+   * return the total amount of disk space being used by storages for each
+   * origin separately.
+   *
+   * @param aCallback
+   *        The callback that will be called when the usage is available.
+   * @param aGetAll
+   *        An optional boolean to indicate inspection of all origins,
+   *        including internal ones.
+   */
+  [must_use] nsIQuotaUsageRequest
+  getUsage(in nsIQuotaUsageCallback aCallback,
+           [optional] in boolean aGetAll);
+
+  /**
    * Schedules an asynchronous callback that will return the total amount of
    * disk space being used by storages for the given origin.
    *
    * @param aPrincipal
    *        A principal for the origin whose usage is being queried.
    * @param aCallback
    *        The callback that will be called when the usage is available.
    * @param aGetGroupUsage
--- a/dom/quota/nsIQuotaRequests.idl
+++ b/dom/quota/nsIQuotaRequests.idl
@@ -17,27 +17,29 @@ interface nsIQuotaRequestBase : nsISuppo
   readonly attribute nsIPrincipal principal;
 
   [must_use] readonly attribute nsresult resultCode;
 };
 
 [scriptable, uuid(166e28e6-cf6d-4927-a6d7-b51bca9d3469)]
 interface nsIQuotaUsageRequest : nsIQuotaRequestBase
 {
-  [must_use] readonly attribute unsigned long long usage;
-
-  [must_use] readonly attribute unsigned long long fileUsage;
-
-  [must_use] readonly attribute unsigned long long limit;
+  // The result can contain one of these types:
+  //   array of nsIQuotaUsageResult
+  //   nsIQuotaOriginUsageResult
+  [must_use] readonly attribute nsIVariant result;
 
   attribute nsIQuotaUsageCallback callback;
 
   [must_use] void
   cancel();
 };
 
 [scriptable, uuid(22890e3e-ff25-4372-9684-d901060e2f6c)]
 interface nsIQuotaRequest : nsIQuotaRequestBase
 {
+  // The result can contain one of these types:
+  //   void
+  //   bool
   [must_use] readonly attribute nsIVariant result;
 
   attribute nsIQuotaCallback callback;
 };
new file mode 100644
--- /dev/null
+++ b/dom/quota/nsIQuotaResults.idl
@@ -0,0 +1,27 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set 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/. */
+
+#include "nsISupports.idl"
+
+[scriptable, function, uuid(d8c9328b-9aa8-4f5d-90e6-482de4a6d5b8)]
+interface nsIQuotaUsageResult : nsISupports
+{
+  readonly attribute ACString origin;
+
+  readonly attribute boolean persisted;
+
+  readonly attribute unsigned long long usage;
+};
+
+[scriptable, function, uuid(96df03d2-116a-493f-bb0b-118c212a6b32)]
+interface nsIQuotaOriginUsageResult : nsISupports
+{
+  readonly attribute unsigned long long usage;
+
+  readonly attribute unsigned long long fileUsage;
+
+  readonly attribute unsigned long long limit;
+};
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5144112bde351703f42ab87f817421af09cdae53
GIT binary patch
literal 24717
zc%1EAcRZEv`>&)WDvC-}vX7Bnh$MRp(XjVAvSoc5l$1SEC|MDqW6Ma$CVNv>c1C80
z-;wnk&N&|a`s4eD)9b0{QC;urzV7Q>@B97SLs|@L_kkUYpE_wt(H(%#z8$A_n3+RO
z)pWEN<>mJ8zzQvVqd0=NEUa;M?A-lp=Z+n_k0Sn^G+GPz01GBsrbcSUTE^y^+B*6N
z`<k(dXr`Wfg%;wkJa_HbaS&lk!&FPnTuVh$ok8F1j}?+9#fpp9IxD`Oe9-3e2c1Ud
zk3E!<lvW%_;y(m=GL(Ew*Y>0{pQrB22XyK9t>pA$?Ls&r^?0pnLbC27_F<*zyQYs$
zbyzo1_3zzT-0{^LcAxYi-=2prZ3qfKvAO%HzdQG!&|K}Qn64A)*U<~6rSy?);sOJ%
zHQZ|IW^E4VYn$Y1LnY2U@5T`nSGe#=D+-Do*%HH}AkQI0m3If8u5!uX%{9k+7oB4G
z+mm)mpQhQxMZBk6_ElydG^N?Hi|W8922IDz@8xdSauga3?59KeB7Jm)YJBdhO*e+N
z=rn80LFxtg6FMX2+10`t9;B#quxq@(-p%&<a_%D~q1yXzzL3lgyz`T9rz@a+;QgjH
zweezUiR=sdqdFfu<5D3R?Zcsv2;1BaH3gU(*=!Zd9ygd+Z6DK1ikpnPTYULrJJJk)
zGX_=!8siHHdE-8NKNDHmS9{`P<vhp8TpslKPCTcVWZmB+GyNBM<+69Kb(MmFiRcK<
z%P6MBK1XyF-deXanB6hdGuQglSq~l-D=uE^ItvGHqKHmJUbuv@Sb|RGytb;ks-~ui
zw6rSX^H9Czzx{D^Sc=)Ck$V{L=nH*9$~P8$6Qq1Q49GW4Ep0Um!{uyKyI-uhc%jW)
zj&+uRnQN|PWP-RewOO*Ihp?lE$(FAHvaJ&+zXck)rck5hFV+kqDl;1+vlih+lfUP}
zqX`jDB#4U)lSu|6Eps(ZHFGsgwl!3LrH9OZ9U;cT!n$cHDC1yEi;uGo@oR<!?;;{C
z;-UbBNN>pu4)mm|SUGiZg@l0mP7IMF!33(OslI9SP@Co1%q%Mt2h;fr?9A*e=4M*@
zW(<g$qobpyWo9nVpsi=9WwwMni@==Stk)KtkKFRujd;xY|KS3@M`&<|TH1}96i)3m
z;UZ@um#B9=o2(EZc~k()g);W8yoI-5?!9=K>Jy>lFDbinMEc!$N!V+vxODF(q%@GK
z64^dz8$7|T=U+{#3XRv$$XS@KwyY(bfK%@->9ulmL|puI0yK_FH4=j5O+gXbUbeZo
zYI-8mPY?4QCi|Vl@YLvM{RcC{AflOi_XkrhWVyz4dKN8@^PC18l^son+<&Rm85d;v
zDaXzy&3-PfDB%@w=$6>Aa5}S@xGL6mRM)Y3@JDZNj9CPSV$xjV`+%5!PK(!-Peom#
zkB-?ydw5WL6-9jvAEP$F_S58Y?h-u^67YckjgMR5*R#GZ;_jAQgE4i($>L))Y5bFV
zS!cZI=w;g&BYjBm?vANC;b)d>h~^KzS9ZMoHgG8DmbbB1awwdj_rp*%RgAWR4dsob
z@{@*v9`Ew~;axoC<bj&g<hMf3nkC@F#6s$EWvL0$!tm2%={U`3$JOxUzSrno=nKoZ
z-sC3LXg2VrZYV7?^)xdFG@<upa}9Q}r%Vr&M~YN0w)bXz4x3=HQg2exKupTPIwqAk
z!ZsdB`U9o`wEcrK*^Q@SAIGQJAM?f^O>Gc+-lX?H$*9i2{<)oYw(#DR%U&b%_hV!Y
z7~FkwKR-3SlJ%NOk2&4ZIrj5I+04$jK5qwI;B$B1m1m74PmHAhuBsb-jaQMlhxe;)
zeWJ4&&tX`PrmP2S;&~~{L-|jaPf4}&)D7r;ANHDzDM=a3)swuK@{z0V_8`$|VOe#k
zl$}!20AZ?f$JNqnUoV?^9URB;`C9aNkVtIqy|-kWbK`LQPvfkBnY};7%k;%E>e-~@
z<(isY6FvMh%V^$Io?`U1yIhhL7V|jl*tdaxu}dC$4IY-ByGVvqvlOs@#mmXW+J<=y
z*?*v=7`v(NSS_jAuY7_-@Y0-N&mP-HTm$f9Gzm!*S*(LWY+04l!efKsj%oxFO=PgC
z1_R?a9kMFEw`&)yl|&7puKssym2SarKYADJbVo(QP1d=lJsbBK-(|lZX5a7UbtjZw
zS81?G3|{IZ{sJQpsSZ*uae1c}_aIxg{c2cVYsPm9v+Ko4)}L4)Y8GaU903#GSTbVh
zV~Yl>ti^8IM+dmWds}(^_?`7Fi6hEyX!nwZeNEfD$MrR_e5^sT5QkutT-b@mV{pRS
z;UPK^mmrda>?3dE=B#bhC8(}fmn%VQIb({h@Kg#BkCdO%lK2IEBCBq8?W4~icdWfl
z^oh`^$5h$h8p8}!N3M*w`%d^RJgHFpQrR3E6~NB=xhq8~w%JHQBIpngi=u(vGuK|j
za$Ox=en%eq1}pD|LnGr3SW5-$KZxG5?7S%lf@z}Vl6H$;q;K+3LalC|rnAx|9qs(e
z^2T9;(8<(lV`jDP@ph|u9=Ncz)`Cp7NoTg?%KvJk;9giZNyjrVvM~Dl(9%<U!_U>*
z>CJB!7IyAH`n=C_1k_)@b@lfg$~vfPZf*jBKn$T8YKFQ{vt{P~jVN@#F%{WG<IN@I
zDd(1niVmD{WRgUKvcy*j^M?^6sUzuNsxB$$aA&{AIS(0GS=I13_rqB09C;C~QcZ?<
z;y_%CTXbZFJ2&;^WJhU{lw@g9AtS?1)7{LXq6cCoejQQA5O6ARuB<XDhM+G2_^$&H
z1`hy^Tj2<FIHqo2^dN{}An(O8xBeRs04$5fgQ1oRNn)W>dw<?O7=wGZETmALER1ho
zt=~cNG8zd;Z3k1TMP1)r`q%PW^w$4LJd;3_>Mrd^r|u3BBp#~dZ$INtY8zLhAs<zr
z#ivtm09$w(6ei>P3%>8OelG_sd!~#|o5FRhSHPRaw8k*#WMGTGvB<S+Ra6g!y^a#Z
z+4NQ2x0cBGGHIh^2d|vFC?|eHDs0dVCqbaE=QPLZwrTtM-n3>HMqhuJW4Qyzc=d#P
zg348boCP5rBfc~<N2a#h-|5GvpC`GMa=uHh(BGpYUlB$BOxr@#JT^X4f(`$Ozz3V#
ziE^a9gE?OPc^-Bm=U6k6_!Fxb8e2nXW%`Eix{{EvH{(k3P+ApHwlcgW7jl)GC@}~Z
z$_yq`49$yic`nP8Vq8axAKk+_$Kk`(=xc4&o@qGVv7f6;-qS@UHi0ukys#R-(82n&
z6}~aEI(~5F<Fp2si{a-D2x)v=ZdAG4pdoC%=$n83Cg+`jnpft<&5+K#$e=U}g7NZ}
zVBW{iUuHLSmJJnS7kl&d#PLcU(TnRPuFqi+Y`Wc>_HDqBov!YCoC1#H=@dfjByl$T
ziQg(vH_NLvEm^|UMfn10-dzQJL5)U}23fD{EMda7DVIeD=kG^fvt@8k$_<T4mf{JW
zJHedlI2#LpSQV6+>J?*H*t%Ccv>?lfqZHcoy=wAK9G=v(^b0aj(vucbcGTMCWnr&-
zevqEf*_UxY<br3GnPDAsUNc4KP5-#YwB|rds0}nGrJ<tznon1O^Y1tPHT340l`aqC
z-h}iV?dv6?4Sji}k<O3(5>@L*`ZmLaAIA3ru=oCyC^Igxu4j{rH!o;&O^lD7eOY}q
z)JBHZ!qpE;r11z17g;5n$6e~`w`YUMoH#i@smC6em5h4RJSBX#enwY8#F(+9m4fOX
zWU5$8qa~$6&^SIN71kCc<5f~JhEvk0<WH2&Eo*1nr_ylsb8_L2OOsDtQh%(e*Sc=e
z{z}0M0vXGH1EUL`5B{vwo@*V)BuI0v|8$G90^=E>@kY^v)2!Bvm3_g%XUl^RKJC2e
zRoJI|yCme@w;29-S(SXBu1wo8>~V!+nDsXn78#3i296VxJuK-lxSc*1!$<wo?`r?_
z?ywn&>wX*}*=%9_VGlG&h&6rcGW3Y}JN-l(GZPITQGplom%c)!hsyhXyl&n0&A<tn
zz3U$NsLtG)Ehw<8K+QGi!()z#PX!rVf=bn`%^$pO-SA>ON+o5hLVCQeL#NbVWx=qR
zCEhV4zg<-OoOOO=j8;Hdfp0(^uB&TvZ+t6Htm(CbJj@Nc$A69M7?$c<>6X}8%A0gh
z-XU%K0^hS-*y^hSt&2u})4DJ&{~#5QN4l;KA2xbihcJ$mMLFTAM)G_f=eOU3pP%9O
z@}HrSa1~>DHJ>~?HRUM67<A~DSjzlB-ZDLQ80C)hF5TvI!FU(kdmWbvy~ug(_R*%d
z3k!#k`PKvu$6Bk-q3fzM5eiuhl%M!c#fpm;+F~2JPJW(2ZxESR(OBM0e1@(QpXWf}
zt<dMDkf^2S`j`=;hg_ve3~@tklpC{AaMTE@w}7(q?@<AChz50AbZ(2zZPB?cI{)`X
zXV|*hdlp3%L@hZ95M_=4Q-KXzCpl@sm_{Z>G#FbFoMGz(C;gV(SmDc~2rrIe@?>+l
zxjxhsU>sRxQ8W&qH!ld*JUBkZfWH=Jpw#>q_yA@_gTE~_w}s}m(A*Z9|I0!%0>ez_
z+N>#1Y7!v|9TBEt8-Zb_bAw4_PDNvTGqD+gVWty3;tG9k3W{28u8$lECeT%?#1K8y
zW_dO<3yvZ|^%}aF&aL7Cs1XhBw&>gzo!g>wTXg>KiO%))_Z-SPh+1|YM-;l_n-y7f
zGo2WWBa<W=lr0I*2n;iwU>sTD&P{#UTzak#I2AZoRv8sT&`|>jg9iY|t)RLc-Aw1-
zdjMcrG#+dV&}{*_EkL&g=>M_+B{N3Px9eWbX<4fonHXv@Xh4mY3U9VcvEt%|w(u?*
zS6C1bra(L~tm9h@#*z6J4ay?N$*}c`@gn%vN?$<Tm`^fV+0=o-1LCvHxO4~BxsoS>
z#Y>KO;#$YJU|d;Y+)ceX*&!J#TuNUkQY%(ofo<xv%(<QdJJAQ73Y;^moQomwr~!n*
z1AyaPP+gCuP^1)yf^+}g0|4iu@nEP$LW)@E_#)>jA3R%hc7=0K?Gt6xyAid={n<^O
zp!fB=ZV1$=AJV**Ej_|{pk>g5pZ99`B-TWwSVh`I4Wo3_m+1CT*g#SvhX$2ijVjzR
z*E(subdaT@R9)eUPZq-u%5y@omi#P5_TM7Tvz)Wzdwgc!k@*`(8R$mqW0s_?6nx5)
zELV_D&EnP*I-L52toff!Dz4cKEpGOZOt*OgxZ1FP<EwMo<COm$5}F$JGVh%qvxDXv
z4t)6%V;@$p6mBM4Ev|4Us7XfmM)+0vv9we2!oo*IbmZG)9Rd?}xqcww{~+L0IZ@6a
z^TbvY>R)^{!j{;`QqIWY1?5a&%eiJ&e}55YLh2EJ`6uqPmu%v%xF~lr<zLa}kGn)J
zS8jgjy@*wn!FVQC?}ymWIx+eR)|5BG3;GAi&R%zAocn4YC~~3br%37*{vLG-ZT~BA
zC&*REOl2rc)1*y$<i39%e47_lty;C;D$a-GRbp?QD}9rh?aUcX<2H3E_7pK9YBA@4
zY&f?~SW@uFEv)+EB051tf^o1mR>fvJ*bVEs3rU3~6wz-xdlxLt63KFVCMCq5FfzKf
zrbdy}1=MP167DUEOu<QX#37#^t|*~R>KRik;uVGL?SkC(Ap1P0Q^_ez-Prod|9iJY
z0)h<c8eAo>Eo6OWG$NTA_<8HyIKeLk`FC8sSWGyQlr|Unr;5n=6^|Xv8=V-^$n+x{
zW}vA^xBDU))Dvb_lA+O>?=a&@p3lLNfBjg7@x1|T$vp03xU5u#XR<G!2zpv*8In50
z+1F+CJeD12q~~RT<Bp1&m}DQ@+gR9Q5iyy<;};v71IZ7RjmZ{qC3cAwKM__ulJ!2T
z1}nfBSC5FM@+)4Cf$w!ISFPG~p|OBr9T}S7o5yS+mb?6ieO(J|DtL%9KDBk0r?XMz
zU%#Gz-8mD+z+ird+-9=MG2TVc$aB<o5SK&7Br2}>eZM_7B)`5cZ(M6h+sahrrp7Vx
z(eU?=v^xv(p5ce}nW`OT{Y@v`m-T{dGI-)yr;=A?pR#g^=aROSB9pZ<5aZSv7EL2$
zwAN;bF&^%w4CS#a@K1_jdw%;QGzvoXVy4Ei4X$xf^Q~Z{aes_nvK0TxAluj3`_g5;
za%vk`YaDgOe&Kif>xlHw@a)s0Dk?;_V)tg#-F1ZO%+1+`0)J^Im7S#P!m>{t9hQ);
z(;P{r&cCjZXI4~R-Q@r11(Th-^%!xWMCzVN2G)h!BGB2m>A)o1%-WBv)#=*Le@{kP
zaz1+!HU8<#9s`M3hr0!oPc5C<CtxM_?KxcFKY98%RtVOMa9Zr+=%bwM<sWo>o^mm_
zf)EC|KQBEG`BF+p+{Dyut<B9=<}Jm+(TEd!M^=ZpR)PQd+*k$dbZGYexFOztBIEh?
zsAXxJGxu<nJNtCtaNgh*xf(&dc6)l$+xZ1vWY*28onl<8&*b0<z{<*s!3cU+&(Khf
z0cxtVRDSaig)a|N`CSC)J^%}*K|C=duJhmlkl7av(lXz@SX8@K#t!n@l9F$f9b`B?
zAbv~itD>y@{t+Ee^M=Tni5k4r<6LxUF*q!L;nE5V2aA;}+9ED=UY*0D?I<scD=sY(
zsVQL;-D{e^Ov5E5CBHnhcA)PG2zakn=@>(Apav1&8VEQ_29*<3X0*j2%ar`@ya3QL
z8ZU-g+9jJ8UpT+qK`Gs&d{9f@$^7sYu`t%e{xU@ly?cR|lWY1;3FSo7Fn3*Uy|~{s
zh&feElyMR-WBHA<xV@7|Mj+)7ljY!rPYb*BGNLJF9j-p^9_RX!jktD;Js#r_XjSie
z-56~^n8w(0l#=ox<NhPN&laed<)+!pzc6<n8Yf$r4WHtX6EDp3w)`^FaNh(zGH~cU
zoNa1uFm_s_uX}>GnpXnOK4UO=sBQPpZ$DZB{EgdHp7$}_pojnTNWwFJAm1#+R;G?n
z!njV_@}hF#@o6H*{wQJJ6gkpvgc2THRKjOjGZF-Rs@NOb-Y|RiSw`gJO}-p*7RWkd
zRm9m!SBOx;K2s%-@JE@!+=?Mr<3<rm*#E1+p?$t)L9GT=LxW@DR`r>NW+ODsDbd^n
zu{SjKa7h7_u-&Q>t~8)TDB)YOF1P+D;hFQqw11RvRWoELFETLAqSFkagyRHC%Txxx
z_E>(~)m?OEoZ}Uhdt&`~tU<?#bKUR92Y*`B5mOo{#a&-g!fE2ievK`@aUOd7HqD;c
zA0G!tok~s5b`Pw1u>KbB%-~(mN#lFu?Qm?R@X1@GG)|9{wEXQPtg1Cl7A9`a?GNYV
zVv&9Gf!4BqLhu>9!T1Mn;!OBZr!q;f-X2~x)+x5nmrg$kuwbDnyqL}}cp~?`Dz#hW
z$f<!O)=^85xw>v!%kS)wEjQbU2k0lq-6?1i(rL5aa$4ZrW;7=oey98PqR8xwQ}GY&
zt97p778N2K&}#i;Me~%L()(D`5!xx?nFA+j6={t|1a36=z!%>*b2IvW<SV%sHuyM<
z<j9Yc!k2vXYCI%8uaE>SzHzpACnqyx8|E=!$3suS?w>dO#yiK!w)^9qf|Lq|R@D&`
z9eY*^3O~O*q6iqQoYCBYd}gw0A>PH=$g||nE9akoUOB@xWku;2U3GBEKUmM&;zioy
zbY>Rp3xE37(S-O#=6|QkbRhW-l^w9l;avJJF4!`kcY}(MMcUq>fAroNhWAO-p2!=2
zYS=}m^d?Qkcc%(*f!eZ+7R`o772R4!x)wb?1uFghp4yl82T#o_x*d;hW2XyZi>VX2
z8ftrJf{>5n-Hm2_JmaUbQNpkfRI~Katx5qN_z;M?6_1?C$Y@vP3%s}pZ&+IcG=bA~
z`toVRj~VBD*lIH=L|yU)M#W9X5~sR@wei|CvVPC%cn9Bu<CHmGuOj{g;nASK24!a`
zt*I1uZReRAvdq-)v->IbAjw%fFz~~X(AE$M_{5uz9EtDTAKhnhm+Ra6Fr|5X=tun3
zSI%|~Jify*`H?#6ge<ZBXJNDvmW9kxWmJ9^6OH}-qoa2s+PG_R`Ab-DKFY1R?if7(
zdj#?=d|U{gTQ(KMvuxy}nDzYLrQ73<lkE$gGpCoHR6l-Oz5TuU?ZV1??3K?g`vrhF
zV_jFQX)x`JK*`Qsi2B!ssS>lUV`t{AKp^uo8mzzI=S8P%sr8RjFY`0oUpckH(3|>o
z5+p&d?+*H{xV1{r7`g;CjO12fz>zel)Buw7zw`q@(`fwIrs-{(-lpkon*JZA>7Bbs
zvCy5ia(wyj@QxwA#Xr~1Ucp{EFJ(j7MQ;rs$=VfwHQ+fcnCzlEg=NX^;;VxH?ztg;
zM?RAUd+AIT3>G&Y7IJ*m>;LXu+_mcIYQe`|IywYH>o=YQvex<>z7K0Q0jGjsFP#d4
z!Rp2{L4a0&1FQm12*F-DAq0cnjpu^^?FwU|>Z{c?bl6MhU0?|C#<N0z0e*?eJYaAJ
z4hMPN91sV0HyE5h<1I{3=*|TJM(jQ&sHHK~)**P1AR0G=05N{TUOKsBlZYa(q60=$
z2K(=Q0DP6u`hae)J}?eS2T=KdVm%A?(k5~Yjor9!AK2Jra6rfj3jz^&*$NPm7iVjT
zE2)bX6x~*QU_6V#fvzU;CSV)4<paSW2SI~@OJ|fD^w;9Oaf?1M-m(A08$e>C^#<Lh
zSYT|5j%?%zV9iCj;c~618#l-Tn|cx-t#RZ827!XSEf$FK1O&=T(xL@Iw;2`~D>!<f
z)kNJQ05=kVECEIUaLEZGmdKlAfw3(7YYzYkxk(H*Zcqcpp#1no4^Y=xlv~x-8oF__
z8nB@>CqTd;Cn*R#<Xve%y!b8Qt)wf;?OEs}Nr4o}izh)qt|smlp#+hjo`Zz~m%?a$
zLANgr80q80|9@Wq$-GHiHtqxg#)bI|s<AS#zM|Y+u-4R#yF!3Xb;4vGIe9_gpdZst
zfx=lyTC`B;c7OmQW_T6@)M~PB5dwKk`*|}6a7hXxqUgu8Tx5Um10XrK7zgArEk6}1
zA5hm?lnZr{8;gES`x+b&a>9Z@L_embq23zeO6sBoMYrf07|%p-psPu|MKI(s?J*kA
zVBpdjM7+_DY5o6+H-N<6BsLqDKLTR|V?fIQ$crJdm)4_UX!gdXkicdiW&{O<oY)``
zkykt-y~Wrf;!0wp1x2^A5g1SE^PoUi6MKtb$cgO&9t>P!gNQfsibr6)ahU#vH-N<6
zBsLpY7y)BL!;aRQjWe3qORG9CG=1Z0BP3Y`9t=6bH$mOFpa_Uc!m)MKl_U?|xU>jU
zY$3=+13d6*qN8moy7faqz~dLT1PCtKLG(ECS|VWVga4UFfP~*9MjNN?ficRzgyCHY
z%9KYrOS=|;jZ^r*08sO60S-CoLEs|K(gSfb{|a{{?a@M`n~4WTSdMoK(5s2RMMy~`
s$c(K*f=hi6J%Btz59|T{%m2<NK=PyX3H#5^6K=#W9E4Og6j*%vKdFhjQ2+n{
--- a/dom/quota/test/unit/head.js
+++ b/dom/quota/test/unit/head.js
@@ -256,22 +256,34 @@ function getPersistedFromMetadata(readBu
 {
   const persistedPosition = 8; // Persisted state is stored in the 9th byte
   let view =
     readBuffer instanceof Uint8Array ? readBuffer : new Uint8Array(readBuffer);
 
   return !!view[persistedPosition];
 }
 
+function grabResultAndContinueHandler(request)
+{
+  testGenerator.next(request.result);
+}
+
 function grabUsageAndContinueHandler(request)
 {
-  testGenerator.next(request.usage);
+  testGenerator.next(request.result.usage);
 }
 
-function getUsage(usageHandler)
+function getUsage(usageHandler, getAll)
+{
+  let request = SpecialPowers._getQuotaManager().getUsage(usageHandler, getAll);
+
+  return request;
+}
+
+function getCurrentUsage(usageHandler)
 {
   let principal = Cc["@mozilla.org/systemprincipal;1"]
                     .createInstance(Ci.nsIPrincipal);
   let request =
     SpecialPowers._getQuotaManager().getUsageForPrincipal(principal,
                                                           usageHandler);
 
   return request;
--- a/dom/quota/test/unit/test_basics.js
+++ b/dom/quota/test/unit/test_basics.js
@@ -33,32 +33,32 @@ function* testSteps()
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
 
   info("Getting usage");
 
-  getUsage(grabUsageAndContinueHandler);
+  getCurrentUsage(grabUsageAndContinueHandler);
   let usage = yield undefined;
 
   ok(usage == 0, "Usage is zero");
 
   info("Installing package");
 
   // The profile contains just one empty IndexedDB database. The file
   // create_db.js in the package was run locally, specifically it was
   // temporarily added to xpcshell.ini and then executed:
   // mach xpcshell-test --interactive dom/quota/test/unit/create_db.js
   installPackage("basics_profile");
 
   info("Getting usage");
 
-  getUsage(grabUsageAndContinueHandler);
+  getCurrentUsage(grabUsageAndContinueHandler);
   usage = yield undefined;
 
   ok(usage > 0, "Usage is not zero");
 
   info("Clearing");
 
   clear(continueToNextStepSync);
   yield undefined;
new file mode 100644
--- /dev/null
+++ b/dom/quota/test/unit/test_getUsage.js
@@ -0,0 +1,127 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+function* testSteps()
+{
+  const origins = [
+    {
+      origin: "http://example.com",
+      persisted: false,
+      usage: 49152
+    },
+
+    {
+      origin: "http://localhost",
+      persisted: false,
+      usage: 147456
+    },
+
+    {
+      origin: "http://www.mozilla.org",
+      persisted: true,
+      usage: 98304
+    }
+  ];
+
+  const allOrigins = [
+    {
+      origin: "chrome",
+      persisted: false,
+      usage: 147456
+    },
+
+    {
+      origin: "http://example.com",
+      persisted: false,
+      usage: 49152
+    },
+
+    {
+      origin: "http://localhost",
+      persisted: false,
+      usage: 147456
+    },
+
+    {
+      origin: "http://www.mozilla.org",
+      persisted: true,
+      usage: 98304
+    }
+  ];
+
+  function verifyResult(result, origins) {
+    ok(result instanceof Array, "Got an array object");
+    ok(result.length == origins.length, "Correct number of elements");
+
+    info("Sorting elements");
+
+    result.sort(function(a, b) {
+      let originA = a.origin
+      let originB = b.origin
+
+      if (originA < originB) {
+        return -1;
+      }
+      if (originA > originB) {
+        return 1;
+      }
+      return 0;
+    });
+
+    info("Verifying elements");
+
+    for (let i = 0; i < result.length; i++) {
+      let a = result[i];
+      let b = origins[i];
+      ok(a.origin == b.origin, "Origin equals");
+      ok(a.persisted == b.persisted, "Persisted equals");
+      ok(a.usage == b.usage, "Usage equals");
+    }
+  }
+
+  info("Clearing");
+
+  clear(continueToNextStepSync);
+  yield undefined;
+
+  info("Getting usage");
+
+  getUsage(grabResultAndContinueHandler, /* getAll */ true);
+  let result = yield undefined;
+
+  info("Verifying result");
+
+  verifyResult(result, []);
+
+  info("Installing package");
+
+  // The profile contains IndexedDB databases placed across the repositories.
+  // The file create_db.js in the package was run locally, specifically it was
+  // temporarily added to xpcshell.ini and then executed:
+  // mach xpcshell-test --interactive dom/quota/test/unit/create_db.js
+  installPackage("getUsage_profile");
+
+  info("Getting usage");
+
+  getUsage(grabResultAndContinueHandler, /* getAll */ false);
+  result = yield undefined;
+
+  info("Verifying result");
+
+  verifyResult(result, origins);
+
+  info("Getting usage");
+
+  getUsage(grabResultAndContinueHandler, /* getAll */ true);
+  result = yield undefined;
+
+  info("Verifying result");
+
+  verifyResult(result, allOrigins);
+
+  finishTest();
+}
--- a/dom/quota/test/unit/test_unknownFiles.js
+++ b/dom/quota/test/unit/test_unknownFiles.js
@@ -126,42 +126,42 @@ function* testSteps()
 
     request = initChromeOrigin("persistent", continueToNextStepSync);
     yield undefined;
 
     ok(request.resultCode == NS_ERROR_UNEXPECTED, "Initialization failed");
 
     info("Getting usage");
 
-    request = getUsage(continueToNextStepSync);
+    request = getCurrentUsage(continueToNextStepSync);
     yield undefined;
 
     ok(request.resultCode == NS_ERROR_UNEXPECTED, "Get usage failed");
 
     file.remove(/* recursive */ false);
 
     info("Getting usage");
 
-    request = getUsage(continueToNextStepSync);
+    request = getCurrentUsage(continueToNextStepSync);
     yield undefined;
 
     ok(request.resultCode == NS_OK, "Get usage succeeded");
 
     info("Initializing origin");
 
     request = initChromeOrigin("persistent", continueToNextStepSync);
     yield undefined;
 
     ok(request.resultCode == NS_OK, "Initialization succeeded");
 
     file = createFile(unknownFile);
 
     info("Getting usage");
 
-    request = getUsage(continueToNextStepSync);
+    request = getCurrentUsage(continueToNextStepSync);
     yield undefined;
 
     ok(request.resultCode == NS_OK, "Get usage succeeded");
 
     info("Clearing origin");
 
     request = clearChromeOrigin(continueToNextStepSync);
     yield undefined;
--- a/dom/quota/test/unit/xpcshell.ini
+++ b/dom/quota/test/unit/xpcshell.ini
@@ -2,27 +2,29 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 [DEFAULT]
 head = head.js
 support-files =
   basics_profile.zip
   defaultStorageUpgrade_profile.zip
+  getUsage_profile.zip
   idbSubdirUpgrade1_profile.zip
   idbSubdirUpgrade2_profile.zip
   morgueCleanup_profile.zip
   obsoleteOriginAttributes_profile.zip
   originAttributesUpgrade_profile.zip
   removeAppsUpgrade_profile.zip
   storagePersistentUpgrade_profile.zip
   tempMetadataCleanup_profile.zip
 
 [test_basics.js]
 [test_defaultStorageUpgrade.js]
+[test_getUsage.js]
 [test_idbSubdirUpgrade.js]
 [test_morgueCleanup.js]
 [test_obsoleteOriginAttributesUpgrade.js]
 [test_originAttributesUpgrade.js]
 [test_persist.js]
 [test_removeAppsUpgrade.js]
 [test_storagePersistentUpgrade.js]
 [test_tempMetadataCleanup.js]
--- a/dom/security/nsCSPService.cpp
+++ b/dom/security/nsCSPService.cpp
@@ -15,17 +15,16 @@
 #include "nsIContentSecurityPolicy.h"
 #include "nsError.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsAsyncRedirectVerifyHelper.h"
 #include "mozilla/Preferences.h"
 #include "nsIScriptError.h"
 #include "nsContentUtils.h"
 #include "nsContentPolicyUtils.h"
-#include "nsPrincipal.h"
 
 using namespace mozilla;
 
 /* Keeps track of whether or not CSP is enabled */
 bool CSPService::sCSPEnabled = true;
 
 static LazyLogModule gCspPRLog("CSP");
 
--- a/dom/security/test/csp/file_upgrade_insecure.html
+++ b/dom/security/test/csp/file_upgrade_insecure.html
@@ -52,16 +52,17 @@
     var mySocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_upgrade_insecure");
     mySocket.onopen = function(e) {
       if (mySocket.url.includes("wss://")) {
         window.parent.postMessage({result: "websocket-ok"}, "*");
       }
       else {
         window.parent.postMessage({result: "websocket-error"}, "*");
       }
+      mySocket.close();
     };
     mySocket.onerror = function(e) {
       // debug information for Bug 1316305
       dump("  xxx mySocket.onerror: (mySocket): " + mySocket + "\n");
       dump("  xxx mySocket.onerror: (mySocket.url): " + mySocket.url + "\n");
       dump("  xxx mySocket.onerror: (e): " + e + "\n");
       dump("  xxx mySocket.onerror: (e.message): " + e.message + "\n");
       window.parent.postMessage({result: "websocket-unexpected-error"}, "*");
--- a/dom/security/test/csp/file_upgrade_insecure_meta.html
+++ b/dom/security/test/csp/file_upgrade_insecure_meta.html
@@ -53,16 +53,17 @@
     var mySocket = new WebSocket("ws://example.com/tests/dom/security/test/csp/file_upgrade_insecure");
     mySocket.onopen = function(e) {
       if (mySocket.url.includes("wss://")) {
         window.parent.postMessage({result: "websocket-ok"}, "*");
       }
       else {
         window.parent.postMessage({result: "websocket-error"}, "*");
       }
+      mySocket.close();
     };
     mySocket.onerror = function(e) {
       window.parent.postMessage({result: "websocket-unexpected-error"}, "*");
     };
   </script>
 
   <!-- form action: (upgrade POST from http:// to https://) -->
   <iframe name='formFrame' id='formFrame'></iframe>
--- a/dom/worklet/Worklet.cpp
+++ b/dom/worklet/Worklet.cpp
@@ -200,19 +200,16 @@ public:
 
     (void) new XPCWrappedNativeScope(cx, globalObj);
 
     JS::CompileOptions compileOptions(cx);
     compileOptions.setIntroductionType("Worklet");
     compileOptions.setFileAndLine(NS_ConvertUTF16toUTF8(mURL).get(), 0);
     compileOptions.setVersion(JSVERSION_DEFAULT);
     compileOptions.setIsRunOnce(true);
-
-    // We only need the setNoScriptRval bit when compiling off-thread here,
-    // since otherwise nsJSUtils::EvaluateString will set it up for us.
     compileOptions.setNoScriptRval(true);
 
     JSAutoCompartment comp(cx, globalObj);
 
     JS::Rooted<JS::Value> unused(cx);
     if (!JS::Evaluate(cx, compileOptions, buffer, &unused)) {
       ErrorResult error;
       error.MightThrowJSException();
--- a/dom/xbl/nsXBLProtoImplField.cpp
+++ b/dom/xbl/nsXBLProtoImplField.cpp
@@ -422,24 +422,29 @@ nsXBLProtoImplField::InstallField(JS::Ha
   JS::Rooted<JSObject*> scopeObject(cx, xpc::GetScopeForXBLExecution(cx, aBoundNode, addonId));
   NS_ENSURE_TRUE(scopeObject, NS_ERROR_OUT_OF_MEMORY);
   JSAutoCompartment ac(cx, scopeObject);
 
   JS::Rooted<JS::Value> result(cx);
   JS::CompileOptions options(cx);
   options.setFileAndLine(uriSpec.get(), mLineNumber)
          .setVersion(JSVERSION_LATEST);
-  nsJSUtils::EvaluateOptions evalOptions(cx);
-  if (!nsJSUtils::GetScopeChainForElement(cx, boundElement,
-                                          evalOptions.scopeChain)) {
+  JS::AutoObjectVector scopeChain(cx);
+  if (!nsJSUtils::GetScopeChainForElement(cx, boundElement, scopeChain)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
-  rv = nsJSUtils::EvaluateString(cx, nsDependentString(mFieldText,
-                                                       mFieldTextLength),
-                                 scopeObject, options, evalOptions, &result);
+  rv = NS_OK;
+  {
+    nsJSUtils::ExecutionContext exec(cx, scopeObject);
+    exec.SetScopeChain(scopeChain);
+    exec.CompileAndExec(options, nsDependentString(mFieldText,
+                                                   mFieldTextLength));
+    rv = exec.ExtractReturnValue(&result);
+  }
+
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   if (rv == NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW) {
     // Report the exception now, before we try using the JSContext for
     // the JS_DefineUCProperty call.
     aes.ReportException();
--- a/extensions/gio/nsGIOProtocolHandler.cpp
+++ b/extensions/gio/nsGIOProtocolHandler.cpp
@@ -19,17 +19,17 @@
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIURI.h"
 #include "nsIAuthPrompt.h"
 #include "nsIChannel.h"
 #include "nsIInputStream.h"
 #include "nsIProtocolHandler.h"
-#include "nsNullPrincipal.h"
+#include "NullPrincipal.h"
 #include "mozilla/Monitor.h"
 #include "plstr.h"
 #include "prtime.h"
 #include <gio/gio.h>
 #include <algorithm>
 
 #define MOZ_GIO_SCHEME              "moz-gio"
 #define MOZ_GIO_SUPPORTED_PROTOCOLS "network.gio.supported-protocols"
--- a/gfx/2d/RecordedEvent.cpp
+++ b/gfx/2d/RecordedEvent.cpp
@@ -1294,41 +1294,50 @@ RecordedSourceSurfaceCreation::~Recorded
   if (mDataOwned) {
     delete [] mData;
   }
 }
 
 bool
 RecordedSourceSurfaceCreation::PlayEvent(Translator *aTranslator) const
 {
+  if (!mData) {
+    return false;
+  }
+
   RefPtr<SourceSurface> src = aTranslator->GetReferenceDrawTarget()->
     CreateSourceSurfaceFromData(mData, mSize, mSize.width * BytesPerPixel(mFormat), mFormat);
   aTranslator->AddSourceSurface(mRefPtr, src);
   return true;
 }
 
 void
 RecordedSourceSurfaceCreation::RecordToStream(ostream &aStream) const
 {
   WriteElement(aStream, mRefPtr);
   WriteElement(aStream, mSize);
   WriteElement(aStream, mFormat);
+  MOZ_ASSERT(mData);
   for (int y = 0; y < mSize.height; y++) {
     aStream.write((const char*)mData + y * mStride, BytesPerPixel(mFormat) * mSize.width);
   }
 }
 
 RecordedSourceSurfaceCreation::RecordedSourceSurfaceCreation(istream &aStream)
   : RecordedEvent(SOURCESURFACECREATION), mDataOwned(true)
 {
   ReadElement(aStream, mRefPtr);
   ReadElement(aStream, mSize);
   ReadElement(aStream, mFormat);
-  mData = (uint8_t*)new char[mSize.width * mSize.height * BytesPerPixel(mFormat)];
-  aStream.read((char*)mData, mSize.width * mSize.height * BytesPerPixel(mFormat));
+  mData = (uint8_t*)new (fallible) char[mSize.width * mSize.height * BytesPerPixel(mFormat)];
+  if (!mData) {
+    gfxWarning() << "RecordedSourceSurfaceCreation failed to allocate data";
+  } else {
+    aStream.read((char*)mData, mSize.width * mSize.height * BytesPerPixel(mFormat));
+  }
 }
 
 void
 RecordedSourceSurfaceCreation::OutputSimpleEventInfo(stringstream &aStringStream) const
 {
   aStringStream << "[" << mRefPtr << "] SourceSurface created (Size: " << mSize.width << "x" << mSize.height << ")";
 }
 
--- a/gfx/skia/skia/src/core/SkScan_Path.cpp
+++ b/gfx/skia/skia/src/core/SkScan_Path.cpp
@@ -587,39 +587,45 @@ static bool clip_to_limit(const SkRegion
     if (limitR.contains(orig.getBounds())) {
         return false;
     }
     reduced->op(orig, limitR, SkRegion::kIntersect_Op);
     return true;
 }
 
 /**
-  * Variant of SkScalarRoundToInt, identical to SkDScalarRoundToInt except when the input fraction
-  * is 0.5. In this case only, round the value down. This is used to round the top and left
-  * of a rectangle, and corresponds to the way the scan converter treats the top and left edges.
+  * Variants of SkScalarRoundToInt, identical to SkDScalarRoundToInt except when the input fraction
+  * is 0.5. When SK_RASTERIZE_EVEN_ROUNDING is enabled, we must bias the result before rounding to
+  * account for potential FDot6 rounding edge-cases.
+  */
+#ifdef SK_RASTERIZE_EVEN_ROUNDING
+static const double kRoundBias = 0.5 / SK_FDot6One;
+#else
+static const double kRoundBias = 0.0;
+#endif
+
+/**
+  * Round the value down. This is used to round the top and left of a rectangle,
+  * and corresponds to the way the scan converter treats the top and left edges.
   */
 static inline int round_down_to_int(SkScalar x) {
     double xx = x;
-    xx += 0.5;
-    double floorXX = floor(xx);
-    return (int)floorXX - (xx == floorXX);
+    xx -= 0.5 + kRoundBias;
+    return (int)ceil(xx);
 }
 
-#ifdef SK_RASTERIZE_EVEN_ROUNDING
 /**
-  * Variant of SkDScalarRoundToInt that allows offseting the input by a small fraction
-  * while trying to preserve intermediate double-precision (rather than directly adding
-  * the bias to the input at lower single-precision).
+  * Round the value up. This is used to round the bottom and right of a rectangle,
+  * and corresponds to the way the scan converter treats the bottom and right edges.
   */
-static inline int round_biased_to_int(SkScalar x, SkScalar bias) {
+static inline int round_up_to_int(SkScalar x) {
     double xx = x;
-    xx += 0.5 + bias;
+    xx += 0.5 + kRoundBias;
     return (int)floor(xx);
 }
-#endif
 
 /**
   *  Variant of SkRect::round() that explicitly performs the rounding step (i.e. floor(x + 0.5))
   *  using double instead of SkScalar (float). It does this by calling SkDScalarRoundToInt(),
   *  which may be slower than calling SkScalarRountToInt(), but gives slightly more accurate
   *  results. Also rounds top and left using double, flooring when the fraction is exactly 0.5f.
   *
   *  e.g.
@@ -630,36 +636,31 @@ static inline int round_biased_to_int(Sk
   *      SkASSERT(0 == ileft);  // <--- succeeds
   *      SkScalar right = 0.49999997f;
   *      int iright = SkScalarRoundToInt(right);
   *      SkASSERT(0 == iright);  // <--- fails
   *      iright = SkDScalarRoundToInt(right);
   *      SkASSERT(0 == iright);  // <--- succeeds
   *
   *
-  *  If using SK_RASTERIZE_EVEN_ROUNDING, we need to ensure that bottom and right account for
-  *  edges bounded by this rect being rounded to FDot6 format before being later rounded to an
-  *  integer. For example, a value like 0.499 can be below 0.5, but round to 0.5 as FDot6, which
-  *  would finally round to the integer 1, instead of just rounding to 0.
+  *  If using SK_RASTERIZE_EVEN_ROUNDING, we need to ensure we account for edges bounded by this
+  *  rect being rounded to FDot6 format before being later rounded to an integer. For example, a
+  *  value like 0.499 can be below 0.5, but round to 0.5 as FDot6, which would finally round to
+  *  the integer 1, instead of just rounding to 0.
   *
   *  To handle this, a small bias of half an FDot6 increment is added before actually rounding to
   *  an integer value. This simulates the rounding of SkScalarRoundToFDot6 without incurring the
   *  range loss of converting to FDot6 format first, preserving the integer range for the SkIRect.
-  *  Thus, bottom and right are rounded in this manner (biased up), ensuring the rect is large enough.
-  *  Top and left can round as normal since they will round (biased down) to values less or equal
-  *  to the desired rect origin.
+  *  Thus, bottom and right are rounded in this manner (biased up), ensuring the rect is large
+  *  enough.
   */
 static void round_asymmetric_to_int(const SkRect& src, SkIRect* dst) {
     SkASSERT(dst);
     dst->set(round_down_to_int(src.fLeft), round_down_to_int(src.fTop),
-#ifdef SK_RASTERIZE_EVEN_ROUNDING
-             round_biased_to_int(src.fRight, 0.5f / SK_FDot6One), round_biased_to_int(src.fBottom, 0.5f / SK_FDot6One));
-#else
-             SkDScalarRoundToInt(src.fRight), SkDScalarRoundToInt(src.fBottom));
-#endif
+             round_up_to_int(src.fRight), round_up_to_int(src.fBottom));
 }
 
 void SkScan::FillPath(const SkPath& path, const SkRegion& origClip,
                       SkBlitter* blitter) {
     if (origClip.isEmpty()) {
         return;
     }
 
deleted file mode 100644
--- a/gfx/thebes/gfxFontconfigFonts.cpp
+++ /dev/null
@@ -1,2262 +0,0 @@
-/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "prlink.h"
-#include "gfxTypes.h"
-
-#include "nsTArray.h"
-
-#include "gfxContext.h"
-#ifdef MOZ_WIDGET_GTK
-#include "gfxPlatformGtk.h"
-#endif
-#include "gfxFontconfigFonts.h"
-#include "gfxFT2FontBase.h"
-#include "gfxFT2Utils.h"
-#include "harfbuzz/hb.h"
-#include "harfbuzz/hb-glib.h"
-#include "harfbuzz/hb-ot.h"
-#include "nsUnicodeProperties.h"
-#include "nsUnicodeScriptCodes.h"
-#include "gfxFontconfigUtils.h"
-#include "gfxUserFontSet.h"
-#include "gfxFontConstants.h"
-#include "nsGkAtoms.h"
-#include "nsILanguageAtomService.h"
-#include "nsServiceManagerUtils.h"
-
-#include <cairo.h>
-#include <cairo-ft.h>
-#include "mozilla/gfx/HelpersCairo.h"
-
-#include <fontconfig/fcfreetype.h>
-#include <pango/pango.h>
-
-#include FT_TRUETYPE_TABLES_H
-
-#ifdef MOZ_WIDGET_GTK
-#include <gdk/gdk.h>
-#endif
-
-#include <math.h>
-
-using namespace mozilla;
-using namespace mozilla::unicode;
-
-#define PRINTING_FC_PROPERTY "gfx.printing"
-
-static PangoLanguage *GuessPangoLanguage(nsIAtom *aLanguage);
-
-static cairo_scaled_font_t *
-CreateScaledFont(FcPattern *aPattern, cairo_font_face_t *aFace);
-
-static FT_Library gFTLibrary;
-
-// FC_FAMILYLANG and FC_FULLNAME were introduced in fontconfig-2.2.97
-// and so fontconfig-2.3.0 (2005).
-#ifndef FC_FAMILYLANG
-#define FC_FAMILYLANG "familylang"
-#endif
-#ifndef FC_FULLNAME
-#define FC_FULLNAME "fullname"
-#endif
-
-static PRFuncPtr
-FindFunctionSymbol(const char *name)
-{
-    PRLibrary *lib = nullptr;
-    PRFuncPtr result = PR_FindFunctionSymbolAndLibrary(name, &lib);
-    if (lib) {
-        PR_UnloadLibrary(lib);
-    }
-
-    return result;
-}
-
-static bool HasChar(FcPattern *aFont, FcChar32 wc)
-{
-    FcCharSet *charset = nullptr;
-    FcPatternGetCharSet(aFont, FC_CHARSET, 0, &charset);
-
-    return charset && FcCharSetHasChar(charset, wc);
-}
-
-/**
- * gfxFcFontEntry:
- *
- * An abstract base class of for gfxFontEntry implementations used by
- * gfxFcFont and gfxUserFontSet.
- */
-
-class gfxFcFontEntry : public gfxFontEntry {
-public:
-    // For all FontEntrys attached to gfxFcFonts, there will be only one
-    // pattern in this array.  This is always a font pattern, not a fully
-    // resolved pattern.  gfxFcFont only uses this to construct a PangoFont.
-    //
-    // FontEntrys for src:local() fonts in gfxUserFontSet may return more than
-    // one pattern.  (See comment in gfxUserFcFontEntry.)
-    const nsTArray< nsCountedRef<FcPattern> >& GetPatterns()
-    {
-        return mPatterns;
-    }
-
-    static gfxFcFontEntry *LookupFontEntry(cairo_font_face_t *aFace)
-    {
-        return static_cast<gfxFcFontEntry*>
-            (cairo_font_face_get_user_data(aFace, &sFontEntryKey));
-    }
-
-    // override the gfxFontEntry impl to read the name from fontconfig
-    // instead of trying to get the 'name' table, as we don't implement
-    // GetFontTable() here
-    virtual nsString RealFaceName();
-
-    // This is needed to make gfxFontEntry::HasCharacter(aCh) work.
-    virtual bool TestCharacterMap(uint32_t aCh)
-    {
-        for (uint32_t i = 0; i < mPatterns.Length(); ++i) {
-            if (HasChar(mPatterns[i], aCh)) {
-                return true;
-            }
-        }
-        return false;
-    }
-
-protected:
-    explicit gfxFcFontEntry(const nsAString& aName)
-        : gfxFontEntry(aName)
-    {
-    }
-
-    // One pattern is the common case and some subclasses rely on successful
-    // addition of the first element to the array.
-    AutoTArray<nsCountedRef<FcPattern>,1> mPatterns;
-
-    static cairo_user_data_key_t sFontEntryKey;
-};
-
-cairo_user_data_key_t gfxFcFontEntry::sFontEntryKey;
-
-nsString
-gfxFcFontEntry::RealFaceName()
-{
-    FcChar8 *name;
-    if (!mPatterns.IsEmpty()) {
-        if (FcPatternGetString(mPatterns[0],
-                               FC_FULLNAME, 0, &name) == FcResultMatch) {
-            return NS_ConvertUTF8toUTF16((const char*)name);
-        }
-        if (FcPatternGetString(mPatterns[0],
-                               FC_FAMILY, 0, &name) == FcResultMatch) {
-            NS_ConvertUTF8toUTF16 result((const char*)name);
-            if (FcPatternGetString(mPatterns[0],
-                                   FC_STYLE, 0, &name) == FcResultMatch) {
-                result.Append(' ');
-                AppendUTF8toUTF16((const char*)name, result);
-            }
-            return result;
-        }
-    }
-    // fall back to gfxFontEntry implementation (only works for sfnt fonts)
-    return gfxFontEntry::RealFaceName();
-}
-
-/**
- * gfxSystemFcFontEntry:
- *
- * An implementation of gfxFcFontEntry used by gfxFcFonts for system fonts,
- * including those from regular family-name based font selection as well as
- * those from src:local().
- *
- * All gfxFcFonts using the same cairo_font_face_t share the same FontEntry. 
- */
-
-class gfxSystemFcFontEntry : public gfxFcFontEntry {
-public:
-    // For memory efficiency, aFontPattern should be a font pattern,
-    // not a fully resolved pattern.
-    gfxSystemFcFontEntry(cairo_font_face_t *aFontFace,
-                         FcPattern *aFontPattern,
-                         const nsAString& aName)
-        : gfxFcFontEntry(aName), mFontFace(aFontFace),
-          mFTFace(nullptr), mFTFaceInitialized(false)
-    {
-        cairo_font_face_reference(mFontFace);
-        cairo_font_face_set_user_data(mFontFace, &sFontEntryKey, this, nullptr);
-
-        // mPatterns is an AutoTArray with 1 space always available, so the
-        // AppendElement always succeeds.
-        // FIXME: Make this infallible after bug 968520 is done.
-        MOZ_ALWAYS_TRUE(mPatterns.AppendElement(fallible));
-        mPatterns[0] = aFontPattern;
-
-        FcChar8 *name;
-        if (FcPatternGetString(aFontPattern,
-                               FC_FAMILY, 0, &name) == FcResultMatch) {
-            mFamilyName = NS_ConvertUTF8toUTF16((const char*)name);
-        }
-    }
-
-    ~gfxSystemFcFontEntry()
-    {
-        cairo_font_face_set_user_data(mFontFace,
-                                      &sFontEntryKey,
-                                      nullptr,
-                                      nullptr);
-        cairo_font_face_destroy(mFontFace);
-    }
-
-    virtual void ForgetHBFace() override;
-    virtual void ReleaseGrFace(gr_face* aFace) override;
-
-protected:
-    virtual nsresult
-    CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer) override;
-
-    void MaybeReleaseFTFace();
-
-private:
-    cairo_font_face_t *mFontFace;
-    FT_Face            mFTFace;
-    bool               mFTFaceInitialized;
-};
-
-nsresult
-gfxSystemFcFontEntry::CopyFontTable(uint32_t aTableTag,
-                                    nsTArray<uint8_t>& aBuffer)
-{
-    if (!mFTFaceInitialized) {
-        mFTFaceInitialized = true;
-        FcChar8 *filename;
-        if (FcPatternGetString(mPatterns[0], FC_FILE, 0, &filename) != FcResultMatch) {
-            return NS_ERROR_FAILURE;
-        }
-        int index;
-        if (FcPatternGetInteger(mPatterns[0], FC_INDEX, 0, &index) != FcResultMatch) {
-            index = 0; // default to 0 if not found in pattern
-        }
-        if (FT_New_Face(gfxPangoFontGroup::GetFTLibrary(),
-                        (const char*)filename, index, &mFTFace) != 0) {
-            return NS_ERROR_FAILURE;
-        }
-    }
-
-    if (!mFTFace) {
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-
-    FT_ULong length = 0;
-    if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, nullptr, &length) != 0) {
-        return NS_ERROR_NOT_AVAILABLE;
-    }
-    if (!aBuffer.SetLength(length, fallible)) {
-        return NS_ERROR_OUT_OF_MEMORY;
-    }
-    if (FT_Load_Sfnt_Table(mFTFace, aTableTag, 0, aBuffer.Elements(), &length) != 0) {
-        aBuffer.Clear();
-        return NS_ERROR_FAILURE;
-    }
-
-    return NS_OK;
-}
-
-void
-gfxSystemFcFontEntry::MaybeReleaseFTFace()
-{
-    // don't release if either HB or Gr face still exists
-    if (mHBFace || mGrFace) {
-        return;
-    }
-    if (mFTFace) {
-        FT_Done_Face(mFTFace);
-        mFTFace = nullptr;
-    }
-    mFTFaceInitialized = false;
-}
-
-void
-gfxSystemFcFontEntry::ForgetHBFace()
-{
-    gfxFontEntry::ForgetHBFace();
-    MaybeReleaseFTFace();
-}
-
-void
-gfxSystemFcFontEntry::ReleaseGrFace(gr_face* aFace)
-{
-    gfxFontEntry::ReleaseGrFace(aFace);
-    MaybeReleaseFTFace();
-}
-
-// A namespace for @font-face family names in FcPatterns so that fontconfig
-// aliases do not pick up families from @font-face rules and so that
-// fontconfig rules can distinguish between web fonts and platform fonts.
-// http://lists.freedesktop.org/archives/fontconfig/2008-November/003037.html
-#define FONT_FACE_FAMILY_PREFIX "@font-face:"
-
-/**
- * gfxUserFcFontEntry:
- *
- * An abstract class for objects in a gfxUserFontSet that can provide
- * FcPattern* handles to fonts.
- *
- * Separate implementations of this class support local fonts from src:local()
- * and web fonts from src:url().
- */
-
-// There is a one-to-one correspondence between gfxUserFcFontEntry objects and
-// @font-face rules, but sometimes a one-to-many correspondence between font
-// entries and font patterns.
-//
-// http://www.w3.org/TR/2002/WD-css3-webfonts-20020802#font-descriptions
-// provided a font-size descriptor to specify the sizes supported by the face,
-// but the "Editor's Draft 27 June 2008"
-// http://dev.w3.org/csswg/css3-fonts/#font-resources does not provide such a
-// descriptor, and Mozilla does not recognize such a descriptor.
-//
-// Font face names used in src:local() also do not usually specify a size.
-//
-// PCF format fonts have each size in a different file, and each of these
-// files is referenced by its own pattern, but really these are each
-// different sizes of one face with one name.
-//
-// Multiple patterns in an entry also effectively deals with a set of
-// PostScript Type 1 font files that all have the same face name but are in
-// several files because of the limit on the number of glyphs in a Type 1 font
-// file.  (e.g. Computer Modern.)
-
-class gfxUserFcFontEntry : public gfxFcFontEntry {
-protected:
-    explicit gfxUserFcFontEntry(const nsAString& aFontName,
-                       uint16_t aWeight,
-                       int16_t aStretch,
-                       uint8_t aStyle)
-        : gfxFcFontEntry(aFontName)
-    {
-        mStyle = aStyle;
-        mWeight = aWeight;
-        mStretch = aStretch;
-    }
-
-    // Helper function to change a pattern so that it matches the CSS style
-    // descriptors and so gets properly sorted in font selection.  This also
-    // avoids synthetic style effects being added by the renderer when the
-    // style of the font itself does not match the descriptor provided by the
-    // author.
-    void AdjustPatternToCSS(FcPattern *aPattern);
-};
-
-void
-gfxUserFcFontEntry::AdjustPatternToCSS(FcPattern *aPattern)
-{
-    int fontWeight = -1;
-    FcPatternGetInteger(aPattern, FC_WEIGHT, 0, &fontWeight);
-    int cssWeight = gfxFontconfigUtils::FcWeightForBaseWeight(mWeight / 100);
-    if (cssWeight != fontWeight) {
-        FcPatternDel(aPattern, FC_WEIGHT);
-        FcPatternAddInteger(aPattern, FC_WEIGHT, cssWeight);
-    }
-
-    int fontSlant;
-    FcResult res = FcPatternGetInteger(aPattern, FC_SLANT, 0, &fontSlant);
-    // gfxFontEntry doesn't understand the difference between oblique
-    // and italic.
-    if (res != FcResultMatch ||
-        IsItalic() != (fontSlant != FC_SLANT_ROMAN)) {
-        FcPatternDel(aPattern, FC_SLANT);
-        FcPatternAddInteger(aPattern, FC_SLANT,
-                            IsItalic() ? FC_SLANT_OBLIQUE : FC_SLANT_ROMAN);
-    }
-
-    int fontWidth = -1;
-    FcPatternGetInteger(aPattern, FC_WIDTH, 0, &fontWidth);
-    int cssWidth = gfxFontconfigUtils::FcWidthForThebesStretch(mStretch);
-    if (cssWidth != fontWidth) {
-        FcPatternDel(aPattern, FC_WIDTH);
-        FcPatternAddInteger(aPattern, FC_WIDTH, cssWidth);
-    }
-
-    // Ensure that there is a fullname property (if there is a family
-    // property) so that fontconfig rules can identify the real name of the
-    // font, because the family property will be replaced.
-    FcChar8 *unused;
-    if (FcPatternGetString(aPattern,
-                           FC_FULLNAME, 0, &unused) == FcResultNoMatch) {
-        nsAutoCString fullname;
-        if (gfxFontconfigUtils::GetFullnameFromFamilyAndStyle(aPattern,
-                                                              &fullname)) {
-            FcPatternAddString(aPattern, FC_FULLNAME,
-                               gfxFontconfigUtils::ToFcChar8(fullname));
-        }
-    }
-
-    nsAutoCString family;
-    family.Append(FONT_FACE_FAMILY_PREFIX);
-    AppendUTF16toUTF8(Name(), family);
-
-    FcPatternDel(aPattern, FC_FAMILY);
-    FcPatternDel(aPattern, FC_FAMILYLANG);
-    FcPatternAddString(aPattern, FC_FAMILY,
-                       gfxFontconfigUtils::ToFcChar8(family));
-}
-
-/**
- * gfxLocalFcFontEntry:
- *
- * An implementation of gfxUserFcFontEntry for local fonts from src:local().
- *
- * This class is used only in gfxUserFontSet and for providing FcPattern*
- * handles to system fonts for font selection.  gfxFcFonts created from these
- * patterns will use gfxSystemFcFontEntrys, which may be shared with
- * gfxFcFonts from regular family-name based font selection.
- */
-
-class gfxLocalFcFontEntry : public gfxUserFcFontEntry {
-public:
-    gfxLocalFcFontEntry(const nsAString& aFontName,
-                        uint16_t aWeight,
-                        int16_t aStretch,
-                        uint8_t aStyle,
-                        const nsTArray< nsCountedRef<FcPattern> >& aPatterns)
-        : gfxUserFcFontEntry(aFontName, aWeight, aStretch, aStyle)
-    {
-        if (!mPatterns.SetCapacity(aPatterns.Length(), fallible))
-            return; // OOM
-
-        for (uint32_t i = 0; i < aPatterns.Length(); ++i) {
-            FcPattern *pattern = FcPatternDuplicate(aPatterns.ElementAt(i));
-            if (!pattern)
-                return; // OOM
-
-            AdjustPatternToCSS(pattern);
-
-            // FIXME: Make this infallible after bug 968520 is done.
-            MOZ_ALWAYS_TRUE(mPatterns.AppendElement(fallible));
-            mPatterns[i].own(pattern);
-        }
-        mIsLocalUserFont = true;
-    }
-};
-
-/**
- * gfxDownloadedFcFontEntry:
- *
- * An implementation of gfxFcFontEntry for web fonts from src:url().
- * 
- * When a cairo_font_face_t is created for these fonts, the cairo_font_face_t
- * keeps a reference to the FontEntry to keep the font data alive.
- */
-
-class gfxDownloadedFcFontEntry : public gfxUserFcFontEntry {
-public:
-    // This takes ownership of the face and its underlying data
-    gfxDownloadedFcFontEntry(const nsAString& aFontName,
-                             uint16_t aWeight,
-                             int16_t aStretch,
-                             uint8_t aStyle,
-                             const uint8_t *aData, FT_Face aFace)
-        : gfxUserFcFontEntry(aFontName, aWeight, aStretch, aStyle),
-          mFontData(aData), mFace(aFace)
-    {
-        NS_PRECONDITION(aFace != nullptr, "aFace is NULL!");
-        mIsDataUserFont = true;
-        InitPattern();
-    }
-
-    virtual ~gfxDownloadedFcFontEntry();
-
-    // Returns true on success
-    bool SetCairoFace(cairo_font_face_t *aFace);
-
-    virtual hb_blob_t* GetFontTable(uint32_t aTableTag) override;
-
-protected:
-    void InitPattern();
-
-    // mFontData holds the data used to instantiate the FT_Face;
-    // this has to persist until we are finished with the face,
-    // then be released with free().
-    const uint8_t* mFontData;
-
-    FT_Face mFace;
-};
-
-// A property for recording gfxDownloadedFcFontEntrys on FcPatterns.
-static const char *kFontEntryFcProp = "-moz-font-entry";
-
-static FcBool AddDownloadedFontEntry(FcPattern *aPattern,
-                                     gfxDownloadedFcFontEntry *aFontEntry)
-{
-    FcValue value;
-    value.type = FcTypeFTFace; // void* field of union
-    value.u.f = aFontEntry;
-
-    return FcPatternAdd(aPattern, kFontEntryFcProp, value, FcFalse);
-}
-
-static FcBool DelDownloadedFontEntry(FcPattern *aPattern)
-{
-    return FcPatternDel(aPattern, kFontEntryFcProp);
-}
-
-static gfxDownloadedFcFontEntry *GetDownloadedFontEntry(FcPattern *aPattern)
-{
-    FcValue value;
-    if (FcPatternGet(aPattern, kFontEntryFcProp, 0, &value) != FcResultMatch)
-        return nullptr;
-
-    if (value.type != FcTypeFTFace) {
-        NS_NOTREACHED("Wrong type for -moz-font-entry font property");
-        return nullptr;
-    }
-
-    return static_cast<gfxDownloadedFcFontEntry*>(value.u.f);
-}
-
-gfxDownloadedFcFontEntry::~gfxDownloadedFcFontEntry()
-{
-    if (mPatterns.Length() != 0) {
-        // Remove back reference to this font entry and the face in case
-        // anyone holds a reference to the pattern.
-        NS_ASSERTION(mPatterns.Length() == 1,
-                     "More than one pattern in gfxDownloadedFcFontEntry!");
-        DelDownloadedFontEntry(mPatterns[0]);
-        FcPatternDel(mPatterns[0], FC_FT_FACE);
-    }
-    FT_Done_Face(mFace);
-    free((void*)mFontData);
-}
-
-typedef FcPattern* (*QueryFaceFunction)(const FT_Face face,
-                                        const FcChar8 *file, int id,
-                                        FcBlanks *blanks);
-
-void
-gfxDownloadedFcFontEntry::InitPattern()
-{
-    static QueryFaceFunction sQueryFacePtr =
-        reinterpret_cast<QueryFaceFunction>
-        (FindFunctionSymbol("FcFreeTypeQueryFace"));
-    FcPattern *pattern;
-
-    // FcFreeTypeQueryFace is the same function used to construct patterns for
-    // system fonts and so is the preferred function to use for this purpose.
-    // This will set up the langset property, which helps with sorting, and
-    // the foundry, fullname, and fontversion properties, which properly
-    // identify the font to fontconfig rules.  However, FcFreeTypeQueryFace is
-    // available only from fontconfig-2.4.2 (December 2006).  (CentOS 5.0 has
-    // fontconfig-2.4.1.)
-    if (sQueryFacePtr) {
-        // The "file" argument cannot be nullptr (in fontconfig-2.6.0 at
-        // least). The dummy file passed here is removed below.
-        //
-        // When fontconfig scans the system fonts, FcConfigGetBlanks(nullptr)
-        // is passed as the "blanks" argument, which provides that unexpectedly
-        // blank glyphs are elided.  Here, however, we pass nullptr for
-        // "blanks", effectively assuming that, if the font has a blank glyph,
-        // then the author intends any associated character to be rendered
-        // blank.
-        pattern =
-            (*sQueryFacePtr)(mFace,
-                             gfxFontconfigUtils::ToFcChar8(""),
-                             0,
-                             nullptr);
-        if (!pattern)
-            // Either OOM, or fontconfig chose to skip this font because it
-            // has "no encoded characters", which I think means "BDF and PCF
-            // fonts which are not in Unicode (or the effectively equivalent
-            // ISO Latin-1) encoding".
-            return;
-
-        // These properties don't make sense for this face without a file.
-        FcPatternDel(pattern, FC_FILE);
-        FcPatternDel(pattern, FC_INDEX);
-
-    } else {
-        // Do the minimum necessary to construct a pattern for sorting.
-
-        // FC_CHARSET is vital to determine which characters are supported.
-        nsAutoRef<FcCharSet> charset(FcFreeTypeCharSet(mFace, nullptr));
-        // If there are no characters then assume we don't know how to read
-        // this font.
-        if (!charset || FcCharSetCount(charset) == 0)
-            return;
-
-        pattern = FcPatternCreate();
-        FcPatternAddCharSet(pattern, FC_CHARSET, charset);
-
-        // FC_PIXEL_SIZE can be important for font selection of fixed-size
-        // fonts.
-        if (!(mFace->face_flags & FT_FACE_FLAG_SCALABLE)) {
-            for (FT_Int i = 0; i < mFace->num_fixed_sizes; ++i) {
-#if HAVE_FT_BITMAP_SIZE_Y_PPEM
-                double size = FLOAT_FROM_26_6(mFace->available_sizes[i].y_ppem);
-#else
-                double size = mFace->available_sizes[i].height;
-#endif
-                FcPatternAddDouble (pattern, FC_PIXEL_SIZE, size);
-            }
-
-            // Not sure whether this is important;
-            // imitating FcFreeTypeQueryFace:
-            FcPatternAddBool (pattern, FC_ANTIALIAS, FcFalse);
-        }
-
-        // Setting up the FC_LANGSET property is very difficult with the APIs
-        // available prior to FcFreeTypeQueryFace.  Having no FC_LANGSET
-        // property seems better than having a property with an empty LangSet.
-        // With no FC_LANGSET property, fontconfig sort functions will
-        // consider this face to have the same priority as (otherwise equal)
-        // faces that have support for the primary requested language, but
-        // will not consider any language to have been satisfied (and so will
-        // continue to look for a face with language support in fallback
-        // fonts).
-    }
-
-    AdjustPatternToCSS(pattern);
-
-    FcPatternAddFTFace(pattern, FC_FT_FACE, mFace);
-    AddDownloadedFontEntry(pattern, this);
-
-    // There is never more than one pattern
-    // FIXME: Make this infallible after bug 968520 is done.
-    MOZ_ALWAYS_TRUE(mPatterns.AppendElement(fallible));
-    mPatterns[0].own(pattern);
-}
-
-static void ReleaseDownloadedFontEntry(void *data)
-{
-    gfxDownloadedFcFontEntry *downloadedFontEntry =
-        static_cast<gfxDownloadedFcFontEntry*>(data);
-    NS_RELEASE(downloadedFontEntry);
-}
-
-bool gfxDownloadedFcFontEntry::SetCairoFace(cairo_font_face_t *aFace)
-{
-    if (CAIRO_STATUS_SUCCESS !=
-        cairo_font_face_set_user_data(aFace, &sFontEntryKey, this,
-                                      ReleaseDownloadedFontEntry))
-        return false;
-
-    // Hold a reference to this font entry to keep the font face data.
-    NS_ADDREF(this);
-    return true;
-}
-
-hb_blob_t *
-gfxDownloadedFcFontEntry::GetFontTable(uint32_t aTableTag)
-{
-    // The entry already owns the (sanitized) sfnt data in mFontData,
-    // so we can just return a blob that "wraps" the appropriate chunk of it.
-    // The blob should not attempt to free its data, as the entire sfnt data
-    // will be freed when the font entry is deleted.
-    return gfxFontUtils::GetTableFromFontData(mFontData, aTableTag);
-}
-
-/*
- * gfxFcFont
- *
- * This is a gfxFont implementation using a CAIRO_FONT_TYPE_FT
- * cairo_scaled_font created from an FcPattern.
- */
-
-class gfxFcFont : public gfxFontconfigFontBase {
-public:
-    virtual ~gfxFcFont();
-    static already_AddRefed<gfxFcFont>
-    GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern,
-                  const gfxFontStyle *aFontStyle);
-
-    // return a cloned font resized and offset to simulate sub/superscript glyphs
-    virtual already_AddRefed<gfxFont>
-    GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel) override;
-
-protected:
-    virtual already_AddRefed<gfxFont> MakeScaledFont(gfxFontStyle *aFontStyle,
-                                                     gfxFloat aFontScale);
-    virtual already_AddRefed<gfxFont> GetSmallCapsFont() override;
-
-private:
-    gfxFcFont(cairo_scaled_font_t *aCairoFont,
-              FcPattern *aPattern,
-              gfxFcFontEntry *aFontEntry,
-              const gfxFontStyle *aFontStyle);
-
-    // key for locating a gfxFcFont corresponding to a cairo_scaled_font
-    static cairo_user_data_key_t sGfxFontKey;
-};
-
-/**
- * gfxFcFontSet:
- *
- * Translation from a desired FcPattern to a sorted set of font references
- * (fontconfig cache data) and (when needed) fonts.
- */
-
-class gfxFcFontSet final {
-public:
-    NS_INLINE_DECL_REFCOUNTING(gfxFcFontSet)
-    
-    explicit gfxFcFontSet(FcPattern *aPattern,
-                               gfxUserFontSet *aUserFontSet)
-        : mSortPattern(aPattern), mUserFontSet(aUserFontSet),
-          mFcFontsTrimmed(0),
-          mHaveFallbackFonts(false)
-    {
-        bool waitForUserFont;
-        mFcFontSet = SortPreferredFonts(waitForUserFont);
-        mWaitingForUserFont = waitForUserFont;
-    }
-
-    // A reference is held by the FontSet.
-    // The caller may add a ref to keep the font alive longer than the FontSet.
-    gfxFcFont *GetFontAt(uint32_t i, const gfxFontStyle *aFontStyle)
-    {
-        if (i >= mFonts.Length() || !mFonts[i].mFont) { 
-            // GetFontPatternAt sets up mFonts
-            FcPattern *fontPattern = GetFontPatternAt(i);
-            if (!fontPattern)
-                return nullptr;
-
-            mFonts[i].mFont =
-                gfxFcFont::GetOrMakeFont(mSortPattern, fontPattern,
-                                         aFontStyle);
-        }
-        return mFonts[i].mFont;
-    }
-
-    FcPattern *GetFontPatternAt(uint32_t i);
-
-    bool WaitingForUserFont() const {
-        return mWaitingForUserFont;
-    }
-
-private:
-    // Private destructor, to discourage deletion outside of Release():
-    ~gfxFcFontSet()
-    {
-    }
-
-    nsReturnRef<FcFontSet> SortPreferredFonts(bool& aWaitForUserFont);
-    nsReturnRef<FcFontSet> SortFallbackFonts();
-
-    struct FontEntry {
-        explicit FontEntry(FcPattern *aPattern) : mPattern(aPattern) {}
-        nsCountedRef<FcPattern> mPattern;
-        RefPtr<gfxFcFont> mFont;
-    };
-
-    struct LangSupportEntry {
-        LangSupportEntry(FcChar8 *aLang, FcLangResult aSupport) :
-            mLang(aLang), mBestSupport(aSupport) {}
-        FcChar8 *mLang;
-        FcLangResult mBestSupport;
-    };
-
-public:
-    // public for nsTArray
-    class LangComparator {
-    public:
-        bool Equals(const LangSupportEntry& a, const FcChar8 *b) const
-        {
-            return FcStrCmpIgnoreCase(a.mLang, b) == 0;
-        }
-    };
-
-private:
-    // The requested pattern
-    nsCountedRef<FcPattern> mSortPattern;
-    // Fonts from @font-face rules
-    RefPtr<gfxUserFontSet> mUserFontSet;
-    // A (trimmed) list of font patterns and fonts that is built up as
-    // required.
-    nsTArray<FontEntry> mFonts;
-    // Holds a list of font patterns that will be trimmed.  This is first set
-    // to a list of preferred fonts.  Then, if/when all the preferred fonts
-    // have been trimmed and added to mFonts, this is set to a list of
-    // fallback fonts.
-    nsAutoRef<FcFontSet> mFcFontSet;
-    // The set of characters supported by the fonts in mFonts.
-    nsAutoRef<FcCharSet> mCharSet;
-    // The index of the next font in mFcFontSet that has not yet been
-    // considered for mFonts.
-    int mFcFontsTrimmed;
-    // True iff fallback fonts are either stored in mFcFontSet or have been
-    // trimmed and added to mFonts (so that mFcFontSet is nullptr).
-    bool mHaveFallbackFonts;
-    // True iff there was a user font set with pending downloads,
-    // so the set may be updated when downloads complete
-    bool mWaitingForUserFont;
-};
-
-// Find the FcPattern for an @font-face font suitable for CSS family |aFamily|
-// and style |aStyle| properties.
-static const nsTArray< nsCountedRef<FcPattern> >*
-FindFontPatterns(gfxUserFontSet *mUserFontSet,
-                 const nsACString &aFamily, uint8_t aStyle,
-                 uint16_t aWeight, int16_t aStretch,
-                 bool& aWaitForUserFont)
-{
-    // Convert to UTF16
-    NS_ConvertUTF8toUTF16 utf16Family(aFamily);
-
-    // needsBold is not used here.  Instead synthetic bold is enabled through
-    // FcFontRenderPrepare when the weight in the requested pattern is
-    // compared against the weight in the font pattern.
-    bool needsBold;
-
-    gfxFontStyle style;
-    style.style = aStyle;
-    style.weight = aWeight;
-    style.stretch = aStretch;
-
-    gfxUserFcFontEntry *fontEntry = nullptr;
-    gfxFontFamily *family = mUserFontSet->LookupFamily(utf16Family);
-    if (family) {
-        gfxUserFontEntry* userFontEntry =
-            mUserFontSet->FindUserFontEntryAndLoad(family, style, needsBold,
-                                                   aWaitForUserFont);
-        if (userFontEntry) {
-            fontEntry = static_cast<gfxUserFcFontEntry*>
-                (userFontEntry->GetPlatformFontEntry());
-        }
-
-        // Accept synthetic oblique for italic and oblique.
-        // xxx - this isn't really ideal behavior, for docs that only use a
-        //       single italic face it will also pull down the normal face
-        //       and probably never use it
-        if (!fontEntry && aStyle != NS_FONT_STYLE_NORMAL) {
-            style.style = NS_FONT_STYLE_NORMAL;
-            userFontEntry =
-                mUserFontSet->FindUserFontEntryAndLoad(family, style,
-                                                       needsBold,
-                                                       aWaitForUserFont);
-            if (userFontEntry) {
-                fontEntry = static_cast<gfxUserFcFontEntry*>
-                    (userFontEntry->GetPlatformFontEntry());
-            }
-        }
-    }
-
-    if (!fontEntry) {
-        return nullptr;
-    }
-
-    return &fontEntry->GetPatterns();
-}
-
-typedef FcBool (*FcPatternRemoveFunction)(FcPattern *p, const char *object,
-                                          int id);
-
-// FcPatternRemove is available in fontconfig-2.3.0 (2005)
-static FcBool
-moz_FcPatternRemove(FcPattern *p, const char *object, int id)
-{
-    static FcPatternRemoveFunction sFcPatternRemovePtr =
-        reinterpret_cast<FcPatternRemoveFunction>
-        (FindFunctionSymbol("FcPatternRemove"));
-
-    if (!sFcPatternRemovePtr)
-        return FcFalse;
-
-    return (*sFcPatternRemovePtr)(p, object, id);
-}
-
-// fontconfig prefers a matching family or lang to pixelsize of bitmap
-// fonts.  CSS suggests a tolerance of 20% on pixelsize.
-static bool
-SizeIsAcceptable(FcPattern *aFont, double aRequestedSize)
-{
-    double size;
-    int v = 0;
-    while (FcPatternGetDouble(aFont,
-                              FC_PIXEL_SIZE, v, &size) == FcResultMatch) {
-        ++v;
-        if (5.0 * fabs(size - aRequestedSize) < aRequestedSize)
-            return true;
-    }
-
-    // No size means scalable
-    return v == 0;
-}
-
-// Sorting only the preferred fonts first usually saves having to sort through
-// every font on the system.
-nsReturnRef<FcFontSet>
-gfxFcFontSet::SortPreferredFonts(bool &aWaitForUserFont)
-{
-    aWaitForUserFont = false;
-
-    gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils();
-    if (!utils)
-        return nsReturnRef<FcFontSet>();
-
-    // The list of families in mSortPattern has values with both weak and
-    // strong bindings.  Values with strong bindings should be preferred.
-    // Values with weak bindings are default fonts that should be considered
-    // only when the font provides the best support for a requested language
-    // or after other fonts have satisfied all the requested languages.
-    //
-    // There are no direct fontconfig APIs to get the binding type.  The
-    // binding only takes effect in the sort and match functions.
-
-    // |requiredLangs| is a list of requested languages that have not yet been
-    // satisfied.  gfxFontconfigUtils only sets one FC_LANG property value,
-    // but FcConfigSubstitute may add more values (e.g. prepending "en" to
-    // "ja" will use western fonts to render Latin/Arabic numerals in Japanese
-    // text.)
-    AutoTArray<LangSupportEntry,10> requiredLangs;
-    for (int v = 0; ; ++v) {
-        FcChar8 *lang;
-        FcResult result = FcPatternGetString(mSortPattern, FC_LANG, v, &lang);
-        if (result != FcResultMatch) {
-            // No need to check FcPatternGetLangSet() because
-            // gfxFontconfigUtils sets only a string value for FC_LANG and
-            // FcConfigSubstitute cannot add LangSets.
-            NS_ASSERTION(result != FcResultTypeMismatch,
-                         "Expected a string for FC_LANG");
-            break;
-        }
-
-        if (!requiredLangs.Contains(lang, LangComparator())) {
-            FcLangResult bestLangSupport = utils->GetBestLangSupport(lang);
-            if (bestLangSupport != FcLangDifferentLang) {
-                requiredLangs.
-                    AppendElement(LangSupportEntry(lang, bestLangSupport));
-            }
-        }
-    }
-
-    nsAutoRef<FcFontSet> fontSet(FcFontSetCreate());
-    if (!fontSet)
-        return fontSet.out();
-
-    // FcDefaultSubstitute() ensures a slant on mSortPattern, but, if that ever
-    // doesn't happen, Roman will be used.
-    int requestedSlant = FC_SLANT_ROMAN;
-    FcPatternGetInteger(mSortPattern, FC_SLANT, 0, &requestedSlant);
-    double requestedSize = -1.0;
-    FcPatternGetDouble(mSortPattern, FC_PIXEL_SIZE, 0, &requestedSize);
-
-    nsTHashtable<gfxFontconfigUtils::DepFcStrEntry> existingFamilies(32);
-    FcChar8 *family;
-    for (int v = 0;
-         FcPatternGetString(mSortPattern,
-                            FC_FAMILY, v, &family) == FcResultMatch; ++v) {
-        const nsTArray< nsCountedRef<FcPattern> > *familyFonts = nullptr;
-
-        // Is this an @font-face family?
-        bool isUserFont = false;
-        if (mUserFontSet) {
-            // Have some @font-face definitions
-
-            nsDependentCString cFamily(gfxFontconfigUtils::ToCString(family));
-            NS_NAMED_LITERAL_CSTRING(userPrefix, FONT_FACE_FAMILY_PREFIX);
-
-            if (StringBeginsWith(cFamily, userPrefix)) {
-                isUserFont = true;
-
-                // Trim off the prefix
-                nsDependentCSubstring cssFamily(cFamily, userPrefix.Length());
-
-                uint8_t thebesStyle =
-                    gfxFontconfigUtils::FcSlantToThebesStyle(requestedSlant);
-                uint16_t thebesWeight =
-                    gfxFontconfigUtils::GetThebesWeight(mSortPattern);
-                int16_t thebesStretch =
-                    gfxFontconfigUtils::GetThebesStretch(mSortPattern);
-
-                bool waitForUserFont;
-                familyFonts = FindFontPatterns(mUserFontSet, cssFamily,
-                                               thebesStyle,
-                                               thebesWeight, thebesStretch,
-                                               waitForUserFont);
-                if (waitForUserFont) {
-                    aWaitForUserFont = true;
-                }
-            }
-        }
-
-        if (!isUserFont) {
-            familyFonts = &utils->GetFontsForFamily(family);
-        }
-
-        if (!familyFonts || familyFonts->Length() == 0) {
-            // There are no fonts matching this family, so there is no point
-            // in searching for this family in the FontSort.
-            //
-            // Perhaps the original pattern should be retained for
-            // FcFontRenderPrepare.  However, the only a useful config
-            // substitution test against missing families that i can imagine
-            // would only be interested in the preferred family
-            // (qual="first"), so always keep the first family and use the
-            // same pattern for Sort and RenderPrepare.
-            if (v != 0 && moz_FcPatternRemove(mSortPattern, FC_FAMILY, v)) {
-                --v;
-            }
-            continue;
-        }
-
-        // Aliases seem to often end up occurring more than once, but
-        // duplicate families can't be removed from the sort pattern without
-        // knowing whether duplicates have the same binding.
-        gfxFontconfigUtils::DepFcStrEntry *familyEntry =
-            existingFamilies.PutEntry(family);
-        if (familyEntry) {
-            if (familyEntry->mKey) // old entry
-                continue;
-
-            familyEntry->mKey = family; // initialize new entry
-        }
-
-        for (uint32_t f = 0; f < familyFonts->Length(); ++f) {
-            FcPattern *font = familyFonts->ElementAt(f);
-
-            // Fix up the family name of user-font patterns, as the same
-            // font entry may be used (via the UserFontCache) for multiple
-            // CSS family names
-            if (isUserFont) {
-                font = FcPatternDuplicate(font);
-                FcPatternDel(font, FC_FAMILY);
-                FcPatternAddString(font, FC_FAMILY, family);
-            }
-
-            // User fonts are already filtered by slant (but not size) in
-            // mUserFontSet->FindUserFontEntry().
-            if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize))
-                continue;
-
-            for (uint32_t r = 0; r < requiredLangs.Length(); ++r) {
-                const LangSupportEntry& langEntry = requiredLangs[r];
-                FcLangResult support =
-                    gfxFontconfigUtils::GetLangSupport(font, langEntry.mLang);
-                if (support <= langEntry.mBestSupport) { // lower is better
-                    requiredLangs.RemoveElementAt(r);
-                    --r;
-                }
-            }
-
-            // FcFontSetDestroy will remove a reference but FcFontSetAdd
-            // does _not_ take a reference!
-            if (FcFontSetAdd(fontSet, font)) {
-                // We don't add a reference here for user fonts, because we're
-                // using a local clone of the pattern (see above) in order to
-                // override the family name
-                if (!isUserFont) {
-                    FcPatternReference(font);
-                }
-            }
-        }
-    }
-
-    FcPattern *truncateMarker = nullptr;
-    for (uint32_t r = 0; r < requiredLangs.Length(); ++r) {
-        const nsTArray< nsCountedRef<FcPattern> >& langFonts =
-            utils->GetFontsForLang(requiredLangs[r].mLang);
-
-        bool haveLangFont = false;
-        for (uint32_t f = 0; f < langFonts.Length(); ++f) {
-            FcPattern *font = langFonts[f];
-            if (requestedSize != -1.0 && !SizeIsAcceptable(font, requestedSize))
-                continue;
-
-            haveLangFont = true;
-            if (FcFontSetAdd(fontSet, font)) {
-                FcPatternReference(font);
-            }
-        }
-
-        if (!haveLangFont && langFonts.Length() > 0) {
-            // There is a font that supports this language but it didn't pass
-            // the slant and size criteria.  Weak default font families should
-            // not be considered until the language has been satisfied.
-            //
-            // Insert a font that supports the language so that it will mark
-            // the position of fonts from weak families in the sorted set and
-            // they can be removed.  The language and weak families will be
-            // considered in the fallback fonts, which use fontconfig's
-            // algorithm.
-            //
-            // Of the fonts that don't meet slant and size criteria, strong
-            // default font families should be considered before (other) fonts
-            // for this language, so this marker font will be removed (as well
-            // as the fonts from weak families), and strong families will be
-            // reconsidered in the fallback fonts.
-            FcPattern *font = langFonts[0];
-            if (FcFontSetAdd(fontSet, font)) {
-                FcPatternReference(font);
-                truncateMarker = font;
-            }
-            break;
-        }
-    }
-
-    FcFontSet *sets[1] = { fontSet };
-    FcResult result;
-#ifdef SOLARIS
-    // Get around a crash of FcFontSetSort when FcConfig is nullptr
-    // Solaris's FcFontSetSort needs an FcConfig (bug 474758)
-    fontSet.own(FcFontSetSort(FcConfigGetCurrent(), sets, 1, mSortPattern,
-                              FcFalse, nullptr, &result));
-#else
-    fontSet.own(FcFontSetSort(nullptr, sets, 1, mSortPattern,
-                              FcFalse, nullptr, &result));
-#endif
-
-    if (truncateMarker != nullptr && fontSet) {
-        nsAutoRef<FcFontSet> truncatedSet(FcFontSetCreate());
-
-        for (int f = 0; f < fontSet->nfont; ++f) {
-            FcPattern *font = fontSet->fonts[f];
-            if (font == truncateMarker)
-                break;
-
-            if (FcFontSetAdd(truncatedSet, font)) {
-                FcPatternReference(font);
-            }
-        }
-
-        fontSet.steal(truncatedSet);
-    }
-
-    return fontSet.out();
-}
-
-nsReturnRef<FcFontSet>
-gfxFcFontSet::SortFallbackFonts()
-{
-    // Setting trim to FcTrue would provide a much smaller (~ 1/10) FcFontSet,
-    // but would take much longer due to comparing all the character sets.
-    //
-    // The references to fonts in this FcFontSet are almost free
-    // as they are pointers into mmaped cache files.
-    //
-    // GetFontPatternAt() will trim lazily if and as needed, which will also
-    // remove duplicates of preferred fonts.
-    FcResult result;
-    return nsReturnRef<FcFontSet>(FcFontSort(nullptr, mSortPattern,
-                                             FcFalse, nullptr, &result));
-}
-
-// GetFontAt relies on this setting up all patterns up to |i|.
-FcPattern *
-gfxFcFontSet::GetFontPatternAt(uint32_t i)
-{
-    while (i >= mFonts.Length()) {
-        while (!mFcFontSet) {
-            if (mHaveFallbackFonts)
-                return nullptr;
-
-            mFcFontSet = SortFallbackFonts();
-            mHaveFallbackFonts = true;
-            mFcFontsTrimmed = 0;
-            // Loop to test that mFcFontSet is non-nullptr.
-        }
-
-        while (mFcFontsTrimmed < mFcFontSet->nfont) {
-            FcPattern *font = mFcFontSet->fonts[mFcFontsTrimmed];
-            ++mFcFontsTrimmed;
-
-            if (mFonts.Length() != 0) {
-                // See if the next font provides support for any extra
-                // characters.  Most often the next font is not going to
-                // support more characters so check for a SubSet first before
-                // allocating a new CharSet with Union.
-                FcCharSet *supportedChars = mCharSet;
-                if (!supportedChars) {
-                    FcPatternGetCharSet(mFonts[mFonts.Length() - 1].mPattern,
-                                        FC_CHARSET, 0, &supportedChars);
-                }
-
-                if (supportedChars) {
-                    FcCharSet *newChars = nullptr;
-                    FcPatternGetCharSet(font, FC_CHARSET, 0, &newChars);
-                    if (newChars) {
-                        if (FcCharSetIsSubset(newChars, supportedChars))
-                            continue;
-
-                        mCharSet.own(FcCharSetUnion(supportedChars, newChars));
-                    } else if (!mCharSet) {
-                        mCharSet.own(FcCharSetCopy(supportedChars));
-                    }
-                }
-            }
-
-            mFonts.AppendElement(font);
-            if (mFonts.Length() >= i)
-                break;
-        }
-
-        if (mFcFontsTrimmed == mFcFontSet->nfont) {
-            // finished with this font set
-            mFcFontSet.reset();
-        }
-    }
-
-    return mFonts[i].mPattern;
-}
-
-#ifdef MOZ_WIDGET_GTK
-static void ApplyGdkScreenFontOptions(FcPattern *aPattern);
-#endif
-
-// Apply user settings and defaults to pattern in preparation for matching.
-static void
-PrepareSortPattern(FcPattern *aPattern, double aFallbackSize,
-                   double aSizeAdjustFactor, bool aIsPrinterFont)
-{
-    FcConfigSubstitute(nullptr, aPattern, FcMatchPattern);
-
-    // This gets cairo_font_options_t for the Screen.  We should have
-    // different font options for printing (no hinting) but we are not told
-    // what we are measuring for.
-    //
-    // If cairo adds support for lcd_filter, gdk will not provide the default
-    // setting for that option.  We could get the default setting by creating
-    // an xlib surface once, recording its font_options, and then merging the
-    // gdk options.
-    //
-    // Using an xlib surface would also be an option to get Screen font
-    // options for non-GTK X11 toolkits, but less efficient than using GDK to
-    // pick up dynamic changes.
-    if(aIsPrinterFont) {
-       cairo_font_options_t *options = cairo_font_options_create();
-       cairo_font_options_set_hint_style (options, CAIRO_HINT_STYLE_NONE);
-       cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
-       cairo_ft_font_options_substitute(options, aPattern);
-       cairo_font_options_destroy(options);
-       FcPatternAddBool(aPattern, PRINTING_FC_PROPERTY, FcTrue);
-    } else {
-#ifdef MOZ_WIDGET_GTK
-       ApplyGdkScreenFontOptions(aPattern);
-#endif
-    }
-
-    // Protect against any fontconfig settings that may have incorrectly
-    // modified the pixelsize, and consider aSizeAdjustFactor.
-    double size = aFallbackSize;
-    if (FcPatternGetDouble(aPattern, FC_PIXEL_SIZE, 0, &size) != FcResultMatch
-        || aSizeAdjustFactor != 1.0) {
-        FcPatternDel(aPattern, FC_PIXEL_SIZE);
-        FcPatternAddDouble(aPattern, FC_PIXEL_SIZE, size * aSizeAdjustFactor);
-    }
-
-    FcDefaultSubstitute(aPattern);
-}
-
-/**
- ** gfxPangoFontGroup
- **/
-
-gfxPangoFontGroup::gfxPangoFontGroup(const FontFamilyList& aFontFamilyList,
-                                     const gfxFontStyle *aStyle,
-                                     gfxUserFontSet *aUserFontSet,
-                                     gfxFloat aDevToCssSize)
-    : gfxFontGroup(aFontFamilyList, aStyle, nullptr, aUserFontSet, aDevToCssSize),
-      mPangoLanguage(GuessPangoLanguage(aStyle->language))
-{
-    // This language is passed to the font for shaping.
-    // Shaping doesn't know about lang groups so make it a real language.
-    if (mPangoLanguage) {
-        mStyle.language = NS_Atomize(pango_language_to_string(mPangoLanguage));
-    }
-
-    // dummy entry, will be replaced when actually needed
-    mFonts.AppendElement(FamilyFace());
-    mSkipUpdateUserFonts = true;
-}
-
-gfxPangoFontGroup::~gfxPangoFontGroup()
-{
-}
-
-gfxFontGroup *
-gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
-{
-    return new gfxPangoFontGroup(mFamilyList, aStyle, mUserFontSet, mDevToCssSize);
-}
-
-void
-gfxPangoFontGroup::FindGenericFontsPFG(FontFamilyType aGenericType,
-                                       nsIAtom *aLanguage,
-                                       void *aClosure)
-{
-    AutoTArray<nsString, 5> resolvedGenerics;
-    ResolveGenericFontNamesPFG(aGenericType, aLanguage, resolvedGenerics);
-    uint32_t g = 0, numGenerics = resolvedGenerics.Length();
-    for (g = 0; g < numGenerics; g++) {
-        FindPlatformFontPFG(resolvedGenerics[g], false, aClosure);
-    }
-}
-
-/* static */ void
-gfxPangoFontGroup::ResolveGenericFontNamesPFG(FontFamilyType aGenericType,
-                                              nsIAtom *aLanguage,
-                                              nsTArray<nsString>& aGenericFamilies)
-{
-    static const char kGeneric_serif[] = "serif";
-    static const char kGeneric_sans_serif[] = "sans-serif";
-    static const char kGeneric_monospace[] = "monospace";
-    static const char kGeneric_cursive[] = "cursive";
-    static const char kGeneric_fantasy[] = "fantasy";
-
-    // treat -moz-fixed as monospace
-    if (aGenericType == eFamily_moz_fixed) {
-        aGenericType = eFamily_monospace;
-    }
-
-    // type should be standard generic type at this point
-    NS_ASSERTION(aGenericType >= eFamily_serif &&
-                 aGenericType <= eFamily_fantasy,
-                 "standard generic font family type required");
-
-    // create the lang string
-    nsIAtom *langGroupAtom = nullptr;
-    nsAutoCString langGroupString;
-    if (aLanguage) {
-        if (!gLangService) {
-            CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
-        }
-        if (gLangService) {
-            nsresult rv;
-            langGroupAtom = gLangService->GetLanguageGroup(aLanguage, &rv);
-        }
-    }
-    if (!langGroupAtom) {
-        langGroupAtom = nsGkAtoms::Unicode;
-    }
-    langGroupAtom->ToUTF8String(langGroupString);
-
-    // map generic type to string
-    const char *generic = nullptr;
-    switch (aGenericType) {
-        case eFamily_serif:
-            generic = kGeneric_serif;
-            break;
-        case eFamily_sans_serif:
-            generic = kGeneric_sans_serif;
-            break;
-        case eFamily_monospace:
-            generic = kGeneric_monospace;
-            break;
-        case eFamily_cursive:
-            generic = kGeneric_cursive;
-            break;
-        case eFamily_fantasy:
-            generic = kGeneric_fantasy;
-            break;
-        default:
-            break;
-    }
-
-    if (!generic) {
-        return;
-    }
-
-    aGenericFamilies.Clear();
-
-    // load family for "font.name.generic.lang"
-    nsAutoCString prefFontName("font.name.");
-    prefFontName.Append(generic);
-    prefFontName.Append('.');
-    prefFontName.Append(langGroupString);
-    gfxFontUtils::AppendPrefsFontList(prefFontName.get(),
-                                      aGenericFamilies);
-
-    // if lang has pref fonts, also load fonts for "font.name-list.generic.lang"
-    if (!aGenericFamilies.IsEmpty()) {
-        nsAutoCString prefFontListName("font.name-list.");
-        prefFontListName.Append(generic);
-        prefFontListName.Append('.');
-        prefFontListName.Append(langGroupString);
-        gfxFontUtils::AppendPrefsFontList(prefFontListName.get(),
-                                          aGenericFamilies);
-    }
-
-#if 0  // dump out generic mappings
-    printf("%s ===> ", prefFontName.get());
-    for (uint32_t k = 0; k < aGenericFamilies.Length(); k++) {
-        if (k > 0) printf(", ");
-        printf("%s", NS_ConvertUTF16toUTF8(aGenericFamilies[k]).get());
-    }
-    printf("\n");
-#endif
-}
-
-void gfxPangoFontGroup::EnumerateFontListPFG(nsIAtom *aLanguage, void *aClosure)
-{
-    // initialize fonts in the font family list
-    const nsTArray<FontFamilyName>& fontlist = mFamilyList.GetFontlist();
-
-    // lookup fonts in the fontlist
-    uint32_t i, numFonts = fontlist.Length();
-    for (i = 0; i < numFonts; i++) {
-        const FontFamilyName& name = fontlist[i];
-        if (name.IsNamed()) {
-            FindPlatformFontPFG(name.mName, true, aClosure);
-        } else {
-            FindGenericFontsPFG(name.mType, aLanguage, aClosure);
-        }
-    }
-
-    // if necessary, append default generic onto the end
-    if (mFamilyList.GetDefaultFontType() != eFamily_none &&
-        !mFamilyList.HasDefaultGeneric()) {
-        FindGenericFontsPFG(mFamilyList.GetDefaultFontType(),
-                            aLanguage, aClosure);
-    }
-}
-
-void
-gfxPangoFontGroup::FindPlatformFontPFG(const nsAString& fontName,
-                                       bool aUseFontSet,
-                                       void *aClosure)
-{
-    nsTArray<nsString> *list = static_cast<nsTArray<nsString>*>(aClosure);
-
-    if (!list->Contains(fontName)) {
-        // names present in the user fontset are not matched against system fonts
-        if (aUseFontSet && mUserFontSet && mUserFontSet->HasFamily(fontName)) {
-            nsAutoString userFontName =
-                NS_LITERAL_STRING(FONT_FACE_FAMILY_PREFIX) + fontName;
-            list->AppendElement(userFontName);
-        } else {
-            list->AppendElement(fontName);
-        }
-    }
-}
-
-gfxFcFont *
-gfxPangoFontGroup::GetBaseFont()
-{
-    if (mFonts[0].Font() == nullptr) {
-        gfxFont* font = GetBaseFontSet()->GetFontAt(0, GetStyle());
-        mFonts[0] = FamilyFace(nullptr, font);
-    }
-
-    return static_cast<gfxFcFont*>(mFonts[0].Font());
-}
-
-gfxFont*
-gfxPangoFontGroup::GetFirstValidFont(uint32_t aCh)
-{
-    return GetFontAt(0);
-}
-
-gfxFont *
-gfxPangoFontGroup::GetFontAt(int32_t i, uint32_t aCh)
-{
-    // If it turns out to be hard for all clients that cache font
-    // groups to call UpdateUserFonts at appropriate times, we could
-    // instead consider just calling UpdateUserFonts from someplace
-    // more central (such as here).
-    NS_ASSERTION(!mUserFontSet || mCurrGeneration == GetGeneration(),
-                 "Whoever was caching this font group should have "
-                 "called UpdateUserFonts on it");
-
-    NS_PRECONDITION(i == 0, "Only have one font");
-
-    return GetBaseFont();
-}
-
-void
-gfxPangoFontGroup::UpdateUserFonts()
-{
-    uint64_t newGeneration = GetGeneration();
-    if (newGeneration == mCurrGeneration)
-        return;
-
-    mFonts[0] = FamilyFace();
-    mFontSets.Clear();
-    ClearCachedData();
-    mCurrGeneration = newGeneration;
-}
-
-already_AddRefed<gfxFcFontSet>
-gfxPangoFontGroup::MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
-                               nsAutoRef<FcPattern> *aMatchPattern)
-{
-    const char *lang = pango_language_to_string(aLang);
-
-    RefPtr<nsIAtom> langGroup;
-    if (aLang != mPangoLanguage) {
-        // Set up langGroup for Mozilla's font prefs.
-        langGroup = NS_Atomize(lang);
-    }
-
-    AutoTArray<nsString, 20> fcFamilyList;
-    EnumerateFontListPFG(langGroup ? langGroup.get() : mStyle.language.get(),
-                         &fcFamilyList);
-
-    // To consider: A fontset cache here could be helpful.
-
-    // Get a pattern suitable for matching.
-    nsAutoRef<FcPattern> pattern
-        (gfxFontconfigUtils::NewPattern(fcFamilyList, mStyle, lang));
-
-    PrepareSortPattern(pattern, mStyle.size, aSizeAdjustFactor, mStyle.printerFont);
-
-    RefPtr<gfxFcFontSet> fontset =
-        new gfxFcFontSet(pattern, mUserFontSet);
-
-    mSkipDrawing = fontset->WaitingForUserFont();
-
-    if (aMatchPattern)
-        aMatchPattern->steal(pattern);
-
-    return fontset.forget();
-}
-
-gfxPangoFontGroup::
-FontSetByLangEntry::FontSetByLangEntry(PangoLanguage *aLang,
-                                       gfxFcFontSet *aFontSet)
-    : mLang(aLang), mFontSet(aFontSet)
-{
-}
-
-gfxFcFontSet *
-gfxPangoFontGroup::GetFontSet(PangoLanguage *aLang)
-{
-    GetBaseFontSet(); // sets mSizeAdjustFactor and mFontSets[0]
-
-    if (!aLang)
-        return mFontSets[0].mFontSet;
-
-    for (uint32_t i = 0; i < mFontSets.Length(); ++i) {
-        if (mFontSets[i].mLang == aLang)
-            return mFontSets[i].mFontSet;
-    }
-
-    RefPtr<gfxFcFontSet> fontSet =
-        MakeFontSet(aLang, mSizeAdjustFactor);
-    mFontSets.AppendElement(FontSetByLangEntry(aLang, fontSet));
-
-    return fontSet;
-}
-
-already_AddRefed<gfxFont>
-gfxPangoFontGroup::FindFontForChar(uint32_t aCh, uint32_t aPrevCh,
-                                   uint32_t aNextCh, Script aRunScript,
-                                   gfxFont *aPrevMatchedFont,
-                                   uint8_t *aMatchType)
-{
-    if (aPrevMatchedFont) {
-        // Don't switch fonts for control characters, regardless of
-        // whether they are present in the current font, as they won't
-        // actually be rendered (see bug 716229)
-        uint8_t category = GetGeneralCategory(aCh);
-        if (category == HB_UNICODE_GENERAL_CATEGORY_CONTROL) {
-            return RefPtr<gfxFont>(aPrevMatchedFont).forget();
-        }
-
-        // if this character is a join-control or the previous is a join-causer,
-        // use the same font as the previous range if we can
-        if (gfxFontUtils::IsJoinControl(aCh) ||
-            gfxFontUtils::IsJoinCauser(aPrevCh)) {
-            if (aPrevMatchedFont->HasCharacter(aCh)) {
-                return RefPtr<gfxFont>(aPrevMatchedFont).forget();
-            }
-        }
-    }
-
-    // if this character is a variation selector,
-    // use the previous font regardless of whether it supports VS or not.
-    // otherwise the text run will be divided.
-    if (gfxFontUtils::IsVarSelector(aCh)) {
-        if (aPrevMatchedFont) {
-            return RefPtr<gfxFont>(aPrevMatchedFont).forget();
-        }
-        // VS alone. it's meaningless to search different fonts
-        return nullptr;
-    }
-
-    // The real fonts that fontconfig provides for generic/fallback families
-    // depend on the language used, so a different FontSet is used for each
-    // language (except for the variation below).
-    //
-    //   With most fontconfig configurations any real family names prior to a
-    //   fontconfig generic with corresponding fonts installed will still lead
-    //   to the same leading fonts in each FontSet.
-    //
-    //   There is an inefficiency here therefore because the same base FontSet
-    //   could often be used if these real families support the character.
-    //   However, with fontconfig aliases, it is difficult to distinguish
-    //   where exactly alias fonts end and generic/fallback fonts begin.
-    //
-    // The variation from pure language-based matching used here is that the
-    // same primary/base font is always used irrespective of the language.
-    // This provides that SCRIPT_COMMON characters are consistently rendered
-    // with the same font (bug 339513 and bug 416725).  This is particularly
-    // important with the word cache as script can't be reliably determined
-    // from surrounding words.  It also often avoids the unnecessary extra
-    // FontSet efficiency mentioned above.
-    //
-    // However, in two situations, the base font is not checked before the
-    // language-specific FontSet.
-    //
-    //   1. When we don't have a language to make a good choice for
-    //      the base font.
-    //
-    //   2. For system fonts, use the default Pango behavior to give
-    //      consistency with other apps.  This is relevant when un-localized
-    //      builds are run in non-Latin locales.  This special-case probably
-    //      wouldn't be necessary but for bug 91190.
-
-    gfxFcFontSet *fontSet = GetBaseFontSet();
-    uint32_t nextFont = 0;
-    FcPattern *basePattern = nullptr;
-    if (!mStyle.systemFont && mPangoLanguage) {
-        basePattern = fontSet->GetFontPatternAt(0);
-        if (HasChar(basePattern, aCh)) {
-            *aMatchType = gfxTextRange::kFontGroup;
-            return RefPtr<gfxFont>(GetBaseFont()).forget();
-        }
-
-        nextFont = 1;
-    }
-
-    // Our MOZ_SCRIPT_* codes may not match the PangoScript enumeration values
-    // (if we're using ICU's codes), so convert by mapping through ISO 15924 tag.
-    // Note that PangoScript is defined to be compatible with GUnicodeScript:
-    // https://developer.gnome.org/pango/stable/pango-Scripts-and-Languages.html#PangoScript
-    const hb_tag_t scriptTag = GetScriptTagForCode(aRunScript);
-    const PangoScript script =
-      (const PangoScript)hb_glib_script_from_script(hb_script_from_iso15924_tag(scriptTag));
-
-    // Might be nice to call pango_language_includes_script only once for the
-    // run rather than for each character.
-    PangoLanguage *scriptLang;
-    if ((!basePattern ||
-         !pango_language_includes_script(mPangoLanguage, script)) &&
-        (scriptLang = pango_script_get_sample_language(script))) {
-        fontSet = GetFontSet(scriptLang);
-        nextFont = 0;
-    }
-
-    for (uint32_t i = nextFont;
-         FcPattern *pattern = fontSet->GetFontPatternAt(i);
-         ++i) {
-        if (pattern == basePattern) {
-            continue; // already checked basePattern
-        }
-
-        if (HasChar(pattern, aCh)) {
-            *aMatchType = gfxTextRange::kFontGroup;
-            return RefPtr<gfxFont>(fontSet->GetFontAt(i, GetStyle())).forget();
-        }
-    }
-
-    return nullptr;
-}
-
-/**
- ** gfxFcFont
- **/
-
-cairo_user_data_key_t gfxFcFont::sGfxFontKey;
-
-gfxFcFont::gfxFcFont(cairo_scaled_font_t *aCairoFont,
-                     FcPattern *aPattern,
-                     gfxFcFontEntry *aFontEntry,
-                     const gfxFontStyle *aFontStyle)
-    : gfxFontconfigFontBase(aCairoFont, aPattern, aFontEntry, aFontStyle)
-{
-    cairo_scaled_font_set_user_data(mScaledFont, &sGfxFontKey, this, nullptr);
-}
-
-gfxFcFont::~gfxFcFont()
-{
-    cairo_scaled_font_set_user_data(mScaledFont,
-                                    &sGfxFontKey,
-                                    nullptr,
-                                    nullptr);
-}
-
-already_AddRefed<gfxFont>
-gfxFcFont::GetSubSuperscriptFont(int32_t aAppUnitsPerDevPixel)
-{
-    gfxFontStyle style(*GetStyle());
-    style.AdjustForSubSuperscript(aAppUnitsPerDevPixel);
-    return MakeScaledFont(&style, style.size / GetStyle()->size);
-}
-
-already_AddRefed<gfxFont>
-gfxFcFont::MakeScaledFont(gfxFontStyle *aFontStyle, gfxFloat aScaleFactor)
-{
-    gfxFcFontEntry* fe = static_cast<gfxFcFontEntry*>(GetFontEntry());
-    RefPtr<gfxFont> font =
-        gfxFontCache::GetCache()->Lookup(fe, aFontStyle, nullptr);
-    if (font) {
-        return font.forget();
-    }
-
-    cairo_matrix_t fontMatrix;
-    cairo_scaled_font_get_font_matrix(mScaledFont, &fontMatrix);
-    cairo_matrix_scale(&fontMatrix, aScaleFactor, aScaleFactor);
-
-    cairo_matrix_t ctm;
-    cairo_scaled_font_get_ctm(mScaledFont, &ctm);
-
-    cairo_font_options_t *options = cairo_font_options_create();
-    cairo_scaled_font_get_font_options(mScaledFont, options);
-
-    cairo_scaled_font_t *newFont =
-        cairo_scaled_font_create(cairo_scaled_font_get_font_face(mScaledFont),
-                                 &fontMatrix, &ctm, options);
-    cairo_font_options_destroy(options);
-
-    font = new gfxFcFont(newFont, GetPattern(), fe, aFontStyle);
-    gfxFontCache::GetCache()->AddNew(font);
-    cairo_scaled_font_destroy(newFont);
-
-    return font.forget();
-}
-
-already_AddRefed<gfxFont>
-gfxFcFont::GetSmallCapsFont()
-{
-    gfxFontStyle style(*GetStyle());
-    style.size *= SMALL_CAPS_SCALE_FACTOR;
-    style.variantCaps = NS_FONT_VARIANT_CAPS_NORMAL;
-    return MakeScaledFont(&style, SMALL_CAPS_SCALE_FACTOR);
-}
-
-/* static */ void
-gfxPangoFontGroup::Shutdown()
-{
-    // Resetting gFTLibrary in case this is wanted again after a
-    // cairo_debug_reset_static_data.
-    gFTLibrary = nullptr;
-}
-
-/* static */ gfxFontEntry *
-gfxPangoFontGroup::NewFontEntry(const nsAString& aFontName,
-                                uint16_t aWeight,
-                                int16_t aStretch,
-                                uint8_t aStyle)
-{
-    gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils();
-    if (!utils)
-        return nullptr;
-
-    // The font face name from @font-face { src: local() } is not well
-    // defined.
-    //
-    // On MS Windows, this name gets compared with
-    // ENUMLOGFONTEXW::elfFullName, which for OpenType fonts seems to be the
-    // full font name from the name table.  For CFF OpenType fonts this is the
-    // same as the PostScript name, but for TrueType fonts it is usually
-    // different.
-    //
-    // On Mac, the font face name is compared with the PostScript name, even
-    // for TrueType fonts.
-    //
-    // Fontconfig only records the full font names, so the behavior here
-    // follows that on MS Windows.  However, to provide the possibility
-    // of aliases to compensate for variations, the font face name is passed
-    // through FcConfigSubstitute.
-
-    nsAutoRef<FcPattern> pattern(FcPatternCreate());
-    if (!pattern)
-        return nullptr;
-
-    NS_ConvertUTF16toUTF8 fullname(aFontName);
-    FcPatternAddString(pattern, FC_FULLNAME,
-                       gfxFontconfigUtils::ToFcChar8(fullname));
-    FcConfigSubstitute(nullptr, pattern, FcMatchPattern);
-
-    FcChar8 *name;
-    for (int v = 0;
-         FcPatternGetString(pattern, FC_FULLNAME, v, &name) == FcResultMatch;
-         ++v) {
-        const nsTArray< nsCountedRef<FcPattern> >& fonts =
-            utils->GetFontsForFullname(name);
-
-        if (fonts.Length() != 0)
-            return new gfxLocalFcFontEntry(aFontName,
-                                           aWeight,
-                                           aStretch,
-                                           aStyle,
-                                           fonts);
-    }
-
-    return nullptr;
-}
-
-/* static */ FT_Library
-gfxPangoFontGroup::GetFTLibrary()
-{
-    if (!gFTLibrary) {
-        // Use cairo's FT_Library so that cairo takes care of shutdown of the
-        // FT_Library after it has destroyed its font_faces, and FT_Done_Face
-        // has been called on each FT_Face, at least until this bug is fixed:
-        // https://bugs.freedesktop.org/show_bug.cgi?id=18857
-        //
-        // Cairo's FT_Library can be obtained from any cairo_scaled_font.  The
-        // font properties requested here are chosen to get an FT_Face that is
-        // likely to be also used elsewhere.
-        gfxFontStyle style;
-        RefPtr<gfxPangoFontGroup> fontGroup =
-            new gfxPangoFontGroup(FontFamilyList(eFamily_sans_serif),
-                                  &style, nullptr, 1.0);
-
-        gfxFcFont *font = fontGroup->GetBaseFont();
-        if (!font)
-            return nullptr;
-
-        gfxFT2LockedFace face(font);
-        if (!face.get())
-            return nullptr;
-
-        gFTLibrary = face.get()->glyph->library;
-    }
-
-    return gFTLibrary;
-}
-
-/* static */ gfxFontEntry *
-gfxPangoFontGroup::NewFontEntry(const nsAString& aFontName,
-                                uint16_t aWeight,
-                                int16_t aStretch,
-                                uint8_t aStyle,
-                                const uint8_t* aFontData,
-                                uint32_t aLength)
-{
-    // Ownership of aFontData is passed in here, and transferred to the
-    // new fontEntry, which will release it when no longer needed.
-
-    // Using face_index = 0 for the first face in the font, as we have no
-    // other information.  FT_New_Memory_Face checks for a nullptr FT_Library.
-    FT_Face face;
-    FT_Error error =
-        FT_New_Memory_Face(GetFTLibrary(), aFontData, aLength, 0, &face);
-    if (error != 0) {
-        free((void*)aFontData);
-        return nullptr;
-    }
-
-    return new gfxDownloadedFcFontEntry(aFontName, aWeight,
-                                        aStretch, aStyle,
-                                        aFontData, face);
-}
-
-
-static double
-GetPixelSize(FcPattern *aPattern)
-{
-    double size;
-    if (FcPatternGetDouble(aPattern,
-                           FC_PIXEL_SIZE, 0, &size) == FcResultMatch)
-        return size;
-
-    NS_NOTREACHED("No size on pattern");
-    return 0.0;
-}
-
-/**
- * The following gfxFcFonts are accessed from the cairo_scaled_font or created
- * from the FcPattern, not from the gfxFontCache hash table.  The gfxFontCache
- * hash table is keyed by desired family and style, whereas here we only know
- * actual family and style.  There may be more than one of these fonts with
- * the same family and style, but different PangoFont and actual font face.
- * 
- * The point of this is to record the exact font face for gfxTextRun glyph
- * indices.  The style of this font does not necessarily represent the exact
- * gfxFontStyle used to build the text run.  Notably, the language is not
- * recorded.
- */
-
-/* static */
-already_AddRefed<gfxFcFont>
-gfxFcFont::GetOrMakeFont(FcPattern *aRequestedPattern, FcPattern *aFontPattern,
-                         const gfxFontStyle *aFontStyle)
-{
-    nsAutoRef<FcPattern> renderPattern
-        (FcFontRenderPrepare(nullptr, aRequestedPattern, aFontPattern));
-
-    // If synthetic bold/italic is not allowed by the style, adjust the
-    // resulting pattern to match the actual properties of the font.
-    if (!aFontStyle->allowSyntheticWeight) {
-        int weight;
-        if (FcPatternGetInteger(aFontPattern, FC_WEIGHT, 0,
-                                &weight) == FcResultMatch) {
-            FcPatternDel(renderPattern, FC_WEIGHT);
-            FcPatternAddInteger(renderPattern, FC_WEIGHT, weight);
-        }
-    }
-    if (!aFontStyle->allowSyntheticStyle) {
-        int slant;
-        if (FcPatternGetInteger(aFontPattern, FC_SLANT, 0,
-                                &slant) == FcResultMatch) {
-            FcPatternDel(renderPattern, FC_SLANT);
-            FcPatternAddInteger(renderPattern, FC_SLANT, slant);
-        }
-    }
-
-    cairo_font_face_t *face =
-        cairo_ft_font_face_create_for_pattern(renderPattern);
-
-    // Reuse an existing font entry if available.
-    RefPtr<gfxFcFontEntry> fe = gfxFcFontEntry::LookupFontEntry(face);
-    if (!fe) {
-        gfxDownloadedFcFontEntry *downloadedFontEntry =
-            GetDownloadedFontEntry(aFontPattern);
-        if (downloadedFontEntry) {
-            // Web font
-            fe = downloadedFontEntry;
-            if (cairo_font_face_status(face) == CAIRO_STATUS_SUCCESS) {
-                // cairo_font_face_t is using the web font data.
-                // Hold a reference to the font entry to keep the font face
-                // data.
-                if (!downloadedFontEntry->SetCairoFace(face)) {
-                    // OOM.  Let cairo pick a fallback font
-                    cairo_font_face_destroy(face);
-                    face = cairo_ft_font_face_create_for_pattern(aRequestedPattern);
-                    fe = gfxFcFontEntry::LookupFontEntry(face);
-                }
-            }
-        }
-        if (!fe) {
-            // Get a unique name for the font face from the file and id.
-            nsAutoString name;
-            FcChar8 *fc_file;
-            if (FcPatternGetString(renderPattern,
-                                   FC_FILE, 0, &fc_file) == FcResultMatch) {
-                int index;
-                if (FcPatternGetInteger(renderPattern,
-                                        FC_INDEX, 0, &index) != FcResultMatch) {
-                    // cairo defaults to 0.
-                    index = 0;
-                }
-
-                AppendUTF8toUTF16(gfxFontconfigUtils::ToCString(fc_file), name);
-                if (index != 0) {
-                    name.Append('/');
-                    name.AppendInt(index);
-                }
-            }
-
-            fe = new gfxSystemFcFontEntry(face, aFontPattern, name);
-        }
-    }
-
-    gfxFontStyle style(*aFontStyle);
-    style.size = GetPixelSize(renderPattern);
-    style.style = gfxFontconfigUtils::GetThebesStyle(renderPattern);
-    style.weight = gfxFontconfigUtils::GetThebesWeight(renderPattern);
-
-    RefPtr<gfxFont> font =
-        gfxFontCache::GetCache()->Lookup(fe, &style, nullptr);
-    if (!font) {
-        // Note that a file/index pair (or FT_Face) and the gfxFontStyle are
-        // not necessarily enough to provide a key that will describe a unique
-        // font.  cairoFont contains information from renderPattern, which is a
-        // fully resolved pattern from FcFontRenderPrepare.
-        // FcFontRenderPrepare takes the requested pattern and the face
-        // pattern as input and can modify elements of the resulting pattern
-        // that affect rendering but are not included in the gfxFontStyle.
-        cairo_scaled_font_t *cairoFont = CreateScaledFont(renderPattern, face);
-        font = new gfxFcFont(cairoFont, renderPattern, fe, &style);
-        gfxFontCache::GetCache()->AddNew(font);
-        cairo_scaled_font_destroy(cairoFont);
-    }
-
-    cairo_font_face_destroy(face);
-
-    RefPtr<gfxFcFont> retval(static_cast<gfxFcFont*>(font.get()));
-    return retval.forget();
-}
-
-gfxFcFontSet *
-gfxPangoFontGroup::GetBaseFontSet()
-{
-    if (mFontSets.Length() > 0)
-        return mFontSets[0].mFontSet;
-
-    mSizeAdjustFactor = 1.0; // will be adjusted below if necessary
-    nsAutoRef<FcPattern> pattern;
-    RefPtr<gfxFcFontSet> fontSet =
-        MakeFontSet(mPangoLanguage, mSizeAdjustFactor, &pattern);
-
-    double size = GetPixelSize(pattern);
-    if (size != 0.0 && mStyle.sizeAdjust > 0.0) {
-        gfxFcFont *font = fontSet->GetFontAt(0, GetStyle());
-        if (font) {
-            const gfxFont::Metrics& metrics =
-                font->GetMetrics(gfxFont::eHorizontal); // XXX vertical?
-
-            // The factor of 0.1 ensures that xHeight is sane so fonts don't
-            // become huge.  Strictly ">" ensures that xHeight and emHeight are
-            // not both zero.
-            if (metrics.xHeight > 0.1 * metrics.emHeight) {
-                mSizeAdjustFactor =
-                    mStyle.sizeAdjust * metrics.emHeight / metrics.xHeight;
-
-                size *= mSizeAdjustFactor;
-                FcPatternDel(pattern, FC_PIXEL_SIZE);
-                FcPatternAddDouble(pattern, FC_PIXEL_SIZE, size);
-
-