merge mozilla-inbound to mozilla-central. r=merge a=merge
authorSebastian Hengst <archaeopteryx@coole-files.de>
Tue, 10 Oct 2017 06:12:26 -0300
changeset 677214 77a4c52e9987d2359969d7c478183b438b464744
parent 677213 87ca0b304342107308e62fde2c043d79a633b2b8 (current diff)
parent 677165 56fffcd3581f39be3f3af1ff62d77e51816a7db6 (diff)
child 677215 1caa1ee2d93805f97a8ea4dcbbc931c10e99575c
child 677225 d45c4e85410a3510829102aac86eff6934d45ab9
child 677228 c8c5979529935e5bd2b3496d7946f4d8ac6c23cb
child 677235 1de75873b6e8aef2098ed0730fb612dfd53d96c7
child 677249 ec2ec418bb355ccfedf3e3201c08909666420e49
child 677254 983a22fe90a4bfcce6bf7c8a6a74e5baa1bcc2cc
child 677278 b0d000fc6e73e52eecbd202e36253b0a387a09c6
child 677282 b1d8f2c4786881f0bfc1656c6e9d1134b6d25bb6
child 677284 54efef2534dda93ab7c516185530deb57b37011a
child 677288 36bc876757147df6a832db09ec4de60aa5b1b902
child 677305 74d3a8b20c4be92d6a04908e90b9b9b652d81895
child 677308 c15156c683c39c7ef4874697c8fe6834f2f13d39
child 677710 802383c4e55dc0a2881ce30d793a80b7b4a06c07
child 677712 e4fd9efa49e414e06a639f2226e5add59f8fa843
child 677713 58dd7795d8e34891f9b5690ac60885cb51fba629
child 677721 ce4374445afdb4de6a24bce1d9012ca7cd0b7e11
child 677722 39fd326b98c121035a0a46458e259753991ee1dd
child 677724 07ff95593d3ad4799495f51040df063148884f35
child 677725 68966767cc5bff586aaf603a8f4ede5d82b1cc0c
child 677726 4949ae553643b1c71a3d04e85f17a8fa0324a4e4
child 677732 e190010a8e53e7f583d061bdefd84df527b2d549
child 677739 f34bdab349363981851c0936cbb2da64c327e657
child 677741 d1a9416336dc53e05890c11e95a73c77e8450696
child 677742 bcac76e0eb96af39c815bca9357566c8940149fc
child 677757 5d845e034089220bd81a1926a36cdf72277727de
child 677773 644e17683dea8067d06c7905df7be96d5c1d446f
child 678043 cb5249929a6801c568c60f4dd0d3929c66328a8c
child 678048 dc636e903d5f1bf12103d1a755b1553d4a297d4b
child 678051 7b21563259103adf5a050b4aa6e1daaf193b41fd
child 678057 3141af189ebe4021058d32007b3c7ea60476d97d
child 678063 11efe877a8629734d974b5534c6a93036e78c85c
child 678067 d421ee4514c37d386e983cb741a0ea3e0039e9fe
child 678116 8758dc9df976469b03d9e88ca663523c0533c33f
child 678129 3cbeb81d083a4f40224c6af755a90ee9bfbee0f5
child 678187 b11ebd0aad7e8450057d03e6a59a3a2c228645dd
child 678188 a39bb127e57a3c390abe428a60c0f3da850939c8
child 678202 a3d8f10ad744d6b376160abd704023c48f7ecd2a
child 678237 4e822a984da4288b6912ca4df5310802666e813f
child 678283 22c394465d9ebabf6d7d30a241215d835e0678c1
child 678374 4c631efcf14737f3bc12cf48274d9bb77c5d5fa2
child 678483 261626b37af211f01ef6571dbc440b606e648d2a
child 678488 4221d1d383885f7a2111a947c95e45412e3c03ad
child 678522 46bba330f9feeb6cea0ca5607014f7dcdcd9c70e
child 678546 371cbae49a5115110f74bb19cf211004eae0d7d8
child 678572 18a008d2fcac0458edf4e16df37e7665d49362b7
child 678573 afdea02290c96d2e3ebab2b87f0111184e423935
child 678577 67cc0f21a84c7b431b0e9ed4746b683c22bdc2cf
child 678624 30df702016a6266e23cceb14c843feb6c8ccc1ce
child 678688 4bda3a076d295835563c44b5e9024824eaff7093
child 678805 c1b17a54a9cc12ff3465c2784ffd4c8a9c57c4a4
child 678965 c725152fd6a1e8830e9476f08d8346b3772b5eee
child 679028 29e16eaccf3d4a8fc2a21829ee4689b99931f260
child 679519 5e9ec4735f632aeff99dfe5faaaaad03c790e4fb
child 679520 fa6cea1219c3ffcbaf5a53981494fae7ea7adee4
child 679522 c24cefece17a683f2795ee9fcdc49b59afd3f3c5
child 679531 22335f2d442bdfc00ff28b788c770541a74f14b0
child 679533 e47bed3ecbd99c2b5575979ee736977993cdebc8
child 679534 2906627e5150cd3021bff1e590f5ef4b1ae82896
child 680987 b16807458f9725f3ef157feae081acad7c1de64e
child 681077 3bd023e7c8de1b7310ba2a1c2c71735a061cc680
child 682750 5641d417a6245cc2f8027fd91032119f1b36d461
child 682858 4908e3cb10e49c8b565c3bda9326b9aa2504496c
child 684077 bc4c6417e77461634263defb88e67ed5036c454e
push id83722
push userbmo:sledru@mozilla.com
push dateTue, 10 Oct 2017 10:01:59 +0000
reviewersmerge, merge
milestone58.0a1
merge mozilla-inbound to mozilla-central. r=merge a=merge
build/moz.configure/toolchain.configure
dom/interfaces/html/nsIDOMHTMLLinkElement.idl
--- a/browser/base/content/test/alerts/browser.ini
+++ b/browser/base/content/test/alerts/browser.ini
@@ -1,14 +1,12 @@
 [DEFAULT]
 support-files =
   head.js
   file_dom_notifications.html
 
 [browser_notification_close.js]
 skip-if = os == 'win' # Bug 1227785
 [browser_notification_do_not_disturb.js]
-skip-if = (os == 'win' && bits == 32) # Bug 1352791
 [browser_notification_open_settings.js]
 [browser_notification_remove_permission.js]
 [browser_notification_replace.js]
 [browser_notification_tab_switching.js]
-skip-if = os == "win" || os == "linux" # Bug 1243263
--- a/browser/base/content/test/alerts/browser_notification_close.js
+++ b/browser/base/content/test/alerts/browser_notification_close.js
@@ -2,19 +2,18 @@
 
 const {PlacesTestUtils} =
   Cu.import("resource://testing-common/PlacesTestUtils.jsm", {});
 
 let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 let oldShowFavicons;
 
 add_task(async function test_notificationClose() {
-  let pm = Services.perms;
   let notificationURI = makeURI(notificationURL);
-  pm.add(notificationURI, "desktop-notification", pm.ALLOW_ACTION);
+  await addNotificationPermission(notificationURL);
 
   oldShowFavicons = Services.prefs.getBoolPref("alerts.showFavicons");
   Services.prefs.setBoolPref("alerts.showFavicons", true);
 
   await PlacesTestUtils.addVisits(notificationURI);
   let faviconURI = await new Promise(resolve => {
     let uri =
       makeURI("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAIAAACQd1PeAAAADElEQVQI12P4//8/AAX+Av7czFnnAAAAAElFTkSuQmCC");
--- a/browser/base/content/test/alerts/browser_notification_do_not_disturb.js
+++ b/browser/base/content/test/alerts/browser_notification_do_not_disturb.js
@@ -16,33 +16,32 @@ function test() {
     ALERT_SERVICE.manualDoNotDisturb;
     ok(true, "Alert service implements do-not-disturb interface");
   } catch (e) {
     ok(true, "Alert service doesn't implement do-not-disturb interface, exiting test");
     finish();
     return;
   }
 
-  let pm = Services.perms;
   registerCleanupFunction(function() {
     ALERT_SERVICE.manualDoNotDisturb = false;
-    pm.remove(makeURI(notificationURL), "desktop-notification");
     gBrowser.removeTab(tab);
     window.restore();
   });
 
-  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
 
   // Make sure that do-not-disturb is not enabled.
   ok(!ALERT_SERVICE.manualDoNotDisturb, "Alert service should not be disabled when test starts");
   ALERT_SERVICE.manualDoNotDisturb = false;
 
-  tab = BrowserTestUtils.addTab(gBrowser, notificationURL);
-  gBrowser.selectedTab = tab;
-  tab.linkedBrowser.addEventListener("load", onLoad, true);
+  addNotificationPermission(notificationURL).then(function openTab() {
+    tab = BrowserTestUtils.addTab(gBrowser, notificationURL);
+    gBrowser.selectedTab = tab;
+    tab.linkedBrowser.addEventListener("load", onLoad, true);
+  });
 }
 
 function onLoad() {
   tab.linkedBrowser.removeEventListener("load", onLoad, true);
   openNotification(tab.linkedBrowser, "showNotification2").then(onAlertShowing);
 }
 
 function onAlertShowing() {
--- a/browser/base/content/test/alerts/browser_notification_open_settings.js
+++ b/browser/base/content/test/alerts/browser_notification_open_settings.js
@@ -19,48 +19,42 @@ add_task(async function test_settingsOpe
     let tab = await tabPromise;
     ok(tab, "The notification settings tab opened");
     await syncPaneLoadedPromise;
     await BrowserTestUtils.removeTab(tab);
   });
 });
 
 add_task(async function test_settingsOpen_button() {
-  let pm = Services.perms;
   info("Adding notification permission");
-  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
+  await addNotificationPermission(notificationURL);
 
-  try {
-    await BrowserTestUtils.withNewTab({
-      gBrowser,
-      url: notificationURL
-    }, async function tabTask(aBrowser) {
-      // Ensure preferences is loaded before removing the tab.
-      let syncPaneLoadedPromise = TestUtils.topicObserved("sync-pane-loaded", () => true);
+  await BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: notificationURL
+  }, async function tabTask(aBrowser) {
+    // Ensure preferences is loaded before removing the tab.
+    let syncPaneLoadedPromise = TestUtils.topicObserved("sync-pane-loaded", () => true);
 
-      info("Waiting for notification");
-      await openNotification(aBrowser, "showNotification2");
+    info("Waiting for notification");
+    await openNotification(aBrowser, "showNotification2");
 
-      let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
-      if (!alertWindow) {
-        ok(true, "Notifications don't use XUL windows on all platforms.");
-        await closeNotification(aBrowser);
-        return;
-      }
-
-      let closePromise = promiseWindowClosed(alertWindow);
-      let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
-      let openSettingsMenuItem = alertWindow.document.getElementById("openSettingsMenuItem");
-      openSettingsMenuItem.click();
+    let alertWindow = Services.wm.getMostRecentWindow("alert:alert");
+    if (!alertWindow) {
+      ok(true, "Notifications don't use XUL windows on all platforms.");
+      await closeNotification(aBrowser);
+      return;
+    }
 
-      info("Waiting for notification settings tab");
-      let tab = await tabPromise;
-      ok(tab, "The notification settings tab opened");
+    let closePromise = promiseWindowClosed(alertWindow);
+    let tabPromise = BrowserTestUtils.waitForNewTab(gBrowser, expectedURL);
+    let openSettingsMenuItem = alertWindow.document.getElementById("openSettingsMenuItem");
+    openSettingsMenuItem.click();
 
-      await syncPaneLoadedPromise;
-      await closePromise;
-      await BrowserTestUtils.removeTab(tab);
-    });
-  } finally {
-    info("Removing notification permission");
-    pm.remove(makeURI(notificationURL), "desktop-notification");
-  }
+    info("Waiting for notification settings tab");
+    let tab = await tabPromise;
+    ok(tab, "The notification settings tab opened");
+
+    await syncPaneLoadedPromise;
+    await closePromise;
+    await BrowserTestUtils.removeTab(tab);
+  });
 });
--- a/browser/base/content/test/alerts/browser_notification_remove_permission.js
+++ b/browser/base/content/test/alerts/browser_notification_remove_permission.js
@@ -3,28 +3,26 @@
 var tab;
 var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 var alertWindowClosed = false;
 var permRemoved = false;
 
 function test() {
   waitForExplicitFinish();
 
-  let pm = Services.perms;
   registerCleanupFunction(function() {
-    pm.remove(makeURI(notificationURL), "desktop-notification");
     gBrowser.removeTab(tab);
     window.restore();
   });
 
-  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
-
-  tab = BrowserTestUtils.addTab(gBrowser, notificationURL);
-  gBrowser.selectedTab = tab;
-  tab.linkedBrowser.addEventListener("load", onLoad, true);
+  addNotificationPermission(notificationURL).then(function openTab() {
+    tab = BrowserTestUtils.addTab(gBrowser, notificationURL);
+    gBrowser.selectedTab = tab;
+    tab.linkedBrowser.addEventListener("load", onLoad, true);
+  });
 }
 
 function onLoad() {
   tab.linkedBrowser.removeEventListener("load", onLoad, true);
   openNotification(tab.linkedBrowser, "showNotification2").then(onAlertShowing);
 }
 
 function onAlertShowing() {
--- a/browser/base/content/test/alerts/browser_notification_replace.js
+++ b/browser/base/content/test/alerts/browser_notification_replace.js
@@ -1,15 +1,14 @@
 "use strict";
 
 let notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 
 add_task(async function test_notificationReplace() {
-  let pm = Services.perms;
-  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
+  await addNotificationPermission(notificationURL);
 
   await BrowserTestUtils.withNewTab({
     gBrowser,
     url: notificationURL
   }, async function dummyTabTask(aBrowser) {
     await ContentTask.spawn(aBrowser, {}, async function() {
       let win = content.window.wrappedJSObject;
       let notification = win.showNotification1();
@@ -27,12 +26,8 @@ add_task(async function test_notificatio
 
       let promiseNewCloseEvent = ContentTaskUtils.waitForEvent(newNotification, "close");
       newNotification.close();
       let newCloseEvent = await promiseNewCloseEvent;
       Assert.equal(newCloseEvent.target.body, "Test body 2", "Closed new notification");
     });
   });
 });
-
-add_task(async function cleanup() {
-  Services.perms.remove(makeURI(notificationURL), "desktop-notification");
-});
--- a/browser/base/content/test/alerts/browser_notification_tab_switching.js
+++ b/browser/base/content/test/alerts/browser_notification_tab_switching.js
@@ -5,18 +5,17 @@
 "use strict";
 
 var tab;
 var notification;
 var notificationURL = "http://example.org/browser/browser/base/content/test/alerts/file_dom_notifications.html";
 var newWindowOpenedFromTab;
 
 add_task(async function test_notificationPreventDefaultAndSwitchTabs() {
-  let pm = Services.perms;
-  pm.add(makeURI(notificationURL), "desktop-notification", pm.ALLOW_ACTION);
+  await addNotificationPermission(notificationURL);
 
   let originalTab = gBrowser.selectedTab;
   await BrowserTestUtils.withNewTab({
     gBrowser,
     url: notificationURL
   }, async function dummyTabTask(aBrowser) {
     // Put new tab in background so it is obvious when it is re-focused.
     await BrowserTestUtils.switchTab(gBrowser, originalTab);
--- a/browser/base/content/test/alerts/head.js
+++ b/browser/base/content/test/alerts/head.js
@@ -1,8 +1,18 @@
+async function addNotificationPermission(originString) {
+  return new Promise(resolve => {
+    SpecialPowers.pushPermissions([{
+      type: "desktop-notification",
+      allow: true,
+      context: originString,
+    }], resolve);
+  });
+}
+
 /**
  * Similar to `BrowserTestUtils.closeWindow`, but
  * doesn't call `window.close()`.
  */
 function promiseWindowClosed(window) {
   return new Promise(function(resolve) {
     Services.ww.registerNotification(function observer(subject, topic, data) {
       if (topic == "domwindowclosed" && subject == window) {
--- a/browser/components/extensions/test/browser/browser_ext_find.js
+++ b/browser/components/extensions/test/browser/browser_ext_find.js
@@ -73,16 +73,31 @@ add_task(async function testDuplicatePin
     browser.test.log("Test that case insensitive match works properly.");
     data = await browser.find.find("banana", {caseSensitive: false});
     browser.test.assertEq(6, data.count, "The number of matches found:");
 
     browser.test.log("Test that entire word match works properly.");
     data = await browser.find.find("banana", {entireWord: true});
     browser.test.assertEq(4, data.count, "The number of matches found, should skip 2 matches, \"banaNaland\" and \"bananAland\":");
 
+    let expectedRangeData = [{framePos: 0, text: "example", startTextNodePos: 15, startOffset: 11, endTextNodePos: 15, endOffset: 18},
+                             {framePos: 0, text: "example", startTextNodePos: 15, startOffset: 25, endTextNodePos: 15, endOffset: 32},
+                             {framePos: 0, text: "example", startTextNodePos: 18, startOffset: 6, endTextNodePos: 18, endOffset: 13},
+                             {framePos: 0, text: "example", startTextNodePos: 20, startOffset: 3, endTextNodePos: 20, endOffset: 10},
+                             {framePos: 1, text: "example", startTextNodePos: 0, startOffset: 0, endTextNodePos: 0, endOffset: 7},
+                             {framePos: 2, text: "example", startTextNodePos: 0, startOffset: 0, endTextNodePos: 0, endOffset: 7}];
+
+    browser.test.log("Test that word found in the same node, different nodes and different frames returns the correct rangeData results.");
+    data = await browser.find.find("example", {includeRangeData: true});
+    for (let i = 0; i < data.rangeData.length; i++) {
+      for (let name in data.rangeData[i]) {
+        browser.test.assertEq(expectedRangeData[i][name], data.rangeData[i][name], `rangeData[${i}].${name}:`);
+      }
+    }
+
     browser.test.log("Test that `rangeData` is not returned if `includeRangeData` is false.");
     data = await browser.find.find("banana", {caseSensitive: false, includeRangeData: false});
     browser.test.assertEq(false, !!data.rangeData, "The boolean cast value of `rangeData`:");
 
     browser.test.log("Test that `rectData` is not returned if `includeRectData` is false.");
     data = await browser.find.find("banana", {caseSensitive: false, includeRectData: false});
     browser.test.assertEq(false, !!data.rectData, "The boolean cast value of `rectData`:");
 
--- a/browser/components/extensions/test/browser/file_find_frames.html
+++ b/browser/components/extensions/test/browser/file_find_frames.html
@@ -5,11 +5,16 @@
 <p>Banana 0</p>
 <iframe src="data:text/html,<p>baNana 2</p>
                             <iframe src='data:text/html,banaNaland 4' height='50' width='100%'></iframe>
                             <iframe src='data:text/html,bananAland 5' height='50' width='100%'></iframe>
                             <p>banAna 3</p>" height="250" width="100%"></iframe>
 <p>bAnana 1</p>
 <p><b>fru</b>it<i><b>ca</b>ke</i></p>
 <p>ang<div>elf</div>ood</p>
+<p>This is an example of an example in the same node.</p>
+<p>This <span>is an example</span> of <span>an example</span> of ranges in separate nodes.</p>
+<iframe src="data:text/html,<p>example within a frame.</p>
+  <iframe src='data:text/html,example within a sub-frame' height='50' width='100%'></iframe>" height="250" width="100%">
+</iframe>
 </body>
 </html>
 
--- a/build/moz.configure/toolchain.configure
+++ b/build/moz.configure/toolchain.configure
@@ -504,19 +504,19 @@ def get_vc_paths(topsrcdir):
         tools_version = open(os.path.join(path, r'VC\Auxiliary\Build\Microsoft.VCToolsVersion.default.txt'), 'rb').read().strip()
         tools_path = os.path.join(path, r'VC\Tools\MSVC', tools_version, r'bin\HostX64')
         yield (Version(install['installationVersion']), {
             'x64': [os.path.join(tools_path, 'x64')],
             # The x64->x86 cross toolchain requires DLLs from the native x64 toolchain.
             'x86': [os.path.join(tools_path, 'x86'), os.path.join(tools_path, 'x64')],
         })
 
-option('--with-visual-studio-version', nargs=1,
-       choices=('2015', '2017'),
-       help='Select a specific Visual Studio version to use')
+js_option('--with-visual-studio-version', nargs=1,
+          choices=('2015', '2017'),
+          help='Select a specific Visual Studio version to use')
 
 @depends('--with-visual-studio-version')
 def vs_major_version(value):
     if value:
         return {'2015': 14,
                 '2017': 15}[value[0]]
 
 @depends(host, target, vs_major_version, check_build_environment, '--with-visual-studio-version')
--- a/dom/base/AnonymousContent.cpp
+++ b/dom/base/AnonymousContent.cpp
@@ -70,25 +70,26 @@ AnonymousContent::GetTextContentForEleme
 
   element->GetTextContent(aText, aRv);
 }
 
 void
 AnonymousContent::SetAttributeForElement(const nsAString& aElementId,
                                          const nsAString& aName,
                                          const nsAString& aValue,
+                                         nsIPrincipal* aSubjectPrincipal,
                                          ErrorResult& aRv)
 {
   Element* element = GetElementById(aElementId);
   if (!element) {
     aRv.Throw(NS_ERROR_NOT_AVAILABLE);
     return;
   }
 
-  element->SetAttribute(aName, aValue, aRv);
+  element->SetAttribute(aName, aValue, aSubjectPrincipal, aRv);
 }
 
 void
 AnonymousContent::GetAttributeForElement(const nsAString& aElementId,
                                          const nsAString& aName,
                                          DOMString& aValue,
                                          ErrorResult& aRv)
 {
--- a/dom/base/AnonymousContent.h
+++ b/dom/base/AnonymousContent.h
@@ -38,16 +38,17 @@ public:
 
   void GetTextContentForElement(const nsAString& aElementId,
                                 DOMString& aText,
                                 ErrorResult& aRv);
 
   void SetAttributeForElement(const nsAString& aElementId,
                               const nsAString& aName,
                               const nsAString& aValue,
+                              nsIPrincipal* aSubjectPrincipal,
                               ErrorResult& aRv);
 
   void GetAttributeForElement(const nsAString& aElementId,
                               const nsAString& aName,
                               DOMString& aValue,
                               ErrorResult& aRv);
 
   void RemoveAttributeForElement(const nsAString& aElementId,
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -170,37 +170,38 @@ Attr::GetValue(nsAString& aValue)
   else {
     aValue = mValue;
   }
 
   return NS_OK;
 }
 
 void
-Attr::SetValue(const nsAString& aValue, ErrorResult& aRv)
+Attr::SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv)
 {
   Element* element = GetElement();
   if (!element) {
     mValue = aValue;
     return;
   }
 
   RefPtr<nsAtom> nameAtom = mNodeInfo->NameAtom();
   aRv = element->SetAttr(mNodeInfo->NamespaceID(),
                          nameAtom,
                          mNodeInfo->GetPrefixAtom(),
                          aValue,
+                         aTriggeringPrincipal,
                          true);
 }
 
 NS_IMETHODIMP
 Attr::SetValue(const nsAString& aValue)
 {
   ErrorResult rv;
-  SetValue(aValue, rv);
+  SetValue(aValue, nullptr, rv);
   return rv.StealNSResult();
 }
 
 bool
 Attr::Specified() const
 {
   return true;
 }
@@ -232,26 +233,22 @@ Attr::GetOwnerElement(nsIDOMElement** aO
   *aOwnerElement = nullptr;
 
   return NS_OK;
 }
 
 void
 Attr::GetNodeValueInternal(nsAString& aNodeValue)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
-
   GetValue(aNodeValue);
 }
 
 void
 Attr::SetNodeValueInternal(const nsAString& aNodeValue, ErrorResult& aError)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eNodeValue);
-
   aError = SetValue(aNodeValue);
 }
 
 nsresult
 Attr::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
             bool aPreallocateChildren) const
 {
   nsAutoString value;
@@ -275,27 +272,23 @@ Attr::GetBaseURI(bool aTryUseXHRDocBaseU
 
   return parent ? parent->GetBaseURI(aTryUseXHRDocBaseURI) : nullptr;
 }
 
 void
 Attr::GetTextContentInternal(nsAString& aTextContent,
                              OOMReporter& aError)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
-
   GetValue(aTextContent);
 }
 
 void
 Attr::SetTextContentInternal(const nsAString& aTextContent,
                              ErrorResult& aError)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eTextContent);
-
   SetNodeValueInternal(aTextContent, aError);
 }
 
 NS_IMETHODIMP
 Attr::GetIsId(bool* aReturn)
 {
   *aReturn = mNodeInfo->Equals(nsGkAtoms::id, kNameSpaceID_None);
   return NS_OK;
--- a/dom/base/Attr.h
+++ b/dom/base/Attr.h
@@ -80,19 +80,23 @@ public:
                                                                    nsIAttribute)
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   // WebIDL
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // XPCOM GetName() is OK
-  // XPCOM GetValue() is OK
 
-  void SetValue(const nsAString& aValue, ErrorResult& aRv);
+  void GetValue(nsString& val, nsIPrincipal&)
+  {
+    GetValue(val);
+  }
+
+  void SetValue(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv);
 
   bool Specified() const;
 
   // XPCOM GetNamespaceURI() is OK
   // XPCOM GetPrefix() is OK
   // XPCOM GetLocalName() is OK
 
   Element* GetOwnerElement(ErrorResult& aRv);
--- a/dom/base/DOMIntersectionObserver.cpp
+++ b/dom/base/DOMIntersectionObserver.cpp
@@ -431,23 +431,25 @@ DOMIntersectionObserver::Update(nsIDocum
         nsIFrame* rootScrollFrame = presContext->PresShell()->GetRootScrollFrame();
         if (rootScrollFrame) {
           nsLayoutUtils::TransformRect(rootFrame, rootScrollFrame, rect);
         }
         intersectionRect = Some(rect);
       }
     }
 
-    double targetArea = targetRect.Width() * targetRect.Height();
-    double intersectionArea = !intersectionRect ?
-      0 : intersectionRect->Width() * intersectionRect->Height();
+    int64_t targetArea =
+      (int64_t) targetRect.Width() * (int64_t) targetRect.Height();
+    int64_t intersectionArea = !intersectionRect ? 0 :
+      (int64_t) intersectionRect->Width() *
+      (int64_t) intersectionRect->Height();
 
     double intersectionRatio;
     if (targetArea > 0.0) {
-      intersectionRatio = intersectionArea / targetArea;
+      intersectionRatio = (double) intersectionArea / (double) targetArea;
     } else {
       intersectionRatio = intersectionRect.isSome() ? 1.0 : 0.0;
     }
 
     int32_t threshold = -1;
     if (intersectionRatio > 0.0) {
       if (intersectionRatio >= 1.0) {
         intersectionRatio = 1.0;
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -65,23 +65,20 @@ public:
       mHost(nullptr)
   {
     Init();
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // nsIContent
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
-  }
+  using nsIContent::SetAttr;
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                            nsAtom* aPrefix, const nsAString& aValue,
+                           nsIPrincipal* aSubjectPrincipal,
                            bool aNotify) override
   {
     return NS_OK;
   }
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                              bool aNotify) override
   {
     return NS_OK;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1292,37 +1292,38 @@ Element::GetAttribute(const nsAString& a
       aReturn.SetNull();
     }
   }
 }
 
 void
 Element::SetAttribute(const nsAString& aName,
                       const nsAString& aValue,
+                      nsIPrincipal* aTriggeringPrincipal,
                       ErrorResult& aError)
 {
   aError = nsContentUtils::CheckQName(aName, false);
   if (aError.Failed()) {
     return;
   }
 
   nsAutoString nameToUse;
   const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
   if (!name) {
     RefPtr<nsAtom> nameAtom = NS_AtomizeMainThread(nameToUse);
     if (!nameAtom) {
       aError.Throw(NS_ERROR_OUT_OF_MEMORY);
       return;
     }
-    aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
+    aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, aTriggeringPrincipal, true);
     return;
   }
 
   aError = SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
-                   aValue, true);
+                   aValue, aTriggeringPrincipal, true);
 }
 
 void
 Element::RemoveAttribute(const nsAString& aName, ErrorResult& aError)
 {
   const nsAttrName* name = InternalGetAttrNameFromQName(aName);
 
   if (!name) {
@@ -1338,41 +1339,35 @@ Element::RemoveAttribute(const nsAString
   nsAttrName tmp(*name);
 
   aError = UnsetAttr(name->NamespaceID(), name->LocalName(), true);
 }
 
 Attr*
 Element::GetAttributeNode(const nsAString& aName)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNode);
   return Attributes()->GetNamedItem(aName);
 }
 
 already_AddRefed<Attr>
 Element::SetAttributeNode(Attr& aNewAttr, ErrorResult& aError)
 {
-  // XXXbz can we just remove this warning and the one in setAttributeNodeNS and
-  // alias setAttributeNode to setAttributeNodeNS?
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode);
-
   return Attributes()->SetNamedItemNS(aNewAttr, aError);
 }
 
 already_AddRefed<Attr>
 Element::RemoveAttributeNode(Attr& aAttribute,
                              ErrorResult& aError)
 {
   Element *elem = aAttribute.GetElement();
   if (elem != this) {
     aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
     return nullptr;
   }
 
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode);
   nsAutoString nameSpaceURI;
   aAttribute.NodeInfo()->GetNamespaceURI(nameSpaceURI);
   return Attributes()->RemoveNamedItemNS(nameSpaceURI, aAttribute.NodeInfo()->LocalName(), aError);
 }
 
 void
 Element::GetAttributeNS(const nsAString& aNamespaceURI,
                         const nsAString& aLocalName,
@@ -1394,30 +1389,31 @@ Element::GetAttributeNS(const nsAString&
     SetDOMStringToNull(aReturn);
   }
 }
 
 void
 Element::SetAttributeNS(const nsAString& aNamespaceURI,
                         const nsAString& aQualifiedName,
                         const nsAString& aValue,
+                        nsIPrincipal* aTriggeringPrincipal,
                         ErrorResult& aError)
 {
   RefPtr<mozilla::dom::NodeInfo> ni;
   aError =
     nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName,
                                          mNodeInfo->NodeInfoManager(),
                                          nsIDOMNode::ATTRIBUTE_NODE,
                                          getter_AddRefs(ni));
   if (aError.Failed()) {
     return;
   }
 
   aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
-                   aValue, true);
+                   aValue, aTriggeringPrincipal, true);
 }
 
 void
 Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
                            const nsAString& aLocalName,
                            ErrorResult& aError)
 {
   RefPtr<nsAtom> name = NS_AtomizeMainThread(aLocalName);
@@ -1434,33 +1430,30 @@ Element::RemoveAttributeNS(const nsAStri
 
   aError = UnsetAttr(nsid, name, true);
 }
 
 Attr*
 Element::GetAttributeNodeNS(const nsAString& aNamespaceURI,
                             const nsAString& aLocalName)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
-
   return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName);
 }
 
 Attr*
 Element::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
                                     const nsAString& aLocalName)
 {
   return Attributes()->GetNamedItemNS(aNamespaceURI, aLocalName);
 }
 
 already_AddRefed<Attr>
 Element::SetAttributeNodeNS(Attr& aNewAttr,
                             ErrorResult& aError)
 {
-  OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS);
   return Attributes()->SetNamedItemNS(aNewAttr, aError);
 }
 
 already_AddRefed<nsIHTMLCollection>
 Element::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
                                 const nsAString& aLocalName,
                                 ErrorResult& aError)
 {
@@ -2466,27 +2459,29 @@ Element::SetSingleClassFromParser(nsAtom
   // is no such node type, so calling SetMayHaveClass() directly.
   SetMayHaveClass();
 
   return SetAttrAndNotify(kNameSpaceID_None,
                           nsGkAtoms::_class,
                           nullptr, // prefix
                           nullptr, // old value
                           value,
+                          nullptr,
                           static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION),
                           false, // hasListeners
                           false, // notify
                           kCallAfterSetAttr,
                           document,
                           updateBatch);
 }
 
 nsresult
 Element::SetAttr(int32_t aNamespaceID, nsAtom* aName,
                  nsAtom* aPrefix, const nsAString& aValue,
+                 nsIPrincipal* aSubjectPrincipal,
                  bool aNotify)
 {
   // Keep this in sync with SetParsedAttr below and SetSingleClassFromParser
   // above.
 
   NS_ENSURE_ARG_POINTER(aName);
   NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
                "Don't call SetAttr with unknown namespace");
@@ -2536,17 +2531,18 @@ Element::SetAttr(int32_t aNamespaceID, n
       !ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
     attrValue.SetTo(aValue);
   }
 
   PreIdMaybeChange(aNamespaceID, aName, &value);
 
   return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
                           oldValueSet ? &oldValue : nullptr,
-                          attrValue, modType, hasListeners, aNotify,
+                          attrValue, aSubjectPrincipal, modType,
+                          hasListeners, aNotify,
                           kCallAfterSetAttr, document, updateBatch);
 }
 
 nsresult
 Element::SetParsedAttr(int32_t aNamespaceID, nsAtom* aName,
                        nsAtom* aPrefix, nsAttrValue& aParsedValue,
                        bool aNotify)
 {
@@ -2581,26 +2577,27 @@ Element::SetParsedAttr(int32_t aNamespac
   NS_ENSURE_SUCCESS(rv, rv);
 
   PreIdMaybeChange(aNamespaceID, aName, &value);
 
   nsIDocument* document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
   return SetAttrAndNotify(aNamespaceID, aName, aPrefix,
                           oldValueSet ? &oldValue : nullptr,
-                          aParsedValue, modType, hasListeners, aNotify,
+                          aParsedValue, nullptr, modType, hasListeners, aNotify,
                           kCallAfterSetAttr, document, updateBatch);
 }
 
 nsresult
 Element::SetAttrAndNotify(int32_t aNamespaceID,
                           nsAtom* aName,
                           nsAtom* aPrefix,
                           const nsAttrValue* aOldValue,
                           nsAttrValue& aParsedValue,
+                          nsIPrincipal* aSubjectPrincipal,
                           uint8_t aModType,
                           bool aFireMutation,
                           bool aNotify,
                           bool aCallAfterSetAttr,
                           nsIDocument* aComposedDocument,
                           const mozAutoDocUpdate&)
 {
   nsresult rv;
@@ -2693,17 +2690,17 @@ Element::SetAttrAndNotify(int32_t aNames
         nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAttributeChanged,
           this, &args, nullptr, definition);
       }
     }
   }
 
   if (aCallAfterSetAttr) {
     rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, oldValue,
-                      aNotify);
+                      aSubjectPrincipal, aNotify);
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
       OnSetDirAttr(this, &valueForAfterSetAttr,
                    hadValidDir, hadDirAuto, aNotify);
     }
   }
 
@@ -2986,17 +2983,17 @@ Element::UnsetAttr(int32_t aNameSpaceID,
         };
 
         nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAttributeChanged,
           this, &args, nullptr, definition);
       }
     }
   }
 
-  rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, aNotify);
+  rv = AfterSetAttr(aNameSpaceID, aName, nullptr, &oldValue, nullptr, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   UpdateState(aNotify);
 
   if (aNotify) {
     // We can always pass oldValue here since there is no new value which could
     // have corrupted it.
     nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -686,22 +686,17 @@ public:
    * null otherwise.
    *
    * @param aStr the unparsed attribute string
    * @return the node info. May be nullptr.
    */
   already_AddRefed<mozilla::dom::NodeInfo>
   GetExistingAttrNameFromQName(const nsAString& aStr) const;
 
-  MOZ_ALWAYS_INLINE  // Avoid a crashy hook from Avast 10 Beta (Bug 1058131)
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
-  }
+  using nsIContent::SetAttr;
 
   /**
    * Helper for SetAttr/SetParsedAttr. This method will return true if aNotify
    * is true or there are mutation listeners that must be triggered, the
    * attribute is currently set, and the new value that is about to be set is
    * different to the current value. As a perf optimization the new and old
    * values will not actually be compared if we aren't notifying and we don't
    * have mutation listeners (in which case it's cheap to just return false
@@ -753,17 +748,18 @@ public:
   /**
    * Sets the class attribute to a value that contains no whitespace.
    * Assumes that we are not notifying and that the attribute hasn't been
    * set previously.
    */
   nsresult SetSingleClassFromParser(nsAtom* aSingleClassName);
 
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
-                           const nsAString& aValue, bool aNotify) override;
+                           const nsAString& aValue, nsIPrincipal* aSubjectPrincipal,
+                           bool aNotify) override;
   // aParsedValue receives the old value of the attribute. That's useful if
   // either the input or output value of aParsedValue is StoresOwnData.
   nsresult SetParsedAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
                          nsAttrValue& aParsedValue, bool aNotify);
   // GetAttr is not inlined on purpose, to keep down codesize from all
   // the inlined nsAttrValue bits for C++ callers.
   bool GetAttr(int32_t aNameSpaceID, nsAtom* aName,
                nsAString& aResult) const;
@@ -924,21 +920,28 @@ public:
     str.ToString(aReturn);
   }
 
   void GetAttribute(const nsAString& aName, DOMString& aReturn);
   void GetAttributeNS(const nsAString& aNamespaceURI,
                       const nsAString& aLocalName,
                       nsAString& aReturn);
   void SetAttribute(const nsAString& aName, const nsAString& aValue,
-                    ErrorResult& aError);
+                    nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError);
   void SetAttributeNS(const nsAString& aNamespaceURI,
                       const nsAString& aLocalName,
                       const nsAString& aValue,
+                      nsIPrincipal* aTriggeringPrincipal,
                       ErrorResult& aError);
+  void SetAttribute(const nsAString& aName, const nsAString& aValue,
+                    ErrorResult& aError)
+  {
+    SetAttribute(aName, aValue, nullptr, aError);
+  }
+
   void RemoveAttribute(const nsAString& aName,
                        ErrorResult& aError);
   void RemoveAttributeNS(const nsAString& aNamespaceURI,
                          const nsAString& aLocalName,
                          ErrorResult& aError);
   bool HasAttribute(const nsAString& aName) const
   {
     return InternalGetAttrNameFromQName(aName) != nullptr;
@@ -1394,16 +1397,21 @@ public:
   /**
    * Set an attribute in the simplest way possible.
    */
   void SetAttr(nsAtom* aAttr, const nsAString& aValue, ErrorResult& aError)
   {
     aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
   }
 
+  void SetAttr(nsAtom* aAttr, const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
+  {
+    aError = nsIContent::SetAttr(kNameSpaceID_None, aAttr, aValue, &aTriggeringPrincipal, true);
+  }
+
   /**
    * Set a content attribute via a reflecting nullable string IDL
    * attribute (e.g. a CORS attribute).  If DOMStringIsNull(aValue),
    * this will actually remove the content attribute.
    */
   void SetOrRemoveNullableStringAttr(nsAtom* aName, const nsAString& aValue,
                                      ErrorResult& aError);
 
@@ -1473,28 +1481,37 @@ protected:
    *                      If the current value is StoresOwnData() (or absent),
    *                      aOldValue will not be used. aOldValue will only be set
    *                      in certain circumstances (there are mutation
    *                      listeners, element is a custom element, attribute was
    *                      not previously unset). Otherwise it will be null.
    * @param aParsedValue  parsed new value of attribute. Replaced by the
    *                      old value of the attribute. This old value is only
    *                      useful if either it or the new value is StoresOwnData.
+   * @param aMaybeScriptedPrincipal
+   *                      the principal of the scripted caller responsible for
+   *                      setting the attribute, or null if no scripted caller
+   *                      can be determined. A null value here does not
+   *                      guarantee that there is no scripted caller, but a
+   *                      non-null value does guarantee that a scripted caller
+   *                      with the given principal is directly responsible for
+   *                      the attribute change.
    * @param aModType      nsIDOMMutationEvent::MODIFICATION or ADDITION.  Only
    *                      needed if aFireMutation or aNotify is true.
    * @param aFireMutation should mutation-events be fired?
    * @param aNotify       should we notify document-observers?
    * @param aCallAfterSetAttr should we call AfterSetAttr?
    * @param aComposedDocument The current composed document of the element.
    */
   nsresult SetAttrAndNotify(int32_t aNamespaceID,
                             nsAtom* aName,
                             nsAtom* aPrefix,
                             const nsAttrValue* aOldValue,
                             nsAttrValue& aParsedValue,
+                            nsIPrincipal* aMaybeScriptedPrincipal,
                             uint8_t aModType,
                             bool aFireMutation,
                             bool aNotify,
                             bool aCallAfterSetAttr,
                             nsIDocument* aComposedDocument,
                             const mozAutoDocUpdate& aGuard);
 
   /**
@@ -1574,23 +1591,31 @@ protected:
    * @param aNamespaceID the namespace of the attr being set
    * @param aName the localname of the attribute being set
    * @param aValue the value it's being set to.  If null, the attr is being
    *        removed.
    * @param aOldValue the value that the attribute had previously. If null,
    *        the attr was not previously set. This argument may not have the
    *        correct value for SVG elements, or other cases in which the
    *        attribute value doesn't store its own data
+   * @param aMaybeScriptedPrincipal the principal of the scripted caller
+   *        responsible for setting the attribute, or null if no scripted caller
+   *        can be determined, or the attribute is being unset. A null value
+   *        here does not guarantee that there is no scripted caller, but a
+   *        non-null value does guarantee that a scripted caller with the given
+   *        principal is directly responsible for the attribute change.
    * @param aNotify Whether we plan to notify document observers.
    */
   // Note that this is inlined so that when subclasses call it it gets
   // inlined.  Those calls don't go through a vtable.
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                bool aNotify)
   {
     return NS_OK;
   }
 
   /**
    * This function shall be called just before the id attribute changes. It will
    * be called after BeforeSetAttr. If the attribute being changed is not the id
    * attribute, this function does nothing. Otherwise, it will remove the old id
@@ -1963,17 +1988,17 @@ NS_IMETHOD GetAttribute(const nsAString&
   GetAttribute(name, attr);                                                   \
   _retval = attr;                                                             \
   return NS_OK;                                                               \
 }                                                                             \
 NS_IMETHOD SetAttribute(const nsAString& name,                                \
                         const nsAString& value) override                      \
 {                                                                             \
   mozilla::ErrorResult rv;                                                    \
-  Element::SetAttribute(name, value, rv);                                     \
+  Element::SetAttribute(name, value, nullptr, rv);                            \
   return rv.StealNSResult();                                                  \
 }                                                                             \
 using Element::HasAttribute;                                                  \
 NS_IMETHOD HasAttribute(const nsAString& name,                                \
                            bool* _retval) final override                      \
 {                                                                             \
   *_retval = HasAttribute(name);                                              \
   return NS_OK;                                                               \
--- a/dom/base/ResponsiveImageSelector.cpp
+++ b/dom/base/ResponsiveImageSelector.cpp
@@ -111,17 +111,18 @@ ResponsiveImageSelector::ResponsiveImage
 {
 }
 
 ResponsiveImageSelector::~ResponsiveImageSelector()
 {}
 
 // http://www.whatwg.org/specs/web-apps/current-work/#processing-the-image-candidates
 bool
-ResponsiveImageSelector::SetCandidatesFromSourceSet(const nsAString & aSrcSet)
+ResponsiveImageSelector::SetCandidatesFromSourceSet(const nsAString & aSrcSet,
+                                                    nsIPrincipal* aTriggeringPrincipal)
 {
   ClearSelectedCandidate();
 
   nsCOMPtr<nsIURI> docBaseURI = mOwnerNode ? mOwnerNode->GetBaseURI() : nullptr;
 
   if (!docBaseURI) {
     MOZ_ASSERT(false,
                "Should not be parsing SourceSet without a document");
@@ -163,16 +164,18 @@ ResponsiveImageSelector::SetCandidatesFr
 
     const nsDependentSubstring &urlStr = Substring(url, iter);
 
     MOZ_ASSERT(url != iter, "Shouldn't have empty URL at this point");
 
     ResponsiveImageCandidate candidate;
     if (candidate.ConsumeDescriptors(iter, end)) {
       candidate.SetURLSpec(urlStr);
+      candidate.SetTriggeringPrincipal(nsContentUtils::GetAttrTriggeringPrincipal(
+          Content(), urlStr, aTriggeringPrincipal));
       AppendCandidateIfUnique(candidate);
     }
   }
 
   bool parsedCandidates = mCandidates.Length() > 0;
 
   // Re-add default to end of list
   MaybeAppendDefaultCandidate();
@@ -203,28 +206,30 @@ ResponsiveImageSelector::Content()
 
 nsIDocument*
 ResponsiveImageSelector::Document()
 {
   return mOwnerNode->OwnerDoc();
 }
 
 void
-ResponsiveImageSelector::SetDefaultSource(const nsAString& aURLString)
+ResponsiveImageSelector::SetDefaultSource(const nsAString& aURLString,
+                                          nsIPrincipal* aPrincipal)
 {
   ClearSelectedCandidate();
 
   // Check if the last element of our candidates is a default
   int32_t candidates = mCandidates.Length();
   if (candidates && (mCandidates[candidates - 1].Type() ==
                      ResponsiveImageCandidate::eCandidateType_Default)) {
     mCandidates.RemoveElementAt(candidates - 1);
   }
 
   mDefaultSourceURL = aURLString;
+  mDefaultSourceTriggeringPrincipal = aPrincipal;
 
   // Add new default to end of list
   MaybeAppendDefaultCandidate();
 }
 
 void
 ResponsiveImageSelector::ClearSelectedCandidate()
 {
@@ -287,16 +292,17 @@ ResponsiveImageSelector::MaybeAppendDefa
     } else if (mCandidates[i].Density(this) == 1.0) {
       return;
     }
   }
 
   ResponsiveImageCandidate defaultCandidate;
   defaultCandidate.SetParameterDefault();
   defaultCandidate.SetURLSpec(mDefaultSourceURL);
+  defaultCandidate.SetTriggeringPrincipal(mDefaultSourceTriggeringPrincipal);
   // We don't use MaybeAppend since we want to keep this even if it can never
   // match, as it may if the source set changes.
   mCandidates.AppendElement(defaultCandidate);
 }
 
 already_AddRefed<nsIURI>
 ResponsiveImageSelector::GetSelectedImageURL()
 {
@@ -325,16 +331,27 @@ ResponsiveImageSelector::GetSelectedImag
   int bestIndex = GetSelectedCandidateIndex();
   if (bestIndex < 0) {
     return 1.0;
   }
 
   return mCandidates[bestIndex].Density(this);
 }
 
+nsIPrincipal*
+ResponsiveImageSelector::GetSelectedImageTriggeringPrincipal()
+{
+  int bestIndex = GetSelectedCandidateIndex();
+  if (bestIndex < 0) {
+    return nullptr;
+  }
+
+  return mCandidates[bestIndex].TriggeringPrincipal();
+}
+
 bool
 ResponsiveImageSelector::SelectImage(bool aReselect)
 {
   if (!aReselect && mSelectedCandidateIndex != -1) {
     // Already have selection
     return false;
   }
 
@@ -453,31 +470,39 @@ ResponsiveImageSelector::ComputeFinalWid
 
 ResponsiveImageCandidate::ResponsiveImageCandidate()
 {
   mType = eCandidateType_Invalid;
   mValue.mDensity = 1.0;
 }
 
 ResponsiveImageCandidate::ResponsiveImageCandidate(const nsAString& aURLString,
-                                                   double aDensity)
+                                                   double aDensity,
+                                                   nsIPrincipal* aTriggeringPrincipal)
   : mURLString(aURLString)
+  , mTriggeringPrincipal(aTriggeringPrincipal)
 {
   mType = eCandidateType_Density;
   mValue.mDensity = aDensity;
 }
 
 
 void
 ResponsiveImageCandidate::SetURLSpec(const nsAString& aURLString)
 {
   mURLString = aURLString;
 }
 
 void
+ResponsiveImageCandidate::SetTriggeringPrincipal(nsIPrincipal* aPrincipal)
+{
+  mTriggeringPrincipal = aPrincipal;
+}
+
+void
 ResponsiveImageCandidate::SetParameterAsComputedWidth(int32_t aWidth)
 {
   mType = eCandidateType_ComputedFromWidth;
   mValue.mWidth = aWidth;
 }
 
 void
 ResponsiveImageCandidate::SetParameterDefault()
@@ -713,16 +738,22 @@ ResponsiveImageCandidate::HasSameParamet
 }
 
 const nsAString&
 ResponsiveImageCandidate::URLString() const
 {
   return mURLString;
 }
 
+nsIPrincipal*
+ResponsiveImageCandidate::TriggeringPrincipal() const
+{
+  return mTriggeringPrincipal;
+}
+
 double
 ResponsiveImageCandidate::Density(ResponsiveImageSelector *aSelector) const
 {
   if (mType == eCandidateType_ComputedFromWidth) {
     double width;
     if (!aSelector->ComputeFinalWidthForCurrentViewport(&width)) {
       return 1.0;
     }
--- a/dom/base/ResponsiveImageSelector.h
+++ b/dom/base/ResponsiveImageSelector.h
@@ -40,24 +40,26 @@ public:
   //
   // Because the selected image depends on external variants like
   // viewport size and device pixel ratio, the time at which image
   // selection occurs can affect the result.
 
 
   // Given a srcset string, parse and replace current candidates (does not
   // replace default source)
-  bool SetCandidatesFromSourceSet(const nsAString & aSrcSet);
+  bool SetCandidatesFromSourceSet(const nsAString & aSrcSet,
+                                  nsIPrincipal* aTriggeringPrincipal = nullptr);
 
   // Fill the source sizes from a valid sizes descriptor. Returns false if
   // descriptor is invalid.
   bool SetSizesFromDescriptor(const nsAString & aSizesDescriptor);
 
   // Set the default source, treated as the least-precedence 1.0 density source.
-  void SetDefaultSource(const nsAString& aURLString);
+  void SetDefaultSource(const nsAString& aURLString,
+                        nsIPrincipal* aPrincipal = nullptr);
 
   uint32_t NumCandidates(bool aIncludeDefault = true);
 
   // If this was created for a specific content. May be null if we were only
   // created for a document.
   nsIContent *Content();
 
   // The document we were created for, or the owner document of the content if
@@ -65,16 +67,17 @@ public:
   nsIDocument *Document();
 
   // Get the url and density for the selected best candidate. These
   // implicitly cause an image to be selected if necessary.
   already_AddRefed<nsIURI> GetSelectedImageURL();
   // Returns false if there is no selected image
   bool GetSelectedImageURLSpec(nsAString& aResult);
   double GetSelectedImageDensity();
+  nsIPrincipal* GetSelectedImageTriggeringPrincipal();
 
   // Runs image selection now if necessary. If an image has already
   // been choosen, takes no action unless aReselect is true.
   //
   // aReselect - Always re-run selection, replacing the previously
   //             choosen image.
   // return - true if the selected image result changed.
   bool SelectImage(bool aReselect = false);
@@ -103,34 +106,37 @@ private:
   //
   // aContext is the presContext to use for current viewport sizing, null will
   // use the associated content's context.
   bool ComputeFinalWidthForCurrentViewport(double* aWidth);
 
   nsCOMPtr<nsINode> mOwnerNode;
   // The cached URL for default candidate.
   nsString mDefaultSourceURL;
+  nsCOMPtr<nsIPrincipal> mDefaultSourceTriggeringPrincipal;
   // If this array contains an eCandidateType_Default, it should be the last
   // element, such that the Setters can preserve/replace it respectively.
   nsTArray<ResponsiveImageCandidate> mCandidates;
   int mSelectedCandidateIndex;
   // The cached resolved URL for mSelectedCandidateIndex, such that we only
   // resolve the absolute URL at selection time
   nsCOMPtr<nsIURI> mSelectedCandidateURL;
 
   nsTArray< nsAutoPtr<nsMediaQuery> > mSizeQueries;
   nsTArray<nsCSSValue> mSizeValues;
 };
 
 class ResponsiveImageCandidate {
 public:
   ResponsiveImageCandidate();
-  ResponsiveImageCandidate(const nsAString& aURLString, double aDensity);
+  ResponsiveImageCandidate(const nsAString& aURLString, double aDensity,
+                           nsIPrincipal* aTriggeringPrincipal = nullptr);
 
   void SetURLSpec(const nsAString& aURLString);
+  void SetTriggeringPrincipal(nsIPrincipal* aPrincipal);
   // Set this as a default-candidate. This behaves the same as density 1.0, but
   // has a differing type such that it can be replaced by subsequent
   // SetDefaultSource calls.
   void SetParameterDefault();
 
   // Set this candidate as a by-density candidate with specified density.
   void SetParameterAsDensity(double aDensity);
   void SetParameterAsComputedWidth(int32_t aWidth);
@@ -143,16 +149,17 @@ public:
   // of descriptors microsyntax.
   bool ConsumeDescriptors(nsAString::const_iterator& aIter,
                           const nsAString::const_iterator& aIterEnd);
 
   // Check if our parameter (which does not include the url) is identical
   bool HasSameParameter(const ResponsiveImageCandidate & aOther) const;
 
   const nsAString& URLString() const;
+  nsIPrincipal* TriggeringPrincipal() const;
 
   // Compute and return the density relative to a selector.
   double Density(ResponsiveImageSelector *aSelector) const;
   // If the width is already known. Useful when iterating over candidates to
   // avoid having each call re-compute the width.
   double Density(double aMatchingWidth) const;
 
   // If this selector is computed from the selector's matching width.
@@ -167,16 +174,17 @@ public:
     eCandidateType_ComputedFromWidth
   };
 
   eCandidateType Type() const { return mType; }
 
 private:
 
   nsString mURLString;
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   eCandidateType mType;
   union {
     double mDensity;
     int32_t mWidth;
   } mValue;
 };
 
 } // namespace dom
--- a/dom/base/nsContentSink.cpp
+++ b/dom/base/nsContentSink.cpp
@@ -805,17 +805,17 @@ nsContentSink::ProcessStyleLink(nsIConte
   mozilla::net::ReferrerPolicy referrerPolicy =
     mozilla::net::AttributeReferrerPolicyFromString(aReferrerPolicy);
   if (referrerPolicy == net::RP_Unset) {
     referrerPolicy = mDocument->GetReferrerPolicy();
   }
   // If this is a fragment parser, we don't want to observe.
   // We don't support CORS for processing instructions
   bool isAlternate;
-  rv = mCSSLoader->LoadStyleLink(aElement, url, aTitle, aMedia, aAlternate,
+  rv = mCSSLoader->LoadStyleLink(aElement, url, nullptr, aTitle, aMedia, aAlternate,
                                  CORS_NONE, referrerPolicy,
                                  integrity, mRunsToCompletion ? nullptr : this,
                                  &isAlternate);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!isAlternate && !mRunsToCompletion) {
     ++mPendingSheetCount;
     mScriptLoader->AddParserBlockingScriptExecutionBlocker();
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -197,16 +197,17 @@
 #include "nsScriptSecurityManager.h"
 #include "nsSerializationHelper.h"
 #include "nsStreamUtils.h"
 #include "nsTextEditorState.h"
 #include "nsTextFragment.h"
 #include "nsTextNode.h"
 #include "nsThreadUtils.h"
 #include "nsUnicodeProperties.h"
+#include "nsURLHelper.h"
 #include "nsViewManager.h"
 #include "nsViewportInfo.h"
 #include "nsWidgetsCID.h"
 #include "nsIWindowProvider.h"
 #include "nsWrapperCacheInlines.h"
 #include "nsXULPopupManager.h"
 #include "xpcprivate.h" // nsXPConnect
 #include "HTMLSplitOnSpacesTokenizer.h"
@@ -2328,16 +2329,64 @@ nsContentUtils::PrincipalHasPermission(n
 
 // static
 bool
 nsContentUtils::CallerHasPermission(JSContext* aCx, const nsAtom* aPerm)
 {
   return PrincipalHasPermission(SubjectPrincipal(aCx), aPerm);
 }
 
+// static
+nsIPrincipal*
+nsContentUtils::GetAttrTriggeringPrincipal(nsIContent* aContent, const nsAString& aAttrValue,
+                                           nsIPrincipal* aSubjectPrincipal)
+{
+  nsIPrincipal* contentPrin = aContent ? aContent->NodePrincipal() : nullptr;
+
+  // If the subject principal is the same as the content principal, or no
+  // explicit subject principal was provided, we don't need to do any further
+  // checks. Just return the content principal.
+  if (contentPrin == aSubjectPrincipal || !aSubjectPrincipal) {
+    return contentPrin;
+  }
+
+  // If the attribute value is empty, it's not an absolute URL, so don't bother
+  // with more expensive checks.
+  if (!aAttrValue.IsEmpty() &&
+      IsAbsoluteURL(NS_ConvertUTF16toUTF8(aAttrValue))) {
+    return aSubjectPrincipal;
+  }
+
+  return contentPrin;
+}
+
+// static
+bool
+nsContentUtils::IsAbsoluteURL(const nsACString& aURL)
+{
+  nsAutoCString scheme;
+  if (NS_FAILED(net_ExtractURLScheme(aURL, scheme))) {
+    // If we can't extract a scheme, it's not an absolute URL.
+    return false;
+  }
+
+  // If it parses as an absolute StandardURL, it's definitely an absolute URL,
+  // so no need to check with the IO service.
+  if (net_IsAbsoluteURL(aURL)) {
+    return true;
+  }
+
+  uint32_t flags;
+  if (NS_SUCCEEDED(sIOService->GetProtocolFlags(scheme.get(), &flags))) {
+    return flags & nsIProtocolHandler::URI_NORELATIVE;
+  }
+
+  return false;
+}
+
 //static
 bool
 nsContentUtils::InProlog(nsINode *aNode)
 {
   NS_PRECONDITION(aNode, "missing node to nsContentUtils::InProlog");
 
   nsINode* parent = aNode->GetParentNode();
   if (!parent || !parent->IsNodeOfType(nsINode::eDOCUMENT)) {
@@ -10403,23 +10452,27 @@ nsContentUtils::AppendNativeAnonymousChi
   if (!(aFlags & nsIContent::eSkipDocumentLevelNativeAnonymousContent) &&
       aContent == aContent->OwnerDoc()->GetRootElement()) {
     AppendDocumentLevelNativeAnonymousContentTo(aContent->OwnerDoc(), aKids);
   }
 }
 
 /* static */ bool
 nsContentUtils::GetLoadingPrincipalForXULNode(nsIContent* aLoadingNode,
+                                              nsIPrincipal* aDefaultPrincipal,
                                               nsIPrincipal** aLoadingPrincipal)
 {
   MOZ_ASSERT(aLoadingNode);
   MOZ_ASSERT(aLoadingPrincipal);
 
   bool result = false;
-  nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingNode->NodePrincipal();
+  nsCOMPtr<nsIPrincipal> loadingPrincipal = aDefaultPrincipal;
+  if (!loadingPrincipal) {
+    loadingPrincipal = aLoadingNode->NodePrincipal();
+  }
   nsAutoString loadingStr;
   aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal,
                         loadingStr);
 
   // Fall back to mContent's principal if 'loadingprincipal' isn't specified,
   // or if the doc isn't loaded by System Principal.
   if (loadingStr.IsEmpty() ||
       !aLoadingNode->OwnerDoc()->NodePrincipal()->GetIsSystemPrincipal()) {
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -596,16 +596,50 @@ public:
 
   // Check if the principal is chrome or an addon with the permission.
   static bool PrincipalHasPermission(nsIPrincipal* aPrincipal, const nsAtom* aPerm);
 
   // Check if the JS caller is chrome or an addon with the permission.
   static bool CallerHasPermission(JSContext* aCx, const nsAtom* aPerm);
 
   /**
+   * Returns the triggering principal which should be used for the given URL
+   * attribute value with the given subject principal.
+   *
+   * If the attribute value is not an absolute URL, the subject principal will
+   * be ignored, and the node principal of aContent will be used instead.
+   * If aContent is non-null, this function will always return a principal.
+   * Otherewise, it may return null if aSubjectPrincipal is null or is rejected
+   * based on the attribute value.
+   *
+   * @param aContent The content on which the attribute is being set.
+   * @param aAttrValue The URL value of the attribute. For parsed attribute
+   *        values, such as `srcset`, this function should be called separately
+   *        for each URL value it contains.
+   * @param aSubjectPrincipal The subject principal of the scripted caller
+   *        responsible for setting the attribute, or null if no scripted caller
+   *        can be determined.
+   */
+  static nsIPrincipal* GetAttrTriggeringPrincipal(nsIContent* aContent,
+                                                  const nsAString& aAttrValue,
+                                                  nsIPrincipal* aSubjectPrincipal);
+
+  /**
+   * Returns true if the given string is guaranteed to be treated as an absolute
+   * URL, rather than a relative URL. In practice, this means any complete URL
+   * as supported by nsStandardURL, or any string beginning with a valid scheme
+   * which is known to the IO service, and has the URI_NORELATIVE flag.
+   *
+   * If the URL may be treated as absolute in some cases, but relative in others
+   * (for instance, "http:foo", which can be either an absolute or relative URL,
+   * depending on the context), this function returns false.
+   */
+  static bool IsAbsoluteURL(const nsACString& aURL);
+
+  /**
    * GetDocumentFromCaller gets its document by looking at the last called
    * function and finding the document that the function itself relates to.
    * For example, consider two windows A and B in the same origin. B has a
    * function which does something that ends up needing the current document.
    * If a script in window A were to call B's function, GetDocumentFromCaller
    * would find that function (in B) and return B's document.
    *
    * @return The document or null if no JS Context.
@@ -3054,17 +3088,25 @@ public:
    * (which is System Principal).
    *
    * Return true if aLoadingPrincipal has 'loadingprincipal' attributes, and
    * the value 'loadingprincipal' is also successfully deserialized, otherwise
    * return false.
    */
   static bool
   GetLoadingPrincipalForXULNode(nsIContent* aLoadingNode,
-                                nsIPrincipal** aLoadingPrincipal);
+                                nsIPrincipal* aDefaultPrincipal,
+                                nsIPrincipal** aTriggeringPrincipal);
+
+  static bool
+  GetLoadingPrincipalForXULNode(nsIContent* aLoadingNode,
+                                nsIPrincipal** aTriggeringPrincipal)
+  {
+    return GetLoadingPrincipalForXULNode(aLoadingNode, nullptr, aTriggeringPrincipal);
+  }
 
   /**
    * Returns the content policy type that should be used for loading images
    * for displaying in the UI.  The sources of such images can be <xul:image>,
    * <xul:menuitem> on OSX where we load the image through nsMenuItemIconX, etc.
    */
   static void
   GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode,
--- a/dom/base/nsDeprecatedOperationList.h
+++ b/dom/base/nsDeprecatedOperationList.h
@@ -5,25 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 // IWYU pragma: private, include "nsIDocument.h"
 
 /*
  * This file contains the list of deprecated DOM operations.  It is
  * designed to be used as input to the C preprocessor *only*.
  */
 
-DEPRECATED_OPERATION(GetAttributeNode)
-DEPRECATED_OPERATION(SetAttributeNode)
-DEPRECATED_OPERATION(GetAttributeNodeNS)
-DEPRECATED_OPERATION(SetAttributeNodeNS)
-DEPRECATED_OPERATION(RemoveAttributeNode)
-DEPRECATED_OPERATION(CreateAttribute)
-DEPRECATED_OPERATION(CreateAttributeNS)
-DEPRECATED_OPERATION(NodeValue)
-DEPRECATED_OPERATION(TextContent)
 DEPRECATED_OPERATION(EnablePrivilege)
 DEPRECATED_OPERATION(DOMExceptionCode)
 DEPRECATED_OPERATION(MutationEvent)
 DEPRECATED_OPERATION(Components)
 DEPRECATED_OPERATION(PrefixedVisibilityAPI)
 DEPRECATED_OPERATION(NodeIteratorDetach)
 DEPRECATED_OPERATION(LenientThis)
 DEPRECATED_OPERATION(GetPreventDefault)
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6241,18 +6241,16 @@ nsDocument::CreateAttribute(const nsAStr
   ErrorResult rv;
   *aReturn = nsIDocument::CreateAttribute(aName, rv).take();
   return rv.StealNSResult();
 }
 
 already_AddRefed<Attr>
 nsIDocument::CreateAttribute(const nsAString& aName, ErrorResult& rv)
 {
-  WarnOnceAbout(eCreateAttribute);
-
   if (!mNodeInfoManager) {
     rv.Throw(NS_ERROR_NOT_INITIALIZED);
     return nullptr;
   }
 
   nsresult res = nsContentUtils::CheckQName(aName, false);
   if (NS_FAILED(res)) {
     rv.Throw(res);
@@ -6291,18 +6289,16 @@ nsDocument::CreateAttributeNS(const nsAS
   return rv.StealNSResult();
 }
 
 already_AddRefed<Attr>
 nsIDocument::CreateAttributeNS(const nsAString& aNamespaceURI,
                                const nsAString& aQualifiedName,
                                ErrorResult& rv)
 {
-  WarnOnceAbout(eCreateAttributeNS);
-
   RefPtr<mozilla::dom::NodeInfo> nodeInfo;
   rv = nsContentUtils::GetNodeInfoFromQName(aNamespaceURI,
                                             aQualifiedName,
                                             mNodeInfoManager,
                                             nsIDOMNode::ATTRIBUTE_NODE,
                                             getter_AddRefs(nodeInfo));
   if (rv.Failed()) {
     return nullptr;
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -52,16 +52,17 @@
 #include "nsGlobalWindow.h"
 #include "nsPIWindowRoot.h"
 #include "nsLayoutUtils.h"
 #include "nsMappedAttributes.h"
 #include "nsView.h"
 #include "nsBaseWidget.h"
 #include "GroupedSHistory.h"
 #include "PartialSHistory.h"
+#include "nsQueryObject.h"
 
 #include "nsIURI.h"
 #include "nsIURL.h"
 #include "nsNetUtil.h"
 
 #include "nsGkAtoms.h"
 #include "nsNameSpaceManager.h"
 
@@ -80,16 +81,17 @@
 #include "mozilla/GuardObjects.h"
 #include "mozilla/HTMLEditor.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Unused.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/dom/FrameLoaderBinding.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrameParent.h"
+#include "nsGenericHTMLFrameElement.h"
 #include "GeckoProfiler.h"
 
 #include "jsapi.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/layers/CompositorBridgeChild.h"
 #include "mozilla/dom/CustomEvent.h"
 
@@ -241,24 +243,25 @@ nsFrameLoader::LoadFrame(ErrorResult& aR
 }
 
 NS_IMETHODIMP
 nsFrameLoader::LoadFrame()
 {
   NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
 
   nsAutoString src;
+  nsCOMPtr<nsIPrincipal> principal;
 
   bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
                   mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
   if (isSrcdoc) {
     src.AssignLiteral("about:srcdoc");
   }
   else {
-    GetURL(src);
+    GetURL(src, getter_AddRefs(principal));
 
     src.Trim(" \t\n\r");
 
     if (src.IsEmpty()) {
       // If the frame is a XUL element and has the attribute 'nodefaultsrc=true'
       // then we will not use 'about:blank' as fallback but return early without
       // starting a load if no 'src' attribute is given (or it's empty).
       if (mOwnerContent->IsXULElement() &&
@@ -288,17 +291,17 @@ nsFrameLoader::LoadFrame()
 
   // If the URI was malformed, try to recover by loading about:blank.
   if (rv == NS_ERROR_MALFORMED_URI) {
     rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_STRING("about:blank"),
                    encoding, base_uri);
   }
 
   if (NS_SUCCEEDED(rv)) {
-    rv = LoadURI(uri);
+    rv = LoadURI(uri, principal);
   }
 
   if (NS_FAILED(rv)) {
     FireErrorEvent();
 
     return rv;
   }
 
@@ -325,36 +328,44 @@ nsFrameLoader::LoadURI(nsIURI* aURI, Err
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
   }
 }
 
 NS_IMETHODIMP
 nsFrameLoader::LoadURI(nsIURI* aURI)
 {
+  return LoadURI(aURI, nullptr);
+}
+
+nsresult
+nsFrameLoader::LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal)
+{
   if (!aURI)
     return NS_ERROR_INVALID_POINTER;
   NS_ENSURE_STATE(!mDestroyCalled && mOwnerContent);
 
   nsCOMPtr<nsIDocument> doc = mOwnerContent->OwnerDoc();
 
   nsresult rv;
   // If IsForJSPlugin() returns true then we want to allow the load. We're just
   // loading the source for the implementation of the JS plugin from a URI
   // that's under our control. We will already have done the security checks for
   // loading the plugin content itself in the object/embed loading code.
   if (!IsForJSPlugin()) {
-    rv = CheckURILoad(aURI);
+    rv = CheckURILoad(aURI, aTriggeringPrincipal);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   mURIToLoad = aURI;
+  mTriggeringPrincipal = aTriggeringPrincipal;
   rv = doc->InitializeFrameLoader(this);
   if (NS_FAILED(rv)) {
     mURIToLoad = nullptr;
+    mTriggeringPrincipal = nullptr;
   }
   return rv;
 }
 
 void
 nsFrameLoader::SetIsPrerendered(ErrorResult& aRv)
 {
   nsresult rv = SetIsPrerendered();
@@ -899,31 +910,35 @@ nsFrameLoader::ReallyStartLoadingInterna
   nsresult rv = MaybeCreateDocShell();
   if (NS_FAILED(rv)) {
     return rv;
   }
   NS_ASSERTION(mDocShell,
                "MaybeCreateDocShell succeeded with a null mDocShell");
 
   // Just to be safe, recheck uri.
-  rv = CheckURILoad(mURIToLoad);
+  rv = CheckURILoad(mURIToLoad, mTriggeringPrincipal);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
   mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
   NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
 
   // If this frame is sandboxed with respect to origin we will set it up with
   // a null principal later in nsDocShell::DoURILoad.
   // We do it there to correctly sandbox content that was loaded into
   // the frame via other methods than the src attribute.
   // We'll use our principal, not that of the document loaded inside us.  This
   // is very important; needed to prevent XSS attacks on documents loaded in
   // subframes!
-  loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
+  if (mTriggeringPrincipal) {
+    loadInfo->SetTriggeringPrincipal(mTriggeringPrincipal);
+  } else {
+    loadInfo->SetTriggeringPrincipal(mOwnerContent->NodePrincipal());
+  }
 
   nsCOMPtr<nsIURI> referrer;
 
   nsAutoString srcdoc;
   bool isSrcdoc = mOwnerContent->IsHTMLElement(nsGkAtoms::iframe) &&
                   mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
                                          srcdoc);
 
@@ -984,17 +999,17 @@ nsFrameLoader::ReallyStartLoadingInterna
   mNeedsAsyncDestroy = tmpState;
   mURIToLoad = nullptr;
   NS_ENSURE_SUCCESS(rv, rv);
 
   return NS_OK;
 }
 
 nsresult
-nsFrameLoader::CheckURILoad(nsIURI* aURI)
+nsFrameLoader::CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal)
 {
   // Check for security.  The fun part is trying to figure out what principals
   // to use.  The way I figure it, if we're doing a LoadFrame() accidentally
   // (eg someone created a frame/iframe node, we're being parsed, XUL iframes
   // are being reframed, etc.) then we definitely want to use the node
   // principal of mOwnerContent for security checks.  If, on the other hand,
   // someone's setting the src on our owner content, or created it via script,
   // or whatever, then they can clearly access it... and we should still use
@@ -1003,17 +1018,19 @@ nsFrameLoader::CheckURILoad(nsIURI* aURI
   // (since caller can already access mOwnerContent in this case).  So just use
   // the principal of mOwnerContent no matter what.  If script wants to run
   // things with its own permissions, which differ from those of mOwnerContent
   // (which means the script is privileged in some way) it should set
   // window.location instead.
   nsIScriptSecurityManager *secMan = nsContentUtils::GetSecurityManager();
 
   // Get our principal
-  nsIPrincipal* principal = mOwnerContent->NodePrincipal();
+  nsIPrincipal* principal = (aTriggeringPrincipal
+                             ? aTriggeringPrincipal
+                             : mOwnerContent->NodePrincipal());
 
   // Check if we are allowed to load absURL
   nsresult rv =
     secMan->CheckLoadURIWithPrincipal(principal, aURI,
                                       nsIScriptSecurityManager::STANDARD);
   if (NS_FAILED(rv)) {
     return rv; // We're not
   }
@@ -2727,24 +2744,28 @@ nsFrameLoader::MaybeCreateDocShell()
     os->NotifyObservers(NS_ISUPPORTS_CAST(nsIFrameLoader*, this),
                         "inprocess-browser-shown", nullptr);
   }
 
   return NS_OK;
 }
 
 void
-nsFrameLoader::GetURL(nsString& aURI)
+nsFrameLoader::GetURL(nsString& aURI, nsIPrincipal** aTriggeringPrincipal)
 {
   aURI.Truncate();
 
   if (mOwnerContent->IsHTMLElement(nsGkAtoms::object)) {
     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::data, aURI);
   } else {
     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, aURI);
+    if (RefPtr<nsGenericHTMLFrameElement> frame = do_QueryObject(mOwnerContent)) {
+      nsCOMPtr<nsIPrincipal> prin = frame->GetSrcTriggeringPrincipal();
+      prin.forget(aTriggeringPrincipal);
+    }
   }
 }
 
 nsresult
 nsFrameLoader::CheckForRecursiveLoad(nsIURI* aURI)
 {
   nsresult rv;
 
--- a/dom/base/nsFrameLoader.h
+++ b/dom/base/nsFrameLoader.h
@@ -108,16 +108,26 @@ public:
   already_AddRefed<nsITabParent> GetTabParent();
 
   already_AddRefed<nsILoadContext> LoadContext();
 
   void LoadFrame(mozilla::ErrorResult& aRv);
 
   void LoadURI(nsIURI* aURI, mozilla::ErrorResult& aRv);
 
+  /**
+   * Triggers a load of the given URI.
+   *
+   * @param aURI The URI to load.
+   * @param aTriggeringPrincipal The triggering principal for the load. May be
+   *        null, in which case the node principal of the owner content will be
+   *        used.
+   */
+  nsresult LoadURI(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal);
+
   void SetIsPrerendered(mozilla::ErrorResult& aRv);
 
   void MakePrerenderedLoaderActive(mozilla::ErrorResult& aRv);
 
   already_AddRefed<mozilla::dom::Promise>
   AppendPartialSHistoryAndSwap(nsIFrameLoader& aOther, mozilla::ErrorResult& aRv);
 
   already_AddRefed<mozilla::dom::Promise>
@@ -319,17 +329,17 @@ public:
 
   /**
    * Applies a new set of sandbox flags. These are merged with the sandbox
    * flags from our owning content's owning document with a logical OR, this
    * ensures that we can only add restrictions and never remove them.
    */
   void ApplySandboxFlags(uint32_t sandboxFlags);
 
-  void GetURL(nsString& aURL);
+  void GetURL(nsString& aURL, nsIPrincipal** aTriggeringPrincipal);
 
   // Properly retrieves documentSize of any subdocument type.
   nsresult GetWindowDimensions(nsIntRect& aRect);
 
   virtual nsIMessageSender* GetProcessMessageManager() const override;
 
   // public because a callback needs these.
   RefPtr<nsFrameMessageManager> mMessageManager;
@@ -379,17 +389,26 @@ private:
    */
   nsresult MaybeCreateDocShell();
   nsresult EnsureMessageManager();
   nsresult ReallyLoadFrameScripts();
 
   // Updates the subdocument position and size. This gets called only
   // when we have our own in-process DocShell.
   void UpdateBaseWindowPositionAndSize(nsSubDocumentFrame *aIFrame);
-  nsresult CheckURILoad(nsIURI* aURI);
+
+  /**
+   * Checks whether a load of the given URI should be allowed, and returns an
+   * error result if it should not.
+   *
+   * @param aURI The URI to check.
+   * @param aTriggeringPrincipal The triggering principal for the load. May be
+   *        null, in which case the node principal of the owner content is used.
+   */
+  nsresult CheckURILoad(nsIURI* aURI, nsIPrincipal* aTriggeringPrincipal);
   void FireErrorEvent();
   nsresult ReallyStartLoadingInternal();
 
   // Return true if remote browser created; nothing else to do
   bool TryRemoteBrowser();
 
   // Tell the remote browser that it's now "virtually visible"
   bool ShowRemoteFrame(const mozilla::ScreenIntSize& size,
@@ -425,16 +444,17 @@ private:
   bool SwapBrowsersAndNotify(nsFrameLoader* aOther);
 
   // Returns a promise which will be resolved once all of the blockers have
   // resolved which were added during the BrowserWillChangeProcess event.
   already_AddRefed<mozilla::dom::Promise> FireWillChangeProcessEvent();
 
   nsCOMPtr<nsIDocShell> mDocShell;
   nsCOMPtr<nsIURI> mURIToLoad;
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   mozilla::dom::Element* mOwnerContent; // WEAK
 
   // After the frameloader has been removed from the DOM but before all of the
   // messages from the frame have been received, we keep a strong reference to
   // our <browser> element.
   RefPtr<mozilla::dom::Element> mOwnerContentStrong;
 
   // Stores the root frame of the subdocument while the subdocument is being
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -634,16 +634,17 @@ already_AddRefed<nsINodeList>
 nsGenericDOMDataNode::GetChildren(uint32_t aFilter)
 {
   return nullptr;
 }
 
 nsresult
 nsGenericDOMDataNode::SetAttr(int32_t aNameSpaceID, nsAtom* aAttr,
                               nsAtom* aPrefix, const nsAString& aValue,
+                              nsIPrincipal* aContentPrincipal,
                               bool aNotify)
 {
   return NS_OK;
 }
 
 nsresult
 nsGenericDOMDataNode::UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttr,
                                 bool aNotify)
--- a/dom/base/nsGenericDOMDataNode.h
+++ b/dom/base/nsGenericDOMDataNode.h
@@ -122,23 +122,20 @@ public:
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
 
   virtual already_AddRefed<nsINodeList> GetChildren(uint32_t aFilter) override;
 
 
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
-  }
+  using nsIContent::SetAttr;
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                            nsAtom* aPrefix, const nsAString& aValue,
+                           nsIPrincipal* aSubjectPrincipal,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                              bool aNotify) override;
   virtual const nsAttrName* GetAttrNameAt(uint32_t aIndex) const override;
   virtual mozilla::dom::BorrowedAttrInfo GetAttrInfoAt(uint32_t aIndex) const override;
   virtual uint32_t GetAttrCount() const override;
   virtual const nsTextFragment *GetText() override;
   virtual uint32_t TextLength() const override;
--- a/dom/base/nsIContent.h
+++ b/dom/base/nsIContent.h
@@ -368,33 +368,50 @@ public:
    * @param aNotify specifies how whether or not the document should be
    *        notified of the attribute change.
    */
   nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
   }
+  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, nsAtom* aPrefix,
+                   const nsAString& aValue, bool aNotify)
+  {
+    return SetAttr(aNameSpaceID, aName, aPrefix, aValue, nullptr, aNotify);
+  }
+  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName, const nsAString& aValue,
+                   nsIPrincipal* aTriggeringPrincipal, bool aNotify)
+  {
+    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aTriggeringPrincipal, aNotify);
+  }
 
   /**
    * Set attribute values. All attribute values are assumed to have a
    * canonical String representation that can be used for these
    * methods. The SetAttr method is assumed to perform a translation
    * of the canonical form into the underlying content specific
    * form.
    *
    * @param aNameSpaceID the namespace of the attribute
    * @param aName the name of the attribute
    * @param aPrefix the prefix of the attribute
    * @param aValue the value to set
+   * @param aMaybeScriptedPrincipal the principal of the scripted caller responsible
+   *        for setting the attribute, or null if no scripted caller can be
+   *        determined. A null value here does not guarantee that there is no
+   *        scripted caller, but a non-null value does guarantee that a scripted
+   *        caller with the given principal is directly responsible for the
+   *        attribute change.
    * @param aNotify specifies how whether or not the document should be
    *        notified of the attribute change.
    */
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                            nsAtom* aPrefix, const nsAString& aValue,
+                           nsIPrincipal* aMaybeScriptedPrincipal,
                            bool aNotify) = 0;
 
   /**
    * Get the current value of the attribute. This returns a form that is
    * suitable for passing back into SetAttr.
    *
    * @param aNameSpaceID the namespace of the attr
    * @param aName the name of the attr
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -892,17 +892,18 @@ nsImageLoadingContent::UnblockOnload(img
 /*
  * Non-interface methods
  */
 
 nsresult
 nsImageLoadingContent::LoadImage(const nsAString& aNewURI,
                                  bool aForce,
                                  bool aNotify,
-                                 ImageLoadType aImageLoadType)
+                                 ImageLoadType aImageLoadType,
+                                 nsIPrincipal* aTriggeringPrincipal)
 {
   // First, get a document (needed for security checks and the like)
   nsIDocument* doc = GetOurOwnerDoc();
   if (!doc) {
     // No reason to bother, I think...
     return NS_OK;
   }
 
@@ -926,27 +927,29 @@ nsImageLoadingContent::LoadImage(const n
   // Parse the URI string to get image URI
   nsCOMPtr<nsIURI> imageURI;
   nsresult rv = StringToURI(aNewURI, doc, getter_AddRefs(imageURI));
   NS_ENSURE_SUCCESS(rv, rv);
   // XXXbiesi fire onerror if that failed?
 
   NS_TryToSetImmutable(imageURI);
 
-  return LoadImage(imageURI, aForce, aNotify, aImageLoadType, false, doc);
+  return LoadImage(imageURI, aForce, aNotify, aImageLoadType, false, doc,
+                   nsIRequest::LOAD_NORMAL, aTriggeringPrincipal);
 }
 
 nsresult
 nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
                                  bool aForce,
                                  bool aNotify,
                                  ImageLoadType aImageLoadType,
                                  bool aLoadStart,
                                  nsIDocument* aDocument,
-                                 nsLoadFlags aLoadFlags)
+                                 nsLoadFlags aLoadFlags,
+                                 nsIPrincipal* aTriggeringPrincipal)
 {
   MOZ_ASSERT(!mIsStartingImageLoad, "some evil code is reentering LoadImage.");
   if (mIsStartingImageLoad) {
     return NS_OK;
   }
 
   // Pending load/error events need to be canceled in some situations. This
   // is not documented in the spec, but can cause site compat problems if not
@@ -1034,33 +1037,33 @@ nsImageLoadingContent::LoadImage(nsIURI*
   if (imgReferrerPolicy != net::RP_Unset) {
     referrerPolicy = imgReferrerPolicy;
   }
 
   RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
   nsCOMPtr<nsIContent> content =
       do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
-  nsCOMPtr<nsIPrincipal> loadingPrincipal;
+  nsCOMPtr<nsIPrincipal> triggeringPrincipal;
   bool result =
-    nsContentUtils::GetLoadingPrincipalForXULNode(content,
-                                                  getter_AddRefs(loadingPrincipal));
+    nsContentUtils::GetLoadingPrincipalForXULNode(content, aTriggeringPrincipal,
+                                                  getter_AddRefs(triggeringPrincipal));
 
   // If result is true, which means this node has specified 'loadingprincipal'
   // attribute on it, so we use favicon as the policy type.
   nsContentPolicyType policyType = result ?
                                      nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
                                      PolicyTypeForLoad(aImageLoadType);
 
   nsCOMPtr<nsINode> thisNode =
     do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
   nsresult rv = nsContentUtils::LoadImage(aNewURI,
                                           thisNode,
                                           aDocument,
-                                          loadingPrincipal,
+                                          triggeringPrincipal,
                                           0,
                                           aDocument->GetDocumentURI(),
                                           referrerPolicy,
                                           this, loadFlags,
                                           content->LocalName(),
                                           getter_AddRefs(req),
                                           policyType,
                                           mUseUrgentStartForChannel);
--- a/dom/base/nsImageLoadingContent.h
+++ b/dom/base/nsImageLoadingContent.h
@@ -98,19 +98,22 @@ protected:
    * into this superclass.
    *
    * @param aNewURI the URI spec to be loaded (may be a relative URI)
    * @param aForce If true, make sure to load the URI.  If false, only
    *        load if the URI is different from the currently loaded URI.
    * @param aNotify If true, nsIDocumentObserver state change notifications
    *                will be sent as needed.
    * @param aImageLoadType The ImageLoadType for this request
+   * @param aTriggeringPrincipal Optional parameter specifying the triggering
+   *        principal to use for the image load
    */
   nsresult LoadImage(const nsAString& aNewURI, bool aForce,
-                     bool aNotify, ImageLoadType aImageLoadType);
+                     bool aNotify, ImageLoadType aImageLoadType,
+                     nsIPrincipal* aTriggeringPrincipal = nullptr);
 
   /**
    * ImageState is called by subclasses that are computing their content state.
    * The return value will have the NS_EVENT_STATE_BROKEN,
    * NS_EVENT_STATE_USERDISABLED, and NS_EVENT_STATE_SUPPRESSED bits set as
    * needed.  Note that this state assumes that this node is "trying" to be an
    * image (so for example complete lack of attempt to load an image will lead
    * to NS_EVENT_STATE_BROKEN being set).  Subclasses that are not "trying" to
@@ -130,21 +133,33 @@ protected:
    * @param aNotify If true, nsIDocumentObserver state change notifications
    *                will be sent as needed.
    * @param aImageLoadType The ImageLoadType for this request
    * @param aLoadStart If true, dispatch "loadstart" event.
    * @param aDocument Optional parameter giving the document this node is in.
    *        This is purely a performance optimization.
    * @param aLoadFlags Optional parameter specifying load flags to use for
    *        the image load
+   * @param aTriggeringPrincipal Optional parameter specifying the triggering
+   *        principal to use for the image load
    */
   nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify,
                      ImageLoadType aImageLoadType, bool aLoadStart = true,
                      nsIDocument* aDocument = nullptr,
-                     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL);
+                     nsLoadFlags aLoadFlags = nsIRequest::LOAD_NORMAL,
+                     nsIPrincipal* aTriggeringPrincipal = nullptr);
+
+  nsresult LoadImage(nsIURI* aNewURI, bool aForce, bool aNotify,
+                     ImageLoadType aImageLoadType,
+                     nsIPrincipal* aTriggeringPrincipal)
+  {
+    return LoadImage(aNewURI, aForce, aNotify, aImageLoadType,
+                     true, nullptr, nsIRequest::LOAD_NORMAL,
+                     aTriggeringPrincipal);
+  }
 
   /**
    * helpers to get the document for this content (from the nodeinfo
    * and such).  Not named GetOwnerDoc/GetCurrentDoc to prevent ambiguous
    * method names in subclasses
    *
    * @return the document we belong to
    */
--- a/dom/base/nsStyleLinkElement.cpp
+++ b/dom/base/nsStyleLinkElement.cpp
@@ -318,18 +318,17 @@ nsStyleLinkElement::CheckPreloadAttrs(co
 NS_IMETHODIMP
 nsStyleLinkElement::UpdateStyleSheet(nsICSSLoaderObserver* aObserver,
                                      bool* aWillNotify,
                                      bool* aIsAlternate,
                                      bool aForceReload)
 {
   if (aForceReload) {
     // We remove this stylesheet from the cache to load a new version.
-    nsCOMPtr<nsIContent> thisContent;
-    CallQueryInterface(this, getter_AddRefs(thisContent));
+    nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
     nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
       thisContent->OwnerDoc() : thisContent->GetUncomposedDoc();
     if (doc && doc->CSSLoader()->GetEnabled() &&
         mStyleSheet && !mStyleSheet->IsInline()) {
       doc->CSSLoader()->ObsoleteSheet(mStyleSheet->GetOriginalURI());
     }
   }
   return DoUpdateStyleSheet(nullptr, nullptr, aObserver, aWillNotify,
@@ -401,21 +400,19 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
                                        ShadowRoot* aOldShadowRoot,
                                        nsICSSLoaderObserver* aObserver,
                                        bool* aWillNotify,
                                        bool* aIsAlternate,
                                        bool aForceUpdate)
 {
   *aWillNotify = false;
 
-  nsCOMPtr<nsIContent> thisContent;
-  CallQueryInterface(this, getter_AddRefs(thisContent));
-
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
   // All instances of nsStyleLinkElement should implement nsIContent.
-  NS_ENSURE_TRUE(thisContent, NS_ERROR_FAILURE);
+  MOZ_ASSERT(thisContent);
 
   if (thisContent->IsInAnonymousSubtree() &&
       thisContent->IsAnonymousContentInSVGUseSubtree()) {
     // Stylesheets in <use>-cloned subtrees are disabled until we figure out
     // how they should behave.
     return NS_OK;
   }
 
@@ -469,17 +466,18 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
 
   nsCOMPtr<nsIDocument> doc = thisContent->IsInShadowTree() ?
     thisContent->OwnerDoc() : thisContent->GetUncomposedDoc();
   if (!doc || !doc->CSSLoader()->GetEnabled()) {
     return NS_OK;
   }
 
   bool isInline;
-  nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline);
+  nsCOMPtr<nsIPrincipal> triggeringPrincipal;
+  nsCOMPtr<nsIURI> uri = GetStyleSheetURL(&isInline, getter_AddRefs(triggeringPrincipal));
 
   if (!aForceUpdate && mStyleSheet && !isInline && uri) {
     nsIURI* oldURI = mStyleSheet->GetSheetURI();
     if (oldURI) {
       bool equal;
       nsresult rv = oldURI->Equals(uri, &equal);
       if (NS_SUCCEEDED(rv) && equal) {
         return NS_OK; // We already loaded this stylesheet
@@ -561,18 +559,18 @@ nsStyleLinkElement::DoUpdateStyleSheet(n
                NS_ConvertUTF16toUTF8(integrity).get()));
     }
 
     // XXXbz clone the URI here to work around content policies modifying URIs.
     nsCOMPtr<nsIURI> clonedURI;
     uri->Clone(getter_AddRefs(clonedURI));
     NS_ENSURE_TRUE(clonedURI, NS_ERROR_OUT_OF_MEMORY);
     rv = doc->CSSLoader()->
-      LoadStyleLink(thisContent, clonedURI, title, media, isAlternate,
-                    GetCORSMode(), referrerPolicy, integrity,
+      LoadStyleLink(thisContent, clonedURI, triggeringPrincipal, title, media,
+                    isAlternate, GetCORSMode(), referrerPolicy, integrity,
                     aObserver, &isAlternate);
     if (NS_FAILED(rv)) {
       // Don't propagate LoadStyleLink() errors further than this, since some
       // consumers (e.g. nsXMLContentSink) will completely abort on innocuous
       // things like a stylesheet load being blocked by the security system.
       doneLoading = true;
       isAlternate = false;
       rv = NS_OK;
@@ -597,18 +595,17 @@ nsStyleLinkElement::UpdateStyleSheetScop
   if (mStyleSheet->IsServo()) {
     // XXXheycam ServoStyleSheets don't support <style scoped>.
     NS_ERROR("stylo: ServoStyleSheets don't support <style scoped>");
     return;
   }
 
   CSSStyleSheet* sheet = mStyleSheet->AsGecko();
 
-  nsCOMPtr<nsIContent> thisContent;
-  CallQueryInterface(this, getter_AddRefs(thisContent));
+  nsCOMPtr<nsIContent> thisContent = do_QueryInterface(this);
 
   Element* oldScopeElement = sheet->GetScopeElement();
   Element* newScopeElement = aIsNowScoped ?
                                thisContent->GetParentElement() :
                                nullptr;
 
   if (oldScopeElement == newScopeElement) {
     return;
--- a/dom/base/nsStyleLinkElement.h
+++ b/dom/base/nsStyleLinkElement.h
@@ -88,17 +88,17 @@ protected:
    *                     changed but the URI may not have changed.
    */
   nsresult UpdateStyleSheetInternal(nsIDocument *aOldDocument,
                                     mozilla::dom::ShadowRoot *aOldShadowRoot,
                                     bool aForceUpdate = false);
 
   void UpdateStyleSheetScopedness(bool aIsNowScoped);
 
-  virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) = 0;
+  virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) = 0;
   virtual void GetStyleSheetInfo(nsAString& aTitle,
                                  nsAString& aType,
                                  nsAString& aMedia,
                                  bool* aIsScoped,
                                  bool* aIsAlternate) = 0;
 
   virtual mozilla::CORSMode GetCORSMode() const
   {
@@ -132,15 +132,16 @@ private:
                               mozilla::dom::ShadowRoot* aOldShadowRoot,
                               nsICSSLoaderObserver* aObserver,
                               bool* aWillNotify,
                               bool* aIsAlternate,
                               bool aForceUpdate);
 
   RefPtr<mozilla::StyleSheet> mStyleSheet;
 protected:
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   bool mDontLoadStyle;
   bool mUpdatesEnabled;
   uint32_t mLineNumber;
 };
 
 #endif /* nsStyleLinkElement_h___ */
 
--- a/dom/base/nsStyledElement.cpp
+++ b/dom/base/nsStyledElement.cpp
@@ -104,17 +104,18 @@ nsStyledElement::SetInlineStyleDeclarati
   // XXXbz do we ever end up with ADDITION here?  I doubt it.
   uint8_t modType = modification ?
     static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) :
     static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
 
   nsIDocument* document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
   return SetAttrAndNotify(kNameSpaceID_None, nsGkAtoms::style, nullptr,
-                          oldValueSet ? &oldValue : nullptr, attrValue, modType,
+                          oldValueSet ? &oldValue : nullptr, attrValue,
+                          nullptr, modType,
                           hasListeners, aNotify, kDontCallAfterSetAttr,
                           document, updateBatch);
 }
 
 // ---------------------------------------------------------------
 // Others and helpers
 
 nsICSSDeclaration*
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -621,16 +621,17 @@ skip-if = toolkit == 'android'
 [test_bug1314032.html]
 [test_bug1318303.html]
 [test_bug1375050.html]
 [test_bug1381710.html]
 [test_bug1384658.html]
 skip-if = toolkit == 'android'
 [test_bug1399603.html]
 [test_bug1399605.html]
+[test_bug1406102.html]
 [test_caretPositionFromPoint.html]
 [test_change_policy.html]
 [test_clearTimeoutIntervalNoArg.html]
 [test_constructor-assignment.html]
 [test_constructor.html]
 [test_copyimage.html]
 subsuite = clipboard
 skip-if = toolkit == 'android' #bug 904183
new file mode 100644
--- /dev/null
+++ b/dom/base/test/test_bug1406102.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1406102</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <style type="text/css">
+    html {
+        height: 100%;
+    }
+    body {
+        height: 2866px;
+    }
+  </style>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1406102">Mozilla Bug 1406102</a>
+<p id="display"></p>
+<div id="content">
+  <div id="target"></div>
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+  let observer = new IntersectionObserver(function (changes) {
+    ok(changes[0].intersectionRatio > 0, 'intersectionRatio should be greater than zero');
+    SimpleTest.finish();
+  });
+  observer.observe(document.body);
+  SimpleTest.waitForExplicitFinish();
+
+</script>
+</pre>
+<div id="log">
+</div>
+</body>
+</html>
--- a/dom/bindings/test/TestCodeGen.webidl
+++ b/dom/bindings/test/TestCodeGen.webidl
@@ -794,37 +794,37 @@ interface TestInterface {
 
   // Typedefs
   const myLong myLongConstant = 5;
   void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
   AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
   void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
 
   // Deprecated methods and attributes
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   attribute byte deprecatedAttribute;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   byte deprecatedMethod();
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   byte deprecatedMethodWithContext(any arg);
 
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
   static void staticMethodWithContext(any arg);
 
   // Testing static method with a reserved C++ keyword as the name
   static void assert(boolean arg);
 
   // Deprecated static methods and attributes
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static attribute byte staticDeprecatedAttribute;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static void staticDeprecatedMethod();
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static void staticDeprecatedMethodWithContext(any arg);
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestInterface arg);
   TestInterface overload1(DOMString strs, TestInterface arg);
   void overload2(TestInterface arg);
   void overload2(optional Dict arg);
@@ -1256,17 +1256,17 @@ interface TestNamedDeleterWithRetvalInte
 };
 
 interface TestCppKeywordNamedMethodsInterface {
   boolean continue();
   boolean delete();
   long volatile();
 };
 
-[Deprecated="GetAttributeNode", Constructor()]
+[Deprecated="EnablePrivilege", Constructor()]
 interface TestDeprecatedInterface {
   static void alsoDeprecated();
 };
 
 
 [Constructor(Promise<void> promise)]
 interface TestInterfaceWithPromiseConstructorArg {
 };
--- a/dom/bindings/test/TestExampleGen.webidl
+++ b/dom/bindings/test/TestExampleGen.webidl
@@ -627,34 +627,34 @@ interface TestExampleInterface {
 
   // Typedefs
   const myLong myLongConstant = 5;
   void exerciseTypedefInterfaces1(AnotherNameForTestInterface arg);
   AnotherNameForTestInterface exerciseTypedefInterfaces2(NullableTestInterface arg);
   void exerciseTypedefInterfaces3(YetAnotherNameForTestInterface arg);
 
   // Deprecated methods and attributes
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   attribute boolean deprecatedAttribute;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   void deprecatedMethod(boolean arg);
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   void deprecatedMethodWithContext(any arg);
 
   // Static methods and attributes
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
   static void staticMethodWithContext(any arg);
 
   // Deprecated methods and attributes;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static attribute boolean staticDeprecatedAttribute;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static void staticDeprecatedMethod(boolean arg);
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static void staticDeprecatedMethodWithContext(any arg);
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestInterface arg);
   TestInterface overload1(DOMString strs, TestInterface arg);
   void overload2(TestInterface arg);
   void overload2(optional Dict arg);
--- a/dom/bindings/test/TestJSImplGen.webidl
+++ b/dom/bindings/test/TestJSImplGen.webidl
@@ -638,36 +638,36 @@ interface TestJSImplInterface {
 
   // Typedefs
   const myLong myLongConstant = 5;
   void exerciseTypedefInterfaces1(AnotherNameForTestJSImplInterface arg);
   AnotherNameForTestJSImplInterface exerciseTypedefInterfaces2(NullableTestJSImplInterface arg);
   void exerciseTypedefInterfaces3(YetAnotherNameForTestJSImplInterface arg);
 
   // Deprecated methods and attributes
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   attribute byte deprecatedAttribute;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   byte deprecatedMethod();
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   void deprecatedMethodWithContext(any arg);
 
   // Static methods and attributes
   // FIXME: Bug 863952 Static things are not supported yet
   /*
   static attribute boolean staticAttribute;
   static void staticMethod(boolean arg);
   static void staticMethodWithContext(any arg);
 
   // Deprecated static methods and attributes
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static attribute byte staticDeprecatedAttribute;
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static byte staticDeprecatedMethod();
-  [Deprecated="GetAttributeNode"]
+  [Deprecated="EnablePrivilege"]
   static byte staticDeprecatedMethodWithContext();
   */
 
   // Overload resolution tests
   //void overload1(DOMString... strs);
   boolean overload1(TestJSImplInterface arg);
   TestJSImplInterface overload1(DOMString strs, TestJSImplInterface arg);
   void overload2(TestJSImplInterface arg);
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -663,17 +663,17 @@ BrowserElementChild.prototype = {
     sendAsyncMsg('scrollviewchange', detail);
   },
 
   _ClickHandler: function(e) {
 
     let isHTMLLink = node =>
         ((ChromeUtils.getClassName(node) === "HTMLAnchorElement" && node.href) ||
          (ChromeUtils.getClassName(node) === "HTMLAreaElement" && node.href) ||
-         node instanceof Ci.nsIDOMHTMLLinkElement);
+         ChromeUtils.getClassName(node) === "HTMLLinkElement");
 
     // Open in a new tab if middle click or ctrl/cmd-click,
     // and e.target is a link or inside a link.
     if ((Services.appinfo.OS == 'Darwin' && e.metaKey) ||
         (Services.appinfo.OS != 'Darwin' && e.ctrlKey) ||
          e.button == 1) {
 
       let node = e.target;
--- a/dom/browser-element/mochitest/browserElement_DataURILoad.js
+++ b/dom/browser-element/mochitest/browserElement_DataURILoad.js
@@ -37,21 +37,21 @@ function runTest2() {
   frame.setAttribute('mozbrowser', 'true');
   frame.src = HTTP_URI;
   document.body.appendChild(frame);
   let wrappedFrame = SpecialPowers.wrap(frame);
 
   wrappedFrame.addEventListener("mozbrowserloadend", function onloadend(e) {
     ok(wrappedFrame.contentWindow.document.location.href.endsWith(HTTP_URI),
        "http: URI navigation should be allowed");
-    wrappedFrame.src = DATA_URI
+    frame.src = DATA_URI
 
     // wait for 1000ms and check that the data: URI did not load
     setTimeout(function () {
       isnot(wrappedFrame.contentWindow.document.body.innerHTML,
             INNER, 
             "data: URI navigation should be blocked");
       SimpleTest.finish();
     }, 1000);
-  });
+  }, {once: true});
 }
 
 addEventListener('testready', runTest1);
--- a/dom/html/HTMLAnchorElement.cpp
+++ b/dom/html/HTMLAnchorElement.cpp
@@ -310,29 +310,31 @@ HTMLAnchorElement::BeforeSetAttr(int32_t
 
   return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue,
                                              aNotify);
 }
 
 nsresult
 HTMLAnchorElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::href) {
       Link::ResetLinkState(aNotify, !!aValue);
       if (aValue && IsInComposedDoc()) {
         TryDNSPrefetch();
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue, aSubjectPrincipal, aNotify);
 }
 
 EventStates
 HTMLAnchorElement::IntrinsicState() const
 {
   return Link::LinkState() | nsGenericHTMLElement::IntrinsicState();
 }
 
--- a/dom/html/HTMLAnchorElement.h
+++ b/dom/html/HTMLAnchorElement.h
@@ -64,16 +64,17 @@ public:
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
 
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual EventStates IntrinsicState() const override;
 
   virtual void OnDNSPrefetchDeferred() override;
--- a/dom/html/HTMLAreaElement.cpp
+++ b/dom/html/HTMLAreaElement.cpp
@@ -115,30 +115,32 @@ HTMLAreaElement::UnbindFromTree(bool aDe
   Link::ResetLinkState(false, Link::ElementHasHref());
 
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsresult
 HTMLAreaElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     // This must happen after the attribute is set. We will need the updated
     // attribute value because notifying the document that content states have
     // changed will call IntrinsicState, which will try to get updated
     // information about the visitedness from Link.
     if (aName == nsGkAtoms::href) {
       Link::ResetLinkState(aNotify, !!aValue);
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 void
 HTMLAreaElement::ToString(nsAString& aSource)
 {
   GetHref(aSource);
 }
 
--- a/dom/html/HTMLAreaElement.h
+++ b/dom/html/HTMLAreaElement.h
@@ -197,16 +197,17 @@ public:
 protected:
   virtual ~HTMLAreaElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   RefPtr<nsDOMTokenList > mRelList;
 };
 
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/html/HTMLBodyElement.cpp
+++ b/dom/html/HTMLBodyElement.cpp
@@ -335,21 +335,23 @@ HTMLBodyElement::BindToTree(nsIDocument*
                                                  aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv, rv);
   return mAttrsAndChildren.ForceMapped(this, OwnerDoc());
 }
 
 nsresult
 HTMLBodyElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   nsresult rv = nsGenericHTMLElement::AfterSetAttr(aNameSpaceID,
                                                    aName, aValue, aOldValue,
-                                                   aNotify);
+                                                   aSubjectPrincipal, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
   // if the last mapped attribute was removed, don't clear the
   // nsMappedAttributes, our style can still depend on the containing frame element
   if (!aValue && IsAttributeMapped(aName)) {
     nsresult rv = mAttrsAndChildren.ForceMapped(this, OwnerDoc());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
--- a/dom/html/HTMLBodyElement.h
+++ b/dom/html/HTMLBodyElement.h
@@ -140,16 +140,17 @@ public:
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   /**
    * Called when an attribute has just been changed
    */
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
 protected:
   virtual ~HTMLBodyElement();
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 private:
--- a/dom/html/HTMLButtonElement.cpp
+++ b/dom/html/HTMLButtonElement.cpp
@@ -407,17 +407,19 @@ HTMLButtonElement::BeforeSetAttr(int32_t
 
   return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
                                                           aValue, aNotify);
 }
 
 nsresult
 HTMLButtonElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::type) {
       if (aValue) {
         mType = aValue->GetEnumValue();
       } else {
         mType = kButtonDefaultType->value;
       }
@@ -431,17 +433,17 @@ HTMLButtonElement::AfterSetAttr(int32_t 
       }
 
       UpdateBarredFromConstraintValidation();
     }
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
                                                          aValue, aOldValue,
-                                                         aNotify);
+                                                         aSubjectPrincipal, aNotify);
 }
 
 NS_IMETHODIMP
 HTMLButtonElement::SaveState()
 {
   if (!mDisabledChanged) {
     return NS_OK;
   }
--- a/dom/html/HTMLButtonElement.h
+++ b/dom/html/HTMLButtonElement.h
@@ -79,16 +79,17 @@ public:
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   /**
    * Called when an attribute has just been changed
    */
   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;
 
   // nsGenericHTMLElement
   virtual bool IsHTMLFocusable(bool aWithMouse,
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -455,22 +455,24 @@ HTMLCanvasElement::GetWidthHeight()
              "unsigned (non-negative) values");
 
   return size;
 }
 
 nsresult
 HTMLCanvasElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLCanvasElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify)
 {
   AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
--- a/dom/html/HTMLCanvasElement.h
+++ b/dom/html/HTMLCanvasElement.h
@@ -358,16 +358,17 @@ protected:
   nsresult MozGetAsFileImpl(const nsAString& aName,
                             const nsAString& aType,
                             File** aResult);
   void CallPrintCallback();
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
   AsyncCanvasRenderer* GetAsyncCanvasRenderer();
 
   bool mResetLayer;
--- a/dom/html/HTMLContentElement.cpp
+++ b/dom/html/HTMLContentElement.cpp
@@ -204,17 +204,19 @@ IsValidContentSelectors(nsCSSSelector* a
   }
 
   return true;
 }
 
 nsresult
 HTMLContentElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValue* aValue,
-                                 const nsAttrValue* aOldValue, bool aNotify)
+                                 const nsAttrValue* aOldValue,
+                                 nsIPrincipal* aSubjectPrincipal,
+                                 bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::select) {
     if (aValue) {
       // Select attribute was updated, the insertion point may match different
       // elements.
       nsIDocument* doc = OwnerDoc();
       nsCSSParser parser(doc->CSSLoader());
 
@@ -258,17 +260,17 @@ HTMLContentElement::AfterSetAttr(int32_t
       ShadowRoot* containingShadow = GetContainingShadow();
       if (containingShadow) {
         containingShadow->DistributeAllNodes();
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 bool
 HTMLContentElement::Match(nsIContent* aContent)
 {
   if (!mValidSelector) {
     return false;
   }
--- a/dom/html/HTMLContentElement.h
+++ b/dom/html/HTMLContentElement.h
@@ -87,16 +87,17 @@ protected:
    * of fallback are cleared, otherwise, this insertion point
    * is a destination insertion point.
    */
   void UpdateFallbackDistribution();
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   /**
    * An array of nodes from the ShadowRoot host that match the
    * content insertion selector.
    */
   nsCOMArray<nsIContent> mMatchedNodes;
 
--- a/dom/html/HTMLEmbedElement.cpp
+++ b/dom/html/HTMLEmbedElement.cpp
@@ -130,25 +130,26 @@ HTMLEmbedElement::UnbindFromTree(bool aD
   nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsresult
 HTMLEmbedElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                const nsAttrValue* aValue,
                                const nsAttrValue* aOldValue,
+                               nsIPrincipal* aSubjectPrincipal,
                                bool aNotify)
 {
   if (aValue) {
     nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLEmbedElement::OnAttrSetButNotChanged(int32_t aNamespaceID,
                                          nsAtom* aName,
                                          const nsAttrValueOrString& aValue,
                                          bool aNotify)
 {
--- a/dom/html/HTMLEmbedElement.h
+++ b/dom/html/HTMLEmbedElement.h
@@ -130,16 +130,17 @@ public:
 
 protected:
   // Override for nsImageLoadingContent.
   nsIContent* AsContent() override { return this; }
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
 private:
   ~HTMLEmbedElement();
 
--- a/dom/html/HTMLFieldSetElement.cpp
+++ b/dom/html/HTMLFieldSetElement.cpp
@@ -65,17 +65,19 @@ HTMLFieldSetElement::GetEventTargetParen
   }
 
   return nsGenericHTMLFormElement::GetEventTargetParent(aVisitor);
 }
 
 nsresult
 HTMLFieldSetElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
-                                  const nsAttrValue* aOldValue, bool aNotify)
+                                  const nsAttrValue* aOldValue,
+                                  nsIPrincipal* aSubjectPrincipal,
+                                  bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
     // This *has* to be called *before* calling FieldSetDisabledChanged on our
     // controls, as they may depend on our disabled state.
     UpdateDisabledState(aNotify);
 
     if (nsINode::GetFirstChild()) {
       if (!mElements) {
@@ -87,17 +89,18 @@ HTMLFieldSetElement::AfterSetAttr(int32_
       for (uint32_t i=0; i<length; ++i) {
         static_cast<nsGenericHTMLFormElement*>(mElements->Item(i))
           ->FieldSetDisabledChanged(aNotify);
       }
     }
   }
 
   return nsGenericHTMLFormElement::AfterSetAttr(aNameSpaceID, aName,
-                                                aValue, aOldValue, aNotify);
+                                                aValue, aOldValue,
+                                                aSubjectPrincipal, aNotify);
 }
 
 NS_IMETHODIMP
 HTMLFieldSetElement::GetType(nsAString& aType)
 {
   aType.AssignLiteral("fieldset");
   return NS_OK;
 }
--- a/dom/html/HTMLFieldSetElement.h
+++ b/dom/html/HTMLFieldSetElement.h
@@ -33,16 +33,17 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
 
   // nsIContent
   virtual nsresult GetEventTargetParent(
                      EventChainPreVisitor& aVisitor) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   virtual nsresult InsertChildAt(nsIContent* aChild, uint32_t aIndex,
                                      bool aNotify) override;
   virtual void RemoveChildAt(uint32_t aIndex, bool aNotify) override;
 
   // nsIFormControl
   NS_IMETHOD Reset() override;
--- a/dom/html/HTMLFormElement.cpp
+++ b/dom/html/HTMLFormElement.cpp
@@ -206,34 +206,36 @@ HTMLFormElement::BeforeSetAttr(int32_t a
 
   return nsGenericHTMLElement::BeforeSetAttr(aNamespaceID, aName, aValue,
                                              aNotify);
 }
 
 nsresult
 HTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   if (aName == nsGkAtoms::novalidate && aNameSpaceID == kNameSpaceID_None) {
     // Update all form elements states because they might be [no longer]
     // affected by :-moz-ui-valid or :-moz-ui-invalid.
     for (uint32_t i = 0, length = mControls->mElements.Length();
          i < length; ++i) {
       mControls->mElements[i]->UpdateState(true);
     }
 
     for (uint32_t i = 0, length = mControls->mNotInElements.Length();
          i < length; ++i) {
       mControls->mNotInElements[i]->UpdateState(true);
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 NS_IMPL_STRING_ATTR(HTMLFormElement, AcceptCharset, acceptcharset)
 NS_IMPL_ACTION_ATTR(HTMLFormElement, Action, action)
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLFormElement, Autocomplete, autocomplete,
                                 kFormDefaultAutocomplete->tag)
 NS_IMPL_ENUM_ATTR_DEFAULT_VALUE(HTMLFormElement, Enctype, enctype,
                                 kFormDefaultEnctype->tag)
--- a/dom/html/HTMLFormElement.h
+++ b/dom/html/HTMLFormElement.h
@@ -108,16 +108,17 @@ public:
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   /**
    * Forget all information about the current submission (and the fact that we
    * are currently submitting at all).
    */
   void ForgetCurrentSubmission();
 
--- a/dom/html/HTMLFrameElement.h
+++ b/dom/html/HTMLFrameElement.h
@@ -94,23 +94,23 @@ public:
   {
     GetHTMLAttr(nsGkAtoms::scrolling, aScrolling);
   }
   void SetScrolling(const nsAString& aScrolling, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::scrolling, aScrolling, aError);
   }
 
-  void GetSrc(nsAString& aSrc) const
+  void GetSrc(nsString& aSrc, nsIPrincipal&)
   {
     GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
   }
-  void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
   {
-    SetAttrHelper(nsGkAtoms::src, aSrc);
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
   }
 
   using nsGenericHTMLFrameElement::GetContentDocument;
   using nsGenericHTMLFrameElement::GetContentWindow;
 
 protected:
   virtual ~HTMLFrameElement();
 
--- a/dom/html/HTMLIFrameElement.cpp
+++ b/dom/html/HTMLIFrameElement.cpp
@@ -131,32 +131,36 @@ nsMapRuleToAttributesFunc
 HTMLIFrameElement::GetAttributeMappingFunction() const
 {
   return &MapAttributesIntoRule;
 }
 
 nsresult
 HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                bool aNotify)
 {
   AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify);
 
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::sandbox) {
       if (mFrameLoader) {
         // If we have an nsFrameLoader, apply the new sandbox flags.
         // Since this is called after the setter, the sandbox flags have
         // alreay been updated.
         mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
       }
     }
   }
-  return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                                 aOldValue, aNotify);
+  return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName,
+                                                 aValue, aOldValue,
+                                                 aMaybeScriptedPrincipal,
+                                                 aNotify);
 }
 
 nsresult
 HTMLIFrameElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify)
 {
   AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
--- a/dom/html/HTMLIFrameElement.h
+++ b/dom/html/HTMLIFrameElement.h
@@ -40,23 +40,23 @@ public:
   virtual nsMapRuleToAttributesFunc GetAttributeMappingFunction() const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   uint32_t GetSandboxFlags();
 
   // Web IDL binding methods
-  void GetSrc(nsAString& aSrc) const
+  void GetSrc(nsString& aSrc, nsIPrincipal&) const
   {
     GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
   }
-  void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
   {
-    SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
   }
   void GetSrcdoc(DOMString& aSrcdoc)
   {
     GetHTMLAttr(nsGkAtoms::srcdoc, aSrcdoc);
   }
   void SetSrcdoc(const nsAString& aSrcdoc, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::srcdoc, aSrcdoc, aError);
@@ -190,16 +190,17 @@ public:
 protected:
   virtual ~HTMLIFrameElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
 private:
   static void MapAttributesIntoRule(const nsMappedAttributes* aAttributes,
                                     GenericSpecifiedValues* aGenericData);
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -313,23 +313,25 @@ HTMLImageElement::BeforeSetAttr(int32_t 
 
   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
                                              aValue, aNotify);
 }
 
 nsresult
 HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                const nsAttrValue* aValue,
-                               const nsAttrValue* aOldValue, bool aNotify)
+                               const nsAttrValue* aOldValue,
+                               nsIPrincipal* aMaybeScriptedPrincipal,
+                               bool aNotify)
 {
   nsAttrValueOrString attrVal(aValue);
 
   if (aValue) {
-    AfterMaybeChangeAttr(aNameSpaceID, aName, attrVal, aOldValue, true,
-                         aNotify);
+    AfterMaybeChangeAttr(aNameSpaceID, aName, attrVal, aOldValue,
+                         aMaybeScriptedPrincipal, true, aNotify);
   }
 
   if (aNameSpaceID == kNameSpaceID_None && mForm &&
       (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
       aValue && !aValue->IsEmptyString()) {
     // add the image to the hashtable as needed
     MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
                "Expected atom value for name/id");
@@ -361,45 +363,50 @@ HTMLImageElement::AfterSetAttr(int32_t a
       CancelImageRequests(aNotify);
     }
   } else if (aName == nsGkAtoms::srcset &&
              aNameSpaceID == kNameSpaceID_None) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
     mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
+    mSrcsetTriggeringPrincipal = aMaybeScriptedPrincipal;
+
     PictureSourceSrcsetChanged(this, attrVal.String(), aNotify);
   } else if (aName == nsGkAtoms::sizes &&
              aNameSpaceID == kNameSpaceID_None) {
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
     mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
     PictureSourceSizesChanged(this, attrVal.String(), aNotify);
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue,
+                                            aMaybeScriptedPrincipal,
+                                            aNotify);
 }
 
 nsresult
 HTMLImageElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                          const nsAttrValueOrString& aValue,
                                          bool aNotify)
 {
-  AfterMaybeChangeAttr(aNamespaceID, aName, aValue, nullptr, false, aNotify);
+  AfterMaybeChangeAttr(aNamespaceID, aName, aValue, nullptr, nullptr, false, aNotify);
 
   return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName,
                                                       aValue, aNotify);
 }
 
 void
 HTMLImageElement::AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName,
                                        const nsAttrValueOrString& aValue,
                                        const nsAttrValue* aOldValue,
+                                       nsIPrincipal* aMaybeScriptedPrincipal,
                                        bool aValueMaybeChanged, bool aNotify)
 {
   bool forceReload = false;
   // We need to force our image to reload.  This must be done here, not in
   // AfterSetAttr or BeforeSetAttr, because we want to do it even if the attr is
   // being set to its existing value, which is normally optimized away as a
   // no-op.
   //
@@ -410,20 +417,24 @@ HTMLImageElement::AfterMaybeChangeAttr(i
   // Both cases handle unsetting src in AfterSetAttr
   if (aNamespaceID == kNameSpaceID_None &&
       aName == nsGkAtoms::src) {
 
     // Mark channel as urgent-start before load image if the image load is
     // initaiated by a user interaction.
     mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
+    mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue.String(), aMaybeScriptedPrincipal);
+
     if (InResponsiveMode()) {
       if (mResponsiveSelector &&
           mResponsiveSelector->Content() == this) {
-        mResponsiveSelector->SetDefaultSource(aValue.String());
+        mResponsiveSelector->SetDefaultSource(aValue.String(),
+                                              mSrcTriggeringPrincipal);
       }
       QueueImageLoadTask(true);
     } else if (aNotify && OwnerDoc()->IsCurrentActiveDocument()) {
       // If aNotify is false, we are coming from the parser or some such place;
       // we'll get bound after all the attributes have been set, so we'll do the
       // sync image load from BindToTree. Skip the LoadImage call in that case.
 
       // Note that this sync behavior is partially removed from the spec, bug 1076583
@@ -435,17 +446,18 @@ HTMLImageElement::AfterMaybeChangeAttr(i
       // network if it's set to be not cacheable.
       // Potentially, false could be passed here rather than aNotify since
       // UpdateState will be called by SetAttrAndNotify, but there are two
       // obstacles to this: 1) LoadImage will end up calling
       // UpdateState(aNotify), and we do not want it to call UpdateState(false)
       // when aNotify is true, and 2) When this function is called by
       // OnAttrSetButNotChanged, SetAttrAndNotify will not subsequently call
       // UpdateState.
-      LoadImage(aValue.String(), true, aNotify, eImageLoadType_Normal);
+      LoadImage(aValue.String(), true, aNotify, eImageLoadType_Normal,
+                mSrcTriggeringPrincipal);
 
       mNewRequestsWillNeedAnimationReset = false;
     }
   } else if (aNamespaceID == kNameSpaceID_None &&
              aName == nsGkAtoms::crossorigin &&
              aNotify) {
     if (aValueMaybeChanged && GetCORSMode() != AttrValueToCORSMode(aOldValue)) {
       // Force a new load of the image with the new cross origin policy.
@@ -967,23 +979,25 @@ HTMLImageElement::LoadSelectedImage(bool
       return NS_OK;
     }
   }
 
   nsCOMPtr<nsIURI> selectedSource;
   double currentDensity = 1.0; // default to 1.0 for the src attribute case
   if (mResponsiveSelector) {
     nsCOMPtr<nsIURI> url = mResponsiveSelector->GetSelectedImageURL();
+    nsCOMPtr<nsIPrincipal> triggeringPrincipal = mResponsiveSelector->GetSelectedImageTriggeringPrincipal();
     selectedSource = url;
     currentDensity = mResponsiveSelector->GetSelectedImageDensity();
     if (!aAlwaysLoad && SelectedSourceMatchesLast(selectedSource, currentDensity)) {
       return NS_OK;
     }
     if (url) {
-      rv = LoadImage(url, aForce, aNotify, eImageLoadType_Imageset);
+      rv = LoadImage(url, aForce, aNotify, eImageLoadType_Imageset,
+                     triggeringPrincipal);
     }
   } else {
     nsAutoString src;
     if (!GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
       CancelImageRequests(aNotify);
       rv = NS_OK;
     } else {
       nsIDocument* doc = GetOurOwnerDoc();
@@ -994,17 +1008,18 @@ HTMLImageElement::LoadSelectedImage(bool
         }
       }
 
       // If we have a srcset attribute or are in a <picture> element,
       // we always use the Imageset load type, even if we parsed no
       // valid responsive sources from either, per spec.
       rv = LoadImage(src, aForce, aNotify,
                      HaveSrcsetOrInPicture() ? eImageLoadType_Imageset
-                                             : eImageLoadType_Normal);
+                                             : eImageLoadType_Normal,
+                     mSrcTriggeringPrincipal);
     }
   }
   mLastSelectedSource = selectedSource;
   mCurrentDensity = currentDensity;
 
   if (NS_FAILED(rv)) {
     CancelImageRequests(aNotify);
   }
@@ -1021,17 +1036,23 @@ HTMLImageElement::PictureSourceSrcsetCha
              "Should not be getting notifications for non-previous-siblings");
 
   nsIContent *currentSrc =
     mResponsiveSelector ? mResponsiveSelector->Content() : nullptr;
 
   if (aSourceNode == currentSrc) {
     // We're currently using this node as our responsive selector
     // source.
-    mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue);
+    nsCOMPtr<nsIPrincipal> principal;
+    if (aSourceNode == this) {
+      principal = mSrcsetTriggeringPrincipal;
+    } else if (auto* source = HTMLSourceElement::FromContent(aSourceNode)) {
+      principal = source->GetSrcsetTriggeringPrincipal();
+    }
+    mResponsiveSelector->SetCandidatesFromSourceSet(aNewValue, principal);
   }
 
   if (!mInDocResponsiveContent && IsInComposedDoc()) {
     nsIDocument* doc = GetOurOwnerDoc();
     if (doc) {
       doc->AddResponsiveContent(this);
       mInDocResponsiveContent = true;
     }
@@ -1206,55 +1227,60 @@ HTMLImageElement::SourceElementMatches(n
   }
 
   return true;
 }
 
 bool
 HTMLImageElement::TryCreateResponsiveSelector(nsIContent *aSourceNode)
 {
+  nsCOMPtr<nsIPrincipal> principal;
+
   // Skip if this is not a <source> with matching media query
   bool isSourceTag = aSourceNode->IsHTMLElement(nsGkAtoms::source);
   if (isSourceTag) {
     if (!SourceElementMatches(aSourceNode)) {
       return false;
     }
+    auto* source = HTMLSourceElement::FromContent(aSourceNode);
+    principal = source->GetSrcsetTriggeringPrincipal();
   } else if (aSourceNode->IsHTMLElement(nsGkAtoms::img)) {
     // Otherwise this is the <img> tag itself
     MOZ_ASSERT(aSourceNode == this);
+    principal = mSrcsetTriggeringPrincipal;
   }
 
   // Skip if has no srcset or an empty srcset
   nsString srcset;
   if (!aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::srcset, srcset)) {
     return false;
   }
 
   if (srcset.IsEmpty()) {
     return false;
   }
 
 
   // Try to parse
   RefPtr<ResponsiveImageSelector> sel = new ResponsiveImageSelector(aSourceNode);
-  if (!sel->SetCandidatesFromSourceSet(srcset)) {
+  if (!sel->SetCandidatesFromSourceSet(srcset, principal)) {
     // No possible candidates, don't need to bother parsing sizes
     return false;
   }
 
   nsAutoString sizes;
   aSourceNode->GetAttr(kNameSpaceID_None, nsGkAtoms::sizes, sizes);
   sel->SetSizesFromDescriptor(sizes);
 
   // If this is the <img> tag, also pull in src as the default source
   if (!isSourceTag) {
     MOZ_ASSERT(aSourceNode == this);
     nsAutoString src;
     if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src) && !src.IsEmpty()) {
-      sel->SetDefaultSource(src);
+      sel->SetDefaultSource(src, mSrcTriggeringPrincipal);
     }
   }
 
   mResponsiveSelector = sel;
   return true;
 }
 
 /* static */ bool
--- a/dom/html/HTMLImageElement.h
+++ b/dom/html/HTMLImageElement.h
@@ -137,31 +137,31 @@ public:
   void GetAlt(nsAString& aAlt)
   {
     GetHTMLAttr(nsGkAtoms::alt, aAlt);
   }
   void SetAlt(const nsAString& aAlt, ErrorResult& aError)
   {
     SetHTMLAttr(nsGkAtoms::alt, aAlt, aError);
   }
-  void GetSrc(nsAString& aSrc)
+  void GetSrc(nsAString& aSrc, nsIPrincipal&)
   {
     GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
   }
-  void SetSrc(const nsAString& aSrc, ErrorResult& aError)
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
   {
-    SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
   }
-  void GetSrcset(nsAString& aSrcset)
+  void GetSrcset(nsAString& aSrcset, nsIPrincipal&)
   {
     GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
   }
-  void SetSrcset(const nsAString& aSrcset, ErrorResult& aError)
+  void SetSrcset(const nsAString& aSrcset, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
   {
-    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aError);
+    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aTriggeringPrincipal, aError);
   }
   void GetCrossOrigin(nsAString& aResult)
   {
     // Null for both missing and invalid defaults is ok, since we
     // always parse to an enum value, so we don't need an invalid
     // default, and we _want_ the missing default to be null.
     GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
   }
@@ -374,16 +374,17 @@ protected:
 
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
   // Override for nsImageLoadingContent.
   nsIContent* AsContent() override { return this; }
   NS_IMETHOD GetNaturalWidth(uint32_t* aNaturalWidth) override;
@@ -415,20 +416,23 @@ private:
    *        aOldValue should be considered unreliable.
    * @param aValueMaybeChanged will be false when this function is called from
    *        OnAttrSetButNotChanged to indicate that the value was not changed.
    * @param aNotify Whether we plan to notify document observers.
    */
   void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName,
                             const nsAttrValueOrString& aValue,
                             const nsAttrValue* aOldValue,
+                            nsIPrincipal* aMaybeScriptedPrincipal,
                             bool aValueMaybeChanged, bool aNotify);
 
   bool mInDocResponsiveContent;
   RefPtr<ImageLoadTask> mPendingImageLoadTask;
+  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+  nsCOMPtr<nsIPrincipal> mSrcsetTriggeringPrincipal;
 
   // Last URL that was attempted to load by this element.
   nsCOMPtr<nsIURI> mLastSelectedSource;
   // Last pixel density that was selected.
   double mCurrentDensity;
 };
 
 } // namespace dom
--- a/dom/html/HTMLInputElement.cpp
+++ b/dom/html/HTMLInputElement.cpp
@@ -1333,28 +1333,16 @@ HTMLInputElement::BeforeSetAttr(int32_t 
     // (type changes are handled in the form itself currently)
     // If we are not done creating the radio, we also should not do it.
     //
     if ((aName == nsGkAtoms::name ||
          (aName == nsGkAtoms::type && !mForm)) &&
         mType == NS_FORM_INPUT_RADIO &&
         (mForm || mDoneCreating)) {
       WillRemoveFromRadioGroup();
-    } else if (aNotify && aName == nsGkAtoms::src &&
-               mType == NS_FORM_INPUT_IMAGE) {
-      if (aValue) {
-        // Mark channel as urgent-start before load image if the image load is
-        // initaiated by a user interaction.
-        mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
-
-        LoadImage(aValue->String(), true, aNotify, eImageLoadType_Normal);
-      } else {
-        // Null value means the attr got unset; drop the image
-        CancelImageRequests(aNotify);
-      }
     } else if (aNotify && aName == nsGkAtoms::disabled) {
       mDisabledChanged = true;
     } else if (mType == NS_FORM_INPUT_RADIO && aName == nsGkAtoms::required) {
       nsCOMPtr<nsIRadioGroupContainer> container = GetRadioGroupContainer();
 
       if (container &&
           ((aValue && !HasAttr(aNameSpaceID, aName)) ||
            (!aValue && HasAttr(aNameSpaceID, aName)))) {
@@ -1371,32 +1359,53 @@ HTMLInputElement::BeforeSetAttr(int32_t 
 
   return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
                                                           aValue, aNotify);
 }
 
 nsresult
 HTMLInputElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                const nsAttrValue* aValue,
-                               const nsAttrValue* aOldValue, bool aNotify)
+                               const nsAttrValue* aOldValue,
+                               nsIPrincipal* aSubjectPrincipal,
+                               bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     //
     // When name or type changes, radio should be added to radio group.
     // (type changes are handled in the form itself currently)
     // If we are not done creating the radio, we also should not do it.
     //
     if ((aName == nsGkAtoms::name ||
          (aName == nsGkAtoms::type && !mForm)) &&
         mType == NS_FORM_INPUT_RADIO &&
         (mForm || mDoneCreating)) {
       AddedToRadioGroup();
       UpdateValueMissingValidityStateForRadio(false);
     }
 
+    if (aName == nsGkAtoms::src) {
+      mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+          this, aValue ? aValue->GetStringValue() : EmptyString(),
+          aSubjectPrincipal);
+      if (aNotify && mType == NS_FORM_INPUT_IMAGE) {
+        if (aValue) {
+          // Mark channel as urgent-start before load image if the image load is
+          // initiated by a user interaction.
+          mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
+
+          LoadImage(aValue->GetStringValue(), true, aNotify, eImageLoadType_Normal,
+                    mSrcTriggeringPrincipal);
+        } else {
+          // Null value means the attr got unset; drop the image
+          CancelImageRequests(aNotify);
+        }
+      }
+    }
+
     // If @value is changed and BF_VALUE_CHANGED is false, @value is the value
     // of the element so, if the value of the element is different than @value,
     // we have to re-set it. This is only the case when GetValueMode() returns
     // VALUE_MODE_VALUE.
     if (aName == nsGkAtoms::value &&
         !mValueChanged && GetValueMode() == VALUE_MODE_VALUE) {
       SetDefaultValueAsValue();
     }
@@ -1515,16 +1524,17 @@ HTMLInputElement::AfterSetAttr(int32_t a
       // Clear the cached @autocomplete attribute and autocompleteInfo state.
       mAutocompleteAttrState = nsContentUtils::eAutocompleteAttrState_Unknown;
       mAutocompleteInfoState = nsContentUtils::eAutocompleteAttrState_Unknown;
     }
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
                                                          aValue, aOldValue,
+                                                         aSubjectPrincipal,
                                                          aNotify);
 }
 
 void
 HTMLInputElement::BeforeSetForm(bool aBindToTree)
 {
   // No need to remove from radio group if we are just binding to tree.
   if (mType == NS_FORM_INPUT_RADIO && !aBindToTree) {
@@ -4789,17 +4799,18 @@ HTMLInputElement::PostHandleEventForRang
 void
 HTMLInputElement::MaybeLoadImage()
 {
   // Our base URI may have changed; claim that our URI changed, and the
   // nsImageLoadingContent will decide whether a new image load is warranted.
   nsAutoString uri;
   if (mType == NS_FORM_INPUT_IMAGE &&
       GetAttr(kNameSpaceID_None, nsGkAtoms::src, uri) &&
-      (NS_FAILED(LoadImage(uri, false, true, eImageLoadType_Normal)) ||
+      (NS_FAILED(LoadImage(uri, false, true, eImageLoadType_Normal,
+                           mSrcTriggeringPrincipal)) ||
        !LoadingEnabled())) {
     CancelImageRequests(true);
   }
 }
 
 nsresult
 HTMLInputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                              nsIContent* aBindingParent,
@@ -5035,17 +5046,18 @@ HTMLInputElement::HandleTypeChange(uint8
     // We just got switched to be an image input; we should see
     // whether we have an image to load;
     nsAutoString src;
     if (GetAttr(kNameSpaceID_None, nsGkAtoms::src, src)) {
       // Mark channel as urgent-start before load image if the image load is
       // initaiated by a user interaction.
       mUseUrgentStartForChannel = EventStateManager::IsHandlingUserInput();
 
-      LoadImage(src, false, aNotify, eImageLoadType_Normal);
+      LoadImage(src, false, aNotify, eImageLoadType_Normal,
+                mSrcTriggeringPrincipal);
     }
   }
 
   if (mType == NS_FORM_INPUT_PASSWORD && IsInComposedDoc()) {
     AsyncEventDispatcher* dispatcher =
       new AsyncEventDispatcher(this,
                                NS_LITERAL_STRING("DOMInputPasswordAdded"),
                                true,
--- a/dom/html/HTMLInputElement.h
+++ b/dom/html/HTMLInputElement.h
@@ -702,23 +702,23 @@ public:
     if (aValue == 0) {
       aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
       return;
     }
 
     SetUnsignedIntAttr(nsGkAtoms::size, aValue, DEFAULT_COLS, aRv);
   }
 
-  void GetSrc(nsAString& aValue)
+  void GetSrc(nsAString& aValue, nsIPrincipal&)
   {
     GetURIAttr(nsGkAtoms::src, nullptr, aValue);
   }
-  void SetSrc(const nsAString& aValue, ErrorResult& aRv)
+  void SetSrc(const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
   {
-    SetHTMLAttr(nsGkAtoms::src, aValue, aRv);
+    SetHTMLAttr(nsGkAtoms::src, aValue, aTriggeringPrincipal, aRv);
   }
 
   void GetStep(nsAString& aValue)
   {
     GetHTMLAttr(nsGkAtoms::step, aValue);
   }
   void SetStep(const nsAString& aValue, ErrorResult& aRv)
   {
@@ -1070,16 +1070,17 @@ protected:
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   /**
    * Called when an attribute has just been changed
    */
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   virtual void BeforeSetForm(bool aBindToTree) override;
 
   virtual void AfterClearForm(bool aUnbindOrDelete) override;
 
   /**
    * Dispatch a select event. Returns true if the event was not cancelled.
@@ -1611,16 +1612,21 @@ protected:
 
   /**
    * The selection properties cache for number controls.  This is needed because
    * the number controls don't recycle their text field, so the normal cache in
    * nsTextEditorState cannot do its job.
    */
   nsTextEditorState::SelectionProperties mSelectionProperties;
 
+  /**
+   * The triggering principal for the src attribute.
+   */
+  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+
   /*
    * InputType object created based on input type.
    */
   UniquePtr<InputType, DoNotDelete> mInputType;
 
   // Memory allocated for mInputType, reused when type changes.
   char mInputTypeMem[INPUT_TYPE_SIZE];
 
--- a/dom/html/HTMLLinkElement.cpp
+++ b/dom/html/HTMLLinkElement.cpp
@@ -72,61 +72,36 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(HTMLLinkElement,
                                                 nsGenericHTMLElement)
   tmp->nsStyleLinkElement::Unlink();
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mRelList)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLLinkElement,
                                              nsGenericHTMLElement,
-                                             nsIDOMHTMLLinkElement,
                                              nsIStyleSheetLinkingElement,
                                              Link)
 
 NS_IMPL_ELEMENT_CLONE(HTMLLinkElement)
 
 bool
 HTMLLinkElement::Disabled()
 {
   StyleSheet* ss = GetSheet();
   return ss && ss->Disabled();
 }
 
-NS_IMETHODIMP
-HTMLLinkElement::GetMozDisabled(bool* aDisabled)
-{
-  *aDisabled = Disabled();
-  return NS_OK;
-}
-
 void
 HTMLLinkElement::SetDisabled(bool aDisabled)
 {
   if (StyleSheet* ss = GetSheet()) {
     ss->SetDisabled(aDisabled);
   }
 }
 
-NS_IMETHODIMP
-HTMLLinkElement::SetMozDisabled(bool aDisabled)
-{
-  SetDisabled(aDisabled);
-  return NS_OK;
-}
-
-
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Charset, charset)
-NS_IMPL_URI_ATTR(HTMLLinkElement, Href, href)
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Hreflang, hreflang)
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Media, media)
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Rel, rel)
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Rev, rev)
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Target, target)
-NS_IMPL_STRING_ATTR(HTMLLinkElement, Type, type)
-
 void
 HTMLLinkElement::OnDNSPrefetchRequested()
 {
   UnsetFlags(HTML_LINK_DNS_PREFETCH_DEFERRED);
   SetFlags(HTML_LINK_DNS_PREFETCH_REQUESTED);
 }
 
 void
@@ -287,31 +262,39 @@ HTMLLinkElement::BeforeSetAttr(int32_t a
 
   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
                                              aValue, aNotify);
 }
 
 nsresult
 HTMLLinkElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   // It's safe to call ResetLinkState here because our new attr value has
   // already been set or unset.  ResetLinkState needs the updated attribute
   // value because notifying the document that content states have changed will
   // call IntrinsicState, which will try to get updated information about the
   // visitedness from Link.
   if (aName == nsGkAtoms::href && kNameSpaceID_None == aNameSpaceID) {
     bool hasHref = aValue;
     Link::ResetLinkState(!!aNotify, hasHref);
     if (IsInUncomposedDoc()) {
       CreateAndDispatchEvent(OwnerDoc(), NS_LITERAL_STRING("DOMLinkChanged"));
     }
   }
 
+  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::href) {
+    mTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aSubjectPrincipal);
+  }
+
   if (aValue) {
     if (aNameSpaceID == kNameSpaceID_None &&
         (aName == nsGkAtoms::href ||
          aName == nsGkAtoms::rel ||
          aName == nsGkAtoms::title ||
          aName == nsGkAtoms::media ||
          aName == nsGkAtoms::type ||
          aName == nsGkAtoms::as ||
@@ -358,17 +341,17 @@ HTMLLinkElement::AfterSetAttr(int32_t aN
            aName == nsGkAtoms::crossorigin || aName == nsGkAtoms::media) &&
           IsInComposedDoc()) {
         UpdatePreload(aName, aValue, aOldValue);
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLLinkElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
 {
   return GetEventTargetParentForAnchors(aVisitor);
 }
 
@@ -419,24 +402,30 @@ HTMLLinkElement::RelList()
 
 already_AddRefed<nsIURI>
 HTMLLinkElement::GetHrefURI() const
 {
   return GetHrefURIForAnchors();
 }
 
 already_AddRefed<nsIURI>
-HTMLLinkElement::GetStyleSheetURL(bool* aIsInline)
+HTMLLinkElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
 {
   *aIsInline = false;
+  *aTriggeringPrincipal = nullptr;
+
   nsAutoString href;
   GetAttr(kNameSpaceID_None, nsGkAtoms::href, href);
   if (href.IsEmpty()) {
     return nullptr;
   }
+
+  nsCOMPtr<nsIPrincipal> prin = mTriggeringPrincipal;
+  prin.forget(aTriggeringPrincipal);
+
   nsCOMPtr<nsIURI> uri = Link::GetURI();
   return uri.forget();
 }
 
 void
 HTMLLinkElement::GetStyleSheetInfo(nsAString& aTitle,
                                    nsAString& aType,
                                    nsAString& aMedia,
--- a/dom/html/HTMLLinkElement.h
+++ b/dom/html/HTMLLinkElement.h
@@ -5,41 +5,37 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_HTMLLinkElement_h
 #define mozilla_dom_HTMLLinkElement_h
 
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/Link.h"
 #include "nsGenericHTMLElement.h"
-#include "nsIDOMHTMLLinkElement.h"
 #include "nsStyleLinkElement.h"
 
 namespace mozilla {
 class EventChainPostVisitor;
 class EventChainPreVisitor;
 namespace dom {
 
 class HTMLLinkElement final : public nsGenericHTMLElement,
-                              public nsIDOMHTMLLinkElement,
                               public nsStyleLinkElement,
                               public Link
 {
 public:
   explicit HTMLLinkElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   // CC
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLLinkElement,
                                            nsGenericHTMLElement)
 
-  // nsIDOMHTMLLinkElement
-  NS_DECL_NSIDOMHTMLLINKELEMENT
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLLinkElement, link);
   NS_DECL_ADDSIZEOFEXCLUDINGTHIS
 
   void LinkAdded();
   void LinkRemoved();
 
   // nsIDOMEventTarget
   virtual nsresult GetEventTargetParent(
@@ -59,16 +55,17 @@ public:
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 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,
@@ -80,73 +77,105 @@ public:
 
   virtual void OnDNSPrefetchDeferred() override;
   virtual void OnDNSPrefetchRequested() override;
   virtual bool HasDeferredDNSPrefetchRequest() override;
 
   // WebIDL
   bool Disabled();
   void SetDisabled(bool aDisabled);
-  // XPCOM GetHref is fine.
-  void SetHref(const nsAString& aHref, ErrorResult& aRv)
+
+  void GetHref(nsAString& aValue)
   {
-    SetHTMLAttr(nsGkAtoms::href, aHref, aRv);
+    GetURIAttr(nsGkAtoms::href, nullptr, aValue);
+  }
+  void GetHref(nsString& aValue, nsIPrincipal&)
+  {
+    GetHref(aValue);
+  }
+  void SetHref(const nsAString& aHref, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::href, aHref, aTriggeringPrincipal, aRv);
   }
   void GetCrossOrigin(nsAString& aResult)
   {
     // Null for both missing and invalid defaults is ok, since we
     // always parse to an enum value, so we don't need an invalid
     // default, and we _want_ the missing default to be null.
     GetEnumAttr(nsGkAtoms::crossorigin, nullptr, aResult);
   }
   void SetCrossOrigin(const nsAString& aCrossOrigin, ErrorResult& aError)
   {
     SetOrRemoveNullableStringAttr(nsGkAtoms::crossorigin, aCrossOrigin, aError);
   }
-  // XPCOM GetRel is fine.
+  // nsAString for WebBrowserPersistLocalDocument
+  void GetRel(nsAString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::rel, aValue);
+  }
   void SetRel(const nsAString& aRel, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::rel, aRel, aRv);
   }
   nsDOMTokenList* RelList();
-  // XPCOM GetMedia is fine.
+  void GetMedia(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::media, aValue);
+  }
   void SetMedia(const nsAString& aMedia, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::media, aMedia, aRv);
   }
-  // XPCOM GetHreflang is fine.
+  void GetHreflang(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::hreflang, aValue);
+  }
   void SetHreflang(const nsAString& aHreflang, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::hreflang, aHreflang, aRv);
   }
   void GetAs(nsAString& aResult);
   void SetAs(const nsAString& aAs, ErrorResult& aRv)
   {
     SetAttr(nsGkAtoms::as ,aAs, aRv);
   }
   nsDOMTokenList* Sizes()
   {
     return GetTokenList(nsGkAtoms::sizes);
   }
-  // XPCOM GetType is fine.
+  void GetType(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::type, aValue);
+  }
   void SetType(const nsAString& aType, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::type, aType, aRv);
   }
-  // XPCOM GetCharset is fine.
+  // Requires nsresult return for nsStyleLinkElement override.
+  NS_IMETHODIMP GetCharset(nsAString& aValue) override
+  {
+    GetHTMLAttr(nsGkAtoms::charset, aValue);
+    return NS_OK;
+  }
   void SetCharset(const nsAString& aCharset, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::charset, aCharset, aRv);
   }
-  // XPCOM GetRev is fine.
+  void GetRev(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::rev, aValue);
+  }
   void SetRev(const nsAString& aRev, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::rev, aRev, aRv);
   }
-  // XPCOM GetTarget is fine.
+  void GetTarget(DOMString& aValue)
+  {
+    GetHTMLAttr(nsGkAtoms::target, aValue);
+  }
   void SetTarget(const nsAString& aTarget, ErrorResult& aRv)
   {
     SetHTMLAttr(nsGkAtoms::target, aTarget, aRv);
   }
   void GetIntegrity(nsAString& aIntegrity) const
   {
     GetHTMLAttr(nsGkAtoms::integrity, aIntegrity);
   }
@@ -174,17 +203,17 @@ public:
     ClearHasPendingLinkUpdate();
     nsGenericHTMLElement::NodeInfoChanged(aOldDoc);
   }
 
 protected:
   virtual ~HTMLLinkElement();
 
   // nsStyleLinkElement
-  virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+  virtual already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
   virtual void GetStyleSheetInfo(nsAString& aTitle,
                                  nsAString& aType,
                                  nsAString& aMedia,
                                  bool* aIsScoped,
                                  bool* aIsAlternate) override;
 protected:
   RefPtr<nsDOMTokenList> mRelList;
 };
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1188,32 +1188,33 @@ public:
     }
 
     MOZ_ASSERT(aElement->IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
     nsContentPolicyType contentPolicyType = aElement->IsHTMLElement(nsGkAtoms::audio)
       ? nsIContentPolicy::TYPE_INTERNAL_AUDIO :
         nsIContentPolicy::TYPE_INTERNAL_VIDEO;
 
     // If aElement has 'loadingprincipal' attribute, we will use the value as
-    // loadingPrincipal for the channel, otherwise it will default to use
+    // triggeringPrincipal for the channel, otherwise it will default to use
     // aElement->NodePrincipal().
     // This function returns true when aElement has 'loadingprincipal', so if
     // setAttrs is true we will override the origin attributes on the channel
     // later.
-    nsCOMPtr<nsIPrincipal> loadingPrincipal;
+    nsCOMPtr<nsIPrincipal> triggeringPrincipal;
     bool setAttrs = nsContentUtils::GetLoadingPrincipalForXULNode(aElement,
-                                    getter_AddRefs(loadingPrincipal));
+                                    aElement->mLoadingSrcTriggeringPrincipal,
+                                    getter_AddRefs(triggeringPrincipal));
 
     nsCOMPtr<nsILoadGroup> loadGroup = aElement->GetDocumentLoadGroup();
     nsCOMPtr<nsIChannel> channel;
     nsresult rv =
       NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
                                            aElement->mLoadingSrc,
                                            static_cast<Element*>(aElement),
-                                           loadingPrincipal,
+                                           triggeringPrincipal,
                                            securityFlags,
                                            contentPolicyType,
                                            loadGroup,
                                            nullptr,   // aCallbacks
                                            nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
                                            nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
                                            nsIChannel::LOAD_CLASSIFY_URI |
                                            nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
@@ -1223,17 +1224,17 @@ public:
       aElement->NotifyLoadError();
       return;
     }
 
     if (setAttrs) {
       nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
       if (loadInfo) {
         // The function simply returns NS_OK, so we ignore the return value.
-        Unused << loadInfo->SetOriginAttributes(loadingPrincipal->OriginAttributesRef());
+        Unused << loadInfo->SetOriginAttributes(triggeringPrincipal->OriginAttributesRef());
       }
     }
 
     nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
     if (cos) {
       if (aElement->mUseUrgentStartForChannel) {
         cos->AddClassFlags(nsIClassOfService::UrgentStart);
 
@@ -1788,16 +1789,17 @@ void HTMLMediaElement::AbortExistingLoad
     ShutdownDecoder();
   }
   if (mSrcStream) {
     EndSrcMediaStreamPlayback();
   }
 
   RemoveMediaElementFromURITable();
   mLoadingSrc = nullptr;
+  mLoadingSrcTriggeringPrincipal = nullptr;
   mMediaSource = nullptr;
 
   if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING ||
       mNetworkState == nsIDOMHTMLMediaElement::NETWORK_IDLE)
   {
     DispatchAsyncEvent(NS_LITERAL_STRING("abort"));
   }
 
@@ -2049,16 +2051,17 @@ void HTMLMediaElement::SelectResource()
     nsresult rv = NewURIFromString(src, getter_AddRefs(uri));
     if (NS_SUCCEEDED(rv)) {
       LOG(LogLevel::Debug, ("%p Trying load from src=%s", this, NS_ConvertUTF16toUTF8(src).get()));
       NS_ASSERTION(!mIsLoadingFromSourceChildren,
         "Should think we're not loading from source children by default");
 
       RemoveMediaElementFromURITable();
       mLoadingSrc = uri;
+      mLoadingSrcTriggeringPrincipal = mSrcAttrTriggeringPrincipal;
       mMediaSource = mSrcMediaSource;
       UpdatePreloadAction();
       if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
           !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
         // preload:none media, suspend the load here before we make any
         // network requests.
         SuspendLoad();
         return;
@@ -2369,16 +2372,17 @@ void HTMLMediaElement::LoadFromSourceChi
       const char16_t* params[] = { src.get() };
       ReportLoadError("MediaLoadInvalidURI", params, ArrayLength(params));
       DealWithFailedElement(child);
       return;
     }
 
     RemoveMediaElementFromURITable();
     mLoadingSrc = uri;
+    mLoadingSrcTriggeringPrincipal = childSrc->GetSrcTriggeringPrincipal();
     mMediaSource = childSrc->GetSrcMediaSource();
     NS_ASSERTION(mNetworkState == nsIDOMHTMLMediaElement::NETWORK_LOADING,
                  "Network state should be loading");
 
     if (mPreloadAction == HTMLMediaElement::PRELOAD_NONE &&
         !IsMediaStreamURI(mLoadingSrc) && !mMediaSource) {
       // preload:none media, suspend the load here before we make any
       // network requests.
@@ -2593,16 +2597,17 @@ nsresult HTMLMediaElement::LoadWithChann
 
   // Make sure we don't reenter during synchronous abort events.
   if (mIsRunningLoadMethod)
     return NS_OK;
   mIsRunningLoadMethod = true;
   AbortExistingLoads();
   mIsRunningLoadMethod = false;
 
+  mLoadingSrcTriggeringPrincipal = nullptr;
   nsresult rv = aChannel->GetOriginalURI(getter_AddRefs(mLoadingSrc));
   NS_ENSURE_SUCCESS(rv, rv);
 
   ChangeDelayLoadStatus(true);
   rv = InitializeDecoderForChannel(aChannel, aListener);
   if (NS_FAILED(rv)) {
     ChangeDelayLoadStatus(false);
     return rv;
@@ -4444,21 +4449,26 @@ bool HTMLMediaElement::IsHTMLFocusable(b
 int32_t HTMLMediaElement::TabIndexDefault()
 {
   return 0;
 }
 
 nsresult
 HTMLMediaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::src) {
       mSrcMediaSource = nullptr;
+      mSrcAttrTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+          this, aValue ? aValue->GetStringValue() : EmptyString(),
+          aMaybeScriptedPrincipal);
       if (aValue) {
         nsString srcStr = aValue->GetStringValue();
         nsCOMPtr<nsIURI> uri;
         NewURIFromString(srcStr, getter_AddRefs(uri));
         if (uri && IsMediaSourceURI(uri)) {
           nsresult rv =
             NS_GetSourceForMediaSourceURI(uri, getter_AddRefs(mSrcMediaSource));
           if (NS_FAILED(rv)) {
@@ -4490,17 +4500,19 @@ HTMLMediaElement::AfterSetAttr(int32_t a
 
   // Since AfterMaybeChangeAttr may call DoLoad, make sure that it is called
   // *after* any possible changes to mSrcMediaSource.
   if (aValue) {
     AfterMaybeChangeAttr(aNameSpaceID, aName, aNotify);
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue,
+                                            aMaybeScriptedPrincipal,
+                                            aNotify);
 }
 
 nsresult
 HTMLMediaElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                          const nsAttrValueOrString& aValue,
                                          bool aNotify)
 {
   AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -430,20 +430,23 @@ public:
    * cycle collection unlinking!
    */
   MediaStream* GetSrcMediaStream() const;
 
   // WebIDL
 
   MediaError* GetError() const;
 
-  // XPCOM GetSrc() is OK
-  void SetSrc(const nsAString& aSrc, ErrorResult& aRv)
+  void GetSrc(nsString& aSrc, nsIPrincipal&)
   {
-    SetHTMLAttr(nsGkAtoms::src, aSrc, aRv);
+    GetSrc(aSrc);
+  }
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
+  {
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aRv);
   }
 
   // XPCOM GetCurrentSrc() is OK
 
   void GetCrossOrigin(nsAString& aResult)
   {
     // Null for both missing and invalid defaults is ok, since we
     // always parse to an enum value, so we don't need an invalid
@@ -1327,16 +1330,17 @@ protected:
 
   // Mark the decoder owned by the element as tainted so that the
   // suspend-video-decoder is disabled.
   void MarkAsTainted();
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
   // The current decoder. Load() has been called on this decoder.
   // At most one of mDecoder and mSrcStream can be non-null.
   RefPtr<MediaDecoder> mDecoder;
@@ -1358,16 +1362,19 @@ protected:
   // A reference to the VideoFrameContainer which contains the current frame
   // of video to display.
   RefPtr<VideoFrameContainer> mVideoFrameContainer;
 
   // Holds a reference to the DOM wrapper for the MediaStream that has been
   // set in the src attribute.
   RefPtr<DOMMediaStream> mSrcAttrStream;
 
+  // Holds the triggering principal for the src attribute.
+  nsCOMPtr<nsIPrincipal> mSrcAttrTriggeringPrincipal;
+
   // Holds a reference to the DOM wrapper for the MediaStream that we're
   // actually playing.
   // At most one of mDecoder and mSrcStream can be non-null.
   RefPtr<DOMMediaStream> mSrcStream;
 
   // True once mSrcStream's initial set of tracks are known.
   bool mSrcStreamTracksAvailable;
 
@@ -1469,16 +1476,19 @@ protected:
 
   // URI of the resource we're attempting to load. This stores the value we
   // return in the currentSrc attribute. Use GetCurrentSrc() to access the
   // currentSrc attribute.
   // This is always the original URL we're trying to load --- before
   // redirects etc.
   nsCOMPtr<nsIURI> mLoadingSrc;
 
+  // The triggering principal for the current source.
+  nsCOMPtr<nsIPrincipal> mLoadingSrcTriggeringPrincipal;
+
   // Stores the current preload action for this element. Initially set to
   // PRELOAD_UNDEFINED, its value is changed by calling
   // UpdatePreloadAction().
   PreloadAction mPreloadAction;
 
   // Time that the last timeupdate event was fired. Read/Write from the
   // main thread only.
   TimeStamp mTimeUpdateTime;
--- a/dom/html/HTMLMenuElement.cpp
+++ b/dom/html/HTMLMenuElement.cpp
@@ -103,28 +103,30 @@ HTMLMenuElement::Build(nsIMenuBuilder* a
   }
 
   BuildSubmenu(EmptyString(), this, aBuilder);
 }
 
 nsresult
 HTMLMenuElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::type) {
     if (aValue) {
       mType = aValue->GetEnumValue();
     } else {
       mType = kMenuDefaultType->value;
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 bool
 HTMLMenuElement::ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 nsAttrValue& aResult)
 {
--- a/dom/html/HTMLMenuElement.h
+++ b/dom/html/HTMLMenuElement.h
@@ -23,16 +23,17 @@ public:
   NS_IMPL_FROMCONTENT_HTML_WITH_TAG(HTMLMenuElement, menu)
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   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;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
--- a/dom/html/HTMLMenuItemElement.cpp
+++ b/dom/html/HTMLMenuItemElement.cpp
@@ -370,17 +370,19 @@ HTMLMenuItemElement::GetText(nsAString& 
 
   text.CompressWhitespace(true, true);
   aText = text;
 }
 
 nsresult
 HTMLMenuItemElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
-                                  const nsAttrValue* aOldValue, bool aNotify)
+                                  const nsAttrValue* aOldValue,
+                                  nsIPrincipal* aSubjectPrincipal,
+                                  bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     // Handle type changes first, since some of the later conditions in this
     // method look at mType and want to see the new value.
     if (aName == nsGkAtoms::type) {
       if (aValue) {
         mType = aValue->GetEnumValue();
       } else {
@@ -404,17 +406,17 @@ HTMLMenuItemElement::AfterSetAttr(int32_
         mShouldInitChecked = true;
       } else {
         InitChecked();
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 void
 HTMLMenuItemElement::WalkRadioGroup(Visitor* aVisitor)
 {
   nsIContent* parent = GetParent();
   if (!parent) {
     aVisitor->Visit(this);
--- a/dom/html/HTMLMenuItemElement.h
+++ b/dom/html/HTMLMenuItemElement.h
@@ -123,16 +123,17 @@ protected:
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 
 protected:
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   void WalkRadioGroup(Visitor* aVisitor);
 
   HTMLMenuItemElement* GetSelectedRadio();
 
   void AddedToRadioGroup();
 
--- a/dom/html/HTMLMetaElement.cpp
+++ b/dom/html/HTMLMetaElement.cpp
@@ -50,17 +50,19 @@ HTMLMetaElement::SetMetaReferrer(nsIDocu
       aDocument->SetHeaderData(nsGkAtoms::referrer, content);
   }
   return NS_OK;
 }
 
 nsresult
 HTMLMetaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     nsIDocument *document = GetUncomposedDoc();
     if (aName == nsGkAtoms::content) {
       if (document && AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
                                   nsGkAtoms::viewport, eIgnoreCase)) {
         nsAutoString content;
         nsresult rv = GetContent(content);
@@ -72,17 +74,17 @@ HTMLMetaElement::AfterSetAttr(int32_t aN
     // Update referrer policy when it got changed from JS
     nsresult rv = SetMetaReferrer(document);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLMetaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                             nsIContent* aBindingParent,
                             bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
--- a/dom/html/HTMLMetaElement.h
+++ b/dom/html/HTMLMetaElement.h
@@ -25,16 +25,17 @@ public:
                               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,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   void CreateAndDispatchEvent(nsIDocument* aDoc, const nsAString& aEventName);
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   void GetName(nsAString& aValue)
--- a/dom/html/HTMLObjectElement.cpp
+++ b/dom/html/HTMLObjectElement.cpp
@@ -278,23 +278,25 @@ HTMLObjectElement::UnbindFromTree(bool a
 #endif
   nsObjectLoadingContent::UnbindFromTree(aDeep, aNullParent);
   nsGenericHTMLFormElement::UnbindFromTree(aDeep, aNullParent);
 }
 
 nsresult
 HTMLObjectElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
   NS_ENSURE_SUCCESS(rv, rv);
 
   return nsGenericHTMLFormElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                                aOldValue, aNotify);
+                                                aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLObjectElement::OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify)
 {
   nsresult rv = AfterMaybeChangeAttr(aNamespaceID, aName, aNotify);
--- a/dom/html/HTMLObjectElement.h
+++ b/dom/html/HTMLObjectElement.h
@@ -248,16 +248,17 @@ public:
 
 protected:
   // Override for nsImageLoadingContent.
   nsIContent* AsContent() override { return this; }
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
 private:
   /**
    * Returns if the element is currently focusable regardless of it's tabindex
--- a/dom/html/HTMLOptGroupElement.cpp
+++ b/dom/html/HTMLOptGroupElement.cpp
@@ -93,17 +93,19 @@ HTMLOptGroupElement::RemoveChildAt(uint3
   SafeOptionListMutation safeMutation(GetSelect(), this, nullptr, aIndex,
                                       aNotify);
   nsGenericHTMLElement::RemoveChildAt(aIndex, aNotify);
 }
 
 nsresult
 HTMLOptGroupElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
-                                  const nsAttrValue* aOldValue, bool aNotify)
+                                  const nsAttrValue* aOldValue,
+                                  nsIPrincipal* aSubjectPrincipal,
+                                  bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::disabled) {
 
     EventStates disabledStates;
     if (aValue) {
       disabledStates |= NS_EVENT_STATE_DISABLED;
     } else {
       disabledStates |= NS_EVENT_STATE_ENABLED;
@@ -122,17 +124,17 @@ HTMLOptGroupElement::AfterSetAttr(int32_
         if (auto optElement = HTMLOptionElement::FromContent(child)) {
           optElement->OptGroupDisabledChanged(true);
         }
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 JSObject*
 HTMLOptGroupElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLOptGroupElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
--- a/dom/html/HTMLOptGroupElement.h
+++ b/dom/html/HTMLOptGroupElement.h
@@ -34,16 +34,17 @@ public:
                      EventChainPreVisitor& aVisitor) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo* aNodeInfo, nsINode** aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   virtual nsIDOMNode* AsDOMNode() override { return this; }
 
   virtual bool IsDisabled() const override {
     return State().HasState(NS_EVENT_STATE_DISABLED);
   }
 
--- a/dom/html/HTMLOptionElement.cpp
+++ b/dom/html/HTMLOptionElement.cpp
@@ -260,17 +260,19 @@ HTMLOptionElement::BeforeSetAttr(int32_t
   mSelectedChanged = false;
 
   return NS_OK;
 }
 
 nsresult
 HTMLOptionElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::disabled) {
       UpdateDisabledState(aNotify);
     }
 
     if (aName == nsGkAtoms::value && Selected()) {
       // Since this option is selected, changing value
@@ -279,17 +281,17 @@ HTMLOptionElement::AfterSetAttr(int32_t 
       HTMLSelectElement* select = GetSelect();
       if (select) {
         select->UpdateValueMissingValidityState();
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue, aSubjectPrincipal, aNotify);
 }
 
 NS_IMETHODIMP
 HTMLOptionElement::GetText(nsAString& aText)
 {
   nsAutoString text;
 
   nsIContent* child = nsINode::GetFirstChild();
--- a/dom/html/HTMLOptionElement.h
+++ b/dom/html/HTMLOptionElement.h
@@ -53,16 +53,17 @@ public:
                                               int32_t aModType) const override;
 
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   void SetSelectedInternal(bool aValue, bool aNotify);
 
   /**
    * This callback is called by an optgroup on all its option elements whenever
    * its disabled state is changed so that option elements can know their
    * disabled state might have changed.
--- a/dom/html/HTMLScriptElement.cpp
+++ b/dom/html/HTMLScriptElement.cpp
@@ -164,19 +164,19 @@ HTMLScriptElement::SetDefer(bool aDefer,
 
 bool
 HTMLScriptElement::Defer()
 {
   return GetBoolAttr(nsGkAtoms::defer);
 }
 
 void
-HTMLScriptElement::SetSrc(const nsAString& aSrc, ErrorResult& rv)
+HTMLScriptElement::SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& rv)
 {
-  rv = SetAttrHelper(nsGkAtoms::src, aSrc);
+  SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, rv);
 }
 
 void
 HTMLScriptElement::SetType(const nsAString& aType, ErrorResult& rv)
 {
   SetHTMLAttr(nsGkAtoms::type, aType, rv);
 }
 
@@ -230,23 +230,32 @@ void
 HTMLScriptElement::SetNoModule(bool aValue, ErrorResult& aRv)
 {
   SetHTMLBoolAttr(nsGkAtoms::nomodule, aValue, aRv);
 }
 
 nsresult
 HTMLScriptElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                bool aNotify)
 {
   if (nsGkAtoms::async == aName && kNameSpaceID_None == aNamespaceID) {
     mForceAsync = false;
   }
-  return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                            aOldValue, aNotify);
+  if (nsGkAtoms::src == aName && kNameSpaceID_None == aNamespaceID) {
+    mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aMaybeScriptedPrincipal);
+  }
+  return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName,
+                                            aValue, aOldValue,
+                                            aMaybeScriptedPrincipal,
+                                            aNotify);
 }
 
 NS_IMETHODIMP
 HTMLScriptElement::GetInnerHTML(nsAString& aInnerHTML)
 {
   if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
--- a/dom/html/HTMLScriptElement.h
+++ b/dom/html/HTMLScriptElement.h
@@ -54,24 +54,29 @@ public:
 
   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,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
 
   // WebIDL
   void SetText(const nsAString& aValue, ErrorResult& rv);
   void SetCharset(const nsAString& aCharset, ErrorResult& rv);
   void SetDefer(bool aDefer, ErrorResult& rv);
   bool Defer();
-  void SetSrc(const nsAString& aSrc, ErrorResult& rv);
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& rv);
+  void GetSrc(nsString& aSrc, nsIPrincipal&)
+  {
+    GetSrc(aSrc);
+  };
   void SetType(const nsAString& aType, ErrorResult& rv);
   void SetHtmlFor(const nsAString& aHtmlFor, ErrorResult& rv);
   void SetEvent(const nsAString& aEvent, ErrorResult& rv);
   void GetCrossOrigin(nsAString& aResult)
   {
     // Null for both missing and invalid defaults is ok, since we
     // always parse to an enum value, so we don't need an invalid
     // default, and we _want_ the missing default to be null.
--- a/dom/html/HTMLSelectElement.cpp
+++ b/dom/html/HTMLSelectElement.cpp
@@ -1311,17 +1311,19 @@ HTMLSelectElement::BeforeSetAttr(int32_t
 
   return nsGenericHTMLFormElementWithState::BeforeSetAttr(aNameSpaceID, aName,
                                                           aValue, aNotify);
 }
 
 nsresult
 HTMLSelectElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::disabled) {
       // This *has* to be called *before* validity state check because
       // UpdateBarredFromConstraintValidation and
       // UpdateValueMissingValidityState depend on our disabled state.
       UpdateDisabledState(aNotify);
 
@@ -1344,16 +1346,17 @@ HTMLSelectElement::AfterSetAttr(int32_t 
         // selected in that case
         CheckSelectSomething(aNotify);
       }
     }
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName,
                                                          aValue, aOldValue,
+                                                         aSubjectPrincipal,
                                                          aNotify);
 }
 
 void
 HTMLSelectElement::DoneAddingChildren(bool aHaveNotified)
 {
   mIsDoneAddingChildren = true;
 
--- a/dom/html/HTMLSelectElement.h
+++ b/dom/html/HTMLSelectElement.h
@@ -381,16 +381,17 @@ public:
                                bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   virtual void DoneAddingChildren(bool aHaveNotified) override;
   virtual bool IsDoneAddingChildren() override {
     return mIsDoneAddingChildren;
   }
 
   virtual bool ParseAttribute(int32_t aNamespaceID,
--- a/dom/html/HTMLSharedElement.cpp
+++ b/dom/html/HTMLSharedElement.cpp
@@ -223,17 +223,19 @@ SetBaseTargetUsingFirstBaseWithTarget(ns
   }
 
   aDocument->SetBaseTarget(EmptyString());
 }
 
 nsresult
 HTMLSharedElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::href) {
       // If the href attribute of a <base> tag is changing, we may need to
       // update the document's base URI, which will cause all the links on the
       // page to be re-resolved given the new base.
       // If the href is being unset (aValue is null), we will need to find a new
       // <base>.
@@ -247,17 +249,17 @@ HTMLSharedElement::AfterSetAttr(int32_t 
       if (mNodeInfo->Equals(nsGkAtoms::base) && IsInUncomposedDoc()) {
         SetBaseTargetUsingFirstBaseWithTarget(GetUncomposedDoc(),
                                               aValue ? this : nullptr);
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 nsresult
 HTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers)
 {
   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
--- a/dom/html/HTMLSharedElement.h
+++ b/dom/html/HTMLSharedElement.h
@@ -162,15 +162,16 @@ public:
 protected:
   virtual ~HTMLSharedElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSharedElement_h
--- a/dom/html/HTMLSourceElement.cpp
+++ b/dom/html/HTMLSourceElement.cpp
@@ -91,18 +91,25 @@ HTMLSourceElement::UpdateMediaList(const
 
   nsCSSParser cssParser;
   mMediaList = MediaList::Create(OwnerDoc()->GetStyleBackendType(), mediaStr);
 }
 
 nsresult
 HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
+                                bool aNotify)
 {
+  if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::srcset) {
+    mSrcsetTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aMaybeScriptedPrincipal);
+  }
   // If we are associated with a <picture> with a valid <img>, notify it of
   // responsive parameter changes
   Element *parent = nsINode::GetParentElement();
   if (aNameSpaceID == kNameSpaceID_None &&
       (aName == nsGkAtoms::srcset ||
        aName == nsGkAtoms::sizes ||
        aName == nsGkAtoms::media ||
        aName == nsGkAtoms::type) &&
@@ -124,29 +131,34 @@ HTMLSourceElement::AfterSetAttr(int32_t 
           img->PictureSourceMediaOrTypeChanged(AsContent(), aNotify);
         }
       }
     }
 
   } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::media) {
     UpdateMediaList(aValue);
   } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
+    mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+        this, aValue ? aValue->GetStringValue() : EmptyString(),
+        aMaybeScriptedPrincipal);
     mSrcMediaSource = nullptr;
     if (aValue) {
       nsString srcStr = aValue->GetStringValue();
       nsCOMPtr<nsIURI> uri;
       NewURIFromString(srcStr, getter_AddRefs(uri));
       if (uri && IsMediaSourceURI(uri)) {
         NS_GetSourceForMediaSourceURI(uri, getter_AddRefs(mSrcMediaSource));
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue,
+                                            aMaybeScriptedPrincipal,
+                                            aNotify);
 }
 
 nsresult
 HTMLSourceElement::BindToTree(nsIDocument *aDocument,
                               nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers)
 {
--- a/dom/html/HTMLSourceElement.h
+++ b/dom/html/HTMLSourceElement.h
@@ -54,41 +54,51 @@ public:
   static bool WouldMatchMediaForDocument(const nsAString& aMediaStr,
                                          const nsIDocument *aDocument);
 
   // Return the MediaSource object if any associated with the src attribute
   // when it was set.
   MediaSource* GetSrcMediaSource() { return mSrcMediaSource; };
 
   // WebIDL
-  void GetSrc(nsString& aSrc)
+  void GetSrc(nsString& aSrc, nsIPrincipal&)
   {
     GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
   }
-  void SetSrc(const nsAString& aSrc, mozilla::ErrorResult& rv)
+  void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& rv)
+  {
+    SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, rv);
+  }
+
+  nsIPrincipal* GetSrcTriggeringPrincipal() const
   {
-    SetHTMLAttr(nsGkAtoms::src, aSrc, rv);
+    return mSrcTriggeringPrincipal;
+  }
+
+  nsIPrincipal* GetSrcsetTriggeringPrincipal() const
+  {
+    return mSrcsetTriggeringPrincipal;
   }
 
   void GetType(DOMString& aType)
   {
     GetHTMLAttr(nsGkAtoms::type, aType);
   }
   void SetType(const nsAString& aType, ErrorResult& rv)
   {
     SetHTMLAttr(nsGkAtoms::type, aType, rv);
   }
 
-  void GetSrcset(DOMString& aSrcset)
+  void GetSrcset(DOMString& aSrcset, nsIPrincipal&)
   {
     GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
   }
-  void SetSrcset(const nsAString& aSrcset, mozilla::ErrorResult& rv)
+  void SetSrcset(const nsAString& aSrcset, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& rv)
   {
-    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, rv);
+    SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aTriggeringPrincipal, rv);
   }
 
   void GetSizes(DOMString& aSizes)
   {
     GetHTMLAttr(nsGkAtoms::sizes, aSizes);
   }
   void SetSizes(const nsAString& aSizes, mozilla::ErrorResult& rv)
   {
@@ -108,22 +118,29 @@ protected:
   virtual ~HTMLSourceElement();
 
   virtual JSObject* WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
 
 private:
   RefPtr<MediaList> mMediaList;
   RefPtr<MediaSource> mSrcMediaSource;
 
+  // The triggering principal for the src attribute.
+  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+
+  // The triggering principal for the srcset attribute.
+  nsCOMPtr<nsIPrincipal> mSrcsetTriggeringPrincipal;
+
   // Generates a new MediaList using the given input
   void UpdateMediaList(const nsAttrValue* aValue);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_HTMLSourceElement_h
--- a/dom/html/HTMLStyleElement.cpp
+++ b/dom/html/HTMLStyleElement.cpp
@@ -138,32 +138,34 @@ HTMLStyleElement::UnbindFromTree(bool aD
   }
 
   UpdateStyleSheetInternal(oldDoc, oldShadow);
 }
 
 nsresult
 HTMLStyleElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                const nsAttrValue* aValue,
-                               const nsAttrValue* aOldValue, bool aNotify)
+                               const nsAttrValue* aOldValue,
+                               nsIPrincipal* aSubjectPrincipal,
+                               bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::title ||
         aName == nsGkAtoms::media ||
         aName == nsGkAtoms::type) {
       UpdateStyleSheetInternal(nullptr, nullptr, true);
     } else if (aName == nsGkAtoms::scoped &&
                OwnerDoc()->IsScopedStyleEnabled()) {
       bool isScoped = aValue;
       UpdateStyleSheetScopedness(isScoped);
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 NS_IMETHODIMP
 HTMLStyleElement::GetInnerHTML(nsAString& aInnerHTML)
 {
   if (!nsContentUtils::GetNodeTextContent(this, false, aInnerHTML, fallible)) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
@@ -179,19 +181,20 @@ HTMLStyleElement::SetInnerHTML(const nsA
   aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);
 
   SetEnableUpdates(true);
 
   UpdateStyleSheetInternal(nullptr, nullptr);
 }
 
 already_AddRefed<nsIURI>
-HTMLStyleElement::GetStyleSheetURL(bool* aIsInline)
+HTMLStyleElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
 {
   *aIsInline = true;
+  *aTriggeringPrincipal = nullptr;
   return nullptr;
 }
 
 void
 HTMLStyleElement::GetStyleSheetInfo(nsAString& aTitle,
                                     nsAString& aType,
                                     nsAString& aMedia,
                                     bool* aIsScoped,
--- a/dom/html/HTMLStyleElement.h
+++ b/dom/html/HTMLStyleElement.h
@@ -39,16 +39,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 nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   // nsIMutationObserver
   NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
   NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
@@ -82,17 +83,17 @@ public:
     SetHTMLBoolAttr(nsGkAtoms::scoped, aScoped, aError);
   }
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
 protected:
   virtual ~HTMLStyleElement();
 
-  already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+  already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
   void GetStyleSheetInfo(nsAString& aTitle,
                          nsAString& aType,
                          nsAString& aMedia,
                          bool* aIsScoped,
                          bool* aIsAlternate) override;
   /**
    * Common method to call from the various mutation observer methods.
    * aContent is a content node that's either the one that changed or its
--- a/dom/html/HTMLTableElement.cpp
+++ b/dom/html/HTMLTableElement.cpp
@@ -1191,19 +1191,21 @@ HTMLTableElement::BeforeSetAttr(int32_t 
   }
   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName, aValue,
                                              aNotify);
 }
 
 nsresult
 HTMLTableElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                const nsAttrValue* aValue,
-                               const nsAttrValue* aOldValue, bool aNotify)
+                               const nsAttrValue* aOldValue,
+                               nsIPrincipal* aSubjectPrincipal,
+                               bool aNotify)
 {
   if (aName == nsGkAtoms::cellpadding && aNameSpaceID == kNameSpaceID_None) {
     BuildInheritedAttributes();
   }
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aSubjectPrincipal, aNotify);
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/html/HTMLTableElement.h
+++ b/dom/html/HTMLTableElement.h
@@ -204,16 +204,17 @@ public:
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   /**
    * Called when an attribute has just been changed
    */
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(HTMLTableElement,
                                            nsGenericHTMLElement)
   nsMappedAttributes* GetAttributesMappedForCell();
 
 protected:
   virtual ~HTMLTableElement();
--- a/dom/html/HTMLTextAreaElement.cpp
+++ b/dom/html/HTMLTextAreaElement.cpp
@@ -1067,17 +1067,19 @@ HTMLTextAreaElement::ContentChanged(nsIC
     nsCOMPtr<nsIMutationObserver> kungFuDeathGrip(this);
     Reset();
   }
 }
 
 nsresult
 HTMLTextAreaElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
-                                  const nsAttrValue* aOldValue, bool aNotify)
+                                  const nsAttrValue* aOldValue,
+                                  nsIPrincipal* aSubjectPrincipal,
+                                  bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::required || aName == nsGkAtoms::disabled ||
         aName == nsGkAtoms::readonly) {
       if (aName == nsGkAtoms::disabled) {
         // This *has* to be called *before* validity state check because
         // UpdateBarredFromConstraintValidation and
         // UpdateValueMissingValidityState depend on our disabled state.
@@ -1100,17 +1102,17 @@ HTMLTextAreaElement::AfterSetAttr(int32_
     } else if (aName == nsGkAtoms::maxlength) {
       UpdateTooLongValidityState();
     } else if (aName == nsGkAtoms::minlength) {
       UpdateTooShortValidityState();
     }
   }
 
   return nsGenericHTMLFormElementWithState::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                                         aOldValue, aNotify);
+                                                         aOldValue, aSubjectPrincipal, aNotify);
   }
 
 nsresult
 HTMLTextAreaElement::CopyInnerTo(Element* aDest, bool aPreallocateChildren)
 {
   nsresult rv = nsGenericHTMLFormElementWithState::CopyInnerTo(aDest,
                                                                aPreallocateChildren);
   NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/html/HTMLTextAreaElement.h
+++ b/dom/html/HTMLTextAreaElement.h
@@ -366,16 +366,17 @@ protected:
    * aContent is a content node that's either the one that changed or its
    * parent; we should only respond to the change if aContent is non-anonymous.
    */
   void ContentChanged(nsIContent* aContent);
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom *aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   /**
    * Return if an element should have a specific validity UI
    * (with :-moz-ui-invalid and :-moz-ui-valid pseudo-classes).
    *
    * @return Whether the element should have a validity UI.
    */
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -694,17 +694,19 @@ nsGenericHTMLElement::BeforeSetAttr(int3
 
   return nsGenericHTMLElementBase::BeforeSetAttr(aNamespaceID, aName, aValue,
                                                  aNotify);
 }
 
 nsresult
 nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                    const nsAttrValue* aValue,
-                                   const nsAttrValue* aOldValue, bool aNotify)
+                                   const nsAttrValue* aOldValue,
+                                   nsIPrincipal* aMaybeScriptedPrincipal,
+                                   bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (IsEventAttributeName(aName) && aValue) {
       MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
                  "Expected string value for script body");
       nsresult rv = SetEventHandler(aName, aValue->GetStringValue());
       NS_ENSURE_SUCCESS(rv, rv);
     }
@@ -785,17 +787,19 @@ nsGenericHTMLElement::AfterSetAttr(int32
         if (CanHaveName(NodeInfo()->NameAtom())) {
           AddToNameTable(aValue->GetAtomValue());
         }
       }
     }
   }
 
   return nsGenericHTMLElementBase::AfterSetAttr(aNamespaceID, aName,
-                                                aValue, aOldValue, aNotify);
+                                                aValue, aOldValue,
+                                                aMaybeScriptedPrincipal,
+                                                aNotify);
 }
 
 EventListenerManager*
 nsGenericHTMLElement::GetEventListenerManagerForAttr(nsAtom* aAttrName,
                                                      bool* aDefer)
 {
   // Attributes on the body and frameset tags get set on the global object
   if ((mNodeInfo->Equals(nsGkAtoms::body) ||
@@ -1990,17 +1994,19 @@ nsGenericHTMLFormElement::BeforeSetAttr(
 
   return nsGenericHTMLElement::BeforeSetAttr(aNameSpaceID, aName,
                                              aValue, aNotify);
 }
 
 nsresult
 nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                        const nsAttrValue* aValue,
-                                       const nsAttrValue* aOldValue, bool aNotify)
+                                       const nsAttrValue* aOldValue,
+                                       nsIPrincipal* aMaybeScriptedPrincipal,
+                                       bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     // add the control to the hashtable as needed
 
     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
         aValue && !aValue->IsEmptyString()) {
       MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
                  "Expected atom value for name/id");
@@ -2039,17 +2045,19 @@ nsGenericHTMLFormElement::AfterSetAttr(i
         // Because we have a new @form value (or no more @form), we have to
         // update our form owner.
         UpdateFormOwner(false, formIdElement);
       }
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue,
+                                            aMaybeScriptedPrincipal,
+                                            aNotify);
 }
 
 nsresult
 nsGenericHTMLFormElement::GetEventTargetParent(EventChainPreVisitor& aVisitor)
 {
   if (aVisitor.mEvent->IsTrusted() && (aVisitor.mEvent->mMessage == eFocus ||
                                        aVisitor.mEvent->mMessage == eBlur)) {
     // We have to handle focus/blur event to change focus states in
--- a/dom/html/nsGenericHTMLElement.h
+++ b/dom/html/nsGenericHTMLElement.h
@@ -759,16 +759,17 @@ private:
 
 protected:
   virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
 
   virtual mozilla::EventListenerManager*
     GetEventListenerManagerForAttr(nsAtom* aAttrName,
                                    bool* aDefer) override;
 
   /**
    * Dispatch a simulated mouse click by keyboard to the given element.
@@ -804,16 +805,20 @@ protected:
   void SetHTMLAttr(nsAtom* aName, const nsAString& aValue)
   {
     SetAttr(kNameSpaceID_None, aName, aValue, true);
   }
   void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, mozilla::ErrorResult& aError)
   {
     mozilla::dom::Element::SetAttr(aName, aValue, aError);
   }
+  void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& aError)
+  {
+    mozilla::dom::Element::SetAttr(aName, aValue, aTriggeringPrincipal, aError);
+  }
   void UnsetHTMLAttr(nsAtom* aName, mozilla::ErrorResult& aError)
   {
     mozilla::dom::Element::UnsetAttr(aName, aError);
   }
   void SetHTMLBoolAttr(nsAtom* aName, bool aValue, mozilla::ErrorResult& aError)
   {
     if (aValue) {
       SetHTMLAttr(aName, EmptyString(), aError);
@@ -1132,16 +1137,17 @@ protected:
 
   virtual nsresult BeforeSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                  const nsAttrValueOrString* aValue,
                                  bool aNotify) override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aMaybeScriptedPrincipal,
                                 bool aNotify) override;
 
   virtual void BeforeSetForm(bool aBindToTree) {}
 
   virtual void AfterClearForm(bool aUnbindOrDelete) {}
 
   void SetForm(mozilla::dom::HTMLFormElement* aForm, bool aBindToTree);
 
--- a/dom/html/nsGenericHTMLFrameElement.cpp
+++ b/dom/html/nsGenericHTMLFrameElement.cpp
@@ -48,17 +48,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerWindow)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserElementAPI)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(nsGenericHTMLFrameElement,
                                              nsGenericHTMLElement,
                                              nsIFrameLoaderOwner,
                                              nsIDOMMozBrowserFrame,
-                                             nsIMozBrowserFrame)
+                                             nsIMozBrowserFrame,
+                                             nsGenericHTMLFrameElement)
 
 NS_IMPL_BOOL_ATTR(nsGenericHTMLFrameElement, Mozbrowser, mozbrowser)
 
 int32_t
 nsGenericHTMLFrameElement::TabIndexDefault()
 {
   return 0;
 }
@@ -326,23 +327,25 @@ PrincipalAllowsBrowserFrame(nsIPrincipal
   nsresult rv = permMgr->TestPermissionFromPrincipal(aPrincipal, "browser", &permission);
   NS_ENSURE_SUCCESS(rv, false);
   return permission == nsIPermissionManager::ALLOW_ACTION;
 }
 
 /* virtual */ nsresult
 nsGenericHTMLFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                         const nsAttrValue* aValue,
-                                        const nsAttrValue* aOldValue, bool aNotify)
+                                        const nsAttrValue* aOldValue,
+                                        nsIPrincipal* aMaybeScriptedPrincipal,
+                                        bool aNotify)
 {
   if (aValue) {
     nsAttrValueOrString value(aValue);
-    AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aNotify);
+    AfterMaybeChangeAttr(aNameSpaceID, aName, &value, aMaybeScriptedPrincipal, aNotify);
   } else {
-    AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aNotify);
+    AfterMaybeChangeAttr(aNameSpaceID, aName, nullptr, aMaybeScriptedPrincipal, aNotify);
   }
 
   if (aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::scrolling) {
       if (mFrameLoader) {
         nsIDocShell* docshell = mFrameLoader->GetExistingDocShell();
         nsCOMPtr<nsIScrollable> scrollable = do_QueryInterface(docshell);
         if (scrollable) {
@@ -365,39 +368,42 @@ nsGenericHTMLFrameElement::AfterSetAttr(
       }
     } else if (aName == nsGkAtoms::mozbrowser) {
       mReallyIsBrowser = !!aValue && BrowserFramesEnabled() &&
                          PrincipalAllowsBrowserFrame(NodePrincipal());
     }
   }
 
   return nsGenericHTMLElement::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                            aOldValue, aNotify);
+                                            aOldValue, aMaybeScriptedPrincipal, aNotify);
 }
 
 nsresult
 nsGenericHTMLFrameElement::OnAttrSetButNotChanged(int32_t aNamespaceID,
                                                   nsAtom* aName,
                                                   const nsAttrValueOrString& aValue,
                                                   bool aNotify)
 {
-  AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, aNotify);
+  AfterMaybeChangeAttr(aNamespaceID, aName, &aValue, nullptr, aNotify);
 
   return nsGenericHTMLElement::OnAttrSetButNotChanged(aNamespaceID, aName,
                                                       aValue, aNotify);
 }
 
 void
 nsGenericHTMLFrameElement::AfterMaybeChangeAttr(int32_t aNamespaceID,
                                                 nsAtom* aName,
                                                 const nsAttrValueOrString* aValue,
+                                                nsIPrincipal* aMaybeScriptedPrincipal,
                                                 bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::src) {
+      mSrcTriggeringPrincipal = nsContentUtils::GetAttrTriggeringPrincipal(
+          this, aValue ? aValue->String() : EmptyString(), aMaybeScriptedPrincipal);
       if (aValue && (!IsHTMLElement(nsGkAtoms::iframe) ||
           !HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc))) {
         // Don't propagate error here. The attribute was successfully set,
         // that's what we should reflect.
         LoadSrc();
       }
     } else if (aName == nsGkAtoms::name) {
       // Propagate "name" to the docshell to make browsing context names live,
--- a/dom/html/nsGenericHTMLFrameElement.h
+++ b/dom/html/nsGenericHTMLFrameElement.h
@@ -14,16 +14,20 @@
 #include "nsFrameLoader.h"
 #include "nsGenericHTMLElement.h"
 #include "nsIDOMEventListener.h"
 #include "nsIFrameLoader.h"
 #include "nsIMozBrowserFrame.h"
 
 class nsXULElement;
 
+#define NS_GENERICHTMLFRAMEELEMENT_IID \
+{ 0x8190db72, 0xdab0, 0x4d72, \
+  { 0x94, 0x26, 0x87, 0x5f, 0x5a, 0x8a, 0x2a, 0xe5 } }
+
 /**
  * A helper class for frame elements
  */
 class nsGenericHTMLFrameElement : public nsGenericHTMLElement,
                                   public nsIFrameLoaderOwner,
                                   public mozilla::nsBrowserElement,
                                   public nsIMozBrowserFrame
 {
@@ -41,16 +45,18 @@ public:
   }
 
   NS_DECL_ISUPPORTS_INHERITED
 
   NS_DECL_NSIFRAMELOADEROWNER
   NS_DECL_NSIDOMMOZBROWSERFRAME
   NS_DECL_NSIMOZBROWSERFRAME
 
+  NS_DECLARE_STATIC_IID_ACCESSOR(NS_GENERICHTMLFRAMEELEMENT_IID)
+
   // nsIContent
   virtual bool IsHTMLFocusable(bool aWithMouse, bool *aIsFocusable, int32_t *aTabIndex) 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 DestroyContent() override;
@@ -84,38 +90,46 @@ public:
    * enum value.  scrolling="no" (and its synonyms) maps to
    * nsIScrollable::Scrollbar_Never, and anything else (including nullptr) maps
    * to nsIScrollable::Scrollbar_Auto.
    * @param aValue the attribute value to map or nullptr
    * @return nsIScrollable::Scrollbar_Never or nsIScrollable::Scrollbar_Auto
    */
   static int32_t MapScrollingAttribute(const nsAttrValue* aValue);
 
+  nsIPrincipal* GetSrcTriggeringPrincipal() const
+  {
+    return mSrcTriggeringPrincipal;
+  }
+
 protected:
   virtual ~nsGenericHTMLFrameElement();
 
   // This doesn't really ensure a frame loader in all cases, only when
   // it makes sense.
   void EnsureFrameLoader();
   nsresult LoadSrc();
   nsIDocument* GetContentDocument(nsIPrincipal& aSubjectPrincipal);
   nsresult GetContentDocument(nsIDOMDocument** aContentDocument);
   already_AddRefed<nsPIDOMWindowOuter> GetContentWindow();
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult OnAttrSetButNotChanged(int32_t aNamespaceID, nsAtom* aName,
                                           const nsAttrValueOrString& aValue,
                                           bool aNotify) override;
 
   RefPtr<nsFrameLoader> mFrameLoader;
   nsCOMPtr<nsPIDOMWindowOuter> mOpenerWindow;
 
+  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+
   /**
    * True when the element is created by the parser using the
    * NS_FROM_PARSER_NETWORK flag.
    * If the element is modified, it may lose the flag.
    */
   bool mNetworkCreated;
 
   bool mIsPrerendered;
@@ -136,12 +150,17 @@ private:
    * It will be called whether the value is being set or unset.
    *
    * @param aNamespaceID the namespace of the attr being set
    * @param aName the localname of the attribute being set
    * @param aValue the value being set or null if the value is being unset
    * @param aNotify Whether we plan to notify document observers.
    */
   void AfterMaybeChangeAttr(int32_t aNamespaceID, nsAtom* aName,
-                            const nsAttrValueOrString* aValue, bool aNotify);
+                            const nsAttrValueOrString* aValue,
+                            nsIPrincipal* aMaybeScriptedPrincipal,
+                            bool aNotify);
 };
 
+NS_DEFINE_STATIC_IID_ACCESSOR(nsGenericHTMLFrameElement,
+                              NS_GENERICHTMLFRAMEELEMENT_IID)
+
 #endif // nsGenericHTMLFrameElement_h
--- a/dom/interfaces/html/moz.build
+++ b/dom/interfaces/html/moz.build
@@ -11,17 +11,16 @@ XPIDL_SOURCES += [
     'nsIDOMHTMLBaseElement.idl',
     'nsIDOMHTMLCollection.idl',
     'nsIDOMHTMLDocument.idl',
     'nsIDOMHTMLElement.idl',
     'nsIDOMHTMLFormElement.idl',
     'nsIDOMHTMLHtmlElement.idl',
     'nsIDOMHTMLImageElement.idl',
     'nsIDOMHTMLInputElement.idl',
-    'nsIDOMHTMLLinkElement.idl',
     'nsIDOMHTMLMediaElement.idl',
     'nsIDOMHTMLMenuItemElement.idl',
     'nsIDOMHTMLOptionElement.idl',
     'nsIDOMHTMLOptionsCollection.idl',
     'nsIDOMHTMLScriptElement.idl',
     'nsIDOMHTMLSelectElement.idl',
     'nsIDOMHTMLSourceElement.idl',
     'nsIDOMHTMLTextAreaElement.idl',
deleted file mode 100644
--- a/dom/interfaces/html/nsIDOMHTMLLinkElement.idl
+++ /dev/null
@@ -1,32 +0,0 @@
-/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "nsIDOMHTMLElement.idl"
-
-/**
- * The nsIDOMHTMLLinkElement interface is the interface to a [X]HTML
- * link element.
- *
- * This interface is trying to follow the DOM Level 2 HTML specification:
- * http://www.w3.org/TR/DOM-Level-2-HTML/
- *
- * with changes from the work-in-progress WHATWG HTML specification:
- * http://www.whatwg.org/specs/web-apps/current-work/
- */
-
-[uuid(ee50b7ab-0015-4fbe-89e0-e3feacd4ffde)]
-interface nsIDOMHTMLLinkElement : nsISupports
-{
-           [binaryname(MozDisabled)]
-           attribute boolean          disabled;
-           attribute DOMString        charset;
-           attribute DOMString        href;
-           attribute DOMString        hreflang;
-           attribute DOMString        media;
-           attribute DOMString        rel;
-           attribute DOMString        rev;
-           attribute DOMString        target;
-           attribute DOMString        type;
-};
--- a/dom/ipc/CoalescedMouseData.h
+++ b/dom/ipc/CoalescedMouseData.h
@@ -12,16 +12,26 @@
 #include "nsRefreshDriver.h"
 
 namespace mozilla {
 namespace dom {
 
 class CoalescedMouseData final : public CoalescedInputData<WidgetMouseEvent>
 {
 public:
+  CoalescedMouseData()
+  {
+    MOZ_COUNT_CTOR(mozilla::dom::CoalescedMouseData);
+  }
+
+  ~CoalescedMouseData()
+  {
+    MOZ_COUNT_DTOR(mozilla::dom::CoalescedMouseData);
+  }
+
   void Coalesce(const WidgetMouseEvent& aEvent,
                 const ScrollableLayerGuid& aGuid,
                 const uint64_t& aInputBlockId);
 
   bool CanCoalesce(const WidgetMouseEvent& aEvent,
                    const ScrollableLayerGuid& aGuid,
                    const uint64_t& aInputBlockId);
 };
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1589,47 +1589,59 @@ TabChild::RecvMouseEvent(const nsString&
                                          nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN,
                                          0 /* Use the default value here. */);
   return IPC_OK();
 }
 
 void
 TabChild::MaybeDispatchCoalescedMouseMoveEvents()
 {
-  if (!mCoalesceMouseMoveEvents || mCoalescedMouseData.IsEmpty()) {
+  if (!mCoalesceMouseMoveEvents) {
     return;
   }
-  const WidgetMouseEvent* event = mCoalescedMouseData.GetCoalescedEvent();
-  MOZ_ASSERT(event);
-  // Dispatch the coalesced mousemove event. Using RecvRealMouseButtonEvent to
-  // bypass the coalesce handling in RecvRealMouseMoveEvent.
-  RecvRealMouseButtonEvent(*event,
-                           mCoalescedMouseData.GetScrollableLayerGuid(),
-                           mCoalescedMouseData.GetInputBlockId());
+  for (auto iter = mCoalescedMouseData.Iter(); !iter.Done(); iter.Next()) {
+    CoalescedMouseData* data = iter.UserData();
+    if (!data || data->IsEmpty()) {
+      continue;
+    }
+    const WidgetMouseEvent* event = data->GetCoalescedEvent();
+    MOZ_ASSERT(event);
+    // Dispatch the coalesced mousemove event. Using RecvRealMouseButtonEvent to
+    // bypass the coalesce handling in RecvRealMouseMoveEvent.
+    RecvRealMouseButtonEvent(*event,
+                             data->GetScrollableLayerGuid(),
+                             data->GetInputBlockId());
+    data->Reset();
+  }
   if (mCoalescedMouseEventFlusher) {
-    mCoalescedMouseData.Reset();
     mCoalescedMouseEventFlusher->RemoveObserver();
   }
 }
 
 mozilla::ipc::IPCResult
 TabChild::RecvRealMouseMoveEvent(const WidgetMouseEvent& aEvent,
                                  const ScrollableLayerGuid& aGuid,
                                  const uint64_t& aInputBlockId)
 {
   if (mCoalesceMouseMoveEvents && mCoalescedMouseEventFlusher) {
-    if (mCoalescedMouseData.CanCoalesce(aEvent, aGuid, aInputBlockId)) {
-      mCoalescedMouseData.Coalesce(aEvent, aGuid, aInputBlockId);
+    CoalescedMouseData* data = nullptr;
+    mCoalescedMouseData.Get(aEvent.pointerId, &data);
+    if (!data) {
+      data = new CoalescedMouseData();
+      mCoalescedMouseData.Put(aEvent.pointerId, data);
+    }
+    if (data->CanCoalesce(aEvent, aGuid, aInputBlockId)) {
+      data->Coalesce(aEvent, aGuid, aInputBlockId);
       mCoalescedMouseEventFlusher->StartObserver();
       return IPC_OK();
     }
     // Can't coalesce current mousemove event. Dispatch the coalesced mousemove
     // event and coalesce the current one.
     MaybeDispatchCoalescedMouseMoveEvents();
-    mCoalescedMouseData.Coalesce(aEvent, aGuid, aInputBlockId);
+    data->Coalesce(aEvent, aGuid, aInputBlockId);
     mCoalescedMouseEventFlusher->StartObserver();
   } else if (!RecvRealMouseButtonEvent(aEvent, aGuid, aInputBlockId)) {
     return IPC_FAIL_NO_REASON(this);
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
@@ -1663,16 +1675,21 @@ mozilla::ipc::IPCResult
 TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
                                    const ScrollableLayerGuid& aGuid,
                                    const uint64_t& aInputBlockId)
 {
   if (aEvent.mMessage != eMouseMove) {
     // Flush the coalesced mousemove event before dispatching other mouse
     // events.
     MaybeDispatchCoalescedMouseMoveEvents();
+    if (aEvent.mMessage == eMouseEnterIntoWidget) {
+      mCoalescedMouseData.Put(aEvent.pointerId, new CoalescedMouseData());
+    } else if (aEvent.mMessage == eMouseExitFromWidget) {
+      mCoalescedMouseData.Remove(aEvent.pointerId);
+    }
   }
   // Mouse events like eMouseEnterIntoWidget, that are created in the parent
   // process EventStateManager code, have an input block id which they get from
   // the InputAPZContext in the parent process stack. However, they did not
   // actually go through the APZ code and so their mHandledByAPZ flag is false.
   // Since thos events didn't go through APZ, we don't need to send
   // notifications for them.
   bool pendingLayerization = false;
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -940,17 +940,17 @@ private:
   // be skipped to not flood child process.
   mozilla::TimeStamp mRepeatedKeyEventTime;
 
   // Similar to mRepeatedKeyEventTime, store the end time (from parent process)
   // of handling the last repeated wheel event so that in case event handling
   // takes time, some repeated events can be skipped to not flood child process.
   mozilla::TimeStamp mLastWheelProcessedTimeFromParent;
   mozilla::TimeDuration mLastWheelProcessingDuration;
-  CoalescedMouseData mCoalescedMouseData;
+  nsClassHashtable<nsUint32HashKey, CoalescedMouseData> mCoalescedMouseData;
   CoalescedWheelData mCoalescedWheelData;
   RefPtr<CoalescedMouseMoveFlusher> mCoalescedMouseEventFlusher;
 
   RefPtr<layers::IAPZCTreeManager> mApzcTreeManager;
 
   // The most recently seen layer observer epoch in RecvSetDocShellIsActive.
   uint64_t mLayerObserverEpoch;
 
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -52,25 +52,16 @@ FormValidationDateTimeRangeOverflow=Plea
 FormValidationNumberRangeUnderflow=Please select a value that is no less than %S.
 # LOCALIZATION NOTE (FormValidationDateTimeRangeUnderflow): %S is a date or a time.
 FormValidationDateTimeRangeUnderflow=Please select a value that is no earlier than %S.
 # LOCALIZATION NOTE (FormValidationStepMismatch): both %S can be a number, a date or a time.
 FormValidationStepMismatch=Please select a valid value. The two nearest valid values are %S and %S.
 # LOCALIZATION NOTE (FormValidationStepMismatchOneValue): %S can be a number, a date or a time. This is called instead of FormValidationStepMismatch when the second value is the same as the first.
 FormValidationStepMismatchOneValue=Please select a valid value. The nearest valid value is %S.
 FormValidationBadInputNumber=Please enter a number.
-GetAttributeNodeWarning=Use of getAttributeNode() is deprecated. Use getAttribute() instead.
-SetAttributeNodeWarning=Use of setAttributeNode() is deprecated. Use setAttribute() instead.
-GetAttributeNodeNSWarning=Use of getAttributeNodeNS() is deprecated. Use getAttributeNS() instead.
-SetAttributeNodeNSWarning=Use of setAttributeNodeNS() is deprecated. Use setAttributeNS() instead.
-RemoveAttributeNodeWarning=Use of removeAttributeNode() is deprecated. Use removeAttribute() instead.
-CreateAttributeWarning=Use of document.createAttribute() is deprecated. Use element.setAttribute() instead.
-CreateAttributeNSWarning=Use of document.createAttributeNS() is deprecated. Use element.setAttributeNS() instead.
-NodeValueWarning=Use of attributes’ nodeValue attribute is deprecated. Use value instead.
-TextContentWarning=Use of attributes’ textContent attribute is deprecated. Use value instead.
 EnablePrivilegeWarning=Use of enablePrivilege is deprecated.  Please use code that runs with the system principal (e.g. an extension) instead.
 FullscreenDeniedDisabled=Request for fullscreen was denied because Fullscreen API is disabled by user preference.
 FullscreenDeniedFocusedPlugin=Request for fullscreen was denied because a windowed plugin is focused.
 FullscreenDeniedHidden=Request for fullscreen was denied because the document is no longer visible.
 FullscreenDeniedContainerNotAllowed=Request for fullscreen was denied because at least one of the document’s containing elements is not an iframe or does not have an “allowfullscreen” attribute.
 FullscreenDeniedNotInputDriven=Request for fullscreen was denied because Element.requestFullscreen() was not called from inside a short running user-generated event handler.
 FullscreenDeniedNotHTMLSVGOrMathML=Request for fullscreen was denied because requesting element is not <svg>, <math>, or an HTML element.
 FullscreenDeniedNotInDocument=Request for fullscreen was denied because requesting element is no longer in its document.
--- a/dom/mathml/nsMathMLElement.cpp
+++ b/dom/mathml/nsMathMLElement.cpp
@@ -1080,17 +1080,19 @@ nsMathMLElement::GetHrefURI() const
 {
   nsCOMPtr<nsIURI> hrefURI;
   return IsLink(getter_AddRefs(hrefURI)) ? hrefURI.forget() : nullptr;
 }
 
 nsresult
 nsMathMLElement::AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   // It is important that this be done after the attribute is set/unset.
   // We will need the updated attribute value because notifying the document
   // that content states have changed will call IntrinsicState, which will try
   // to get updated information about the visitedness from Link.
   if (aName == nsGkAtoms::href &&
       (aNameSpaceID == kNameSpaceID_None ||
        aNameSpaceID == kNameSpaceID_XLink)) {
@@ -1098,16 +1100,16 @@ nsMathMLElement::AfterSetAttr(int32_t aN
       WarnDeprecated(u"xlink:href", u"href", OwnerDoc());
     }
     // Note: When unsetting href, there may still be another href since there
     // are 2 possible namespaces.
     Link::ResetLinkState(aNotify, aValue || Link::ElementHasHref());
   }
 
   return nsMathMLElementBase::AfterSetAttr(aNameSpaceID, aName, aValue,
-                                           aOldValue, aNotify);
+                                           aOldValue, aSubjectPrincipal, aNotify);
 }
 
 JSObject*
 nsMathMLElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return ElementBinding::Wrap(aCx, this, aGivenProto);
 }
--- a/dom/mathml/nsMathMLElement.h
+++ b/dom/mathml/nsMathMLElement.h
@@ -106,15 +106,16 @@ public:
 protected:
   virtual ~nsMathMLElement() {}
 
   virtual JSObject* WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
 private:
   bool mIncrementScriptLevel;
 };
 
 #endif // nsMathMLElement_h
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -828,17 +828,17 @@ skip-if = android_version == '17' # andr
 tags=msg
 [test_mediarecorder_fires_start_event_once_when_erroring.html]
 skip-if = android_version == '17' # android(bug 1232305)
 tags=msg
 [test_mediarecorder_getencodeddata.html]
 skip-if = android_version == '17' # android(bug 1232305)
 tags=msg
 [test_mediarecorder_pause_resume_video.html]
-skip-if = toolkit == 'android' # android(bug 1232305)
+skip-if = toolkit == 'android' || debug # android(bug 1232305), debug Bug 1403307
 [test_mediarecorder_playback_can_repeat.html]
 skip-if = android_version == '17' || android_version == '22' # android(bug 1232305, bug 1372457)
 tags=msg
 [test_mediarecorder_principals.html]
 skip-if = (os == 'linux' && bits == 64) || toolkit == 'android' # See bug 1266345, android(bug 1232305)
 tags=msg
 [test_mediarecorder_record_4ch_audiocontext.html]
 skip-if = android_version == '17' # android(bug 1232305)
--- a/dom/script/ScriptLoadRequest.h
+++ b/dom/script/ScriptLoadRequest.h
@@ -175,16 +175,17 @@ public:
 
   // Holds the SRI serialized hash and the script bytecode for non-inline
   // scripts.
   mozilla::Vector<uint8_t> mScriptBytecode;
   uint32_t mBytecodeOffset; // Offset of the bytecode in mScriptBytecode
 
   uint32_t mJSVersion;
   nsCOMPtr<nsIURI> mURI;
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   nsCOMPtr<nsIPrincipal> mOriginPrincipal;
   nsAutoCString mURL;     // Keep the URI's filename alive during off thread parsing.
   int32_t mLineNo;
   const mozilla::CORSMode mCORSMode;
   const mozilla::dom::SRIMetadata mIntegrity;
   mozilla::net::ReferrerPolicy mReferrerPolicy;
 
   // Holds the Cache information, which is used to register the bytecode
--- a/dom/script/ScriptLoader.cpp
+++ b/dom/script/ScriptLoader.cpp
@@ -746,16 +746,17 @@ ScriptLoader::StartFetchingModuleAndDepe
   MOZ_ASSERT(aURI);
 
   RefPtr<ModuleLoadRequest> childRequest =
     new ModuleLoadRequest(aRequest->mElement, aRequest->mJSVersion,
                             aRequest->mCORSMode, aRequest->mIntegrity, this);
 
   childRequest->mIsTopLevel = false;
   childRequest->mURI = aURI;
+  childRequest->mTriggeringPrincipal = aRequest->mTriggeringPrincipal;
   childRequest->mIsInline = false;
   childRequest->mReferrerPolicy = aRequest->mReferrerPolicy;
   childRequest->mParent = aRequest;
   aRequest->mImports.AppendElement(childRequest);
 
   if (LOG_ENABLED()) {
     nsAutoCString url1;
     aRequest->mURI->GetAsciiSpec(url1);
@@ -1014,25 +1015,27 @@ ScriptLoader::StartLoad(ScriptLoadReques
       securityFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN;
     } else if (aRequest->mCORSMode == CORS_USE_CREDENTIALS) {
       securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
     }
   }
   securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
 
   nsCOMPtr<nsIChannel> channel;
-  nsresult rv = NS_NewChannel(getter_AddRefs(channel),
-                              aRequest->mURI,
-                              context,
-                              securityFlags,
-                              contentPolicyType,
-                              loadGroup,
-                              prompter,
-                              nsIRequest::LOAD_NORMAL |
-                              nsIChannel::LOAD_CLASSIFY_URI);
+  nsresult rv = NS_NewChannelWithTriggeringPrincipal(
+      getter_AddRefs(channel),
+      aRequest->mURI,
+      context,
+      aRequest->mTriggeringPrincipal,
+      securityFlags,
+      contentPolicyType,
+      loadGroup,
+      prompter,
+      nsIRequest::LOAD_NORMAL |
+      nsIChannel::LOAD_CLASSIFY_URI);
 
   NS_ENSURE_SUCCESS(rv, rv);
 
   // To avoid decoding issues, the JSVersion is explicitly guarded here, and the
   // build-id is part of the JSBytecodeMimeType constant.
   aRequest->mCacheInfo = nullptr;
   nsCOMPtr<nsICacheInfoChannel> cic(do_QueryInterface(channel));
   if (cic && nsContentUtils::IsBytecodeCacheEnabled() &&
@@ -1367,19 +1370,25 @@ ScriptLoader::ProcessScriptElement(nsISc
           if (mDocument->GetDocumentURI()) {
             mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri);
           }
           SRICheck::IntegrityMetadata(integrity, sourceUri, mReporter,
                                       &sriMetadata);
         }
       }
 
+      nsCOMPtr<nsIPrincipal> principal = aElement->GetScriptURITriggeringPrincipal();
+      if (!principal) {
+        principal = scriptContent->NodePrincipal();
+      }
+
       request = CreateLoadRequest(scriptKind, aElement, version, ourCORSMode,
                                   sriMetadata);
       request->mURI = scriptURI;
+      request->mTriggeringPrincipal = Move(principal);
       request->mIsInline = false;
       request->mReferrerPolicy = ourRefPolicy;
       // keep request->mScriptFromHead to false so we don't treat non preloaded
       // scripts as blockers for full page load. See bug 792438.
 
       rv = StartLoad(request);
       if (NS_FAILED(rv)) {
         const char* message = "ScriptSourceLoadFailed";
@@ -1514,16 +1523,17 @@ ScriptLoader::ProcessScriptElement(nsISc
   }
 
   // Inline scripts ignore ther CORS mode and are always CORS_NONE
   request = CreateLoadRequest(scriptKind, aElement, version, CORS_NONE,
                               SRIMetadata()); // SRI doesn't apply
   request->mJSVersion = version;
   request->mIsInline = true;
   request->mURI = mDocument->GetDocumentURI();
+  request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mLineNo = aElement->GetScriptLineNumber();
   request->mProgress = ScriptLoadRequest::Progress::Loading_Source;
   request->mDataType = ScriptLoadRequest::DataType::Source;
   TRACE_FOR_TEST_BOOL(request->mElement, "scriptloader_load_source");
   CollectScriptTelemetry(nullptr, request);
 
   LOG(("ScriptLoadRequest (%p): Created request for inline script",
        request.get()));
@@ -3099,16 +3109,17 @@ ScriptLoader::PreloadURI(nsIURI* aURI, c
     }
     SRICheck::IntegrityMetadata(aIntegrity, sourceUri, mReporter, &sriMetadata);
   }
 
   RefPtr<ScriptLoadRequest> request =
     CreateLoadRequest(ScriptKind::Classic, nullptr, 0,
                       Element::StringToCORSMode(aCrossOrigin), sriMetadata);
   request->mURI = aURI;
+  request->mTriggeringPrincipal = mDocument->NodePrincipal();
   request->mIsInline = false;
   request->mReferrerPolicy = aReferrerPolicy;
   request->mScriptFromHead = aScriptFromHead;
   request->mPreloadAsAsync = aAsync;
   request->mPreloadAsDefer = aDefer;
 
   nsresult rv = StartLoad(request);
   if (NS_FAILED(rv)) {
--- a/dom/script/nsIScriptElement.h
+++ b/dom/script/nsIScriptElement.h
@@ -61,16 +61,22 @@ public:
    * this is assumed to be an inline script element.
    */
   nsIURI* GetScriptURI()
   {
     NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
     return mUri;
   }
 
+  nsIPrincipal* GetScriptURITriggeringPrincipal()
+  {
+    NS_PRECONDITION(mFrozen, "Not ready for this call yet!");
+    return mSrcTriggeringPrincipal;
+  }
+
   /**
    * Script source text for inline script elements.
    */
   virtual void GetScriptText(nsAString& text) = 0;
 
   virtual void GetScriptCharset(nsAString& charset) = 0;
 
   /**
@@ -317,16 +323,21 @@ protected:
   mozilla::dom::FromParser mParserCreated;
 
   /**
    * The effective src (or null if no src).
    */
   nsCOMPtr<nsIURI> mUri;
 
   /**
+   * The triggering principal for the src URL.
+   */
+  nsCOMPtr<nsIPrincipal> mSrcTriggeringPrincipal;
+
+  /**
    * The creator parser of a non-defer, non-async parser-inserted script.
    */
   nsWeakPtr mCreatorParser;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptElement, NS_ISCRIPTELEMENT_IID)
 
 #endif // nsIScriptElement_h___
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -330,20 +330,21 @@ EventStates
 SVGAElement::IntrinsicState() const
 {
   return Link::LinkState() | SVGAElementBase::IntrinsicState();
 }
 
 nsresult
 SVGAElement::SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                      nsAtom* aPrefix, const nsAString& aValue,
+                     nsIPrincipal* aSubjectPrincipal,
                      bool aNotify)
 {
   nsresult rv = SVGAElementBase::SetAttr(aNameSpaceID, aName, aPrefix,
-                                         aValue, aNotify);
+                                         aValue, aSubjectPrincipal, aNotify);
 
   // The ordering of the parent class's SetAttr call and Link::ResetLinkState
   // is important here!  The attribute is not set until SetAttr returns, and
   // we will need the updated attribute value because notifying the document
   // that content states have changed will call IntrinsicState, which will try
   // to get updated information about the visitedness from Link.
   if (aName == nsGkAtoms::href &&
       (aNameSpaceID == kNameSpaceID_XLink ||
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -51,23 +51,20 @@ public:
                               bool aNullParent = true) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
   virtual int32_t TabIndexDefault() override;
   virtual bool IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
   virtual EventStates IntrinsicState() const override;
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
-  }
+  using nsIContent::SetAttr;
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                            nsAtom* aPrefix, const nsAString& aValue,
+                           nsIPrincipal* aSubjectPrincipal,
                            bool aNotify) override;
   virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsAtom* aAttribute,
                              bool aNotify) override;
 
   // Link
   virtual bool ElementHasHref() const override;
 
   // WebIDL
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -279,21 +279,23 @@ SVGAnimationElement::ParseAttribute(int3
 
   return SVGAnimationElementBase::ParseAttribute(aNamespaceID, aAttribute,
                                                  aValue, aResult);
 }
 
 nsresult
 SVGAnimationElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
-                                  const nsAttrValue* aOldValue, bool aNotify)
+                                  const nsAttrValue* aOldValue,
+                                  nsIPrincipal* aSubjectPrincipal,
+                                  bool aNotify)
 {
   nsresult rv =
     SVGAnimationElementBase::AfterSetAttr(aNamespaceID, aName, aValue,
-                                          aOldValue, aNotify);
+                                          aOldValue, aSubjectPrincipal, aNotify);
 
   if (SVGTests::IsConditionalProcessingAttribute(aName)) {
     bool isDisabled = !SVGTests::PassesConditionalProcessingTests();
     if (mTimedElement.SetIsDisabled(isDisabled)) {
       AnimationNeedsResample();
     }
   }
 
--- a/dom/svg/SVGAnimationElement.h
+++ b/dom/svg/SVGAnimationElement.h
@@ -56,16 +56,17 @@ public:
   // Element specializations
   virtual bool ParseAttribute(int32_t aNamespaceID,
                                 nsAtom* aAttribute,
                                 const nsAString& aValue,
                                 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;
   bool GetAnimAttr(nsAtom* aAttName, nsAString& aResult) const;
   bool HasAnimAttr(nsAtom* aAttName) const;
   Element* GetTargetElementContent();
   virtual bool GetTargetAttributeName(int32_t* aNamespaceID,
                                       nsAtom** aLocalName) const;
--- a/dom/svg/SVGFEImageElement.cpp
+++ b/dom/svg/SVGFEImageElement.cpp
@@ -119,31 +119,35 @@ SVGFEImageElement::IsAttributeMapped(con
 
   return FindAttributeDependence(name, map) ||
     SVGFEImageElementBase::IsAttributeMapped(name);
 }
 
 nsresult
 SVGFEImageElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
-                                const nsAttrValue* aOldValue, bool aNotify)
+                                const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
+                                bool aNotify)
 {
   if (aName == nsGkAtoms::href &&
       (aNamespaceID == kNameSpaceID_XLink ||
        aNamespaceID == kNameSpaceID_None)) {
 
     if (aValue) {
       LoadSVGImage(true, aNotify);
     } else {
       CancelImageRequests(aNotify);
     }
   }
 
   return SVGFEImageElementBase::AfterSetAttr(aNamespaceID, aName,
-                                             aValue, aOldValue, aNotify);
+                                             aValue, aOldValue,
+                                             aSubjectPrincipal,
+                                             aNotify);
 }
 
 void
 SVGFEImageElement::MaybeLoadSVGImage()
 {
   if ((mStringAttributes[HREF].IsExplicitlySet() ||
        mStringAttributes[XLINK_HREF].IsExplicitlySet() ) &&
       (NS_FAILED(LoadSVGImage(false, true)) ||
--- a/dom/svg/SVGFEImageElement.h
+++ b/dom/svg/SVGFEImageElement.h
@@ -56,16 +56,17 @@ public:
   NS_IMETHOD_(bool) IsAttributeMapped(const nsAtom* aAttribute) const override;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
   virtual EventStates IntrinsicState() const override;
 
   NS_IMETHOD Notify(imgIRequest *aRequest, int32_t aType, const nsIntRect* aData) override;
--- a/dom/svg/SVGGeometryElement.cpp
+++ b/dom/svg/SVGGeometryElement.cpp
@@ -32,25 +32,29 @@ nsSVGElement::NumberAttributesInfo
 SVGGeometryElement::GetNumberInfo()
 {
   return NumberAttributesInfo(&mPathLength, &sNumberInfo, 1);
 }
 
 nsresult
 SVGGeometryElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                  const nsAttrValue* aValue,
-                                 const nsAttrValue* aOldValue, bool aNotify)
+                                 const nsAttrValue* aOldValue,
+                                 nsIPrincipal* aSubjectPrincipal,
+                                 bool aNotify)
 {
   if (mCachedPath &&
       aNamespaceID == kNameSpaceID_None &&
       AttributeDefinesGeometry(aName)) {
     mCachedPath = nullptr;
   }
   return SVGGeometryElementBase::AfterSetAttr(aNamespaceID, aName,
-                                              aValue, aOldValue, aNotify);
+                                              aValue, aOldValue,
+                                              aSubjectPrincipal,
+                                              aNotify);
 }
 
 bool
 SVGGeometryElement::AttributeDefinesGeometry(const nsAtom *aName)
 {
   if (aName == nsGkAtoms::pathLength) {
     return true;
   }
--- a/dom/svg/SVGGeometryElement.h
+++ b/dom/svg/SVGGeometryElement.h
@@ -49,16 +49,17 @@ protected:
   typedef mozilla::gfx::StrokeOptions StrokeOptions;
 
 public:
   explicit SVGGeometryElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
 
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
 
   /**
    * Causes this element to discard any Path object that GetOrBuildPath may
    * have cached.
    */
   virtual void ClearAnyCachedPath() override final {
     mCachedPath = nullptr;
--- a/dom/svg/SVGImageElement.cpp
+++ b/dom/svg/SVGImageElement.cpp
@@ -151,30 +151,33 @@ SVGImageElement::AsyncEventRunning(Async
 }
 
 //----------------------------------------------------------------------
 // nsIContent methods:
 
 nsresult
 SVGImageElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                               const nsAttrValue* aValue,
-                              const nsAttrValue* aOldValue, bool aNotify)
+                              const nsAttrValue* aOldValue,
+                              nsIPrincipal* aSubjectPrincipal,
+                              bool aNotify)
 {
   if (aName == nsGkAtoms::href &&
       (aNamespaceID == kNameSpaceID_None ||
        aNamespaceID == kNameSpaceID_XLink)) {
 
     if (aValue) {
       LoadSVGImage(true, aNotify);
     } else {
       CancelImageRequests(aNotify);
     }
   }
   return SVGImageElementBase::AfterSetAttr(aNamespaceID, aName,
-                                           aValue, aOldValue, aNotify);
+                                           aValue, aOldValue,
+                                           aSubjectPrincipal, aNotify);
 }
 
 void
 SVGImageElement::MaybeLoadSVGImage()
 {
   if ((mStringAttributes[HREF].IsExplicitlySet() ||
        mStringAttributes[XLINK_HREF].IsExplicitlySet()) &&
       (NS_FAILED(LoadSVGImage(false, true)) ||
--- a/dom/svg/SVGImageElement.h
+++ b/dom/svg/SVGImageElement.h
@@ -43,16 +43,17 @@ public:
 
   // EventTarget
   virtual void AsyncEventRunning(AsyncEventDispatcher* aEvent) override;
 
   // nsIContent interface
   virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                 const nsAttrValue* aValue,
                                 const nsAttrValue* aOldValue,
+                                nsIPrincipal* aSubjectPrincipal,
                                 bool aNotify) override;
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep, bool aNullParent) override;
 
   virtual EventStates IntrinsicState() const override;
 
--- a/dom/svg/SVGScriptElement.cpp
+++ b/dom/svg/SVGScriptElement.cpp
@@ -229,25 +229,28 @@ SVGScriptElement::BindToTree(nsIDocument
   }
 
   return NS_OK;
 }
 
 nsresult
 SVGScriptElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                const nsAttrValue* aValue,
-                               const nsAttrValue* aOldValue, bool aNotify)
+                               const nsAttrValue* aOldValue,
+                               nsIPrincipal* aSubjectPrincipal,
+                               bool aNotify)
 {
   if ((aNamespaceID == kNameSpaceID_XLink ||
        aNamespaceID == kNameSpaceID_None) &&
       aName == nsGkAtoms::href) {
     MaybeProcessScript();
   }
   return SVGScriptElementBase::AfterSetAttr(aNamespaceID, aName,
-                                            aValue, aOldValue, aNotify);
+                                            aValue, aOldValue,
+                                            aSubjectPrincipal, aNotify);
 }
 
 bool
 SVGScriptElement::ParseAttribute(int32_t aNamespaceID,
                                  nsAtom* aAttribute,
                                  const nsAString& aValue,
                                  nsAttrValue& aResult)
 {
--- a/dom/svg/SVGScriptElement.h
+++ b/dom/svg/SVGScriptElement.h
@@ -52,16 +52,17 @@ public:
 
   // nsIContent specializations:
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   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;
 
   virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult,
                          bool aPreallocateChildren) const override;
--- a/dom/svg/SVGStyleElement.cpp
+++ b/dom/svg/SVGStyleElement.cpp
@@ -87,20 +87,21 @@ SVGStyleElement::UnbindFromTree(bool aDe
   ShadowRoot* oldShadow = GetContainingShadow();
   SVGStyleElementBase::UnbindFromTree(aDeep, aNullParent);
   UpdateStyleSheetInternal(oldDoc, oldShadow);
 }
 
 nsresult
 SVGStyleElement::SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                          nsAtom* aPrefix, const nsAString& aValue,
+                         nsIPrincipal* aSubjectPrincipal,
                          bool aNotify)
 {
   nsresult rv = SVGStyleElementBase::SetAttr(aNameSpaceID, aName, aPrefix,
-                                             aValue, aNotify);
+                                             aValue, aSubjectPrincipal, aNotify);
   if (NS_SUCCEEDED(rv) && aNameSpaceID == kNameSpaceID_None) {
     if (aName == nsGkAtoms::title ||
         aName == nsGkAtoms::media ||
         aName == nsGkAtoms::type) {
       UpdateStyleSheetInternal(nullptr, nullptr, true);
     } else if (aName == nsGkAtoms::scoped &&
                OwnerDoc()->IsScopedStyleEnabled()) {
       UpdateStyleSheetScopedness(true);
@@ -251,19 +252,20 @@ SVGStyleElement::SetTitle(const nsAStrin
 {
   rv = SetAttr(kNameSpaceID_None, nsGkAtoms::title, aTitle, true);
 }
 
 //----------------------------------------------------------------------
 // nsStyleLinkElement methods
 
 already_AddRefed<nsIURI>
-SVGStyleElement::GetStyleSheetURL(bool* aIsInline)
+SVGStyleElement::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
 {
   *aIsInline = true;
+  *aTriggeringPrincipal = nullptr;
   return nullptr;
 }
 
 void
 SVGStyleElement::GetStyleSheetInfo(nsAString& aTitle,
                                    nsAString& aType,
                                    nsAString& aMedia,
                                    bool* aIsScoped,
--- a/dom/svg/SVGStyleElement.h
+++ b/dom/svg/SVGStyleElement.h
@@ -39,23 +39,20 @@ public:
                                            SVGStyleElementBase)
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
                               nsIContent* aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
-  nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
-                   const nsAString& aValue, bool aNotify)
-  {
-    return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
-  }
+  using nsIContent::SetAttr;
   virtual nsresult SetAttr(int32_t aNameSpaceID, nsAtom* aName,
                            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,
                               nsAttrValue& aResult) override;
 
@@ -85,17 +82,17 @@ protected:
   // NS_IMPL_ELEMENT_CLONE_WITH_INIT usable with this class. This should be
   // completely optimized away.
   inline nsresult Init()
   {
     return NS_OK;
   }
 
   // nsStyleLinkElement overrides
-  already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+  already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
 
   void GetStyleSheetInfo(nsAString& aTitle,
                          nsAString& aType,
                          nsAString& aMedia,
                          bool* aIsScoped,
                          bool* aIsAlternate) override;
   virtual CORSMode GetCORSMode() const override;
 
--- a/dom/svg/nsSVGElement.cpp
+++ b/dom/svg/nsSVGElement.cpp
@@ -296,17 +296,19 @@ nsSVGElement::BindToTree(nsIDocument* aD
   }
 
   return NS_OK;
 }
 
 nsresult
 nsSVGElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                            const nsAttrValue* aValue,
-                           const nsAttrValue* aOldValue, bool aNotify)
+                           const nsAttrValue* aOldValue,
+                           nsIPrincipal* aSubjectPrincipal,
+                           bool aNotify)
 {
   // We don't currently use nsMappedAttributes within SVG. If this changes, we
   // need to be very careful because some nsAttrValues used by SVG point to
   // member data of SVG elements and if an nsAttrValue outlives the SVG element
   // whose data it points to (by virtue of being stored in
   // mAttrsAndChildren->mMappedAttributes, meaning it's shared between
   // elements), the pointer will dangle. See bug 724680.
   MOZ_ASSERT(!mAttrsAndChildren.HasMappedAttrs(),
@@ -327,17 +329,17 @@ nsSVGElement::AfterSetAttr(int32_t aName
     MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
                "Expected string value for script body");
     nsresult rv = SetEventHandler(GetEventNameForAttr(aName),
                                   aValue->GetStringValue());
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return nsSVGElementBase::AfterSetAttr(aNamespaceID, aName, aValue, aOldValue,
-                                        aNotify);
+                                        aSubjectPrincipal, aNotify);
 }
 
 bool
 nsSVGElement::ParseAttribute(int32_t aNamespaceID,
                              nsAtom* aAttribute,
                              const nsAString& aValue,
                              nsAttrValue& aResult)
 {
@@ -1490,17 +1492,17 @@ nsSVGElement::DidChangeValue(nsAtom* aNa
   nsIDocument* document = GetComposedDoc();
   mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL,
                                kNotifyDocumentObservers);
   // XXX Really, the fourth argument to SetAttrAndNotify should be null if
   // aEmptyOrOldValue does not represent the actual previous value of the
   // attribute, but currently SVG elements do not even use the old attribute
   // value in |AfterSetAttr|, so this should be ok.
   SetAttrAndNotify(kNameSpaceID_None, aName, nullptr, &aEmptyOrOldValue,
-                   aNewValue, modType, hasListeners, kNotifyDocumentObservers,
+                   aNewValue, nullptr, modType, hasListeners, kNotifyDocumentObservers,
                    kCallAfterSetAttr, document, updateBatch);
 }
 
 void
 nsSVGElement::MaybeSerializeAttrBeforeRemoval(nsAtom* aName, bool aNotify)
 {
   if (!aNotify ||
       !nsContentUtils::HasMutationListeners(this,
--- a/dom/svg/nsSVGElement.h
+++ b/dom/svg/nsSVGElement.h
@@ -346,16 +346,17 @@ protected:
                                  bool aNotify) override final
   {
     return nsSVGElementBase::BeforeSetAttr(aNamespaceID, aName, aValue, aNotify);
   }
 #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;
   static nsresult ReportAttributeParseFailure(nsIDocument* aDocument,
                                               nsAtom* aAttribute,
                                               const nsAString& aValue);
 
   nsAttrValue WillChangeValue(nsAtom* aName);
--- a/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
+++ b/dom/webbrowserpersist/WebBrowserPersistLocalDocument.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebBrowserPersistLocalDocument.h"
 #include "WebBrowserPersistDocumentParent.h"
 
 #include "mozilla/dom/HTMLAnchorElement.h"
 #include "mozilla/dom/HTMLAreaElement.h"
 #include "mozilla/dom/HTMLInputElement.h"
+#include "mozilla/dom/HTMLLinkElement.h"
 #include "mozilla/dom/HTMLObjectElement.h"
 #include "mozilla/dom/HTMLSharedElement.h"
 #include "mozilla/dom/TabParent.h"
 #include "nsComponentManagerUtils.h"
 #include "nsContentUtils.h"
 #include "nsContentCID.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsFrameLoader.h"
@@ -22,17 +23,16 @@
 #include "nsIDOMAttr.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMHTMLBaseElement.h"
 #include "nsIDOMHTMLCollection.h"
 #include "nsIDOMHTMLDocument.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLMediaElement.h"
 #include "nsIDOMHTMLOptionElement.h"
 #include "nsIDOMHTMLScriptElement.h"
 #include "nsIDOMHTMLSourceElement.h"
 #include "nsIDOMHTMLTextAreaElement.h"
 #include "nsIDOMMozNamedAttrMap.h"
 #include "nsIDOMNode.h"
 #include "nsIDOMNodeFilter.h"
@@ -529,21 +529,21 @@ ResourceReader::OnWalkDOMNode(nsIDOMNode
     if (content->IsHTMLElement(nsGkAtoms::embed)) {
         return OnWalkAttribute(aNode, "src");
     }
 
     if (content->IsHTMLElement(nsGkAtoms::object)) {
         return OnWalkAttribute(aNode, "data");
     }
 
-    nsCOMPtr<nsIDOMHTMLLinkElement> nodeAsLink = do_QueryInterface(aNode);
-    if (nodeAsLink) {
+    if (auto nodeAsLink = dom::HTMLLinkElement::FromContent(content)) {
         // Test if the link has a rel value indicating it to be a stylesheet
         nsAutoString linkRel;
-        if (NS_SUCCEEDED(nodeAsLink->GetRel(linkRel)) && !linkRel.IsEmpty()) {
+        nodeAsLink->GetRel(linkRel);
+        if (!linkRel.IsEmpty()) {
             nsReadingIterator<char16_t> start;
             nsReadingIterator<char16_t> end;
             nsReadingIterator<char16_t> current;
 
             linkRel.BeginReading(start);
             linkRel.EndReading(end);
 
             // Walk through space delimited string looking for "stylesheet"
@@ -1064,18 +1064,17 @@ PersistNodeFixup::FixupNode(nsIDOMNode *
     if (content->IsHTMLElement(nsGkAtoms::object)) {
         rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             FixupAttribute(*aNodeOut, "data");
         }
         return rv;
     }
 
-    nsCOMPtr<nsIDOMHTMLLinkElement> nodeAsLink = do_QueryInterface(aNodeIn);
-    if (nodeAsLink) {
+    if (content->IsHTMLElement(nsGkAtoms::link)) {
         rv = GetNodeToFixup(aNodeIn, aNodeOut);
         if (NS_SUCCEEDED(rv) && *aNodeOut) {
             // First see if the link represents linked content
             rv = FixupAttribute(*aNodeOut, "href");
             if (NS_FAILED(rv)) {
                 // Perhaps this link is actually an anchor to related content
                 FixupAnchor(*aNodeOut);
             }
--- a/dom/webidl/AnonymousContent.webidl
+++ b/dom/webidl/AnonymousContent.webidl
@@ -37,17 +37,17 @@ interface AnonymousContent {
   [Throws]
   DOMString? getAttributeForElement(DOMString elementId,
                                     DOMString attributeName);
 
   /**
    * Set the value of an attribute of an element inside this custom anonymous
    * content.
    */
-  [Throws]
+  [NeedsSubjectPrincipal, Throws]
   void setAttributeForElement(DOMString elementId,
                               DOMString attributeName,
                               DOMString value);
 
   /**
    * Remove an attribute from an element inside this custom anonymous content.
    */
   [Throws]
--- a/dom/webidl/Attr.webidl
+++ b/dom/webidl/Attr.webidl
@@ -7,17 +7,17 @@
  * http://www.w3.org/TR/2012/WD-dom-20120105/
  *
  * Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
  * liability, trademark and document use rules apply.
  */
 
 interface Attr : Node {
   readonly attribute DOMString localName;
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString value;
 
   [Constant]
   readonly attribute DOMString name;
   [Constant]
   readonly attribute DOMString? namespaceURI;
   [Constant]
   readonly attribute DOMString? prefix;
--- a/dom/webidl/Element.webidl
+++ b/dom/webidl/Element.webidl
@@ -35,19 +35,19 @@ interface Element : Node {
   [SameObject]
   readonly attribute NamedNodeMap attributes;
   [Pure]
   sequence<DOMString> getAttributeNames();
   [Pure]
   DOMString? getAttribute(DOMString name);
   [Pure]
   DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
-  [CEReactions, Throws]
+  [CEReactions, NeedsSubjectPrincipal, Throws]
   void setAttribute(DOMString name, DOMString value);
-  [CEReactions, Throws]
+  [CEReactions, NeedsSubjectPrincipal, Throws]
   void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
   [CEReactions, Throws]
   void removeAttribute(DOMString name);
   [CEReactions, Throws]
   void removeAttributeNS(DOMString? namespace, DOMString localName);
   [Pure]
   boolean hasAttribute(DOMString name);
   [Pure]
--- a/dom/webidl/HTMLFrameElement.webidl
+++ b/dom/webidl/HTMLFrameElement.webidl
@@ -12,17 +12,17 @@
 
 // http://www.whatwg.org/specs/web-apps/current-work/#htmlframeelement
 [HTMLConstructor]
 interface HTMLFrameElement : HTMLElement {
            [CEReactions, SetterThrows]
            attribute DOMString name;
            [CEReactions, SetterThrows]
            attribute DOMString scrolling;
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
            [CEReactions, SetterThrows]
            attribute DOMString frameBorder;
            [CEReactions, SetterThrows]
            attribute DOMString longDesc;
            [CEReactions, SetterThrows]
            attribute boolean noResize;
   [NeedsSubjectPrincipal]
--- a/dom/webidl/HTMLIFrameElement.webidl
+++ b/dom/webidl/HTMLIFrameElement.webidl
@@ -8,17 +8,17 @@
  * http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 [HTMLConstructor]
 interface HTMLIFrameElement : HTMLElement {
-  [CEReactions, SetterThrows, Pure]
+  [CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
            attribute DOMString src;
   [CEReactions, SetterThrows, Pure]
            attribute DOMString srcdoc;
   [CEReactions, SetterThrows, Pure]
            attribute DOMString name;
   [PutForwards=value] readonly attribute DOMTokenList sandbox;
            // attribute boolean seamless;
   [CEReactions, SetterThrows, Pure]
--- a/dom/webidl/HTMLImageElement.webidl
+++ b/dom/webidl/HTMLImageElement.webidl
@@ -16,19 +16,19 @@ interface imgIRequest;
 interface URI;
 interface nsIStreamListener;
 
 [HTMLConstructor,
  NamedConstructor=Image(optional unsigned long width, optional unsigned long height)]
 interface HTMLImageElement : HTMLElement {
            [CEReactions, SetterThrows]
            attribute DOMString alt;
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString srcset;
            [CEReactions, SetterThrows]
            attribute DOMString? crossOrigin;
            [CEReactions, SetterThrows]
            attribute DOMString useMap;
            [CEReactions, SetterThrows]
            attribute DOMString referrerPolicy;
            [CEReactions, SetterThrows]
--- a/dom/webidl/HTMLInputElement.webidl
+++ b/dom/webidl/HTMLInputElement.webidl
@@ -76,17 +76,17 @@ interface HTMLInputElement : HTMLElement
   [CEReactions, Pure, SetterThrows]
            attribute DOMString placeholder;
   [CEReactions, Pure, SetterThrows]
            attribute boolean readOnly;
   [CEReactions, Pure, SetterThrows]
            attribute boolean required;
   [CEReactions, Pure, SetterThrows]
            attribute unsigned long size;
-  [CEReactions, Pure, SetterThrows]
+  [CEReactions, Pure, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
   [CEReactions, Pure, SetterThrows]
            attribute DOMString step;
   [CEReactions, Pure, SetterThrows]
            attribute DOMString type;
   [CEReactions, Pure, SetterThrows]
            attribute DOMString defaultValue;
   [CEReactions, Pure, TreatNullAs=EmptyString, SetterThrows, NeedsCallerType]
--- a/dom/webidl/HTMLLinkElement.webidl
+++ b/dom/webidl/HTMLLinkElement.webidl
@@ -11,17 +11,17 @@
  * and create derivative works of this document.
  */
 
 // http://www.whatwg.org/specs/web-apps/current-work/#the-link-element
 [HTMLConstructor]
 interface HTMLLinkElement : HTMLElement {
   [Pure]
            attribute boolean disabled;
-  [CEReactions, SetterThrows, Pure]
+  [CEReactions, NeedsSubjectPrincipal, SetterThrows, Pure]
            attribute DOMString href;
   [CEReactions, SetterThrows, Pure]
            attribute DOMString? crossOrigin;
   [CEReactions, SetterThrows, Pure]
            attribute DOMString rel;
   [PutForwards=value]
   readonly attribute DOMTokenList relList;
   [CEReactions, SetterThrows, Pure]
--- a/dom/webidl/HTMLMediaElement.webidl
+++ b/dom/webidl/HTMLMediaElement.webidl
@@ -12,17 +12,17 @@
  */
 
 interface HTMLMediaElement : HTMLElement {
 
   // error state
   readonly attribute MediaError? error;
 
   // network state
-  [CEReactions, SetterThrows]
+  [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
   readonly attribute DOMString currentSrc;
 
   [CEReactions, SetterThrows]
            attribute DOMString? crossOrigin;
   const unsigned short NETWORK_EMPTY = 0;
   const unsigned short NETWORK_IDLE = 1;
   const unsigned short NETWORK_LOADING = 2;
@@ -211,9 +211,9 @@ partial interface HTMLMediaElement {
  *   drawImage().
  */
 partial interface HTMLMediaElement {
   [Pref="media.test.video-suspend"]
   void setVisible(boolean aVisible);
 
   [Pref="media.test.video-suspend"]
   boolean hasSuspendTaint();
-};
\ No newline at end of file
+};
--- a/dom/webidl/HTMLScriptElement.webidl
+++ b/dom/webidl/HTMLScriptElement.webidl
@@ -5,17 +5,17 @@
  *
  * The origin of this IDL file is
  * http://www.whatwg.org/specs/web-apps/current-work/#the-script-element
  * http://www.whatwg.org/specs/web-apps/current-work/#other-elements,-attributes-and-apis
  */
 
 [HTMLConstructor]
 interface HTMLScriptElement : HTMLElement {
-  [CEReactions, SetterThrows]
+  [CEReactions, NeedsSubjectPrincipal, SetterThrows]
   attribute DOMString src;
   [CEReactions, SetterThrows]
   attribute DOMString type;
   [CEReactions, SetterThrows, Pref="dom.moduleScripts.enabled"]
   attribute boolean noModule;
   [CEReactions, SetterThrows]
   attribute DOMString charset;
   [CEReactions, SetterThrows]
--- a/dom/webidl/HTMLSourceElement.webidl
+++ b/dom/webidl/HTMLSourceElement.webidl
@@ -8,22 +8,22 @@
  *
  * © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
  * Opera Software ASA. You are granted a license to use, reproduce
  * and create derivative works of this document.
  */
 
 [HTMLConstructor]
 interface HTMLSourceElement : HTMLElement {
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString src;
            [CEReactions, SetterThrows]
            attribute DOMString type;
 };
 
 partial interface HTMLSourceElement {
-           [CEReactions, SetterThrows]
+           [CEReactions, NeedsSubjectPrincipal, SetterThrows]
            attribute DOMString srcset;
            [CEReactions, SetterThrows]
            attribute DOMString sizes;
            [CEReactions, SetterThrows]
            attribute DOMString media;
 };
--- a/dom/xml/XMLStylesheetProcessingInstruction.cpp
+++ b/dom/xml/XMLStylesheetProcessingInstruction.cpp
@@ -95,19 +95,20 @@ XMLStylesheetProcessingInstruction::GetC
 
 /* virtual */ void
 XMLStylesheetProcessingInstruction::OverrideBaseURI(nsIURI* aNewBaseURI)
 {
   mOverriddenBaseURI = aNewBaseURI;
 }
 
 already_AddRefed<nsIURI>
-XMLStylesheetProcessingInstruction::GetStyleSheetURL(bool* aIsInline)
+XMLStylesheetProcessingInstruction::GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal)
 {
   *aIsInline = false;
+  *aTriggeringPrincipal = nullptr;
 
   nsAutoString href;
   if (!GetAttrValue(nsGkAtoms::href, href)) {
     return nullptr;
   }
 
   nsIURI *baseURL;
   nsIDocument *document = OwnerDoc();
--- a/dom/xml/XMLStylesheetProcessingInstruction.h
+++ b/dom/xml/XMLStylesheetProcessingInstruction.h
@@ -72,17 +72,17 @@ public:
   }
   using ProcessingInstruction::SetData; // Prevent hiding overloaded virtual function.
 
 protected:
   virtual ~XMLStylesheetProcessingInstruction();
 
   nsCOMPtr<nsIURI> mOverriddenBaseURI;
 
-  already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline) override;
+  already_AddRefed<nsIURI> GetStyleSheetURL(bool* aIsInline, nsIPrincipal** aTriggeringPrincipal) override;
   void GetStyleSheetInfo(nsAString& aTitle,
                          nsAString& aType,
                          nsAString& aMedia,
                          bool* aIsScoped,
                          bool* aIsAlternate) override;
   virtual nsGenericDOMDataNode* CloneDataNode(mozilla::dom::NodeInfo *aNodeInfo,
                                               bool aCloneText) const override;
 };
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -1025,17 +1025,19 @@ nsXULElement::BeforeSetAttr(int32_t aNam
 
     return nsStyledElement::BeforeSetAttr(aNamespaceID, aName,
                                           aValue, aNotify);
 }
 
 nsresult
 nsXULElement::AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                            const nsAttrValue* aValue,
-                           const nsAttrValue* aOldValue, bool aNotify)
+                           const nsAttrValue* aOldValue,
+                           nsIPrincipal* aSubjectPrincipal,
+                           bool aNotify)
 {
     if (aNamespaceID == kNameSpaceID_None) {
         if (aValue) {
             // Add popup and event listeners. We can't call AddListenerFor since
             // the attribute isn't set yet.
             MaybeAddPopupListener(aName);
             if (nsContentUtils::IsEventAttributeName(aName, EventNameType_XUL)) {
                 if (aValue->Type() == nsAttrValue::eString) {
@@ -1146,17 +1148,17 @@ nsXULElement::AfterSetAttr(int32_t aName
             }
         }
 
         // XXX need to check if they're changing an event handler: if
         // so, then we need to unhook the old one.  Or something.
     }
 
     return nsStyledElement::AfterSetAttr(aNamespaceID, aName,
-                                         aValue, aOldValue, aNotify);
+                                         aValue, aOldValue, aSubjectPrincipal, aNotify);
 }
 
 bool
 nsXULElement::ParseAttribute(int32_t aNamespaceID,
                              nsAtom* aAttribute,
                              const nsAString& aValue,
                              nsAttrValue& aResult)
 {
--- a/dom/xul/nsXULElement.h
+++ b/dom/xul/nsXULElement.h
@@ -739,16 +739,17 @@ protected:
     nsresult MakeHeavyweight(nsXULPrototypeElement* aPrototype);
 
     virtual nsresult BeforeSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                    const nsAttrValueOrString* aValue,
                                    bool aNotify) override;
     virtual nsresult AfterSetAttr(int32_t aNamespaceID, nsAtom* aName,
                                   const nsAttrValue* aValue,
                                   const nsAttrValue* aOldValue,
+                                  nsIPrincipal* aSubjectPrincipal,
                                   bool aNotify) override;
 
     virtual void UpdateEditableState(bool aNotify) override;
 
     virtual bool ParseAttribute(int32_t aNamespaceID,
                                   nsAtom* aAttribute,
                                   const nsAString& aValue,
                                   nsAttrValue& aResult) override;
--- a/editor/libeditor/HTMLEditorDataTransfer.cpp
+++ b/editor/libeditor/HTMLEditorDataTransfer.cpp
@@ -36,17 +36,16 @@
 #include "nsIContent.h"
 #include "nsIContentFilter.h"
 #include "nsIDOMComment.h"
 #include "nsIDOMDocument.h"
 #include "nsIDOMDocumentFragment.h"
 #include "nsIDOMElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIDOMHTMLInputElement.h"
-#include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLScriptElement.h"
 #include "nsIDOMNode.h"
 #include "nsIDocument.h"
 #include "nsIEditRules.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
 #include "nsIMIMEService.h"
 #include "nsNameSpaceManager.h"
--- a/gfx/thebes/gfxUserFontSet.h
+++ b/gfx/thebes/gfxUserFontSet.h
@@ -398,21 +398,22 @@ public:
 
             explicit Entry(KeyTypePointer aKey)
                 : mURI(aKey->mURI),
                   mPrincipal(aKey->mPrincipal),
                   mFontEntry(aKey->mFontEntry),
                   mPrivate(aKey->mPrivate)
             { }
 
-            Entry(const Entry& aOther)
-                : mURI(aOther.mURI),
-                  mPrincipal(aOther.mPrincipal),
-                  mFontEntry(aOther.mFontEntry),
-                  mPrivate(aOther.mPrivate)
+            Entry(Entry&& aOther)
+                : mAllowedFontSets(mozilla::Move(aOther.mAllowedFontSets)),
+                  mURI(mozilla::Move(aOther.mURI)),
+                  mPrincipal(mozilla::Move(aOther.mPrincipal)),
+                  mFontEntry(mozilla::Move(aOther.mFontEntry)),
+                  mPrivate(mozilla::Move(aOther.mPrivate))
             { }
 
             ~Entry() { }
 
             bool KeyEquals(const KeyTypePointer aKey) const;
 
             static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
 
--- a/image/imgLoader.cpp
+++ b/image/imgLoader.cpp
@@ -565,17 +565,17 @@ ShouldRevalidateEntry(imgCacheEntry* aEn
 
   return bValidateEntry;
 }
 
 /* Call content policies on cached images that went through a redirect */
 static bool
 ShouldLoadCachedImage(imgRequest* aImgRequest,
                       nsISupports* aLoadingContext,
-                      nsIPrincipal* aLoadingPrincipal,
+                      nsIPrincipal* aTriggeringPrincipal,
                       nsContentPolicyType aPolicyType)
 {
   /* Call content policies on cached images - Bug 1082837
    * Cached images are keyed off of the first uri in a redirect chain.
    * Hence content policies don't get a chance to test the intermediate hops
    * or the final desitnation.  Here we test the final destination using
    * mCurrentURI off of the imgRequest and passing it into content policies.
    * For Mixed Content Blocker, we do an additional check to determine if any
@@ -585,17 +585,17 @@ ShouldLoadCachedImage(imgRequest* aImgRe
   bool insecureRedirect = aImgRequest->HadInsecureRedirect();
   nsCOMPtr<nsIURI> contentLocation;
   aImgRequest->GetCurrentURI(getter_AddRefs(contentLocation));
   nsresult rv;
 
   int16_t decision = nsIContentPolicy::REJECT_REQUEST;
   rv = NS_CheckContentLoadPolicy(aPolicyType,
                                  contentLocation,
-                                 aLoadingPrincipal,
+                                 aTriggeringPrincipal,
                                  aLoadingContext,
                                  EmptyCString(), //mime guess
                                  nullptr, //aExtra
                                  &decision,
                                  nsContentUtils::GetContentPolicy());
   if (NS_FAILED(rv) || !NS_CP_ACCEPTED(decision)) {
     return false;
   }
@@ -611,34 +611,34 @@ ShouldLoadCachedImage(imgRequest* aImgRe
     nsCOMPtr<nsIDocShell> docShell = NS_CP_GetDocShellFromContext(aLoadingContext);
     if (docShell) {
       nsIDocument* document = docShell->GetDocument();
       if (document && document->GetUpgradeInsecureRequests(false)) {
         return false;
       }
     }
 
-    if (!nsContentUtils::IsSystemPrincipal(aLoadingPrincipal)) {
-      // Set the requestingLocation from the aLoadingPrincipal.
+    if (!nsContentUtils::IsSystemPrincipal(aTriggeringPrincipal)) {
+      // Set the requestingLocation from the aTriggeringPrincipal.
       nsCOMPtr<nsIURI> requestingLocation;
-      if (aLoadingPrincipal) {
-        rv = aLoadingPrincipal->GetURI(getter_AddRefs(requestingLocation));
+      if (aTriggeringPrincipal) {
+        rv = aTriggeringPrincipal->GetURI(getter_AddRefs(requestingLocation));
         NS_ENSURE_SUCCESS(rv, false);
       }
 
       // reset the decision for mixed content blocker check
       decision = nsIContentPolicy::REJECT_REQUEST;
       rv = nsMixedContentBlocker::ShouldLoad(insecureRedirect,
                                              aPolicyType,
                                              contentLocation,
                                              requestingLocation,
                                              aLoadingContext,
                                              EmptyCString(), //mime guess
                                              nullptr,
-                                             aLoadingPrincipal,
+                                             aTriggeringPrincipal,
                                              &decision);
       if (NS_FAILED(rv) || !NS_CP_ACCEPTED(decision)) {
         return false;
       }
     }
   }
 
   bool sendPriming = false;
@@ -658,17 +658,17 @@ ShouldLoadCachedImage(imgRequest* aImgRe
 }
 
 // Returns true if this request is compatible with the given CORS mode on the
 // given loading principal, and false if the request may not be reused due
 // to CORS.  Also checks the Referrer Policy, since requests with different
 // referrers/policies may generate different responses.
 static bool
 ValidateSecurityInfo(imgRequest* request, bool forcePrincipalCheck,
-                     int32_t corsmode, nsIPrincipal* loadingPrincipal,
+                     int32_t corsmode, nsIPrincipal* triggeringPrincipal,
                      nsISupports* aCX, nsContentPolicyType aPolicyType,
                      ReferrerPolicy referrerPolicy)
 {
   // If the entry's Referrer Policy doesn't match, we can't use this request.
   // XXX: this will return false if an image has different referrer attributes,
   // i.e. we currently don't use the cached image but reload the image with
   // the new referrer policy bug 1174921
   if (referrerPolicy != request->GetReferrerPolicy()) {
@@ -677,56 +677,56 @@ ValidateSecurityInfo(imgRequest* request
 
   // If the entry's CORS mode doesn't match, or the CORS mode matches but the
   // document principal isn't the same, we can't use this request.
   if (request->GetCORSMode() != corsmode) {
     return false;
   }
   if (request->GetCORSMode() != imgIRequest::CORS_NONE ||
       forcePrincipalCheck) {
-    nsCOMPtr<nsIPrincipal> otherprincipal = request->GetLoadingPrincipal();
+    nsCOMPtr<nsIPrincipal> otherprincipal = request->GetTriggeringPrincipal();
 
     // If we previously had a principal, but we don't now, we can't use this
     // request.
-    if (otherprincipal && !loadingPrincipal) {
+    if (otherprincipal && !triggeringPrincipal) {
       return false;
     }
 
-    if (otherprincipal && loadingPrincipal) {
+    if (otherprincipal && triggeringPrincipal) {
       bool equals = false;
-      otherprincipal->Equals(loadingPrincipal, &equals);
+      otherprincipal->Equals(triggeringPrincipal, &equals);
       if (!equals) {
         return false;
       }
     }
   }
 
   // Content Policy Check on Cached Images
-  return ShouldLoadCachedImage(request, aCX, loadingPrincipal, aPolicyType);
+  return ShouldLoadCachedImage(request, aCX, triggeringPrincipal, aPolicyType);
 }
 
 static nsresult
 NewImageChannel(nsIChannel** aResult,
                 // If aForcePrincipalCheckForCacheEntry is true, then we will
                 // force a principal check even when not using CORS before
                 // assuming we have a cache hit on a cache entry that we
                 // create for this channel.  This is an out param that should
                 // be set to true if this channel ends up depending on
-                // aLoadingPrincipal and false otherwise.
+                // aTriggeringPrincipal and false otherwise.
                 bool* aForcePrincipalCheckForCacheEntry,
                 nsIURI* aURI,
                 nsIURI* aInitialDocumentURI,
                 int32_t aCORSMode,
                 nsIURI* aReferringURI,
                 ReferrerPolicy aReferrerPolicy,
                 nsILoadGroup* aLoadGroup,
                 const nsCString& aAcceptHeader,
                 nsLoadFlags aLoadFlags,
                 nsContentPolicyType aPolicyType,
-                nsIPrincipal* aLoadingPrincipal,
+                nsIPrincipal* aTriggeringPrincipal,
                 nsISupports* aRequestingContext,
                 bool aRespectPrivacy)
 {
   MOZ_ASSERT(aResult);
 
   nsresult rv;
   nsCOMPtr<nsIHttpChannel> newHttpChannel;
 
@@ -763,46 +763,46 @@ NewImageChannel(nsIChannel** aResult,
     securityFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE;
   }
   securityFlags |= nsILoadInfo::SEC_ALLOW_CHROME;
 
   // Note we are calling NS_NewChannelWithTriggeringPrincipal() here with a
   // node and a principal. This is for things like background images that are
   // specified by user stylesheets, where the document is being styled, but
   // the principal is that of the user stylesheet.
-  if (requestingNode && aLoadingPrincipal) {
+  if (requestingNode && aTriggeringPrincipal) {
     rv = NS_NewChannelWithTriggeringPrincipal(aResult,
                                               aURI,
                                               requestingNode,
-                                              aLoadingPrincipal,
+                                              aTriggeringPrincipal,
                                               securityFlags,
                                               aPolicyType,
                                               nullptr,   // loadGroup
                                               callbacks,
                                               aLoadFlags);
 
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     if (aPolicyType == nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
       // If this is a favicon loading, we will use the originAttributes from the
-      // loadingPrincipal as the channel's originAttributes. This allows the favicon
+      // triggeringPrincipal as the channel's originAttributes. This allows the favicon
       // loading from XUL will use the correct originAttributes.
 
       nsCOMPtr<nsILoadInfo> loadInfo = (*aResult)->GetLoadInfo();
       if (loadInfo) {
         rv =
-          loadInfo->SetOriginAttributes(aLoadingPrincipal->OriginAttributesRef());
+          loadInfo->SetOriginAttributes(aTriggeringPrincipal->OriginAttributesRef());
       }
     }
   } else {
     // either we are loading something inside a document, in which case
     // we should always have a requestingNode, or we are loading something
-    // outside a document, in which case the loadingPrincipal and
+    // outside a document, in which case the triggeringPrincipal and
     // triggeringPrincipal should always be the systemPrincipal.
     // However, there are exceptions: one is Notifications which create a
     // channel in the parent prcoess in which case we can't get a requestingNode.
     rv = NS_NewChannel(aResult,
                        aURI,
                        nsContentUtils::GetSystemPrincipal(),
                        securityFlags,
                        aPolicyType,
@@ -813,36 +813,36 @@ NewImageChannel(nsIChannel** aResult,
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     // Use the OriginAttributes from the loading principal, if one is available,
     // and adjust the private browsing ID based on what kind of load the caller
     // has asked us to perform.
     OriginAttributes attrs;
-    if (aLoadingPrincipal) {
-      attrs = aLoadingPrincipal->OriginAttributesRef();
+    if (aTriggeringPrincipal) {
+      attrs = aTriggeringPrincipal->OriginAttributesRef();
     }
     attrs.mPrivateBrowsingId = aRespectPrivacy ? 1 : 0;
 
     nsCOMPtr<nsILoadInfo> loadInfo = (*aResult)->GetLoadInfo();
     if (loadInfo) {
       rv = loadInfo->SetOriginAttributes(attrs);
     }
   }
 
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   // only inherit if we have a principal
   *aForcePrincipalCheckForCacheEntry =
-    aLoadingPrincipal &&
+    aTriggeringPrincipal &&
     nsContentUtils::ChannelShouldInheritPrincipal(
-      aLoadingPrincipal,
+      aTriggeringPrincipal,
       aURI,
       /* aInheritForAboutBlank */ false,
       /* aForceInherit */ false);
 
   // Initialize HTTP-specific attributes
   newHttpChannel = do_QueryInterface(*aResult);
   if (newHttpChannel) {
     rv = newHttpChannel->SetRequestHeader(NS_LITERAL_CSTRING("Accept"),
@@ -1705,17 +1705,17 @@ imgLoader::ValidateRequestWithNewChannel
                                          ReferrerPolicy aReferrerPolicy,
                                          nsILoadGroup* aLoadGroup,
                                          imgINotificationObserver* aObserver,
                                          nsISupports* aCX,
                                          nsIDocument* aLoadingDocument,
                                          nsLoadFlags aLoadFlags,
                                          nsContentPolicyType aLoadPolicyType,
                                          imgRequestProxy** aProxyRequest,
-                                         nsIPrincipal* aLoadingPrincipal,
+                                         nsIPrincipal* aTriggeringPrincipal,
                                          int32_t aCORSMode)
 {
   // now we need to insert a new channel request object inbetween the real
   // request and the proxy that basically delays loading the image until it
   // gets a 304 or figures out that this needs to be a new request
 
   nsresult rv;
 
@@ -1755,17 +1755,17 @@ imgLoader::ValidateRequestWithNewChannel
                        aInitialDocumentURI,
                        aCORSMode,
                        aReferrerURI,
                        aReferrerPolicy,
                        aLoadGroup,
                        mAcceptHeader,
                        aLoadFlags,
                        aLoadPolicyType,
-                       aLoadingPrincipal,
+                       aTriggeringPrincipal,
                        aCX,
                        mRespectPrivacy);
   if (NS_FAILED(rv)) {
     return false;
   }
 
   RefPtr<imgRequestProxy> req;
   rv = CreateNewProxyForRequest(request, aLoadGroup, aLoadingDocument,
@@ -1827,17 +1827,17 @@ imgLoader::ValidateEntry(imgCacheEntry* 
                          nsILoadGroup* aLoadGroup,
                          imgINotificationObserver* aObserver,
                          nsISupports* aCX,
                          nsIDocument* aLoadingDocument,
                          nsLoadFlags aLoadFlags,
                          nsContentPolicyType aLoadPolicyType,
                          bool aCanMakeNewChannel,
                          imgRequestProxy** aProxyRequest,
-                         nsIPrincipal* aLoadingPrincipal,
+                         nsIPrincipal* aTriggeringPrincipal,
                          int32_t aCORSMode)
 {
   LOG_SCOPE(gImgLog, "imgLoader::ValidateEntry");
 
   bool hasExpired;
   uint32_t expirationTime = aEntry->GetExpiryTime();
   if (expirationTime <= SecondsFromPRTime(PR_Now())) {
     hasExpired = true;
@@ -1867,17 +1867,17 @@ imgLoader::ValidateEntry(imgCacheEntry* 
 
   RefPtr<imgRequest> request(aEntry->GetRequest());
 
   if (!request) {
     return false;
   }
 
   if (!ValidateSecurityInfo(request, aEntry->ForcePrincipalCheck(),
-                            aCORSMode, aLoadingPrincipal,
+                            aCORSMode, aTriggeringPrincipal,
                             aCX, aLoadPolicyType, aReferrerPolicy))
     return false;
 
   // data URIs are immutable and by their nature can't leak data, so we can
   // just return true in that case.  Doing so would mean that shift-reload
   // doesn't reload data URI documents/images though (which is handy for
   // debugging during gecko development) so we make an exception in that case.
   nsAutoCString scheme;
@@ -1945,17 +1945,17 @@ imgLoader::ValidateEntry(imgCacheEntry* 
     LOG_SCOPE(gImgLog,
               "imgLoader::ValidateRequest |cache hit| must validate");
 
     return ValidateRequestWithNewChannel(request, aURI, aInitialDocumentURI,
                                          aReferrerURI, aReferrerPolicy,
                                          aLoadGroup, aObserver,
                                          aCX, aLoadingDocument,
                                          aLoadFlags, aLoadPolicyType,
-                                         aProxyRequest, aLoadingPrincipal,
+                                         aProxyRequest, aTriggeringPrincipal,
                                          aCORSMode);
   }
 
   return !validateRequest;
 }
 
 bool
 imgLoader::RemoveFromCache(const ImageCacheKey& aKey)
@@ -2103,17 +2103,17 @@ imgLoader::RemoveFromUncachedImages(imgR
                                   nsIRequest::VALIDATE_NEVER |    \
                                   nsIRequest::VALIDATE_ONCE_PER_SESSION)
 
 NS_IMETHODIMP
 imgLoader::LoadImageXPCOM(nsIURI* aURI,
                           nsIURI* aInitialDocumentURI,
                           nsIURI* aReferrerURI,
                           const nsAString& aReferrerPolicy,
-                          nsIPrincipal* aLoadingPrincipal,
+                          nsIPrincipal* aTriggeringPrincipal,
                           nsILoadGroup* aLoadGroup,
                           imgINotificationObserver* aObserver,
                           nsISupports* aCX,
                           nsLoadFlags aLoadFlags,
                           nsISupports* aCacheKey,
                           nsContentPolicyType aContentPolicyType,
                           imgIRequest** _retval)
 {
@@ -2124,17 +2124,17 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
     imgRequestProxy* proxy;
     ReferrerPolicy refpol = ReferrerPolicyFromString(aReferrerPolicy);
     nsCOMPtr<nsINode> node = do_QueryInterface(aCX);
     nsCOMPtr<nsIDocument> doc = do_QueryInterface(aCX);
     nsresult rv = LoadImage(aURI,
                             aInitialDocumentURI,
                             aReferrerURI,
                             refpol,
-                            aLoadingPrincipal,
+                            aTriggeringPrincipal,
                             0,
                             aLoadGroup,
                             aObserver,
                             node,
                             doc,
                             aLoadFlags,
                             aCacheKey,
                             aContentPolicyType,
@@ -2145,17 +2145,17 @@ imgLoader::LoadImageXPCOM(nsIURI* aURI,
     return rv;
 }
 
 nsresult
 imgLoader::LoadImage(nsIURI* aURI,
                      nsIURI* aInitialDocumentURI,
                      nsIURI* aReferrerURI,
                      ReferrerPolicy aReferrerPolicy,
-                     nsIPrincipal* aLoadingPrincipal,
+                     nsIPrincipal* aTriggeringPrincipal,
                      uint64_t aRequestContextID,
                      nsILoadGroup* aLoadGroup,
                      imgINotificationObserver* aObserver,
                      nsINode *aContext,
                      nsIDocument* aLoadingDocument,
                      nsLoadFlags aLoadFlags,
                      nsISupports* aCacheKey,
                      nsContentPolicyType aContentPolicyType,
@@ -2227,28 +2227,28 @@ imgLoader::LoadImage(nsIURI* aURI,
 
   RefPtr<imgCacheEntry> entry;
 
   // Look in the cache for our URI, and then validate it.
   // XXX For now ignore aCacheKey. We will need it in the future
   // for correctly dealing with image load requests that are a result
   // of post data.
   OriginAttributes attrs;
-  if (aLoadingPrincipal) {
-    attrs = aLoadingPrincipal->OriginAttributesRef();
+  if (aTriggeringPrincipal) {
+    attrs = aTriggeringPrincipal->OriginAttributesRef();
   }
   ImageCacheKey key(aURI, attrs, aLoadingDocument, rv);
   NS_ENSURE_SUCCESS(rv, rv);
   imgCacheTable& cache = GetCache(key);
 
   if (cache.Get(key, getter_AddRefs(entry)) && entry) {
     if (ValidateEntry(entry, aURI, aInitialDocumentURI, aReferrerURI,
                       aReferrerPolicy, aLoadGroup, aObserver, aLoadingDocument,
                       aLoadingDocument, requestFlags, aContentPolicyType, true,
-                      _retval, aLoadingPrincipal, corsmode)) {
+                      _retval, aTriggeringPrincipal, corsmode)) {
       request = entry->GetRequest();
 
       // If this entry has no proxies, its request has no reference to the
       // entry.
       if (entry->HasNoProxies()) {
         LOG_FUNC_WITH_PARAM(gImgLog,
           "imgLoader::LoadImage() adding proxyless entry", "uri", key.Spec());
         MOZ_ASSERT(!request->HasCacheEntry(),
@@ -2283,17 +2283,17 @@ imgLoader::LoadImage(nsIURI* aURI,
                          aInitialDocumentURI,
                          corsmode,
                          aReferrerURI,
                          aReferrerPolicy,
                          aLoadGroup,
                          mAcceptHeader,
                          requestFlags,
                          aContentPolicyType,
-                         aLoadingPrincipal,
+                         aTriggeringPrincipal,
                          aContext,
                          mRespectPrivacy);
     if (NS_FAILED(rv)) {
       return NS_ERROR_FAILURE;
     }
 
     MOZ_ASSERT(NS_UsePrivateBrowsing(newChannel) == mRespectPrivacy);
 
@@ -2321,17 +2321,17 @@ imgLoader::LoadImage(nsIURI* aURI,
         }
       }
     }
 
     nsCOMPtr<nsILoadGroup> channelLoadGroup;
     newChannel->GetLoadGroup(getter_AddRefs(channelLoadGroup));
     rv = request->Init(aURI, aURI, /* aHadInsecureRedirect = */ false,
                        channelLoadGroup, newChannel, entry, aLoadingDocument,
-                       aLoadingPrincipal, corsmode, aReferrerPolicy);
+                       aTriggeringPrincipal, corsmode, aReferrerPolicy);
     if (NS_FAILED(rv)) {
       return NS_ERROR_FAILURE;
     }
 
     // Add the initiator type for this image load
     nsCOMPtr<nsITimedChannel> timedChannel = do_QueryInterface(newChannel);
     if (timedChannel) {
       timedChannel->SetInitiatorType(initiatorType);
@@ -2946,30 +2946,30 @@ imgCacheValidator::OnStartRequest(nsIReq
   if (MOZ_LOG_TEST(gImgLog, LogLevel::Debug)) {
     LOG_MSG_WITH_PARAM(gImgLog,
                        "imgCacheValidator::OnStartRequest creating new request",
                        "uri", uri->GetSpecOrDefault().get());
   }
 
   int32_t corsmode = mRequest->GetCORSMode();
   ReferrerPolicy refpol = mRequest->GetReferrerPolicy();
-  nsCOMPtr<nsIPrincipal> loadingPrincipal = mRequest->GetLoadingPrincipal();
+  nsCOMPtr<nsIPrincipal> triggeringPrincipal = mRequest->GetTriggeringPrincipal();
 
   // Doom the old request's cache entry
   mRequest->RemoveFromCache();
 
   mRequest->SetValidator(nullptr);
   mRequest = nullptr;
 
   // We use originalURI here to fulfil the imgIRequest contract on GetURI.
   nsCOMPtr<nsIURI> originalURI;
   channel->GetOriginalURI(getter_AddRefs(originalURI));
   nsresult rv =
     mNewRequest->Init(originalURI, uri, mHadInsecureRedirect, aRequest, channel,
-                      mNewEntry, context, loadingPrincipal, corsmode, refpol);
+                      mNewEntry, context, triggeringPrincipal, corsmode, refpol);
   if (NS_FAILED(rv)) {
     return rv;
   }
 
   mDestListener = new ProxyListener(mNewRequest);
 
   // Try to add the new request into the cache. Note that the entry must be in
   // the cache before the proxies' ownership changes, because adding a proxy
--- a/image/imgRequest.cpp
+++ b/image/imgRequest.cpp
@@ -90,17 +90,17 @@ imgRequest::~imgRequest()
 nsresult
 imgRequest::Init(nsIURI *aURI,
                  nsIURI *aCurrentURI,
                  bool aHadInsecureRedirect,
                  nsIRequest *aRequest,
                  nsIChannel *aChannel,
                  imgCacheEntry *aCacheEntry,
                  nsISupports* aCX,
-                 nsIPrincipal* aLoadingPrincipal,
+                 nsIPrincipal* aTriggeringPrincipal,
                  int32_t aCORSMode,
                  ReferrerPolicy aReferrerPolicy)
 {
   MOZ_ASSERT(NS_IsMainThread(), "Cannot use nsIURI off main thread!");
 
   LOG_FUNC(gImgLog, "imgRequest::Init");
 
   MOZ_ASSERT(!mImage, "Multiple calls to init");
@@ -116,17 +116,17 @@ imgRequest::Init(nsIURI *aURI,
   mURI = new ImageURL(aURI, rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mCurrentURI = aCurrentURI;
   mRequest = aRequest;
   mChannel = aChannel;
   mTimedChannel = do_QueryInterface(mChannel);
 
-  mLoadingPrincipal = aLoadingPrincipal;
+  mTriggeringPrincipal = aTriggeringPrincipal;
   mCORSMode = aCORSMode;
   mReferrerPolicy = aReferrerPolicy;
 
   // If the original URI and the current URI are different, check whether the
   // original URI is secure. We deliberately don't take the current URI into
   // account, as it needs to be handled using more complicated rules than
   // earlier elements of the redirect chain.
   if (aURI != aCurrentURI) {
--- a/image/imgRequest.h
+++ b/image/imgRequest.h
@@ -67,17 +67,17 @@ public:
 
   MOZ_MUST_USE nsresult Init(nsIURI* aURI,
                              nsIURI* aCurrentURI,
                              bool aHadInsecureRedirect,
                              nsIRequest* aRequest,
                              nsIChannel* aChannel,
                              imgCacheEntry* aCacheEntry,
                              nsISupports* aCX,
-                             nsIPrincipal* aLoadingPrincipal,
+                             nsIPrincipal* aTriggeringPrincipal,
                              int32_t aCORSMode,
                              ReferrerPolicy aReferrerPolicy);
 
   void ClearLoader();
 
   // Callers must call imgRequestProxy::Notify later.
   void AddProxy(imgRequestProxy* proxy);
 
@@ -122,19 +122,19 @@ public:
   // The CORS mode for which we loaded this image.
   int32_t GetCORSMode() const { return mCORSMode; }
 
   // The Referrer Policy in effect when loading this image.
   ReferrerPolicy GetReferrerPolicy() const { return mReferrerPolicy; }
 
   // The principal for the document that loaded this image. Used when trying to
   // validate a CORS image load.
-  already_AddRefed<nsIPrincipal> GetLoadingPrincipal() const
+  already_AddRefed<nsIPrincipal> GetTriggeringPrincipal() const
   {
-    nsCOMPtr<nsIPrincipal> principal = mLoadingPrincipal;
+    nsCOMPtr<nsIPrincipal> principal = mTriggeringPrincipal;
     return principal.forget();
   }
 
   // Return the ProgressTracker associated with this imgRequest. It may live
   // in |mProgressTracker| or in |mImage.mProgressTracker|, depending on whether
   // mImage has been instantiated yet.
   already_AddRefed<ProgressTracker> GetProgressTracker() const;
 
@@ -233,19 +233,20 @@ private:
   imgLoader* mLoader;
   nsCOMPtr<nsIRequest> mRequest;
   // The original URI we were loaded with. This is the same as the URI we are
   // keyed on in the cache. We store a string here to avoid off main thread
   // refcounting issues with nsStandardURL.
   RefPtr<ImageURL> mURI;
   // The URI of the resource we ended up loading after all redirects, etc.
   nsCOMPtr<nsIURI> mCurrentURI;
-  // The principal of the document which loaded this image. Used when
-  // validating for CORS.
-  nsCOMPtr<nsIPrincipal> mLoadingPrincipal;
+  // The principal which triggered the load of this image. Generally either
+  // the principal of the document the image is being loaded into, or of the
+  // stylesheet which specified the image to load. Used when validating for CORS.
+  nsCOMPtr<nsIPrincipal> mTriggeringPrincipal;
   // The principal of this image.
   nsCOMPtr<nsIPrincipal> mPrincipal;
   nsCOMPtr<nsIProperties> mProperties;
   nsCOMPtr<nsISupports> mSecurityInfo;
   nsCOMPtr<nsIChannel> mChannel;
   nsCOMPtr<nsIInterfaceRequestor> mPrevChannelSink;
   nsCOMPtr<nsIApplicationCache> mApplicationCache;
 
--- a/image/test/browser/browser_docshell_type_editor.js
+++ b/image/test/browser/browser_docshell_type_editor.js
@@ -104,15 +104,17 @@ add_task(async function() {
         }
         image.onerror = function() {
           ok(true, "APP_TYPE_UNKNOWN is *not* allowed to acces privileged image");
           // restore appType of rootDocShell before moving on to the next test
           rootDocShell.appType = defaultAppType;
           resolve();
         }
         doc.body.appendChild(image);
-        image.src = "chrome://test1/skin/privileged.png";
+        // Set the src via wrappedJSObject so the load is triggered with
+        // the content page's principal rather than ours.
+        image.wrappedJSObject.src = "chrome://test1/skin/privileged.png";
       });
     });
   });
 
   Components.manager.removeBootstrappedManifestLocation(manifestDir);
 });
--- a/layout/generic/CSSOrderAwareFrameIterator.h
+++ b/layout/generic/CSSOrderAwareFrameIterator.h
@@ -10,17 +10,17 @@
 #define mozilla_CSSOrderAwareFrameIterator_h
 
 #include <algorithm>
 #include "nsFrameList.h"
 #include "nsIFrame.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Assertions.h"
 
-#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 8
+#if defined(__clang__) && __clang_major__ == 3 && __clang_minor__ <= 9
 #define CLANG_CRASH_BUG 1
 #endif
 
 namespace mozilla {
 
 /**
  * CSSOrderAwareFrameIteratorT is a base class for iterators that traverse
  * child frame lists in a way that respects their CSS "order" property.
--- a/layout/printing/nsPrintEngine.cpp
+++ b/layout/printing/nsPrintEngine.cpp
@@ -96,17 +96,16 @@ static const char kPrintingPromptService
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIWebBrowserChrome.h"
 #include "nsIBaseWindow.h"
 #include "nsILayoutHistoryState.h"
 #include "nsFrameManager.h"
 #include "mozilla/ReflowInput.h"
-#include "nsIDOMHTMLLinkElement.h"
 #include "nsIDOMHTMLImageElement.h"
 #include "nsIContentViewerContainer.h"
 #include "nsIContentViewer.h"
 #include "nsIDocumentViewerPrint.h"
 
 #include "nsFocusManager.h"
 #include "nsRange.h"
 #include "nsCDefaultURIFixup.h"
--- a/layout/style/Loader.cpp
+++ b/layout/style/Loader.cpp
@@ -1917,16 +1917,17 @@ Loader::LoadInlineStyle(nsIContent* aEle
     data->mMustNotify = true;
   }
   return rv;
 }
 
 nsresult
 Loader::LoadStyleLink(nsIContent* aElement,
                       nsIURI* aURL,
+                      nsIPrincipal* aTriggeringPrincipal,
                       const nsAString& aTitle,
                       const nsAString& aMedia,
                       bool aHasAlternateRel,
                       CORSMode aCORSMode,
                       ReferrerPolicy aReferrerPolicy,
                       const nsAString& aIntegrity,
                       nsICSSLoaderObserver* aObserver,
                       bool* aIsAlternate)
@@ -1942,18 +1943,21 @@ Loader::LoadStyleLink(nsIContent* aEleme
 
   if (!mEnabled) {
     LOG_WARN(("  Not enabled"));
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_INITIALIZED);
 
-  nsIPrincipal* principal =
-    aElement ? aElement->NodePrincipal() : mDocument->NodePrincipal();
+  nsIPrincipal* principal = aTriggeringPrincipal;
+  if (!principal) {
+    principal = aElement ? aElement->NodePrincipal()
+                         : mDocument->NodePrincipal();
+  }
 
   nsISupports* context = aElement;
   if (!context) {
     context = mDocument;
   }
 
   nsresult rv = CheckContentPolicy(principal, aURL, context, false);
   if (NS_WARN_IF(NS_FAILED(rv))) {
--- a/layout/style/Loader.h
+++ b/layout/style/Loader.h
@@ -251,29 +251,33 @@ public:
    * Load a linked (document) stylesheet.  If a successful result is returned,
    * aObserver is guaranteed to be notified asynchronously once the sheet is
    * loaded and marked complete.  If an error is returned, aObserver will not
    * be notified.  In addition to loading the sheet, this method will insert it
    * into the stylesheet list of this CSSLoader's document.
    *
    * @param aElement the element linking to the the stylesheet.  May be null.
    * @param aURL the URL of the sheet.
+   * @param aTriggeringPrincipal the triggering principal for the load. May be
+   *        null, in which case the NodePrincipal() of the element (or
+   *        document if aElement is null) should be used.
    * @param aTitle the title of the sheet.
    * @param aMedia the media string for the sheet.
    * @param aHasAlternateRel whether the rel for this link included
    *        "alternate".
    * @param aCORSMode the CORS mode for this load.
    * @param aObserver the observer to notify when the load completes.
    *                  May be null.
    * @param [out] aIsAlternate whether the stylesheet actually ended up beinga
    *        an alternate sheet.  Note that this need not match
    *        aHasAlternateRel.
    */
   nsresult LoadStyleLink(nsIContent* aElement,
                          nsIURI* aURL,
+                         nsIPrincipal* aTriggeringPrincipal,
                          const nsAString& aTitle,
                          const nsAString& aMedia,
                          bool aHasAlternateRel,
                          CORSMode aCORSMode,
                          ReferrerPolicy aReferrerPolicy,
                          const nsAString& aIntegrity,
                          nsICSSLoaderObserver* aObserver,
                          bool* aIsAlternate);
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -3048,17 +3048,17 @@ var NativeWindow = {
     makeURI: function makeURI(aURL, aOriginCharset, aBaseURI) {
       return Services.io.newURI(aURL, aOriginCharset, aBaseURI);
     },
 
     _getLink: function(aElement) {
       if (aElement.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
           ((ChromeUtils.getClassName(aElement) === "HTMLAnchorElement" && aElement.href) ||
            (ChromeUtils.getClassName(aElement) === "HTMLAreaElement" && aElement.href) ||
-           aElement instanceof Ci.nsIDOMHTMLLinkElement ||
+           ChromeUtils.getClassName(aElement) === "HTMLLinkElement" ||
            aElement.getAttributeNS(kXLinkNamespace, "type") == "simple")) {
         try {
           let url = this._getLinkURL(aElement);
           return Services.io.newURI(url);
         } catch (e) {}
       }
       return null;
     },
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -1,495 +1,528 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "mozilla/MemoryReporting.h"
-#include "mozilla/dom/PContent.h"
-
+#include "GeckoProfiler.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/dom/PContent.h"
 #include "mozilla/HashFunctions.h"
+#include "mozilla/MemoryReporting.h"
+#include "mozilla/Omnijar.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/ResultExtensions.h"
 #include "mozilla/ScopeExit.h"
 #include "mozilla/ServoStyleSet.h"
 #include "mozilla/SyncRunnable.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/UniquePtrExtensions.h"
 #include "mozilla/URLPreloader.h"
-#include "mozilla/UniquePtrExtensions.h"
-
-#include "nsXULAppAPI.h"
-
-#include "mozilla/Preferences.h"
 #include "nsAppDirectoryServiceDefs.h"
+#include "nsAutoPtr.h"
+#include "nsCategoryManagerUtils.h"
+#include "nsCOMArray.h"
+#include "nsCRT.h"
 #include "nsDataHashtable.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsICategoryManager.h"
-#include "nsCategoryManagerUtils.h"
-#include "nsNetUtil.h"
 #include "nsIFile.h"
 #include "nsIInputStream.h"
+#include "nsIMemoryReporter.h"
 #include "nsIObserverService.h"
 #include "nsIOutputStream.h"
 #include "nsISafeOutputStream.h"
 #include "nsISimpleEnumerator.h"
 #include "nsIStringEnumerator.h"
 #include "nsIZipReader.h"
+#include "nsNetUtil.h"
 #include "nsPrefBranch.h"
+#include "nsPrintfCString.h"
+#include "nsQuickSort.h"
+#include "nsRefPtrHashtable.h"
 #include "nsString.h"
-#include "nsCRT.h"
-#include "nsCOMArray.h"
+#include "nsTArray.h"
+#include "nsThreadUtils.h"
 #include "nsXPCOMCID.h"
-#include "nsAutoPtr.h"
-#include "nsPrintfCString.h"
-
-#include "nsQuickSort.h"
+#include "nsXULAppAPI.h"
+#include "nsZipArchive.h"
 #include "PLDHashTable.h"
-
 #include "prefapi.h"
+#include "prefapi_private_data.h"
 #include "prefread.h"
-#include "prefapi_private_data.h"
-
-#include "mozilla/Omnijar.h"
-#include "nsZipArchive.h"
-
-#include "nsTArray.h"
-#include "nsRefPtrHashtable.h"
-#include "nsIMemoryReporter.h"
-#include "nsThreadUtils.h"
-#include "GeckoProfiler.h"
 
 using namespace mozilla;
 
 #ifdef DEBUG
-#define ENSURE_MAIN_PROCESS(message, pref) do {                                \
-  if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {                                  \
-    nsPrintfCString msg("ENSURE_MAIN_PROCESS failed. %s %s", message, pref);   \
-    NS_WARNING(msg.get());                                                     \
-    return NS_ERROR_NOT_AVAILABLE;                                             \
-  }                                                                            \
-} while (0);
-class WatchinPrefRAII {
+
+#define ENSURE_MAIN_PROCESS(message, pref)                                     \
+  do {                                                                         \
+    if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {                                \
+      nsPrintfCString msg("ENSURE_MAIN_PROCESS failed. %s %s", message, pref); \
+      NS_WARNING(msg.get());                                                   \
+      return NS_ERROR_NOT_AVAILABLE;                                           \
+    }                                                                          \
+  } while (0)
+
+class WatchinPrefRAII
+{
 public:
-  WatchinPrefRAII() {
-    pref_SetWatchingPref(true);
-  }
-  ~WatchinPrefRAII() {
-    pref_SetWatchingPref(false);
-  }
+  WatchinPrefRAII() { pref_SetWatchingPref(true); }
+  ~WatchinPrefRAII() { pref_SetWatchingPref(false); }
 };
+
 #define WATCHING_PREF_RAII() WatchinPrefRAII watchingPrefRAII
-#else
+
+#else // DEBUG
+
 #define ENSURE_MAIN_PROCESS(message, pref)                                     \
   if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {                                  \
     return NS_ERROR_NOT_AVAILABLE;                                             \
   }
+
 #define WATCHING_PREF_RAII()
-#endif
+
+#endif // DEBUG
 
 class PrefCallback;
 
 namespace mozilla {
 
-// Definitions
 #define INITIAL_PREF_FILES 10
+
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 void
 Preferences::DirtyCallback()
 {
   if (!XRE_IsParentProcess()) {
     // TODO: this should really assert because you can't set prefs in a
     // content process. But so much code currently does this that we just
     // ignore it for now.
     return;
   }
+
   if (!gHashTable || !sPreferences) {
     return;
   }
+
   if (sPreferences->mProfileShutdown) {
     NS_WARNING("Setting user pref after profile shutdown.");
     return;
   }
+
   if (!sPreferences->mDirty) {
     sPreferences->mDirty = true;
 
-    if (sPreferences->mCurrentFile &&
-        sPreferences->AllowOffMainThreadSave()
-        && !sPreferences->mSavePending) {
+    if (sPreferences->mCurrentFile && sPreferences->AllowOffMainThreadSave() &&
+        !sPreferences->mSavePending) {
       sPreferences->mSavePending = true;
       static const int PREF_DELAY_MS = 500;
       NS_DelayedDispatchToCurrentThread(
         mozilla::NewRunnableMethod("Preferences::SavePrefFileAsynchronous",
                                    sPreferences,
                                    &Preferences::SavePrefFileAsynchronous),
         PREF_DELAY_MS);
     }
   }
 }
 
-// Prototypes
-static nsresult openPrefFile(nsIFile* aFile);
-static Result<Ok, const char*> pref_InitInitialObjects();
-static nsresult pref_LoadPrefsInDirList(const char *listId);
-static nsresult ReadExtensionPrefs(nsIFile *aFile);
+static nsresult
+openPrefFile(nsIFile* aFile);
+
+static Result<Ok, const char*>
+pref_InitInitialObjects();
+
+static nsresult
+pref_LoadPrefsInDirList(const char* aListId);
+
+static nsresult
+ReadExtensionPrefs(nsIFile* aFile);
 
 static const char kTelemetryPref[] = "toolkit.telemetry.enabled";
 static const char kOldTelemetryPref[] = "toolkit.telemetry.enabledPreRelease";
 static const char kChannelPref[] = "app.update.channel";
 
+// clang-format off
 static const char kPrefFileHeader[] =
   "# Mozilla User Preferences"
   NS_LINEBREAK
   NS_LINEBREAK
   "/* Do not edit this file."
   NS_LINEBREAK
   " *"
   NS_LINEBREAK
   " * If you make changes to this file while the application is running,"
   NS_LINEBREAK
   " * the changes will be overwritten when the application exits."
   NS_LINEBREAK
   " *"
   NS_LINEBREAK
-  " * To make a manual change to preferences, you can visit the URL about:config"
+  " * To make a manual change to preferences, you can visit the URL "
+  "about:config"
   NS_LINEBREAK
   " */"
   NS_LINEBREAK
   NS_LINEBREAK;
+// clang-format on
 
 Preferences* Preferences::sPreferences = nullptr;
 nsIPrefBranch* Preferences::sRootBranch = nullptr;
 nsIPrefBranch* Preferences::sDefaultRootBranch = nullptr;
 bool Preferences::sShutdown = false;
 
-// This globally enables or disables OMT pref writing, both sync and async
+// This globally enables or disables OMT pref writing, both sync and async.
 static int32_t sAllowOMTPrefWrite = -1;
 
-
-class ValueObserverHashKey : public PLDHashEntryHdr {
+class ValueObserverHashKey : public PLDHashEntryHdr
+{
 public:
   typedef ValueObserverHashKey* KeyType;
   typedef const ValueObserverHashKey* KeyTypePointer;
 
-  static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey *aKey)
+  static const ValueObserverHashKey* KeyToPointer(ValueObserverHashKey* aKey)
   {
     return aKey;
   }
 
-  static PLDHashNumber HashKey(const ValueObserverHashKey *aKey)
+  static PLDHashNumber HashKey(const ValueObserverHashKey* aKey)
   {
     PLDHashNumber hash = HashString(aKey->mPrefName);
     hash = AddToHash(hash, aKey->mMatchKind);
     return AddToHash(hash, aKey->mCallback);
   }
 
-  ValueObserverHashKey(const char *aPref, PrefChangedFunc aCallback, Preferences::MatchKind aMatchKind) :
-    mPrefName(aPref), mCallback(aCallback), mMatchKind(aMatchKind) { }
+  ValueObserverHashKey(const char* aPref,
+                       PrefChangedFunc aCallback,
+                       Preferences::MatchKind aMatchKind)
+    : mPrefName(aPref)
+    , mCallback(aCallback)
+    , mMatchKind(aMatchKind)
+  {
+  }
 
-  explicit ValueObserverHashKey(const ValueObserverHashKey *aOther) :
-    mPrefName(aOther->mPrefName),
-    mCallback(aOther->mCallback),
-    mMatchKind(aOther->mMatchKind)
-  { }
+  explicit ValueObserverHashKey(const ValueObserverHashKey* aOther)
+    : mPrefName(aOther->mPrefName)
+    , mCallback(aOther->mCallback)
+    , mMatchKind(aOther->mMatchKind)
+  {
+  }
 
-  bool KeyEquals(const ValueObserverHashKey *aOther) const
+  bool KeyEquals(const ValueObserverHashKey* aOther) const
   {
-    return mCallback == aOther->mCallback &&
-           mPrefName == aOther->mPrefName &&
+    return mCallback == aOther->mCallback && mPrefName == aOther->mPrefName &&
            mMatchKind == aOther->mMatchKind;
   }
 
-  ValueObserverHashKey *GetKey() const
+  ValueObserverHashKey* GetKey() const
   {
     return const_cast<ValueObserverHashKey*>(this);
   }
 
-  enum { ALLOW_MEMMOVE = true };
+  enum
+  {
+    ALLOW_MEMMOVE = true
+  };
 
   nsCString mPrefName;
   PrefChangedFunc mCallback;
   Preferences::MatchKind mMatchKind;
 };
 
-class ValueObserver final : public nsIObserver,
-                            public ValueObserverHashKey
+class ValueObserver final
+  : public nsIObserver
+  , public ValueObserverHashKey
 {
-  ~ValueObserver() {
-    Preferences::RemoveObserver(this, mPrefName.get());
-  }
+  ~ValueObserver() { Preferences::RemoveObserver(this, mPrefName.get()); }
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIOBSERVER
 
-  ValueObserver(const char *aPref, PrefChangedFunc aCallback, Preferences::MatchKind aMatchKind)
-    : ValueObserverHashKey(aPref, aCallback, aMatchKind) { }
-
-  void AppendClosure(void *aClosure) {
-    mClosures.AppendElement(aClosure);
+  ValueObserver(const char* aPref,
+                PrefChangedFunc aCallback,
+                Preferences::MatchKind aMatchKind)
+    : ValueObserverHashKey(aPref, aCallback, aMatchKind)
+  {
   }
 
-  void RemoveClosure(void *aClosure) {
-    mClosures.RemoveElement(aClosure);
-  }
+  void AppendClosure(void* aClosure) { mClosures.AppendElement(aClosure); }
 
-  bool HasNoClosures() {
-    return mClosures.Length() == 0;
-  }
+  void RemoveClosure(void* aClosure) { mClosures.RemoveElement(aClosure); }
+
+  bool HasNoClosures() { return mClosures.Length() == 0; }
 
   nsTArray<void*> mClosures;
 };
 
 NS_IMPL_ISUPPORTS(ValueObserver, nsIObserver)
 
 NS_IMETHODIMP
-ValueObserver::Observe(nsISupports     *aSubject,
-                       const char      *aTopic,
-                       const char16_t *aData)
+ValueObserver::Observe(nsISupports* aSubject,
+                       const char* aTopic,
+                       const char16_t* aData)
 {
   NS_ASSERTION(!nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID),
                "invalid topic");
+
   NS_ConvertUTF16toUTF8 data(aData);
-  if (mMatchKind == Preferences::ExactMatch && !mPrefName.EqualsASCII(data.get())) {
+  if (mMatchKind == Preferences::ExactMatch &&
+      !mPrefName.EqualsASCII(data.get())) {
     return NS_OK;
   }
+
   for (uint32_t i = 0; i < mClosures.Length(); i++) {
     mCallback(data.get(), mClosures.ElementAt(i));
   }
 
   return NS_OK;
 }
 
 // Write the preference data to a file.
-//
 class PreferencesWriter final
 {
 public:
-  PreferencesWriter()
-  {
-  }
+  PreferencesWriter() = default;
 
-  static
-  nsresult Write(nsIFile* aFile, PrefSaveData& aPrefs)
+  static nsresult Write(nsIFile* aFile, PrefSaveData& aPrefs)
   {
     nsCOMPtr<nsIOutputStream> outStreamSink;
     nsCOMPtr<nsIOutputStream> outStream;
-    uint32_t                  writeAmount;
-    nsresult                  rv;
+    uint32_t writeAmount;
+    nsresult rv;
 
-    // execute a "safe" save by saving through a tempfile
-    rv = NS_NewSafeLocalFileOutputStream(getter_AddRefs(outStreamSink),
-                                         aFile,
-                                         -1,
-                                         0600);
+    // Execute a "safe" save by saving through a tempfile.
+    rv = NS_NewSafeLocalFileOutputStream(
+      getter_AddRefs(outStreamSink), aFile, -1, 0600);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
-    rv = NS_NewBufferedOutputStream(getter_AddRefs(outStream), outStreamSink, 4096);
+    rv = NS_NewBufferedOutputStream(
+      getter_AddRefs(outStream), outStreamSink, 4096);
     if (NS_FAILED(rv)) {
       return rv;
     }
 
     struct CharComparator
     {
       bool LessThan(const mozilla::UniqueFreePtr<char>& a,
                     const mozilla::UniqueFreePtr<char>& b) const
       {
         return strcmp(a.get(), b.get()) < 0;
       }
+
       bool Equals(const mozilla::UniqueFreePtr<char>& a,
                   const mozilla::UniqueFreePtr<char>& b) const
       {
         return strcmp(a.get(), b.get()) == 0;
       }
     };
 
-    /* Sort the preferences to make a readable file on disk */
+    // Sort the preferences to make a readable file on disk.
     aPrefs.Sort(CharComparator());
 
-    // write out the file header
-    outStream->Write(kPrefFileHeader, sizeof(kPrefFileHeader) - 1, &writeAmount);
+    // Write out the file header.
+    outStream->Write(
+      kPrefFileHeader, sizeof(kPrefFileHeader) - 1, &writeAmount);
 
     for (auto& prefptr : aPrefs) {
       char* pref = prefptr.get();
       MOZ_ASSERT(pref);
       outStream->Write(pref, strlen(pref), &writeAmount);
       outStream->Write(NS_LINEBREAK, NS_LINEBREAK_LEN, &writeAmount);
     }
 
-    // tell the safe output stream to overwrite the real prefs file
-    // (it'll abort if there were any errors during writing)
+    // Tell the safe output stream to overwrite the real prefs file.
+    // (It'll abort if there were any errors during writing.)
     nsCOMPtr<nsISafeOutputStream> safeStream = do_QueryInterface(outStream);
     NS_ASSERTION(safeStream, "expected a safe output stream!");
     if (safeStream) {
       rv = safeStream->Finish();
     }
 
 #ifdef DEBUG
     if (NS_FAILED(rv)) {
       NS_WARNING("failed to save prefs file! possible data loss");
     }
 #endif
+
     return rv;
   }
 
-  static
-  void Flush()
+  static void Flush()
   {
-    // This can be further optimized; instead of waiting for
-    // all of the writer thread to be available, we just have
-    // to wait for all the pending writes to be done.
+    // This can be further optimized; instead of waiting for all of the writer
+    // thread to be available, we just have to wait for all the pending writes
+    // to be done.
     if (!sPendingWriteData.compareExchange(nullptr, nullptr)) {
       nsresult rv = NS_OK;
       nsCOMPtr<nsIEventTarget> target =
         do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
       if (NS_SUCCEEDED(rv)) {
         target->Dispatch(NS_NewRunnableFunction("Preferences_dummy", [] {}),
                          nsIEventTarget::DISPATCH_SYNC);
       }
     }
   }
 
   // This is the data that all of the runnables (see below) will attempt
   // to write.  It will always have the most up to date version, or be
   // null, if the up to date information has already been written out.
   static Atomic<PrefSaveData*> sPendingWriteData;
 };
+
 Atomic<PrefSaveData*> PreferencesWriter::sPendingWriteData(nullptr);
 
 class PWRunnable : public Runnable
 {
 public:
   explicit PWRunnable(nsIFile* aFile)
     : Runnable("PWRunnable")
     , mFile(aFile)
-  {}
+  {
+  }
 
   NS_IMETHOD Run() override
   {
-    mozilla::UniquePtr<PrefSaveData> prefs(PreferencesWriter::sPendingWriteData.exchange(nullptr));
     // If we get a nullptr on the exchange, it means that somebody
     // else has already processed the request, and we can just return.
-
+    mozilla::UniquePtr<PrefSaveData> prefs(
+      PreferencesWriter::sPendingWriteData.exchange(nullptr));
     nsresult rv = NS_OK;
     if (prefs) {
       rv = PreferencesWriter::Write(mFile, *prefs);
 
       // Make a copy of these so we can have them in runnable lambda.
       // nsIFile is only there so that we would never release the
       // ref counted pointer off main thread.
       nsresult rvCopy = rv;
       nsCOMPtr<nsIFile> fileCopy(mFile);
-      SystemGroup::Dispatch(TaskCategory::Other,
-                            NS_NewRunnableFunction("Preferences::WriterRunnable", [fileCopy, rvCopy] {
-        MOZ_RELEASE_ASSERT(NS_IsMainThread());
-        if (NS_FAILED(rvCopy)) {
-          Preferences::DirtyCallback();
-        }
-      }));
+      SystemGroup::Dispatch(
+        TaskCategory::Other,
+        NS_NewRunnableFunction("Preferences::WriterRunnable",
+                               [fileCopy, rvCopy] {
+                                 MOZ_RELEASE_ASSERT(NS_IsMainThread());
+                                 if (NS_FAILED(rvCopy)) {
+                                   Preferences::DirtyCallback();
+                                 }
+                               }));
     }
     return rv;
   }
 
 protected:
   nsCOMPtr<nsIFile> mFile;
 };
 
-struct CacheData {
-  void* cacheLocation;
+struct CacheData
+{
+  void* mCacheLocation;
   union {
-    bool defaultValueBool;
-    int32_t defaultValueInt;
-    uint32_t defaultValueUint;
-    float defaultValueFloat;
+    bool mDefaultValueBool;
+    int32_t mDefaultValueInt;
+    uint32_t mDefaultValueUint;
+    float mDefaultValueFloat;
   };
 };
 
 // gCacheDataDesc holds information about prefs startup. It's being used for
 // diagnosing prefs startup problems in bug 1276488.
 static const char* gCacheDataDesc = "untouched";
-static nsTArray<nsAutoPtr<CacheData> >* gCacheData = nullptr;
-static nsRefPtrHashtable<ValueObserverHashKey,
-                         ValueObserver>* gObserverTable = nullptr;
+static nsTArray<nsAutoPtr<CacheData>>* gCacheData = nullptr;
+static nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>* gObserverTable =
+  nullptr;
 
 #ifdef DEBUG
 static bool
 HaveExistingCacheFor(void* aPtr)
 {
   MOZ_ASSERT(NS_IsMainThread());
   if (gCacheData) {
     for (size_t i = 0, count = gCacheData->Length(); i < count; ++i) {
-      if ((*gCacheData)[i]->cacheLocation == aPtr) {
+      if ((*gCacheData)[i]->mCacheLocation == aPtr) {
         return true;
       }
     }
   }
   return false;
 }
 
 static void
-AssertNotAlreadyCached(const char* aPrefType,
-                       const char* aPref,
-                       void* aPtr)
+AssertNotAlreadyCached(const char* aPrefType, const char* aPref, void* aPtr)
 {
   if (HaveExistingCacheFor(aPtr)) {
-    fprintf_stderr(stderr,
+    fprintf_stderr(
+      stderr,
       "Attempt to add a %s pref cache for preference '%s' at address '%p'"
       "was made. However, a pref was already cached at this address.\n",
-      aPrefType, aPref, aPtr);
-    MOZ_ASSERT(false, "Should not have an existing pref cache for this address");
+      aPrefType,
+      aPref,
+      aPtr);
+    MOZ_ASSERT(false,
+               "Should not have an existing pref cache for this address");
   }
 }
 #endif
 
 static void
 ReportToConsole(const char* aMessage, int aLine, bool aError)
 {
   nsPrintfCString message("** Preference parsing %s (line %d) = %s **\n",
-                          (aError ? "error" : "warning"), aLine, aMessage);
+                          (aError ? "error" : "warning"),
+                          aLine,
+                          aMessage);
   nsPrefBranch::ReportToConsole(NS_ConvertUTF8toUTF16(message.get()));
 }
 
 // Although this is a member of Preferences, it measures sPreferences and
 // several other global structures.
 /* static */ int64_t
-Preferences::SizeOfIncludingThisAndOtherStuff(mozilla::MallocSizeOf aMallocSizeOf)
+Preferences::SizeOfIncludingThisAndOtherStuff(
+  mozilla::MallocSizeOf aMallocSizeOf)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), 0);
 
   size_t n = aMallocSizeOf(sPreferences);
   if (gHashTable) {
-    // pref keys are allocated in a private arena, which we count elsewhere.
-    // pref stringvals are allocated out of the same private arena.
+    // Pref keys are allocated in a private arena, which we count elsewhere.
+    // Pref stringvals are allocated out of the same private arena.
     n += gHashTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
   }
+
   if (gCacheData) {
     n += gCacheData->ShallowSizeOfIncludingThis(aMallocSizeOf);
     for (uint32_t i = 0, count = gCacheData->Length(); i < count; ++i) {
       n += aMallocSizeOf((*gCacheData)[i]);
     }
   }
+
   if (gObserverTable) {
     n += gObserverTable->ShallowSizeOfIncludingThis(aMallocSizeOf);
     for (auto iter = gObserverTable->Iter(); !iter.Done(); iter.Next()) {
       n += iter.Key()->mPrefName.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
       n += iter.Data()->mClosures.ShallowSizeOfExcludingThis(aMallocSizeOf);
     }
   }
+
   if (sRootBranch) {
-    n += reinterpret_cast<nsPrefBranch*>(sRootBranch)->SizeOfIncludingThis(aMallocSizeOf);
+    n += reinterpret_cast<nsPrefBranch*>(sRootBranch)
+           ->SizeOfIncludingThis(aMallocSizeOf);
   }
+
   if (sDefaultRootBranch) {
-    n += reinterpret_cast<nsPrefBranch*>(sDefaultRootBranch)->SizeOfIncludingThis(aMallocSizeOf);
+    n += reinterpret_cast<nsPrefBranch*>(sDefaultRootBranch)
+           ->SizeOfIncludingThis(aMallocSizeOf);
   }
+
   n += pref_SizeOfPrivateData(aMallocSizeOf);
+
   return n;
 }
 
 class PreferenceServiceReporter final : public nsIMemoryReporter
 {
   ~PreferenceServiceReporter() {}
 
 public:
@@ -501,22 +534,26 @@ protected:
 };
 
 NS_IMPL_ISUPPORTS(PreferenceServiceReporter, nsIMemoryReporter)
 
 MOZ_DEFINE_MALLOC_SIZE_OF(PreferenceServiceMallocSizeOf)
 
 NS_IMETHODIMP
 PreferenceServiceReporter::CollectReports(
-  nsIHandleReportCallback* aHandleReport, nsISupports* aData, bool aAnonymize)
+  nsIHandleReportCallback* aHandleReport,
+  nsISupports* aData,
+  bool aAnonymize)
 {
-  MOZ_COLLECT_REPORT(
-    "explicit/preferences", KIND_HEAP, UNITS_BYTES,
-    Preferences::SizeOfIncludingThisAndOtherStuff(PreferenceServiceMallocSizeOf),
-    "Memory used by the preferences system.");
+  MOZ_COLLECT_REPORT("explicit/preferences",
+                     KIND_HEAP,
+                     UNITS_BYTES,
+                     Preferences::SizeOfIncludingThisAndOtherStuff(
+                       PreferenceServiceMallocSizeOf),
+                     "Memory used by the preferences system.");
 
   nsPrefBranch* rootBranch =
     static_cast<nsPrefBranch*>(Preferences::GetRootBranch());
   if (!rootBranch) {
     return NS_OK;
   }
 
   size_t numStrong = 0;
@@ -524,17 +561,17 @@ PreferenceServiceReporter::CollectReport
   size_t numWeakDead = 0;
   nsTArray<nsCString> suspectPreferences;
   // Count of the number of referents for each preference.
   nsDataHashtable<nsCStringHashKey, uint32_t> prefCounter;
 
   for (auto iter = rootBranch->mObservers.Iter(); !iter.Done(); iter.Next()) {
     nsAutoPtr<PrefCallback>& callback = iter.Data();
     nsPrefBranch* prefBranch = callback->GetPrefBranch();
-    const auto& pref = prefBranch->getPrefName(callback->GetDomain().get());
+    const auto& pref = prefBranch->GetPrefName(callback->GetDomain().get());
 
     if (callback->IsWeak()) {
       nsCOMPtr<nsIObserver> callbackRef = do_QueryReferent(callback->mWeakRef);
       if (callbackRef) {
         numWeakAlive++;
       } else {
         numWeakDead++;
       }
@@ -556,61 +593,76 @@ PreferenceServiceReporter::CollectReport
   }
 
   for (uint32_t i = 0; i < suspectPreferences.Length(); i++) {
     nsCString& suspect = suspectPreferences[i];
     uint32_t totalReferentCount = 0;
     prefCounter.Get(suspect, &totalReferentCount);
 
     nsPrintfCString suspectPath("preference-service-suspect/"
-                                "referent(pref=%s)", suspect.get());
+                                "referent(pref=%s)",
+                                suspect.get());
 
     aHandleReport->Callback(
       /* process = */ EmptyCString(),
-      suspectPath, KIND_OTHER, UNITS_COUNT, totalReferentCount,
+      suspectPath,
+      KIND_OTHER,
+      UNITS_COUNT,
+      totalReferentCount,
       NS_LITERAL_CSTRING(
         "A preference with a suspiciously large number referents (symptom of a "
         "leak)."),
       aData);
   }
 
   MOZ_COLLECT_REPORT(
-    "preference-service/referent/strong", KIND_OTHER, UNITS_COUNT,
+    "preference-service/referent/strong",
+    KIND_OTHER,
+    UNITS_COUNT,
     numStrong,
     "The number of strong referents held by the preference service.");
 
   MOZ_COLLECT_REPORT(
-    "preference-service/referent/weak/alive", KIND_OTHER, UNITS_COUNT,
+    "preference-service/referent/weak/alive",
+    KIND_OTHER,
+    UNITS_COUNT,
     numWeakAlive,
     "The number of weak referents held by the preference service that are "
     "still alive.");
 
   MOZ_COLLECT_REPORT(
-    "preference-service/referent/weak/dead", KIND_OTHER, UNITS_COUNT,
+    "preference-service/referent/weak/dead",
+    KIND_OTHER,
+    UNITS_COUNT,
     numWeakDead,
     "The number of weak referents held by the preference service that are "
     "dead.");
 
   return NS_OK;
 }
 
 namespace {
+
 class AddPreferencesMemoryReporterRunnable : public Runnable
 {
 public:
-  AddPreferencesMemoryReporterRunnable() : Runnable("AddPreferencesMemoryReporterRunnable") {}
+  AddPreferencesMemoryReporterRunnable()
+    : Runnable("AddPreferencesMemoryReporterRunnable")
+  {
+  }
+
   NS_IMETHOD Run() override
   {
     return RegisterStrongMemoryReporter(new PreferenceServiceReporter());
   }
 };
+
 } // namespace
 
-// static
-Preferences*
+/* static */ Preferences*
 Preferences::GetInstanceForService()
 {
   if (sPreferences) {
     NS_ADDREF(sPreferences);
     return sPreferences;
   }
 
   if (sShutdown) {
@@ -629,80 +681,75 @@ Preferences::GetInstanceForService()
   Result<Ok, const char*> res = sPreferences->Init();
   if (res.isErr()) {
     // The singleton instance will delete sRootBranch and sDefaultRootBranch.
     gCacheDataDesc = res.unwrapErr();
     NS_RELEASE(sPreferences);
     return nullptr;
   }
 
-  gCacheData = new nsTArray<nsAutoPtr<CacheData> >();
+  gCacheData = new nsTArray<nsAutoPtr<CacheData>>();
   gCacheDataDesc = "set by GetInstanceForService()";
 
   gObserverTable = new nsRefPtrHashtable<ValueObserverHashKey, ValueObserver>();
 
   // Preferences::GetInstanceForService() can be called from GetService(), and
   // RegisterStrongMemoryReporter calls GetService(nsIMemoryReporter).  To
   // avoid a potential recursive GetService() call, we can't register the
   // memory reporter here; instead, do it off a runnable.
   RefPtr<AddPreferencesMemoryReporterRunnable> runnable =
     new AddPreferencesMemoryReporterRunnable();
   NS_DispatchToMainThread(runnable);
 
   NS_ADDREF(sPreferences);
   return sPreferences;
 }
 
-// static
-bool
+/* static */ bool
 Preferences::IsServiceAvailable()
 {
   return !!sPreferences;
 }
 
-// static
-bool
+/* static */ bool
 Preferences::InitStaticMembers()
 {
   MOZ_ASSERT(NS_IsMainThread() || mozilla::ServoStyleSet::IsInServoTraversal());
 
   if (!sShutdown && !sPreferences) {
     MOZ_ASSERT(NS_IsMainThread());
     nsCOMPtr<nsIPrefService> prefService =
       do_GetService(NS_PREFSERVICE_CONTRACTID);
   }
 
   return sPreferences != nullptr;
 }
 
-// static
-void
+/* static */ void
 Preferences::Shutdown()
 {
   if (!sShutdown) {
     sShutdown = true; // Don't create the singleton instance after here.
 
-    // Don't set sPreferences to nullptr here.  The instance may be grabbed by
-    // other modules.  The utility methods of Preferences should be available
+    // Don't set sPreferences to nullptr here. The instance may be grabbed by
+    // other modules. The utility methods of Preferences should be available
     // until the singleton instance actually released.
     if (sPreferences) {
       sPreferences->Release();
     }
   }
 }
 
 //-----------------------------------------------------------------------------
 
-/*
- * Constructor/Destructor
- */
+//
+// Constructor/Destructor
+//
 
-Preferences::Preferences()
-{
-}
+Preferences::Preferences() = default;
 
 Preferences::~Preferences()
 {
   NS_ASSERTION(sPreferences == this, "Isn't this the singleton instance?");
 
   delete gObserverTable;
   gObserverTable = nullptr;
 
@@ -712,41 +759,40 @@ Preferences::~Preferences()
   NS_RELEASE(sRootBranch);
   NS_RELEASE(sDefaultRootBranch);
 
   sPreferences = nullptr;
 
   PREF_Cleanup();
 }
 
-
-/*
- * nsISupports Implementation
- */
+//
+// nsISupports Implementation
+//
 
 NS_IMPL_ADDREF(Preferences)
 NS_IMPL_RELEASE(Preferences)
 
 NS_INTERFACE_MAP_BEGIN(Preferences)
-    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService)
-    NS_INTERFACE_MAP_ENTRY(nsIPrefService)
-    NS_INTERFACE_MAP_ENTRY(nsIObserver)
-    NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
-    NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIPrefService)
+  NS_INTERFACE_MAP_ENTRY(nsIPrefService)
+  NS_INTERFACE_MAP_ENTRY(nsIObserver)
+  NS_INTERFACE_MAP_ENTRY(nsIPrefBranch)
+  NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
 NS_INTERFACE_MAP_END
 
-/*
- * nsIPrefService Implementation
- */
+//
+// nsIPrefService Implementation
+//
 
 InfallibleTArray<Preferences::PrefSetting>* gInitPrefs;
 
-/*static*/
-void
-Preferences::SetInitPreferences(nsTArray<PrefSetting>* aPrefs) {
+/* static */ void
+Preferences::SetInitPreferences(nsTArray<PrefSetting>* aPrefs)
+{
   gInitPrefs = new InfallibleTArray<PrefSetting>(mozilla::Move(*aPrefs));
 }
 
 Result<Ok, const char*>
 Preferences::Init()
 {
   PREF_SetDirtyCallback(&DirtyCallback);
   PREF_Init();
@@ -759,30 +805,31 @@ Preferences::Init()
       Preferences::SetPreference(gInitPrefs->ElementAt(i));
     }
     delete gInitPrefs;
     gInitPrefs = nullptr;
     return Ok();
   }
 
   nsCString lockFileName;
-  /*
-   * The following is a small hack which will allow us to only load the library
-   * which supports the netscape.cfg file if the preference is defined. We
-   * test for the existence of the pref, set in the all.js (mozilla) or
-   * all-ns.js (netscape 6), and if it exists we startup the pref config
-   * category which will do the rest.
-   */
+
+  // The following is a small hack which will allow us to only load the library
+  // which supports the netscape.cfg file if the preference is defined. We
+  // test for the existence of the pref, set in the all.js (mozilla) or
+  // all-ns.js (netscape 6), and if it exists we startup the pref config
+  // category which will do the rest.
 
-  nsresult rv = PREF_CopyCharPref("general.config.filename",
-                                  getter_Copies(lockFileName), false);
-  if (NS_SUCCEEDED(rv))
-    NS_CreateServicesFromCategory("pref-config-startup",
-                                  static_cast<nsISupports *>(static_cast<void *>(this)),
-                                  "pref-config-startup");
+  nsresult rv = PREF_CopyCharPref(
+    "general.config.filename", getter_Copies(lockFileName), false);
+  if (NS_SUCCEEDED(rv)) {
+    NS_CreateServicesFromCategory(
+      "pref-config-startup",
+      static_cast<nsISupports*>(static_cast<void*>(this)),
+      "pref-config-startup");
+  }
 
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   if (!observerService) {
     return Err("GetObserverService() failed (1)");
   }
 
   observerService->AddObserver(this, "profile-before-change-telemetry", true);
@@ -793,84 +840,89 @@ Preferences::Init()
 
   if (NS_FAILED(rv)) {
     return Err("AddObserver(\"profile-before-change\") failed");
   }
 
   return Ok();
 }
 
-// static
-void
+/* static */ void
 Preferences::InitializeUserPrefs()
 {
   MOZ_ASSERT(!sPreferences->mCurrentFile, "Should only initialize prefs once");
 
-  // prefs which are set before we initialize the profile are silently discarded.
-  // This is stupid, but there are various tests which depend on this behavior.
+  // Prefs which are set before we initialize the profile are silently
+  // discarded. This is stupid, but there are various tests which depend on
+  // this behavior.
   sPreferences->ResetUserPrefs();
 
   nsCOMPtr<nsIFile> prefsFile = sPreferences->ReadSavedPrefs();
   sPreferences->ReadUserOverridePrefs();
 
   sPreferences->mDirty = false;
 
-  // Don't set mCurrentFile until we're done so that dirty flags work properly
+  // Don't set mCurrentFile until we're done so that dirty flags work properly.
   sPreferences->mCurrentFile = prefsFile.forget();
 
-  // Migrate the old prerelease telemetry pref
+  // Migrate the old prerelease telemetry pref.
   if (!Preferences::GetBool(kOldTelemetryPref, true)) {
     Preferences::SetBool(kTelemetryPref, false);
     Preferences::ClearUser(kOldTelemetryPref);
   }
 
   sPreferences->NotifyServiceObservers(NS_PREFSERVICE_READ_TOPIC_ID);
 }
 
 NS_IMETHODIMP
-Preferences::Observe(nsISupports *aSubject, const char *aTopic,
-                     const char16_t *someData)
+Preferences::Observe(nsISupports* aSubject,
+                     const char* aTopic,
+                     const char16_t* someData)
 {
   if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   nsresult rv = NS_OK;
 
   if (!nsCRT::strcmp(aTopic, "profile-before-change")) {
     // Normally prefs aren't written after this point, and so we kick off
     // an asynchronous pref save so that I/O can be done in parallel with
     // other shutdown.
     if (AllowOffMainThreadSave()) {
       SavePrefFile(nullptr);
     }
+
   } else if (!nsCRT::strcmp(aTopic, "profile-before-change-telemetry")) {
     // It's possible that a profile-before-change observer after ours
     // set a pref. A blocking save here re-saves if necessary and also waits
     // for any pending saves to complete.
     SavePrefFileBlocking();
     MOZ_ASSERT(!mDirty, "Preferences should not be dirty");
     mProfileShutdown = true;
+
   } else if (!strcmp(aTopic, "load-extension-defaults")) {
     pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
+
   } else if (!nsCRT::strcmp(aTopic, "reload-default-prefs")) {
     // Reload the default prefs from file.
     Unused << pref_InitInitialObjects();
+
   } else if (!nsCRT::strcmp(aTopic, "suspend_process_notification")) {
     // Our process is being suspended. The OS may wake our process later,
     // or it may kill the process. In case our process is going to be killed
     // from the suspended state, we save preferences before suspending.
     rv = SavePrefFileBlocking();
   }
+
   return rv;
 }
 
-
 NS_IMETHODIMP
-Preferences::ReadUserPrefsFromFile(nsIFile *aFile)
+Preferences::ReadUserPrefsFromFile(nsIFile* aFile)
 {
   if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {
     NS_ERROR("must load prefs from parent process");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (!aFile) {
     NS_ERROR("ReadUserPrefsFromFile requires a parameter");
@@ -906,72 +958,74 @@ Preferences::ResetUserPrefs()
 
   PREF_ClearAllUserPrefs();
   return NS_OK;
 }
 
 bool
 Preferences::AllowOffMainThreadSave()
 {
-  // Put in a preference that allows us to disable
-  // off main thread preference file save.
+  // Put in a preference that allows us to disable off main thread preference
+  // file save.
   if (sAllowOMTPrefWrite < 0) {
     bool value = false;
     Preferences::GetBool("preferences.allow.omt-write", &value);
     sAllowOMTPrefWrite = value ? 1 : 0;
   }
+
   return !!sAllowOMTPrefWrite;
 }
 
 nsresult
 Preferences::SavePrefFileBlocking()
 {
   if (mDirty) {
     return SavePrefFileInternal(nullptr, SaveMethod::Blocking);
   }
 
-  // If we weren't dirty to start, SavePrefFileInternal will early exit
-  // so there is no guarantee that we don't have oustanding async
-  // saves in the pipe.  Since the contract of SavePrefFileOnMainThread
-  // is that the file on disk matches the preferences, we have to make
-  // sure those requests are completed.
+  // If we weren't dirty to start, SavePrefFileInternal will early exit so
+  // there is no guarantee that we don't have oustanding async saves in the
+  // pipe. Since the contract of SavePrefFileOnMainThread is that the file on
+  // disk matches the preferences, we have to make sure those requests are
+  // completed.
 
   if (AllowOffMainThreadSave()) {
     PreferencesWriter::Flush();
   }
+
   return NS_OK;
 }
 
 nsresult
 Preferences::SavePrefFileAsynchronous()
 {
   return SavePrefFileInternal(nullptr, SaveMethod::Asynchronous);
 }
 
 NS_IMETHODIMP
-Preferences::SavePrefFile(nsIFile *aFile)
+Preferences::SavePrefFile(nsIFile* aFile)
 {
-  // This is the method accessible from service API.  Make it off
-  // main thread.
+  // This is the method accessible from service API. Make it off main thread.
   return SavePrefFileInternal(aFile, SaveMethod::Asynchronous);
 }
 
 static nsresult
-ReadExtensionPrefs(nsIFile *aFile)
+ReadExtensionPrefs(nsIFile* aFile)
 {
   nsresult rv;
   nsCOMPtr<nsIZipReader> reader = do_CreateInstance(kZipReaderCID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = reader->Open(aFile);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIUTF8StringEnumerator> files;
-  rv = reader->FindEntries(nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"),
-                           getter_AddRefs(files));
+  rv = reader->FindEntries(
+    nsDependentCString("defaults/preferences/*.(J|j)(S|s)$"),
+    getter_AddRefs(files));
   NS_ENSURE_SUCCESS(rv, rv);
 
   char buffer[4096];
 
   bool more;
   while (NS_SUCCEEDED(rv = files->HasMore(&more)) && more) {
     nsAutoCString entry;
     rv = files->GetNext(entry);
@@ -992,31 +1046,33 @@ ReadExtensionPrefs(nsIFile *aFile)
         NS_WARNING("Pref stream read failed");
         break;
       }
 
       PREF_ParseBuf(&ps, buffer, read);
     }
     PREF_FinalizeParseState(&ps);
   }
+
   return rv;
 }
 
 void
 Preferences::SetPreference(const PrefSetting& aPref)
 {
   pref_SetPref(aPref);
 }
 
 void
 Preferences::GetPreference(PrefSetting* aPref)
 {
-  PrefHashEntry *entry = pref_HashTableLookup(aPref->name().get());
-  if (!entry)
+  PrefHashEntry* entry = pref_HashTableLookup(aPref->name().get());
+  if (!entry) {
     return;
+  }
 
   if (pref_EntryHasAdvisablySizedValues(entry)) {
     pref_GetPrefFromEntry(entry, aPref);
   }
 }
 
 void
 Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
@@ -1024,17 +1080,17 @@ Preferences::GetPreferences(InfallibleTA
   aPrefs->SetCapacity(gHashTable->Capacity());
   for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
     auto entry = static_cast<PrefHashEntry*>(iter.Get());
 
     if (!pref_EntryHasAdvisablySizedValues(entry)) {
       continue;
     }
 
-    dom::PrefSetting *pref = aPrefs->AppendElement();
+    dom::PrefSetting* pref = aPrefs->AppendElement();
     pref_GetPrefFromEntry(entry, pref);
   }
 }
 
 #ifdef DEBUG
 void
 Preferences::SetInitPhase(pref_initPhase phase)
 {
@@ -1044,189 +1100,199 @@ Preferences::SetInitPhase(pref_initPhase
 pref_initPhase
 Preferences::InitPhase()
 {
   return pref_GetInitPhase();
 }
 #endif
 
 NS_IMETHODIMP
-Preferences::GetBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
+Preferences::GetBranch(const char* aPrefRoot, nsIPrefBranch** aRetVal)
 {
-  nsresult rv;
-
   if ((nullptr != aPrefRoot) && (*aPrefRoot != '\0')) {
-    // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
+    // TODO: Cache this stuff and allow consumers to share branches (hold weak
+    // references, I think).
     RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, false);
-    prefBranch.forget(_retval);
-    rv = NS_OK;
+    prefBranch.forget(aRetVal);
   } else {
-    // special case caching the default root
+    // Special case: caching the default root.
     nsCOMPtr<nsIPrefBranch> root(sRootBranch);
-    root.forget(_retval);
-    rv = NS_OK;
-  }
-  return rv;
-}
-
-NS_IMETHODIMP
-Preferences::GetDefaultBranch(const char *aPrefRoot, nsIPrefBranch **_retval)
-{
-  if (!aPrefRoot || !aPrefRoot[0]) {
-    nsCOMPtr<nsIPrefBranch> root(sDefaultRootBranch);
-    root.forget(_retval);
-    return NS_OK;
+    root.forget(aRetVal);
   }
 
-  // TODO: - cache this stuff and allow consumers to share branches (hold weak references I think)
-  RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, true);
-  if (!prefBranch)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  prefBranch.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
-Preferences::GetDirty(bool *_retval) {
-  *_retval = mDirty;
+Preferences::GetDefaultBranch(const char* aPrefRoot, nsIPrefBranch** aRetVal)
+{
+  if (!aPrefRoot || !aPrefRoot[0]) {
+    nsCOMPtr<nsIPrefBranch> root(sDefaultRootBranch);
+    root.forget(aRetVal);
+    return NS_OK;
+  }
+
+  // TODO: Cache this stuff and allow consumers to share branches (hold weak
+  // references, I think).
+  RefPtr<nsPrefBranch> prefBranch = new nsPrefBranch(aPrefRoot, true);
+  if (!prefBranch) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  prefBranch.forget(aRetVal);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+Preferences::GetDirty(bool* aRetVal)
+{
+  *aRetVal = mDirty;
   return NS_OK;
 }
 
 nsresult
-Preferences::NotifyServiceObservers(const char *aTopic)
+Preferences::NotifyServiceObservers(const char* aTopic)
 {
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
-  if (!observerService)
+  if (!observerService) {
     return NS_ERROR_FAILURE;
+  }
 
-  nsISupports *subject = (nsISupports *)((nsIPrefService *)this);
+  auto subject = static_cast<nsIPrefService*>(this);
   observerService->NotifyObservers(subject, aTopic, nullptr);
 
   return NS_OK;
 }
 
 already_AddRefed<nsIFile>
 Preferences::ReadSavedPrefs()
 {
   nsCOMPtr<nsIFile> file;
-  nsresult rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE,
-                                       getter_AddRefs(file));
+  nsresult rv =
+    NS_GetSpecialDirectory(NS_APP_PREFS_50_FILE, getter_AddRefs(file));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return nullptr;
   }
 
   rv = openPrefFile(file);
   if (rv == NS_ERROR_FILE_NOT_FOUND) {
-    // this is a normal case for new users
-    Telemetry::ScalarSet(Telemetry::ScalarID::PREFERENCES_CREATED_NEW_USER_PREFS_FILE, true);
+    // This is a normal case for new users.
+    Telemetry::ScalarSet(
+      Telemetry::ScalarID::PREFERENCES_CREATED_NEW_USER_PREFS_FILE, true);
     rv = NS_OK;
   } else if (NS_FAILED(rv)) {
     // Save a backup copy of the current (invalid) prefs file, since all prefs
     // from the error line to the end of the file will be lost (bug 361102).
     // TODO we should notify the user about it (bug 523725).
-    Telemetry::ScalarSet(Telemetry::ScalarID::PREFERENCES_PREFS_FILE_WAS_INVALID, true);
+    Telemetry::ScalarSet(
+      Telemetry::ScalarID::PREFERENCES_PREFS_FILE_WAS_INVALID, true);
     MakeBackupPrefFile(file);
   }
 
   return file.forget();
 }
 
 void
 Preferences::ReadUserOverridePrefs()
 {
   nsCOMPtr<nsIFile> aFile;
-  nsresult rv = NS_GetSpecialDirectory(NS_APP_PREFS_50_DIR,
-                                       getter_AddRefs(aFile));
+  nsresult rv =
+    NS_GetSpecialDirectory(NS_APP_PREFS_50_DIR, getter_AddRefs(aFile));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return;
   }
 
   aFile->AppendNative(NS_LITERAL_CSTRING("user.js"));
   rv = openPrefFile(aFile);
   if (rv != NS_ERROR_FILE_NOT_FOUND) {
-    // If the file exists and was at least partially read, record that
-    // in telemetry as it may be a sign of pref injection.
+    // If the file exists and was at least partially read, record that in
+    // telemetry as it may be a sign of pref injection.
     Telemetry::ScalarSet(Telemetry::ScalarID::PREFERENCES_READ_USER_JS, true);
   }
 }
 
 nsresult
-Preferences::MakeBackupPrefFile(nsIFile *aFile)
+Preferences::MakeBackupPrefFile(nsIFile* aFile)
 {
   // Example: this copies "prefs.js" to "Invalidprefs.js" in the same directory.
   // "Invalidprefs.js" is removed if it exists, prior to making the copy.
   nsAutoString newFilename;
   nsresult rv = aFile->GetLeafName(newFilename);
   NS_ENSURE_SUCCESS(rv, rv);
+
   newFilename.InsertLiteral(u"Invalid", 0);
   nsCOMPtr<nsIFile> newFile;
   rv = aFile->GetParent(getter_AddRefs(newFile));
   NS_ENSURE_SUCCESS(rv, rv);
+
   rv = newFile->Append(newFilename);
   NS_ENSURE_SUCCESS(rv, rv);
+
   bool exists = false;
   newFile->Exists(&exists);
   if (exists) {
     rv = newFile->Remove(false);
     NS_ENSURE_SUCCESS(rv, rv);
   }
+
   rv = aFile->CopyTo(nullptr, newFilename);
   NS_ENSURE_SUCCESS(rv, rv);
+
   return rv;
 }
 
 nsresult
-Preferences::SavePrefFileInternal(nsIFile *aFile, SaveMethod aSaveMethod)
+Preferences::SavePrefFileInternal(nsIFile* aFile, SaveMethod aSaveMethod)
 {
   if (MOZ_UNLIKELY(!XRE_IsParentProcess())) {
     NS_ERROR("must save pref file from parent process");
     return NS_ERROR_NOT_AVAILABLE;
   }
 
-  // We allow different behavior here when aFile argument is not null,
-  // but it happens to be the same as the current file.  It is not
-  // clear that we should, but it does give us a "force" save on the
-  // unmodified pref file (see the original bug 160377 when we added this.)
+  // We allow different behavior here when aFile argument is not null, but it
+  // happens to be the same as the current file.  It is not clear that we
+  // should, but it does give us a "force" save on the unmodified pref file
+  // (see the original bug 160377 when we added this.)
 
   if (nullptr == aFile) {
     mSavePending = false;
 
-    // Off main thread writing only if allowed
+    // Off main thread writing only if allowed.
     if (!AllowOffMainThreadSave()) {
       aSaveMethod = SaveMethod::Blocking;
     }
 
-    // the mDirty flag tells us if we should write to mCurrentFile
-    // we only check this flag when the caller wants to write to the default
+    // The mDirty flag tells us if we should write to mCurrentFile. We only
+    // check this flag when the caller wants to write to the default.
     if (!mDirty) {
       return NS_OK;
     }
 
-    // check for profile shutdown after mDirty because the runnables from
-    // DirtyCallback can still be pending
+    // Check for profile shutdown after mDirty because the runnables from
+    // DirtyCallback can still be pending.
     if (mProfileShutdown) {
       NS_WARNING("Cannot save pref file after profile shutdown.");
       return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
     }
 
     // It's possible that we never got a prefs file.
     nsresult rv = NS_OK;
     if (mCurrentFile) {
       rv = WritePrefFile(mCurrentFile, aSaveMethod);
     }
 
-    // If we succeeded writing to mCurrentFile, reset the dirty flag
+    // If we succeeded writing to mCurrentFile, reset the dirty flag.
     if (NS_SUCCEEDED(rv)) {
       mDirty = false;
     }
     return rv;
+
   } else {
-    // We only allow off main thread writes on mCurrentFile
+    // We only allow off main thread writes on mCurrentFile.
     return WritePrefFile(aFile, SaveMethod::Blocking);
   }
 }
 
 nsresult
 Preferences::WritePrefFile(nsIFile* aFile, SaveMethod aSaveMethod)
 {
   if (!gHashTable) {
@@ -1243,131 +1309,135 @@ Preferences::WritePrefFile(nsIFile* aFil
 
     // Put the newly constructed preference data into sPendingWriteData
     // for the next request to pick up
     prefs.reset(PreferencesWriter::sPendingWriteData.exchange(prefs.release()));
     if (prefs) {
       // There was a previous request that hasn't been processed,
       // and this is the data it had.
       return rv;
-    } else {
-      // There were no previous requests, dispatch one since
-      // sPendingWriteData has the up to date information.
-      nsCOMPtr<nsIEventTarget> target =
-        do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
-      if (NS_SUCCEEDED(rv)) {
-        bool async = aSaveMethod == SaveMethod::Asynchronous;
-        if (async) {
-          rv = target->Dispatch(new PWRunnable(aFile),
-                                nsIEventTarget::DISPATCH_NORMAL);
-        } else {
-          // Note that we don't get the nsresult return value here
-          SyncRunnable::DispatchToThread(target, new PWRunnable(aFile), true);
-        }
-        return rv;
-      }
     }
 
-    // If we can't get the thread for writing, for whatever reason, do the
-    // main thread write after making some noise:
-    MOZ_ASSERT(false,"failed to get the target thread for OMT pref write");
+    // There were no previous requests. Dispatch one since sPendingWriteData has
+    // the up to date information.
+    nsCOMPtr<nsIEventTarget> target =
+      do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
+    if (NS_SUCCEEDED(rv)) {
+      bool async = aSaveMethod == SaveMethod::Asynchronous;
+      if (async) {
+        rv = target->Dispatch(new PWRunnable(aFile),
+                              nsIEventTarget::DISPATCH_NORMAL);
+      } else {
+        // Note that we don't get the nsresult return value here.
+        SyncRunnable::DispatchToThread(target, new PWRunnable(aFile), true);
+      }
+      return rv;
+    }
+
+    // If we can't get the thread for writing, for whatever reason, do the main
+    // thread write after making some noise.
+    MOZ_ASSERT(false, "failed to get the target thread for OMT pref write");
   }
 
-  // This will do a main thread write.  It is safe to do it this way
-  // as AllowOffMainThreadSave() returns a consistent value for the
-  // lifetime of the parent process.
+  // This will do a main thread write. It is safe to do it this way because
+  // AllowOffMainThreadSave() returns a consistent value for the lifetime of
+  // the parent process.
   PrefSaveData prefsData = pref_savePrefs(gHashTable);
   return PreferencesWriter::Write(aFile, prefsData);
 }
 
-static nsresult openPrefFile(nsIFile* aFile)
+static nsresult
+openPrefFile(nsIFile* aFile)
 {
   PrefParseState ps;
   PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
-  auto cleanup = MakeScopeExit([&] () {
-    PREF_FinalizeParseState(&ps);
-  });
+  auto cleanup = MakeScopeExit([&]() { PREF_FinalizeParseState(&ps); });
 
   nsCString data;
   MOZ_TRY_VAR(data, URLPreloader::ReadFile(aFile));
   if (!PREF_ParseBuf(&ps, data.get(), data.Length())) {
     return NS_ERROR_FILE_CORRUPTED;
   }
 
   return NS_OK;
-
 }
 
-/*
- * some stuff that gets called from Pref_Init()
- */
+//
+// Some stuff that gets called from Pref_Init()
+//
 
 static int
-pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2, void* /*unused*/)
+pref_CompareFileNames(nsIFile* aFile1, nsIFile* aFile2, void* /* unused */)
 {
   nsAutoCString filename1, filename2;
   aFile1->GetNativeLeafName(filename1);
   aFile2->GetNativeLeafName(filename2);
 
   return Compare(filename2, filename1);
 }
 
-/**
- * Load default pref files from a directory. The files in the
- * directory are sorted reverse-alphabetically; a set of "special file
- * names" may be specified which are loaded after all the others.
- */
+// Load default pref files from a directory. The files in the directory are
+// sorted reverse-alphabetically; a set of "special file names" may be
+// specified which are loaded after all the others.
 static nsresult
-pref_LoadPrefsInDir(nsIFile* aDir, char const *const *aSpecialFiles, uint32_t aSpecialFilesCount)
+pref_LoadPrefsInDir(nsIFile* aDir,
+                    char const* const* aSpecialFiles,
+                    uint32_t aSpecialFilesCount)
 {
   nsresult rv, rv2;
   bool hasMoreElements;
 
   nsCOMPtr<nsISimpleEnumerator> dirIterator;
 
-  // this may fail in some normal cases, such as embedders who do not use a GRE
+  // This may fail in some normal cases, such as embedders who do not use a
+  // GRE.
   rv = aDir->GetDirectoryEntries(getter_AddRefs(dirIterator));
   if (NS_FAILED(rv)) {
-    // If the directory doesn't exist, then we have no reason to complain.  We
+    // If the directory doesn't exist, then we have no reason to complain. We
     // loaded everything (and nothing) successfully.
-    if (rv == NS_ERROR_FILE_NOT_FOUND || rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
+    if (rv == NS_ERROR_FILE_NOT_FOUND ||
+        rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST) {
       rv = NS_OK;
+    }
     return rv;
   }
 
   rv = dirIterator->HasMoreElements(&hasMoreElements);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMArray<nsIFile> prefFiles(INITIAL_PREF_FILES);
   nsCOMArray<nsIFile> specialFiles(aSpecialFilesCount);
   nsCOMPtr<nsIFile> prefFile;
 
   while (hasMoreElements && NS_SUCCEEDED(rv)) {
-    nsAutoCString leafName;
-
     nsCOMPtr<nsISupports> supports;
     rv = dirIterator->GetNext(getter_AddRefs(supports));
     prefFile = do_QueryInterface(supports);
     if (NS_FAILED(rv)) {
       break;
     }
 
+    nsAutoCString leafName;
     prefFile->GetNativeLeafName(leafName);
-    NS_ASSERTION(!leafName.IsEmpty(), "Failure in default prefs: directory enumerator returned empty file?");
+    NS_ASSERTION(
+      !leafName.IsEmpty(),
+      "Failure in default prefs: directory enumerator returned empty file?");
 
-    // Skip non-js files
-    if (StringEndsWith(leafName, NS_LITERAL_CSTRING(".js"),
+    // Skip non-js files.
+    if (StringEndsWith(leafName,
+                       NS_LITERAL_CSTRING(".js"),
                        nsCaseInsensitiveCStringComparator())) {
       bool shouldParse = true;
-      // separate out special files
+
+      // Separate out special files.
       for (uint32_t i = 0; i < aSpecialFilesCount; ++i) {
         if (leafName.Equals(nsDependentCString(aSpecialFiles[i]))) {
           shouldParse = false;
-          // special files should be process in order; we put them into
-          // the array by index; this can make the array sparse
+          // Special files should be processed in order. We put them into the
+          // array by index, which can make the array sparse.
           specialFiles.ReplaceObjectAt(prefFile, i);
         }
       }
 
       if (shouldParse) {
         prefFiles.AppendObject(prefFile);
       }
     }
@@ -1392,548 +1462,542 @@ pref_LoadPrefsInDir(nsIFile* aDir, char 
     if (NS_FAILED(rv2)) {
       NS_ERROR("Default pref file not parsed successfully.");
       rv = rv2;
     }
   }
 
   arrayCount = specialFiles.Count();
   for (i = 0; i < arrayCount; ++i) {
-    // this may be a sparse array; test before parsing
+    // This may be a sparse array; test before parsing.
     nsIFile* file = specialFiles[i];
     if (file) {
       rv2 = openPrefFile(file);
       if (NS_FAILED(rv2)) {
         NS_ERROR("Special default pref file not parsed successfully.");
         rv = rv2;
       }
     }
   }
 
   return rv;
 }
 
-static nsresult pref_LoadPrefsInDirList(const char *listId)
+static nsresult
+pref_LoadPrefsInDirList(const char* aListId)
 {
   nsresult rv;
-  nsCOMPtr<nsIProperties> dirSvc(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
-  if (NS_FAILED(rv))
+  nsCOMPtr<nsIProperties> dirSvc(
+    do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv));
+  if (NS_FAILED(rv)) {
     return rv;
+  }
 
   nsCOMPtr<nsISimpleEnumerator> list;
-  dirSvc->Get(listId,
-              NS_GET_IID(nsISimpleEnumerator),
-              getter_AddRefs(list));
-  if (!list)
+  dirSvc->Get(aListId, NS_GET_IID(nsISimpleEnumerator), getter_AddRefs(list));
+  if (!list) {
     return NS_OK;
+  }
 
   bool hasMore;
   while (NS_SUCCEEDED(list->HasMoreElements(&hasMore)) && hasMore) {
     nsCOMPtr<nsISupports> elem;
     list->GetNext(getter_AddRefs(elem));
-    if (!elem)
+    if (!elem) {
       continue;
+    }
 
     nsCOMPtr<nsIFile> path = do_QueryInterface(elem);
-    if (!path)
+    if (!path) {
       continue;
+    }
 
     nsAutoCString leaf;
     path->GetNativeLeafName(leaf);
 
     // Do we care if a file provided by this process fails to load?
-    if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi"))
+    if (Substring(leaf, leaf.Length() - 4).EqualsLiteral(".xpi")) {
       ReadExtensionPrefs(path);
-    else
+    } else {
       pref_LoadPrefsInDir(path, nullptr, 0);
+    }
   }
+
   return NS_OK;
 }
 
-static nsresult pref_ReadPrefFromJar(nsZipArchive* jarReader, const char *name)
+static nsresult
+pref_ReadPrefFromJar(nsZipArchive* aJarReader, const char* aName)
 {
   nsCString manifest;
-  MOZ_TRY_VAR(manifest, URLPreloader::ReadZip(jarReader, nsDependentCString(name)));
+  MOZ_TRY_VAR(manifest,
+              URLPreloader::ReadZip(aJarReader, nsDependentCString(aName)));
 
   PrefParseState ps;
   PREF_InitParseState(&ps, PREF_ReaderCallback, ReportToConsole, nullptr);
   PREF_ParseBuf(&ps, manifest.get(), manifest.Length());
   PREF_FinalizeParseState(&ps);
 
   return NS_OK;
 }
 
-//----------------------------------------------------------------------------------------
-// Initialize default preference JavaScript buffers from
-// appropriate TEXT resources
-//----------------------------------------------------------------------------------------
+// Initialize default preference JavaScript buffers from appropriate TEXT
+// resources.
 static Result<Ok, const char*>
 pref_InitInitialObjects()
 {
-  nsresult rv;
-
-  // In omni.jar case, we load the following prefs:
+  // In the omni.jar case, we load the following prefs:
   // - jar:$gre/omni.jar!/greprefs.js
   // - jar:$gre/omni.jar!/defaults/pref/*.js
-  // In non omni.jar case, we load:
+  //
+  // In the non-omni.jar case, we load:
   // - $gre/greprefs.js
   //
   // In both cases, we also load:
   // - $gre/defaults/pref/*.js
+  //
   // This is kept for bug 591866 (channel-prefs.js should not be in omni.jar)
-  // on $app == $gre case ; we load all files instead of channel-prefs.js only
-  // to have the same behaviour as $app != $gre, where this is required as
-  // a supported location for GRE preferences.
+  // in the `$app == $gre` case; we load all files instead of channel-prefs.js
+  // only to have the same behaviour as `$app != $gre`, where this is required
+  // as a supported location for GRE preferences.
   //
-  // When $app != $gre, we additionally load, in omni.jar case:
+  // When `$app != $gre`, we additionally load, in the omni.jar case:
   // - jar:$app/omni.jar!/defaults/preferences/*.js
   // - $app/defaults/preferences/*.js
-  // and in non omni.jar case:
+  //
+  // and in the non-omni.jar case:
   // - $app/defaults/preferences/*.js
-  // When $app == $gre, we additionally load, in omni.jar case:
+  //
+  // When `$app == $gre`, we additionally load, in the omni.jar case:
   // - jar:$gre/omni.jar!/defaults/preferences/*.js
-  // Thus, in omni.jar case, we always load app-specific default preferences
-  // from omni.jar, whether or not $app == $gre.
+  //
+  // Thus, in the omni.jar case, we always load app-specific default
+  // preferences from omni.jar, whether or not `$app == $gre`.
 
-  nsZipFind *findPtr;
+  nsresult rv;
+  nsZipFind* findPtr;
   nsAutoPtr<nsZipFind> find;
   nsTArray<nsCString> prefEntries;
-  const char *entryName;
+  const char* entryName;
   uint16_t entryNameLen;
 
-  RefPtr<nsZipArchive> jarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
+  RefPtr<nsZipArchive> jarReader =
+    mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
   if (jarReader) {
-    // Load jar:$gre/omni.jar!/greprefs.js
+    // Load jar:$gre/omni.jar!/greprefs.js.
     rv = pref_ReadPrefFromJar(jarReader, "greprefs.js");
     NS_ENSURE_SUCCESS(rv, Err("pref_ReadPrefFromJar() failed"));
 
-    // Load jar:$gre/omni.jar!/defaults/pref/*.js
+    // Load jar:$gre/omni.jar!/defaults/pref/*.js.
     rv = jarReader->FindInit("defaults/pref/*.js$", &findPtr);
     NS_ENSURE_SUCCESS(rv, Err("jarReader->FindInit() failed"));
 
     find = findPtr;
     while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
       prefEntries.AppendElement(Substring(entryName, entryNameLen));
     }
 
     prefEntries.Sort();
-    for (uint32_t i = prefEntries.Length(); i--; ) {
+    for (uint32_t i = prefEntries.Length(); i--;) {
       rv = pref_ReadPrefFromJar(jarReader, prefEntries[i].get());
-      if (NS_FAILED(rv))
+      if (NS_FAILED(rv)) {
         NS_WARNING("Error parsing preferences.");
+      }
     }
+
   } else {
-    // Load $gre/greprefs.js
+    // Load $gre/greprefs.js.
     nsCOMPtr<nsIFile> greprefsFile;
     rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greprefsFile));
     NS_ENSURE_SUCCESS(rv, Err("NS_GetSpecialDirectory(NS_GRE_DIR) failed"));
 
     rv = greprefsFile->AppendNative(NS_LITERAL_CSTRING("greprefs.js"));
     NS_ENSURE_SUCCESS(rv, Err("greprefsFile->AppendNative() failed"));
 
     rv = openPrefFile(greprefsFile);
-    if (NS_FAILED(rv))
-      NS_WARNING("Error parsing GRE default preferences. Is this an old-style embedding app?");
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Error parsing GRE default preferences. Is this an old-style "
+                 "embedding app?");
+    }
   }
 
-  // Load $gre/defaults/pref/*.js
+  // Load $gre/defaults/pref/*.js.
   nsCOMPtr<nsIFile> defaultPrefDir;
-
-  rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR, getter_AddRefs(defaultPrefDir));
+  rv = NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR,
+                              getter_AddRefs(defaultPrefDir));
   NS_ENSURE_SUCCESS(
     rv, Err("NS_GetSpecialDirectory(NS_APP_PREF_DEFAULTS_50_DIR) failed"));
 
-  /* these pref file names should not be used: we process them after all other application pref files for backwards compatibility */
+  // These pref file names should not be used: we process them after all other
+  // application pref files for backwards compatibility.
   static const char* specialFiles[] = {
 #if defined(XP_MACOSX)
     "macprefs.js"
 #elif defined(XP_WIN)
     "winpref.js"
 #elif defined(XP_UNIX)
     "unix.js"
 #if defined(_AIX)
-    , "aix.js"
+    ,
+    "aix.js"
 #endif
 #elif defined(XP_BEOS)
     "beos.js"
 #endif
   };
 
-  rv = pref_LoadPrefsInDir(defaultPrefDir, specialFiles, ArrayLength(specialFiles));
-  if (NS_FAILED(rv))
+  rv = pref_LoadPrefsInDir(
+    defaultPrefDir, specialFiles, ArrayLength(specialFiles));
+  if (NS_FAILED(rv)) {
     NS_WARNING("Error parsing application default preferences.");
+  }
 
   // Load jar:$app/omni.jar!/defaults/preferences/*.js
   // or jar:$gre/omni.jar!/defaults/preferences/*.js.
-  RefPtr<nsZipArchive> appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
-  // GetReader(mozilla::Omnijar::APP) returns null when $app == $gre, in which
-  // case we look for app-specific default preferences in $gre.
-  if (!appJarReader)
+  RefPtr<nsZipArchive> appJarReader =
+    mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
+
+  // GetReader(mozilla::Omnijar::APP) returns null when `$app == $gre`, in
+  // which case we look for app-specific default preferences in $gre.
+  if (!appJarReader) {
     appJarReader = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
+  }
+
   if (appJarReader) {
     rv = appJarReader->FindInit("defaults/preferences/*.js$", &findPtr);
     NS_ENSURE_SUCCESS(rv, Err("appJarReader->FindInit() failed"));
     find = findPtr;
     prefEntries.Clear();
     while (NS_SUCCEEDED(find->FindNext(&entryName, &entryNameLen))) {
       prefEntries.AppendElement(Substring(entryName, entryNameLen));
     }
     prefEntries.Sort();
-    for (uint32_t i = prefEntries.Length(); i--; ) {
+    for (uint32_t i = prefEntries.Length(); i--;) {
       rv = pref_ReadPrefFromJar(appJarReader, prefEntries[i].get());
-      if (NS_FAILED(rv))
+      if (NS_FAILED(rv)) {
         NS_WARNING("Error parsing preferences.");
+      }
     }
   }
 
   rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
   NS_ENSURE_SUCCESS(
     rv, Err("pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST) failed"));
 
-  // Set up the correct default for toolkit.telemetry.enabled.
-  // If this build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta
-  // channel, telemetry is on by default, otherwise not. This is necessary
-  // so that beta users who are testing final release builds don't flipflop
-  // defaults.
-  if (Preferences::GetDefaultType(kTelemetryPref) == nsIPrefBranch::PREF_INVALID) {
+  // Set up the correct default for toolkit.telemetry.enabled. If this build
+  // has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta channel, telemetry
+  // is on by default, otherwise not. This is necessary so that beta users who
+  // are testing final release builds don't flipflop defaults.
+  if (Preferences::GetDefaultType(kTelemetryPref) ==
+      nsIPrefBranch::PREF_INVALID) {
     bool prerelease = false;
 #ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
     prerelease = true;
 #else
     nsAutoCString prefValue;
     Preferences::GetDefaultCString(kChannelPref, prefValue);
     if (prefValue.EqualsLiteral("beta")) {
       prerelease = true;
     }
 #endif
     PREF_SetBoolPref(kTelemetryPref, prerelease, true);
   }
 
   NS_CreateServicesFromCategory(NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID,
-                                nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
+                                nullptr,
+                                NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID);
 
   nsCOMPtr<nsIObserverService> observerService =
     mozilla::services::GetObserverService();
   NS_ENSURE_SUCCESS(rv, Err("GetObserverService() failed (2)"));
 
-  observerService->NotifyObservers(nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr);
+  observerService->NotifyObservers(
+    nullptr, NS_PREFSERVICE_APPDEFAULTS_TOPIC_ID, nullptr);
 
   rv = pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST);
   NS_ENSURE_SUCCESS(
     rv, Err("pref_LoadPrefsInDirList(NS_EXT_PREFS_DEFAULTS_DIR_LIST) failed"));
 
   return Ok();
 }
 
+//----------------------------------------------------------------------------
+// Static utilities
+//----------------------------------------------------------------------------
 
-/******************************************************************************
- *
- * static utilities
- *
- ******************************************************************************/
-
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetBool(const char* aPref, bool* aResult)
 {
   NS_PRECONDITION(aResult, "aResult must not be NULL");
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_GetBoolPref(aPref, aResult, false);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetInt(const char* aPref, int32_t* aResult)
 {
   NS_PRECONDITION(aResult, "aResult must not be NULL");
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_GetIntPref(aPref, aResult, false);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetFloat(const char* aPref, float* aResult)
 {
   NS_PRECONDITION(aResult, "aResult must not be NULL");
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   nsAutoCString result;
   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
   if (NS_SUCCEEDED(rv)) {
     *aResult = result.ToFloat(&rv);
   }
-
   return rv;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetCString(const char* aPref, nsACString& aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   char* result;
   nsresult rv = PREF_CopyCharPref(aPref, &result, false);
   if (NS_SUCCEEDED(rv)) {
     aResult.Adopt(result);
   }
   return rv;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetString(const char* aPref, nsAString& aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   nsAutoCString result;
   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), false);
   if (NS_SUCCEEDED(rv)) {
     CopyUTF8toUTF16(result, aResult);
   }
   return rv;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetLocalizedCString(const char* aPref, nsACString& aResult)
 {
   nsAutoString result;
   nsresult rv = GetLocalizedString(aPref, result);
   if (NS_SUCCEEDED(rv)) {
     CopyUTF16toUTF8(result, aResult);
   }
   return rv;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetLocalizedString(const char* aPref, nsAString& aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
-  nsresult rv = sRootBranch->GetComplexValue(aPref,
-                                             NS_GET_IID(nsIPrefLocalizedString),
-                                             getter_AddRefs(prefLocalString));
+  nsresult rv = sRootBranch->GetComplexValue(
+    aPref, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(prefLocalString));
   if (NS_SUCCEEDED(rv)) {
     NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
     prefLocalString->GetData(getter_Copies(aResult));
   }
   return rv;
 }
 
-// static
-nsresult
-Preferences::GetComplex(const char* aPref, const nsIID &aType, void** aResult)
+/* static */ nsresult
+Preferences::GetComplex(const char* aPref, const nsIID& aType, void** aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return sRootBranch->GetComplexValue(aPref, aType, aResult);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::SetCString(const char* aPref, const char* aValue)
 {
   ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_SetCharPref(aPref, aValue, false);
 }
 
-// static
-nsresult
-Preferences::SetCString(const char* aPref, const nsACString &aValue)
+/* static */ nsresult
+Preferences::SetCString(const char* aPref, const nsACString& aValue)
 {
   ENSURE_MAIN_PROCESS("Cannot SetCString from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_SetCharPref(aPref, PromiseFlatCString(aValue).get(), false);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::SetString(const char* aPref, const char16ptr_t aValue)
 {
   ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
 }
 
-// static
-nsresult
-Preferences::SetString(const char* aPref, const nsAString &aValue)
+/* static */ nsresult
+Preferences::SetString(const char* aPref, const nsAString& aValue)
 {
   ENSURE_MAIN_PROCESS("Cannot SetString from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_SetCharPref(aPref, NS_ConvertUTF16toUTF8(aValue).get(), false);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::SetBool(const char* aPref, bool aValue)
 {
   ENSURE_MAIN_PROCESS("Cannot SetBool from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_SetBoolPref(aPref, aValue, false);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::SetInt(const char* aPref, int32_t aValue)
 {
   ENSURE_MAIN_PROCESS("Cannot SetInt from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_SetIntPref(aPref, aValue, false);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::SetFloat(const char* aPref, float aValue)
 {
   return SetCString(aPref, nsPrintfCString("%f", aValue).get());
 }
 
-// static
-nsresult
-Preferences::SetComplex(const char* aPref, const nsIID &aType,
+/* static */ nsresult
+Preferences::SetComplex(const char* aPref,
+                        const nsIID& aType,
                         nsISupports* aValue)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return sRootBranch->SetComplexValue(aPref, aType, aValue);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::ClearUser(const char* aPref)
 {
   ENSURE_MAIN_PROCESS("Cannot ClearUser from content process:", aPref);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_ClearUserPref(aPref);
 }
 
-// static
-bool
+/* static */ bool
 Preferences::HasUserValue(const char* aPref)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), false);
   return PREF_HasUserPref(aPref);
 }
 
-// static
-int32_t
+/* static */ int32_t
 Preferences::GetType(const char* aPref)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
   int32_t result;
-  return NS_SUCCEEDED(sRootBranch->GetPrefType(aPref, &result)) ?
-    result : nsIPrefBranch::PREF_INVALID;
+  return NS_SUCCEEDED(sRootBranch->GetPrefType(aPref, &result))
+           ? result
+           : nsIPrefBranch::PREF_INVALID;
 }
 
-// static
-nsresult
-Preferences::AddStrongObserver(nsIObserver* aObserver,
-                               const char* aPref)
+/* static */ nsresult
+Preferences::AddStrongObserver(nsIObserver* aObserver, const char* aPref)
 {
   MOZ_ASSERT(aObserver);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return sRootBranch->AddObserver(aPref, aObserver, false);
 }
 
-// static
-nsresult
-Preferences::AddWeakObserver(nsIObserver* aObserver,
-                             const char* aPref)
+/* static */ nsresult
+Preferences::AddWeakObserver(nsIObserver* aObserver, const char* aPref)
 {
   MOZ_ASSERT(aObserver);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return sRootBranch->AddObserver(aPref, aObserver, true);
 }
 
-// static
-nsresult
-Preferences::RemoveObserver(nsIObserver* aObserver,
-                            const char* aPref)
+/* static */ nsresult
+Preferences::RemoveObserver(nsIObserver* aObserver, const char* aPref)
 {
   MOZ_ASSERT(aObserver);
   if (!sPreferences && sShutdown) {
     return NS_OK; // Observers have been released automatically.
   }
   NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
   return sRootBranch->RemoveObserver(aPref, aObserver);
 }
 
-// static
-nsresult
-Preferences::AddStrongObservers(nsIObserver* aObserver,
-                                const char** aPrefs)
+/* static */ nsresult
+Preferences::AddStrongObservers(nsIObserver* aObserver, const char** aPrefs)
 {
   MOZ_ASSERT(aObserver);
   for (uint32_t i = 0; aPrefs[i]; i++) {
     nsresult rv = AddStrongObserver(aObserver, aPrefs[i]);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
-// static
-nsresult
-Preferences::AddWeakObservers(nsIObserver* aObserver,
-                              const char** aPrefs)
+/* static */ nsresult
+Preferences::AddWeakObservers(nsIObserver* aObserver, const char** aPrefs)
 {
   MOZ_ASSERT(aObserver);
   for (uint32_t i = 0; aPrefs[i]; i++) {
     nsresult rv = AddWeakObserver(aObserver, aPrefs[i]);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
-// static
-nsresult
-Preferences::RemoveObservers(nsIObserver* aObserver,
-                             const char** aPrefs)
+/* static */ nsresult
+Preferences::RemoveObservers(nsIObserver* aObserver, const char** aPrefs)
 {
   MOZ_ASSERT(aObserver);
   if (!sPreferences && sShutdown) {
     return NS_OK; // Observers have been released automatically.
   }
   NS_ENSURE_TRUE(sPreferences, NS_ERROR_NOT_AVAILABLE);
 
   for (uint32_t i = 0; aPrefs[i]; i++) {
     nsresult rv = RemoveObserver(aObserver, aPrefs[i]);
     NS_ENSURE_SUCCESS(rv, rv);
   }
   return NS_OK;
 }
 
-static void NotifyObserver(const char* aPref, void* aClosure)
+static void
+NotifyObserver(const char* aPref, void* aClosure)
 {
   nsCOMPtr<nsIObserver> observer = static_cast<nsIObserver*>(aClosure);
-  observer->Observe(nullptr, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID,
+  observer->Observe(nullptr,
+                    NS_PREFBRANCH_PREFCHANGE_TOPIC_ID,
                     NS_ConvertASCIItoUTF16(aPref).get());
 }
 
-static void RegisterPriorityCallback(PrefChangedFunc aCallback,
-                                     const char* aPref,
-                                     void* aClosure)
+static void
+RegisterPriorityCallback(PrefChangedFunc aCallback,
+                         const char* aPref,
+                         void* aClosure)
 {
   MOZ_ASSERT(Preferences::IsServiceAvailable());
 
   ValueObserverHashKey hashKey(aPref, aCallback, Preferences::ExactMatch);
   RefPtr<ValueObserver> observer;
   gObserverTable->Get(&hashKey, getter_AddRefs(observer));
   if (observer) {
     observer->AppendClosure(aClosure);
     return;
   }
 
   observer = new ValueObserver(aPref, aCallback, Preferences::ExactMatch);
   observer->AppendClosure(aClosure);
-  PREF_RegisterPriorityCallback(aPref, NotifyObserver,
-                                static_cast<nsIObserver*>(observer));
+  PREF_RegisterPriorityCallback(
+    aPref, NotifyObserver, static_cast<nsIObserver*>(observer));
   gObserverTable->Put(observer, observer);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::RegisterCallback(PrefChangedFunc aCallback,
                               const char* aPref,
                               void* aClosure,
                               MatchKind aMatchKind)
 {
   MOZ_ASSERT(aCallback);
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
 
@@ -1944,38 +2008,37 @@ Preferences::RegisterCallback(PrefChange
     observer->AppendClosure(aClosure);
     return NS_OK;
   }
 
   observer = new ValueObserver(aPref, aCallback, aMatchKind);
   observer->AppendClosure(aClosure);
   nsresult rv = AddStrongObserver(observer, aPref);
   NS_ENSURE_SUCCESS(rv, rv);
+
   gObserverTable->Put(observer, observer);
   return NS_OK;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::RegisterCallbackAndCall(PrefChangedFunc aCallback,
                                      const char* aPref,
                                      void* aClosure,
                                      MatchKind aMatchKind)
 {
   MOZ_ASSERT(aCallback);
   WATCHING_PREF_RAII();
   nsresult rv = RegisterCallback(aCallback, aPref, aClosure, aMatchKind);
   if (NS_SUCCEEDED(rv)) {
     (*aCallback)(aPref, aClosure);
   }
   return rv;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::UnregisterCallback(PrefChangedFunc aCallback,
                                 const char* aPref,
                                 void* aClosure,
                                 MatchKind aMatchKind)
 {
   MOZ_ASSERT(aCallback);
   if (!sPreferences && sShutdown) {
     return NS_OK; // Observers have been released automatically.
@@ -1992,262 +2055,249 @@ Preferences::UnregisterCallback(PrefChan
   observer->RemoveClosure(aClosure);
   if (observer->HasNoClosures()) {
     // Delete the callback since its list of closures is empty.
     gObserverTable->Remove(observer);
   }
   return NS_OK;
 }
 
-// We insert cache observers using RegisterPriorityCallback to ensure they
-// are called prior to ordinary pref observers.  Doing this ensures that
-// ordinary observers will never get stale values from cache variables.
+// We insert cache observers using RegisterPriorityCallback to ensure they are
+// called prior to ordinary pref observers. Doing this ensures that ordinary
+// observers will never get stale values from cache variables.
 
-static void BoolVarChanged(const char* aPref, void* aClosure)
+static void
+BoolVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
-  *((bool*)cache->cacheLocation) =
-    Preferences::GetBool(aPref, cache->defaultValueBool);
+  *static_cast<bool*>(cache->mCacheLocation) =
+    Preferences::GetBool(aPref, cache->mDefaultValueBool);
 }
 
 static void
 CacheDataAppendElement(CacheData* aData)
 {
   if (!gCacheData) {
     MOZ_CRASH_UNSAFE_PRINTF("!gCacheData: %s", gCacheDataDesc);
   }
   gCacheData->AppendElement(aData);
 }
 
-// static
-nsresult
-Preferences::AddBoolVarCache(bool* aCache,
-                             const char* aPref,
-                             bool aDefault)
+/* static */ nsresult
+Preferences::AddBoolVarCache(bool* aCache, const char* aPref, bool aDefault)
 {
   WATCHING_PREF_RAII();
   NS_ASSERTION(aCache, "aCache must not be NULL");
 #ifdef DEBUG
   AssertNotAlreadyCached("bool", aPref, aCache);
 #endif
   *aCache = GetBool(aPref, aDefault);
   CacheData* data = new CacheData();
-  data->cacheLocation = aCache;
-  data->defaultValueBool = aDefault;
+  data->mCacheLocation = aCache;
+  data->mDefaultValueBool = aDefault;
   CacheDataAppendElement(data);
   RegisterPriorityCallback(BoolVarChanged, aPref, data);
   return NS_OK;
 }
 
-static void IntVarChanged(const char* aPref, void* aClosure)
+static void
+IntVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
-  *((int32_t*)cache->cacheLocation) =
-    Preferences::GetInt(aPref, cache->defaultValueInt);
+  *static_cast<int32_t*>(cache->mCacheLocation) =
+    Preferences::GetInt(aPref, cache->mDefaultValueInt);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::AddIntVarCache(int32_t* aCache,
                             const char* aPref,
                             int32_t aDefault)
 {
   WATCHING_PREF_RAII();
   NS_ASSERTION(aCache, "aCache must not be NULL");
 #ifdef DEBUG
   AssertNotAlreadyCached("int", aPref, aCache);
 #endif
   *aCache = Preferences::GetInt(aPref, aDefault);
   CacheData* data = new CacheData();
-  data->cacheLocation = aCache;
-  data->defaultValueInt = aDefault;
+  data->mCacheLocation = aCache;
+  data->mDefaultValueInt = aDefault;
   CacheDataAppendElement(data);
   RegisterPriorityCallback(IntVarChanged, aPref, data);
   return NS_OK;
 }
 
-static void UintVarChanged(const char* aPref, void* aClosure)
+static void
+UintVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
-  *((uint32_t*)cache->cacheLocation) =
-    Preferences::GetUint(aPref, cache->defaultValueUint);
+  *static_cast<uint32_t*>(cache->mCacheLocation) =
+    Preferences::GetUint(aPref, cache->mDefaultValueUint);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::AddUintVarCache(uint32_t* aCache,
                              const char* aPref,
                              uint32_t aDefault)
 {
   WATCHING_PREF_RAII();
   NS_ASSERTION(aCache, "aCache must not be NULL");
 #ifdef DEBUG
   AssertNotAlreadyCached("uint", aPref, aCache);
 #endif
   *aCache = Preferences::GetUint(aPref, aDefault);
   CacheData* data = new CacheData();
-  data->cacheLocation = aCache;
-  data->defaultValueUint = aDefault;
+  data->mCacheLocation = aCache;
+  data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
   RegisterPriorityCallback(UintVarChanged, aPref, data);
   return NS_OK;
 }
 
-template <MemoryOrdering Order>
-static void AtomicUintVarChanged(const char* aPref, void* aClosure)
+template<MemoryOrdering Order>
+static void
+AtomicUintVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
-  *((Atomic<uint32_t, Order>*)cache->cacheLocation) =
-    Preferences::GetUint(aPref, cache->defaultValueUint);
+  *static_cast<Atomic<uint32_t, Order>*>(cache->mCacheLocation) =
+    Preferences::GetUint(aPref, cache->mDefaultValueUint);
 }
 
-template <MemoryOrdering Order>
-// static
-nsresult
+template<MemoryOrdering Order>
+/* static */ nsresult
 Preferences::AddAtomicUintVarCache(Atomic<uint32_t, Order>* aCache,
                                    const char* aPref,
                                    uint32_t aDefault)
 {
   WATCHING_PREF_RAII();
   NS_ASSERTION(aCache, "aCache must not be NULL");
 #ifdef DEBUG
   AssertNotAlreadyCached("uint", aPref, aCache);
 #endif
   *aCache = Preferences::GetUint(aPref, aDefault);
   CacheData* data = new CacheData();
-  data->cacheLocation = aCache;
-  data->defaultValueUint = aDefault;
+  data->mCacheLocation = aCache;
+  data->mDefaultValueUint = aDefault;
   CacheDataAppendElement(data);
   RegisterPriorityCallback(AtomicUintVarChanged<Order>, aPref, data);
   return NS_OK;
 }
 
-// Since the definition of this template function 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::AddAtomicUintVarCache(Atomic<uint32_t,Relaxed>*,
-                                            const char*, uint32_t);
+// Since the definition of this template function 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::AddAtomicUintVarCache(Atomic<uint32_t, Relaxed>*,
+                                   const char*,
+                                   uint32_t);
 
-static void FloatVarChanged(const char* aPref, void* aClosure)
+static void
+FloatVarChanged(const char* aPref, void* aClosure)
 {
   CacheData* cache = static_cast<CacheData*>(aClosure);
-  *((float*)cache->cacheLocation) =
-    Preferences::GetFloat(aPref, cache->defaultValueFloat);
+  *static_cast<float*>(cache->mCacheLocation) =
+    Preferences::GetFloat(aPref, cache->mDefaultValueFloat);
 }
 
-// static
-nsresult
-Preferences::AddFloatVarCache(float* aCache,
-                             const char* aPref,
-                             float aDefault)
+/* static */ nsresult
+Preferences::AddFloatVarCache(float* aCache, const char* aPref, float aDefault)
 {
   WATCHING_PREF_RAII();
   NS_ASSERTION(aCache, "aCache must not be NULL");
 #ifdef DEBUG
   AssertNotAlreadyCached("float", aPref, aCache);
 #endif
   *aCache = Preferences::GetFloat(aPref, aDefault);
   CacheData* data = new CacheData();
-  data->cacheLocation = aCache;
-  data->defaultValueFloat = aDefault;
+  data->mCacheLocation = aCache;
+  data->mDefaultValueFloat = aDefault;
   CacheDataAppendElement(data);
   RegisterPriorityCallback(FloatVarChanged, aPref, data);
   return NS_OK;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetDefaultBool(const char* aPref, bool* aResult)
 {
   NS_PRECONDITION(aResult, "aResult must not be NULL");
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_GetBoolPref(aPref, aResult, true);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetDefaultInt(const char* aPref, int32_t* aResult)
 {
   NS_PRECONDITION(aResult, "aResult must not be NULL");
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return PREF_GetIntPref(aPref, aResult, true);
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetDefaultCString(const char* aPref, nsACString& aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   char* result;
   nsresult rv = PREF_CopyCharPref(aPref, &result, true);
   if (NS_SUCCEEDED(rv)) {
     aResult.Adopt(result);
   }
   return rv;
 }
 
-// static
-nsresult
+/* static */ nsresult
 Preferences::GetDefaultString(const char* aPref, nsAString& aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   nsAutoCString result;
   nsresult rv = PREF_CopyCharPref(aPref, getter_Copies(result), true);
   if (NS_SUCCEEDED(rv)) {
     CopyUTF8toUTF16(result, aResult);
   }
   return rv;
 }
 
-// static
-nsresult
-Preferences::GetDefaultLocalizedCString(const char* aPref,
-                                        nsACString& aResult)
+/* static */ nsresult
+Preferences::GetDefaultLocalizedCString(const char* aPref, nsACString& aResult)
 {
   nsAutoString result;
   nsresult rv = GetDefaultLocalizedString(aPref, result);
   if (NS_SUCCEEDED(rv)) {
     CopyUTF16toUTF8(result, aResult);
   }
   return rv;
 }
 
-// static
-nsresult
-Preferences::GetDefaultLocalizedString(const char* aPref,
-                                       nsAString& aResult)
+/* static */ nsresult
+Preferences::GetDefaultLocalizedString(const char* aPref, nsAString& aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   nsCOMPtr<nsIPrefLocalizedString> prefLocalString;
-  nsresult rv =
-    sDefaultRootBranch->GetComplexValue(aPref,
-                                        NS_GET_IID(nsIPrefLocalizedString),
-                                        getter_AddRefs(prefLocalString));
+  nsresult rv = sDefaultRootBranch->GetComplexValue(
+    aPref, NS_GET_IID(nsIPrefLocalizedString), getter_AddRefs(prefLocalString));
   if (NS_SUCCEEDED(rv)) {
     NS_ASSERTION(prefLocalString, "Succeeded but the result is NULL");
     prefLocalString->GetData(getter_Copies(aResult));
   }
   return rv;
 }
 
-// static
-nsresult
-Preferences::GetDefaultComplex(const char* aPref, const nsIID &aType,
+/* static */ nsresult
+Preferences::GetDefaultComplex(const char* aPref,
+                               const nsIID& aType,
                                void** aResult)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), NS_ERROR_NOT_AVAILABLE);
   return sDefaultRootBranch->GetComplexValue(aPref, aType, aResult);
 }
 
-// static
-int32_t
+/* static */ int32_t
 Preferences::GetDefaultType(const char* aPref)
 {
   NS_ENSURE_TRUE(InitStaticMembers(), nsIPrefBranch::PREF_INVALID);
   int32_t result;
-  return NS_SUCCEEDED(sDefaultRootBranch->GetPrefType(aPref, &result)) ?
-    result : nsIPrefBranch::PREF_INVALID;
+  return NS_SUCCEEDED(sDefaultRootBranch->GetPrefType(aPref, &result))
+           ? result
+           : nsIPrefBranch::PREF_INVALID;
 }
 
 } // namespace mozilla
 
 #undef ENSURE_MAIN_PROCESS
--- a/modules/libpref/Preferences.h
+++ b/modules/libpref/Preferences.h
@@ -1,128 +1,117 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_Preferences_h
 #define mozilla_Preferences_h
 
 #ifndef MOZILLA_INTERNAL_API
 #error "This header is only usable from within libxul (MOZILLA_INTERNAL_API)."
 #endif
 
-#include "nsIPrefService.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/MemoryReporting.h"
+#include "nsCOMPtr.h"
+#include "nsIObserver.h"
 #include "nsIPrefBranch.h"
-#include "nsIObserver.h"
-#include "nsCOMPtr.h"
+#include "nsIPrefService.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
-#include "mozilla/Atomics.h"
-#include "mozilla/MemoryReporting.h"
 
 class nsIFile;
 
 #ifndef have_PrefChangedFunc_typedef
-typedef void (*PrefChangedFunc)(const char *, void *);
+typedef void (*PrefChangedFunc)(const char*, void*);
 #define have_PrefChangedFunc_typedef
 #endif
 
 #ifdef DEBUG
-enum pref_initPhase {
+enum pref_initPhase
+{
   START,
   BEGIN_INIT_PREFS