Merge mozilla-inbound to mozilla-central r=merge a=merge
authorCosmin Sabou <csabou@mozilla.com>
Thu, 23 Nov 2017 11:42:46 +0200
changeset 445072 b6bed1b710c3e22cab49f22f1b5f44d80286bcb9
parent 445004 4f8b98354732bf1a166305ee30cd8a9bf143e5de (current diff)
parent 445071 fedc2d408840d81fdb3550c83121b400a2e63a0b (diff)
child 445073 6bc53832c0046e4d09fdc33cdb7427e9ee925605
child 445090 668dadde22cbb67a2de2920b7609b642d1be7ea2
child 445158 2219f1fc39029c651659aa996d22d5816ade2d37
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, merge
milestone59.0a1
first release with
nightly linux32
b6bed1b710c3 / 59.0a1 / 20171123100420 / files
nightly linux64
b6bed1b710c3 / 59.0a1 / 20171123100420 / files
nightly mac
b6bed1b710c3 / 59.0a1 / 20171123100420 / files
nightly win32
b6bed1b710c3 / 59.0a1 / 20171123100420 / files
nightly win64
b6bed1b710c3 / 59.0a1 / 20171123100420 / 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 mozilla-inbound to mozilla-central r=merge a=merge
accessible/base/nsAccessibilityService.cpp
dom/base/Element.cpp
dom/html/test/forms/test_input_autocomplete.html
dom/ipc/TabChild.cpp
toolkit/components/extensions/test/xpcshell/test_ext_contentscript_triggeringPrincipal.js
toolkit/library/gtest/rust/Cargo.lock
toolkit/library/rust/Cargo.lock
toolkit/mozapps/extensions/internal/XPIProvider.jsm
widget/cocoa/nsChildView.mm
--- a/browser/base/content/test/tabs/browser_opened_file_tab_navigated_to_web.js
+++ b/browser/base/content/test/tabs/browser_opened_file_tab_navigated_to_web.js
@@ -2,16 +2,21 @@
 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
 
 const TEST_FILE = "dummy_page.html";
 
 // Test for bug 1321020.
 add_task(async function() {
   let dir = getChromeDir(getResolvedURI(gTestPath));
   dir.append(TEST_FILE);
+
+  // The file can be a symbolic link on local build.  Normalize it to make sure
+  // the path matches to the actual URI opened in the new tab.
+  dir.normalize();
+
   const uriString = Services.io.newFileURI(dir).spec;
   const openedUriString = uriString + "?opened";
 
   // Open first file:// page.
   let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, uriString);
   registerCleanupFunction(async function() {
     await BrowserTestUtils.removeTab(tab);
   });
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1738,17 +1738,17 @@ BrowserGlue.prototype = {
         return;
       this._openPreferences("sync", { origin: "doorhanger" });
     };
     this.AlertsService.showAlertNotification(null, title, body, true, null, clickCallback);
   },
 
   // eslint-disable-next-line complexity
   _migrateUI: function BG__migrateUI() {
-    const UI_VERSION = 58;
+    const UI_VERSION = 59;
     const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
 
     let currentUIVersion;
     if (Services.prefs.prefHasUserValue("browser.migration.version")) {
       currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
     } else {
       // This is a new profile, nothing to migrate.
       Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
@@ -2170,16 +2170,50 @@ BrowserGlue.prototype = {
 
     if (currentUIVersion < 58) {
       // With Firefox 57, we are doing a one time reset of the geo prefs due to bug 1413652
       Services.prefs.clearUserPref("browser.search.countryCode");
       Services.prefs.clearUserPref("browser.search.region");
       Services.prefs.clearUserPref("browser.search.isUS");
     }
 
+    if (currentUIVersion < 59) {
+      let searchInitializedPromise = new Promise(resolve => {
+        if (Services.search.isInitialized) {
+          resolve();
+        }
+        const SEARCH_SERVICE_TOPIC = "browser-search-service";
+        Services.obs.addObserver(function observer(subject, topic, data) {
+          if (data != "init-complete") {
+            return;
+          }
+          Services.obs.removeObserver(observer, SEARCH_SERVICE_TOPIC);
+          resolve();
+        }, SEARCH_SERVICE_TOPIC);
+      });
+      searchInitializedPromise.then(() => {
+        let currentEngine = Services.search.currentEngine.wrappedJSObject;
+        // Only reset the current engine if it wasn't set by a WebExtension
+        // and it is not one of the default engines.
+        if (currentEngine._extensionID || currentEngine._isDefault)
+          return;
+
+        if (currentEngine._loadPath.startsWith("[https]")) {
+          Services.prefs.setCharPref("browser.search.reset.status", "pending");
+        } else {
+          // Can't call resetToOriginalDefaultEngine because it doesn't
+          // unhide the engine.
+          let defaultEngine = Services.search.originalDefaultEngine;
+          defaultEngine.hidden = false;
+          Services.search.currentEngine = defaultEngine;
+          Services.prefs.setIntPref("browser.search.reset.status", "silent");
+        }
+      });
+    }
+
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
   _checkForDefaultBrowser() {
     // Perform default browser checking.
     if (!ShellService) {
       return;
--- a/browser/components/preferences/in-content/containers.js
+++ b/browser/components/preferences/in-content/containers.js
@@ -12,18 +12,20 @@ const containersBundle = Services.string
 const defaultContainerIcon = "fingerprint";
 const defaultContainerColor = "blue";
 
 let gContainersPane = {
 
   init() {
     this._list = document.getElementById("containersView");
 
-    document.getElementById("backContainersLink").addEventListener("click", function() {
-      gotoPref("general");
+    document.getElementById("backContainersLink").addEventListener("click", function(event) {
+      if (event.button == 0) {
+        gotoPref("general");
+      }
     });
 
     this._rebuildView();
   },
 
   _rebuildView() {
     const containers = ContextualIdentityService.getPublicIdentities();
     while (this._list.firstChild) {
--- a/browser/components/preferences/in-content/privacy.js
+++ b/browser/components/preferences/in-content/privacy.js
@@ -109,26 +109,38 @@ var gPrivacyPane = {
     setEventListener("browser.privatebrowsing.autostart", "change",
       gPrivacyPane.updatePrivacyMicroControls);
     setEventListener("historyMode", "command", function() {
       gPrivacyPane.updateHistoryModePane();
       gPrivacyPane.updateHistoryModePrefs();
       gPrivacyPane.updatePrivacyMicroControls();
       gPrivacyPane.updateAutostart();
     });
-    setEventListener("historyRememberClear", "click", function() {
-      gPrivacyPane.clearPrivateDataNow(false);
+    setEventListener("historyRememberClear", "click", function(event) {
+      if (event.button == 0) {
+        gPrivacyPane.clearPrivateDataNow(false);
+      }
       return false;
     });
-    setEventListener("historyRememberCookies", "click", function() {
-      gPrivacyPane.showCookies();
+    setEventListener("historyRememberCookies", "click", function(event) {
+      if (event.button == 0) {
+        gPrivacyPane.showCookies();
+      }
       return false;
     });
-    setEventListener("historyDontRememberClear", "click", function() {
-      gPrivacyPane.clearPrivateDataNow(true);
+    setEventListener("historyDontRememberClear", "click", function(event) {
+      if (event.button == 0) {
+        gPrivacyPane.clearPrivateDataNow(true);
+      }
+      return false;
+    });
+    setEventListener("openSearchEnginePreferences", "click", function(event) {
+      if (event.button == 0) {
+        gotoPref("search");
+      }
       return false;
     });
     setEventListener("privateBrowsingAutoStart", "command",
       gPrivacyPane.updateAutostart);
     setEventListener("cookieExceptions", "command",
       gPrivacyPane.showCookieExceptions);
     setEventListener("showCookiesButton", "command",
       gPrivacyPane.showCookies);
--- a/browser/components/preferences/in-content/privacy.xul
+++ b/browser/components/preferences/in-content/privacy.xul
@@ -410,17 +410,17 @@
             accesskey="&locbar.history2.accesskey;"
             preference="browser.urlbar.suggest.history"/>
   <checkbox id="bookmarkSuggestion" label="&locbar.bookmarks.label;"
             accesskey="&locbar.bookmarks.accesskey;"
             preference="browser.urlbar.suggest.bookmark"/>
   <checkbox id="openpageSuggestion" label="&locbar.openpage.label;"
             accesskey="&locbar.openpage.accesskey;"
             preference="browser.urlbar.suggest.openpage"/>
-  <label class="text-link" onclick="gotoPref('search')">
+  <label class="text-link" id="openSearchEnginePreferences">
     &suggestionSettings2.label;
   </label>
 </groupbox>
 
 <!-- Cache -->
 <groupbox id="cacheGroup" data-category="panePrivacy" hidden="true">
   <caption><label>&httpCache.label;</label></caption>
 
--- a/browser/components/search/content/searchReset.js
+++ b/browser/components/search/content/searchReset.js
@@ -54,37 +54,46 @@ function doSearch() {
                   .rootTreeItem
                   .QueryInterface(Ci.nsIInterfaceRequestor)
                   .getInterface(Ci.nsIDOMWindow);
   win.openUILinkIn(submission.uri.spec, "current", false, submission.postData);
 }
 
 function openingSettings() {
   record(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
+  savePref("customized");
   window.removeEventListener("unload", recordPageClosed);
 }
 
+function savePref(value) {
+  const statusPref = "browser.search.reset.status";
+  if (Services.prefs.getCharPref(statusPref, "") == "pending")
+    Services.prefs.setCharPref(statusPref, value);
+}
+
 function record(result) {
   Services.telemetry.getHistogramById("SEARCH_RESET_RESULT").add(result);
 }
 
 function keepCurrentEngine() {
   // Calling the currentEngine setter will force a correct loadPathHash to be
   // written for this engine, so that we don't prompt the user again.
   Services.search.currentEngine = Services.search.currentEngine;
   record(TELEMETRY_RESULT_ENUM.KEPT_CURRENT);
+  savePref("declined");
   doSearch();
 }
 
 function changeSearchEngine() {
   let engine = Services.search.originalDefaultEngine;
   if (engine.hidden)
     engine.hidden = false;
   Services.search.currentEngine = engine;
 
   record(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
+  savePref("accepted");
 
   doSearch();
 }
 
 function recordPageClosed() {
   record(TELEMETRY_RESULT_ENUM.CLOSED_PAGE);
 }
--- a/browser/components/search/test/browser_aboutSearchReset.js
+++ b/browser/components/search/test/browser_aboutSearchReset.js
@@ -10,16 +10,18 @@ const TELEMETRY_RESULT_ENUM = {
   OPENED_SETTINGS: 4
 };
 
 const kSearchStr = "a search";
 const kSearchPurpose = "searchbar";
 
 const kTestEngine = "testEngine.xml";
 
+const kStatusPref = "browser.search.reset.status";
+
 function checkTelemetryRecords(expectedValue) {
   let histogram = Services.telemetry.getHistogramById("SEARCH_RESET_RESULT");
   let snapshot = histogram.snapshot();
   // The probe is declared with 5 values, but we get 6 back from .counts
   let expectedCounts = [0, 0, 0, 0, 0, 0];
   if (expectedValue != null) {
     expectedCounts[expectedValue] = 1;
   }
@@ -54,28 +56,30 @@ var gTests = [
 
     let expectedURL = engine.
                       getSubmission(kSearchStr, null, kSearchPurpose).
                       uri.spec;
 
     let rawEngine = engine.wrappedJSObject;
     let initialHash = rawEngine.getAttr("loadPathHash");
     rawEngine.setAttr("loadPathHash", "broken");
+    Services.prefs.setCharPref(kStatusPref, "pending");
 
     let loadPromise = promiseStoppedLoad(expectedURL);
     // eslint-disable-next-line mozilla/no-cpows-in-tests
     gBrowser.contentDocument.getElementById("searchResetKeepCurrent").click();
     await loadPromise;
 
     is(engine, Services.search.currentEngine,
        "the custom engine is still default");
     is(rawEngine.getAttr("loadPathHash"), initialHash,
        "the loadPathHash has been fixed");
 
     checkTelemetryRecords(TELEMETRY_RESULT_ENUM.KEPT_CURRENT);
+    is(Services.prefs.getCharPref(kStatusPref), "declined");
   }
 },
 
 {
   desc: "Test the 'Restore Search Defaults' button.",
   async run() {
     let currentEngine = Services.search.currentEngine;
     let originalEngine = Services.search.originalDefaultEngine;
@@ -87,47 +91,53 @@ var gTests = [
 
     let expectedURL = originalEngine.
                       getSubmission(kSearchStr, null, kSearchPurpose).
                       uri.spec;
     let loadPromise = promiseStoppedLoad(expectedURL);
     let button = doc.getElementById("searchResetChangeEngine");
     is(doc.activeElement, button,
        "the 'Change Search Engine' button is focused");
+    Services.prefs.setCharPref(kStatusPref, "pending");
     button.click();
     await loadPromise;
 
     is(originalEngine, Services.search.currentEngine,
        "the default engine is back to the original one");
 
     checkTelemetryRecords(TELEMETRY_RESULT_ENUM.RESTORED_DEFAULT);
+    is(Services.prefs.getCharPref(kStatusPref), "accepted");
     Services.search.currentEngine = currentEngine;
   }
 },
 
 {
   desc: "Click the settings link.",
   async run() {
+    Services.prefs.setCharPref(kStatusPref, "pending");
     let loadPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser,
                                                      false,
                                                      "about:preferences");
     // eslint-disable-next-line mozilla/no-cpows-in-tests
     gBrowser.contentDocument.getElementById("linkSettingsPage").click();
     await loadPromise;
 
     checkTelemetryRecords(TELEMETRY_RESULT_ENUM.OPENED_SETTINGS);
+    is(Services.prefs.getCharPref(kStatusPref), "customized");
   }
 },
 
 {
   desc: "Load another page without clicking any of the buttons.",
   async run() {
+    Services.prefs.setCharPref(kStatusPref, "pending");
     await promiseTabLoadEvent(gBrowser.selectedTab, "about:mozilla");
 
     checkTelemetryRecords(TELEMETRY_RESULT_ENUM.CLOSED_PAGE);
+    is(Services.prefs.getCharPref(kStatusPref), "pending");
   }
 },
 
 ];
 
 function test() {
   waitForExplicitFinish();
   (async function() {
@@ -148,14 +158,15 @@ function test() {
 
       info("Running test");
       await testCase.run();
 
       info("Cleanup");
       gBrowser.removeCurrentTab();
     }
 
+    Services.prefs.clearUserPref(kStatusPref);
     Services.telemetry.canRecordExtended = oldCanRecord;
   })().then(finish, ex => {
     ok(false, "Unexpected Exception: " + ex);
     finish();
   });
 }
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -354,22 +354,20 @@ BasePrincipal::AddonHasPermission(const 
 {
   if (auto policy = AddonPolicy()) {
     return policy->HasPermission(aPerm);
   }
   return false;
 }
 
 nsIPrincipal*
-BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI,
-                                  bool aAllowIfInheritsPrincipal)
+BasePrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
 {
   if (Is<ExpandedPrincipal>()) {
-    return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI,
-                                                       aAllowIfInheritsPrincipal);
+    return As<ExpandedPrincipal>()->PrincipalToInherit(aRequestedURI);
   }
   return this;
 }
 
 already_AddRefed<BasePrincipal>
 BasePrincipal::CreateCodebasePrincipal(nsIURI* aURI,
                                        const OriginAttributes& aAttrs)
 {
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -126,30 +126,36 @@ public:
   inline bool FastSubsumesConsideringDomainIgnoringFPD(nsIPrincipal* aOther);
 
   // Returns the principal to inherit when a caller with this principal loads
   // the given URI.
   //
   // For most principal types, this returns the principal itself. For expanded
   // principals, it returns the first sub-principal which subsumes the given URI
   // (or, if no URI is given, the last whitelist principal).
-  //
-  // The aAllowIfInheritsPrincipal argument is passed through to CheckMayLoad()
-  // to determine which consistituent principals may load the requested URI.
-  nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr,
-                                   bool aAllowIfInheritsPrincipal = true);
+  nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
 
   /**
    * Returns true if this principal's CSP should override a document's CSP for
    * loads that it triggers. Currently true only for expanded principals which
-   * subsume the document principal.
+   * subsume the document principal, and add-on codebase principals regardless
+   * of whether they subsume the document principal.
    */
   bool OverridesCSP(nsIPrincipal* aDocumentPrincipal)
   {
-    return mKind == eExpandedPrincipal && FastSubsumes(aDocumentPrincipal);
+    // Expanded principals override CSP if and only if they subsume the document
+    // principal.
+    if (mKind == eExpandedPrincipal) {
+      return FastSubsumes(aDocumentPrincipal);
+    }
+    // Extension principals always override the CSP non-extension principals.
+    // This is primarily for the sake of their stylesheets, which are usually
+    // loaded from channels and cannot have expanded principals.
+    return (AddonPolicy() &&
+            !BasePrincipal::Cast(aDocumentPrincipal)->AddonPolicy());
   }
 
 protected:
   virtual ~BasePrincipal();
 
   // Note that this does not check OriginAttributes. Callers that depend on
   // those must call Subsumes instead.
   virtual bool SubsumesInternal(nsIPrincipal* aOther, DocumentDomainConsideration aConsider) = 0;
--- a/caps/ExpandedPrincipal.cpp
+++ b/caps/ExpandedPrincipal.cpp
@@ -176,23 +176,27 @@ ExpandedPrincipal::AddonHasPermission(co
     if (BasePrincipal::Cast(mPrincipals[i])->AddonHasPermission(aPerm)) {
       return true;
     }
   }
   return false;
 }
 
 nsIPrincipal*
-ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI,
-                                      bool aAllowIfInheritsPrincipal)
+ExpandedPrincipal::PrincipalToInherit(nsIURI* aRequestedURI)
 {
   if (aRequestedURI) {
+    // If a given sub-principal subsumes the given URI, use that principal for
+    // inheritance. In general, this only happens with certain CORS modes, loads
+    // with forced principal inheritance, and creation of XML documents from
+    // XMLHttpRequests or fetch requests. For URIs that normally inherit a
+    // principal (such as data: URIs), we fall back to the last principal in the
+    // whitelist.
     for (const auto& principal : mPrincipals) {
-      if (NS_SUCCEEDED(principal->CheckMayLoad(aRequestedURI, false,
-                                               aAllowIfInheritsPrincipal))) {
+      if (Cast(principal)->MayLoadInternal(aRequestedURI)) {
         return principal;
       }
     }
   }
   return mPrincipals.LastElement();
 }
 
 nsresult
--- a/caps/ExpandedPrincipal.h
+++ b/caps/ExpandedPrincipal.h
@@ -34,18 +34,17 @@ public:
   NS_IMETHOD SetDomain(nsIURI* aDomain) override;
   NS_IMETHOD GetBaseDomain(nsACString& aBaseDomain) override;
   NS_IMETHOD GetAddonId(nsAString& aAddonId) override;
   virtual bool AddonHasPermission(const nsAtom* aPerm) override;
   virtual nsresult GetScriptLocation(nsACString &aStr) override;
 
   // Returns the principal to inherit when this principal requests the given
   // URL. See BasePrincipal::PrincipalToInherit.
-  nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr,
-                                   bool aAllowIfInheritsPrincipal = true);
+  nsIPrincipal* PrincipalToInherit(nsIURI* aRequestedURI = nullptr);
 
 protected:
   explicit ExpandedPrincipal(nsTArray<nsCOMPtr<nsIPrincipal>> &aWhiteList);
 
   virtual ~ExpandedPrincipal();
 
   bool SubsumesInternal(nsIPrincipal* aOther,
                         DocumentDomainConsideration aConsideration) override;
--- a/devtools/server/actors/highlighters/shapes.js
+++ b/devtools/server/actors/highlighters/shapes.js
@@ -1447,18 +1447,18 @@ class ShapesHighlighter extends AutoRefr
       coordParser: this.ellipsePoints.bind(this)
     }, {
       name: "inset",
       prefix: "inset(",
       coordParser: this.insetPoints.bind(this)
     }];
     const geometryTypes = ["margin", "border", "padding", "content"];
 
-    // default to border
-    let referenceBox = "border";
+    // default to border for clip-path, and margin for shape-outside
+    let referenceBox = this.property === "clip-path" ? "border" : "margin";
     for (let geometry of geometryTypes) {
       if (definition.includes(geometry)) {
         referenceBox = geometry;
       }
     }
     this.referenceBox = referenceBox;
 
     this.useStrokeBox = definition.includes("stroke-box");
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -277,16 +277,17 @@ void
 Attr::GetTextContentInternal(nsAString& aTextContent,
                              OOMReporter& aError)
 {
   GetValue(aTextContent);
 }
 
 void
 Attr::SetTextContentInternal(const nsAString& aTextContent,
+                             nsIPrincipal* aSubjectPrincipal,
                              ErrorResult& aError)
 {
   SetNodeValueInternal(aTextContent, aError);
 }
 
 NS_IMETHODIMP
 Attr::GetIsId(bool* aReturn)
 {
--- a/dom/base/Attr.h
+++ b/dom/base/Attr.h
@@ -41,16 +41,17 @@ public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
 
   // nsIDOMNode interface
   NS_FORWARD_NSIDOMNODE_TO_NSINODE
   virtual void GetTextContentInternal(nsAString& aTextContent,
                                       OOMReporter& aError) override;
   virtual void SetTextContentInternal(const nsAString& aTextContent,
+                                      nsIPrincipal* aSubjectPrincipal,
                                       ErrorResult& aError) override;
   virtual void GetNodeValueInternal(nsAString& aNodeValue) override;
   virtual void SetNodeValueInternal(const nsAString& aNodeValue,
                                     ErrorResult& aError) override;
 
   // nsIDOMAttr interface
   NS_DECL_NSIDOMATTR
 
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -2678,17 +2678,18 @@ Element::SetAttr(int32_t aNamespaceID, n
   // out to id-observers
   nsIDocument* document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
 
   nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!preparsedAttrValue &&
-      !ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
+      !ParseAttribute(aNamespaceID, aName, aValue, aSubjectPrincipal,
+                      attrValue)) {
     attrValue.SetTo(aValue);
   }
 
   PreIdMaybeChange(aNamespaceID, aName, &value);
 
   return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
                           oldValueSet ? &oldValue : nullptr,
                           attrValue, aSubjectPrincipal, modType,
@@ -2898,16 +2899,17 @@ Element::SetAttrAndNotify(int32_t aNames
 
   return NS_OK;
 }
 
 bool
 Element::ParseAttribute(int32_t aNamespaceID,
                         nsAtom* aAttribute,
                         const nsAString& aValue,
+                        nsIPrincipal* aMaybeScriptedPrincipal,
                         nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::lang) {
     aResult.ParseAtom(aValue);
     return true;
   }
 
   if (aNamespaceID == kNameSpaceID_None) {
@@ -3994,17 +3996,17 @@ Element::GetAnimationsUnsorted(Element* 
 NS_IMETHODIMP
 Element::GetInnerHTML(nsAString& aInnerHTML)
 {
   GetMarkup(false, aInnerHTML);
   return NS_OK;
 }
 
 void
-Element::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError)
+Element::SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
 {
   SetInnerHTMLInternal(aInnerHTML, aError);
 }
 
 void
 Element::GetOuterHTML(nsAString& aOuterHTML)
 {
   GetMarkup(true, aOuterHTML);
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -1214,17 +1214,21 @@ public:
   // this element.
   void GetAnimations(const AnimationFilter& filter,
                      nsTArray<RefPtr<Animation>>& aAnimations);
   static void GetAnimationsUnsorted(Element* aElement,
                                     CSSPseudoElementType aPseudoType,
                                     nsTArray<RefPtr<Animation>>& aAnimations);
 
   NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
-  virtual void SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError);
+  void GetInnerHTML(nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal)
+  {
+    GetInnerHTML(aInnerHTML);
+  }
+  virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
   void GetOuterHTML(nsAString& aOuterHTML);
   void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
   void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
                           ErrorResult& aError);
 
   //----------------------------------------
 
   /**
@@ -1560,22 +1564,28 @@ protected:
   /**
    * Convert an attribute string value to attribute type based on the type of
    * attribute.  Called by SetAttr().  Note that at the moment we only do this
    * for attributes in the null namespace (kNameSpaceID_None).
    *
    * @param aNamespaceID the namespace of the attribute to convert
    * @param aAttribute the attribute to convert
    * @param aValue the string value to convert
+   * @param aMaybeScriptedPrincipal the principal of the script setting the
+   *        attribute, if one can be determined, or null otherwise. As in
+   *        AfterSetAttr, a null value does not guarantee that the attribute was
+   *        not set by a scripted caller, but a non-null value guarantees that
+   *        the attribute was set by a scripted caller with the given principal.
    * @param aResult the nsAttrValue [OUT]
    * @return true if the parsing was successful, false otherwise
    */
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult);
 
   /**
    * Try to set the attribute as a mapped attribute, if applicable.  This will
    * only be called for attributes that are in the null namespace and only on
    * attributes that returned true when passed to IsAttributeMapped.  The
    * caller will not try to set the attr in any other way if this method
    * returns true (the value of aRetval does not matter for that purpose).
--- a/dom/base/FragmentOrElement.cpp
+++ b/dom/base/FragmentOrElement.cpp
@@ -499,30 +499,36 @@ nsIContent::GetBaseURIForStyleAttr() con
       return data->BaseURI();
     }
   }
   // This also ignores the case that SVG inside XBL binding.
   // But it is probably fine.
   return OwnerDoc()->GetDocBaseURI();
 }
 
-URLExtraData*
-nsIContent::GetURLDataForStyleAttr() const
+already_AddRefed<URLExtraData>
+nsIContent::GetURLDataForStyleAttr(nsIPrincipal* aSubjectPrincipal) const
 {
   if (IsInAnonymousSubtree() && IsAnonymousContentInSVGUseSubtree()) {
     nsIContent* bindingParent = GetBindingParent();
     MOZ_ASSERT(bindingParent);
     SVGUseElement* useElement = static_cast<SVGUseElement*>(bindingParent);
     if (URLExtraData* data = useElement->GetContentURLData()) {
-      return data;
+      return do_AddRef(data);
     }
   }
+  if (aSubjectPrincipal && aSubjectPrincipal != NodePrincipal()) {
+    // TODO: Cache this?
+    return MakeAndAddRef<URLExtraData>(OwnerDoc()->GetDocBaseURI(),
+                                       OwnerDoc()->GetDocumentURI(),
+                                       aSubjectPrincipal);
+  }
   // This also ignores the case that SVG inside XBL binding.
   // But it is probably fine.
-  return OwnerDoc()->DefaultStyleAttrURLData();
+  return do_AddRef(OwnerDoc()->DefaultStyleAttrURLData());
 }
 
 //----------------------------------------------------------------------
 
 static inline JSObject*
 GetJSObjectChild(nsWrapperCache* aCache)
 {
   return aCache->PreservingWrapper() ? aCache->GetWrapperPreserveColor() : nullptr;
@@ -1383,16 +1389,17 @@ FragmentOrElement::GetTextContentInterna
 {
   if (!nsContentUtils::GetNodeTextContent(this, true, aTextContent, fallible)) {
     aError.ReportOOM();
   }
 }
 
 void
 FragmentOrElement::SetTextContentInternal(const nsAString& aTextContent,
+                                          nsIPrincipal* aSubjectPrincipal,
                                           ErrorResult& aError)
 {
   aError = nsContentUtils::SetNodeTextContent(this, aTextContent, false);
 }
 
 void
 FragmentOrElement::DestroyContent()
 {
--- a/dom/base/FragmentOrElement.h
+++ b/dom/base/FragmentOrElement.h
@@ -121,16 +121,17 @@ public:
   virtual nsIContent *GetChildAt(uint32_t aIndex) const override;
   virtual int32_t IndexOf(const nsINode* aPossibleChild) const override;
   virtual nsresult InsertChildAt(nsIContent* aKid, uint32_t aIndex,
                                  bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
   virtual void GetTextContentInternal(nsAString& aTextContent,
                                       mozilla::OOMReporter& aError) override;
   virtual void SetTextContentInternal(const nsAString& aTextContent,
+                                      nsIPrincipal* aSubjectPrincipal,
                                       mozilla::ErrorResult& aError) override;
 
   // nsIContent interface methods
   virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) override;
   virtual const nsTextFragment *GetText() override;
   virtual uint32_t TextLength() const override;
   virtual nsresult SetText(const char16_t* aBuffer, uint32_t aLength,
                            bool aNotify) override;
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -1720,53 +1720,62 @@ nsAttrValue::LoadImage(nsIDocument* aDoc
   NS_ADDREF(image);
   cont->mValue.mImage = image;
   NS_RELEASE(url);
   cont->mType = eImage;
 }
 
 bool
 nsAttrValue::ParseStyleAttribute(const nsAString& aString,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsStyledElement* aElement)
 {
   nsIDocument* ownerDoc = aElement->OwnerDoc();
   nsHTMLCSSStyleSheet* sheet = ownerDoc->GetInlineStyleSheet();
   nsCOMPtr<nsIURI> baseURI = aElement->GetBaseURIForStyleAttr();
   nsIURI* docURI = ownerDoc->GetDocumentURI();
 
   NS_ASSERTION(aElement->NodePrincipal() == ownerDoc->NodePrincipal(),
                "This is unexpected");
 
+  nsCOMPtr<nsIPrincipal> principal = (
+      aMaybeScriptedPrincipal ? aMaybeScriptedPrincipal
+                              : aElement->NodePrincipal());
+
   // If the (immutable) document URI does not match the element's base URI
   // (the common case is that they do match) do not cache the rule.  This is
   // because the results of the CSS parser are dependent on these URIs, and we
   // do not want to have to account for the URIs in the hash lookup.
-  bool cachingAllowed = sheet && baseURI == docURI;
+  // Similarly, if the triggering principal does not match the node principal,
+  // do not cache the rule, since the principal will be encoded in any parsed
+  // URLs in the rule.
+  bool cachingAllowed = (sheet && baseURI == docURI &&
+                         principal == aElement->NodePrincipal());
   if (cachingAllowed) {
     MiscContainer* cont = sheet->LookupStyleAttr(aString);
     if (cont) {
       // Set our MiscContainer to the cached one.
       NS_ADDREF(cont);
       SetPtrValueAndType(cont, eOtherBase);
       return true;
     }
   }
 
   RefPtr<DeclarationBlock> decl;
   if (ownerDoc->GetStyleBackendType() == StyleBackendType::Servo) {
     RefPtr<URLExtraData> data = new URLExtraData(baseURI, docURI,
-                                                 aElement->NodePrincipal());
+                                                 principal);
     decl = ServoDeclarationBlock::FromCssText(aString, data,
                                               ownerDoc->GetCompatibilityMode(),
                                               ownerDoc->CSSLoader());
   } else {
     css::Loader* cssLoader = ownerDoc->CSSLoader();
     nsCSSParser cssParser(cssLoader);
     decl = cssParser.ParseStyleAttribute(aString, docURI, baseURI,
-                                         aElement->NodePrincipal());
+                                         principal);
   }
   if (!decl) {
     return false;
   }
   decl->SetHTMLCSSStyleSheet(sheet);
   SetTo(decl.forget(), &aString);
 
   if (cachingAllowed) {
--- a/dom/base/nsAttrValue.h
+++ b/dom/base/nsAttrValue.h
@@ -428,18 +428,22 @@ public:
    */
   void LoadImage(nsIDocument* aDocument);
 
   /**
    * Parse a string into a CSS style rule.
    *
    * @param aString the style attribute value to be parsed.
    * @param aElement the element the attribute is set on.
+   * @param aMaybeScriptedPrincipal if available, the scripted principal
+   *        responsible for this attribute value, as passed to
+   *        Element::ParseAttribute.
    */
   bool ParseStyleAttribute(const nsAString& aString,
+                           nsIPrincipal* aMaybeScriptedPrincipal,
                            nsStyledElement* aElement);
 
   size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
 
 private:
   // These have to be the same as in ValueType
   enum ValueBaseType {
     eStringBase =    eString,    // 00
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -1132,17 +1132,17 @@ nsContentUtils::SerializeAutocompleteAtt
  *
  * @return {AutocompleteAttrState} The state of the attribute (invalid/valid).
  */
 nsContentUtils::AutocompleteAttrState
 nsContentUtils::InternalSerializeAutocompleteAttribute(const nsAttrValue* aAttrVal,
                                                        mozilla::dom::AutocompleteInfo& aInfo,
                                                        bool aGrantAllValidValue)
 {
-  // No sandbox attribute so we are done
+  // No autocomplete attribute so we are done
   if (!aAttrVal) {
     return eAutocompleteAttrState_Invalid;
   }
 
   uint32_t numTokens = aAttrVal->GetAtomCount();
   if (!numTokens) {
     return eAutocompleteAttrState_Invalid;
   }
--- a/dom/base/nsGenericDOMDataNode.h
+++ b/dom/base/nsGenericDOMDataNode.h
@@ -111,16 +111,17 @@ public:
                                  bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
   virtual void GetTextContentInternal(nsAString& aTextContent,
                                       mozilla::OOMReporter& aError) override
   {
     GetNodeValue(aTextContent);
   }
   virtual void SetTextContentInternal(const nsAString& aTextContent,
+                                      nsIPrincipal* aSubjectPrincipal,
                                       mozilla::ErrorResult& aError) override
   {
     // Batch possible DOMSubtreeModified events.
     mozAutoSubtreeModified subtree(OwnerDoc(), nullptr);
     return SetNodeValue(aTextContent, aError);
   }
 
   // Implementation for nsIContent
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -1019,17 +1019,20 @@ public:
 
   // Overloaded from nsINode
   virtual already_AddRefed<nsIURI> GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override;
 
   // Returns base URI for style attribute.
   nsIURI* GetBaseURIForStyleAttr() const;
 
   // Returns the URL data for style attribute.
-  mozilla::URLExtraData* GetURLDataForStyleAttr() const;
+  // If aSubjectPrincipal is passed, it should be the scripted principal
+  // responsible for generating the URL data.
+  already_AddRefed<mozilla::URLExtraData>
+  GetURLDataForStyleAttr(nsIPrincipal* aSubjectPrincipal = nullptr) const;
 
   virtual nsresult GetEventTargetParent(
                      mozilla::EventChainPreVisitor& aVisitor) override;
 
   virtual bool IsPurple() = 0;
   virtual void RemovePurple() = 0;
 
   virtual bool OwnedOnlyByTheDOMTree() { return false; }
--- a/dom/base/nsINode.h
+++ b/dom/base/nsINode.h
@@ -1330,24 +1330,36 @@ public:
   // a way to ask an element whether it's an HTMLShadowElement.
   virtual bool IsHTMLShadowElement() const { return false; }
 
   // Elements named <content> may or may not be HTMLContentElement.  This is a
   // way to ask an element whether it's an HTMLContentElement.
   virtual bool IsHTMLContentElement() const { return false; }
 
   void GetTextContent(nsAString& aTextContent,
+                      nsIPrincipal& aSubjectPrincipal,
+                      mozilla::OOMReporter& aError)
+  {
+    GetTextContentInternal(aTextContent, aError);
+  }
+  void GetTextContent(nsAString& aTextContent,
                       mozilla::OOMReporter& aError)
   {
     GetTextContentInternal(aTextContent, aError);
   }
   void SetTextContent(const nsAString& aTextContent,
+                      nsIPrincipal& aSubjectPrincipal,
                       mozilla::ErrorResult& aError)
   {
-    SetTextContentInternal(aTextContent, aError);
+    SetTextContentInternal(aTextContent, &aSubjectPrincipal, aError);
+  }
+  void SetTextContent(const nsAString& aTextContent,
+                      mozilla::ErrorResult& aError)
+  {
+    SetTextContentInternal(aTextContent, nullptr, aError);
   }
 
   mozilla::dom::Element* QuerySelector(const nsAString& aSelector,
                                        mozilla::ErrorResult& aResult);
   already_AddRefed<nsINodeList> QuerySelectorAll(const nsAString& aSelector,
                                                  mozilla::ErrorResult& aResult);
 
 protected:
@@ -1988,16 +2000,17 @@ protected:
   virtual bool IsEditableExternal() const
   {
     return IsEditableInternal();
   }
 
   virtual void GetTextContentInternal(nsAString& aTextContent,
                                       mozilla::OOMReporter& aError);
   virtual void SetTextContentInternal(const nsAString& aTextContent,
+                                      nsIPrincipal* aSubjectPrincipal,
                                       mozilla::ErrorResult& aError)
   {
   }
 
 #ifdef DEBUG
   // Note: virtual so that IsInNativeAnonymousSubtree can be called accross
   // module boundaries.
   virtual void CheckNotNativeAnonymous() const;
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -535,25 +535,26 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
     if (!nsContentUtils::GetNodeTextContent(thisContent, false, text, fallible)) {
       return NS_ERROR_OUT_OF_MEMORY;
     }
 
     MOZ_ASSERT(thisContent->NodeInfo()->NameAtom() != nsGkAtoms::link,
                "<link> is not 'inline', and needs different CSP checks");
     if (!nsStyleUtil::CSPAllowsInlineStyle(thisContent,
                                            thisContent->NodePrincipal(),
+                                           triggeringPrincipal,
                                            doc->GetDocumentURI(),
                                            mLineNumber, text, &rv))
       return rv;
 
     // Parse the style sheet.
     rv = doc->CSSLoader()->
-      LoadInlineStyle(thisContent, text, mLineNumber, title, media,
-                      referrerPolicy, scopeElement, aObserver, &doneLoading,
-                      &isAlternate);
+      LoadInlineStyle(thisContent, text, triggeringPrincipal, mLineNumber,
+                      title, media, referrerPolicy, scopeElement,
+                      aObserver, &doneLoading, &isAlternate);
   }
   else {
     nsAutoString integrity;
     thisContent->GetAttr(kNameSpaceID_None, nsGkAtoms::integrity, integrity);
     if (!integrity.IsEmpty()) {
       MOZ_LOG(SRILogHelper::GetSriLog(), mozilla::LogLevel::Debug,
               ("nsStyleLinkElement::DoUpdateStyleSheet, integrity=%s",
                NS_ConvertUTF16toUTF8(integrity).get()));
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -34,25 +34,26 @@ NS_IMPL_QUERY_INTERFACE_CYCLE_COLLECTION
 
 //----------------------------------------------------------------------
 // nsIContent methods
 
 bool
 nsStyledElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::style && aNamespaceID == kNameSpaceID_None) {
-    ParseStyleAttribute(aValue, aResult, false);
+    ParseStyleAttribute(aValue, aMaybeScriptedPrincipal, aResult, false);
     return true;
   }
 
   return nsStyledElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                             aResult);
+                                             aMaybeScriptedPrincipal, aResult);
 }
 
 nsresult
 nsStyledElement::BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                const nsAttrValueOrString* aValue, bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::style) {
@@ -140,17 +141,17 @@ nsStyledElement::ReparseStyleAttribute(b
   if (!MayHaveStyle()) {
     return NS_OK;
   }
   const nsAttrValue* oldVal = mAttrsAndChildren.GetAttr(nsGkAtoms::style);
   if (oldVal && (aForceIfAlreadyParsed || oldVal->Type() != nsAttrValue::eCSSDeclaration)) {
     nsAttrValue attrValue;
     nsAutoString stringValue;
     oldVal->ToString(stringValue);
-    ParseStyleAttribute(stringValue, attrValue, aForceInDataDoc);
+    ParseStyleAttribute(stringValue, nullptr, attrValue, aForceInDataDoc);
     // Don't bother going through SetInlineStyleDeclaration; we don't
     // want to fire off mutation events or document notifications anyway
     bool oldValueSet;
     nsresult rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
                                                    &oldValueSet);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -174,24 +175,26 @@ nsStyledElement::GetExistingStyle()
     return nullptr;
   }
 
   return slots->mStyle;
 }
 
 void
 nsStyledElement::ParseStyleAttribute(const nsAString& aValue,
+                                     nsIPrincipal* aMaybeScriptedPrincipal,
                                      nsAttrValue& aResult,
                                      bool aForceInDataDoc)
 {
   nsIDocument* doc = OwnerDoc();
   bool isNativeAnon = IsInNativeAnonymousSubtree();
 
   if (!isNativeAnon &&
       !nsStyleUtil::CSPAllowsInlineStyle(nullptr, NodePrincipal(),
+                                         aMaybeScriptedPrincipal,
                                          doc->GetDocumentURI(), 0, aValue,
                                          nullptr))
     return;
 
   if (aForceInDataDoc ||
       !doc->IsLoadedAsData() ||
       GetExistingStyle() ||
       doc->IsStaticDocument()) {
@@ -201,15 +204,16 @@ nsStyledElement::ParseStyleAttribute(con
       nsAutoString styleType;
       doc->GetHeaderData(nsGkAtoms::headerContentStyleType, styleType);
       if (!styleType.IsEmpty()) {
         static const char textCssStr[] = "text/css";
         isCSS = (styleType.EqualsIgnoreCase(textCssStr, sizeof(textCssStr) - 1));
       }
     }
 
-    if (isCSS && aResult.ParseStyleAttribute(aValue, this)) {
+    if (isCSS && aResult.ParseStyleAttribute(aValue, aMaybeScriptedPrincipal,
+                                             this)) {
       return;
     }
   }
 
   aResult.SetTo(aValue);
 }
--- a/dom/base/nsStyledElement.h
+++ b/dom/base/nsStyledElement.h
@@ -56,24 +56,30 @@ protected:
 
   nsICSSDeclaration* GetExistingStyle();
 
   /**
    * Parse a style attr value into a CSS rulestruct (or, if there is no
    * document, leave it as a string) and return as nsAttrValue.
    *
    * @param aValue the value to parse
+   * @param aMaybeScriptedPrincipal if available, the scripted principal
+   *        responsible for this attribute value, as passed to
+   *        Element::ParseAttribute.
    * @param aResult the resulting HTMLValue [OUT]
    */
   void ParseStyleAttribute(const nsAString& aValue,
+                           nsIPrincipal* aMaybeScriptedPrincipal,
                            nsAttrValue& aResult,
                            bool aForceInDataDoc);
 
   virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                                const nsAString& aValue, nsAttrValue& aResult) override;
+                                const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                nsAttrValue& aResult) override;
 
   friend class mozilla::dom::Element;
 
   /**
    * Create the style struct from the style attr.  Used when an element is
    * first put into a document.  Only has an effect if the old value is a
    * string.  If aForceInDataDoc is true, will reparse even if we're in a data
    * document. If aForceIfAlreadyParsed is set, this will always reparse even
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1180,19 +1180,20 @@ nsTreeSanitizer::SanitizeAttributes(mozi
 
     if (kNameSpaceID_None == attrNs) {
       if (aAllowStyle && nsGkAtoms::style == attrLocal) {
         RefPtr<DeclarationBlock> decl;
         nsAutoString value;
         aElement->GetAttr(attrNs, attrLocal, value);
         nsIDocument* document = aElement->OwnerDoc();
         if (document->IsStyledByServo()) {
+          RefPtr<URLExtraData> urlExtra(aElement->GetURLDataForStyleAttr());
           decl = ServoDeclarationBlock::FromCssText(
               value,
-              aElement->GetURLDataForStyleAttr(),
+              urlExtra,
               document->GetCompatibilityMode(),
               document->CSSLoader());
         } else {
           // Pass the CSS Loader object to the parser, to allow parser error
           // reports to include the outer window ID.
           nsCSSParser parser(document->CSSLoader());
           decl = parser.ParseStyleAttribute(value, document->GetDocumentURI(),
                                             aElement->GetBaseURIForStyleAttr(),
--- a/dom/bindings/GenerateCSS2PropertiesWebIDL.py
+++ b/dom/bindings/GenerateCSS2PropertiesWebIDL.py
@@ -23,17 +23,18 @@ def generate(output, idlFilename, prepro
 
     propList = eval(preprocessed)
     props = ""
     for [name, prop, id, flags, pref, proptype] in propList:
         if "CSS_PROPERTY_INTERNAL" in flags:
             continue
         # Unfortunately, even some of the getters here are fallible
         # (e.g. on nsComputedDOMStyle).
-        extendedAttrs = ["Throws", "TreatNullAs=EmptyString"]
+        extendedAttrs = ["Throws", "TreatNullAs=EmptyString",
+                         "NeedsSubjectPrincipal"]
         if pref is not "":
             extendedAttrs.append('Pref="%s"' % pref)
 
         # webkit properties get a capitalized "WebkitFoo" accessor (added here)
         # as well as a camelcase "webkitFoo" accessor (added next).
         if (prop.startswith("Webkit")):
             props += generateLine(prop, extendedAttrs)
 
--- a/dom/html/HTMLBRElement.cpp
+++ b/dom/html/HTMLBRElement.cpp
@@ -35,24 +35,25 @@ static const nsAttrValue::EnumTable kCle
   { "both", StyleClear::Both },
   { nullptr, 0 }
 };
 
 bool
 HTMLBRElement::ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::clear && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kClearTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLBRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                      GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Display))) {
     if (!aData->PropertyIsSet(eCSSProperty_clear)) {
--- a/dom/html/HTMLBRElement.h
+++ b/dom/html/HTMLBRElement.h
@@ -17,16 +17,17 @@ namespace dom {
 class HTMLBRElement final : public nsGenericHTMLElement
 {
 public:
   explicit HTMLBRElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   bool Clear()
   {
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -41,16 +41,17 @@ HTMLBodyElement::WrapNode(JSContext *aCx
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLBodyElement, nsGenericHTMLElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLBodyElement)
 
 bool
 HTMLBodyElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::bgcolor ||
         aAttribute == nsGkAtoms::text ||
         aAttribute == nsGkAtoms::link ||
         aAttribute == nsGkAtoms::alink ||
         aAttribute == nsGkAtoms::vlink) {
@@ -65,17 +66,17 @@ HTMLBodyElement::ParseAttribute(int32_t 
       return aResult.ParseIntWithBounds(aValue, 0);
     }
   }
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLBodyElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                        GenericSpecifiedValues* aData)
 {
   if (aData->mSIDs & NS_STYLE_INHERIT_BIT(Margin)) {
 
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -121,16 +121,17 @@ public:
   void SetBackground(const nsAString& aBackground, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::background, aBackground, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual already_AddRefed<TextEditor> GetAssociatedEditor() override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual bool IsEventAttributeNameInternal(nsAtom* aName) override;
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -150,16 +150,17 @@ HTMLButtonElement::IsHTMLFocusable(bool 
 
   return false;
 }
 
 bool
 HTMLButtonElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::type) {
       return aResult.ParseEnumValue(aValue, kButtonTypeTable, false,
                                     kButtonDefaultType);
     }
 
@@ -167,17 +168,17 @@ HTMLButtonElement::ParseAttribute(int32_
       return aResult.ParseEnumValue(aValue, kFormMethodTable, false);
     }
     if (aAttribute == nsGkAtoms::formenctype) {
       return aResult.ParseEnumValue(aValue, kFormEnctypeTable, false);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 bool
 HTMLButtonElement::IsDisabledForEvents(EventMessage aMessage)
 {
   nsIFormControlFrame* formControlFrame = GetFormControlFrame(false);
   nsIFrame* formFrame = do_QueryFrame(formControlFrame);
   return IsElementDisabledForEvents(aMessage, formFrame);
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -84,16 +84,17 @@ public:
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   // nsGenericHTMLElement
   virtual bool IsHTMLFocusable(bool aWithMouse,
                                bool* aIsFocusable,
                                int32_t* aTabIndex) override;
 
   // WebIDL
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -637,25 +637,26 @@ HTMLCanvasElement::GetAttributeChangeHin
   }
   return retval;
 }
 
 bool
 HTMLCanvasElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None &&
       (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height)) {
     return aResult.ParseNonNegativeIntValue(aValue);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 
 
 void
 HTMLCanvasElement::ToDataURL(JSContext* aCx, const nsAString& aType,
                              JS::Handle<JS::Value> aParams,
                              nsAString& aDataURL,
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -285,16 +285,17 @@ public:
    * FrameCaptureListeners having requested frame capture.
    */
   void SetFrameCapture(already_AddRefed<gfx::SourceSurface> aSurface,
                        const TimeStamp& aTime);
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute, int32_t aModType) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
   nsresult CopyInnerTo(mozilla::dom::Element* aDest,
                        bool aPreallocateChildren);
 
--- a/dom/html/HTMLDivElement.cpp
+++ b/dom/html/HTMLDivElement.cpp
@@ -26,16 +26,17 @@ HTMLDivElement::WrapNode(JSContext *aCx,
 {
   return dom::HTMLDivElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
 bool
 HTMLDivElement::ParseAttribute(int32_t aNamespaceID,
                                nsAtom* aAttribute,
                                const nsAString& aValue,
+                               nsIPrincipal* aMaybeScriptedPrincipal,
                                nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (mNodeInfo->Equals(nsGkAtoms::marquee)) {
       if ((aAttribute == nsGkAtoms::width) ||
           (aAttribute == nsGkAtoms::height)) {
         return aResult.ParseSpecialIntValue(aValue);
       }
@@ -50,17 +51,17 @@ HTMLDivElement::ParseAttribute(int32_t a
 
     if (mNodeInfo->Equals(nsGkAtoms::div) &&
         aAttribute == nsGkAtoms::align) {
       return ParseDivAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLDivElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                       GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
--- a/dom/html/HTMLDivElement.h
+++ b/dom/html/HTMLDivElement.h
@@ -27,16 +27,17 @@ public:
   void SetAlign(const nsAString& aAlign, mozilla::ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLDivElement();
--- a/dom/html/HTMLEmbedElement.cpp
+++ b/dom/html/HTMLEmbedElement.cpp
@@ -216,29 +216,30 @@ HTMLEmbedElement::TabIndexDefault()
 {
   return -1;
 }
 
 bool
 HTMLEmbedElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom *aAttribute,
                                  const nsAString &aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue &aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 static void
 MapAttributesIntoRuleBase(const nsMappedAttributes *aAttributes,
                           GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageMarginAttributeInto(aAttributes, aData);
--- a/dom/html/HTMLEmbedElement.h
+++ b/dom/html/HTMLEmbedElement.h
@@ -43,16 +43,17 @@ public:
                               bool aNullParent = true) override;
 
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
   virtual IMEState GetDesiredIMEState() override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom *aAttribute,
                               const nsAString &aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue &aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom *aAttribute) const override;
   virtual EventStates IntrinsicState() const override;
   virtual void DestroyContent() override;
 
   // nsObjectLoadingContent
   virtual uint32_t GetCapabilities() const override;
--- a/dom/html/HTMLFontElement.cpp
+++ b/dom/html/HTMLFontElement.cpp
@@ -28,16 +28,17 @@ HTMLFontElement::WrapNode(JSContext *aCx
 }
 
 NS_IMPL_ELEMENT_CLONE(HTMLFontElement)
 
 bool
 HTMLFontElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::size) {
       int32_t size = nsContentUtils::ParseLegacyFontSize(aValue);
       if (size) {
         aResult.SetTo(size, &aValue);
         return true;
@@ -45,17 +46,17 @@ HTMLFontElement::ParseAttribute(int32_t 
       return false;
     }
     if (aAttribute == nsGkAtoms::color) {
       return aResult.ParseColor(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLFontElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                        GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Font))) {
     // face: string list
--- a/dom/html/HTMLFontElement.h
+++ b/dom/html/HTMLFontElement.h
@@ -43,16 +43,17 @@ public:
   void SetSize(const nsAString& aSize, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::size, aSize, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
 protected:
   virtual ~HTMLFontElement();
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -274,32 +274,33 @@ HTMLFormElement::CheckValidity(bool* ret
   *retVal = CheckValidity();
   return NS_OK;
 }
 
 bool
 HTMLFormElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::method) {
       return aResult.ParseEnumValue(aValue, kFormMethodTable, false);
     }
     if (aAttribute == nsGkAtoms::enctype) {
       return aResult.ParseEnumValue(aValue, kFormEnctypeTable, false);
     }
     if (aAttribute == nsGkAtoms::autocomplete) {
       return aResult.ParseEnumValue(aValue, kFormAutocompleteTable, false);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 nsresult
 HTMLFormElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                             nsIContent* aBindingParent,
                             bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -89,16 +89,17 @@ public:
 
   // EventTarget
   virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult WillHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
   virtual nsresult PostHandleEvent(
                      EventChainPostVisitor& aVisitor) override;
 
--- a/dom/html/HTMLFrameElement.cpp
+++ b/dom/html/HTMLFrameElement.cpp
@@ -28,16 +28,17 @@ HTMLFrameElement::~HTMLFrameElement()
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLFrameElement, nsGenericHTMLFrameElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLFrameElement)
 
 bool
 HTMLFrameElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::bordercolor) {
       return aResult.ParseColor(aValue);
     }
     if (aAttribute == nsGkAtoms::frameborder) {
       return ParseFrameborderValue(aValue, aResult);
@@ -49,17 +50,17 @@ HTMLFrameElement::ParseAttribute(int32_t
       return aResult.ParseSpecialIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::scrolling) {
       return ParseScrollingValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                   aValue, aResult);
+                                                   aValue, aMaybeScriptedPrincipal, aResult);
 }
 
 JSObject*
 HTMLFrameElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLFrameElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
--- a/dom/html/HTMLFrameElement.h
+++ b/dom/html/HTMLFrameElement.h
@@ -26,16 +26,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLFrameElement, frame)
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // WebIDL API
   void GetFrameBorder(DOMString& aFrameBorder) const
   {
     GetHTMLAttr(nsGkAtoms::frameborder, aFrameBorder);
--- a/dom/html/HTMLFrameSetElement.cpp
+++ b/dom/html/HTMLFrameSetElement.cpp
@@ -132,32 +132,33 @@ HTMLFrameSetElement::GetColSpec(int32_t 
   return NS_OK;
 }
 
 
 bool
 HTMLFrameSetElement::ParseAttribute(int32_t aNamespaceID,
                                     nsAtom* aAttribute,
                                     const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::bordercolor) {
       return aResult.ParseColor(aValue);
     }
     if (aAttribute == nsGkAtoms::frameborder) {
       return nsGenericHTMLElement::ParseFrameborderValue(aValue, aResult);
     }
     if (aAttribute == nsGkAtoms::border) {
       return aResult.ParseIntWithBounds(aValue, 0, 100);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 nsChangeHint
 HTMLFrameSetElement::GetAttributeChangeHint(const nsAtom* aAttribute,
                                             int32_t aModType) const
 {
   nsChangeHint retval =
     nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLFrameSetElement.h
+++ b/dom/html/HTMLFrameSetElement.h
@@ -111,16 +111,17 @@ public:
              implementation.  DO NOT DELETE IT.
     */
   nsresult GetColSpec(int32_t *aNumValues, const nsFramesetSpec** aSpecs);
 
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
 protected:
--- a/dom/html/HTMLHRElement.cpp
+++ b/dom/html/HTMLHRElement.cpp
@@ -25,16 +25,17 @@ NS_IMPL_ISUPPORTS_INHERITED0(HTMLHREleme
 
 NS_IMPL_ELEMENT_CLONE(HTMLHRElement)
 
 
 bool
 HTMLHRElement::ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult)
 {
   static const nsAttrValue::EnumTable kAlignTable[] = {
     { "left", NS_STYLE_TEXT_ALIGN_LEFT },
     { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
     { "center", NS_STYLE_TEXT_ALIGN_CENTER },
     { nullptr, 0 }
   };
@@ -50,17 +51,17 @@ HTMLHRElement::ParseAttribute(int32_t aN
       return aResult.ParseEnumValue(aValue, kAlignTable, false);
     }
     if (aAttribute == nsGkAtoms::color) {
       return aResult.ParseColor(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLHRElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                      GenericSpecifiedValues* aData)
 {
   bool noshade = false;
 
--- a/dom/html/HTMLHRElement.h
+++ b/dom/html/HTMLHRElement.h
@@ -22,16 +22,17 @@ public:
   explicit HTMLHRElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // WebIDL API
   void GetAlign(nsAString& aValue) const
--- a/dom/html/HTMLHeadingElement.cpp
+++ b/dom/html/HTMLHeadingElement.cpp
@@ -29,24 +29,25 @@ HTMLHeadingElement::WrapNode(JSContext *
 {
   return HTMLHeadingElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
 bool
 HTMLHeadingElement::ParseAttribute(int32_t aNamespaceID,
                                    nsAtom* aAttribute,
                                    const nsAString& aValue,
+                                   nsIPrincipal* aMaybeScriptedPrincipal,
                                    nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return ParseDivAlignValue(aValue, aResult);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLHeadingElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                           GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
--- a/dom/html/HTMLHeadingElement.h
+++ b/dom/html/HTMLHeadingElement.h
@@ -19,16 +19,17 @@ public:
   explicit HTMLHeadingElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : nsGenericHTMLElement(aNodeInfo)
   {
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
--- a/dom/html/HTMLIFrameElement.cpp
+++ b/dom/html/HTMLIFrameElement.cpp
@@ -40,16 +40,17 @@ HTMLIFrameElement::~HTMLIFrameElement()
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLIFrameElement, nsGenericHTMLFrameElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLIFrameElement)
 
 bool
 HTMLIFrameElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::marginwidth) {
       return aResult.ParseSpecialIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::marginheight) {
       return aResult.ParseSpecialIntValue(aValue);
@@ -71,17 +72,19 @@ HTMLIFrameElement::ParseAttribute(int32_
     }
     if (aAttribute == nsGkAtoms::sandbox) {
       aResult.ParseAtomArray(aValue);
       return true;
     }
   }
 
   return nsGenericHTMLFrameElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                   aValue, aResult);
+                                                   aValue,
+                                                   aMaybeScriptedPrincipal,
+                                                   aResult);
 }
 
 void
 HTMLIFrameElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                          GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Border))) {
     // frameborder: 0 | 1 (| NO | YES in quirks mode)
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -30,16 +30,17 @@ public:
   {
     return true;
   }
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   uint32_t GetSandboxFlags();
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -220,33 +220,34 @@ HTMLImageElement::Y()
 {
   return GetXY().y;
 }
 
 bool
 HTMLImageElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
     if (aAttribute == nsGkAtoms::crossorigin) {
       ParseCORSValue(aValue, aResult);
       return true;
     }
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLImageElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                         GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapImageBorderAttributeInto(aAttributes, aData);
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -53,16 +53,17 @@ public:
 
   // override from nsImageLoadingContent
   CORSMode GetCORSMode() override;
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -5747,16 +5747,17 @@ HTMLInputElement::IsInputColorEnabled()
 
   return sInputColorEnabled;
 }
 
 bool
 HTMLInputElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   // We can't make these static_asserts because kInputDefaultType and
   // kInputTypeTable aren't constexpr.
   MOZ_ASSERT(kInputDefaultType->value == NS_FORM_INPUT_TEXT,
              "Someone forgot to update kInputDefaultType when adding a new "
              "input type.");
   MOZ_ASSERT(kInputTypeTable[ArrayLength(kInputTypeTable) - 1].tag == nullptr,
@@ -5819,17 +5820,17 @@ HTMLInputElement::ParseAttribute(int32_t
       // don't know if we're going to have a type="image" attribute yet,
       // (or could have it set dynamically in the future).  See bug
       // 214077.
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLInputElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                         GenericSpecifiedValues* aData)
 {
   const nsAttrValue* value = aAttributes->GetAttr(nsGkAtoms::type);
   if (value && value->Type() == nsAttrValue::eEnum &&
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -190,16 +190,17 @@ public:
   virtual void FieldSetDisabledChanged(bool aNotify) override;
 
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
--- a/dom/html/HTMLLIElement.cpp
+++ b/dom/html/HTMLLIElement.cpp
@@ -44,31 +44,32 @@ static const nsAttrValue::EnumTable kOrd
   { "1", NS_STYLE_LIST_STYLE_DECIMAL },
   { nullptr, 0 }
 };
 
 bool
 HTMLLIElement::ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::type) {
       return aResult.ParseEnumValue(aValue, kOrderedListItemTypeTable,
                                     true) ||
              aResult.ParseEnumValue(aValue, kUnorderedListItemTypeTable, false);
     }
     if (aAttribute == nsGkAtoms::value) {
       return aResult.ParseIntValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLLIElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                      GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(List))) {
     if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
--- a/dom/html/HTMLLIElement.h
+++ b/dom/html/HTMLLIElement.h
@@ -23,16 +23,17 @@ public:
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // WebIDL API
   void GetType(DOMString& aType)
--- a/dom/html/HTMLLegendElement.cpp
+++ b/dom/html/HTMLLegendElement.cpp
@@ -33,16 +33,17 @@ HTMLLegendElement::GetFieldSet() const
 
   return nullptr;
 }
 
 bool
 HTMLLegendElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   // this contains center, because IE4 does
   static const nsAttrValue::EnumTable kAlignTable[] = {
     { "left", NS_STYLE_TEXT_ALIGN_LEFT },
     { "right", NS_STYLE_TEXT_ALIGN_RIGHT },
     { "center", NS_STYLE_TEXT_ALIGN_CENTER },
     { "bottom", NS_STYLE_VERTICAL_ALIGN_BOTTOM },
@@ -50,17 +51,17 @@ HTMLLegendElement::ParseAttribute(int32_
     { nullptr, 0 }
   };
 
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kAlignTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 nsChangeHint
 HTMLLegendElement::GetAttributeChangeHint(const nsAtom* aAttribute,
                                           int32_t aModType) const
 {
   nsChangeHint retval =
       nsGenericHTMLElement::GetAttributeChangeHint(aAttribute, aModType);
--- a/dom/html/HTMLLegendElement.h
+++ b/dom/html/HTMLLegendElement.h
@@ -34,16 +34,17 @@ public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
 
   Element* GetFormElement() const
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -187,16 +187,17 @@ HTMLLinkElement::UnbindFromTree(bool aDe
 
   UpdateStyleSheetInternal(oldDoc, oldShadowRoot);
 }
 
 bool
 HTMLLinkElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::crossorigin) {
       ParseCORSValue(aValue, aResult);
       return true;
     }
 
@@ -212,17 +213,17 @@ HTMLLinkElement::ParseAttribute(int32_t 
 
     if (aAttribute == nsGkAtoms::integrity) {
       aResult.ParseStringOrAtom(aValue);
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLLinkElement::CreateAndDispatchEvent(nsIDocument* aDoc,
                                         const nsAString& aEventName)
 {
   if (!aDoc)
     return;
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -64,16 +64,17 @@ public:
                                 bool aNotify) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
 
   // Element
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual EventStates IntrinsicState() const override;
 
   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
 
   virtual void OnDNSPrefetchDeferred() override;
   virtual void OnDNSPrefetchRequested() override;
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -4454,16 +4454,17 @@ HTMLMediaElement::GetEventTargetParent(E
     default:
       return nsGenericHTMLElement::GetEventTargetParent(aVisitor);
   }
 }
 
 bool HTMLMediaElement::ParseAttribute(int32_t aNamespaceID,
                                       nsAtom* aAttribute,
                                       const nsAString& aValue,
+                                      nsIPrincipal* aMaybeScriptedPrincipal,
                                       nsAttrValue& aResult)
 {
   // Mappings from 'preload' attribute strings to an enumeration.
   static const nsAttrValue::EnumTable kPreloadTable[] = {
     { "",         HTMLMediaElement::PRELOAD_ATTR_EMPTY },
     { "none",     HTMLMediaElement::PRELOAD_ATTR_NONE },
     { "metadata", HTMLMediaElement::PRELOAD_ATTR_METADATA },
     { "auto",     HTMLMediaElement::PRELOAD_ATTR_AUTO },
@@ -4479,17 +4480,17 @@ bool HTMLMediaElement::ParseAttribute(in
       return true;
     }
     if (aAttribute == nsGkAtoms::preload) {
       return aResult.ParseEnumValue(aValue, kPreloadTable, false);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void HTMLMediaElement::DoneCreatingElement()
 {
    if (HasAttr(kNameSpaceID_None, nsGkAtoms::muted)) {
      mMuted |= MUTED_BY_CONTENT;
    }
 }
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -147,16 +147,17 @@ public:
 
   // nsIDOMEventTarget
   virtual nsresult
   GetEventTargetParent(EventChainPreVisitor& aVisitor) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual void DoneCreatingElement() override;
--- a/dom/html/HTMLMenuElement.cpp
+++ b/dom/html/HTMLMenuElement.cpp
@@ -123,25 +123,26 @@ HTMLMenuElement::AfterSetAttr(int32_t aN
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                             aOldValue, aSubjectPrincipal, aNotify);
 }
 
 bool
 HTMLMenuElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::type) {
     return aResult.ParseEnumValue(aValue, kMenuTypeTable, false,
                                   kMenuDefaultType);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLMenuElement::BuildSubmenu(const nsAString& aLabel,
                               nsIContent* aContent,
                               nsIMenuBuilder* aBuilder)
 {
   aBuilder->OpenContainer(aLabel);
--- a/dom/html/HTMLMenuElement.h
+++ b/dom/html/HTMLMenuElement.h
@@ -28,16 +28,17 @@ public:
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   uint8_t GetType() const { return mType; }
 
   // WebIDL
--- a/dom/html/HTMLMenuItemElement.cpp
+++ b/dom/html/HTMLMenuItemElement.cpp
@@ -315,32 +315,33 @@ HTMLMenuItemElement::BindToTree(nsIDocum
 
   return rv;
 }
 
 bool
 HTMLMenuItemElement::ParseAttribute(int32_t aNamespaceID,
                                     nsAtom* aAttribute,
                                     const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::type) {
       return aResult.ParseEnumValue(aValue, kMenuItemTypeTable, false,
                                     kMenuItemDefaultType);
     }
 
     if (aAttribute == nsGkAtoms::radiogroup) {
       aResult.ParseAtom(aValue);
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLMenuItemElement::DoneCreatingElement()
 {
   mParserCreating = false;
 
   if (mShouldInitChecked) {
--- a/dom/html/HTMLMenuItemElement.h
+++ b/dom/html/HTMLMenuItemElement.h
@@ -38,16 +38,17 @@ public:
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   virtual void DoneCreatingElement() override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   uint8_t GetType() const { return mType; }
--- a/dom/html/HTMLMeterElement.cpp
+++ b/dom/html/HTMLMeterElement.cpp
@@ -35,29 +35,34 @@ HTMLMeterElement::IntrinsicState() const
   EventStates state = nsGenericHTMLElement::IntrinsicState();
 
   state |= GetOptimumState();
 
   return state;
 }
 
 bool
-HTMLMeterElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                                 const nsAString& aValue, nsAttrValue& aResult)
+HTMLMeterElement::ParseAttribute(int32_t aNamespaceID,
+                                 nsAtom* aAttribute,
+                                 const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
+                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::value || aAttribute == nsGkAtoms::max ||
         aAttribute == nsGkAtoms::min   || aAttribute == nsGkAtoms::low ||
         aAttribute == nsGkAtoms::high  || aAttribute == nsGkAtoms::optimum) {
       return aResult.ParseDoubleValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                  aValue, aResult);
+                                              aValue,
+                                              aMaybeScriptedPrincipal,
+                                              aResult);
 }
 
 /*
  * Value getters :
  * const getters used by XPCOM methods and by IntrinsicState
  */
 
 double
--- a/dom/html/HTMLMeterElement.h
+++ b/dom/html/HTMLMeterElement.h
@@ -22,18 +22,20 @@ class HTMLMeterElement final : public ns
 public:
   explicit HTMLMeterElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual EventStates IntrinsicState() const override;
 
   nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                  bool aPreallocateChildren) const override;
 
-  bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                      const nsAString& aValue, nsAttrValue& aResult) override;
+  virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
+                              nsAttrValue& aResult) override;
 
   // WebIDL
 
   /* @return the value */
   double Value() const;
   void SetValue(double aValue, ErrorResult& aRv)
   {
     SetDoubleAttr(nsGkAtoms::value, aValue, aRv);
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -448,29 +448,30 @@ HTMLObjectElement::GetContentWindow(nsIP
 
   return nullptr;
 }
 
 bool
 HTMLObjectElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom *aAttribute,
                                   const nsAString &aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue &aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::align) {
       return ParseAlignValue(aValue, aResult);
     }
     if (ParseImageAttribute(aAttribute, aValue, aResult)) {
       return true;
     }
   }
 
   return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                  aValue, aResult);
+                                                  aValue, aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLObjectElement::MapAttributesIntoRule(const nsMappedAttributes *aAttributes,
                                          GenericSpecifiedValues *aData)
 {
   nsGenericHTMLFormElement::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElement::MapImageBorderAttributeInto(aAttributes, aData);
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -65,16 +65,17 @@ public:
   virtual bool IsDisabled() const override { return false; }
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
   virtual bool IsDoneAddingChildren() override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom *aAttribute,
                                 const nsAString &aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue &aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom *aAttribute) const override;
   virtual EventStates IntrinsicState() const override;
   virtual void DestroyContent() override;
 
   // nsObjectLoadingContent
   virtual uint32_t GetCapabilities() const override;
--- a/dom/html/HTMLOutputElement.cpp
+++ b/dom/html/HTMLOutputElement.cpp
@@ -65,28 +65,33 @@ HTMLOutputElement::Reset()
 NS_IMETHODIMP
 HTMLOutputElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission)
 {
   // The output element is not submittable.
   return NS_OK;
 }
 
 bool
-HTMLOutputElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                                  const nsAString& aValue, nsAttrValue& aResult)
+HTMLOutputElement::ParseAttribute(int32_t aNamespaceID,
+                                  nsAtom* aAttribute,
+                                  const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
+                                  nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::_for) {
       aResult.ParseAtomArray(aValue);
       return true;
     }
   }
 
   return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
-                                                  aValue, aResult);
+                                                  aValue,
+                                                  aMaybeScriptedPrincipal,
+                                                  aResult);
 }
 
 void
 HTMLOutputElement::DoneAddingChildren(bool aHaveNotified)
 {
   mIsDoneAddingChildren = true;
 }
 
--- a/dom/html/HTMLOutputElement.h
+++ b/dom/html/HTMLOutputElement.h
@@ -34,18 +34,20 @@ public:
   NS_IMETHOD Reset() override;
   NS_IMETHOD SubmitNamesValues(HTMLFormSubmission* aFormSubmission) override;
 
   virtual bool IsDisabled() const override { return false; }
 
   nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                  bool aPreallocateChildren) const override;
 
-  bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                        const nsAString& aValue, nsAttrValue& aResult) override;
+  virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
+                              nsAttrValue& aResult) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
 
   EventStates IntrinsicState() const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                nsIContent* aBindingParent,
                                bool aCompileEventHandlers) override;
--- a/dom/html/HTMLParagraphElement.cpp
+++ b/dom/html/HTMLParagraphElement.cpp
@@ -24,24 +24,25 @@ HTMLParagraphElement::~HTMLParagraphElem
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLParagraphElement, nsGenericHTMLElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLParagraphElement)
 
 bool
 HTMLParagraphElement::ParseAttribute(int32_t aNamespaceID,
                                      nsAtom* aAttribute,
                                      const nsAString& aValue,
+                                     nsIPrincipal* aMaybeScriptedPrincipal,
                                      nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return ParseDivAlignValue(aValue, aResult);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLParagraphElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                             GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
--- a/dom/html/HTMLParagraphElement.h
+++ b/dom/html/HTMLParagraphElement.h
@@ -23,16 +23,17 @@ public:
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // WebIDL API
--- a/dom/html/HTMLPreElement.cpp
+++ b/dom/html/HTMLPreElement.cpp
@@ -25,26 +25,27 @@ HTMLPreElement::~HTMLPreElement()
 NS_IMPL_ISUPPORTS_INHERITED0(HTMLPreElement, nsGenericHTMLElement)
 
 NS_IMPL_ELEMENT_CLONE(HTMLPreElement)
 
 bool
 HTMLPreElement::ParseAttribute(int32_t aNamespaceID,
                                nsAtom* aAttribute,
                                const nsAString& aValue,
+                               nsIPrincipal* aMaybeScriptedPrincipal,
                                nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::width) {
       return aResult.ParseIntValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLPreElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                       GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
     if (!aData->PropertyIsSet(eCSSProperty_white_space)) {
--- a/dom/html/HTMLPreElement.h
+++ b/dom/html/HTMLPreElement.h
@@ -23,16 +23,17 @@ public:
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // WebIDL API
--- a/dom/html/HTMLProgressElement.cpp
+++ b/dom/html/HTMLProgressElement.cpp
@@ -40,27 +40,32 @@ HTMLProgressElement::IntrinsicState() co
   if (IsIndeterminate()) {
     state |= NS_EVENT_STATE_INDETERMINATE;
   }
 
   return state;
 }
 
 bool
-HTMLProgressElement::ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                                    const nsAString& aValue, nsAttrValue& aResult)
+HTMLProgressElement::ParseAttribute(int32_t aNamespaceID,
+                                    nsAtom* aAttribute,
+                                    const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
+                                    nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::value || aAttribute == nsGkAtoms::max) {
       return aResult.ParseDoubleValue(aValue);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute,
-                                              aValue, aResult);
+                                              aValue,
+                                              aMaybeScriptedPrincipal,
+                                              aResult);
 }
 
 double
 HTMLProgressElement::Value() const
 {
   const nsAttrValue* attrValue = mAttrsAndChildren.GetAttr(nsGkAtoms::value);
   if (!attrValue || attrValue->Type() != nsAttrValue::eDoubleValue ||
       attrValue->GetDoubleValue() < 0.0) {
--- a/dom/html/HTMLProgressElement.h
+++ b/dom/html/HTMLProgressElement.h
@@ -21,18 +21,20 @@ class HTMLProgressElement final : public
 public:
   explicit HTMLProgressElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   EventStates IntrinsicState() const override;
 
   nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                  bool aPreallocateChildren) const override;
 
-  bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                        const nsAString& aValue, nsAttrValue& aResult) override;
+  virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
+                              nsAttrValue& aResult) override;
 
   // WebIDL
   double Value() const;
   void SetValue(double aValue, ErrorResult& aRv)
   {
     SetDoubleAttr(nsGkAtoms::value, aValue, aRv);
   }
   double Max() const;
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -68,32 +68,33 @@ HTMLScriptElement::BindToTree(nsIDocumen
 
   return NS_OK;
 }
 
 bool
 HTMLScriptElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::crossorigin) {
       ParseCORSValue(aValue, aResult);
       return true;
     }
 
     if (aAttribute == nsGkAtoms::integrity) {
       aResult.ParseStringOrAtom(aValue);
       return true;
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 nsresult
 HTMLScriptElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const
 {
   *aResult = nullptr;
 
@@ -141,16 +142,17 @@ HTMLScriptElement::GetInnerHTML(nsAStrin
   if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
 void
 HTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML,
+                                nsIPrincipal& aScriptedPrincipal,
                                 ErrorResult& aError)
 {
   aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
 }
 
 void
 HTMLScriptElement::GetText(nsAString& aValue, ErrorResult& aRv)
 {
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -24,32 +24,34 @@ public:
   HTMLScriptElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
                     FromParser aFromParser);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) override;
   virtual void SetInnerHTML(const nsAString& aInnerHTML,
+                            nsIPrincipal& aSubjectPrincipal,
                             mozilla::ErrorResult& aError) override;
 
   // nsIScriptElement
   virtual bool GetScriptType(nsAString& type) override;
   virtual void GetScriptText(nsAString& text) override;
   virtual void GetScriptCharset(nsAString& charset) override;
   virtual void FreezeUriAsyncDefer() override;
   virtual CORSMode GetCORSMode() const override;
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // Element
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -1252,28 +1252,29 @@ HTMLSelectElement::DoneAddingChildren(bo
 
   mDefaultSelectionSet = true;
 }
 
 bool
 HTMLSelectElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   if (kNameSpaceID_None == aNamespaceID) {
     if (aAttribute == nsGkAtoms::size) {
       return aResult.ParsePositiveIntValue(aValue);
     } else if (aAttribute == nsGkAtoms::autocomplete) {
       aResult.ParseAtomArray(aValue);
       return true;
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLSelectElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                          GenericSpecifiedValues* aData)
 {
   nsGenericHTMLFormElementWithState::MapImageAlignAttributeInto(aAttributes, aData);
   nsGenericHTMLFormElementWithState::MapCommonAttributesInto(aAttributes, aData);
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -379,16 +379,17 @@ public:
   virtual void DoneAddingChildren(bool aHaveNotified) override;
   virtual bool IsDoneAddingChildren() override {
     return mIsDoneAddingChildren;
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -55,30 +55,31 @@ HTMLSharedElement::GetHref(nsAString& aV
   uri->GetSpec(spec);
   CopyUTF8toUTF16(spec, aValue);
 }
 
 bool
 HTMLSharedElement::ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None &&
       mNodeInfo->Equals(nsGkAtoms::dir)) {
     if (aAttribute == nsGkAtoms::type) {
       return aResult.ParseEnumValue(aValue, mozilla::dom::kListTypeTable, false);
     }
     if (aAttribute == nsGkAtoms::start) {
       return aResult.ParseIntWithBounds(aValue, 1);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 static void
 DirectoryMapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(List))) {
     if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
--- a/dom/html/HTMLSharedElement.h
+++ b/dom/html/HTMLSharedElement.h
@@ -28,16 +28,17 @@ public:
       SetHasWeirdParserInsertionMode();
     }
   }
 
   // nsIContent
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
 
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
--- a/dom/html/HTMLSharedListElement.cpp
+++ b/dom/html/HTMLSharedListElement.cpp
@@ -54,33 +54,34 @@ static const nsAttrValue::EnumTable kOld
   { "i", NS_STYLE_LIST_STYLE_LOWER_ROMAN },
   { nullptr, 0 }
 };
 
 bool
 HTMLSharedListElement::ParseAttribute(int32_t aNamespaceID,
                                       nsAtom* aAttribute,
                                       const nsAString& aValue,
+                                      nsIPrincipal* aMaybeScriptedPrincipal,
                                       nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (mNodeInfo->Equals(nsGkAtoms::ol) ||
         mNodeInfo->Equals(nsGkAtoms::ul)) {
       if (aAttribute == nsGkAtoms::type) {
         return aResult.ParseEnumValue(aValue, kListTypeTable, false) ||
                aResult.ParseEnumValue(aValue, kOldListTypeTable, true);
       }
       if (aAttribute == nsGkAtoms::start) {
         return aResult.ParseIntValue(aValue);
       }
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLSharedListElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                              GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(List))) {
     if (!aData->PropertyIsSet(eCSSProperty_list_style_type)) {
--- a/dom/html/HTMLSharedListElement.h
+++ b/dom/html/HTMLSharedListElement.h
@@ -23,16 +23,17 @@ public:
   }
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   bool Reversed() const
   {
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -95,16 +95,17 @@ HTMLStyleElement::ContentRemoved(nsIDocu
                                  nsIContent* aPreviousSibling)
 {
   ContentChanged(aChild);
 }
 
 void
 HTMLStyleElement::ContentChanged(nsIContent* aContent)
 {
+  mTriggeringPrincipal = nullptr;
   if (nsContentUtils::IsInSameAnonymousTree(this, aContent)) {
     UpdateStyleSheetInternal(nullptr, nullptr);
   }
 }
 
 nsresult
 HTMLStyleElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                              nsIContent* aBindingParent,
@@ -169,32 +170,43 @@ HTMLStyleElement::GetInnerHTML(nsAString
   if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
   return NS_OK;
 }
 
 void
 HTMLStyleElement::SetInnerHTML(const nsAString& aInnerHTML,
+                               nsIPrincipal& aScriptedPrincipal,
                                ErrorResult& aError)
 {
+  SetTextContentInternal(aInnerHTML, &aScriptedPrincipal, aError);
+}
+
+void
+HTMLStyleElement::SetTextContentInternal(const nsAString& aTextContent,
+                                         nsIPrincipal* aScriptedPrincipal,
+                                         ErrorResult& aError)
+{
   SetEnableUpdates(false);
 
-  aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
+  aError = nsContentUtils::SetNodeTextContent(this, aTextContent, true);
 
   SetEnableUpdates(true);
 
+  mTriggeringPrincipal = aScriptedPrincipal;
+
   UpdateStyleSheetInternal(nullptr, nullptr);
 }
 
 already_AddRefed<nsIURI>
 HTMLStyleElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
 {
   *aIsInline = true;
-  *aTriggeringPrincipal = nullptr;
+  *aTriggeringPrincipal = do_AddRef(mTriggeringPrincipal).take();
   return nullptr;
 }
 
 void
 HTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
                                     nsAString& aType,
                                     nsAString& aMedia,
                                     bool* aIsScoped,
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -29,17 +29,21 @@ public:
 
   // CC
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLStyleElement,
                                            nsGenericHTMLElement)
 
   NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) override;
   using nsGenericHTMLElement::SetInnerHTML;
   virtual void SetInnerHTML(const nsAString& aInnerHTML,
+                            nsIPrincipal& aSubjectPrincipal,
                             mozilla::ErrorResult& aError) override;
+  virtual void SetTextContentInternal(const nsAString& aTextContent,
+                                      nsIPrincipal* aSubjectPrincipal,
+                                      mozilla::ErrorResult& aError) override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
--- a/dom/html/HTMLTableCaptionElement.cpp
+++ b/dom/html/HTMLTableCaptionElement.cpp
@@ -35,24 +35,25 @@ static const nsAttrValue::EnumTable kCap
   { "bottom", NS_STYLE_CAPTION_SIDE_BOTTOM },
   { nullptr,  0 }
 };
 
 bool
 HTMLTableCaptionElement::ParseAttribute(int32_t aNamespaceID,
                                         nsAtom* aAttribute,
                                         const nsAString& aValue,
+                                        nsIPrincipal* aMaybeScriptedPrincipal,
                                         nsAttrValue& aResult)
 {
   if (aAttribute == nsGkAtoms::align && aNamespaceID == kNameSpaceID_None) {
     return aResult.ParseEnumValue(aValue, kCaptionAlignTable, false);
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableCaptionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                                GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(TableBorder))) {
     if (!aData->PropertyIsSet(eCSSProperty_caption_side)) {
--- a/dom/html/HTMLTableCaptionElement.h
+++ b/dom/html/HTMLTableCaptionElement.h
@@ -28,16 +28,17 @@ public:
   void SetAlign(const nsAString& aAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::align, aAlign, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
 protected:
--- a/dom/html/HTMLTableCellElement.cpp
+++ b/dom/html/HTMLTableCellElement.cpp
@@ -142,16 +142,17 @@ HTMLTableCellElement::GetScope(DOMString
 {
   GetEnumAttr(nsGkAtoms::scope, nullptr, aScope);
 }
 
 bool
 HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID,
                                      nsAtom* aAttribute,
                                      const nsAString& aValue,
+                                     nsIPrincipal* aMaybeScriptedPrincipal,
                                      nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings
        abbr, axis, ch, headers
     */
     if (aAttribute == nsGkAtoms::charoff) {
       /* attributes that resolve to integers with a min of 0 */
@@ -188,17 +189,17 @@ HTMLTableCellElement::ParseAttribute(int
       return ParseTableVAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableCellElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                             GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
     // width: value
--- a/dom/html/HTMLTableCellElement.h
+++ b/dom/html/HTMLTableCellElement.h
@@ -134,16 +134,17 @@ public:
   void SetBgColor(const nsAString& aBgColor, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::bgcolor, aBgColor, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD WalkContentStyleRules(nsRuleWalker* aRuleWalker) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   // Get mapped attributes of ancestor table, if any
   nsMappedAttributes* GetMappedAttributesInheritedFromTable() const;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
--- a/dom/html/HTMLTableColElement.cpp
+++ b/dom/html/HTMLTableColElement.cpp
@@ -30,16 +30,17 @@ HTMLTableColElement::WrapNode(JSContext 
 }
 
 NS_IMPL_ELEMENT_CLONE(HTMLTableColElement)
 
 bool
 HTMLTableColElement::ParseAttribute(int32_t aNamespaceID,
                                     nsAtom* aAttribute,
                                     const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings ch */
     if (aAttribute == nsGkAtoms::charoff) {
       return aResult.ParseSpecialIntValue(aValue);
     }
     if (aAttribute == nsGkAtoms::span) {
@@ -54,17 +55,17 @@ HTMLTableColElement::ParseAttribute(int3
       return ParseTableCellHAlignValue(aValue, aResult);
     }
     if (aAttribute == nsGkAtoms::valign) {
       return ParseTableVAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableColElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                            GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Table))) {
     if (!aData->PropertyIsSet(eCSSProperty__x_span)) {
--- a/dom/html/HTMLTableColElement.h
+++ b/dom/html/HTMLTableColElement.h
@@ -69,16 +69,17 @@ public:
   void SetWidth(const nsAString& aWidth, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::width, aWidth, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
 protected:
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -886,16 +886,17 @@ HTMLTableElement::DeleteRow(int32_t aInd
 
   row->RemoveFromParent();
 }
 
 bool
 HTMLTableElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   /* ignore summary, just a string */
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::cellspacing ||
         aAttribute == nsGkAtoms::cellpadding ||
         aAttribute == nsGkAtoms::border) {
       return aResult.ParseNonNegativeIntValue(aValue);
@@ -927,17 +928,17 @@ HTMLTableElement::ParseAttribute(int32_t
       return aResult.ParseIntWithBounds(aValue, 0);
     }
   }
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 
 
 void
 HTMLTableElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                         GenericSpecifiedValues* aData)
 {
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -180,16 +180,17 @@ public:
   void SetCellSpacing(const nsAString& aCellSpacing, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::cellspacing, aCellSpacing, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
--- a/dom/html/HTMLTableRowElement.cpp
+++ b/dom/html/HTMLTableRowElement.cpp
@@ -216,16 +216,17 @@ HTMLTableRowElement::DeleteCell(int32_t 
 
   nsINode::RemoveChild(*cell, aError);
 }
 
 bool
 HTMLTableRowElement::ParseAttribute(int32_t aNamespaceID,
                                     nsAtom* aAttribute,
                                     const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
                                     nsAttrValue& aResult)
 {
   /*
    * ignore these attributes, stored simply as strings
    *
    * ch
    */
 
@@ -249,17 +250,17 @@ HTMLTableRowElement::ParseAttribute(int3
       return ParseTableVAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableRowElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                            GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapHeightAttributeInto(aAttributes, aData);
   nsGenericHTMLElement::MapDivAlignAttributeInto(aAttributes, aData);
--- a/dom/html/HTMLTableRowElement.h
+++ b/dom/html/HTMLTableRowElement.h
@@ -76,16 +76,17 @@ public:
   void SetBgColor(const nsAString& aBgColor, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::bgcolor, aBgColor, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableRowElement,
--- a/dom/html/HTMLTableSectionElement.cpp
+++ b/dom/html/HTMLTableSectionElement.cpp
@@ -125,16 +125,17 @@ HTMLTableSectionElement::DeleteRow(int32
 
   nsINode::RemoveChild(*row, aError);
 }
 
 bool
 HTMLTableSectionElement::ParseAttribute(int32_t aNamespaceID,
                                         nsAtom* aAttribute,
                                         const nsAString& aValue,
+                                        nsIPrincipal* aMaybeScriptedPrincipal,
                                         nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     /* ignore these attributes, stored simply as strings
        ch
     */
     if (aAttribute == nsGkAtoms::charoff) {
       return aResult.ParseIntWithBounds(aValue, 0);
@@ -152,17 +153,17 @@ HTMLTableSectionElement::ParseAttribute(
       return ParseTableVAlignValue(aValue, aResult);
     }
   }
 
   return nsGenericHTMLElement::ParseBackgroundAttribute(aNamespaceID,
                                                         aAttribute, aValue,
                                                         aResult) ||
          nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTableSectionElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                                GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Position))) {
     // height: value
--- a/dom/html/HTMLTableSectionElement.h
+++ b/dom/html/HTMLTableSectionElement.h
@@ -61,16 +61,17 @@ public:
   void SetVAlign(const nsAString& aVAlign, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::valign, aVAlign, aError);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED_NO_UNLINK(HTMLTableSectionElement,
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -58,16 +58,17 @@ HTMLTextAreaElement::HTMLTextAreaElement
     mLastValueChangeWasInteractive(false),
     mHandlingSelect(false),
     mDoneAddingChildren(!aFromParser),
     mInhibitStateRestoration(!!(aFromParser & FROM_PARSER_FRAGMENT)),
     mDisabledChanged(false),
     mCanShowInvalidUI(true),
     mCanShowValidUI(true),
     mIsPreviewEnabled(false),
+    mAutocompleteAttrState(nsContentUtils::eAutocompleteAttrState_Unknown),
     mState(this)
 {
   AddMutationObserver(this);
 
   // Set up our default state.  By default we're enabled (since we're
   // a control type that can be disabled but not actually disabled
   // right now), optional, and valid.  We are NOT readwrite by default
   // until someone calls UpdateEditableState on us, apparently!  Also
@@ -419,32 +420,36 @@ HTMLTextAreaElement::SetDefaultValue(con
     aError.Throw(rv);
   }
 }
 
 bool
 HTMLTextAreaElement::ParseAttribute(int32_t aNamespaceID,
                                     nsAtom* aAttribute,
                                     const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::maxlength ||
         aAttribute == nsGkAtoms::minlength) {
       return aResult.ParseNonNegativeIntValue(aValue);
     } else if (aAttribute == nsGkAtoms::cols) {
       aResult.ParseIntWithFallback(aValue, DEFAULT_COLS);
       return true;
     } else if (aAttribute == nsGkAtoms::rows) {
       aResult.ParseIntWithFallback(aValue, DEFAULT_ROWS_TEXTAREA);
       return true;
+    } else if (aAttribute == nsGkAtoms::autocomplete) {
+      aResult.ParseAtomArray(aValue);
+      return true;
     }
   }
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                              aResult);
+                                              aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLTextAreaElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                            GenericSpecifiedValues* aData)
 {
   if (aData->ShouldComputeStyleStruct(NS_STYLE_INHERIT_BIT(Text))) {
     // wrap=off
@@ -1055,16 +1060,19 @@ HTMLTextAreaElement::AfterSetAttr(int32_
       }
 
       UpdateValueMissingValidityState();
 
       // This *has* to be called *after* validity has changed.
       if (aName == nsGkAtoms::readonly || aName == nsGkAtoms::disabled) {
         UpdateBarredFromConstraintValidation();
       }
+    } else if (aName == nsGkAtoms::autocomplete) {
+      // Clear the cached @autocomplete attribute state.
+      mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
     } else if (aName == nsGkAtoms::maxlength) {
       UpdateTooLongValidityState();
     } else if (aName == nsGkAtoms::minlength) {
       UpdateTooShortValidityState();
     }
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
@@ -1364,10 +1372,20 @@ HTMLTextAreaElement::FieldSetDisabledCha
 }
 
 JSObject*
 HTMLTextAreaElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLTextAreaElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
+void
+HTMLTextAreaElement::GetAutocomplete(DOMString& aValue)
+{
+  const nsAttrValue* attributeVal = GetParsedAttr(nsGkAtoms::autocomplete);
+
+  mAutocompleteAttrState =
+    nsContentUtils::SerializeAutocompleteAttribute(attributeVal, aValue,
+                                                   mAutocompleteAttrState);
+}
+
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -120,16 +120,17 @@ public:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                                nsIContent* aBindingParent,
                                bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
   virtual nsChangeHint GetAttributeChangeHint(const nsAtom* aAttribute,
                                               int32_t aModType) const override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
@@ -176,16 +177,21 @@ public:
   void     UpdateTooLongValidityState();
   void     UpdateTooShortValidityState();
   void     UpdateValueMissingValidityState();
   void     UpdateBarredFromConstraintValidation();
   nsresult GetValidationMessage(nsAString& aValidationMessage,
                                 ValidityStateType aType) override;
 
   // Web IDL binding methods
+  void GetAutocomplete(DOMString& aValue);
+  void SetAutocomplete(const nsAString& aValue, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::autocomplete, aValue, aRv);
+  }
   bool Autofocus()
   {
     return GetBoolAttr(nsGkAtoms::autofocus);
   }
   void SetAutofocus(bool aAutoFocus, ErrorResult& aError)
   {
     SetHTMLBoolAttr(nsGkAtoms::autofocus, aAutoFocus, aError);
   }
@@ -342,16 +348,18 @@ protected:
   /** Whether our disabled state has changed from the default **/
   bool                     mDisabledChanged;
   /** Whether we should make :-moz-ui-invalid apply on the element. **/
   bool                     mCanShowInvalidUI;
   /** Whether we should make :-moz-ui-valid apply on the element. **/
   bool                     mCanShowValidUI;
   bool                     mIsPreviewEnabled;
 
+  nsContentUtils::AutocompleteAttrState mAutocompleteAttrState;
+
   void FireChangeEventIfNeeded();
 
   nsString mFocusedValue;
 
   /** The state of the text editor (selection controller and the editor) **/
   nsTextEditorState mState;
 
   NS_IMETHOD SelectAll(nsPresContext* aPresContext);
--- a/dom/html/HTMLTrackElement.cpp
+++ b/dom/html/HTMLTrackElement.cpp
@@ -213,28 +213,30 @@ HTMLTrackElement::CreateTextTrack()
     mMediaParent->AddTextTrack(mTrack);
   }
 }
 
 bool
 HTMLTrackElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::kind) {
     // Case-insensitive lookup, with the first element as the default.
     return aResult.ParseEnumValue(aValue, kKindTable, false,
                                   kKindTableInvalidValueDefault);
   }
 
   // Otherwise call the generic implementation.
   return nsGenericHTMLElement::ParseAttribute(aNamespaceID,
                                               aAttribute,
                                               aValue,
+                                              aMaybeScriptedPrincipal,
                                               aResult);
 }
 
 void
 HTMLTrackElement::SetSrc(const nsAString& aSrc, ErrorResult& aError)
 {
   SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
   uint16_t oldReadyState = ReadyState();
--- a/dom/html/HTMLTrackElement.h
+++ b/dom/html/HTMLTrackElement.h
@@ -92,16 +92,17 @@ public:
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
 
   // Override ParseAttribute() to convert kind strings to enum values.
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   // Override BindToTree() so that we can trigger a load when we become
   // the child of a media element.
   virtual nsresult BindToTree(nsIDocument* aDocument,
                               nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
--- a/dom/html/HTMLVideoElement.cpp
+++ b/dom/html/HTMLVideoElement.cpp
@@ -81,24 +81,25 @@ nsresult HTMLVideoElement::GetVideoSize(
   }
   return NS_OK;
 }
 
 bool
 HTMLVideoElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
    if (aAttribute == nsGkAtoms::width || aAttribute == nsGkAtoms::height) {
      return aResult.ParseSpecialIntValue(aValue);
    }
 
    return HTMLMediaElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                           aResult);
+                                           aMaybeScriptedPrincipal, aResult);
 }
 
 void
 HTMLVideoElement::MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                         GenericSpecifiedValues* aData)
 {
   nsGenericHTMLElement::MapImageSizeAttributesInto(aAttributes, aData);
   nsGenericHTMLElement::MapCommonAttributesInto(aAttributes, aData);
--- a/dom/html/HTMLVideoElement.h
+++ b/dom/html/HTMLVideoElement.h
@@ -33,16 +33,17 @@ public:
 
   NS_IMETHOD_(bool) IsVideo() override {
     return true;
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   static void Init();
 
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult Clone(NodeInfo *aNodeInfo, nsINode **aResult,
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -922,16 +922,17 @@ nsGenericHTMLElement::GetBaseTarget(nsAS
 }
 
 //----------------------------------------------------------------------
 
 bool
 nsGenericHTMLElement::ParseAttribute(int32_t aNamespaceID,
                                      nsAtom* aAttribute,
                                      const nsAString& aValue,
+                                     nsIPrincipal* aMaybeScriptedPrincipal,
                                      nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aAttribute == nsGkAtoms::dir) {
       return aResult.ParseEnumValue(aValue, kDirTable, false);
     }
 
     if (aAttribute == nsGkAtoms::tabindex) {
@@ -959,17 +960,18 @@ nsGenericHTMLElement::ParseAttribute(int
 
     if (aAttribute == nsGkAtoms::rel) {
       aResult.ParseAtomArray(aValue);
       return true;
     }
   }
 
   return nsGenericHTMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
-                                                  aValue, aResult);
+                                                  aValue, aMaybeScriptedPrincipal,
+                                                  aResult);
 }
 
 bool
 nsGenericHTMLElement::ParseBackgroundAttribute(int32_t aNamespaceID,
                                                nsAtom* aAttribute,
                                                const nsAString& aValue,
                                                nsAttrValue& aResult)
 {
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -339,16 +339,17 @@ public:
   void DoSetEditableFlag(bool aEditable, bool aNotify) {
     SetEditableFlag(aEditable);
     UpdateState(aNotify);
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   bool ParseBackgroundAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult);
 
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
--- a/dom/html/test/forms/mochitest.ini
+++ b/dom/html/test/forms/mochitest.ini
@@ -1,16 +1,17 @@
 [DEFAULT]
 support-files =
   save_restore_radio_groups.sjs
   test_input_number_data.js
   !/dom/html/test/reflect.js
   FAIL.html
   PASS.html
 
+[test_autocomplete.html]
 [test_bug1039548.html]
 [test_bug1283915.html]
 [test_bug1286509.html]
 skip-if = os == "android" # up/down arrow keys not supported on android
 [test_button_attributes_reflection.html]
 [test_input_radio_indeterminate.html]
 [test_input_radio_radiogroup.html]
 [test_input_radio_required.html]
@@ -20,17 +21,16 @@ skip-if = os == "android" # up/down arro
 [test_form_attribute-2.html]
 [test_form_attribute-3.html]
 [test_form_attribute-4.html]
 [test_form_attributes_reflection.html]
 [test_form_named_getter_dynamic.html]
 [test_formaction_attribute.html]
 [test_formnovalidate_attribute.html]
 [test_input_attributes_reflection.html]
-[test_input_autocomplete.html]
 [test_input_color_input_change_events.html]
 [test_input_color_picker_initial.html]
 [test_input_color_picker_popup.html]
 skip-if = android_version == '18' # Android, bug 1147974
 [test_input_color_picker_update.html]
 skip-if = android_version == '18' # Android, bug 1147974
 [test_input_date_bad_input.html]
 [test_input_date_key_events.html]
rename from dom/html/test/forms/test_input_autocomplete.html
rename to dom/html/test/forms/test_autocomplete.html
--- a/dom/html/test/forms/test_input_autocomplete.html
+++ b/dom/html/test/forms/test_autocomplete.html
@@ -1,15 +1,15 @@
 <!DOCTYPE html>
 <html>
 <!--
-Test @autocomplete on <input>
+Test @autocomplete on <input>/<select>/<textarea>
 -->
 <head>
-  <title>Test for &lt;input autocomplete='…'&gt;</title>
+  <title>Test for @autocomplete</title>
   <script src="/tests/SimpleTest/SimpleTest.js"></script>
   <link rel="stylesheet" href="/tests/SimpleTest/test.css"/>
 <script>
 "use strict";
 
 var values = [
   // @autocomplete content attribute, expected IDL attribute value
 
@@ -103,28 +103,33 @@ function start() {
       inputField.removeAttribute("type");
     else
       inputField.type = type;
     checkAutocompleteValues(inputField, type || "");
   }
 
   var selectField = document.getElementById("select-field");
   checkAutocompleteValues(selectField, "select");
+
+  var textarea = document.getElementById("textarea");
+  checkAutocompleteValues(textarea, "textarea");
+
   SimpleTest.finish();
 }
 
 SimpleTest.waitForExplicitFinish();
 SpecialPowers.pushPrefEnv({"set": [["dom.forms.autocomplete.formautofill", true]]}, start);
 </script>
 </head>
 
 <body>
 <p id="display"></p>
 <div id="content" style="display: none">
   <form>
     <input id="input-field" />
     <select id="select-field" />
+    <textarea id="textarea"></textarea>
   </form>
 </div>
 <pre id="test">
 </pre>
 </body>
 </html>
--- a/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl
+++ b/dom/interfaces/css/nsIDOMCSSStyleDeclaration.idl
@@ -8,27 +8,37 @@
 /**
  * The nsIDOMCSSStyleDeclaration interface is a datatype for a CSS
  * style declaration in the Document Object Model.
  *
  * For more information on this interface please see
  * http://www.w3.org/TR/DOM-Level-2-Style
  */
 
+interface nsIPrincipal;
+
 [uuid(a6cf90be-15b3-11d2-932e-00805f8add32)]
 interface nsIDOMCSSStyleDeclaration : nsISupports
 {
-           attribute DOMString        cssText;
-                                        // raises(DOMException) on setting
+  // We declare these in C++, so that we can declare default argument values,
+  // since those are unsupported by XPIDL and this is not a scriptable
+  // interface.
+  %{C++
+  NS_IMETHOD GetCssText(nsAString& aCssText) = 0;
+  NS_IMETHOD SetCssText(const nsAString& aCssText,
+                        nsIPrincipal* aSubjectPrincipal = nullptr) = 0;
+
+  NS_IMETHOD SetProperty(const nsAString& aPropertyName,
+                         const nsAString& aValue,
+                         const nsAString& aPriority,
+                         nsIPrincipal* aSubjectPrincipal = nullptr) = 0;
+  %}
 
   DOMString          getPropertyValue(in DOMString propertyName);
   nsIDOMCSSValue     getPropertyCSSValue(in DOMString propertyName);
   DOMString          removeProperty(in DOMString propertyName)
                                         raises(DOMException);
   DOMString          getPropertyPriority(in DOMString propertyName);
-  void               setProperty(in DOMString propertyName, 
-                                 in DOMString value, 
-                                 [optional] in DOMString priority)
-                                        raises(DOMException);
+
   readonly attribute unsigned long    length;
   DOMString          item(in unsigned long index);
   readonly attribute nsIDOMCSSRule    parentRule;
 };
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -140,16 +140,17 @@ nsMathMLElement::UnbindFromTree(bool aDe
 
   nsMathMLElementBase::UnbindFromTree(aDeep, aNullParent);
 }
 
 bool
 nsMathMLElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   MOZ_ASSERT(IsMathMLElement());
 
   if (aNamespaceID == kNameSpaceID_None) {
     if (mNodeInfo->Equals(nsGkAtoms::math) && aAttribute == nsGkAtoms::mode) {
       WarnDeprecated(nsGkAtoms::mode->GetUTF16String(),
                      nsGkAtoms::display->GetUTF16String(), OwnerDoc());
@@ -172,17 +173,19 @@ nsMathMLElement::ParseAttribute(int32_t 
       if (aAttribute == nsGkAtoms::rowspan) {
         aResult.ParseClampedNonNegativeInt(aValue, 1, 0, MAX_ROWSPAN);
         return true;
       }
     }
   }
 
   return nsMathMLElementBase::ParseAttribute(aNamespaceID, aAttribute,
-                                             aValue, aResult);
+                                             aValue,
+                                             aMaybeScriptedPrincipal,
+                                             aResult);
 }
 
 static Element::MappedAttributeEntry sMtableStyles[] = {
   { &nsGkAtoms::width },
   { nullptr }
 };
 
 static Element::MappedAttributeEntry sTokenStyles[] = {
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -46,16 +46,17 @@ public:
                       nsIContent* aBindingParent,
                       bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   enum {
     PARSE_ALLOW_UNITLESS = 0x01, // unitless 0 will be turned into 0px
     PARSE_ALLOW_NEGATIVE = 0x02,
--- a/dom/security/nsCSPContext.cpp
+++ b/dom/security/nsCSPContext.cpp
@@ -34,16 +34,17 @@
 #include "nsNetUtil.h"
 #include "nsIContentPolicy.h"
 #include "nsSupportsPrimitives.h"
 #include "nsThreadUtils.h"
 #include "nsString.h"
 #include "nsScriptSecurityManager.h"
 #include "nsStringStream.h"
 #include "mozilla/Logging.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/dom/CSPReportBinding.h"
 #include "mozilla/dom/CSPDictionariesBinding.h"
 #include "mozilla/net/ReferrerPolicy.h"
 #include "nsINetworkInterceptController.h"
 #include "nsSandboxFlags.h"
 #include "nsIScriptElement.h"
 #include "nsIEventTarget.h"
 #include "mozilla/dom/DocGroup.h"
@@ -266,22 +267,32 @@ NS_IMPL_CLASSINFO(nsCSPContext,
                   nullptr,
                   nsIClassInfo::MAIN_THREAD_ONLY,
                   NS_CSPCONTEXT_CID)
 
 NS_IMPL_ISUPPORTS_CI(nsCSPContext,
                      nsIContentSecurityPolicy,
                      nsISerializable)
 
+int32_t nsCSPContext::sScriptSampleMaxLength;
+
 nsCSPContext::nsCSPContext()
   : mInnerWindowID(0)
   , mLoadingContext(nullptr)
   , mLoadingPrincipal(nullptr)
   , mQueueUpMessages(true)
 {
+  static bool sInitialized = false;
+  if (!sInitialized) {
+    Preferences::AddIntVarCache(&sScriptSampleMaxLength,
+                                "security.csp.reporting.script-sample.max-length",
+                                40);
+    sInitialized = true;
+  }
+
   CSPCONTEXTLOG(("nsCSPContext::nsCSPContext"));
 }
 
 nsCSPContext::~nsCSPContext()
 {
   CSPCONTEXTLOG(("nsCSPContext::~nsCSPContext"));
   for (uint32_t i = 0; i < mPolicies.Length(); i++) {
     delete mPolicies[i];
@@ -474,19 +485,19 @@ nsCSPContext::reportInlineViolation(nsCo
 
   // use selfURI as the sourceFile
   nsAutoCString sourceFile;
   if (mSelfURI) {
     mSelfURI->GetSpec(sourceFile);
   }
 
   nsAutoString codeSample(aContent);
-  // cap the length of the script sample at 40 chars
-  if (codeSample.Length() > 40) {
-    codeSample.Truncate(40);
+  // cap the length of the script sample
+  if (codeSample.Length() > ScriptSampleMaxLength()) {
+    codeSample.Truncate(ScriptSampleMaxLength());
     codeSample.AppendLiteral("...");
   }
   AsyncReportViolation(selfISupports,                      // aBlockedContentSource
                        mSelfURI,                           // aOriginalURI
                        aViolatedDirective,                 // aViolatedDirective
                        aViolatedPolicyIndex,               // aViolatedPolicyIndex
                        observerSubject,                    // aObserverSubject
                        NS_ConvertUTF8toUTF16(sourceFile),  // aSourceFile
--- a/dom/security/nsCSPContext.h
+++ b/dom/security/nsCSPContext.h
@@ -101,16 +101,23 @@ class nsCSPContext : public nsIContentSe
     // helper to report inline script/style violations
     void reportInlineViolation(nsContentPolicyType aContentType,
                                const nsAString& aNonce,
                                const nsAString& aContent,
                                const nsAString& aViolatedDirective,
                                uint32_t aViolatedPolicyIndex,
                                uint32_t aLineNumber);
 
+    static int32_t sScriptSampleMaxLength;
+
+    static uint32_t ScriptSampleMaxLength()
+    {
+      return std::max(sScriptSampleMaxLength, 0);
+    }
+
     nsString                                   mReferrer;
     uint64_t                                   mInnerWindowID; // used for web console logging
     nsTArray<nsCSPPolicy*>                     mPolicies;
     nsCOMPtr<nsIURI>                           mSelfURI;
     nsDataHashtable<nsCStringHashKey, int16_t> mShouldLoadCache;
     nsCOMPtr<nsILoadGroup>                     mCallingChannelLoadGroup;
     nsWeakPtr                                  mLoadingContext;
     // The CSP hangs off the principal, so let's store a raw pointer of the principal
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -751,16 +751,17 @@ nsSMILCSSValueType::ValueFromString(nsCS
   if (!presContext) {
     NS_WARNING("Not parsing animation value; unable to get PresContext");
     return;
   }
 
   nsIDocument* doc = aTargetElement->GetUncomposedDoc();
   if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr,
                                                 doc->NodePrincipal(),
+                                                nullptr,
                                                 doc->GetDocumentURI(),
                                                 0, aString, nullptr)) {
     return;
   }
 
   RefPtr<nsStyleContext> styleContext =
     nsComputedDOMStyle::GetStyleContext(aTargetElement, nullptr,
                                         presContext->PresShell());
@@ -806,16 +807,17 @@ nsSMILCSSValueType::ValueFromAnimationVa
   // We'd like to avoid serializing |aValue| if possible, and since the
   // string passed to CSPAllowsInlineStyle is only used for reporting violations
   // and an intermediate CSS value is not likely to be particularly useful
   // in that case, we just use a generic placeholder string instead.
   static const nsLiteralString kPlaceholderText =
     NS_LITERAL_STRING("[SVG animation of CSS]");
   if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr,
                                                 doc->NodePrincipal(),
+                                                nullptr,
                                                 doc->GetDocumentURI(),
                                                 0, kPlaceholderText, nullptr)) {
     return result;
   }
 
   sSingleton.Init(result);
   result.mU.mPtr = new ValueWrapper(aPropID, aValue);
 
--- a/dom/svg/SVGAnimateTransformElement.cpp
+++ b/dom/svg/SVGAnimateTransformElement.cpp
@@ -25,16 +25,17 @@ SVGAnimateTransformElement::SVGAnimateTr
   : SVGAnimationElement(aNodeInfo)
 {
 }
 
 bool
 SVGAnimateTransformElement::ParseAttribute(int32_t aNamespaceID,
                                            nsAtom* aAttribute,
                                            const nsAString& aValue,
+                                           nsIPrincipal* aMaybeScriptedPrincipal,
                                            nsAttrValue& aResult)
 {
   // 'type' is an <animateTransform>-specific attribute, and we'll handle it
   // specially.
   if (aNamespaceID == kNameSpaceID_None && aAttribute == nsGkAtoms::type) {
     aResult.ParseAtom(aValue);
     nsAtom* atom = aResult.GetAtomValue();
     if (atom != nsGkAtoms::translate &&
@@ -44,16 +45,17 @@ SVGAnimateTransformElement::ParseAttribu
         atom != nsGkAtoms::skewY) {
       ReportAttributeParseFailure(OwnerDoc(), aAttribute, aValue);
     }
     return true;
   }
 
   return SVGAnimationElement::ParseAttribute(aNamespaceID,
                                              aAttribute, aValue,
+                                             aMaybeScriptedPrincipal,
                                              aResult);
 }
 
 //----------------------------------------------------------------------
 // nsIDOMNode methods
 
 NS_IMPL_ELEMENT_CLONE_WITH_INIT(SVGAnimateTransformElement)
 
--- a/dom/svg/SVGAnimateTransformElement.h
+++ b/dom/svg/SVGAnimateTransformElement.h
@@ -30,20 +30,21 @@ protected:
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 public:
   // nsIDOMNode specializations
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // Element specializations
-  bool ParseAttribute(int32_t aNamespaceID,
-                        nsAtom* aAttribute,
-                        const nsAString& aValue,
-                        nsAttrValue& aResult) override;
+  virtual bool ParseAttribute(int32_t aNamespaceID,
+                              nsAtom* aAttribute,
+                              const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
+                              nsAttrValue& aResult) override;
 
   // SVGAnimationElement
   virtual nsSMILAnimationFunction& AnimationFunction() override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -239,16 +239,17 @@ SVGAnimationElement::UnbindFromTree(bool
 
   SVGAnimationElementBase::UnbindFromTree(aDeep, aNullParent);
 }
 
 bool
 SVGAnimationElement::ParseAttribute(int32_t aNamespaceID,
                                     nsAtom* aAttribute,
                                     const nsAString& aValue,
+                                    nsIPrincipal* aMaybeScriptedPrincipal,
                                     nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     // Deal with target-related attributes here
     if (aAttribute == nsGkAtoms::attributeName) {
       aResult.ParseAtom(aValue);
       AnimationNeedsResample();
       return true;
@@ -273,17 +274,19 @@ SVGAnimationElement::ParseAttribute(int3
         ReportAttributeParseFailure(OwnerDoc(), aAttribute, aValue);
         return false;
       }
       return true;
     }
   }
 
   return SVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
-                                                 aValue, aResult);
+                                                 aValue,
+                                                 aMaybeScriptedPrincipal,
+                                                 aResult);
 }
 
 nsresult
 SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
                                   const nsAttrValue* aOldValue,
                                   nsIPrincipal* aSubjectPrincipal,
                                   bool aNotify)
--- a/dom/svg/SVGAnimationElement.h
+++ b/dom/svg/SVGAnimationElement.h
@@ -52,16 +52,17 @@ public:
                              bool aNotify) override;
 
   virtual bool IsNodeOfType(uint32_t aFlags) const override;
 
   // Element specializations
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   const nsAttrValue* GetAnimAttr(nsAtom* aName) const;
--- a/dom/svg/SVGMPathElement.cpp
+++ b/dom/svg/SVGMPathElement.cpp
@@ -114,21 +114,24 @@ SVGMPathElement::UnbindFromTree(bool aDe
   UnlinkHrefTarget(true);
   SVGMPathElementBase::UnbindFromTree(aDeep, aNullParent);
 }
 
 bool
 SVGMPathElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   bool returnVal =
     SVGMPathElementBase::ParseAttribute(aNamespaceID, aAttribute,
-                                          aValue, aResult);
+                                          aValue,
+                                          aMaybeScriptedPrincipal,
+                                          aResult);
   if ((aNamespaceID == kNameSpaceID_XLink ||
        aNamespaceID == kNameSpaceID_None ) &&
       aAttribute == nsGkAtoms::href &&
       IsInUncomposedDoc()) {
     // Note: If we fail the IsInDoc call, it's ok -- we'll update the target
     // on next BindToTree call.
 
     // Note: "href" takes priority over xlink:href. So if "xlink:href" is being
--- a/dom/svg/SVGMPathElement.h
+++ b/dom/svg/SVGMPathElement.h
@@ -50,16 +50,17 @@ public:
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual nsresult UnsetAttr(int32_t aNamespaceID, nsAtom* aAttribute,
                              bool aNotify) override;
   // Element specializations
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   // Public helper method: If our xlink:href attribute links to a <path>
   // element, this method returns a pointer to that element. Otherwise,
   // this returns nullptr.
   SVGPathElement* GetReferencedPath();
 
   // WebIDL
--- a/dom/svg/SVGMarkerElement.cpp
+++ b/dom/svg/SVGMarkerElement.cpp
@@ -206,16 +206,17 @@ SVGMarkerElement::IsAttributeMapped(cons
 }
 
 //----------------------------------------------------------------------
 // nsSVGElement methods
 
 bool
 SVGMarkerElement::ParseAttribute(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::orient) {
     if (aValue.EqualsLiteral("auto")) {
       mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO);
       aResult.SetTo(aValue);
       mAngleAttributes[ORIENT].SetBaseValue(0.f, this, false);
       return true;
@@ -225,17 +226,19 @@ SVGMarkerElement::ParseAttribute(int32_t
       mOrientType.SetBaseValue(SVG_MARKER_ORIENT_AUTO_START_REVERSE);
       aResult.SetTo(aValue);
       mAngleAttributes[ORIENT].SetBaseValue(0.f, this, false);
       return true;
     }
     mOrientType.SetBaseValue(SVG_MARKER_ORIENT_ANGLE);
   }
   return SVGMarkerElementBase::ParseAttribute(aNameSpaceID, aName,
-                                              aValue, aResult);
+                                              aValue,
+                                              aMaybeScriptedPrincipal,
+                                              aResult);
 }
 
 nsresult
 SVGMarkerElement::UnsetAttr(int32_t aNamespaceID, nsAtom* aName,
                             bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::orient) {
--- a/dom/svg/SVGMarkerElement.h
+++ b/dom/svg/SVGMarkerElement.h
@@ -146,16 +146,17 @@ public:
   already_AddRefed<SVGAnimatedAngle> OrientAngle();
   void SetOrientToAuto();
   void SetOrientToAngle(SVGAngle& angle, ErrorResult& rv);
 
 protected:
 
   virtual bool ParseAttribute(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult) override;
 
   void SetParentCoordCtxProvider(SVGViewportElement *aContext);
 
   virtual LengthAttributesInfo GetLengthInfo() override;
   virtual AngleAttributesInfo GetAngleInfo() override;
   virtual EnumAttributesInfo GetEnumInfo() override;
   virtual nsSVGViewBox *GetViewBox() override;
--- a/dom/svg/SVGScriptElement.cpp
+++ b/dom/svg/SVGScriptElement.cpp
@@ -247,26 +247,29 @@ SVGScriptElement::AfterSetAttr(int32_t a
                                             aValue, aOldValue,
                                             aSubjectPrincipal, aNotify);
 }
 
 bool
 SVGScriptElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
+                                 nsIPrincipal* aMaybeScriptedPrincipal,
                                  nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None &&
       aAttribute == nsGkAtoms::crossorigin) {
     ParseCORSValue(aValue, aResult);
     return true;
   }
 
   return SVGScriptElementBase::ParseAttribute(aNamespaceID, aAttribute,
-                                              aValue, aResult);
+                                              aValue,
+                                              aMaybeScriptedPrincipal,
+                                              aResult);
 }
 
 CORSMode
 SVGScriptElement::GetCORSMode() const
 {
   return AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
 }
 
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -57,16 +57,17 @@ public:
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // WebIDL
   void GetType(nsAString & aType);
   void SetType(const nsAString & aType, ErrorResult& rv);
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -130,26 +130,27 @@ SVGStyleElement::UnsetAttr(int32_t aName
 
   return rv;
 }
 
 bool
 SVGStyleElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 nsAttrValue& aResult)
 {
   if (aNamespaceID == kNameSpaceID_None &&
       aAttribute == nsGkAtoms::crossorigin) {
     ParseCORSValue(aValue, aResult);
     return true;
   }
 
   return SVGStyleElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                             aResult);
+                                             aMaybeScriptedPrincipal, aResult);
 }
 
 //----------------------------------------------------------------------
 // nsIMutationObserver methods
 
 void
 SVGStyleElement::CharacterDataChanged(nsIDocument* aDocument,
                                       nsIContent* aContent,
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -49,16 +49,17 @@ public:
                            nsAtom* aPrefix, const nsAString& aValue,
                            nsIPrincipal* aSubjectPrincipal,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                              bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID,
                               nsAtom* aAttribute,
                               const nsAString& aValue,
+                              nsIPrincipal* aMaybeScriptedPrincipal,
                               nsAttrValue& aResult) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -281,17 +281,17 @@ nsSVGElement::BindToTree(nsIDocument* aD
     // XBL anonymous content now being bound to the document we should
     // render in and due to the hacky way in which we implement the
     // interaction of XBL and SVG resources.  Once we have a sane
     // ownerDocument on XBL anonymous content, this can all go away.
     nsAttrValue attrValue;
     nsAutoString stringValue;
     oldVal->ToString(stringValue);
     // Force in data doc, since we already have a style rule
-    ParseStyleAttribute(stringValue, attrValue, true);
+    ParseStyleAttribute(stringValue, nullptr, attrValue, true);
     // Don't bother going through SetInlineStyleDeclaration; we don't
     // want to fire off mutation events or document notifications anyway
     bool oldValueSet;
     rv = mAttrsAndChildren.SetAndSwapAttr(nsGkAtoms::style, attrValue,
                                           &oldValueSet);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
@@ -336,16 +336,17 @@ nsSVGElement::AfterSetAttr(int32_t aName
   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
                                         aSubjectPrincipal, aNotify);
 }
 
 bool
 nsSVGElement::ParseAttribute(int32_t aNamespaceID,
                              nsAtom* aAttribute,
                              const nsAString& aValue,
+                             nsIPrincipal* aMaybeScriptedPrincipal,
                              nsAttrValue& aResult)
 {
   nsresult rv = NS_OK;
   bool foundMatch = false;
   bool didSetResult = false;
 
   if (aNamespaceID == kNameSpaceID_None) {
     // Check for nsSVGLength2 attribute
@@ -668,17 +669,17 @@ nsSVGElement::ParseAttribute(int32_t aNa
     }
     if (!didSetResult) {
       aResult.SetTo(aValue);
     }
     return true;
   }
 
   return nsSVGElementBase::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                          aResult);
+                                          aMaybeScriptedPrincipal, aResult);
 }
 
 void
 nsSVGElement::UnsetAttrInternal(int32_t aNamespaceID, nsAtom* aName,
                                 bool aNotify)
 {
   // XXXbz there's a bunch of redundancy here with AfterSetAttr.
   // Maybe consolidate?
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -350,17 +350,19 @@ protected:
   }
 #endif // DEBUG
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
                                 nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual bool ParseAttribute(int32_t aNamespaceID, nsAtom* aAttribute,
-                                const nsAString& aValue, nsAttrValue& aResult) override;
+                                const nsAString& aValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                nsAttrValue& aResult) override;
   static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
                                               nsAtom* aAttribute,
                                               const nsAString& aValue);
 
   nsAttrValue WillChangeValue(nsAtom* aName);
   // aNewValue is set to the old value. This value may be invalid if
   // !StoresOwnData.
   void DidChangeValue(nsAtom* aName, const nsAttrValue& aEmptyOrOldValue,
--- a/dom/webauthn/u2f-hid-rs/src/lib.rs
+++ b/dom/webauthn/u2f-hid-rs/src/lib.rs
@@ -30,16 +30,17 @@ pub mod platform;
 #[macro_use]
 extern crate log;
 extern crate rand;
 extern crate libc;
 extern crate boxfnonce;
 extern crate runloop;
 
 mod consts;
+mod statemachine;
 mod u2ftypes;
 mod u2fprotocol;
 
 mod manager;
 pub use manager::U2FManager;
 
 mod capi;
 pub use capi::*;
--- a/dom/webauthn/u2f-hid-rs/src/linux/mod.rs
+++ b/dom/webauthn/u2f-hid-rs/src/linux/mod.rs
@@ -1,149 +1,9 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use std::time::Duration;
-use std::thread;
+pub mod device;
+pub mod transaction;
 
-mod device;
 mod hidraw;
 mod monitor;
-mod transaction;
-
-use consts::PARAMETER_SIZE;
-use platform::device::Device;
-use platform::transaction::Transaction;
-use util::{io_err, OnceCallback};
-use u2fprotocol::{u2f_init_device, u2f_is_keyhandle_valid, u2f_register, u2f_sign};
-
-#[derive(Default)]
-pub struct PlatformManager {
-    transaction: Option<Transaction>,
-}
-
-impl PlatformManager {
-    pub fn new() -> Self {
-        Default::default()
-    }
-
-    pub fn register(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<Vec<u8>>,
-    ) {
-        // Abort any prior register/sign calls.
-        self.cancel();
-
-        let cbc = callback.clone();
-
-        let transaction = Transaction::new(timeout, cbc.clone(), move |path, alive| {
-            // Create a new device.
-            let dev = &mut match Device::new(path) {
-                Ok(dev) => dev,
-                _ => return,
-            };
-
-            // Try initializing it.
-            if !dev.is_u2f() || !u2f_init_device(dev) {
-                return;
-            }
-
-            // Iterate the exclude list and see if there are any matches.
-            // Abort the state machine if we found a valid key handle.
-            if key_handles.iter().any(|key_handle| {
-                u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                    .unwrap_or(false) /* no match on failure */
-            })
-            {
-                return;
-            }
-
-            while alive() {
-                if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
-                    callback.call(Ok(bytes));
-                    break;
-                }
-
-                // Sleep a bit before trying again.
-                thread::sleep(Duration::from_millis(100));
-            }
-        });
-
-        self.transaction = Some(try_or!(transaction, |_| {
-            cbc.call(Err(io_err("couldn't create transaction")))
-        }));
-    }
-
-    pub fn sign(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
-    ) {
-        // Abort any prior register/sign calls.
-        self.cancel();
-
-        let cbc = callback.clone();
-
-        let transaction = Transaction::new(timeout, cbc.clone(), move |path, alive| {
-            // Create a new device.
-            let dev = &mut match Device::new(path) {
-                Ok(dev) => dev,
-                _ => return,
-            };
-
-            // Try initializing it.
-            if !dev.is_u2f() || !u2f_init_device(dev) {
-                return;
-            }
-
-            // Find all matching key handles.
-            let key_handles = key_handles
-                .iter()
-                .filter(|key_handle| {
-                    u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                        .unwrap_or(false) /* no match on failure */
-                })
-                .collect::<Vec<_>>();
-
-            while alive() {
-                // If the device matches none of the given key handles
-                // then just make it blink with bogus data.
-                if key_handles.is_empty() {
-                    let blank = vec![0u8; PARAMETER_SIZE];
-                    if let Ok(_) = u2f_register(dev, &blank, &blank) {
-                        callback.call(Err(io_err("invalid key")));
-                        break;
-                    }
-                } else {
-                    // Otherwise, try to sign.
-                    for key_handle in &key_handles {
-                        if let Ok(bytes) = u2f_sign(dev, &challenge, &application, key_handle) {
-                            callback.call(Ok((key_handle.to_vec(), bytes)));
-                            break;
-                        }
-                    }
-                }
-
-                // Sleep a bit before trying again.
-                thread::sleep(Duration::from_millis(100));
-            }
-        });
-
-        self.transaction = Some(try_or!(transaction, |_| {
-            cbc.call(Err(io_err("couldn't create transaction")))
-        }));
-    }
-
-    // This blocks.
-    pub fn cancel(&mut self) {
-        if let Some(mut transaction) = self.transaction.take() {
-            transaction.cancel();
-        }
-    }
-}
--- a/dom/webauthn/u2f-hid-rs/src/macos/device.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/device.rs
@@ -2,51 +2,42 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 extern crate log;
 
 use consts::{CID_BROADCAST, HID_RPT_SIZE};
 use core_foundation_sys::base::*;
 use platform::iokit::*;
-use std::{fmt, io};
+use std::io;
 use std::io::{Read, Write};
 use std::sync::mpsc::{Receiver, RecvTimeoutError};
 use std::time::Duration;
 use u2ftypes::U2FDevice;
 
 const READ_TIMEOUT: u64 = 15;
 
 pub struct Device {
     device_ref: IOHIDDeviceRef,
     cid: [u8; 4],
     report_rx: Receiver<Vec<u8>>,
 }
 
 impl Device {
-    pub fn new(device_ref: IOHIDDeviceRef, report_rx: Receiver<Vec<u8>>) -> Self {
-        Self {
+    pub fn new(dev_info: (IOHIDDeviceRef, Receiver<Vec<u8>>)) -> io::Result<Self> {
+        let (device_ref, report_rx) = dev_info;
+        Ok(Self {
             device_ref,
             cid: CID_BROADCAST,
             report_rx,
-        }
+        })
     }
-}
 
-impl fmt::Display for Device {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        write!(
-            f,
-            "InternalDevice(ref:{:?}, cid: {:02x}{:02x}{:02x}{:02x})",
-            self.device_ref,
-            self.cid[0],
-            self.cid[1],
-            self.cid[2],
-            self.cid[3]
-        )
+    pub fn is_u2f(&self) -> bool {
+        true
     }
 }
 
 impl PartialEq for Device {
     fn eq(&self, other_device: &Device) -> bool {
         self.device_ref == other_device.device_ref
     }
 }
--- a/dom/webauthn/u2f-hid-rs/src/macos/mod.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/mod.rs
@@ -1,147 +1,9 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-extern crate log;
+pub mod device;
+pub mod transaction;
 
-mod device;
 mod iokit;
 mod monitor;
-mod transaction;
-
-use consts::PARAMETER_SIZE;
-use platform::device::Device;
-use platform::transaction::Transaction;
-use std::thread;
-use std::time::Duration;
-use u2fprotocol::{u2f_init_device, u2f_register, u2f_sign, u2f_is_keyhandle_valid};
-use util::{io_err, OnceCallback};
-
-#[derive(Default)]
-pub struct PlatformManager {
-    transaction: Option<Transaction>,
-}
-
-impl PlatformManager {
-    pub fn new() -> Self {
-        Default::default()
-    }
-
-    pub fn register(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<Vec<u8>>,
-    ) {
-        // Abort any prior register/sign calls.
-        self.cancel();
-
-        let cbc = callback.clone();
-
-        // Start a new "sign" transaction.
-        let transaction = Transaction::new(timeout, cbc.clone(), move |device_ref, rx, alive| {
-            // Create a new device.
-            let dev = &mut Device::new(device_ref, rx);
-
-            // Try initializing it.
-            if !u2f_init_device(dev) {
-                return;
-            }
-
-            // Iterate the exclude list and see if there are any matches.
-            // Abort the state machine if we found a valid key handle.
-            if key_handles.iter().any(|key_handle| {
-                u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                    .unwrap_or(false) /* no match on failure */
-            })
-            {
-                return;
-            }
-
-            while alive() {
-                if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
-                    callback.call(Ok(bytes));
-                    break;
-                }
-
-                // Sleep a bit before trying again.
-                thread::sleep(Duration::from_millis(100));
-            }
-        });
-
-        // Store the transaction so we can cancel it, if needed.
-        self.transaction = Some(try_or!(transaction, |_| {
-            cbc.call(Err(io_err("couldn't create transaction")))
-        }));
-    }
-
-    pub fn sign(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
-    ) {
-        // Abort any prior register/sign calls.
-        self.cancel();
-
-        let cbc = callback.clone();
-
-        // Start a new "register" transaction.
-        let transaction = Transaction::new(timeout, cbc.clone(), move |device_ref, rx, alive| {
-            // Create a new device.
-            let dev = &mut Device::new(device_ref, rx);
-
-            // Try initializing it.
-            if !u2f_init_device(dev) {
-                return;
-            }
-
-            // Find all matching key handles.
-            let key_handles = key_handles
-                .iter()
-                .filter(|key_handle| {
-                    u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                        .unwrap_or(false) /* no match on failure */
-                })
-                .collect::<Vec<_>>();
-
-            while alive() {
-                // If the device matches none of the given key handles
-                // then just make it blink with bogus data.
-                if key_handles.is_empty() {
-                    let blank = vec![0u8; PARAMETER_SIZE];
-                    if let Ok(_) = u2f_register(dev, &blank, &blank) {
-                        callback.call(Err(io_err("invalid key")));
-                        break;
-                    }
-                } else {
-                    // Otherwise, try to sign.
-                    for key_handle in &key_handles {
-                        if let Ok(bytes) = u2f_sign(dev, &challenge, &application, key_handle) {
-                            callback.call(Ok((key_handle.to_vec(), bytes)));
-                            break;
-                        }
-                    }
-                }
-
-                // Sleep a bit before trying again.
-                thread::sleep(Duration::from_millis(100));
-            }
-        });
-
-        // Store the transaction so we can cancel it, if needed.
-        self.transaction = Some(try_or!(transaction, |_| {
-            cbc.call(Err(io_err("couldn't create transaction")))
-        }));
-    }
-
-    pub fn cancel(&mut self) {
-        if let Some(mut transaction) = self.transaction.take() {
-            transaction.cancel();
-        }
-    }
-}
--- a/dom/webauthn/u2f-hid-rs/src/macos/monitor.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/monitor.rs
@@ -17,28 +17,28 @@ use util::io_err;
 
 struct DeviceData {
     tx: Sender<Vec<u8>>,
     runloop: RunLoop,
 }
 
 pub struct Monitor<F>
 where
-    F: Fn(IOHIDDeviceRef, Receiver<Vec<u8>>, &Fn() -> bool) + Sync,
+    F: Fn((IOHIDDeviceRef, Receiver<Vec<u8>>), &Fn() -> bool) + Sync,
 {
     manager: IOHIDManagerRef,
     // Keep alive until the monitor goes away.
     _matcher: IOHIDDeviceMatcher,
     map: HashMap<IOHIDDeviceRef, DeviceData>,
     new_device_cb: F,
 }
 
 impl<F> Monitor<F>
 where
-    F: Fn(IOHIDDeviceRef, Receiver<Vec<u8>>, &Fn() -> bool) + Sync + 'static,
+    F: Fn((IOHIDDeviceRef, Receiver<Vec<u8>>), &Fn() -> bool) + Sync + 'static,
 {
     pub fn new(new_device_cb: F) -> Self {
         let manager = unsafe { IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDManagerOptionNone) };
 
         // Match FIDO devices only.
         let _matcher = IOHIDDeviceMatcher::new();
         unsafe { IOHIDManagerSetDeviceMatching(manager, _matcher.get()) };
 
@@ -140,17 +140,17 @@ where
 
         let (tx, rx) = channel();
         let f = &this.new_device_cb;
 
         // Create a new per-device runloop.
         let runloop = RunLoop::new(move |alive| {
             // Ensure that the runloop is still alive.
             if alive() {
-                f(device_ref, rx, alive);
+                f((device_ref, rx), alive);
             }
         });
 
         if let Ok(runloop) = runloop {
             this.map.insert(device_ref, DeviceData { tx, runloop });
         }
     }
 
@@ -162,14 +162,14 @@ where
     ) {
         let this = unsafe { &mut *(context as *mut Self) };
         this.remove_device(&device_ref);
     }
 }
 
 impl<F> Drop for Monitor<F>
 where
-    F: Fn(IOHIDDeviceRef, Receiver<Vec<u8>>, &Fn() -> bool) + Sync,
+    F: Fn((IOHIDDeviceRef, Receiver<Vec<u8>>), &Fn() -> bool) + Sync,
 {
     fn drop(&mut self) {
         unsafe { CFRelease(self.manager as *mut libc::c_void) };
     }
 }
--- a/dom/webauthn/u2f-hid-rs/src/macos/transaction.rs
+++ b/dom/webauthn/u2f-hid-rs/src/macos/transaction.rs
@@ -20,17 +20,17 @@ use util::{io_err, to_io_err, OnceCallba
 pub struct Transaction {
     runloop: Option<SendableRunLoop>,
     thread: Option<thread::JoinHandle<()>>,
 }
 
 impl Transaction {
     pub fn new<F, T>(timeout: u64, callback: OnceCallback<T>, new_device_cb: F) -> io::Result<Self>
     where
-        F: Fn(IOHIDDeviceRef, Receiver<Vec<u8>>, &Fn() -> bool) + Sync + Send + 'static,
+        F: Fn((IOHIDDeviceRef, Receiver<Vec<u8>>), &Fn() -> bool) + Sync + Send + 'static,
         T: 'static,
     {
         let (tx, rx) = channel();
         let timeout = (timeout as f64) / 1000.0;
 
         let builder = thread::Builder::new();
         let thread = builder.spawn(move || {
             // Add a runloop observer that will be notified when we enter the
--- a/dom/webauthn/u2f-hid-rs/src/manager.rs
+++ b/dom/webauthn/u2f-hid-rs/src/manager.rs
@@ -2,17 +2,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/. */
 
 use std::io;
 use std::sync::mpsc::{channel, Sender, RecvTimeoutError};
 use std::time::Duration;
 
 use consts::PARAMETER_SIZE;
-use platform::PlatformManager;
+use statemachine::StateMachine;
 use runloop::RunLoop;
 use util::{to_io_err, OnceCallback};
 
 pub enum QueueAction {
     Register {
         timeout: u64,
         challenge: Vec<u8>,
         application: Vec<u8>,
@@ -35,54 +35,54 @@ pub struct U2FManager {
 }
 
 impl U2FManager {
     pub fn new() -> io::Result<Self> {
         let (tx, rx) = channel();
 
         // Start a new work queue thread.
         let queue = RunLoop::new(move |alive| {
-            let mut pm = PlatformManager::new();
+            let mut sm = StateMachine::new();
 
             while alive() {
                 match rx.recv_timeout(Duration::from_millis(50)) {
                     Ok(QueueAction::Register {
                            timeout,
                            challenge,
                            application,
                            key_handles,
                            callback,
                        }) => {
                         // This must not block, otherwise we can't cancel.
-                        pm.register(timeout, challenge, application, key_handles, callback);
+                        sm.register(timeout, challenge, application, key_handles, callback);
                     }
                     Ok(QueueAction::Sign {
                            timeout,
                            challenge,
                            application,
                            key_handles,
                            callback,
                        }) => {
                         // This must not block, otherwise we can't cancel.
-                        pm.sign(timeout, challenge, application, key_handles, callback);
+                        sm.sign(timeout, challenge, application, key_handles, callback);
                     }
                     Ok(QueueAction::Cancel) => {
                         // Cancelling must block so that we don't start a new
                         // polling thread before the old one has shut down.
-                        pm.cancel();
+                        sm.cancel();
                     }
                     Err(RecvTimeoutError::Disconnected) => {
                         break;
                     }
                     _ => { /* continue */ }
                 }
             }
 
             // Cancel any ongoing activity.
-            pm.cancel();
+            sm.cancel();
         })?;
 
         Ok(Self {
             queue: queue,
             tx: tx,
         })
     }
 
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/u2f-hid-rs/src/statemachine.rs
@@ -0,0 +1,143 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use consts::PARAMETER_SIZE;
+use platform::device::Device;
+use platform::transaction::Transaction;
+use std::thread;
+use std::time::Duration;
+use util::{io_err, OnceCallback};
+use u2fprotocol::{u2f_init_device, u2f_is_keyhandle_valid, u2f_register, u2f_sign};
+
+#[derive(Default)]
+pub struct StateMachine {
+    transaction: Option<Transaction>,
+}
+
+impl StateMachine {
+    pub fn new() -> Self {
+        Default::default()
+    }
+
+    pub fn register(
+        &mut self,
+        timeout: u64,
+        challenge: Vec<u8>,
+        application: Vec<u8>,
+        key_handles: Vec<Vec<u8>>,
+        callback: OnceCallback<Vec<u8>>,
+    ) {
+        // Abort any prior register/sign calls.
+        self.cancel();
+
+        let cbc = callback.clone();
+
+        let transaction = Transaction::new(timeout, cbc.clone(), move |info, alive| {
+            // Create a new device.
+            let dev = &mut match Device::new(info) {
+                Ok(dev) => dev,
+                _ => return,
+            };
+
+            // Try initializing it.
+            if !dev.is_u2f() || !u2f_init_device(dev) {
+                return;
+            }
+
+            // Iterate the exclude list and see if there are any matches.
+            // Abort the state machine if we found a valid key handle.
+            if key_handles.iter().any(|key_handle| {
+                u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
+                    .unwrap_or(false) /* no match on failure */
+            })
+            {
+                return;
+            }
+
+            while alive() {
+                if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
+                    callback.call(Ok(bytes));
+                    break;
+                }
+
+                // Sleep a bit before trying again.
+                thread::sleep(Duration::from_millis(100));
+            }
+        });
+
+        self.transaction = Some(try_or!(transaction, |_| {
+            cbc.call(Err(io_err("couldn't create transaction")))
+        }));
+    }
+
+    pub fn sign(
+        &mut self,
+        timeout: u64,
+        challenge: Vec<u8>,
+        application: Vec<u8>,
+        key_handles: Vec<Vec<u8>>,
+        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
+    ) {
+        // Abort any prior register/sign calls.
+        self.cancel();
+
+        let cbc = callback.clone();
+
+        let transaction = Transaction::new(timeout, cbc.clone(), move |info, alive| {
+            // Create a new device.
+            let dev = &mut match Device::new(info) {
+                Ok(dev) => dev,
+                _ => return,
+            };
+
+            // Try initializing it.
+            if !dev.is_u2f() || !u2f_init_device(dev) {
+                return;
+            }
+
+            // Find all matching key handles.
+            let key_handles = key_handles
+                .iter()
+                .filter(|key_handle| {
+                    u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
+                        .unwrap_or(false) /* no match on failure */
+                })
+                .collect::<Vec<_>>();
+
+            while alive() {
+                // If the device matches none of the given key handles
+                // then just make it blink with bogus data.
+                if key_handles.is_empty() {
+                    let blank = vec![0u8; PARAMETER_SIZE];
+                    if let Ok(_) = u2f_register(dev, &blank, &blank) {
+                        callback.call(Err(io_err("invalid key")));
+                        break;
+                    }
+                } else {
+                    // Otherwise, try to sign.
+                    for key_handle in &key_handles {
+                        if let Ok(bytes) = u2f_sign(dev, &challenge, &application, key_handle) {
+                            callback.call(Ok((key_handle.to_vec(), bytes)));
+                            break;
+                        }
+                    }
+                }
+
+                // Sleep a bit before trying again.
+                thread::sleep(Duration::from_millis(100));
+            }
+        });
+
+        self.transaction = Some(try_or!(transaction, |_| {
+            cbc.call(Err(io_err("couldn't create transaction")))
+        }));
+    }
+
+    // This blocks.
+    pub fn cancel(&mut self) {
+        if let Some(mut transaction) = self.transaction.take() {
+            transaction.cancel();
+        }
+    }
+}
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/u2f-hid-rs/src/stub/device.rs
@@ -0,0 +1,45 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::io;
+use std::io::{Read, Write};
+use u2ftypes::U2FDevice;
+
+pub struct Device {}
+
+impl Device {
+    pub fn new(path: String) -> io::Result<Self> {
+        panic!("not implemented");
+    }
+
+    pub fn is_u2f(&self) -> bool {
+        panic!("not implemented");
+    }
+}
+
+impl Read for Device {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        panic!("not implemented");
+    }
+}
+
+impl Write for Device {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        panic!("not implemented");
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        panic!("not implemented");
+    }
+}
+
+impl U2FDevice for Device {
+    fn get_cid<'a>(&'a self) -> &'a [u8; 4] {
+        panic!("not implemented");
+    }
+
+    fn set_cid(&mut self, cid: [u8; 4]) {
+        panic!("not implemented");
+    }
+}
--- a/dom/webauthn/u2f-hid-rs/src/stub/mod.rs
+++ b/dom/webauthn/u2f-hid-rs/src/stub/mod.rs
@@ -1,46 +1,11 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // No-op module to permit compiling token HID support for Android, where
 // no results are returned.
 
-#![allow(dead_code)]
-
-use util::{io_err, OnceCallback};
-
-pub struct PlatformManager {}
-
-impl PlatformManager {
-    pub fn new() -> Self {
-        Self {}
-    }
+#![allow(unused_variables)]
 
-    pub fn register(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<Vec<u8>>,
-    ) {
-        // Not implemented.
-        callback.call(Err(io_err("not implemented")));
-    }
-
-    pub fn sign(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
-    ) {
-        // Not implemented.
-        callback.call(Err(io_err("not implemented")));
-    }
-
-    pub fn cancel(&mut self) {
-        // No-op.
-    }
-}
+pub mod device;
+pub mod transaction;
new file mode 100644
--- /dev/null
+++ b/dom/webauthn/u2f-hid-rs/src/stub/transaction.rs
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::io;
+use util::{io_err, OnceCallback};
+
+pub struct Transaction {}
+
+impl Transaction {
+    pub fn new<F, T>(timeout: u64, callback: OnceCallback<T>, new_device_cb: F) -> io::Result<Self>
+    where
+        F: Fn(String, &Fn() -> bool),
+    {
+        callback.call(Err(io_err("not implemented")));
+        Err(io_err("not implemented"))
+    }
+
+    pub fn cancel(&mut self) {
+        /* No-op. */
+    }
+}
--- a/dom/webauthn/u2f-hid-rs/src/windows/mod.rs
+++ b/dom/webauthn/u2f-hid-rs/src/windows/mod.rs
@@ -1,149 +1,9 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use std::thread;
-use std::time::Duration;
-
-mod device;
-mod monitor;
-mod transaction;
-mod winapi;
-
-use consts::PARAMETER_SIZE;
-use platform::device::Device;
-use platform::transaction::Transaction;
-use util::{io_err, OnceCallback};
-use u2fprotocol::{u2f_init_device, u2f_register, u2f_sign, u2f_is_keyhandle_valid};
-
-#[derive(Default)]
-pub struct PlatformManager {
-    transaction: Option<Transaction>,
-}
-
-impl PlatformManager {
-    pub fn new() -> Self {
-        Default::default()
-    }
-
-    pub fn register(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<Vec<u8>>,
-    ) {
-        // Abort any prior register/sign calls.
-        self.cancel();
-
-        let cbc = callback.clone();
-
-        let transaction = Transaction::new(timeout, cbc.clone(), move |path, alive| {
-            // Create a new device.
-            let dev = &mut match Device::new(path) {
-                Ok(dev) => dev,
-                _ => return,
-            };
-
-            // Try initializing it.
-            if !dev.is_u2f() || !u2f_init_device(dev) {
-                return;
-            }
-
-            // Iterate the exclude list and see if there are any matches.
-            // Abort the state machine if we found a valid key handle.
-            if key_handles.iter().any(|key_handle| {
-                u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                    .unwrap_or(false) /* no match on failure */
-            })
-            {
-                return;
-            }
-
-            while alive() {
-                if let Ok(bytes) = u2f_register(dev, &challenge, &application) {
-                    callback.call(Ok(bytes));
-                    break;
-                }
-
-                // Sleep a bit before trying again.
-                thread::sleep(Duration::from_millis(100));
-            }
-        });
+pub mod device;
+pub mod transaction;
 
-        self.transaction = Some(try_or!(transaction, |_| {
-            cbc.call(Err(io_err("couldn't create transaction")));
-        }));
-    }
-
-    pub fn sign(
-        &mut self,
-        timeout: u64,
-        challenge: Vec<u8>,
-        application: Vec<u8>,
-        key_handles: Vec<Vec<u8>>,
-        callback: OnceCallback<(Vec<u8>, Vec<u8>)>,
-    ) {
-        // Abort any prior register/sign calls.
-        self.cancel();
-
-        let cbc = callback.clone();
-
-        let transaction = Transaction::new(timeout, cbc.clone(), move |path, alive| {
-            // Create a new device.
-            let dev = &mut match Device::new(path) {
-                Ok(dev) => dev,
-                _ => return,
-            };
-
-            // Try initializing it.
-            if !dev.is_u2f() || !u2f_init_device(dev) {
-                return;
-            }
-
-            // Find all matching key handles.
-            let key_handles = key_handles
-                .iter()
-                .filter(|key_handle| {
-                    u2f_is_keyhandle_valid(dev, &challenge, &application, key_handle)
-                        .unwrap_or(false) /* no match on failure */
-                })
-                .collect::<Vec<_>>();
-
-            while alive() {
-                // If the device matches none of the given key handles
-                // then just make it blink with bogus data.
-                if key_handles.is_empty() {
-                    let blank = vec![0u8; PARAMETER_SIZE];
-                    if let Ok(_) = u2f_register(dev, &blank, &blank) {
-                        callback.call(Err(io_err("invalid key")));
-                        break;
-                    }
-                } else {
-                    // Otherwise, try to sign.
-                    for key_handle in &key_handles {
-                        if let Ok(bytes) = u2f_sign(dev, &challenge, &application, key_handle) {
-                            callback.call(Ok((key_handle.to_vec(), bytes)));
-                            break;
-                        }
-                    }
-                }
-
-                // Sleep a bit before trying again.
-                thread::sleep(Duration::from_millis(100));
-            }
-        });
-
-        self.transaction = Some(try_or!(transaction, |_| {
-            cbc.call(Err(io_err("couldn't create transaction")));
-        }));
-    }
-
-    // This might block.
-    pub fn cancel(&mut self) {
-        if let Some(mut transaction) = self.transaction.take() {
-            transaction.cancel();
-        }
-    }
-}
+mod monitor;
+mod winapi;
--- a/dom/webidl/CSSStyleDeclaration.webidl
+++ b/dom/webidl/CSSStyleDeclaration.webidl
@@ -3,27 +3,27 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/.
  *
  * The origin of this IDL file is
  * http://dev.w3.org/csswg/cssom/
  */
 
 interface CSSStyleDeclaration {
-  [CEReactions, SetterThrows]
+  [CEReactions, NeedsSubjectPrincipal, SetterThrows]
   attribute DOMString cssText;
 
   readonly attribute unsigned long length;
   getter DOMString item(unsigned long index);
 
   [Throws]
   DOMString getPropertyValue(DOMString property);
   // Mozilla extension, sort of
   [Throws]
   CSSValue? getPropertyCSSValue(DOMString property);
   DOMString getPropertyPriority(DOMString property);
-  [CEReactions, Throws]
+  [CEReactions, NeedsSubjectPrincipal, Throws]
   void setProperty(DOMString property, [TreatNullAs=EmptyString] DOMString value, [TreatNullAs=EmptyString] optional DOMString priority = "");
   [CEReactions, Throws]
   DOMString removeProperty(DOMString property);
 
   readonly attribute CSSRule? parentRule;
 };
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -216,17 +216,17 @@ partial interface Element {
   [ChromeOnly] readonly attribute long scrollTopMin;
                readonly attribute long scrollTopMax;
   [ChromeOnly] readonly attribute long scrollLeftMin;
                readonly attribute long scrollLeftMax;
 };
 
 // http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface
 partial interface Element {
-  [CEReactions, Pure,SetterThrows,TreatNullAs=EmptyString]
+  [CEReactions, NeedsSubjectPrincipal, Pure,SetterThrows,TreatNullAs=EmptyString]
   attribute DOMString innerHTML;
   [CEReactions, Pure,SetterThrows,TreatNullAs=EmptyString]
   attribute DOMString outerHTML;
   [CEReactions, Throws]
   void insertAdjacentHTML(DOMString position, DOMString text);
 };
 
 // http://www.w3.org/TR/selectors-api/#interface-definitions
--- a/dom/webidl/HTMLSelectElement.webidl
+++ b/dom/webidl/HTMLSelectElement.webidl
@@ -6,17 +6,17 @@
  * The origin of this IDL file is
  * http://www.whatwg.org/html/#the-select-element
  */
 
 [HTMLConstructor]
 interface HTMLSelectElement : HTMLElement {
   [CEReactions, SetterThrows, Pure]
   attribute boolean autofocus;
-  [CEReactions, Pref="dom.forms.autocomplete.formautofill", SetterThrows, Pure]
+  [CEReactions, SetterThrows, Pure]
   attribute DOMString autocomplete;
   [CEReactions, SetterThrows, Pure]
   attribute boolean disabled;
   [Pure]
   readonly attribute HTMLFormElement? form;
   [CEReactions, SetterThrows, Pure]
   attribute boolean multiple;
   [CEReactions, SetterThrows, Pure]
--- a/dom/webidl/HTMLTextAreaElement.webidl
+++ b/dom/webidl/HTMLTextAreaElement.webidl
@@ -11,17 +11,18 @@
  * and create derivative works of this document.
  */
 
 interface nsIEditor;
 interface XULControllers;
 
 [HTMLConstructor]
 interface HTMLTextAreaElement : HTMLElement {
-           // attribute DOMString autocomplete;
+  [CEReactions, SetterThrows, Pure]
+           attribute DOMString autocomplete;
   [CEReactions, SetterThrows, Pure]
            attribute boolean autofocus;
   [CEReactions, SetterThrows, Pure]
            attribute unsigned long cols;
            // attribute DOMString dirName;
   [CEReactions, SetterThrows, Pure]
            attribute boolean disabled;
   [Pure]
--- a/dom/webidl/Node.webidl
+++ b/dom/webidl/Node.webidl
@@ -54,17 +54,17 @@ interface Node : EventTarget {
   readonly attribute Node? lastChild;
   [Pure]
   readonly attribute Node? previousSibling;
   [Pure]
   readonly attribute Node? nextSibling;
 
   [CEReactions, SetterThrows, Pure]
            attribute DOMString? nodeValue;
-  [CEReactions, SetterThrows, GetterCanOOM, Pure]
+  [CEReactions, SetterThrows, GetterCanOOM, NeedsSubjectPrincipal, Pure]
            attribute DOMString? textContent;
   [CEReactions, Throws]
   Node insertBefore(Node node, Node? child);
   [CEReactions, Throws]
   Node appendChild(Node node);
   [CEReactions, Throws]
   Node replaceChild(Node node, Node child);
   [CEReactions, Throws]
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -1156,21 +1156,22 @@ nsXULElement::AfterSetAttr(int32_t aName
     return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
                                          aValue, aOldValue, aSubjectPrincipal, aNotify);
 }
 
 bool
 nsXULElement::ParseAttribute(int32_t aNamespaceID,
                              nsAtom* aAttribute,
                              const nsAString& aValue,
+                             nsIPrincipal* aMaybeScriptedPrincipal,
                              nsAttrValue& aResult)
 {
     // Parse into a nsAttrValue
     if (!nsStyledElement::ParseAttribute(aNamespaceID, aAttribute, aValue,
-                                         aResult)) {
+                                         aMaybeScriptedPrincipal, aResult)) {
         // Fall back to parsing as atom for short values
         aResult.ParseStringOrAtom(aValue);
     }
 
     return true;
 }
 
 void
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -754,16 +754,17 @@ protected:
                                   nsIPrincipal* aSubjectPrincipal,
                                   bool aNotify) override;
 
     virtual void UpdateEditableState(bool aNotify) override;
 
     virtual bool ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
+                                  nsIPrincipal* aMaybeScriptedPrincipal,
                                   nsAttrValue& aResult) override;
 
     virtual mozilla::EventListenerManager*
       GetEventListenerManagerForAttr(nsAtom* aAttrName,
                                      bool* aDefer) override;
 
     /**
      * Add a listener for the specified attribute, if appropriate.
--- a/gfx/layers/GLImages.h
+++ b/gfx/layers/GLImages.h
@@ -44,16 +44,22 @@ public:
   }
   bool GetContinuous() const {
     return mContinuous;
   }
   gl::OriginPos GetOriginPos() const {
     return mOriginPos;
   }
 
+  virtual already_AddRefed<gfx::SourceSurface> GetAsSourceSurface() override {
+    // We can implement this, but currently don't want to because it will cause the
+    // SurfaceTexture to be permanently bound to the snapshot readback context.
+    return nullptr;
+  }
+
   SurfaceTextureImage* AsSurfaceTextureImage() override {
     return this;
   }
 
 private:
   AndroidSurfaceTextureHandle mHandle;
   gfx::IntSize mSize;
   bool mContinuous;
--- a/image/decoders/nsGIFDecoder2.cpp
+++ b/image/decoders/nsGIFDecoder2.cpp
@@ -955,18 +955,21 @@ nsGIFDecoder2::ReadImageDataBlock(const 
     if (mColormap == mGIFStruct.global_colormap) {
         mOldColor = mColormap[mGIFStruct.tpixel];
     }
     mColormap[mGIFStruct.tpixel] = 0;
   }
 
   // Initialize the LZW decoder.
   mGIFStruct.datasize = uint8_t(aData[0]);
+  if (mGIFStruct.datasize > MAX_LZW_BITS) {
+    return Transition::TerminateFailure();
+  }
   const int clearCode = ClearCode();
-  if (mGIFStruct.datasize > MAX_LZW_BITS || clearCode >= MAX_BITS) {
+  if (clearCode >= MAX_BITS) {
     return Transition::TerminateFailure();
   }
 
   mGIFStruct.avail = clearCode + 2;
   mGIFStruct.oldcode = -1;
   mGIFStruct.codesize = mGIFStruct.datasize + 1;
   mGIFStruct.codemask = (1 << mGIFStruct.codesize) - 1;
   mGIFStruct.datum = mGIFStruct.bits = 0;
--- a/image/decoders/nsGIFDecoder2.h
+++ b/image/decoders/nsGIFDecoder2.h
@@ -66,17 +66,20 @@ private:
   template <typename PixelSize> NextPixel<PixelSize>
   YieldPixel(const uint8_t* aData, size_t aLength, size_t* aBytesReadOut);
 
   /// Checks if we have transparency, either because the header indicates that
   /// there's alpha, or because the frame rect doesn't cover the entire image.
   bool CheckForTransparency(const gfx::IntRect& aFrameRect);
 
   // @return the clear code used for LZW decompression.
-  int ClearCode() const { return 1 << mGIFStruct.datasize; }
+  int ClearCode() const {
+    MOZ_ASSERT(mGIFStruct.datasize <= MAX_LZW_BITS);
+    return 1 << mGIFStruct.datasize;
+  }
 
   enum class State
   {
     FAILURE,
     SUCCESS,
     GIF_HEADER,
     SCREEN_DESCRIPTOR,
     GLOBAL_COLOR_TABLE,
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..5dd10b8f25a2d055cc9d6cfe38faf1a26ed88e6d
GIT binary patch
literal 7866
zc%1E+Wl$Sh+peK_aQBkn5TL=OSb{^K!GabK9wc}RE$&`|Td)Gfz1S}96t_Z)J1tP7
zrMvyQ_xs7bGv~)S`{$W&{e13q&$?%xYu2-7Y3XRn$=ieRz<5V^;&^y?`1tsD?%W|D
zARr_pBqAarCMG5!At5CtB_ksP0089V<P;PXl$4ZIR8-W|)HF0Sw6wHzbaeFe^b8CP
zjEsy-Oiawo%q%P{tgNhTY;5f8>>L~%oSd9@@80F&;sOGJAP|U~o12G+hnJU^kB^U^
zpI<;gKu}OnNJvOnSQrcji-?Gbii(PfiQT(*4+4RRi;GK0NJvUbN=ZpcOH0eh$jHjd
z%E`&e%gZY$DBQn)Ur|v}Nl8grSy@FzMO9T53WdU8Ff}zbb#-+O4Gm3AO)V`gZEbBG
z9UWa=T|GTLI2^98uWw*r@ZiA%1Oj1bXlP_)WNd6~Vq#)yYKlZ6&CJZq&CM+=EG#W8
zt*or9t*swEd}w21V{2<`XJ=<`Z|~sX;OOY+<m7}xp`4waU0hsTU0vPW+}z#WJv=--
zJw4HAw3nBcx3{;CkB_gfF9w70^Yiof_YVjN2n-Ai3JMAi4h{(kdGzSf<HwIfLqo&D
z!k#>N^7QG`@bK`6h=|C@$f&5O=;-K}n3&ku*tod3`1tsQgoMPz#H6I8<mBX(l$6xe
z)U>p;^z`(MjEv08%xBM@Wo2byvDobF?3|pO+}zx}yuAGU{DOjl!otF$qN3vB;*ye*
z($Z2K4p&xIR$g9SQBhG@Sy@$8_5Ats>gwv6nwr|$+7~Zg)YaA1*Vi{RG&D9gHZ?Uh
zH#fJmw6wOiwzajjx3_n6baZxhc6D{VeEG7wySt~Sr?<DaudlDazyFUv{&@B3)xf~O
z;NalU(9rPk@W{x>=;-L!*x2~^_{7A-<mBYk)YSC!^vul6?Ck98*RSX1=H}<;7Zw&4
z7Z;b7mX?>7S5{V5S6A28*4Ee8H#Rojym_;^xw*Bq_4e)CckkY9Z*TAH?CkFD?(OaE
z@9!TR92_1V9vvMWA0MBboSdGXo}HbYpPye`T)cn({=<h4mzS4US6A29*B?KA{PgM5
z=g*(NeEIVA>(`r`n{VH~egFRb_V)J2j~{>j`RC7{KY#uD1^Pv9pkZRH21RH{h(QSO
z4+-!<-w4U@@qXcn;QhV8c;Tc!@P3hTXg8G(M3K@9OS!`1hvM4ZMGNE8jZ!&aV(v?V
z8D(0@)N0O~!Oi7kQQXF{ym>?W6HniA2-B8TRL$gZTXa{*#U9R-$ojb_+n-l3mB_R&
znbhvP&c*R28Tfa%xtUg)KZS8_c-S{qm^C}2-2D#bVq{0$EvB;3#&yb_hw-#LptX+R
zkCtKG;-hTQ_E)L%66PN^S}<p9y>9}O_r}t$WK!;5J0x=?Ew_aAI>V1<Q~8Vo<V>z!
ziATskwi()xbn0}X?`hju6F+;?1!Y!F?vmJw7|mX>>2prKlJDZ_5q-1j?=v%;!KL!#
z{->R_3Q;}AJ4)SGO1FzItm2Yd+h`)BmN&%uiGLJ--Of0(v5~y`_VmP~Rk=TI?(u28
z4$>Cox0UnOD!P7@D-=&yi^+gz9%UEQDJn-2yn7*I5f;WOxM^9)IK~xT+WtAq`>RqM
z(7q(WmE&=}P^X!LIvE288c5g4l`IaBvvVUP$}UY^##VzI!VF;uusvnfhD(Dy*_-h7
znfA3fc~}*neG^Ed6iXyt$(m#JKARESkI%pF3``7kuq9o_tR{vOt+N-Bfnv(-+qPJD
z!a}M7OiQQ%C{~R}i4zZvY_j77%24<k%WxV8{}nxn6N`6M&TbXMdIYp(bkRlb`;^s0
zHBQx<EJiqY8UbL&7ZlZpuI_Yk%F5^$^}S_mH2+S?UzaJ#zf)p8-h>;9qv6pl)P7K)
zk@V?U-&6a6xrnYZES7iwWJ@z9nG||Ot6nh<e9Xdk-y)r^04V2o=zl^0C~%WH5eGy@
z3ucyU1YB?4@pq6A)XdOTs+HQOl-b|~fQ1<Wbd9!^?-|Gh&eVJn88C~Uz$vpP6W_#M
zLt<{8c0|Yi%nP#*8;$A*mZ-hCMZ-obI<QTloXA49pO831;;`u6FiOmf_<qN8otUoF
zFQ(R2Z70)-zlZ}vqA~`9qTh<i%*4)|j6AKGjrsVkRHhN#nbn|Q*mW}e@|h)NB-p;L
zv2}_jPHijLZ6xjJtq&H$V6|}DzSD#==>HP%hcD<Iu;R)teS5GnO~Cf;mylPH-kX>9
zE8CCzuVzTb?h+zhY~6ilMz~<VuB16a2;bXphdkmtj(S4gP4dp?j;<gs<ZC6-dJHR@
zKa1P-yvue(N@b_@Q=*sL?9M_+f#R_0gY0*dS#2(J$oP3dTi?T->@Cb7FE15`Jx;L1
zf2?xU;>qKi;5olJvJkeI;}aQX5II?tIjUl0jL%0bwoO9~$I-EhlJ6$Uv15*$NS8xZ
zYw$aIo@gIEq2{A!^m*4O?cyRU6|_?N$N;+(&nyhckkQl#Ft41PVVu&O=t2pZnI@Qw
zRtf0uB^Xr0P6^ogloq6D#2T^&=!&?TcM|0q*mzSR5@n~lB7FzK=S{;*9_LN?`2R1+
zG?$Geu?P`+j9le(CX@AHGbGgGbU1bLBSct4Cem{t5ArMgDR~v;A%3HZdAuy6&N`6*
z&eQ7y9adrR3Y#!rLROV|^n3LaKZkA!gI3M04XI-jRt9$Yu*Awb3lXEaOc8gZ*erj#
z_Tmwv!}G-k&4BUh?=;}`7StVb<umC<iYDrU03vH*eaErXvs%$j8Mh(i(-URQA^8@I
zUcS%#A=*NIE>akypzI$@9&bQC?8MTyaskCl7&#I#aC?0+k}B@UmWV*w)n=+nj~96_
z?vgiL{!M>MXpqTdT!CaECuci)xwyEoN3k}{9=Mp|YxZty<1#&sQYhu(iDl>Yfy5+l
zzus-L-NdsCUIICqZ_DqV2I$C`xGGT4&fkNgG*_ch?V5Qup&3jdOTViXMl1dkfehKz
zEo^o|srU`M#x?~l4#CA#wR?{#B5FiW{iQiWltOZ3hOFyx#WOg@DcDfdkSrvVLAqWF
z0m<4Q05YY_9q(h!oof!VtpiUEu>YW6lJ1*bv^HJ##jxwa(RsTXsAb`extmk+b637!
z;*TAF4+1Q>=!We1)x(-B%|g-u4E<4Q5X+7zK!ITrfs^+A4t4iM8Vj1YQl)fbXnPZ<
zjT9ove)p?hJ!M<Obbisi)n_I(rgkNczLvJUlGiFQ`Q0C=W+v>8+iq>M)1Unoy=&ff
z-O5hMJFLDmwxWse#xoX!lbN2Yn@#$_Bz9f;lVo2!*<<lHVO2)zNDT(T-Br5eTc1p0
zFFosWji;_!^V(gS8^g3hlh!*<cT+P~O{sioKTdZCl^C$ElTF9_zi9b_^86w4b^J-c
z=5R;nhj+&%AT4L`)fRBrcPEmn4+Gcu0>cktLR#(Y4?&o&Fj!=R?}6GQW}%xUW0~cH
zD2`x0QX*qF#)BwY8#F@-m!*j-jy~#=Zt?zFq0<g~5~SP)F16yimm+sqy_c%^<p!bp
zPr5MvdkUw_Ax`qjT{3&q2nP6A2Ql%fInP!?vc`mTr?T$__~Wk{KFH)X3@3hgVx&b^
z%oe0!(cLz+P$FX6A)j~UlJnx>q;*)gQCx~0D-^%avZ`+7g}UuVsk`9=h8Fa0hdjGf
zEhU1b$R_2!i-C2$+QSW+XkSm(ex4(*i`sJiozA#hez7-1wPs_?Z+d4osy@7v(7P}g
zJZ8GKZ%w*@4GDU9B9~lQsVBM`QV?}Xi&W6Wc`HN}9LF?LC%%TLR*#$7KfZNd$|*!N
z(65giq)Uh!y1$$4>-qYDe0wN~>p_3-xA*@HQFB8srLa4nBN*gq_Ej?Y!5xdMsl|$E
z%fS&FgaBk)_V*6-SycmfA8PjJ+WO+5ZaUDcjZmC^pM(z)<4L9`WLN~zmBuXDaUW`=
z03S9&CVYq0Da7I3ro2ILU5ZX<?y#$4oL(}I$`fFSFQEpd3*++DWUYp7L9=z^@LcWJ
z7;B-i(Bg&by>X*Hhke%?TAtCgv3m{GErKL7X+Z4_!i?Q&#3GkdUT^yKAXQ)D8zxZ)
zj7BOeFTCxXtc+-aTGVk1(D=o0SK@w#rB<RkgFd@xU@iwOefg-(&h2BFniN6L`A_;q
z3sLzN<MYMSS{}VLtu7BL-08^4=-RYqxpa$4Np!=r-~!r)=%vmv?r^1wG{vWF5z#Ep
zm&kb5KtxLdPX@xs4is|^iswW_ZqgOrkn(8Iyr~IPH-wj7k<c5JLUq_(;|E6WN@uam
zpvea+lE9HafTLU(2rVHq95|o>+5qj4rf2~N$~j8odD0YBxe1?%HmqetamH}O<_E5U
ze1~Zxfxa48^e`|^^wW|K7HV7DqD`SU({-2+y@^$)2?XL8V&LOAgQ6L}PkbUtrTkj#
zMke3ZUCgv2qTQT_OS4!bIfjmlh{D{agpBqtdFk@xlcim2^%D#Un5A8DM10F_PS0U?
z*LT4pXcKMg7am?%0yf)apeB{&kBG(U-UYwp##52KcvjbO+zBm)$PjER{o~SEHlSGD
zsO?ia4~^0Vha(BwrKP}V?+0H{ER($Z)$0a|kfj6F>-g4WNcXGVL~sWM#gfd$_@cpm
z0c=nDFx%CXVS0s4-PI^Z(D~IEFizxpoPvn(A7DD%)mSF)b)qon@in7B#{FnxKyUTE
zO;64xzx&=YF(6B2=nElPrqgr@k2$~ePDJ%mvC306${v#Dhcz<n23^}ek~&0Gpl+!e
zA7Z^287tYfCg=gHx?f$jXZWC_TDrWB4DU{b4w_z&@o<|{0UywtN;M;D{CJ;&QN7&L
z=U5`qIG$42+OygM>JbAx%*WhswIAZR8^~`@nc+B>K*=E&jP#J#>W;rf)W~H<t7XDK
zo`v5ebu^A<{i;pgo?4d47n_)5QPC1+i0gx_Uuo9|1;=oNbH%a`fk>$tZ#`&=!snwG
zOX#7gKI4X464Z{3TrCTPvf3eCI-aU0Wo0_-3xR9fOcacl;pAdFZF_TqLo7p6kSUfZ
zasdVzqj9#BCJZ5C%zk<lz%0dgI|3j^NG&!hQobwkx^0bHO00IA44eaB&}M$zG)R7r
zWb`>gPO*$TNu+L^ZU;gM8`_lwvpG^^4xJ04oXIYDSh&%bbK1-@`{9$oz-iosWDI;z
zS9Iz;*iN+N+?-sXJ^C4q;@t5;q<@YS?I4+~E>VoQmi8*4*fZXNp}RV-Adc(;J}`Yf
zlFFe;mQzDtGVr6=balGN`~!M4AayfckW96mmQ{WeW|Zu<(#O#NPFxuUs1&mv)Dz9?
z#;dKWTk{!gjAtl=(FFRBCWz=a<r^q8G4Y<UBvML@3l{!-6bS%vh>sURqD#rV%-3*i
zg#wp|sg@Z!-ZR$30leQYx>r7TNEDrVNc;-9B}hqjFm`IS!gipk7Wl}9W;V!tQWq@`
zCmLx&uOZ)X>^g{(kchcnYmw$O5!MW#t7SEXS~!~VsUd}Rg_f%rAI)K=BN}zll*^`R
zB_76e5n=Q&V<g~Vbvr$YR-v65J$n}r$mm$NtVtxsa81H^c;5P2X}zWg&Rz+`L_AeF
zz*D0tT!(NP3BSVAAXRL`-=+PtIa(TajEt3}5U6xr(B{dvHi{2f_$f{*mUB)k;_c#^
z1mG4EFZir_q4<+p_BEoFB6>*iV}&@sC_&1>W?OlR%waUa%<{=`?>x+`@%{I+rZKVG
z^R`v59*uuA27YK6Y)E>4{kg@Xm1*6Ru@CEzOvrT7j{7P@bTWt2#09oR9#g<bR-XaW
zD%|iNdAiVurj1L7^50R7p)$}y-%({$P1mQyTPh_oC9kiwV83y@Nj$~Mnw-Fiwg+EV
zn^}MrPrsX<71Tj(ghf0)XE2Etthl><O+zB_%!KhSb)~iWMifc!g%UHqqPGOCu2e@)
zK}<)I&J<!rEOz>|O7Gveb!OKxb(ua)dO`uj3_WfP4sB@bAV91&vszW6ALC>dypOGM
z-zzdL(u*H*Fe!Hjo<w)GD6dzr9DjU#Tih;1xs`hp5S`V|WVBgW8xQts{cd4UeDQ4b
z5q(E_V;2m!;yI5T=dmCoVdA6;*(0G=lv<q?_s#|3xVqHilcfA}n-iqybZ<2Ibd{E7
zb=a}N8L|r%f-|~8kxQwGx&cdNs)7xIJoaDPa!X_t=awSK%Uz+*$X_dR-_d`v=@^>^
z4fh{OYn+>pAT9X8qfaTVqn0kaCp|YH2t_QbrknQ78&H}C_)IHxr??TDrkSs2k-zm^
zHzC5#aqH*0ooFtzTO&;ez@B%u`3o`brbns~ftM6op_T`*yfIax4W5|00M){`aLb`G
zDVgP0jQ$KnNP@V&9aic&i@fziL2s|g3@>Oji+g@!w8en^USIP{W_-p+_c~vI2e$qf
z;YK)Xnj(D_`Cc<1oHYhvI$oiuEh$oVu^BWHkfN+R+xo;Em&??AU7AZe<_SJinsRG)
zH0IofrOMi`sB&>0y=8t=`u@9prY&~*te9M4Su+lI28umwp;p;_p9byrA!><0ejX1?
z#aHDsfx>I~Eh&3(Rzyvs$ONwvx@arA2qm>C{<h$c*)s*b+{=R0#4GFk<-vXw)9kbG
z>I7|p`cDgR*^5t$ME_`d{4d@AU()^bf9d|4?lG!DS^sZ84;-~Ji+VH8VUz!&`&%%+
zWh?OmaL6>?2_bKy1-EM3E9jkkv;a`MZB6=9M{Htll|$rJ84L>m+B~e@wqIeOYpu25
zDs|6IuH|`PqM=_YL1NnEWHB=Lo9-9S>%#w{8_UG2-Ma$I{F-Kg6iyvRT<J2>h>e7j
z-gDBGrfp64xY~Ab&aK@Y3E))Au7hyZzxF^(Sm`m+ZPwPSsZ`OuwC{HcRot`eAwKq4
zORk@7=%XnTd{D+=I*MX)I+BlzN~+RVus>4oWgtKoH%eAi-IlUbH>Rey=#M1i8e8m*
zqmd?)L#_Ht=H9T7E5;<Zk^GBuWSbKshk2P?G?j4ZWk#{$dT``KR5fG|D7hUUNp^2r
z@upOuOYn2Lq5ztASK~O`ky{R&N1CZ9AiSKBcn2H5n-qOeUKVzI30-9KBmBsj_I6r>
zUih0`3l9(|Kj<h?Ha9$_vb}9cFGq+YuwnKfBp@|?cw>$gxZXBgW?SEXW|fnR&>+v!
zpNTNQBGAOM*=`4#SOFxGPgBC#D55Ig)BW?IYDmKlrIx>?^jOZiYNd0@Q=?{ng`{0^
z*JS;Gop?cwh~*LcV*gPsq+Ky9JU<hY#SR>~>!9E)VU_615?ow|;&nLBO+3wiX}Nr=
z5)v3eCi>P>o+P;3C_)Ep(%vG-wS5ezR{SJy^bi-<;#gOdE=WvP8!D(-)mC#@&cQ1u
z(@rdTUfRlc_bOpmG_2`DM@*RiTZ~?}$(0~Iy6k2>(IGWnsBWMweX2aoPwv{I*mNFN
z;&^tozyM6jOh7Uh?=vyhn(Sm2R1$76ncKaE43SG7_byA^o6u&Yh>GwX)q@;6`ANhI
zf0W;Stx6*LX-=IP?GOED&k?iNMLi(|X9;z2X^u(}H`@6Otj%v4Em|=aLt5{1W^Cui
zX>YMJTeHQoPidzDGjTnZHFo?&tD@LNlRvs&>SB{N>r95nm5NRQmTL9pMe;E#S;A62
z`&F}(fzmG)t!Jx#em~6;5O>&`qyy)z2sL-uh1mRQiox}~FrOe3DFCy-?AQ5|*qOZj
z5;m!W+W~_^P8Wv*gy;j!7f&`?T7zLvPMK<5r^t?=e#9xc?>wJCzswxGY~P-wxZUMU
zW`FU%W;i`EP>DrmaLA;-UDPINZM~+Q?~iuMc98P>TQe7nJvg?d-E(}v>+=SpV+MD#
zDQ~5zaukYrUn+Wbn5rD+q7IEt^J8a}n^(LWl9j0i966fT;S?97iF_|&j#H(hlX|TO
zIk+=xEB^ACz9=N5odRAH@yX0|ZrVss_E*<4y?8d^qe+qNAG=v#F69FX<(G=mN%wyp
zkMBtspy+vwUWQA}DQefpl%zTu<|RrZ05!Q8+rYfUOfAEM{b)lvi!|&XgeO^&bD%2T
z92;Tz2kH7NxryMFmyVU-(1!KZd&Yl~x@2;k+~^rPx!3H86bl`}Ed(3_4vQYrDV*Q}
zyIUv_CPE~x!c*pZS<=v-WdfDHKR<FJW1CR&PB;_8Z_G%W{w!V5=XZ6ERXS*m(_ic_
zwSr7H+v6F763Y~rbk-?8zreKb@6wsfZ3=NBq3-!;nJE4PkoZfQsACli<>fk$&Ok}?
zbhX5TM9CzidqZjfow|Wd$V<O_@*hi=y=C_yL<XTDN-LCdq`On^`iW)EFNbKfM6QMz
z*ctwh|Mgn`7vD%}K(#~;otBD;XM)DH))Ot2Q#laF$wHmhs+j^gzthbLKL=Gj(9aJh
zu5NxnEgemuvzsRh7-a7UwD<Evp&dL?PQV~Hf7ib?HE%CJe@uX5sGGMJ&=}<pbjEn2
z6#xLJr=u$h9Rk#M^KuIE#(4Mvb-WzK00^-MVnCR8Fi;u-0l-iwe{U}l-~%szdyJbm
z01nXtibEj)HK+kp9V!L@{GGtj8;wSJ`2!t1y&XM%AMEJ~^z!xx+WYvR>@h$$ufOB{
z-iATh`~ObX@K-W>AO_{)=I4*X{H_F|Fn)if^LGBX#Qy)87!UM|{C8dLfq|EUxESOP
zAs!U~?+zXT-hV9s3<`&fi~Zh%M@9ZyA^LBH{BH&NFX=B6$-kQ<{>Mc2yB7XGCW(KU
H@b3QyvgPp>
--- a/image/test/crashtests/crashtests.list
+++ b/image/test/crashtests/crashtests.list
@@ -23,16 +23,17 @@ load 1235605.gif
 load 1241728-1.html
 load 1241729-1.html
 load 1242093-1.html
 load 1242778-1.png
 load 1249576-1.png
 load 1253362-1.html
 load 1355898-1.html
 load 1375842-1.html
+load 1413762-1.gif
 load colormap-range.gif
 HTTP load delayedframe.sjs # A 3-frame animated GIF with an inordinate delay between the second and third frame
 
 # Animated gifs with a very large canvas, but tiny actual content.
 load delaytest.html?523528-1.gif
 load delaytest.html?523528-2.gif
 
 # Bug 1160801 - Ensure that we handle invalid disposal types.
--- a/js/src/builtin/RegExp.cpp
+++ b/js/src/builtin/RegExp.cpp
@@ -171,28 +171,48 @@ js::ExecuteRegExpLegacy(JSContext* cx, R
         rval.setBoolean(true);
         return true;
     }
 
     return CreateRegExpMatchResult(cx, input, matches, rval);
 }
 
 static bool
-CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
+CheckPatternSyntaxSlow(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
 {
     CompileOptions options(cx);
     frontend::TokenStream dummyTokenStream(cx, options, nullptr, 0, nullptr);
     return irregexp::ParsePatternSyntax(dummyTokenStream, cx->tempLifoAlloc(), pattern,
                                         flags & UnicodeFlag);
 }
 
-enum RegExpSharedUse {
-    UseRegExpShared,
-    DontUseRegExpShared
-};
+static RegExpShared*
+CheckPatternSyntax(JSContext* cx, HandleAtom pattern, RegExpFlag flags)
+{
+    // If we already have a RegExpShared for this pattern/flags, we can
+    // avoid the much slower CheckPatternSyntaxSlow call.
+
+    if (RegExpShared* shared = cx->zone()->regExps.maybeGet(pattern, flags)) {
+#ifdef DEBUG
+        // Assert the pattern is valid.
+        if (!CheckPatternSyntaxSlow(cx, pattern, flags)) {
+            MOZ_ASSERT(cx->isThrowingOutOfMemory() || cx->isThrowingOverRecursed());
+            return nullptr;
+        }
+#endif
+        return shared;
+    }
+
+    if (!CheckPatternSyntaxSlow(cx, pattern, flags))
+        return nullptr;
+
+    // Allocate and return a new RegExpShared so we will hit the fast path
+    // next time.
+    return cx->zone()->regExps.get(cx, pattern, flags);
+}
 
 /*
  * ES 2016 draft Mar 25, 2016 21.2.3.2.2.
  *
  * Steps 14-15 set |obj|'s "lastIndex" property to zero.  Some of
  * RegExpInitialize's callers have a fresh RegExp not yet exposed to script:
  * in these cases zeroing "lastIndex" is infallible.  But others have a RegExp
  * whose "lastIndex" property might have been made non-writable: here, zeroing
@@ -201,18 +221,17 @@ enum RegExpSharedUse {
  *
  * CALLERS MUST HANDLE "lastIndex" ZEROING THEMSELVES!
  *
  * Because this function only ever returns a user-provided |obj| in the spec,
  * we omit it and just return the usual success/failure.
  */
 static bool
 RegExpInitializeIgnoringLastIndex(JSContext* cx, Handle<RegExpObject*> obj,
-                                  HandleValue patternValue, HandleValue flagsValue,
-                                  RegExpSharedUse sharedUse = DontUseRegExpShared)
+                                  HandleValue patternValue, HandleValue flagsValue)
 {
     RootedAtom pattern(cx);
     if (patternValue.isUndefined()) {
         /* Step 1. */
         pattern = cx->names().empty;
     } else {
         /* Step 2. */
         pattern = ToAtom<CanGC>(cx, patternValue);
@@ -228,50 +247,41 @@ RegExpInitializeIgnoringLastIndex(JSCont
         if (!flagStr)
             return false;
 
         /* Step 5. */
         if (!ParseRegExpFlags(cx, flagStr, &flags))
             return false;
     }
 
-    if (sharedUse == UseRegExpShared) {
-        /* Steps 7-8. */
-        RegExpShared* re = cx->zone()->regExps.get(cx, pattern, flags);
-        if (!re)
-            return false;
-
-        /* Steps 9-12. */
-        obj->initIgnoringLastIndex(pattern, flags);
+    /* Steps 7-8. */
+    RegExpShared* shared = CheckPatternSyntax(cx, pattern, flags);
+    if (!shared)
+        return false;
 
-        obj->setShared(*re);
-    } else {
-        /* Steps 7-8. */
-        if (!CheckPatternSyntax(cx, pattern, flags))
-            return false;
+    /* Steps 9-12. */
+    obj->initIgnoringLastIndex(pattern, flags);
 
-        /* Steps 9-12. */
-        obj->initIgnoringLastIndex(pattern, flags);
-    }
+    obj->setShared(*shared);
 
     return true;
 }
 
 /* ES 2016 draft Mar 25, 2016 21.2.3.2.3. */
 bool
 js::RegExpCreate(JSContext* cx, HandleValue patternValue, HandleValue flagsValue,
                  MutableHandleValue rval)
 {
     /* Step 1. */
     Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject));
     if (!regexp)
          return false;
 
     /* Step 2. */
-    if (!RegExpInitializeIgnoringLastIndex(cx, regexp, patternValue, flagsValue, UseRegExpShared))
+    if (!RegExpInitializeIgnoringLastIndex(cx, regexp, patternValue, flagsValue))
         return false;
     regexp->zeroLastIndex(cx);
 
     rval.setObject(*regexp);
     return true;
 }
 
 MOZ_ALWAYS_INLINE bool
@@ -423,32 +433,36 @@ js::regexp_construct(JSContext* cx, unsi
     RootedValue patternValue(cx, args.get(0));
 
     // Step 4.
     ESClass cls;
     if (!GetClassOfValue(cx, patternValue, &cls))
         return false;
     if (cls == ESClass::RegExp) {
         // Beware!  |patternObj| might be a proxy into another compartment, so
-        // don't assume |patternObj.is<RegExpObject>()|.  For the same reason,
-        // don't reuse the RegExpShared below.
+        // don't assume |patternObj.is<RegExpObject>()|.
         RootedObject patternObj(cx, &patternValue.toObject());
 
         RootedAtom sourceAtom(cx);
         RegExpFlag flags;
+        RootedRegExpShared shared(cx);
         {
             // Step 4.a.
-            RegExpShared* shared = RegExpToShared(cx, patternObj);
+            shared = RegExpToShared(cx, patternObj);
             if (!shared)
                 return false;
             sourceAtom = shared->getSource();
 
             // Step 4.b.
             // Get original flags in all cases, to compare with passed flags.
             flags = shared->getFlags();
+
+            // If the RegExpShared is in another Zone, don't reuse it.
+            if (cx->zone() != shared->zone())
+                shared = nullptr;
         }
 
         // Step 7.
         RootedObject proto(cx);
         if (!GetPrototypeFromBuiltinConstructor(cx, args, &proto))
             return false;
 
         Rooted<RegExpObject*> regexp(cx, RegExpAlloc(cx, GenericObject, proto));
@@ -460,29 +474,37 @@ js::regexp_construct(JSContext* cx, unsi
             // Step 4.c / 21.2.3.2.2 RegExpInitialize step 4.
             RegExpFlag flagsArg = RegExpFlag(0);
             RootedString flagStr(cx, ToString<CanGC>(cx, args[1]));
             if (!flagStr)
                 return false;
             if (!ParseRegExpFlags(cx, flagStr, &flagsArg))
                 return false;
 
+            // Don't reuse the RegExpShared if we have different flags.
+            if (flags != flagsArg)
+                shared = nullptr;
+
             if (!(flags & UnicodeFlag) && flagsArg & UnicodeFlag) {
                 // Have to check syntax again when adding 'u' flag.
 
                 // ES 2017 draft rev 9b49a888e9dfe2667008a01b2754c3662059ae56
                 // 21.2.3.2.2 step 7.
-                if (!CheckPatternSyntax(cx, sourceAtom, flagsArg))
+                shared = CheckPatternSyntax(cx, sourceAtom, flagsArg);
+                if (!shared)
                     return false;
             }
             flags = flagsArg;
         }
 
         regexp->initAndZeroLastIndex(sourceAtom, flags, cx);
 
+        if (shared)
+            regexp->setShared(*shared);
+
         args.rval().setObject(*regexp);
         return true;
     }
 
     RootedValue P(cx);
     RootedValue F(cx);
 
     // Step 5.
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -336,32 +336,35 @@ EvalSharedContext::EvalSharedContext(JSC
   : SharedContext(cx, Kind::Eval, directives, extraWarnings),
     enclosingScope_(cx, enclosingScope),
     bindings(cx)
 {
     computeAllowSyntax(enclosingScope);
     computeInWith(enclosingScope);
     computeThisBinding(enclosingScope);
 
-    // Like all things Debugger, Debugger.Frame.eval needs special
-    // handling. Since the environment chain of such evals are non-syntactic
-    // (DebuggerEnvironmentProxy is not an EnvironmentObject), computing the
-    // this binding with respect to enclosingScope is incorrect if the
-    // Debugger.Frame is a function frame. Recompute the this binding if we
-    // are such an eval.
+    // If this eval is in response to Debugger.Frame.eval, we may have been
+    // passed an incomplete scope chain. In order to better determine the 'this'
+    // binding type, we traverse the environment chain, looking for a CallObject
+    // and recompute the binding type based on its body scope.
+    //
+    // NOTE: A non-debug eval in a non-syntactic environment will also trigger
+    // this code. In that case, we should still compute the same binding type.
     if (enclosingEnv && enclosingScope->hasOnChain(ScopeKind::NonSyntactic)) {
-        // For Debugger.Frame.eval with bindings, the environment chain may
-        // have more than the DebugEnvironmentProxy.
         JSObject* env = enclosingEnv;
         while (env) {
+            // Look at target of any DebugEnvironmentProxy, but be sure to use
+            // enclosingEnvironment() of the proxy itself.
+            JSObject* unwrapped = env;
             if (env->is<DebugEnvironmentProxy>())
-                env = &env->as<DebugEnvironmentProxy>().environment();
-
-            if (env->is<CallObject>()) {
-                computeThisBinding(env->as<CallObject>().callee().nonLazyScript()->bodyScope());
+                unwrapped = &env->as<DebugEnvironmentProxy>().environment();
+
+            if (unwrapped->is<CallObject>()) {
+                JSFunction* callee = &unwrapped->as<CallObject>().callee();
+                computeThisBinding(callee->nonLazyScript()->bodyScope());
                 break;
             }
 
             env = env->enclosingEnvironment();
         }
     }
 }
 
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -1063,11 +1063,16 @@ struct DeletePolicy<js::FunctionScope::D
   : public js::GCManagedDeletePolicy<js::FunctionScope::Data>
 { };
 
 template <>
 struct DeletePolicy<js::ModuleScope::Data>
   : public js::GCManagedDeletePolicy<js::ModuleScope::Data>
 { };
 
+template <>
+struct DeletePolicy<js::WasmInstanceScope::Data>
+  : public js::GCManagedDeletePolicy<js::WasmInstanceScope::Data>
+{ };
+
 } // namespace JS
 
 #endif // gc_Zone_h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1397049.js
@@ -0,0 +1,40 @@
+// Run debugger in its own global
+let g = newGlobal();
+g.target = this;
+g.evaluate(`
+    let d = new Debugger;
+    let gw = d.addDebuggee(target);
+
+    d.onDebuggerStatement = function(frame)
+    {
+        frame = frame.older;
+
+        let res = frame.eval("this");
+        assertEq(res.return, frame.this);
+
+        res = frame.evalWithBindings("this", {x:42});
+        assertEq(res.return, frame.this);
+    }
+`);
+
+// Debugger statement affects parse so hide in another function
+function brk() { debugger; }
+
+function f1() {
+    var temp = "string";
+    brk();
+}
+
+function f2() {
+    let temp = "string";
+    brk();
+}
+
+function f3() {
+    const temp = "string";
+    brk();
+}
+
+f1.call({});
+f2.call({});
+f3.call({});
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/regexp/bug1419785.js
@@ -0,0 +1,3 @@
+// |jit-test| error:character class
+Object.defineProperty(RegExp.prototype, Symbol.search, {get: () => { throw "wrong"; }});
+"abc".search("[[");
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -3222,16 +3222,20 @@ MacroAssembler::emitPreBarrierFastPath(J
     shlq_cl(temp1);
 #elif JS_CODEGEN_X86
     MOZ_ASSERT(temp3 == ecx);
     shll_cl(temp1);
 #elif JS_CODEGEN_ARM
     ma_lsl(temp3, temp1, temp1);
 #elif JS_CODEGEN_ARM64
     Lsl(ARMRegister(temp1, 64), ARMRegister(temp1, 64), ARMRegister(temp3, 64));
+#elif JS_CODEGEN_MIPS32
+    ma_sll(temp1, temp1, temp3);
+#elif JS_CODEGEN_MIPS64
+    ma_dsll(temp1, temp1, temp3);
 #elif JS_CODEGEN_NONE
     MOZ_CRASH();
 #else
 # error "Unknown architecture"
 #endif
 
     // No barrier is needed if the bit is set, |word & mask != 0|.
     branchTestPtr(Assembler::NonZero, temp2, temp1, noBarrier);
--- a/js/src/vm/EnvironmentObject.h
+++ b/js/src/vm/EnvironmentObject.h
@@ -903,16 +903,19 @@ class DebugEnvironmentProxy : public Pro
      * frame that has been popped.
      */
     static const unsigned SNAPSHOT_SLOT = 1;
 
   public:
     static DebugEnvironmentProxy* create(JSContext* cx, EnvironmentObject& env,
                                          HandleObject enclosing);
 
+    // NOTE: The environment may be a debug hollow with invalid
+    // enclosingEnvironment. Always use the enclosingEnvironment accessor on
+    // the DebugEnvironmentProxy in order to walk the environment chain.
     EnvironmentObject& environment() const;
     JSObject& enclosingEnvironment() const;
 
     /* May only be called for proxies to function call objects. */
     ArrayObject* maybeSnapshot() const;
     void initSnapshot(ArrayObject& snapshot);
 
     // Currently, the 'declarative' environments are function, module, and
--- a/js/src/vm/RegExpShared.h
+++ b/js/src/vm/RegExpShared.h
@@ -269,16 +269,21 @@ class RegExpZone
     ~RegExpZone() {
         MOZ_ASSERT_IF(set_.initialized(), set_.empty());
     }
 
     bool init();
 
     bool empty() const { return set_.empty(); }
 
+    RegExpShared* maybeGet(JSAtom* source, RegExpFlag flags) const {
+        Set::Ptr p = set_.lookup(Key(source, flags));
+        return p ? *p : nullptr;
+    }
+
     RegExpShared* get(JSContext* cx, HandleAtom source, RegExpFlag flags);
 
     /* Like 'get', but compile 'maybeOpt' (if non-null). */
     RegExpShared* get(JSContext* cx, HandleAtom source, JSString* maybeOpt);
 
 #ifdef DEBUG
     void clear() { set_.clear(); }
 #endif
--- a/layout/reftests/css-invalid/select/reftest.list
+++ b/layout/reftests/css-invalid/select/reftest.list
@@ -3,10 +3,10 @@ fuzzy-if(skiaContent,1,3) needs-focus ==
 fuzzy-if(skiaContent,2,6) needs-focus == select-disabled.html select-disabled-ref.html
 fuzzy-if(skiaContent,2,6) needs-focus == select-dyn-disabled.html select-disabled-ref.html
 fuzzy-if(skiaContent,1,3) needs-focus == select-dyn-not-disabled.html select-ref.html
 needs-focus == select-required-invalid.html select-required-ref.html
 needs-focus == select-required-valid.html select-required-ref.html
 needs-focus == select-required-multiple-still-valid.html select-required-multiple-ref.html
 fuzzy-if(skiaContent,1,250) needs-focus == select-required-multiple-valid.html select-required-multiple-ref.html
 fuzzy-if(skiaContent&&!Android,1,3) skip-if(Android) needs-focus == select-disabled-fieldset-1.html select-fieldset-ref.html
-fuzzy-if(skiaContent&&!Android,2,3) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html
+fuzzy-if(skiaContent&&!Android,2,3) skip-if(Android) needs-focus == select-disabled-fieldset-2.html select-fieldset-ref.html
 fuzzy-if(skiaContent,2,5) needs-focus == select-fieldset-legend.html select-fieldset-legend-ref.html
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1843,16 +1843,17 @@ Loader::DoSheetComplete(SheetLoadData* a
   }
 
   NS_RELEASE(aLoadData);  // this will release parents and siblings and all that
 }
 
 nsresult
 Loader::LoadInlineStyle(nsIContent* aElement,
                         const nsAString& aBuffer,
+                        nsIPrincipal* aTriggeringPrincipal,
                         uint32_t aLineNumber,
                         const nsAString& aTitle,
                         const nsAString& aMedia,
                         ReferrerPolicy aReferrerPolicy,
                         Element* aScopeElement,
                         nsICSSLoaderObserver* aObserver,
                         bool* aCompleted,
                         bool* aIsAlternate)
@@ -1895,22 +1896,32 @@ Loader::LoadInlineStyle(nsIContent* aEle
     ShadowRoot* containingShadow = aElement->GetContainingShadow();
     MOZ_ASSERT(containingShadow);
     containingShadow->InsertSheet(sheet, aElement);
   } else {
     rv = InsertSheetInDoc(sheet, aElement, mDocument);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  nsIPrincipal* principal = aElement->NodePrincipal();
+  if (aTriggeringPrincipal) {
+    // The triggering principal may be an expanded principal, which is safe to
+    // use for URL security checks, but not as the loader principal for a
+    // stylesheet. So treat this as principal inheritance, and downgrade if
+    // necessary.
+    principal = BasePrincipal::Cast(aTriggeringPrincipal)->PrincipalToInherit();
+  }
+
   SheetLoadData* data = new SheetLoadData(this, aTitle, nullptr, sheet,
                                           owningElement, *aIsAlternate,
-                                          aObserver, nullptr, static_cast<nsINode*>(aElement));
+                                          aObserver, nullptr,
+                                          static_cast<nsINode*>(aElement));
 
   // We never actually load this, so just set its principal directly
-  sheet->SetPrincipal(aElement->NodePrincipal());
+  sheet->SetPrincipal(principal);
 
   NS_ADDREF(data);
   data->mLineNumber = aLineNumber;
   // Parse completion releases the load data
   rv = ParseSheet(aBuffer, Span<const uint8_t>(), data, *aCompleted);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // If aCompleted is true, |data| may well be deleted by now.
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -222,28 +222,32 @@ public:
    * asynchronously once the sheet is marked complete.  If an error is
    * returned, or if *aCompleted is true, aObserver will not be notified.  In
    * addition to parsing the sheet, this method will insert it into the
    * stylesheet list of this CSSLoader's document.
    *
    * @param aElement the element linking to the stylesheet.  This must not be
    *                 null and must implement nsIStyleSheetLinkingElement.
    * @param aBuffer the stylesheet data
+   * @param aTriggeringPrincipal The principal of the scripted caller that
+   *                             initiated the load, if available. Otherwise
+   *                             null.
    * @param aLineNumber the line number at which the stylesheet data started.
    * @param aTitle the title of the sheet.
    * @param aMedia the media string for the sheet.
    * @param aReferrerPolicy the referrer policy for loading the sheet.
    * @param aObserver the observer to notify when the load completes.
    *        May be null.
    * @param [out] aCompleted whether parsing of the sheet completed.
    * @param [out] aIsAlternate whether the stylesheet ended up being an
    *        alternate sheet.
    */
   nsresult LoadInlineStyle(nsIContent* aElement,
                            const nsAString& aBuffer,
+                           nsIPrincipal* aTriggeringPrincipal,
                            uint32_t aLineNumber,
                            const nsAString& aTitle,
                            const nsAString& aMedia,
                            ReferrerPolicy aReferrerPolicy,
                            mozilla::dom::Element* aScopeElement,
                            nsICSSLoaderObserver* aObserver,
                            bool* aCompleted,
                            bool* aIsAlternate);
--- a/layout/style/ServoKeyframeRule.cpp
+++ b/layout/style/ServoKeyframeRule.cpp
@@ -51,23 +51,25 @@ public:
         mDecls->SetOwningRule(nullptr);
         mDecls = aDecls->AsServo();
         mDecls->SetOwningRule(mRule);
         Servo_Keyframe_SetStyle(mRule->Raw(), mDecls->Raw());
       }
     });
     return NS_OK;
   }
-  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) final
+  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                nsIPrincipal* aSubjectPrincipal) final
   {
     MOZ_ASSERT_UNREACHABLE("GetCSSParsingEnvironment "
                            "shouldn't be calling for a Servo rule");
     GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
   }
-  ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final
+  ServoCSSParsingEnvironment GetServoCSSParsingEnvironment(
+      nsIPrincipal* aSubjectPrincipal) const final
   {
     return GetServoCSSParsingEnvironmentForRule(mRule);
   }
   nsIDocument* DocToUpdate() final { return nullptr; }
 
   nsINode* GetParentObject() final
   {
     return mRule ? mRule->GetDocument() : nullptr;
--- a/layout/style/ServoPageRule.cpp
+++ b/layout/style/ServoPageRule.cpp
@@ -84,25 +84,27 @@ ServoPageRuleDeclaration::SetCSSDeclarat
 nsIDocument*
 ServoPageRuleDeclaration::DocToUpdate()
 {
   return nullptr;
 }
 
 void
 ServoPageRuleDeclaration::GetCSSParsingEnvironment(
-  CSSParsingEnvironment& aCSSParseEnv)
+  CSSParsingEnvironment& aCSSParseEnv,
+  nsIPrincipal* aSubjectPrincipal)
 {
   MOZ_ASSERT_UNREACHABLE("GetCSSParsingEnvironment "
                          "shouldn't be calling for a Servo rule");
   GetCSSParsingEnvironmentForRule(Rule(), aCSSParseEnv);
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-ServoPageRuleDeclaration::GetServoCSSParsingEnvironment() const
+ServoPageRuleDeclaration::GetServoCSSParsingEnvironment(
+  nsIPrincipal* aSubjectPrincipal) const
 {
   return GetServoCSSParsingEnvironmentForRule(Rule());
 }
 
 // -- ServoPageRule --------------------------------------------------
 
 ServoPageRule::ServoPageRule(RefPtr<RawServoPageRule> aRawRule,
                              uint32_t aLine, uint32_t aColumn)
--- a/layout/style/ServoPageRule.h
+++ b/layout/style/ServoPageRule.h
@@ -26,18 +26,20 @@ public:
 
   NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParent) final;
   nsINode* GetParentObject() final;
 
 protected:
   DeclarationBlock* GetCSSDeclaration(Operation aOperation) final;
   nsresult SetCSSDeclaration(DeclarationBlock* aDecl) final;
   nsIDocument* DocToUpdate() final;
-  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) final;
-  nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                nsIPrincipal* aSubjectPrincipal) final;
+  nsDOMCSSDeclaration::ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
 
 private:
   // For accessing the constructor.
   friend class ServoPageRule;
 
   explicit ServoPageRuleDeclaration(
     already_AddRefed<RawServoDeclarationBlock> aDecls);
   ~ServoPageRuleDeclaration();
--- a/layout/style/ServoStyleRule.cpp
+++ b/layout/style/ServoStyleRule.cpp
@@ -90,25 +90,27 @@ ServoStyleRuleDeclaration::SetCSSDeclara
 nsIDocument*
 ServoStyleRuleDeclaration::DocToUpdate()
 {
   return nullptr;
 }
 
 void
 ServoStyleRuleDeclaration::GetCSSParsingEnvironment(
-  CSSParsingEnvironment& aCSSParseEnv)
+  CSSParsingEnvironment& aCSSParseEnv,
+  nsIPrincipal* aSubjectPrincipal)
 {
   MOZ_ASSERT_UNREACHABLE("GetCSSParsingEnvironment "
                          "shouldn't be calling for a Servo rule");
   GetCSSParsingEnvironmentForRule(Rule(), aCSSParseEnv);
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-ServoStyleRuleDeclaration::GetServoCSSParsingEnvironment() const
+ServoStyleRuleDeclaration::GetServoCSSParsingEnvironment(
+  nsIPrincipal* aSubjectPrincipal) const
 {
   return GetServoCSSParsingEnvironmentForRule(Rule());
 }
 
 // -- ServoStyleRule --------------------------------------------------
 
 ServoStyleRule::ServoStyleRule(already_AddRefed<RawServoStyleRule> aRawRule,
                                uint32_t aLine, uint32_t aColumn)
--- a/layout/style/ServoStyleRule.h
+++ b/layout/style/ServoStyleRule.h
@@ -30,18 +30,20 @@ public:
 
   NS_IMETHOD GetParentRule(nsIDOMCSSRule** aParent) final;
   nsINode* GetParentObject() final;
 
 protected:
   DeclarationBlock* GetCSSDeclaration(Operation aOperation) final;
   nsresult SetCSSDeclaration(DeclarationBlock* aDecl) final;
   nsIDocument* DocToUpdate() final;
-  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) final;
-  ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                nsIPrincipal* aSubjectPrincipal) final;
+  ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
 
 private:
   // For accessing the constructor.
   friend class ServoStyleRule;
 
   explicit ServoStyleRuleDeclaration(
     already_AddRefed<RawServoDeclarationBlock> aDecls);
   ~ServoStyleRuleDeclaration();
--- a/layout/style/StyleRule.cpp
+++ b/layout/style/StyleRule.cpp
@@ -1061,18 +1061,20 @@ protected:
   friend class mozilla::DefaultDelete<DOMCSSDeclarationImpl>;
 
 public:
   explicit DOMCSSDeclarationImpl(css::StyleRule *aRule);
 
   NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) override;
   virtual DeclarationBlock* GetCSSDeclaration(Operation aOperation) override;
   virtual nsresult SetCSSDeclaration(DeclarationBlock* aDecl) override;
-  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override;
-  nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                        nsIPrincipal* aSubjectPrincipal) override;
+  nsDOMCSSDeclaration::ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
   virtual nsIDocument* DocToUpdate() override;
 
   // Override |AddRef| and |Release| for being owned by StyleRule.  Also, we
   // need to forward QI for cycle collection things to StyleRule.
   NS_DECL_ISUPPORTS_INHERITED
 
   virtual nsINode *GetParentObject() override
   {
@@ -1116,23 +1118,25 @@ DOMCSSDeclarationImpl::GetCSSDeclaration
     if (sheet) {
       sheet->WillDirty();
     }
   }
   return mRule->GetDeclaration();
 }
 
 void
-DOMCSSDeclarationImpl::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
+DOMCSSDeclarationImpl::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                                nsIPrincipal* aSubjectPrincipal)
 {
   GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-DOMCSSDeclarationImpl::GetServoCSSParsingEnvironment() const
+DOMCSSDeclarationImpl::GetServoCSSParsingEnvironment(
+  nsIPrincipal* aSubjectPrincipal) const
 {
   MOZ_CRASH("GetURLData shouldn't be calling on a Gecko rule");
 }
 
 NS_IMETHODIMP
 DOMCSSDeclarationImpl::GetParentRule(nsIDOMCSSRule **aParent)
 {
   NS_ENSURE_ARG_POINTER(aParent);
--- a/layout/style/nsCSSRules.cpp
+++ b/layout/style/nsCSSRules.cpp
@@ -885,17 +885,18 @@ nsCSSFontFaceStyleDecl::GetCssTextImpl(n
       aCssText.AppendLiteral(": ");
       aCssText.Append(descStr);
       aCssText.AppendLiteral(";\n");
     }
   }
 }
 
 NS_IMETHODIMP
-nsCSSFontFaceStyleDecl::SetCssText(const nsAString & aCssText)
+nsCSSFontFaceStyleDecl::SetCssText(const nsAString& aCssText,
+                                   nsIPrincipal* aSubjectPrincipal)
 {
   return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
 }
 
 NS_IMETHODIMP
 nsCSSFontFaceStyleDecl::GetPropertyValue(const nsAString & propertyName,
                                          nsAString & aResult)
 {
@@ -935,19 +936,20 @@ nsCSSFontFaceStyleDecl::GetPropertyPrior
                                             nsAString & aResult)
 {
   // font descriptors do not have priorities at present
   aResult.Truncate();
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsCSSFontFaceStyleDecl::SetProperty(const nsAString & propertyName,
-                                    const nsAString & value,
-                                    const nsAString & priority)
+nsCSSFontFaceStyleDecl::SetProperty(const nsAString& propertyName,
+                                    const nsAString& value,
+                                    const nsAString& priority,
+                                    nsIPrincipal* aSubjectPrincipal)
 {
   // FIXME(heycam): If we are changing unicode-range, then a FontFace object
   // representing this rule must have its mUnicodeRange value invalidated.
 
   return NS_ERROR_NOT_IMPLEMENTED; // bug 443978
 }
 
 NS_IMETHODIMP
@@ -1007,20 +1009,21 @@ nsCSSFontFaceStyleDecl::GetPropertyValue
 {
   return
     GetPropertyValue(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
                      aValue);
 }
 
 NS_IMETHODIMP
 nsCSSFontFaceStyleDecl::SetPropertyValue(const nsCSSPropertyID aPropID,
-                                         const nsAString& aValue)
+                                         const nsAString& aValue,
+                                         nsIPrincipal* aSubjectPrincipal)
 {
   return SetProperty(NS_ConvertUTF8toUTF16(nsCSSProps::GetStringValue(aPropID)),
-                     aValue, EmptyString());
+                     aValue, EmptyString(), aSubjectPrincipal);
 }
 
 nsINode*
 nsCSSFontFaceStyleDecl::GetParentObject()
 {
   return ContainingRule()->GetDocument();
 }
 
@@ -1413,23 +1416,25 @@ nsCSSKeyframeStyleDeclaration::GetCSSDec
   if (mRule) {
     return mRule->Declaration();
   } else {
     return nullptr;
   }
 }
 
 void
-nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
+nsCSSKeyframeStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                                        nsIPrincipal* aSubjectPrincipal)
 {
   GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-nsCSSKeyframeStyleDeclaration::GetServoCSSParsingEnvironment() const
+nsCSSKeyframeStyleDeclaration::GetServoCSSParsingEnvironment(
+  nsIPrincipal* aSubjectPrincipal) const
 {
   MOZ_CRASH("GetURLData shouldn't be calling on a Gecko rule");
 }
 
 NS_IMETHODIMP
 nsCSSKeyframeStyleDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
 {
   NS_ENSURE_ARG_POINTER(aParent);
@@ -1859,23 +1864,25 @@ nsCSSPageStyleDeclaration::GetCSSDeclara
   if (mRule) {
     return mRule->Declaration();
   } else {
     return nullptr;
   }
 }
 
 void
-nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
+nsCSSPageStyleDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                                    nsIPrincipal* aSubjectPrincipal)
 {
   GetCSSParsingEnvironmentForRule(mRule, aCSSParseEnv);
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-nsCSSPageStyleDeclaration::GetServoCSSParsingEnvironment() const
+nsCSSPageStyleDeclaration::GetServoCSSParsingEnvironment(
+  nsIPrincipal* aSubjectPrincipal) const
 {
   MOZ_CRASH("GetURLData shouldn't be calling on a Gecko rule");
 }
 
 NS_IMETHODIMP
 nsCSSPageStyleDeclaration::GetParentRule(nsIDOMCSSRule** aParent)
 {
   NS_ENSURE_ARG_POINTER(aParent);
--- a/layout/style/nsCSSRules.h
+++ b/layout/style/nsCSSRules.h
@@ -213,18 +213,20 @@ class nsCSSKeyframeStyleDeclaration fina
 {
 public:
   explicit nsCSSKeyframeStyleDeclaration(nsCSSKeyframeRule *aRule);
 
   NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) override;
   void DropReference() { mRule = nullptr; }
   virtual mozilla::DeclarationBlock* GetCSSDeclaration(Operation aOperation) override;
   virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock* aDecl) override;
-  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override;
-  nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                        nsIPrincipal* aSubjectPrincipal) override;
+  nsDOMCSSDeclaration::ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
   virtual nsIDocument* DocToUpdate() override;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsCSSKeyframeStyleDeclaration,
                                                          nsICSSDeclaration)
 
   virtual nsINode* GetParentObject() override;
 
@@ -336,18 +338,20 @@ class nsCSSPageStyleDeclaration final : 
 {
 public:
   explicit nsCSSPageStyleDeclaration(nsCSSPageRule *aRule);
 
   NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) override;
   void DropReference() { mRule = nullptr; }
   virtual mozilla::DeclarationBlock* GetCSSDeclaration(Operation aOperation) override;
   virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock* aDecl) override;
-  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override;
-  nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                        nsIPrincipal* aSubjectPrincipal) override;
+  nsDOMCSSDeclaration::ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
   virtual nsIDocument* DocToUpdate() override;
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsCSSPageStyleDeclaration,
                                                          nsICSSDeclaration)
 
   virtual nsINode *GetParentObject() override;
 
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -414,31 +414,33 @@ nsComputedDOMStyle::GetPropertyValue(con
   // this.
   return GetPropertyValue(
     NS_ConvertASCIItoUTF16(nsCSSProps::GetStringValue(aPropID)),
     aValue);
 }
 
 NS_IMETHODIMP
 nsComputedDOMStyle::SetPropertyValue(const nsCSSPropertyID aPropID,
-                                     const nsAString& aValue)
+                                     const nsAString& aValue,
+                                     nsIPrincipal* aSubjectPrincipal)
 {
   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
 }
 
 NS_IMETHODIMP
 nsComputedDOMStyle::GetCssText(nsAString& aCssText)
 {
   aCssText.Truncate();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsComputedDOMStyle::SetCssText(const nsAString& aCssText)
+nsComputedDOMStyle::SetCssText(const nsAString& aCssText,
+                               nsIPrincipal* aSubjectPrincipal)
 {
   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
 }
 
 NS_IMETHODIMP
 nsComputedDOMStyle::GetLength(uint32_t* aLength)
 {
   NS_PRECONDITION(aLength, "Null aLength!  Prepare to die!");
@@ -863,23 +865,25 @@ nsComputedDOMStyle::SetCSSDeclaration(De
 
 nsIDocument*
 nsComputedDOMStyle::DocToUpdate()
 {
   MOZ_CRASH("called nsComputedDOMStyle::DocToUpdate");
 }
 
 void
-nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
+nsComputedDOMStyle::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                             nsIPrincipal* aSubjectPrincipal)
 {
   MOZ_CRASH("called nsComputedDOMStyle::GetCSSParsingEnvironment");
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-nsComputedDOMStyle::GetServoCSSParsingEnvironment() const
+nsComputedDOMStyle::GetServoCSSParsingEnvironment(
+  nsIPrincipal* aSubjectPrincipal) const
 {
   MOZ_CRASH("called nsComputedDOMStyle::GetServoCSSParsingEnvironment");
 }
 
 void
 nsComputedDOMStyle::ClearStyleContext()
 {
   if (mResolvedStyleContext) {
@@ -1203,17 +1207,18 @@ nsComputedDOMStyle::GetPropertyPriority(
   aReturn.Truncate();
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsComputedDOMStyle::SetProperty(const nsAString& aPropertyName,
                                 const nsAString& aValue,
-                                const nsAString& aPriority)
+                                const nsAString& aPriority,
+                                nsIPrincipal* aSubjectPrincipal)
 {
   return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
 }
 
 NS_IMETHODIMP
 nsComputedDOMStyle::Item(uint32_t aIndex, nsAString& aReturn)
 {
   return nsDOMCSSDeclaration::Item(aIndex, aReturn);
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -133,18 +133,20 @@ public:
   }
 
   // nsDOMCSSDeclaration abstract methods which should never be called
   // on a nsComputedDOMStyle object, but must be defined to avoid
   // compile errors.
   virtual mozilla::DeclarationBlock* GetCSSDeclaration(Operation) override;
   virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock*) override;
   virtual nsIDocument* DocToUpdate() override;
-  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override;
-  nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                        nsIPrincipal* aSubjectPrincipal) override;
+  nsDOMCSSDeclaration::ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
 
   static already_AddRefed<nsROCSSPrimitiveValue>
     MatrixToCSSValue(const mozilla::gfx::Matrix4x4& aMatrix);
 
   static void RegisterPrefChangeCallbacks();
   static void UnregisterPrefChangeCallbacks();
 
   // nsIMutationObserver
--- a/layout/style/nsDOMCSSAttrDeclaration.cpp
+++ b/layout/style/nsDOMCSSAttrDeclaration.cpp
@@ -159,32 +159,35 @@ nsDOMCSSAttributeDeclaration::GetCSSDecl
   if (NS_FAILED(rv)) {
     return nullptr; // the decl will be destroyed along with the style rule
   }
 
   return decl;
 }
 
 void
-nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv)
+nsDOMCSSAttributeDeclaration::GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                                       nsIPrincipal* aSubjectPrincipal)
 {
   NS_ASSERTION(mElement, "Something is severely broken -- there should be an Element here!");
 
   nsIDocument* doc = mElement->OwnerDoc();
   aCSSParseEnv.mSheetURI = doc->GetDocumentURI();
   aCSSParseEnv.mBaseURI = mElement->GetBaseURIForStyleAttr();
-  aCSSParseEnv.mPrincipal = mElement->NodePrincipal();
+  aCSSParseEnv.mPrincipal = (aSubjectPrincipal ? aSubjectPrincipal
+                                               : mElement->NodePrincipal());
   aCSSParseEnv.mCSSLoader = doc->CSSLoader();
 }
 
 nsDOMCSSDeclaration::ServoCSSParsingEnvironment
-nsDOMCSSAttributeDeclaration::GetServoCSSParsingEnvironment() const
+nsDOMCSSAttributeDeclaration::GetServoCSSParsingEnvironment(
+    nsIPrincipal* aSubjectPrincipal) const
 {
   return {
-    mElement->GetURLDataForStyleAttr(),
+    mElement->GetURLDataForStyleAttr(aSubjectPrincipal),
     mElement->OwnerDoc()->GetCompatibilityMode(),
     mElement->OwnerDoc()->CSSLoader(),
   };
 }
 
 NS_IMETHODIMP
 nsDOMCSSAttributeDeclaration::GetParentRule(nsIDOMCSSRule **aParent)
 {
@@ -197,17 +200,18 @@ nsDOMCSSAttributeDeclaration::GetParentR
 /* virtual */ nsINode*
 nsDOMCSSAttributeDeclaration::GetParentObject()
 {
   return mElement;
 }
 
 NS_IMETHODIMP
 nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
-                                               const nsAString& aValue)
+                                               const nsAString& aValue,
+                                               nsIPrincipal* aSubjectPrincipal)
 {
   // Scripted modifications to style.opacity or style.transform
   // could immediately force us into the animated state if heuristics suggest
   // this is scripted animation.
   // FIXME: This is missing the margin shorthand and the logical versions of
   // the margin properties, see bug 1266287.
   if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform ||
       aPropID == eCSSProperty_left || aPropID == eCSSProperty_top ||
@@ -215,10 +219,10 @@ nsDOMCSSAttributeDeclaration::SetPropert
       aPropID == eCSSProperty_background_position_x ||
       aPropID == eCSSProperty_background_position_y ||
       aPropID == eCSSProperty_background_position) {
     nsIFrame* frame = mElement->GetPrimaryFrame();
     if (frame) {
       ActiveLayerTracker::NotifyInlineStyleRuleModified(frame, aPropID, aValue, this);
     }
   }
-  return nsDOMCSSDeclaration::SetPropertyValue(aPropID, aValue);
+  return nsDOMCSSDeclaration::SetPropertyValue(aPropID, aValue, aSubjectPrincipal);
 }
--- a/layout/style/nsDOMCSSAttrDeclaration.h
+++ b/layout/style/nsDOMCSSAttrDeclaration.h
@@ -27,24 +27,27 @@ public:
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS_AMBIGUOUS(nsDOMCSSAttributeDeclaration,
                                                                    nsICSSDeclaration)
 
   // If GetCSSDeclaration returns non-null, then the decl it returns
   // is owned by our current style rule.
   virtual mozilla::DeclarationBlock* GetCSSDeclaration(Operation aOperation) override;
-  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) override;
-  nsDOMCSSDeclaration::ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const final;
+  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                        nsIPrincipal* aSubjectPrincipal) override;
+  nsDOMCSSDeclaration::ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal) const final;
   NS_IMETHOD GetParentRule(nsIDOMCSSRule **aParent) override;
 
   virtual nsINode* GetParentObject() override;
 
   NS_IMETHOD SetPropertyValue(const nsCSSPropertyID aPropID,
-                              const nsAString& aValue) override;
+                              const nsAString& aValue,
+                              nsIPrincipal* aSubjectPrincipal) override;
 
 protected:
   ~nsDOMCSSAttributeDeclaration();
 
   virtual nsresult SetCSSDeclaration(mozilla::DeclarationBlock* aDecl) override;
   virtual nsIDocument* DocToUpdate() override;
 
   RefPtr<Element> mElement;
--- a/layout/style/nsDOMCSSDeclaration.cpp
+++ b/layout/style/nsDOMCSSDeclaration.cpp
@@ -49,17 +49,18 @@ nsDOMCSSDeclaration::GetPropertyValue(co
   if (DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read)) {
     decl->GetPropertyValueByID(aPropID, aValue);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMCSSDeclaration::SetPropertyValue(const nsCSSPropertyID aPropID,
-                                      const nsAString& aValue)
+                                      const nsAString& aValue,
+                                      nsIPrincipal* aSubjectPrincipal)
 {
   switch (aPropID) {
     case eCSSProperty_background_position:
     case eCSSProperty_background_position_x:
     case eCSSProperty_background_position_y:
     case eCSSProperty_transform:
     case eCSSProperty_top:
     case eCSSProperty_left:
@@ -81,17 +82,17 @@ nsDOMCSSDeclaration::SetPropertyValue(co
   }
 
   if (aValue.IsEmpty()) {
     // If the new value of the property is an empty string we remove the
     // property.
     return RemovePropertyInternal(aPropID);
   }
 
-  return ParsePropertyValue(aPropID, aValue, false);
+  return ParsePropertyValue(aPropID, aValue, false, aSubjectPrincipal);
 }
 
 
 NS_IMETHODIMP
 nsDOMCSSDeclaration::GetCssText(nsAString& aCssText)
 {
   DeclarationBlock* decl = GetCSSDeclaration(eOperation_Read);
   aCssText.Truncate();
@@ -99,17 +100,18 @@ nsDOMCSSDeclaration::GetCssText(nsAStrin
   if (decl) {
     decl->ToString(aCssText);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-nsDOMCSSDeclaration::SetCssText(const nsAString& aCssText)
+nsDOMCSSDeclaration::SetCssText(const nsAString& aCssText,
+                                nsIPrincipal* aSubjectPrincipal)
 {
   // We don't need to *do* anything with the old declaration, but we need
   // to ensure that it exists, or else SetCSSDeclaration may crash.
   DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
   if (!olddecl) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
@@ -117,26 +119,27 @@ nsDOMCSSDeclaration::SetCssText(const ns
   // Attribute setting code, which leads in turn to BeginUpdate.  We
   // need to start the update now so that the old rule doesn't get used
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
 
   RefPtr<DeclarationBlock> newdecl;
   if (olddecl->IsServo()) {
-    ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment();
+    ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment(
+        aSubjectPrincipal);
     if (!servoEnv.mUrlExtraData) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     newdecl = ServoDeclarationBlock::FromCssText(aCssText, servoEnv.mUrlExtraData,
                                                  servoEnv.mCompatMode, servoEnv.mLoader);
   } else {
     CSSParsingEnvironment geckoEnv;
-    GetCSSParsingEnvironment(geckoEnv);
+    GetCSSParsingEnvironment(geckoEnv, aSubjectPrincipal);
     if (!geckoEnv.mPrincipal) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     RefPtr<css::Declaration> decl(new css::Declaration());
     decl->InitializeEmpty();
     nsCSSParser cssParser(geckoEnv.mCSSLoader);
     bool changed;
@@ -204,17 +207,18 @@ nsDOMCSSDeclaration::GetPropertyPriority
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMCSSDeclaration::SetProperty(const nsAString& aPropertyName,
                                  const nsAString& aValue,
-                                 const nsAString& aPriority)
+                                 const nsAString& aPriority,
+                                 nsIPrincipal* aSubjectPrincipal)
 {
   if (aValue.IsEmpty()) {
     // If the new value of the property is an empty string we remove the
     // property.
     // XXX this ignores the priority string, should it?
     return RemovePropertyInternal(aPropertyName);
   }
 
@@ -231,19 +235,20 @@ nsDOMCSSDeclaration::SetProperty(const n
   } else if (aPriority.EqualsLiteral("important")) {
     important = true;
   } else {
     // XXX silent failure?
     return NS_OK;
   }
 
   if (propID == eCSSPropertyExtra_variable) {
-    return ParseCustomPropertyValue(aPropertyName, aValue, important);
+    return ParseCustomPropertyValue(aPropertyName, aValue, important,
+                                    aSubjectPrincipal);
   }
-  return ParsePropertyValue(propID, aValue, important);
+  return ParsePropertyValue(propID, aValue, important, aSubjectPrincipal);
 }
 
 NS_IMETHODIMP
 nsDOMCSSDeclaration::RemoveProperty(const nsAString& aPropertyName,
                                     nsAString& aReturn)
 {
   nsresult rv = GetPropertyValue(aPropertyName, aReturn);
   NS_ENSURE_SUCCESS(rv, rv);
@@ -287,17 +292,18 @@ nsDOMCSSDeclaration::GetServoCSSParsingE
     sheet->AsServo()->URLData(),
     eCompatibility_FullStandards,
     nullptr,
   };
 }
 
 template<typename GeckoFunc, typename ServoFunc>
 nsresult
-nsDOMCSSDeclaration::ModifyDeclaration(GeckoFunc aGeckoFunc,
+nsDOMCSSDeclaration::ModifyDeclaration(nsIPrincipal* aSubjectPrincipal,
+                                       GeckoFunc aGeckoFunc,
                                        ServoFunc aServoFunc)
 {
   DeclarationBlock* olddecl = GetCSSDeclaration(eOperation_Modify);
   if (!olddecl) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   // For nsDOMCSSAttributeDeclaration, SetCSSDeclaration will lead to
@@ -306,24 +312,25 @@ nsDOMCSSDeclaration::ModifyDeclaration(G
   // between when we mutate the declaration and when we set the new
   // rule (see stack in bug 209575).
   mozAutoDocConditionalContentUpdateBatch autoUpdate(DocToUpdate(), true);
   RefPtr<DeclarationBlock> decl = olddecl->EnsureMutable();
 
   bool changed;
   if (decl->IsGecko()) {
     CSSParsingEnvironment geckoEnv;
-    GetCSSParsingEnvironment(geckoEnv);
+    GetCSSParsingEnvironment(geckoEnv, aSubjectPrincipal);
     if (!geckoEnv.mPrincipal) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     aGeckoFunc(decl->AsGecko(), geckoEnv, &changed);
   } else {
-    ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment();
+    ServoCSSParsingEnvironment servoEnv = GetServoCSSParsingEnvironment(
+        aSubjectPrincipal);
     if (!servoEnv.mUrlExtraData) {
       return NS_ERROR_NOT_AVAILABLE;
     }
 
     changed = aServoFunc(decl->AsServo(), servoEnv);
   }
   if (!changed) {
     // Parsing failed -- but we don't throw an exception for that.
@@ -331,19 +338,21 @@ nsDOMCSSDeclaration::ModifyDeclaration(G
   }
 
   return SetCSSDeclaration(decl);
 }
 
 nsresult
 nsDOMCSSDeclaration::ParsePropertyValue(const nsCSSPropertyID aPropID,
                                         const nsAString& aPropValue,
-                                        bool aIsImportant)
+                                        bool aIsImportant,
+                                        nsIPrincipal* aSubjectPrincipal)
 {
   return ModifyDeclaration(
+    aSubjectPrincipal,
     [&](css::Declaration* decl, CSSParsingEnvironment& env, bool* changed) {
       nsCSSParser cssParser(env.mCSSLoader);
       cssParser.ParseProperty(aPropID, aPropValue,
                               env.mSheetURI, env.mBaseURI, env.mPrincipal,
                               decl, changed, aIsImportant);
     },
     [&](ServoDeclarationBlock* decl, ServoCSSParsingEnvironment& env) {
       NS_ConvertUTF16toUTF8 value(aPropValue);
@@ -351,20 +360,22 @@ nsDOMCSSDeclaration::ParsePropertyValue(
         decl->Raw(), aPropID, &value, aIsImportant, env.mUrlExtraData,
         ParsingMode::Default, env.mCompatMode, env.mLoader);
     });
 }
 
 nsresult
 nsDOMCSSDeclaration::ParseCustomPropertyValue(const nsAString& aPropertyName,
                                               const nsAString& aPropValue,
-                                              bool aIsImportant)
+                                              bool aIsImportant,
+                                              nsIPrincipal* aSubjectPrincipal)
 {
   MOZ_ASSERT(nsCSSProps::IsCustomPropertyName(aPropertyName));
   return ModifyDeclaration(
+    aSubjectPrincipal,
     [&](css::Declaration* decl, CSSParsingEnvironment& env, bool* changed) {
       nsCSSParser cssParser(env.mCSSLoader);
       auto propName = Substring(aPropertyName, CSS_CUSTOM_NAME_PREFIX_LENGTH);
       cssParser.ParseVariable(propName, aPropValue, env.mSheetURI,
                               env.mBaseURI, env.mPrincipal, decl,
                               changed, aIsImportant);
     },
     [&](ServoDeclarationBlock* decl, ServoCSSParsingEnvironment& env) {
--- a/layout/style/nsDOMCSSDeclaration.h
+++ b/layout/style/nsDOMCSSDeclaration.h
@@ -44,46 +44,51 @@ public:
   NS_IMETHOD_(MozExternalRefCountType) Release() override = 0;
 
   NS_DECL_NSICSSDECLARATION
   using nsICSSDeclaration::GetLength;
 
   // Require subclasses to implement |GetParentRule|.
   //NS_DECL_NSIDOMCSSSTYLEDECLARATION
   NS_IMETHOD GetCssText(nsAString & aCssText) override;
-  NS_IMETHOD SetCssText(const nsAString & aCssText) override;
+  NS_IMETHOD SetCssText(const nsAString & aCssText,
+                        nsIPrincipal* aSubjectPrincipal) override;
   NS_IMETHOD GetPropertyValue(const nsAString & propertyName,
                               nsAString & _retval) override;
   virtual already_AddRefed<mozilla::dom::CSSValue>
     GetPropertyCSSValue(const nsAString & propertyName,
                         mozilla::ErrorResult& aRv) override;
   using nsICSSDeclaration::GetPropertyCSSValue;
   NS_IMETHOD RemoveProperty(const nsAString & propertyName,
                             nsAString & _retval) override;
   NS_IMETHOD GetPropertyPriority(const nsAString & propertyName,
                                  nsAString & _retval) override;
-  NS_IMETHOD SetProperty(const nsAString & propertyName,
-                         const nsAString & value, const nsAString & priority) override;
+  NS_IMETHOD SetProperty(const nsAString& propertyName,
+                         const nsAString& value,
+                         const nsAString& priority,
+                         nsIPrincipal* aSubjectPrincipal) override;
   NS_IMETHOD GetLength(uint32_t *aLength) override;
   NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) override = 0;
 
   // WebIDL interface for CSS2Properties
 #define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) publicname_
 #define CSS_PROP(name_, id_, method_, flags_, pref_, parsevariant_,          \
                  kwtable_, stylestruct_, stylestructoffset_, animtype_)      \
   void                                                                       \
-  Get##method_(nsAString& aValue, mozilla::ErrorResult& rv)                  \
+  Get##method_(nsAString& aValue, nsIPrincipal& aSubjectPrincipal,           \
+               mozilla::ErrorResult& rv)                                     \
   {                                                                          \
     rv = GetPropertyValue(eCSSProperty_##id_, aValue);                       \
   }                                                                          \
                                                                              \
   void                                                                       \
-  Set##method_(const nsAString& aValue, mozilla::ErrorResult& rv)            \
+  Set##method_(const nsAString& aValue, nsIPrincipal& aSubjectPrincipal,     \
+               mozilla::ErrorResult& rv)                                     \
   {                                                                          \
-    rv = SetPropertyValue(eCSSProperty_##id_, aValue);                       \
+    rv = SetPropertyValue(eCSSProperty_##id_, aValue, &aSubjectPrincipal);   \
   }
 
 #define CSS_PROP_LIST_EXCLUDE_INTERNAL
 #define CSS_PROP_LIST_INCLUDE_LOGICAL
 #define CSS_PROP_SHORTHAND(name_, id_, method_, flags_, pref_)  \
   CSS_PROP(name_, id_, method_, flags_, pref_, X, X, X, X, X)
 #include "nsCSSPropList.h"
 
@@ -147,61 +152,78 @@ protected:
     mozilla::css::Loader* MOZ_UNSAFE_REF("user of CSSParsingEnviroment must hold an owning "
                                          "reference; reference counting here has unacceptable "
                                          "performance overhead (see bug 649163)") mCSSLoader;
   };
 
   // Information neded to parse a declaration for Servo side.
   struct MOZ_STACK_CLASS ServoCSSParsingEnvironment
   {
-    mozilla::URLExtraData* mUrlExtraData;
+    RefPtr<mozilla::URLExtraData> mUrlExtraData;
     nsCompatibility mCompatMode;
     mozilla::css::Loader* mLoader;
 
     ServoCSSParsingEnvironment(mozilla::URLExtraData* aUrlData,
                                nsCompatibility aCompatMode,
                                mozilla::css::Loader* aLoader)
       : mUrlExtraData(aUrlData)
       , mCompatMode(aCompatMode)
       , mLoader(aLoader)
     {}
+
+    ServoCSSParsingEnvironment(already_AddRefed<mozilla::URLExtraData> aUrlData,
+                               nsCompatibility aCompatMode,
+                               mozilla::css::Loader* aLoader)
+      : mUrlExtraData(aUrlData)
+      , mCompatMode(aCompatMode)
+      , mLoader(aLoader)
+    {}
   };
 
   // On failure, mPrincipal should be set to null in aCSSParseEnv.
   // If mPrincipal is null, the other members may not be set to
   // anything meaningful.
-  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv) = 0;
+  // If aSubjectPrincipal is passed, it should be the subject principal of the
+  // scripted caller that initiated the parser.
+  virtual void GetCSSParsingEnvironment(CSSParsingEnvironment& aCSSParseEnv,
+                                        nsIPrincipal* aSubjectPrincipal = nullptr) = 0;
 
   // mUrlExtraData returns URL data for parsing url values in
   // CSS. Returns nullptr on failure. If mUrlExtraData is nullptr,
   // mCompatMode may not be set to anything meaningful.
-  virtual ServoCSSParsingEnvironment GetServoCSSParsingEnvironment() const = 0;
+  // If aSubjectPrincipal is passed, it should be the subject principal of the
+  // scripted caller that initiated the parser.
+  virtual ServoCSSParsingEnvironment
+  GetServoCSSParsingEnvironment(nsIPrincipal* aSubjectPrincipal = nullptr) const = 0;
 
   // An implementation for GetCSSParsingEnvironment for callers wrapping
   // an css::Rule.
   static void GetCSSParsingEnvironmentForRule(mozilla::css::Rule* aRule,
                                               CSSParsingEnvironment& aCSSParseEnv);
 
   // An implementation for GetServoCSSParsingEnvironment for callers wrapping
   // an css::Rule.
   static ServoCSSParsingEnvironment
     GetServoCSSParsingEnvironmentForRule(const mozilla::css::Rule* aRule);
 
   nsresult ParsePropertyValue(const nsCSSPropertyID aPropID,
                               const nsAString& aPropValue,
-                              bool aIsImportant);
+                              bool aIsImportant,
+                              nsIPrincipal* aSubjectPrincipal);
 
   nsresult ParseCustomPropertyValue(const nsAString& aPropertyName,
                                     const nsAString& aPropValue,
-                                    bool aIsImportant);
+                                    bool aIsImportant,
+                                    nsIPrincipal* aSubjectPrincipal);
 
   nsresult RemovePropertyInternal(nsCSSPropertyID aPropID);
   nsresult RemovePropertyInternal(const nsAString& aProperty);
 
 protected:
   virtual ~nsDOMCSSDeclaration();
 
 private:
   template<typename GeckoFunc, typename ServoFunc>
-  inline nsresult ModifyDeclaration(GeckoFunc aGeckoFunc, ServoFunc aServoFunc);
+  inline nsresult ModifyDeclaration(nsIPrincipal* aSubjectPrincipal,
+                                    GeckoFunc aGeckoFunc, ServoFunc aServoFunc);
 };
 
 #endif // nsDOMCSSDeclaration_h___
--- a/layout/style/nsICSSDeclaration.h
+++ b/layout/style/nsICSSDeclaration.h
@@ -27,16 +27,17 @@
 #include "nsWrapperCache.h"
 #include "nsString.h"
 #include "nsIDOMCSSRule.h"
 #include "nsIDOMCSSValue.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCOMPtr.h"
 
 class nsINode;
+class nsIPrincipal;
 
 // dbeabbfa-6cb3-4f5c-aec2-dd558d9d681f
 #define NS_ICSSDECLARATION_IID \
 { 0xdbeabbfa, 0x6cb3, 0x4f5c, \
  { 0xae, 0xc2, 0xdd, 0x55, 0x8d, 0x9d, 0x68, 0x1f } }
 
 class nsICSSDeclaration : public nsIDOMCSSStyleDeclaration,
                           public nsWrapperCache
@@ -52,24 +53,26 @@ public:
                               nsAString& aValue) = 0;
 
   /**
    * Method analogous to nsIDOMCSSStyleDeclaration::SetProperty.  This
    * method does NOT allow setting a priority (the priority will
    * always be set to default priority).
    */
   NS_IMETHOD SetPropertyValue(const nsCSSPropertyID aPropID,
-                              const nsAString& aValue) = 0;
+                              const nsAString& aValue,
+                              nsIPrincipal* aSubjectPrincipal = nullptr) = 0;
 
   virtual nsINode *GetParentObject() = 0;
 
   // Also have to declare all the nsIDOMCSSStyleDeclaration methods,
   // since we want to be able to call them from the WebIDL versions.
   NS_IMETHOD GetCssText(nsAString& aCssText) override = 0;
-  NS_IMETHOD SetCssText(const nsAString& aCssText) override = 0;
+  NS_IMETHOD SetCssText(const nsAString& aCssText,
+                        nsIPrincipal* aSubjectPrincipal = nullptr) override = 0;
   NS_IMETHOD GetPropertyValue(const nsAString& aPropName,
                               nsAString& aValue) override = 0;
   virtual already_AddRefed<mozilla::dom::CSSValue>
     GetPropertyCSSValue(const nsAString& aPropertyName,
                         mozilla::ErrorResult& aRv) = 0;
   NS_IMETHOD GetPropertyCSSValue(const nsAString& aProp, nsIDOMCSSValue** aVal) override
   {
     mozilla::ErrorResult error;
@@ -83,34 +86,36 @@ public:
     return NS_OK;
   }
   NS_IMETHOD RemoveProperty(const nsAString& aPropertyName,
                             nsAString& aReturn) override = 0;
   NS_IMETHOD GetPropertyPriority(const nsAString& aPropertyName,
                                  nsAString& aReturn) override = 0;
   NS_IMETHOD SetProperty(const nsAString& aPropertyName,
                          const nsAString& aValue,
-                         const nsAString& aPriority) override = 0;
+                         const nsAString& aPriority,
+                         nsIPrincipal* aSubjectPrincipal = nullptr) override = 0;
   NS_IMETHOD GetLength(uint32_t* aLength) override = 0;
   NS_IMETHOD Item(uint32_t aIndex, nsAString& aReturn) override
   {
     bool found;
     IndexedGetter(aIndex, found, aReturn);
     if (!found) {
       aReturn.Truncate();
     }
     return NS_OK;
   }
   NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) override = 0;
 
   // WebIDL interface for CSSStyleDeclaration
-  void SetCssText(const nsAString& aString, mozilla::ErrorResult& rv) {
-    rv = SetCssText(aString);
+  void SetCssText(const nsAString& aString, nsIPrincipal& aSubjectPrincipal,
+                  mozilla::ErrorResult& rv) {
+    rv = SetCssText(aString, &aSubjectPrincipal);
   }
-  void GetCssText(nsString& aString) {
+  void GetCssText(nsString& aString, nsIPrincipal& aSubjectPrincipal) {
     // Cast to nsAString& so we end up calling our virtual
     // |GetCssText(nsAString& aCssText)| overload, which does the real work.
     GetCssText(static_cast<nsAString&>(aString));
   }
   uint32_t Length() {
     uint32_t length;
     GetLength(&length);
     return length;
@@ -125,42 +130,48 @@ public:
   void GetPropertyValue(const nsAString& aPropName, nsString& aValue,
                         mozilla::ErrorResult& rv) {
     rv = GetPropertyValue(aPropName, aValue);
   }
   void GetPropertyPriority(const nsAString& aPropName, nsString& aPriority) {
     GetPropertyPriority(aPropName, static_cast<nsAString&>(aPriority));
   }
   void SetProperty(const nsAString& aPropName, const nsAString& aValue,
-                   const nsAString& aPriority, mozilla::ErrorResult& rv) {
-    rv = SetProperty(aPropName, aValue, aPriority);
+                   const nsAString& aPriority, nsIPrincipal& aSubjectPrincipal,
+                   mozilla::ErrorResult& rv) {
+    rv = SetProperty(aPropName, aValue, aPriority, &aSubjectPrincipal);
   }
   void RemoveProperty(const nsAString& aPropName, nsString& aRetval,
                       mozilla::ErrorResult& rv) {
     rv = RemoveProperty(aPropName, aRetval);
   }
   already_AddRefed<nsIDOMCSSRule> GetParentRule() {
     nsCOMPtr<nsIDOMCSSRule> rule;
     GetParentRule(getter_AddRefs(rule));
     return rule.forget();
   }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsICSSDeclaration, NS_ICSSDECLARATION_IID)
 
 #define NS_DECL_NSICSSDECLARATION                                   \
-  NS_IMETHOD GetPropertyValue(const nsCSSPropertyID aPropID,          \
+  NS_IMETHOD GetPropertyValue(const nsCSSPropertyID aPropID,        \
                               nsAString& aValue) override;          \
-  NS_IMETHOD SetPropertyValue(const nsCSSPropertyID aPropID,          \
-                              const nsAString& aValue) override;
+  NS_IMETHOD SetPropertyValue(const nsCSSPropertyID aPropID,        \
+                              const nsAString& aValue,              \
+                              nsIPrincipal* aSubjectPrincipal = nullptr) override;
 
 #define NS_DECL_NSIDOMCSSSTYLEDECLARATION_HELPER \
   NS_IMETHOD GetCssText(nsAString & aCssText) override; \
-  NS_IMETHOD SetCssText(const nsAString & aCssText) override; \
+  NS_IMETHOD SetCssText(const nsAString& aCssText,                 \
+                        nsIPrincipal* aSubjectPrincipal) override; \
   NS_IMETHOD GetPropertyValue(const nsAString & propertyName, nsAString & _retval) override; \
   NS_IMETHOD RemoveProperty(const nsAString & propertyName, nsAString & _retval) override; \
   NS_IMETHOD GetPropertyPriority(const nsAString & propertyName, nsAString & _retval) override; \
-  NS_IMETHOD SetProperty(const nsAString & propertyName, const nsAString & value, const nsAString & priority) override; \
+  NS_IMETHOD SetProperty(const nsAString& propertyName,                       \
+                         const nsAString& value,                              \
+                         const nsAString& priority,                           \
+                         nsIPrincipal* aSubjectPrincipal = nullptr) override; \
   NS_IMETHOD GetLength(uint32_t *aLength) override; \
   NS_IMETHOD Item(uint32_t index, nsAString & _retval) override; \
   NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) override;
 
 #endif // nsICSSDeclaration_h__
--- a/layout/style/nsStyleUtil.cpp
+++ b/layout/style/nsStyleUtil.cpp
@@ -830,33 +830,40 @@ nsStyleUtil::ObjectPropsMightCauseOverfl
 
   return false;
 }
 
 
 /* static */ bool
 nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
                                   nsIPrincipal* aPrincipal,
+                                  nsIPrincipal* aTriggeringPrincipal,
                                   nsIURI* aSourceURI,
                                   uint32_t aLineNumber,
                                   const nsAString& aStyleText,
                                   nsresult* aRv)
 {
   nsresult rv;
 
   if (aRv) {
     *aRv = NS_OK;
   }
 
   MOZ_ASSERT(!aContent || aContent->NodeInfo()->NameAtom() == nsGkAtoms::style,
       "aContent passed to CSPAllowsInlineStyle "
       "for an element that is not <style>");
 
+  nsIPrincipal* principal = aPrincipal;
+  if (aTriggeringPrincipal &&
+      BasePrincipal::Cast(aTriggeringPrincipal)->OverridesCSP(aPrincipal)) {
+    principal = aTriggeringPrincipal;
+  }
+
   nsCOMPtr<nsIContentSecurityPolicy> csp;
-  rv = aPrincipal->GetCsp(getter_AddRefs(csp));
+  rv = principal->GetCsp(getter_AddRefs(csp));
 
   if (NS_FAILED(rv)) {
     if (aRv)
       *aRv = rv;
     return false;
   }
 
   if (!csp) {
--- a/layout/style/nsStyleUtil.h
+++ b/layout/style/nsStyleUtil.h
@@ -184,30 +184,34 @@ public:
    *      The <style> element that the caller wants to know whether to honor.
    *      Included to check the nonce attribute if one is provided. Allowed to
    *      be null, if this is for something other than a <style> element (in
    *      which case nonces won't be checked).
    *  @param aPrincipal
    *      The principal of the of the document (*not* of the style sheet).
    *      The document's principal is where any Content Security Policy that
    *      should be used to block or allow inline styles will be located.
+   *  @param aTriggeringPrincipal
+   *      The principal of the scripted caller which added the inline
+   *      stylesheet, or null if no scripted caller can be identified.
    *  @param aSourceURI
    *      URI of document containing inline style (for reporting violations)
    *  @param aLineNumber
    *      Line number of inline style element in the containing document (for
    *      reporting violations)
    *  @param aStyleText
    *      Contents of the inline style element (for reporting violations)
    *  @param aRv
    *      Return error code in case of failure
    *  @return
    *      Does CSP allow application of the specified inline style?
    */
   static bool CSPAllowsInlineStyle(nsIContent* aContent,
                                    nsIPrincipal* aPrincipal,
+                                   nsIPrincipal* aTriggeringPrincipal,
                                    nsIURI* aSourceURI,
                                    uint32_t aLineNumber,
                                    const nsAString& aStyleText,
                                    nsresult* aRv);
 
   template<size_t N>
   static bool MatchesLanguagePrefix(const char16_t* aLang, size_t aLen,
                                     const char16_t (&aPrefix)[N])
--- a/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
+++ b/mobile/android/base/java/org/mozilla/gecko/webapps/WebAppActivity.java
@@ -317,16 +317,21 @@ public class WebAppActivity extends AppC
         }
 
         if (mManifest.isInScope(uri) && where != TargetWindow.NEW) {
             // This is in scope and wants to load in the same frame, so
             // let Gecko handle it.
             return false;
         }
 
+        if ("javascript".equals(uri.getScheme())) {
+            // These URIs will fail the scope check but should still be loaded in the PWA.
+            return false;
+        }
+
         if ("http".equals(uri.getScheme()) || "https".equals(uri.getScheme()) ||
             "data".equals(uri.getScheme()) || "blob".equals(uri.getScheme())) {
             final CustomTabsIntent.Builder builder = new CustomTabsIntent.Builder()
                 .addDefaultShareMenuItem()
                 .setStartAnimations(this, R.anim.slide_in_right, R.anim.slide_out_left)
                 .setExitAnimations(this, R.anim.slide_in_left, R.anim.slide_out_right);
 
             final Integer themeColor = mManifest.getThemeColor();
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -657,111 +657,16 @@ pref_savePrefs()
       "user_pref(%s, %s);", prefNameStr.get(), prefValueStr.get());
 
     savedPrefs.AppendElement(str);
   }
 
   return savedPrefs;
 }
 
-static bool
-PREF_HasUserPref(const char* aPrefName)
-{
-  if (!gHashTable) {
-    return false;
-  }
-
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  return pref && pref->HasUserValue();
-}
-
-// Clears the given pref (reverts it to its default value).
-static nsresult
-PREF_ClearUserPref(const char* aPrefName)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  if (pref && pref->HasUserValue()) {
-    pref->ClearUserValue();
-
-    if (!pref->HasDefaultValue()) {
-      gHashTable->RemoveEntry(pref);
-    }
-
-    NotifyCallbacks(aPrefName);
-    Preferences::HandleDirty();
-  }
-  return NS_OK;
-}
-
-// Clears all user prefs.
-static nsresult
-PREF_ClearAllUserPrefs()
-{
-  MOZ_ASSERT(NS_IsMainThread());
-
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  Vector<const char*> prefNames;
-  for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
-    auto pref = static_cast<PrefHashEntry*>(iter.Get());
-
-    if (pref->HasUserValue()) {
-      if (!prefNames.append(pref->Name())) {
-        return NS_ERROR_OUT_OF_MEMORY;
-      }
-
-      pref->ClearUserValue();
-      if (!pref->HasDefaultValue()) {
-        iter.Remove();
-      }
-    }
-  }
-
-  for (const char* prefName : prefNames) {
-    NotifyCallbacks(prefName);
-  }
-
-  Preferences::HandleDirty();
-  return NS_OK;
-}
-
-// Function that sets whether or not the preference is locked and therefore
-// cannot be changed.
-static nsresult
-PREF_LockPref(const char* aPrefName, bool aLockIt)
-{
-  if (!gHashTable) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-  if (!pref) {
-    return NS_ERROR_UNEXPECTED;
-  }
-
-  if (aLockIt) {
-    if (!pref->IsLocked()) {
-      pref->SetIsLocked(true);
-      gIsAnyPrefLocked = true;
-      NotifyCallbacks(aPrefName);
-    }
-  } else if (pref->IsLocked()) {
-    pref->SetIsLocked(false);
-    NotifyCallbacks(aPrefName);
-  }
-
-  return NS_OK;
-}
-
   //
   // Hash table functions
   //
 
 #ifdef DEBUG
 
 static pref_initPhase gPhase = START;
 
@@ -874,65 +779,16 @@ pref_SetPref(const char* aPrefName,
   }
   if (valueChanged) {
     NotifyCallbacks(aPrefName);
   }
 
   return NS_OK;
 }
 
-// Bool function that returns whether or not the preference is locked and
-// therefore cannot be changed.
-static bool
-PREF_PrefIsLocked(const char* aPrefName)
-{
-  bool result = false;
-  if (gIsAnyPrefLocked && gHashTable) {
-    PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
-    if (pref && pref->IsLocked()) {
-      result = true;
-    }
-  }
-
-  return result;
-}
-
-// Adds a node to the callback list; the position depends on aIsPriority. The
-// callback function will be called if anything below that node is modified.
-static void
-PREF_RegisterCallback(const char* aPrefNode,
-                      PrefChangedFunc aCallback,
-                      void* aData,
-                      Preferences::MatchKind aMatchKind,
-                      bool aIsPriority)
-{
-  NS_PRECONDITION(aPrefNode, "aPrefNode must not be nullptr");
-  NS_PRECONDITION(aCallback, "aCallback must not be nullptr");
-
-  auto node = new CallbackNode(aPrefNode, aCallback, aData, aMatchKind);
-
-  if (aIsPriority) {
-    // Add to the start of the list.
-    node->mNext = gFirstCallback;
-    gFirstCallback = node;
-    if (!gLastPriorityNode) {
-      gLastPriorityNode = node;
-    }
-  } else {
-    // Add to the start of the non-priority part of the list.
-    if (gLastPriorityNode) {
-      node->mNext = gLastPriorityNode->mNext;
-      gLastPriorityNode->mNext = node;
-    } else {
-      node->mNext = gFirstCallback;
-      gFirstCallback = node;
-    }
-  }
-}
-
 // Removes |node| from callback list. Returns the node after the deleted one.
 static CallbackNode*
 pref_RemoveCallbackNode(CallbackNode* aNode, CallbackNode* aPrevNode)
 {
   NS_PRECONDITION(!aPrevNode || aPrevNode->mNext == aNode, "invalid params");
   NS_PRECONDITION(aPrevNode || gFirstCallback == aNode, "invalid params");
 
   NS_ASSERTION(
@@ -947,51 +803,16 @@ pref_RemoveCallbackNode(CallbackNode* aN
   }
   if (gLastPriorityNode == aNode) {
     gLastPriorityNode = aPrevNode;
   }
   delete aNode;
   return next_node;
 }
 
-// Deletes a node from the callback list or marks it for deletion. Succeeds if
-// a callback was found that matched all the parameters.
-static nsresult
-PREF_UnregisterCallback(const char* aPrefNode,
-                        PrefChangedFunc aCallback,
-                        void* aData,
-                        Preferences::MatchKind aMatchKind)
-{
-  nsresult rv = NS_ERROR_FAILURE;
-  CallbackNode* node = gFirstCallback;
-  CallbackNode* prev_node = nullptr;
-
-  while (node != nullptr) {
-    if (node->mFunc == aCallback && node->mData == aData &&
-        node->mMatchKind == aMatchKind &&
-        strcmp(node->mDomain.get(), aPrefNode) == 0) {
-      if (gCallbacksInProgress) {
-        // postpone the node removal until after
-        // callbacks enumeration is finished.
-        node->mFunc = nullptr;
-        gShouldCleanupDeadNodes = true;
-        prev_node = node;
-        node = node->mNext;
-      } else {
-        node = pref_RemoveCallbackNode(node, prev_node);
-      }
-      rv = NS_OK;
-    } else {
-      prev_node = node;
-      node = node->mNext;
-    }
-  }
-  return rv;
-}
-
 static void
 NotifyCallbacks(const char* aPrefName)
 {
   bool reentered = gCallbacksInProgress;
 
   // Nodes must not be deleted while gCallbacksInProgress is true.
   // Nodes that need to be deleted are marked for deletion by nulling
   // out the |func| pointer. We release them at the end of this function
@@ -2203,17 +2024,18 @@ nsPrefBranch::GetComplexValue(const char
 
     const PrefName& pref = GetPrefName(aPrefName);
     bool bNeedDefault = false;
 
     if (mKind == PrefValueKind::Default) {
       bNeedDefault = true;
     } else {
       // if there is no user (or locked) value
-      if (!PREF_HasUserPref(pref.get()) && !PREF_PrefIsLocked(pref.get())) {
+      if (!Preferences::HasUserValue(pref.get()) &&
+          !Preferences::IsLocked(pref.get())) {
         bNeedDefault = true;
       }
     }
 
     // if we need to fetch the default value, do that instead, otherwise use the
     // value we pulled in at the top of this function
     if (bNeedDefault) {
       nsAutoString utf16String;
@@ -2448,64 +2270,60 @@ nsPrefBranch::SetComplexValue(const char
 
   NS_WARNING("nsPrefBranch::SetComplexValue - Unsupported interface type");
   return NS_NOINTERFACE;
 }
 
 NS_IMETHODIMP
 nsPrefBranch::ClearUserPref(const char* aPrefName)
 {
-  ENSURE_PARENT_PROCESS("ClearUserPref", aPrefName);
   NS_ENSURE_ARG(aPrefName);
 
   const PrefName& pref = GetPrefName(aPrefName);
-  return PREF_ClearUserPref(pref.get());
+  return Preferences::ClearUser(pref.get());
 }
 
 NS_IMETHODIMP
 nsPrefBranch::PrefHasUserValue(const char* aPrefName, bool* aRetVal)
 {
   NS_ENSURE_ARG_POINTER(aRetVal);
   NS_ENSURE_ARG(aPrefName);
 
   const PrefName& pref = GetPrefName(aPrefName);
-  *aRetVal = PREF_HasUserPref(pref.get());
+  *aRetVal = Preferences::HasUserValue(pref.get());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPrefBranch::LockPref(const char* aPrefName)
 {
-  ENSURE_PARENT_PROCESS("LockPref", aPrefName);
   NS_ENSURE_ARG(aPrefName);
 
   const PrefName& pref = GetPrefName(aPrefName);
-  return PREF_LockPref(pref.get(), true);
+  return Preferences::Lock(pref.get());
 }
 
 NS_IMETHODIMP
 nsPrefBranch::PrefIsLocked(const char* aPrefName, bool* aRetVal)
 {
-  ENSURE_PARENT_PROCESS("PrefIsLocked", aPrefName);
   NS_ENSURE_ARG_POINTER(aRetVal);
   NS_ENSURE_ARG(aPrefName);
 
   const PrefName& pref = GetPrefName(aPrefName);
-  *aRetVal = PREF_PrefIsLocked(pref.get());
+  *aRetVal = Preferences::IsLocked(pref.get());
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPrefBranch::UnlockPref(const char* aPrefName)
 {
-  ENSURE_PARENT_PROCESS("UnlockPref", aPrefName);
   NS_ENSURE_ARG(aPrefName);
 
   const PrefName& pref = GetPrefName(aPrefName);
-  return PREF_LockPref(pref.get(), false);
+  return Preferences::Unlock(pref.get());
 }
 
 NS_IMETHODIMP
 nsPrefBranch::ResetBranch(const char* aStartingAt)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
@@ -2643,21 +2461,21 @@ nsPrefBranch::AddObserver(const char* aD
   }
 
   p.OrInsert([&pCallback]() { return pCallback; });
 
   // We must pass a fully qualified preference name to the callback
   // aDomain == nullptr is the only possible failure, and we trapped it with
   // NS_ENSURE_ARG above.
   const PrefName& pref = GetPrefName(aDomain);
-  PREF_RegisterCallback(pref.get(),
-                        NotifyObserver,
-                        pCallback,
-                        Preferences::PrefixMatch,
-                        /* isPriority */ false);
+  Preferences::RegisterCallback(NotifyObserver,
+                                pref.get(),
+                                pCallback,
+                                Preferences::PrefixMatch,
+                                /* isPriority */ false);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsPrefBranch::RemoveObserver(const char* aDomain, nsIObserver* aObserver)
 {
   NS_ENSURE_ARG(aDomain);
@@ -2680,18 +2498,18 @@ nsPrefBranch::RemoveObserver(const char*
   // to it. Unregister the callback first, and then let the owning pointer go
   // out of scope and destroy the callback.
   PrefCallback key(aDomain, aObserver, this);
   nsAutoPtr<PrefCallback> pCallback;
   mObservers.Remove(&key, &pCallback);
   if (pCallback) {
     // aDomain == nullptr is the only possible failure, trapped above.
     const PrefName& pref = GetPrefName(aDomain);
-    rv = PREF_UnregisterCallback(
-      pref.get(), NotifyObserver, pCallback, Preferences::PrefixMatch);
+    rv = Preferences::UnregisterCallback(
+      NotifyObserver, pref.get(), pCallback, Preferences::PrefixMatch);
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsPrefBranch::Observe(nsISupports* aSubject,
                       const char* aTopic,
@@ -2750,20 +2568,20 @@ nsPrefBranch::FreeObserverList()
   // over it. In particular, some clients will call RemoveObserver() when
   // they're removed and destructed via the iterator; we set
   // mFreeingObserverList to keep those calls from touching mObservers.
   mFreeingObserverList = true;
   for (auto iter = mObservers.Iter(); !iter.Done(); iter.Next()) {
     nsAutoPtr<PrefCallback>& callback = iter.Data();
     nsPrefBranch* prefBranch = callback->GetPrefBranch();
     const PrefName& pref = prefBranch->GetPrefName(callback->GetDomain().get());
-    PREF_UnregisterCallback(pref.get(),
-                            nsPrefBranch::NotifyObserver,
-                            callback,
-                            Preferences::PrefixMatch);
+    Preferences::UnregisterCallback(nsPrefBranch::NotifyObserver,
+                                    pref.get(),
+                                    callback,
+                                    Preferences::PrefixMatch);
     iter.Remove();
   }
   mFreeingObserverList = false;
 }
 
 void
 nsPrefBranch::RemoveExpiredCallback(PrefCallback* aCallback)
 {
@@ -3432,16 +3250,18 @@ Preferences::GetInstanceForService()
 
   } else {
     // Check if there is a deployment configuration file. If so, set up the
     // pref config machinery, which will actually read the file.
     nsAutoCString lockFileName;
     nsresult rv = Preferences::GetCString(
       "general.config.filename", lockFileName, PrefValueKind::User);
     if (NS_SUCCEEDED(rv)) {
+      Telemetry::ScalarSet(Telemetry::ScalarID::GENERAL_AUTOCONFIG_HAS_FILENAME,
+                           true);
       NS_CreateServicesFromCategory(
         "pref-config-startup",
         static_cast<nsISupports*>(static_cast<void*>(sPreferences)),
         "pref-config-startup");
     }
 
     nsCOMPtr<nsIObserverService> observerService =
       mozilla::services::GetObserverService();
@@ -3666,18 +3486,40 @@ Preferences::ResetPrefs()
 
   return InitInitialObjects().isOk() ? NS_OK : NS_ERROR_FAILURE;
 }
 
 NS_IMETHODIMP
 Preferences::ResetUserPrefs()
 {
   ENSURE_PARENT_PROCESS("Preferences::ResetUserPrefs", "all prefs");
-
-  PREF_ClearAllUserPrefs();
+  NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
+  MOZ_ASSERT(NS_IsMainThread());
+
+  Vector<const char*> prefNames;
+  for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
+    auto pref = static_cast<PrefHashEntry*>(iter.Get());
+
+    if (pref->HasUserValue()) {
+      if (!prefNames.append(pref->Name())) {
+        return NS_ERROR_OUT_OF_MEMORY;
+      }
+
+      pref->ClearUserValue();
+      if (!pref->HasDefaultValue()) {
+        iter.Remove();
+      }
+    }
+  }
+
+  for (const char* prefName : prefNames) {
+    NotifyCallbacks(prefName);
+  }
+
+  Preferences::HandleDirty();
   return NS_OK;
 }
 
 bool
 Preferences::AllowOffMainThreadSave()
 {
   // Put in a preference that allows us to disable off main thread preference
   // file save.
@@ -3759,17 +3601,17 @@ Preferences::SetPreference(const PrefSet
     if (NS_FAILED(rv)) {
       return;
     }
   }
 
   if (userValue.type() == dom::MaybePrefValue::TPrefValue) {
     SetValueFromDom(prefName, userValue.get_PrefValue(), PrefValueKind::User);
   } else {
-    PREF_ClearUserPref(prefName);
+    Preferences::ClearUserInAnyProcess(prefName);
   }
 
   // NB: we should never try to clear a default value, that doesn't
   // make sense
 }
 
 void
 Preferences::GetPreference(PrefSetting* aSetting)
@@ -4409,17 +4251,17 @@ Preferences::InitInitialObjects()
       !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "aurora") ||
       !strcmp(NS_STRINGIFY(MOZ_UPDATE_CHANNEL), "beta") || developerBuild) {
     Preferences::SetBoolInAnyProcess(
       kTelemetryPref, true, PrefValueKind::Default);
   } else {
     Preferences::SetBoolInAnyProcess(
       kTelemetryPref, false, PrefValueKind::Default);
   }
-  PREF_LockPref(kTelemetryPref, true);
+  Preferences::LockInAnyProcess(kTelemetryPref);
 #endif // MOZ_WIDGET_ANDROID
 
   NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID,
                                 nullptr,
                                 NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
 
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
@@ -4620,28 +4462,108 @@ Preferences::SetComplex(const char* aPre
                         nsISupports* aValue,
                         PrefValueKind aKind)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return GetRootBranch(aKind)->SetComplexValue(aPrefName, aType, aValue);
 }
 
 /* static */ nsresult
-Preferences::ClearUser(const char* aPref)
+Preferences::LockInAnyProcess(const char* aPrefName)
+{
+  NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
+
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  if (!pref) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (!pref->IsLocked()) {
+    pref->SetIsLocked(true);
+    gIsAnyPrefLocked = true;
+    NotifyCallbacks(aPrefName);
+  }
+
+  return NS_OK;
+}
+
+/* static */ nsresult
+Preferences::Lock(const char* aPrefName)
 {
-  ENSURE_PARENT_PROCESS("ClearUser", aPref);
+  ENSURE_PARENT_PROCESS("Lock", aPrefName);
+  return Preferences::LockInAnyProcess(aPrefName);
+}
+
+/* static */ nsresult
+Preferences::Unlock(const char* aPrefName)
+{
+  ENSURE_PARENT_PROCESS("Unlock", aPrefName);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
-  return PREF_ClearUserPref(aPref);
+
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  if (!pref) {
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  if (pref->IsLocked()) {
+    pref->SetIsLocked(false);
+    NotifyCallbacks(aPrefName);
+  }
+
+  return NS_OK;
 }
 
 /* static */ bool
-Preferences::HasUserValue(const char* aPref)
+Preferences::IsLocked(const char* aPrefName)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), false);
-  return PREF_HasUserPref(aPref);
+
+  if (gIsAnyPrefLocked) {
+    PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+    if (pref && pref->IsLocked()) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+/* static */ nsresult
+Preferences::ClearUserInAnyProcess(const char* aPrefName)
+{
+  NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
+
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  if (pref && pref->HasUserValue()) {
+    pref->ClearUserValue();
+
+    if (!pref->HasDefaultValue()) {
+      gHashTable->RemoveEntry(pref);
+    }
+
+    NotifyCallbacks(aPrefName);
+    Preferences::HandleDirty();
+  }
+  return NS_OK;
+}
+
+/* static */ nsresult
+Preferences::ClearUser(const char* aPrefName)
+{
+  ENSURE_PARENT_PROCESS("ClearUser", aPrefName);
+  return ClearUserInAnyProcess(aPrefName);
+}
+
+/* static */ bool
+Preferences::HasUserValue(const char* aPrefName)
+{
+  NS_ENSURE_TRUE(InitStaticMembers(), false);
+
+  PrefHashEntry* pref = pref_HashTableLookup(aPrefName);
+  return pref && pref->HasUserValue();
 }
 
 /* static */ int32_t
 Preferences::GetType(const char* aPrefName, PrefValueKind aKind)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
   int32_t result;
   return NS_SUCCEEDED(GetRootBranch(aKind)->GetPrefType(aPrefName, &result))
@@ -4711,41 +4633,47 @@ Preferences::RemoveObservers(nsIObserver
 
   for (uint32_t i = 0; aPrefs[i]; i++) {
     nsresult rv = RemoveObserver(aObserver, aPrefs[i]);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
-// RegisterVarCacheCallback uses high priority callbacks to ensure that cache
-// observers are called prior to ordinary pref observers. Doing this ensures
-// that ordinary observers will never get stale values from cache variables.
-static void
-RegisterVarCacheCallback(PrefChangedFunc aCallback,
-                         const char* aPref,
-                         void* aClosure)
-{
-  MOZ_ASSERT(Preferences::IsServiceAvailable());
-
-  PREF_RegisterCallback(
-    aPref, aCallback, aClosure, Preferences::ExactMatch, /* isPriority */ true);
-}
-
 /* static */ nsresult
 Preferences::RegisterCallback(PrefChangedFunc aCallback,
-                              const char* aPref,
-                              void* aClosure,
-                              MatchKind aMatchKind)
+                              const char* aPrefNode,
+                              void* aData,
+                              MatchKind aMatchKind,
+                              bool aIsPriority)
 {
-  MOZ_ASSERT(aCallback);
+  NS_ENSURE_ARG(aPrefNode);
+  NS_ENSURE_ARG(aCallback);
+
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
 
-  PREF_RegisterCallback(
-    aPref, aCallback, aClosure, aMatchKind, /* isPriority */ false);
+  auto node = new CallbackNode(aPrefNode, aCallback, aData, aMatchKind);
+
+  if (aIsPriority) {
+    // Add to the start of the list.
+    node->mNext = gFirstCallback;
+    gFirstCallback = node;
+    if (!gLastPriorityNode) {
+      gLastPriorityNode = node;
+    }
+  } else {
+    // Add to the start of the non-priority part of the list.
+    if (gLastPriorityNode) {
+      node->mNext = gLastPriorityNode->mNext;
+      gLastPriorityNode->mNext = node;
+    } else {
+      node->mNext = gFirstCallback;
+      gFirstCallback = node;
+    }
+  }
 
   return NS_OK;
 }
 
 /* static */ nsresult
 Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback,
                                      const char* aPref,
                                      void* aClosure,
@@ -4757,28 +4685,52 @@ Preferences::RegisterCallbackAndCall(Pre
     AUTO_INSTALLING_CALLBACK();
     (*aCallback)(aPref, aClosure);
   }
   return rv;
 }
 
 /* static */ nsresult
 Preferences::UnregisterCallback(PrefChangedFunc aCallback,
-                                const char* aPref,
-                                void* aClosure,
+                                const char* aPrefNode,
+                                void* aData,
                                 MatchKind aMatchKind)
 {
   MOZ_ASSERT(aCallback);
   if (sShutdown) {
     MOZ_ASSERT(!sPreferences);
     return NS_OK; // Observers have been released automatically.
   }
   NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
 
-  return PREF_UnregisterCallback(aPref, aCallback, aClosure, aMatchKind);
+  nsresult rv = NS_ERROR_FAILURE;
+  CallbackNode* node = gFirstCallback;
+  CallbackNode* prev_node = nullptr;
+
+  while (node) {
+    if (node->mFunc == aCallback && node->mData == aData &&
+        node->mMatchKind == aMatchKind &&
+        strcmp(node->mDomain.get(), aPrefNode) == 0) {
+      if (gCallbacksInProgress) {
+        // postpone the node removal until after
+        // callbacks enumeration is finished.
+        node->mFunc = nullptr;
+        gShouldCleanupDeadNodes = true;
+        prev_node = node;
+        node = node->mNext;
+      } else {
+        node = pref_RemoveCallbackNode(node, prev_node);
+      }
+      rv = NS_OK;
+    } else {
+      prev_node = node;
+      node = node->mNext;
+    }
+  }
+  return rv;
 }
 
 static void
 CacheDataAppendElement(CacheData* aData)
 {
   if (!gCacheData) {
     MOZ_CRASH_UNSAFE_PRINTF("!gCacheData: %s", gCacheDataDesc);
   }
@@ -4803,46 +4755,56 @@ Preferences::AddBoolVarCache(bool* aCach
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = GetBool(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueBool = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(BoolVarChanged, aPref, data);
+  Preferences::RegisterCallback(BoolVarChanged,
+                                aPref,
+                                data,
+                                Preferences::ExactMatch,
+                                /* isPriority */ true);
   return NS_OK;
 }
 
 template<MemoryOrdering Order>
 static void
 AtomicBoolVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<Atomic<bool, Order>*>(cache->mCacheLocation) =
     Preferences::GetBool(aPref, cache->mDefaultValueBool);
 }
 
 template<MemoryOrdering Order>
 /* static */ nsresult
-Preferences::AddAtomicBoolVarCache(Atomic<bool, Order>* aCache, const char* aPref, bool aDefault)
+Preferences::AddAtomicBoolVarCache(Atomic<bool, Order>* aCache,
+                                   const char* aPref,
+                                   bool aDefault)
 {
   NS_ASSERTION(aCache, "aCache must not be NULL");
 #ifdef DEBUG
   AssertNotAlreadyCached("bool", aPref, aCache);
 #endif
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = Preferences::GetBool(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueBool = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(AtomicBoolVarChanged<Order>, aPref, data);
+  Preferences::RegisterCallback(AtomicBoolVarChanged<Order>,
+                                aPref,
+                                data,
+                                Preferences::ExactMatch,
+                                /* isPriority */ true);
   return NS_OK;
 }
 
 static void
 IntVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<int32_t*>(cache->mCacheLocation) =
@@ -4861,17 +4823,18 @@ Preferences::AddIntVarCache(int32_t* aCa
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = Preferences::GetInt(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueInt = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(IntVarChanged, aPref, data);
+  Preferences::RegisterCallback(
+    IntVarChanged, aPref, data, Preferences::ExactMatch, /* isPriority */ true);
   return NS_OK;
 }
 
 template<MemoryOrdering Order>
 static void
 AtomicIntVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
@@ -4892,17 +4855,21 @@ Preferences::AddAtomicIntVarCache(Atomic
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = Preferences::GetInt(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(AtomicIntVarChanged<Order>, aPref, data);
+  Preferences::RegisterCallback(AtomicIntVarChanged<Order>,
+                                aPref,
+                                data,
+                                Preferences::ExactMatch,
+                                /* isPriority */ true);
   return NS_OK;
 }
 
 static void
 UintVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
   *static_cast<uint32_t*>(cache->mCacheLocation) =
@@ -4921,17 +4888,21 @@ Preferences::AddUintVarCache(uint32_t* a
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = Preferences::GetUint(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(UintVarChanged, aPref, data);
+  Preferences::RegisterCallback(UintVarChanged,
+                                aPref,
+                                data,
+                                Preferences::ExactMatch,
+                                /* isPriority */ true);
   return NS_OK;
 }
 
 template<MemoryOrdering Order>
 static void
 AtomicUintVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
@@ -4952,27 +4923,29 @@ Preferences::AddAtomicUintVarCache(Atomi
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = Preferences::GetUint(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(AtomicUintVarChanged<Order>, aPref, data);
+  Preferences::RegisterCallback(AtomicUintVarChanged<Order>,
+                                aPref,
+                                data,
+                                Preferences::ExactMatch,
+                                /* isPriority */ true);
   return NS_OK;
 }
 
 // Since the definition of template functions is not in a header file, we
 // need to explicitly specify the instantiations that are required. Currently
 // only the order=Relaxed variant is needed.
 template nsresult
-Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*,
-                                   const char*,
-                                   bool);
+Preferences::AddAtomicBoolVarCache(Atomic<bool, Relaxed>*, const char*, bool);
 
 template nsresult
 Preferences::AddAtomicIntVarCache(Atomic<int32_t, Relaxed>*,
                                   const char*,
                                   int32_t);
 
 template nsresult
 Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Relaxed>*,
@@ -4997,17 +4970,21 @@ Preferences::AddFloatVarCache(float* aCa
   {
     AUTO_INSTALLING_CALLBACK();
     *aCache = Preferences::GetFloat(aPref, aDefault);
   }
   CacheData* data = new CacheData();
   data->mCacheLocation = aCache;
   data->mDefaultValueFloat = aDefault;
   CacheDataAppendElement(data);
-  RegisterVarCacheCallback(FloatVarChanged, aPref, data);
+  Preferences::RegisterCallback(FloatVarChanged,
+                                aPref,
+                                data,
+                                Preferences::ExactMatch,
+                                /* isPriority */ true);
   return NS_OK;
 }
 
 } // namespace mozilla
 
 #undef ENSURE_PARENT_PROCESS
 
 //===========================================================================
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -232,18 +232,22 @@ public:
       aPrefName, NS_ConvertUTF16toUTF8(aValue), aKind);
   }
 
   static nsresult SetComplex(const char* aPrefName,
                              const nsIID& aType,
                              nsISupports* aValue,
                              PrefValueKind aKind = PrefValueKind::User);
 
+  static nsresult Lock(const char* aPrefName);
+  static nsresult Unlock(const char* aPrefName);
+  static bool IsLocked(const char* aPrefName);
+
   // Clears user set pref. Fails if run outside the parent process.
-  static nsresult ClearUser(const char* aPref);
+  static nsresult ClearUser(const char* aPrefName);
 
   // Whether the pref has a user value or not.
   static bool HasUserValue(const char* aPref);
 
   // Adds/Removes the observer for the root pref branch. See nsIPrefBranch.idl
   // for details.
   static nsresult AddStrongObserver(nsIObserver* aObserver, const char* aPref);
   static nsresult AddWeakObserver(nsIObserver* aObserver, const char* aPref);
@@ -422,20 +426,25 @@ private:
                                      int32_t aValue,
                                      PrefValueKind aKind = PrefValueKind::User);
 
   static nsresult SetCStringInAnyProcess(
     const char* aPrefName,
     const nsACString& aValue,
     PrefValueKind aKind = PrefValueKind::User);
 
+  static nsresult ClearUserInAnyProcess(const char* aPrefName);
+
+  static nsresult LockInAnyProcess(const char* aPrefName);
+
   static nsresult RegisterCallback(PrefChangedFunc aCallback,
                                    const char* aPref,
                                    void* aClosure,
-                                   MatchKind aMatchKind);
+                                   MatchKind aMatchKind,
+                                   bool aIsPriority = false);
   static nsresult UnregisterCallback(PrefChangedFunc aCallback,
                                      const char* aPref,
                                      void* aClosure,
                                      MatchKind aMatchKind);
   static nsresult RegisterCallbackAndCall(PrefChangedFunc aCallback,
                                           const char* aPref,
                                           void* aClosure,
                                           MatchKind aMatchKind);
--- a/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
+++ b/modules/libpref/test/gtest/CallbackAndVarCacheOrder.cpp
@@ -152,27 +152,29 @@ RunTest(const char* aPrefName1, const ch
 
 TEST(CallbackAndVarCacheOrder, Bool)
 {
   RunTest<bool>("test_pref.bool.1", "test_pref.bool.2", false, true);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicBool)
 {
-  RunTest<bool, Atomic<bool, Relaxed>>("test_pref.atomic_bool.1", "test_pref.atomic_bool.2", false, true);
+  RunTest<bool, Atomic<bool, Relaxed>>(
+    "test_pref.atomic_bool.1", "test_pref.atomic_bool.2", false, true);
 }
 
 TEST(CallbackAndVarCacheOrder, Int)
 {
   RunTest<int32_t>("test_pref.int.1", "test_pref.int.2", -2, 3);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicInt)
 {
-  RunTest<int32_t, Atomic<int32_t, Relaxed>>("test_pref.atomic_int.1", "test_pref.atomic_int.2", -3, 4);
+  RunTest<int32_t, Atomic<int32_t, Relaxed>>(
+    "test_pref.atomic_int.1", "test_pref.atomic_int.2", -3, 4);
 }
 
 TEST(CallbackAndVarCacheOrder, Uint)
 {
   RunTest<uint32_t>("test_pref.uint.1", "test_pref.uint.2", 4u, 5u);
 }
 
 TEST(CallbackAndVarCacheOrder, AtomicUint)
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -536,22 +536,18 @@ LoadInfo::FindPrincipalToInherit(nsIChan
     return mPrincipalToInherit;
   }
 
   nsCOMPtr<nsIURI> uri = mResultPrincipalURI;
   if (!uri) {
     Unused << aChannel->GetOriginalURI(getter_AddRefs(uri));
   }
 
-  bool dataInherits = mSecurityFlags & (SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS |
-                                        SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
-                                        SEC_REQUIRE_CORS_DATA_INHERITS);
-
   auto prin = BasePrincipal::Cast(mTriggeringPrincipal);
-  return prin->PrincipalToInherit(uri, dataInherits);
+  return prin->PrincipalToInherit(uri);
 }
 
 NS_IMETHODIMP
 LoadInfo::GetSandboxedLoadingPrincipal(nsIPrincipal** aPrincipal)
 {
   if (!(mSecurityFlags & nsILoadInfo::SEC_SANDBOXED)) {
     *aPrincipal = nullptr;
     return NS_OK;
--- a/netwerk/base/nsSimpleURI.cpp
+++ b/netwerk/base/nsSimpleURI.cpp
@@ -465,17 +465,19 @@ nsSimpleURI::SetPathQueryRefEscaped(cons
     nsresult rv;
     nsAutoCString path;
     if (aNeedsEscape) {
         rv = NS_EscapeURL(aPath, esc_OnlyNonASCII, path, fallible);
         if (NS_FAILED(rv)) {
           return rv;
         }
     } else {
-        path.Assign(aPath);
+        if (!path.Assign(aPath, fallible)) {
+            return NS_ERROR_OUT_OF_MEMORY;
+        }
     }
 
     int32_t queryPos = path.FindChar('?');
     int32_t hashPos = path.FindChar('#');
 
     if (queryPos != kNotFound && hashPos != kNotFound && hashPos < queryPos) {
         queryPos = kNotFound;
     }
--- a/netwerk/test/unit/test_aboutblank.js
+++ b/netwerk/test/unit/test_aboutblank.js
@@ -16,17 +16,20 @@ function run_test() {
   }).QueryInterface(Components.interfaces.nsIPropertyBag2);
 
   var haveProp = false;
   var propVal = null;
   try {
     propVal = chan1.getPropertyAsInterface("baseURI",
                                            Components.interfaces.nsIURI);
     haveProp = true;
-  } catch (e if e.result == Components.results.NS_ERROR_NOT_AVAILABLE) {
+  } catch (e) {
+    if (e.result != Components.results.NS_ERROR_NOT_AVAILABLE) {
+      throw e;
+    }
     // Property shouldn't be there.
   }
   do_check_eq(propVal, null);
   do_check_eq(haveProp, false);
   do_check_eq(chan2.getPropertyAsInterface("baseURI",
                                            Components.interfaces.nsIURI),
               base);
 }
--- a/netwerk/test/unit/test_backgroundfilesaver.js
+++ b/netwerk/test/unit/test_backgroundfilesaver.js
@@ -355,17 +355,21 @@ add_task(async function test_combination
     if (!cancelAtSomePoint) {
       saver.finish(Cr.NS_OK);
     }
     try {
       await completionPromise;
       if (cancelAtSomePoint) {
         do_throw("Failure expected.");
       }
-    } catch (ex if cancelAtSomePoint && ex.result == Cr.NS_ERROR_FAILURE) { }
+    } catch (ex) {
+      if (!cancelAtSomePoint || ex.result != Cr.NS_ERROR_FAILURE) {
+        throw ex;
+      }
+    }
 
     if (!cancelAtSomePoint) {
       // In this case, the file must exist.
       do_check_true(currentFile.exists());
       let expectedContents = testData + testData;
       await promiseVerifyContents(currentFile, expectedContents);
       do_check_eq(EXPECTED_HASHES[expectedContents.length],
                   toHex(saver.sha256Hash));
@@ -641,50 +645,66 @@ add_task(async function test_empty_hash(
 add_task(async function test_invalid_hash()
 {
   let saver = new BackgroundFileSaverStreamListener();
   let completionPromise = promiseSaverComplete(saver);
   // We shouldn't be able to get the hash if hashing hasn't been enabled
   try {
     let hash = saver.sha256Hash;
     do_throw("Shouldn't be able to get hash if hashing not enabled");
-  } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
+  } catch (ex) {
+    if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
+      throw e;
+    }
+  }
   // Enable hashing, but don't feed any data to saver
   saver.enableSha256();
   let destFile = getTempFile(TEST_FILE_NAME_1);
   saver.setTarget(destFile, false);
   // We don't wait on promiseSaverComplete, so the hash getter can run before
   // or after onSaveComplete is called. However, the expected behavior is the
   // same in both cases since the hash is only valid when the save completes
   // successfully.
   saver.finish(Cr.NS_ERROR_FAILURE);
   try {
     let hash = saver.sha256Hash;
     do_throw("Shouldn't be able to get hash if save did not succeed");
-  } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
+  } catch (ex) {
+    if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
+      throw ex;
+    }
+  }
   // Wait for completion so that the worker thread finishes dealing with the
   // target file. We expect it to fail.
   try {
     await completionPromise;
     do_throw("completionPromise should throw");
-  } catch (ex if ex.result == Cr.NS_ERROR_FAILURE) { }
+  } catch (ex) {
+    if (ex.result != Cr.NS_ERROR_FAILURE) {
+      throw ex;
+    }
+  }
 });
 
 add_task(async function test_signature()
 {
   // Check that we get a signature if the saver is finished.
   let destFile = getTempFile(TEST_FILE_NAME_1);
 
   let saver = new BackgroundFileSaverOutputStream();
   let completionPromise = promiseSaverComplete(saver);
 
   try {
     let signatureInfo = saver.signatureInfo;
     do_throw("Can't get signature if saver is not complete");
-  } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
+  } catch (ex) {
+    if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
+      throw ex;
+    }
+  }
 
   saver.enableSignatureInfo();
   saver.setTarget(destFile, false);
   await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
 
   saver.finish(Cr.NS_OK);
   await completionPromise;
   await promiseVerifyContents(destFile, TEST_DATA_SHORT);
@@ -706,17 +726,21 @@ add_task(async function test_signature_n
   saver.setTarget(destFile, false);
   await promiseCopyToSaver(TEST_DATA_SHORT, saver, true);
 
   saver.finish(Cr.NS_OK);
   await completionPromise;
   try {
     let signatureInfo = saver.signatureInfo;
     do_throw("Can't get signature if not enabled");
-  } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
+  } catch (ex) {
+    if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
+      throw ex;
+    }
+  }
 
   // Clean up.
   destFile.remove(false);
 });
 
 add_task(function test_teardown()
 {
   gStillRunning = false;
--- a/netwerk/test/unit/test_psl.js
+++ b/netwerk/test/unit/test_psl.js
@@ -18,18 +18,21 @@ function run_test()
   scriptLoader.loadSubScript(uri.spec, srvScope, "utf-8");
 }
 
 function checkPublicSuffix(host, expectedSuffix)
 {
   var actualSuffix = null;
   try {
     actualSuffix = etld.getBaseDomainFromHost(host);
-  } catch (e if e.result == Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS ||
-                e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
+  } catch (e) {
+    if (e.result != Cr.NS_ERROR_INSUFFICIENT_DOMAIN_LEVELS &&
+        e.result != Cr.NS_ERROR_ILLEGAL_VALUE) {
+      throw e;
+    }
   }
   // The EffectiveTLDService always gives back punycoded labels.
   // The test suite wants to get back what it put in.
   if (actualSuffix !== null && expectedSuffix !== null &&
       /(^|\.)xn--/.test(actualSuffix) && !/(^|\.)xn--/.test(expectedSuffix)) {
     actualSuffix = idna.convertACEtoUTF8(actualSuffix);
   }
   do_check_eq(actualSuffix, expectedSuffix);
--- a/netwerk/test/unit/test_signature_extraction.js
+++ b/netwerk/test/unit/test_signature_extraction.js
@@ -143,17 +143,21 @@ add_task(async function test_signature()
 
   let data = readFileToString("data/signed_win.exe");
   let saver = new BackgroundFileSaverOutputStream();
   let completionPromise = promiseSaverComplete(saver);
 
   try {
     let signatureInfo = saver.signatureInfo;
     do_throw("Can't get signature before saver is complete.");
-  } catch (ex if ex.result == Cr.NS_ERROR_NOT_AVAILABLE) { }
+  } catch (ex) {
+    if (ex.result != Cr.NS_ERROR_NOT_AVAILABLE) {
+      throw ex;
+    }
+  }
 
   saver.enableSignatureInfo();
   saver.setTarget(destFile, false);
   await promiseCopyToSaver(data, saver, true);
 
   saver.finish(Cr.NS_OK);
   await completionPromise;
 
new file mode 100644
--- /dev/null
+++ b/security/manager/ssl/tests/gtest/CoseTest.cpp
@@ -0,0 +1,738 @@
+/* -*- 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/. */
+
+#include "gtest/gtest.h"
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <cstddef>
+#include <memory>
+
+#include <keyhi.h>
+#include <nss.h>
+#include <pk11pub.h>
+
+#include <pkcs11t.h>
+#include <secmodt.h>
+#include <cert.h>
+
+#include "ScopedNSSTypes.h"
+#include "cosec.h"
+
+namespace mozilla {
+
+// "This is the content."
+const uint8_t PAYLOAD[] = { 84,  104, 105, 115, 32,  105, 115, 32,  116, 104,
+                            101, 32,  99,  111, 110, 116, 101, 110, 116, 46 };
+
+// This is a COSE signature generated with the cose rust library (see
+// third-party/rust/cose). The payload is signed with the P256 key from
+// pykey.py.
+const uint8_t SIGNATURE[] = {
+  0xd8, 0x62, 0x84, 0x59, 0x02, 0xa3, 0xa1, 0x04, 0x82, 0x59, 0x01, 0x4e, 0x30,
+  0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14,
+  0x5f, 0x3f, 0xae, 0x90, 0x49, 0x30, 0x2f, 0x33, 0x6e, 0x95, 0x23, 0xa7, 0xcb,
+  0x23, 0xd7, 0x65, 0x4f, 0xea, 0x3c, 0xf7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86,
+  0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06,
+  0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32,
+  0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30,
+  0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32,
+  0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
+  0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72,
+  0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06,
+  0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+  0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb,
+  0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec,
+  0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b,
+  0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07,
+  0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d,
+  0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30,
+  0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+  0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06,
+  0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
+  0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50,
+  0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73,
+  0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02,
+  0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7, 0xd5,
+  0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22, 0x54, 0xc8,
+  0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b, 0x59, 0x01, 0x4c, 0x30, 0x82,
+  0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x43,
+  0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80, 0x43, 0xec, 0x90, 0x6a, 0xd4, 0x10,
+  0x64, 0x7c, 0x7f, 0x38, 0x32, 0xe2, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
+  0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+  0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35,
+  0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31,
+  0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13,
+  0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69, 0x6e,
+  0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
+  0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+  0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0,
+  0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b,
+  0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c,
+  0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0,
+  0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3,
+  0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06,
+  0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b,
+  0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a,
+  0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00,
+  0x30, 0x44, 0x02, 0x20, 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e, 0x5b, 0xff,
+  0xd1, 0x16, 0x4e, 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf, 0x77, 0x5c,
+  0x93, 0x60, 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d, 0x24, 0x02, 0x20, 0x3d,
+  0x87, 0x0f, 0xac, 0x22, 0x4d, 0x16, 0xd9, 0xa1, 0x95, 0xbb, 0x56, 0xe0, 0x21,
+  0x05, 0x93, 0xd1, 0x07, 0xb5, 0x25, 0x3b, 0xf4, 0x57, 0x20, 0x87, 0x13, 0xa2,
+  0xf7, 0x78, 0x15, 0x30, 0xa7, 0xa0, 0xf6, 0x81, 0x83, 0x59, 0x01, 0x33, 0xa2,
+  0x01, 0x26, 0x04, 0x59, 0x01, 0x2c, 0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xcf,
+  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x2f, 0xc3, 0x5f, 0x05, 0x80, 0xb4,
+  0x49, 0x45, 0x13, 0x92, 0xd6, 0x93, 0xb7, 0x2d, 0x71, 0x19, 0xc5, 0x8c, 0x40,
+  0x39, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+  0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+  0x69, 0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32,
+  0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03,
+  0x55, 0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30,
+  0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
+  0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04,
+  0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac,
+  0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f,
+  0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36,
+  0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7,
+  0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30,
+  0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48,
+  0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd,
+  0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75,
+  0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x21,
+  0x00, 0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b, 0x75, 0xe2, 0x70, 0x6a,
+  0xac, 0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89, 0xc1, 0xcf, 0x88, 0xc2, 0xc8,
+  0x2a, 0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, 0x58, 0x40, 0xb7, 0x50, 0xae,
+  0x12, 0x41, 0xb2, 0x62, 0x28, 0x80, 0x0b, 0xaa, 0x99, 0xec, 0x5f, 0x1c, 0x91,
+  0x2f, 0xd8, 0x65, 0xd0, 0x1c, 0x38, 0x7c, 0x37, 0x63, 0x6d, 0xfa, 0x67, 0x9d,
+  0x21, 0xff, 0x54, 0x98, 0xf8, 0x97, 0x63, 0xc2, 0x2e, 0x3c, 0xfa, 0x25, 0x28,
+  0xec, 0x2c, 0x96, 0x8c, 0xca, 0xfc, 0x94, 0xd0, 0xc2, 0x19, 0x28, 0x28, 0x43,
+  0xe6, 0x64, 0xd4, 0x09, 0x2b, 0x0f, 0x01, 0xc3, 0x6e
+};
+
+// This is a COSE signature generated with the cose rust library (see
+// third-party/rust/cose). The payload is signed twice; with the P256 and the
+// RSA key from pykey.py.
+const uint8_t SIGNATURE_ES256_PS256[] = {
+  0xd8, 0x62, 0x84, 0x59, 0x08, 0x52, 0xa1, 0x04, 0x84, 0x59, 0x01, 0x4e, 0x30,
+  0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14,
+  0x5f, 0x3f, 0xae, 0x90, 0x49, 0x30, 0x2f, 0x33, 0x6e, 0x95, 0x23, 0xa7, 0xcb,
+  0x23, 0xd7, 0x65, 0x4f, 0xea, 0x3c, 0xf7, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86,
+  0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06,
+  0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32,
+  0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30,
+  0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32,
+  0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
+  0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72,
+  0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06,
+  0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+  0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb,
+  0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec,
+  0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b,
+  0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07,
+  0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d,
+  0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30,
+  0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+  0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06,
+  0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
+  0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50,
+  0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73,
+  0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02,
+  0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7, 0xd5,
+  0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22, 0x54, 0xc8,
+  0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b, 0x59, 0x01, 0x4c, 0x30, 0x82,
+  0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x43,
+  0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80, 0x43, 0xec, 0x90, 0x6a, 0xd4, 0x10,
+  0x64, 0x7c, 0x7f, 0x38, 0x32, 0xe2, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48,
+  0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03,
+  0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35,
+  0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31,
+  0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13,
+  0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69, 0x6e,
+  0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
+  0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d,
+  0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb, 0x61, 0xe0,
+  0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec, 0x05, 0x0b,
+  0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b, 0x45, 0x5c,
+  0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07, 0x06, 0xe0,
+  0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d, 0x07, 0xa3,
+  0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06,
+  0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b,
+  0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0a,
+  0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00,
+  0x30, 0x44, 0x02, 0x20, 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e, 0x5b, 0xff,
+  0xd1, 0x16, 0x4e, 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf, 0x77, 0x5c,
+  0x93, 0x60, 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d, 0x24, 0x02, 0x20, 0x3d,
+  0x87, 0x0f, 0xac, 0x22, 0x4d, 0x16, 0xd9, 0xa1, 0x95, 0xbb, 0x56, 0xe0, 0x21,
+  0x05, 0x93, 0xd1, 0x07, 0xb5, 0x25, 0x3b, 0xf4, 0x57, 0x20, 0x87, 0x13, 0xa2,
+  0xf7, 0x78, 0x15, 0x30, 0xa7, 0x59, 0x02, 0xd5, 0x30, 0x82, 0x02, 0xd1, 0x30,
+  0x82, 0x01, 0xbb, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x29, 0x6c, 0x1a,
+  0xd8, 0x20, 0xcd, 0x74, 0x6d, 0x4b, 0x00, 0xf3, 0x16, 0x88, 0xd9, 0x66, 0x87,
+  0x5f, 0x28, 0x56, 0x6a, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x01, 0x0b, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+  0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30,
+  0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32,
+  0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x13, 0x31, 0x11,
+  0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f, 0x6f, 0x74,
+  0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a,
+  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01,
+  0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xba, 0x88,
+  0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd, 0x6e, 0xb6, 0x88, 0x06, 0x36,
+  0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4, 0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68,
+  0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7, 0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1,
+  0x9c, 0x06, 0x9b, 0x6e, 0x1a, 0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b,
+  0x6a, 0x64, 0x71, 0x08, 0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5,
+  0x24, 0x9c, 0x02, 0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29,
+  0x93, 0xab, 0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e,
+  0xed, 0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a,
+  0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66, 0x0b,
+  0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90, 0xb1, 0x57,
+  0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8, 0x37, 0xd3, 0x88,
+  0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a, 0xaa, 0x7e, 0x02, 0x90,
+  0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc, 0x1c, 0x6c, 0x97, 0xad, 0x96,
+  0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0, 0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd,
+  0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d, 0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e,
+  0xa7, 0x68, 0xe1, 0xb3, 0x7b, 0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95,
+  0x61, 0x1d, 0xee, 0x26, 0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb,
+  0x1c, 0x24, 0x04, 0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17,
+  0x31, 0xb8, 0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03,
+  0xac, 0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3,
+  0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30,
+  0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04,
+  0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00, 0x23, 0x2f, 0x9f, 0x72,
+  0xeb, 0x70, 0x6d, 0x9e, 0x3e, 0x9f, 0xd7, 0x9c, 0xd9, 0x19, 0x7c, 0x99, 0x07,
+  0xc5, 0x5c, 0x9d, 0xf5, 0x66, 0x9f, 0x28, 0x8d, 0xfe, 0x0e, 0x3f, 0x38, 0x75,
+  0xed, 0xee, 0x4e, 0x3f, 0xf6, 0x6e, 0x35, 0xe0, 0x95, 0x3f, 0x08, 0x4a, 0x71,
+  0x5a, 0xf2, 0x4f, 0xc9, 0x96, 0x61, 0x8d, 0x45, 0x4b, 0x97, 0x85, 0xff, 0xb0,
+  0xe3, 0xbb, 0xb5, 0xd7, 0x7e, 0xfb, 0xd2, 0xfc, 0xec, 0xfe, 0x42, 0x9f, 0x4e,
+  0x7b, 0xbf, 0x97, 0xbb, 0xb4, 0x3a, 0x93, 0x0b, 0x13, 0x61, 0x90, 0x0c, 0x3a,
+  0xce, 0xf7, 0x8e, 0xef, 0x80, 0xf5, 0x4a, 0x92, 0xc5, 0xa5, 0x03, 0x78, 0xc2,
+  0xee, 0xb8, 0x66, 0x60, 0x6b, 0x76, 0x4f, 0x32, 0x5a, 0x1a, 0xa2, 0x4b, 0x7e,
+  0x2b, 0xa6, 0x1a, 0x89, 0x01, 0xe3, 0xbb, 0x55, 0x13, 0x7c, 0x4c, 0xf4, 0x6a,
+  0x99, 0x94, 0xd1, 0xa0, 0x84, 0x1c, 0x1a, 0xc2, 0x7b, 0xb4, 0xa0, 0xb0, 0x3b,
+  0xdc, 0x5a, 0x7b, 0xc7, 0xe0, 0x44, 0xb2, 0x1f, 0x46, 0xd5, 0x8b, 0x39, 0x8b,
+  0xdc, 0x9e, 0xce, 0xa8, 0x7f, 0x85, 0x1d, 0x4b, 0x63, 0x06, 0x1e, 0x8e, 0xe5,
+  0xe5, 0x99, 0xd9, 0xf7, 0x4d, 0x89, 0x0b, 0x1d, 0x5c, 0x27, 0x33, 0x66, 0x21,
+  0xcf, 0x9a, 0xbd, 0x98, 0x68, 0x23, 0x3a, 0x66, 0x9d, 0xd4, 0x46, 0xed, 0x63,
+  0x58, 0xf3, 0x42, 0xe4, 0x1d, 0xe2, 0x47, 0x65, 0x13, 0x8d, 0xd4, 0x1f, 0x4b,
+  0x7e, 0xde, 0x11, 0x56, 0xf8, 0x6d, 0x01, 0x0c, 0x99, 0xbd, 0x8d, 0xca, 0x8a,
+  0x2e, 0xe3, 0x8a, 0x9c, 0x3d, 0x83, 0x8d, 0x69, 0x62, 0x8d, 0x05, 0xea, 0xb7,
+  0xf5, 0xa3, 0x4b, 0xfc, 0x96, 0xcf, 0x18, 0x21, 0x0a, 0xc7, 0xf3, 0x23, 0x7e,
+  0x1c, 0xab, 0xe2, 0xa2, 0xd1, 0x83, 0xc4, 0x25, 0x93, 0x37, 0x80, 0xca, 0xda,
+  0xf0, 0xef, 0x7d, 0x94, 0xb5, 0x59, 0x02, 0xd4, 0x30, 0x82, 0x02, 0xd0, 0x30,
+  0x82, 0x01, 0xba, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x07, 0x10, 0xaf,
+  0xc4, 0x1a, 0x3a, 0x56, 0x4f, 0xd8, 0xc2, 0xcc, 0x46, 0xd7, 0x5b, 0xdf, 0x1c,
+  0x4e, 0x2f, 0x49, 0x3a, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x01, 0x0b, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55,
+  0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30,
+  0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32,
+  0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10,
+  0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x69, 0x6e, 0x74, 0x2d,
+  0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86,
+  0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f,
+  0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xba, 0x88, 0x51,
+  0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd, 0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10,
+  0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4, 0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57,
+  0x6c, 0x24, 0x7b, 0xc1, 0xc7, 0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c,
+  0x06, 0x9b, 0x6e, 0x1a, 0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a,
+  0x64, 0x71, 0x08, 0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24,
+  0x9c, 0x02, 0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93,
+  0xab, 0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed,
+  0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a, 0x8b,
+  0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66, 0x0b, 0x2b,
+  0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90, 0xb1, 0x57, 0x90,
+  0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8, 0x37, 0xd3, 0x88, 0x43,
+  0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a, 0xaa, 0x7e, 0x02, 0x90, 0x2f,
+  0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc, 0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61,
+  0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0, 0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4,
+  0xca, 0xf7, 0xfc, 0xad, 0x1d, 0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7,
+  0x68, 0xe1, 0xb3, 0x7b, 0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61,
+  0x1d, 0xee, 0x26, 0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c,
+  0x24, 0x04, 0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31,
+  0xb8, 0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac,
+  0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x1d,
+  0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03,
+  0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
+  0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+  0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00, 0x5e, 0xba, 0x69, 0x55, 0x9f,
+  0xf8, 0xeb, 0x16, 0x21, 0x98, 0xde, 0xb7, 0x31, 0x3e, 0x66, 0xe1, 0x3b, 0x0c,
+  0x29, 0xf7, 0x48, 0x73, 0x05, 0xd9, 0xce, 0x5e, 0x4c, 0xbe, 0x03, 0xc4, 0x51,
+  0xd6, 0x21, 0x92, 0x40, 0x38, 0xaa, 0x5b, 0x28, 0xb5, 0xa1, 0x10, 0x52, 0x57,
+  0xff, 0x91, 0x54, 0x82, 0x86, 0x9e, 0x74, 0xd5, 0x3d, 0x82, 0x29, 0xee, 0xd1,
+  0xcf, 0x93, 0xb1, 0x24, 0x76, 0xbb, 0x95, 0x41, 0x06, 0x7e, 0x40, 0x9b, 0xb4,
+  0xab, 0x44, 0x34, 0x10, 0x8f, 0xb1, 0x51, 0x6f, 0xc0, 0x89, 0xd1, 0xa3, 0xc4,
+  0x9f, 0xb3, 0x48, 0xe1, 0xcd, 0x73, 0xad, 0xff, 0x42, 0x5f, 0x76, 0x05, 0x60,
+  0xc5, 0xe0, 0x45, 0x79, 0x18, 0xa1, 0x19, 0xb8, 0xa7, 0x3a, 0x64, 0xb3, 0x19,
+  0xba, 0x14, 0xa1, 0xb5, 0xdc, 0x32, 0xec, 0x09, 0x39, 0x58, 0x54, 0x5b, 0x04,
+  0xdc, 0x1b, 0x66, 0x0d, 0x1d, 0x0d, 0xce, 0x7f, 0xfa, 0x24, 0x52, 0x6a, 0xad,
+  0xe2, 0xc8, 0x30, 0xaf, 0xf2, 0xaf, 0x63, 0xc5, 0xe2, 0xbf, 0xe2, 0x20, 0x1b,
+  0x9e, 0xf9, 0x3d, 0xbc, 0xfb, 0x04, 0x8e, 0xda, 0x7a, 0x1a, 0x5d, 0xd3, 0x13,
+  0xd7, 0x00, 0x8e, 0x9b, 0x5d, 0x85, 0x51, 0xda, 0xd3, 0x91, 0x25, 0xf5, 0x67,
+  0x85, 0x3e, 0x25, 0x89, 0x5e, 0xcb, 0x89, 0x8a, 0xec, 0x8a, 0xde, 0x8b, 0xf4,
+  0x33, 0x5f, 0x76, 0xdb, 0x3d, 0xfc, 0x6a, 0x05, 0x21, 0x43, 0xb2, 0x41, 0xd8,
+  0x33, 0x8d, 0xfd, 0x05, 0x5c, 0x22, 0x0a, 0xf6, 0x90, 0x65, 0x9c, 0x4f, 0x8c,
+  0x44, 0x9f, 0x2d, 0xca, 0xf3, 0x49, 0x9c, 0x3a, 0x14, 0x88, 0xab, 0xe4, 0xce,
+  0xb7, 0xbc, 0x95, 0x22, 0x2e, 0xb1, 0x82, 0x4c, 0xbf, 0x83, 0x3e, 0x49, 0x72,
+  0x03, 0x2a, 0x68, 0xe7, 0x2d, 0xe5, 0x2d, 0x4b, 0x61, 0xb0, 0x8d, 0x0d, 0x0c,
+  0x87, 0xc6, 0x5c, 0x51, 0xa0, 0xf6, 0x82, 0x83, 0x59, 0x01, 0x33, 0xa2, 0x01,
+  0x26, 0x04, 0x59, 0x01, 0x2c, 0x30, 0x82, 0x01, 0x28, 0x30, 0x81, 0xcf, 0xa0,
+  0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x2f, 0xc3, 0x5f, 0x05, 0x80, 0xb4, 0x49,
+  0x45, 0x13, 0x92, 0xd6, 0x93, 0xb7, 0x2d, 0x71, 0x19, 0xc5, 0x8c, 0x40, 0x39,
+  0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30,
+  0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x69,
+  0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30,
+  0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
+  0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55,
+  0x04, 0x03, 0x0c, 0x07, 0x65, 0x65, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59,
+  0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08,
+  0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f,
+  0xbf, 0xbb, 0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87,
+  0x04, 0xe2, 0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c,
+  0x4f, 0x79, 0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4,
+  0x11, 0x9d, 0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99,
+  0x1b, 0x7b, 0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0x30, 0x0a,
+  0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00,
+  0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11, 0x50, 0xcd, 0x5d,
+  0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2, 0x73, 0x75, 0x5f,
+  0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6, 0x02, 0x21, 0x00,
+  0xff, 0x81, 0xbe, 0xa8, 0x0d, 0x03, 0x36, 0x6b, 0x75, 0xe2, 0x70, 0x6a, 0xac,
+  0x07, 0x2e, 0x4c, 0xdc, 0xf9, 0xc5, 0x89, 0xc1, 0xcf, 0x88, 0xc2, 0xc8, 0x2a,
+  0x32, 0xf5, 0x42, 0x0c, 0xfa, 0x0b, 0xa0, 0x58, 0x40, 0xfa, 0xc6, 0xb7, 0xae,
+  0xec, 0x0b, 0x0b, 0xe2, 0xef, 0xae, 0xf7, 0x9d, 0x64, 0xe5, 0xaf, 0xbb, 0x2c,
+  0x4b, 0xe8, 0x7c, 0x61, 0xa9, 0x1e, 0xb9, 0x6d, 0x9c, 0xfa, 0xe3, 0x11, 0x77,
+  0xaf, 0x44, 0x9d, 0xc3, 0xa8, 0xa9, 0xbc, 0x58, 0xed, 0xc5, 0xe5, 0xa1, 0x92,
+  0x3b, 0x89, 0xa3, 0x3b, 0x1e, 0xbf, 0x6e, 0x33, 0x64, 0x21, 0x0b, 0x97, 0xee,
+  0xb7, 0xae, 0x84, 0x17, 0x5c, 0xff, 0x27, 0xa0, 0x83, 0x59, 0x02, 0xbb, 0xa2,
+  0x01, 0x38, 0x24, 0x04, 0x59, 0x02, 0xb3, 0x30, 0x82, 0x02, 0xaf, 0x30, 0x82,
+  0x01, 0x99, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x07, 0x1c, 0x3b, 0x71,
+  0x08, 0xbe, 0xd7, 0x9f, 0xfd, 0xaf, 0x26, 0xb6, 0x08, 0xa3, 0x99, 0x06, 0x77,
+  0x69, 0x32, 0x7e, 0x30, 0x0b, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d,
+  0x01, 0x01, 0x0b, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04,
+  0x03, 0x0c, 0x07, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18,
+  0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x11, 0x31, 0x0f, 0x30, 0x0d,
+  0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x06, 0x65, 0x65, 0x2d, 0x72, 0x73, 0x61,
+  0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
+  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82,
+  0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e,
+  0x16, 0xd6, 0x41, 0xfd, 0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13,
+  0xd9, 0xea, 0xe4, 0x35, 0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b,
+  0xc1, 0xc7, 0x25, 0xa8, 0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e,
+  0x1a, 0x86, 0xf2, 0x6b, 0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08,
+  0x7a, 0xa5, 0x5a, 0xa7, 0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02, 0x7e,
+  0xcd, 0x43, 0xfc, 0x1e, 0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab, 0x20, 0xc3,
+  0x49, 0xe4, 0xdb, 0xb9, 0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed, 0x15, 0x82, 0x0f,
+  0xf1, 0x7e, 0xad, 0x69, 0x1a, 0xb1, 0xd3, 0x02, 0x3a, 0x8b, 0x2a, 0x41, 0xee,
+  0xa7, 0x70, 0xe0, 0x0f, 0x0d, 0x8d, 0xfd, 0x66, 0x0b, 0x2b, 0xb0, 0x24, 0x92,
+  0xa4, 0x7d, 0xb9, 0x88, 0x61, 0x79, 0x90, 0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b,
+  0xc5, 0xe0, 0xb8, 0x48, 0x1f, 0xa8, 0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16,
+  0xd8, 0x55, 0xb7, 0x66, 0x5a, 0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10,
+  0x80, 0x06, 0x24, 0xcc, 0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2,
+  0x96, 0x12, 0xc0, 0x75, 0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc,
+  0xad, 0x1d, 0x25, 0xd3, 0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3,
+  0x7b, 0x2f, 0x22, 0x6f, 0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26,
+  0xd6, 0x25, 0x9d, 0xab, 0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04, 0x2c,
+  0xbf, 0x16, 0x8b, 0x2f, 0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8, 0xb3, 0xfe,
+  0x49, 0x23, 0xfa, 0x72, 0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac, 0xda, 0x18, 0x0a,
+  0x35, 0xed, 0x8d, 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x0b, 0x06, 0x09, 0x2a,
+  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00,
+  0x44, 0x92, 0xbb, 0x8e, 0x83, 0x58, 0x56, 0x2e, 0x7a, 0x86, 0xfa, 0x1d, 0x77,
+  0x50, 0x3f, 0x45, 0x8d, 0x90, 0xc4, 0x62, 0x27, 0x21, 0x96, 0x5a, 0xef, 0x51,
+  0x78, 0xd7, 0x7d, 0x0d, 0x02, 0x2d, 0x5a, 0x0e, 0x3c, 0x82, 0x6f, 0x1d, 0x92,
+  0x87, 0xd5, 0x1a, 0x44, 0xae, 0xa7, 0x92, 0xd1, 0x8b, 0xfa, 0x16, 0x53, 0x7f,
+  0xa3, 0x22, 0x96, 0x1a, 0x51, 0x8c, 0xeb, 0xa1, 0xe6, 0xf6, 0x37, 0x11, 0xfe,
+  0x7d, 0x53, 0x3f, 0xae, 0xf0, 0x6b, 0xb9, 0xb1, 0x7a, 0x73, 0x07, 0x14, 0xcf,
+  0x04, 0x05, 0x93, 0x9e, 0xe3, 0xd2, 0x4d, 0x9d, 0x6d, 0x35, 0x68, 0xf9, 0x36,
+  0xe5, 0x10, 0x0a, 0x36, 0xd9, 0x48, 0xb0, 0x83, 0xd0, 0xb9, 0x58, 0x74, 0x53,
+  0xb3, 0xbc, 0x99, 0xab, 0xe1, 0x3e, 0xd5, 0x01, 0x8e, 0xcf, 0x3a, 0x69, 0x93,
+  0x9e, 0xa7, 0x88, 0xd4, 0xad, 0x95, 0xf9, 0x2a, 0xb4, 0x7f, 0x95, 0x97, 0x86,
+  0x50, 0x38, 0xb1, 0x04, 0x0a, 0xe4, 0x7a, 0xd5, 0x2d, 0x6c, 0xde, 0x3e, 0x1a,
+  0x47, 0x17, 0x88, 0x63, 0x20, 0x9d, 0x21, 0x3e, 0x0c, 0x6f, 0xfd, 0x20, 0x54,
+  0xd0, 0x67, 0xd2, 0x6b, 0x06, 0xfe, 0x60, 0x13, 0x42, 0x3d, 0xb7, 0xca, 0xcb,
+  0xab, 0x7b, 0x5f, 0x5d, 0x01, 0x56, 0xd3, 0x99, 0x80, 0x0f, 0xde, 0x7f, 0x3a,
+  0x61, 0x9c, 0xd3, 0x6b, 0x5e, 0xfe, 0xb5, 0xfc, 0x39, 0x8b, 0x8e, 0xf0, 0x8c,
+  0x8b, 0x65, 0x46, 0x45, 0xff, 0x47, 0x8f, 0xd4, 0xdd, 0xae, 0xc9, 0x72, 0xc7,
+  0x7f, 0x28, 0x86, 0xf1, 0xf7, 0x6e, 0xcb, 0x86, 0x03, 0xeb, 0x0c, 0x46, 0xe5,
+  0xa0, 0x6b, 0xef, 0xd4, 0x5e, 0xa4, 0x0f, 0x53, 0xe1, 0xbc, 0xb4, 0xc9, 0x37,
+  0x0e, 0x75, 0xdd, 0x93, 0xe8, 0x0f, 0x18, 0x0a, 0x02, 0x83, 0x17, 0x74, 0xbb,
+  0x1a, 0x42, 0x5b, 0x63, 0x2c, 0x80, 0x80, 0xa6, 0x84, 0xa0, 0x59, 0x01, 0x00,
+  0x67, 0xbe, 0xe4, 0x81, 0xed, 0x1e, 0xce, 0x7d, 0x18, 0xf5, 0x85, 0xa2, 0xcb,
+  0x1d, 0x75, 0x6f, 0x8a, 0x34, 0xaa, 0x6b, 0x58, 0x91, 0xd2, 0xa4, 0x58, 0x4f,
+  0xe1, 0x8b, 0x6a, 0x36, 0xe1, 0x67, 0x23, 0x2c, 0x5d, 0x7e, 0x05, 0xe2, 0xa0,
+  0x18, 0xa8, 0x78, 0x7d, 0x85, 0xda, 0x07, 0x60, 0xc6, 0x8e, 0x44, 0x14, 0xad,
+  0xbc, 0x35, 0x2f, 0xf3, 0xd8, 0xda, 0x34, 0x65, 0x12, 0x45, 0x6a, 0xbe, 0x46,
+  0x53, 0x09, 0xc8, 0xcc, 0x96, 0x6b, 0x07, 0xd4, 0xc3, 0x4f, 0xd2, 0x7b, 0x88,
+  0xad, 0x10, 0x3b, 0x93, 0x3c, 0x9a, 0xc4, 0x1a, 0x98, 0x12, 0x2f, 0xf9, 0xc9,
+  0xb9, 0xd2, 0xda, 0x40, 0xe9, 0x9e, 0xd8, 0x74, 0x2f, 0x02, 0xf1, 0xf0, 0x9a,
+  0x31, 0x99, 0xb4, 0x82, 0xe1, 0x25, 0xee, 0x3f, 0xf9, 0xd5, 0xbb, 0x10, 0x8b,
+  0xff, 0x03, 0x0f, 0xcb, 0x96, 0x8f, 0x29, 0x51, 0x71, 0xfc, 0xe2, 0x0e, 0x9c,
+  0xf7, 0x3d, 0xc0, 0x95, 0xc6, 0x70, 0xfd, 0x8c, 0xb7, 0xf6, 0xa7, 0xfa, 0x7d,
+  0xd6, 0x44, 0x0b, 0xa3, 0xd3, 0x97, 0xf5, 0xcd, 0x6d, 0xc9, 0x17, 0xc6, 0xcb,
+  0xd5, 0x82, 0x01, 0x0e, 0xef, 0xb3, 0xbd, 0x33, 0x6e, 0x49, 0x57, 0xb1, 0x38,
+  0x57, 0x27, 0x91, 0x22, 0x5a, 0xeb, 0x02, 0x97, 0x53, 0xeb, 0x56, 0x01, 0xdc,
+  0xf9, 0xe9, 0x6c, 0x38, 0x7c, 0x0b, 0x1c, 0x7e, 0x19, 0xc7, 0x4b, 0x9d, 0x30,
+  0xad, 0x14, 0x2a, 0xb2, 0x07, 0x99, 0x80, 0x40, 0x42, 0x82, 0x49, 0x4e, 0xb5,
+  0x1a, 0x49, 0xa3, 0x31, 0x7f, 0xd9, 0x78, 0xd1, 0x08, 0x39, 0xaf, 0x0d, 0xeb,
+  0x8a, 0x93, 0x43, 0xab, 0x3d, 0x3f, 0x9b, 0xe3, 0x25, 0x3b, 0x09, 0xa9, 0x00,
+  0xfc, 0x98, 0xb9, 0xdc, 0x73, 0x91, 0x87, 0x58, 0x53, 0xd4, 0xc1, 0x8b, 0x05,
+  0xe6, 0x85, 0xc8, 0x48, 0xb8, 0x7e, 0x23, 0xcf, 0x12
+};
+
+// The RSA intermediate certificate that issued the EE cert used in the
+// signature above. The certificate was generated with pycert.py
+const uint8_t RSA_INT[] = {
+  0x30, 0x82, 0x02, 0xd0, 0x30, 0x82, 0x01, 0xba, 0xa0, 0x03, 0x02, 0x01, 0x02,
+  0x02, 0x14, 0x07, 0x10, 0xaf, 0xc4, 0x1a, 0x3a, 0x56, 0x4f, 0xd8, 0xc2, 0xcc,
+  0x46, 0xd7, 0x5b, 0xdf, 0x1c, 0x4e, 0x2f, 0x49, 0x3a, 0x30, 0x0b, 0x06, 0x09,
+  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x30, 0x13, 0x31, 0x11,
+  0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f, 0x6f, 0x74,
+  0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30,
+  0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32,
+  0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x5a, 0x30, 0x12, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+  0x07, 0x69, 0x6e, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22, 0x30,
+  0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+  0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01,
+  0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd, 0x6e,
+  0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4, 0x35, 0x4a,
+  0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7, 0x25, 0xa8, 0xe0,
+  0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a, 0x86, 0xf2, 0x6b, 0xe2,
+  0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08, 0x7a, 0xa5, 0x5a, 0xa7, 0x45,
+  0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02, 0x7e, 0xcd, 0x43, 0xfc, 0x1e, 0x69,
+  0xd0, 0x38, 0x20, 0x29, 0x93, 0xab, 0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9, 0x4c,
+  0xc2, 0x6b, 0x6c, 0x0e, 0xed, 0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69, 0x1a,
+  0xb1, 0xd3, 0x02, 0x3a, 0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f, 0x0d,
+  0x8d, 0xfd, 0x66, 0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88, 0x61,
+  0x79, 0x90, 0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48, 0x1f,
+  0xa8, 0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66, 0x5a,
+  0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc, 0x1c,
+  0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0, 0x75, 0x31,
+  0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d, 0x25, 0xd3, 0x09,
+  0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b, 0x2f, 0x22, 0x6f, 0x69,
+  0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26, 0xd6, 0x25, 0x9d, 0xab, 0x91,
+  0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04, 0x2c, 0xbf, 0x16, 0x8b, 0x2f, 0xe5,
+  0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8, 0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72, 0x51,
+  0xc4, 0x31, 0xd5, 0x03, 0xac, 0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02, 0x03,
+  0x01, 0x00, 0x01, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d,
+  0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03, 0x55,
+  0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09, 0x2a,
+  0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01, 0x00,
+  0x5e, 0xba, 0x69, 0x55, 0x9f, 0xf8, 0xeb, 0x16, 0x21, 0x98, 0xde, 0xb7, 0x31,
+  0x3e, 0x66, 0xe1, 0x3b, 0x0c, 0x29, 0xf7, 0x48, 0x73, 0x05, 0xd9, 0xce, 0x5e,
+  0x4c, 0xbe, 0x03, 0xc4, 0x51, 0xd6, 0x21, 0x92, 0x40, 0x38, 0xaa, 0x5b, 0x28,
+  0xb5, 0xa1, 0x10, 0x52, 0x57, 0xff, 0x91, 0x54, 0x82, 0x86, 0x9e, 0x74, 0xd5,
+  0x3d, 0x82, 0x29, 0xee, 0xd1, 0xcf, 0x93, 0xb1, 0x24, 0x76, 0xbb, 0x95, 0x41,
+  0x06, 0x7e, 0x40, 0x9b, 0xb4, 0xab, 0x44, 0x34, 0x10, 0x8f, 0xb1, 0x51, 0x6f,
+  0xc0, 0x89, 0xd1, 0xa3, 0xc4, 0x9f, 0xb3, 0x48, 0xe1, 0xcd, 0x73, 0xad, 0xff,
+  0x42, 0x5f, 0x76, 0x05, 0x60, 0xc5, 0xe0, 0x45, 0x79, 0x18, 0xa1, 0x19, 0xb8,
+  0xa7, 0x3a, 0x64, 0xb3, 0x19, 0xba, 0x14, 0xa1, 0xb5, 0xdc, 0x32, 0xec, 0x09,
+  0x39, 0x58, 0x54, 0x5b, 0x04, 0xdc, 0x1b, 0x66, 0x0d, 0x1d, 0x0d, 0xce, 0x7f,
+  0xfa, 0x24, 0x52, 0x6a, 0xad, 0xe2, 0xc8, 0x30, 0xaf, 0xf2, 0xaf, 0x63, 0xc5,
+  0xe2, 0xbf, 0xe2, 0x20, 0x1b, 0x9e, 0xf9, 0x3d, 0xbc, 0xfb, 0x04, 0x8e, 0xda,
+  0x7a, 0x1a, 0x5d, 0xd3, 0x13, 0xd7, 0x00, 0x8e, 0x9b, 0x5d, 0x85, 0x51, 0xda,
+  0xd3, 0x91, 0x25, 0xf5, 0x67, 0x85, 0x3e, 0x25, 0x89, 0x5e, 0xcb, 0x89, 0x8a,
+  0xec, 0x8a, 0xde, 0x8b, 0xf4, 0x33, 0x5f, 0x76, 0xdb, 0x3d, 0xfc, 0x6a, 0x05,
+  0x21, 0x43, 0xb2, 0x41, 0xd8, 0x33, 0x8d, 0xfd, 0x05, 0x5c, 0x22, 0x0a, 0xf6,
+  0x90, 0x65, 0x9c, 0x4f, 0x8c, 0x44, 0x9f, 0x2d, 0xca, 0xf3, 0x49, 0x9c, 0x3a,
+  0x14, 0x88, 0xab, 0xe4, 0xce, 0xb7, 0xbc, 0x95, 0x22, 0x2e, 0xb1, 0x82, 0x4c,
+  0xbf, 0x83, 0x3e, 0x49, 0x72, 0x03, 0x2a, 0x68, 0xe7, 0x2d, 0xe5, 0x2d, 0x4b,
+  0x61, 0xb0, 0x8d, 0x0d, 0x0c, 0x87, 0xc6, 0x5c, 0x51
+};
+
+// The RSA root certificate that issued the RSA intermediate certificate above.
+// The certificate was generated with pycert.py
+const uint8_t RSA_ROOT[] = {
+  0x30, 0x82, 0x02, 0xd1, 0x30, 0x82, 0x01, 0xbb, 0xa0, 0x03, 0x02, 0x01, 0x02,
+  0x02, 0x14, 0x29, 0x6c, 0x1a, 0xd8, 0x20, 0xcd, 0x74, 0x6d, 0x4b, 0x00, 0xf3,
+  0x16, 0x88, 0xd9, 0x66, 0x87, 0x5f, 0x28, 0x56, 0x6a, 0x30, 0x0b, 0x06, 0x09,
+  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x30, 0x13, 0x31, 0x11,
+  0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08, 0x72, 0x6f, 0x6f, 0x74,
+  0x2d, 0x72, 0x73, 0x61, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30,
+  0x31, 0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32,
+  0x30, 0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x5a, 0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c,
+  0x08, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x72, 0x73, 0x61, 0x30, 0x82, 0x01, 0x22,
+  0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+  0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82,
+  0x01, 0x01, 0x00, 0xba, 0x88, 0x51, 0xa8, 0x44, 0x8e, 0x16, 0xd6, 0x41, 0xfd,
+  0x6e, 0xb6, 0x88, 0x06, 0x36, 0x10, 0x3d, 0x3c, 0x13, 0xd9, 0xea, 0xe4, 0x35,
+  0x4a, 0xb4, 0xec, 0xf5, 0x68, 0x57, 0x6c, 0x24, 0x7b, 0xc1, 0xc7, 0x25, 0xa8,
+  0xe0, 0xd8, 0x1f, 0xbd, 0xb1, 0x9c, 0x06, 0x9b, 0x6e, 0x1a, 0x86, 0xf2, 0x6b,
+  0xe2, 0xaf, 0x5a, 0x75, 0x6b, 0x6a, 0x64, 0x71, 0x08, 0x7a, 0xa5, 0x5a, 0xa7,
+  0x45, 0x87, 0xf7, 0x1c, 0xd5, 0x24, 0x9c, 0x02, 0x7e, 0xcd, 0x43, 0xfc, 0x1e,
+  0x69, 0xd0, 0x38, 0x20, 0x29, 0x93, 0xab, 0x20, 0xc3, 0x49, 0xe4, 0xdb, 0xb9,
+  0x4c, 0xc2, 0x6b, 0x6c, 0x0e, 0xed, 0x15, 0x82, 0x0f, 0xf1, 0x7e, 0xad, 0x69,
+  0x1a, 0xb1, 0xd3, 0x02, 0x3a, 0x8b, 0x2a, 0x41, 0xee, 0xa7, 0x70, 0xe0, 0x0f,
+  0x0d, 0x8d, 0xfd, 0x66, 0x0b, 0x2b, 0xb0, 0x24, 0x92, 0xa4, 0x7d, 0xb9, 0x88,
+  0x61, 0x79, 0x90, 0xb1, 0x57, 0x90, 0x3d, 0xd2, 0x3b, 0xc5, 0xe0, 0xb8, 0x48,
+  0x1f, 0xa8, 0x37, 0xd3, 0x88, 0x43, 0xef, 0x27, 0x16, 0xd8, 0x55, 0xb7, 0x66,
+  0x5a, 0xaa, 0x7e, 0x02, 0x90, 0x2f, 0x3a, 0x7b, 0x10, 0x80, 0x06, 0x24, 0xcc,
+  0x1c, 0x6c, 0x97, 0xad, 0x96, 0x61, 0x5b, 0xb7, 0xe2, 0x96, 0x12, 0xc0, 0x75,
+  0x31, 0xa3, 0x0c, 0x91, 0xdd, 0xb4, 0xca, 0xf7, 0xfc, 0xad, 0x1d, 0x25, 0xd3,
+  0x09, 0xef, 0xb9, 0x17, 0x0e, 0xa7, 0x68, 0xe1, 0xb3, 0x7b, 0x2f, 0x22, 0x6f,
+  0x69, 0xe3, 0xb4, 0x8a, 0x95, 0x61, 0x1d, 0xee, 0x26, 0xd6, 0x25, 0x9d, 0xab,
+  0x91, 0x08, 0x4e, 0x36, 0xcb, 0x1c, 0x24, 0x04, 0x2c, 0xbf, 0x16, 0x8b, 0x2f,
+  0xe5, 0xf1, 0x8f, 0x99, 0x17, 0x31, 0xb8, 0xb3, 0xfe, 0x49, 0x23, 0xfa, 0x72,
+  0x51, 0xc4, 0x31, 0xd5, 0x03, 0xac, 0xda, 0x18, 0x0a, 0x35, 0xed, 0x8d, 0x02,
+  0x03, 0x01, 0x00, 0x01, 0xa3, 0x1d, 0x30, 0x1b, 0x30, 0x0c, 0x06, 0x03, 0x55,
+  0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0b, 0x06, 0x03,
+  0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x0b, 0x06, 0x09,
+  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x03, 0x82, 0x01, 0x01,
+  0x00, 0x23, 0x2f, 0x9f, 0x72, 0xeb, 0x70, 0x6d, 0x9e, 0x3e, 0x9f, 0xd7, 0x9c,
+  0xd9, 0x19, 0x7c, 0x99, 0x07, 0xc5, 0x5c, 0x9d, 0xf5, 0x66, 0x9f, 0x28, 0x8d,
+  0xfe, 0x0e, 0x3f, 0x38, 0x75, 0xed, 0xee, 0x4e, 0x3f, 0xf6, 0x6e, 0x35, 0xe0,
+  0x95, 0x3f, 0x08, 0x4a, 0x71, 0x5a, 0xf2, 0x4f, 0xc9, 0x96, 0x61, 0x8d, 0x45,
+  0x4b, 0x97, 0x85, 0xff, 0xb0, 0xe3, 0xbb, 0xb5, 0xd7, 0x7e, 0xfb, 0xd2, 0xfc,
+  0xec, 0xfe, 0x42, 0x9f, 0x4e, 0x7b, 0xbf, 0x97, 0xbb, 0xb4, 0x3a, 0x93, 0x0b,
+  0x13, 0x61, 0x90, 0x0c, 0x3a, 0xce, 0xf7, 0x8e, 0xef, 0x80, 0xf5, 0x4a, 0x92,
+  0xc5, 0xa5, 0x03, 0x78, 0xc2, 0xee, 0xb8, 0x66, 0x60, 0x6b, 0x76, 0x4f, 0x32,
+  0x5a, 0x1a, 0xa2, 0x4b, 0x7e, 0x2b, 0xa6, 0x1a, 0x89, 0x01, 0xe3, 0xbb, 0x55,
+  0x13, 0x7c, 0x4c, 0xf4, 0x6a, 0x99, 0x94, 0xd1, 0xa0, 0x84, 0x1c, 0x1a, 0xc2,
+  0x7b, 0xb4, 0xa0, 0xb0, 0x3b, 0xdc, 0x5a, 0x7b, 0xc7, 0xe0, 0x44, 0xb2, 0x1f,
+  0x46, 0xd5, 0x8b, 0x39, 0x8b, 0xdc, 0x9e, 0xce, 0xa8, 0x7f, 0x85, 0x1d, 0x4b,
+  0x63, 0x06, 0x1e, 0x8e, 0xe5, 0xe5, 0x99, 0xd9, 0xf7, 0x4d, 0x89, 0x0b, 0x1d,
+  0x5c, 0x27, 0x33, 0x66, 0x21, 0xcf, 0x9a, 0xbd, 0x98, 0x68, 0x23, 0x3a, 0x66,
+  0x9d, 0xd4, 0x46, 0xed, 0x63, 0x58, 0xf3, 0x42, 0xe4, 0x1d, 0xe2, 0x47, 0x65,
+  0x13, 0x8d, 0xd4, 0x1f, 0x4b, 0x7e, 0xde, 0x11, 0x56, 0xf8, 0x6d, 0x01, 0x0c,
+  0x99, 0xbd, 0x8d, 0xca, 0x8a, 0x2e, 0xe3, 0x8a, 0x9c, 0x3d, 0x83, 0x8d, 0x69,
+  0x62, 0x8d, 0x05, 0xea, 0xb7, 0xf5, 0xa3, 0x4b, 0xfc, 0x96, 0xcf, 0x18, 0x21,
+  0x0a, 0xc7, 0xf3, 0x23, 0x7e, 0x1c, 0xab, 0xe2, 0xa2, 0xd1, 0x83, 0xc4, 0x25,
+  0x93, 0x37, 0x80, 0xca, 0xda, 0xf0, 0xef, 0x7d, 0x94, 0xb5
+};
+
+// The P256 intermediate certificate that issued the EE cert used in the
+// signatures above. The certificate was generated with pycert.py
+const uint8_t P256_INT[] = {
+  0x30, 0x82, 0x01, 0x48, 0x30, 0x81, 0xf0, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+  0x14, 0x43, 0x63, 0x59, 0xad, 0x04, 0x34, 0x56, 0x80, 0x43, 0xec, 0x90, 0x6a,
+  0xd4, 0x10, 0x64, 0x7c, 0x7f, 0x38, 0x32, 0xe2, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+  0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
+  0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70,
+  0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31,
+  0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30,
+  0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
+  0x30, 0x13, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x08,
+  0x69, 0x6e, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06,
+  0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+  0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb, 0xbb,
+  0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2, 0xec,
+  0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79, 0x4b,
+  0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d, 0x07,
+  0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b, 0x2d,
+  0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b, 0x30,
+  0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
+  0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06,
+  0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
+  0x47, 0x00, 0x30, 0x44, 0x02, 0x20, 0x63, 0x59, 0x02, 0x01, 0x89, 0xd7, 0x3e,
+  0x5b, 0xff, 0xd1, 0x16, 0x4e, 0xe3, 0xe2, 0x0a, 0xe0, 0x4a, 0xd8, 0x75, 0xaf,
+  0x77, 0x5c, 0x93, 0x60, 0xba, 0x10, 0x1f, 0x97, 0xdd, 0x27, 0x2d, 0x24, 0x02,
+  0x20, 0x3d, 0x87, 0x0f, 0xac, 0x22, 0x4d, 0x16, 0xd9, 0xa1, 0x95, 0xbb, 0x56,
+  0xe0, 0x21, 0x05, 0x93, 0xd1, 0x07, 0xb5, 0x25, 0x3b, 0xf4, 0x57, 0x20, 0x87,
+  0x13, 0xa2, 0xf7, 0x78, 0x15, 0x30, 0xa7
+};
+
+// The P256 root certificate that issued the P256 intermediate certificate
+// above. The certificate was generated with pycert.py
+const uint8_t P256_ROOT[] = {
+  0x30, 0x82, 0x01, 0x4a, 0x30, 0x81, 0xf1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
+  0x14, 0x5f, 0x3f, 0xae, 0x90, 0x49, 0x30, 0x2f, 0x33, 0x6e, 0x95, 0x23, 0xa7,
+  0xcb, 0x23, 0xd7, 0x65, 0x4f, 0xea, 0x3c, 0xf7, 0x30, 0x0a, 0x06, 0x08, 0x2a,
+  0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x14, 0x31, 0x12, 0x30, 0x10,
+  0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09, 0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70,
+  0x32, 0x35, 0x36, 0x30, 0x22, 0x18, 0x0f, 0x32, 0x30, 0x31, 0x32, 0x30, 0x31,
+  0x30, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x32, 0x30,
+  0x32, 0x31, 0x31, 0x32, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
+  0x30, 0x14, 0x31, 0x12, 0x30, 0x10, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x09,
+  0x72, 0x6f, 0x6f, 0x74, 0x2d, 0x70, 0x32, 0x35, 0x36, 0x30, 0x59, 0x30, 0x13,
+  0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86,
+  0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x4f, 0xbf, 0xbb,
+  0xbb, 0x61, 0xe0, 0xf8, 0xf9, 0xb1, 0xa6, 0x0a, 0x59, 0xac, 0x87, 0x04, 0xe2,
+  0xec, 0x05, 0x0b, 0x42, 0x3e, 0x3c, 0xf7, 0x2e, 0x92, 0x3f, 0x2c, 0x4f, 0x79,
+  0x4b, 0x45, 0x5c, 0x2a, 0x69, 0xd2, 0x33, 0x45, 0x6c, 0x36, 0xc4, 0x11, 0x9d,
+  0x07, 0x06, 0xe0, 0x0e, 0xed, 0xc8, 0xd1, 0x93, 0x90, 0xd7, 0x99, 0x1b, 0x7b,
+  0x2d, 0x07, 0xa3, 0x04, 0xea, 0xa0, 0x4a, 0xa6, 0xc0, 0xa3, 0x1d, 0x30, 0x1b,
+  0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01,
+  0xff, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x01,
+  0x06, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
+  0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x5c, 0x75, 0x51, 0x9f, 0x13, 0x11,
+  0x50, 0xcd, 0x5d, 0x8a, 0xde, 0x20, 0xa3, 0xbc, 0x06, 0x30, 0x91, 0xff, 0xb2,
+  0x73, 0x75, 0x5f, 0x31, 0x64, 0xec, 0xfd, 0xcb, 0x42, 0x80, 0x0a, 0x70, 0xe6,
+  0x02, 0x21, 0x00, 0xc2, 0xe4, 0xc1, 0xa8, 0xe2, 0x89, 0xdc, 0xa1, 0xbb, 0xe7,
+  0xd5, 0x4f, 0x5c, 0x88, 0xad, 0xeb, 0xa4, 0x78, 0xa1, 0x19, 0xbe, 0x22, 0x54,
+  0xc8, 0x9f, 0xef, 0xb8, 0x5d, 0xa2, 0x40, 0xd9, 0x8b
+};
+
+void
+check_hard_coded_certs(const uint8_t** cert_chain,
+                       size_t cert_chain_len,
+                       const size_t* certs_len)
+{
+  // Very hacky and fragile check that the intermediate certs are correct.
+  switch (cert_chain_len) {
+    case 2: {
+      const uint8_t* cert = cert_chain[0];
+      size_t cert_len = certs_len[0];
+      ASSERT_EQ(cert_len, sizeof(P256_ROOT));
+      ASSERT_EQ(0, memcmp(cert, P256_ROOT, cert_len));
+      cert = cert_chain[1];
+      cert_len = certs_len[1];
+      ASSERT_EQ(cert_len, sizeof(P256_INT));
+      ASSERT_EQ(0, memcmp(cert, P256_INT, cert_len));
+      break;
+    }
+    case 4: {
+      const uint8_t* cert = cert_chain[0];
+      size_t cert_len = certs_len[0];
+      ASSERT_EQ(cert_len, sizeof(P256_ROOT));
+      ASSERT_EQ(0, memcmp(cert, P256_ROOT, cert_len));
+      cert = cert_chain[1];
+      cert_len = certs_len[1];
+      ASSERT_EQ(cert_len, sizeof(P256_INT));
+      ASSERT_EQ(0, memcmp(cert, P256_INT, cert_len));
+      cert = cert_chain[2];
+      cert_len = certs_len[2];
+      ASSERT_EQ(cert_len, sizeof(RSA_ROOT));
+      ASSERT_EQ(0, memcmp(cert, RSA_ROOT, cert_len));
+      cert = cert_chain[3];
+      cert_len = certs_len[3];
+      ASSERT_EQ(cert_len, sizeof(RSA_INT));
+      ASSERT_EQ(0, memcmp(cert, RSA_INT, cert_len));
+      break;
+    }
+    default:
+      // In this case something went wrong.
+      ASSERT_EQ(true, false);
+  }
+}
+
+/* Verification function called from cose-rust.
+ * Returns true if everything goes well and the signature is good, false in any
+ * other case. */
+bool
+verify_callback(const uint8_t* payload,
+                size_t payload_len,
+                const uint8_t** cert_chain,
+                size_t cert_chain_len,
+                const size_t* certs_len,
+                const uint8_t* ee_cert,
+                size_t ee_cert_len,
+                const uint8_t* signature,
+                size_t signature_len,
+                uint8_t signature_algorithm)
+{
+  UniquePK11SlotInfo slot(PK11_GetInternalSlot());
+  if (!slot) {
+    return false;
+  }
+
+  CK_MECHANISM_TYPE mechanism;
+  SECOidTag oid;
+  uint32_t hash_length;
+  SECItem param = { siBuffer, nullptr, 0 };
+  CK_RSA_PKCS_PSS_PARAMS rsa_pss_params = { CKM_SHA256, CKG_MGF1_SHA256, SHA256_LENGTH };
+  switch (signature_algorithm) {
+    case (ES256):
+      mechanism = CKM_ECDSA;
+      oid = SEC_OID_SHA256;
+      hash_length = SHA256_LENGTH;
+      break;
+    case (PS256):
+      mechanism = CKM_RSA_PKCS_PSS;
+      oid = SEC_OID_SHA256;
+      hash_length = SHA256_LENGTH;
+      param = { siBuffer,
+                reinterpret_cast<unsigned char*>(&rsa_pss_params),
+                sizeof(rsa_pss_params) };
+      break;
+    default:
+      return false;
+  }
+  check_hard_coded_certs(cert_chain, cert_chain_len, certs_len);
+
+  uint8_t hash_buf[HASH_LENGTH_MAX];
+  SECStatus rv = PK11_HashBuf(oid, hash_buf, payload, payload_len);
+  if (rv != SECSuccess) {
+    return false;
+  }
+  SECItem hash_item = { siBuffer, hash_buf, hash_length };
+  CERTCertDBHandle* db_handle = CERT_GetDefaultCertDB();
+  if (!db_handle) {
+    return false;
+  }
+  SECItem der_cert = { siBuffer,
+                       const_cast<uint8_t*>(ee_cert),
+                       static_cast<unsigned int>(ee_cert_len) };
+  UniqueCERTCertificate cert(
+    CERT_NewTempCertificate(db_handle, &der_cert, nullptr, false, true));
+  if (!cert) {
+    return false;
+  }
+  UniqueSECKEYPublicKey key(CERT_ExtractPublicKey(cert.get()));
+  if (!key) {
+    return false;
+  }
+  SECItem signature_item = { siBuffer,
+                             const_cast<uint8_t*>(signature),
+                             static_cast<unsigned int>(signature_len) };
+  rv = PK11_VerifyWithMechanism(
+    key.get(), mechanism, &param, &signature_item, &hash_item, nullptr);
+  if (rv != SECSuccess) {
+    return false;
+  }
+
+  return true;
+}
+
+class psm_COSE : public ::testing::Test
+{
+};
+
+TEST_F(psm_COSE, CoseTestingSingleSignature)
+{
+  SECStatus rv = NSS_NoDB_Init(nullptr);
+  ASSERT_EQ(SECSuccess, rv);
+  bool result = verify_cose_signature_ffi(
+    PAYLOAD, sizeof(PAYLOAD), SIGNATURE, sizeof(SIGNATURE), verify_callback);
+  ASSERT_TRUE(result);
+}
+
+TEST_F(psm_COSE, CoseTestingTwoSignatures)
+{
+  SECStatus rv = NSS_NoDB_Init(nullptr);
+  ASSERT_EQ(SECSuccess, rv);
+  bool result = verify_cose_signature_ffi(PAYLOAD,
+                                          sizeof(PAYLOAD),
+                                          SIGNATURE_ES256_PS256,
+                                          sizeof(SIGNATURE_ES256_PS256),
+                                          verify_callback);
+  ASSERT_TRUE(result);
+}
+
+TEST_F(psm_COSE, CoseTestingAlteredPayload)
+{
+  SECStatus rv = NSS_NoDB_Init(nullptr);
+  ASSERT_EQ(SECSuccess, rv);
+  uint8_t altered_payload[20] = { 84,  104, 105, 115, 32,  104, 115,
+                                  32,  116, 104, 101, 32,  99,  111,
+                                  110, 116, 101, 110, 116, 46 };
+  bool result = verify_cose_signature_ffi(altered_payload,
+                                          sizeof(altered_payload),
+                                          SIGNATURE_ES256_PS256,
+                                          sizeof(SIGNATURE_ES256_PS256),
+                                          verify_callback);
+  ASSERT_FALSE(result);
+}
+
+} // namespace mozilla
--- a/security/manager/ssl/tests/gtest/moz.build
+++ b/security/manager/ssl/tests/gtest/moz.build
@@ -2,28 +2,30 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SOURCES += [
     'CertDBTest.cpp',
     'CertListTest.cpp',
+    'CoseTest.cpp',
     'DataStorageTest.cpp',
     'DeserializeCertTest.cpp',
     'MD4Test.cpp',
     'OCSPCacheTest.cpp',
     'TLSIntoleranceTest.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '/security/certverifier',
     '/security/manager/ssl',
     '/security/pkix/include',
     '/security/pkix/test/lib',
+    '/third_party/rust/cose-c/include',
 ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul-gtest'
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wno-error=shadow']
--- a/taskcluster/ci/test/mochitest.yml
+++ b/taskcluster/ci/test/mochitest.yml
@@ -192,20 +192,16 @@ mochitest-chrome:
             default: default
 
 mochitest-clipboard:
     description: "Mochitest clipboard run"
     suite: mochitest/clipboard
     treeherder-symbol: tc-M(cl)
     loopback-video: true
     instance-size: xlarge
-    worker-type:
-        by-test-platform:
-            windows7-32.*: buildbot-bridge/buildbot-bridge
-            default: null
     e10s:
         by-test-platform:
             windows7-32/debug: both
             default: true
     mozharness:
         mochitest-flavor: plain
         config:
             by-test-platform:
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -323,20 +323,39 @@ def call(*args, **kwargs):
     # https://bugzilla.mozilla.org/show_bug.cgi?id=791383
     process = mozprocess.ProcessHandler(*args, **kwargs)
     process.run()
     return process.wait()
 
 
 def killPid(pid, log):
     # see also https://bugzilla.mozilla.org/show_bug.cgi?id=911249#c58
-    try:
-        os.kill(pid, getattr(signal, "SIGKILL", signal.SIGTERM))
-    except Exception as e:
-        log.info("Failed to kill process %d: %s" % (pid, str(e)))
+
+    if HAVE_PSUTIL:
+        # Kill a process tree (including grandchildren) with signal.SIGTERM
+        if pid == os.getpid():
+            raise RuntimeError("Error: trying to kill ourselves, not another process")
+        try:
+            parent = psutil.Process(pid)
+            children = parent.children(recursive=True)
+            children.append(parent)
+            for p in children:
+                p.send_signal(signal.SIGTERM)
+            gone, alive = psutil.wait_procs(children, timeout=30)
+            for p in gone:
+                log.info('psutil found pid %s dead' % p.pid)
+            for p in alive:
+                log.info('failed to kill pid %d after 30s' % p.pid)
+        except Exception as e:
+            log.info("Error: Failed to kill process %d: %s" % (pid, str(e)))
+    else:
+        try:
+            os.kill(pid, getattr(signal, "SIGKILL", signal.SIGTERM))
+        except Exception as e:
+            log.info("Failed to kill process %d: %s" % (pid, str(e)))
 
 
 if mozinfo.isWin:
     import ctypes.wintypes
 
     def isPidAlive(pid):
         STILL_ACTIVE = 259
         PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
@@ -1665,17 +1684,18 @@ toolbar#nav-bar {
                 try:
                     if proc.name() == pname:
                         procd = proc.as_dict(attrs=['pid', 'ppid', 'name', 'username'])
                         if proc.ppid() == 1 or not orphans:
                             self.log.info("killing %s" % procd)
                             killPid(proc.pid, self.log)
                         else:
                             self.log.info("NOT killing %s (not an orphan?)" % procd)
-                except:
+                except Exception as e:
+                    self.log.info("Warning: Unable to kill process %s: %s" % (pname, str(e)))
                     # may not be able to access process info for all processes
                     continue
         else:
             def _psInfo(line):
                 if pname in line:
                     self.log.info(line)
 
             process = mozprocess.ProcessHandler(['ps', '-f'],
--- a/testing/mozharness/scripts/desktop_unittest.py
+++ b/testing/mozharness/scripts/desktop_unittest.py
@@ -658,16 +658,81 @@ class DesktopUnittest(TestingMixin, Merc
         self._stage_files()
         dirs = self.query_abs_dirs()
         modules = ['jsbridge', 'mozmill']
         for module in modules:
             self.install_module(module=os.path.join(dirs['abs_mozmill_dir'],
                                                     'resources',
                                                     module))
 
+    def _kill_proc_tree(self, pid):
+        # Kill a process tree (including grandchildren) with signal.SIGTERM
+        try:
+            import signal
+            import psutil
+            if pid == os.getpid():
+                return (None, None)
+
+            parent = psutil.Process(pid)
+            children = parent.children(recursive=True)
+            children.append(parent)
+
+            for p in children:
+                p.send_signal(signal.SIGTERM)
+
+            # allow for 60 seconds to kill procs
+            timeout = 60
+            gone, alive = psutil.wait_procs(children, timeout=timeout)
+            for p in gone:
+                self.info('psutil found pid %s dead' % p.pid)
+            for p in alive:
+                self.error('failed to kill pid %d after %d' % (p.pid, timeout))
+
+            return (gone, alive)
+        except Exception as e:
+            self.error('Exception while trying to kill process tree: %s' % str(e))
+
+    def _kill_named_proc(self, pname):
+        try:
+            import psutil
+        except Exception as e:
+            self.info("Error importing psutil, not killing process %s: %s" % pname, str(e))
+            return
+
+        for proc in psutil.process_iter():
+            try:
+                if proc.name() == pname:
+                    procd = proc.as_dict(attrs=['pid', 'ppid', 'name', 'username'])
+                    self.info("in _kill_named_proc, killing %s" % procd)
+                    self._kill_proc_tree(proc.pid)
+            except Exception as e:
+                self.info("Warning: Unable to kill process %s: %s" % (pname, str(e)))
+                # may not be able to access process info for all processes
+                continue
+
+    def _remove_xen_clipboard(self):
+        """
+            When running on a Windows 7 VM, we have XenDPriv.exe running which
+            interferes with the clipboard, lets terminate this process and remove
+            the binary so it doesn't restart
+        """
+        if not self._is_windows():
+            return
+
+        self._kill_named_proc('XenDPriv.exe')
+        xenpath = os.path.join(os.environ['ProgramFiles'],
+                               'Citrix',
+                               'XenTools',
+                               'XenDPriv.exe')
+        try:
+            if os.path.isfile(xenpath):
+                os.remove(xenpath)
+        except Exception as e:
+            self.error("Error: Failure to remove file %s: %s" % (xenpath, str(e)))
+
     def _report_system_info(self):
         """
            Create the system-info.log artifact file, containing a variety of
            system information that might be useful in diagnosing test failures.
         """
         try:
             import psutil
             dir = self.query_abs_dirs()['abs_blob_upload_dir']
@@ -699,16 +764,17 @@ class DesktopUnittest(TestingMixin, Merc
         except:
             # psutil throws a variety of intermittent exceptions
             self.info("Unable to complete system-info.log: %s" % sys.exc_info()[0])
 
     # pull defined in VCSScript.
     # preflight_run_tests defined in TestingMixin.
 
     def run_tests(self):
+        self._remove_xen_clipboard()
         self._report_system_info()
         self.start_time = datetime.now()
         for category in SUITE_CATEGORIES:
             if not self._run_category_suites(category):
                 break
 
     def get_timeout_for_category(self, suite_category):
         if suite_category == 'cppunittest':
--- a/testing/web-platform/meta/html/dom/interfaces.html.ini
+++ b/testing/web-platform/meta/html/dom/interfaces.html.ini
@@ -1067,28 +1067,22 @@
     expected: FAIL
 
   [HTMLButtonElement interface: document.createElement("button") must inherit property "menu" with the proper type (11)]
     expected: FAIL
 
   [HTMLButtonElement interface: document.createElement("button") must inherit property "labels" with the proper type (18)]
     expected: FAIL
 
-  [HTMLTextAreaElement interface: attribute autocomplete]
-    expected: FAIL
-
   [HTMLTextAreaElement interface: attribute dirName]
     expected: FAIL
 
   [HTMLTextAreaElement interface: attribute inputMode]
     expected: FAIL
 
-  [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type (0)]
-    expected: FAIL
-
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "dirName" with the proper type (3)]
     expected: FAIL
 
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type (6)]
     expected: FAIL
 
   [HTMLKeygenElement interface: existence and properties of interface object]
     expected: FAIL
@@ -3815,19 +3809,16 @@
     expected: FAIL
 
   [HTMLInputElement interface: createInput("reset") must inherit property "dirName" with the proper type]
     expected: FAIL
 
   [HTMLInputElement interface: createInput("button") must inherit property "dirName" with the proper type]
     expected: FAIL
 
-  [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "autocomplete" with the proper type]
-    expected: FAIL
-
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "dirName" with the proper type]
     expected: FAIL
 
   [HTMLTextAreaElement interface: document.createElement("textarea") must inherit property "inputMode" with the proper type]
     expected: FAIL
 
   [HTMLScriptElement interface: document.createElement("script") must inherit property "noModule" with the proper type]
     expected: FAIL
--- a/testing/web-platform/meta/html/dom/reflection-forms.html.ini
+++ b/testing/web-platform/meta/html/dom/reflection-forms.html.ini
@@ -3458,67 +3458,16 @@
     expected: FAIL
 
   [input.inputMode: IDL set to "KANA-NAME"]
     expected: FAIL
 
   [input.inputMode: IDL set to "Kana-name"]
     expected: FAIL
 
-  [textarea.autocomplete: typeof IDL attribute]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL get with DOM attribute unset]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to ""]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f  foo "]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to undefined]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to 7]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to 1.5]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to true]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to false]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to object "[object Object\]"]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to NaN]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to Infinity]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to -Infinity]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to "\\0"]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to null]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to object "test-toString"]
-    expected: FAIL
-
-  [textarea.autocomplete: IDL set to object "test-valueOf"]
-    expected: FAIL
-
   [textarea.inputMode: setAttribute() to "kana-name"]
     expected: FAIL
 
   [textarea.inputMode: setAttribute() to "xkana-name"]
     expected: FAIL
 
   [textarea.inputMode: setAttribute() to "kana-name\\0"]
     expected: FAIL
@@ -3553,417 +3502,8 @@
   [meter.max: IDL get with DOM attribute unset]
     expected: FAIL
 
   [meter.high: IDL get with DOM attribute unset]
     expected: FAIL
 
   [meter.optimum: IDL get with DOM attribute unset]
     expected: FAIL
-
-  [select.autocomplete: typeof IDL attribute]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL get with DOM attribute unset]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to ""]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f  foo "]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to undefined]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to 7]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to 1.5]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to true]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to false]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and not stylo and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and not e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-      if not debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): FAIL
-      if debug and stylo and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): FAIL
-      if debug and stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL
-
-  [select.autocomplete: IDL set to object "[object Object\]"]
-    expected:
-      if debug and not stylo and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): FAIL<