Merge mozilla-central to mozilla-inbound. CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 14 Mar 2019 07:05:57 +0200
changeset 521900 6fbff0b70ee6
parent 521899 b3ac7a20c462 (current diff)
parent 521836 9fa0296c189b (diff)
child 521901 2709c2d4b40a
push id10870
push usernbeleuzu@mozilla.com
push dateFri, 15 Mar 2019 20:00:07 +0000
treeherdermozilla-beta@c594aee5b7a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to mozilla-inbound. CLOSED TREE
browser/themes/linux/monitor.png
browser/themes/linux/monitor_16-10.png
browser/themes/linux/setDesktopBackground.css
browser/themes/osx/monitor.png
browser/themes/osx/monitor_16-10.png
browser/themes/osx/setDesktopBackground.css
browser/themes/windows/monitor.png
browser/themes/windows/monitor_16-10.png
browser/themes/windows/setDesktopBackground.css
--- a/.cron.yml
+++ b/.cron.yml
@@ -111,16 +111,17 @@ jobs:
           by-project:
               mozilla-central: [{hour: 10, minute: 30}]
 
     - name: chromium-update
       job:
           type: decision-task
           treeherder-symbol: Chromium
           target-tasks-method: chromium_update
+          optimize-target-tasks: false
       run-on-projects:
           - mozilla-central
       when:
           by-project:
               mozilla-central: [{hour: 10, minute: 30}]
 
     - name: bouncer-check
       job:
--- a/Makefile.in
+++ b/Makefile.in
@@ -165,16 +165,23 @@ endif
 
 # Host binaries are not produced for macOS consumers: that is, there's
 # no macOS-hosted job to produce them at this time.  Therefore we
 # enable --host-bins only for automation builds, which only require Linux and
 # Windows host binaries.
 recurse_artifact:
 	$(topsrcdir)/mach --log-no-times artifact install$(if $(MOZ_ARTIFACT_BUILD_SYMBOLS), --symbols)$(if $(MOZ_AUTOMATION), --host-bins)
 
+ifdef MOZ_EME_WIN32_ARTIFACT
+recurse_win32-artifact:
+	rm -rf $(DIST)/i686
+	$(topsrcdir)/mach --log-no-times artifact install --job $(if $(MOZ_PGO),win32-pgo,win32-opt) --no-tests --distdir $(DIST)/i686
+	mv $(DIST)/i686/bin/* $(DIST)/i686
+endif
+
 ifdef MOZ_WIDGET_TOOLKIT
 ifdef ENABLE_TESTS
 # Additional makefile targets to call automated test suites
 include $(topsrcdir)/testing/testsuite-targets.mk
 endif
 endif
 
 default all::
--- a/accessible/tests/browser/browser.ini
+++ b/accessible/tests/browser/browser.ini
@@ -1,10 +1,10 @@
 [DEFAULT]
-
+skip-if = (os == 'win' && processor == 'aarch64') # 1534855
 support-files =
   events.js
   head.js
   shared-head.js
 
 [browser_shutdown_acc_reference.js]
 skip-if = (os == 'linux' && debug && bits == 64) #Bug 1421307
 [browser_shutdown_doc_acc_reference.js]
--- a/accessible/tests/browser/general/browser.ini
+++ b/accessible/tests/browser/general/browser.ini
@@ -1,8 +1,8 @@
 [DEFAULT]
 support-files =
   !/accessible/tests/browser/shared-head.js
   head.js
   !/accessible/tests/mochitest/*.js
-
+skip-if = (os == 'win' && processor == 'aarch64') # windows-aarch64, 1534811
 [browser_test_doc_creation.js]
 [browser_test_urlbar.js]
--- a/browser/actors/NetErrorChild.jsm
+++ b/browser/actors/NetErrorChild.jsm
@@ -23,16 +23,18 @@ XPCOMUtils.defineLazyGetter(this, "gPipN
 });
 XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
   return Services.strings.createBundle("chrome://branding/locale/brand.properties");
 });
 XPCOMUtils.defineLazyPreferenceGetter(this, "newErrorPagesEnabled",
   "browser.security.newcerterrorpage.enabled");
 XPCOMUtils.defineLazyPreferenceGetter(this, "mitmErrorPageEnabled",
   "browser.security.newcerterrorpage.mitm.enabled");
+XPCOMUtils.defineLazyPreferenceGetter(this, "mitmPrimingEnabled",
+  "security.certerrors.mitm.priming.enabled");
 XPCOMUtils.defineLazyGetter(this, "gNSSErrorsBundle", function() {
   return Services.strings.createBundle("chrome://pipnss/locale/nsserrors.properties");
 });
 
 
 const SEC_ERROR_BASE          = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
 const MOZILLA_PKIX_ERROR_BASE = Ci.nsINSSErrorsService.MOZILLA_PKIX_ERROR_BASE;
 
@@ -351,16 +353,17 @@ class NetErrorChild extends ActorChild {
       errorCode.addEventListener("click", () => {
         let debugInfo = doc.getElementById("certificateErrorDebugInformation");
         debugInfo.style.display = "block";
         debugInfo.scrollIntoView({block: "start", behavior: "smooth"});
       });
     }
   }
 
+  // eslint-disable-next-line complexity
   onCertErrorDetails(msg, docShell) {
     let doc = docShell.document;
 
     // This function centers the error container after its content updates.
     // It is currently duplicated in aboutNetError.js to avoid having to do
     // async communication to the page that would result in flicker.
     // TODO(johannh): Get rid of this duplication.
     function updateContainerPosition() {
@@ -373,16 +376,26 @@ class NetErrorChild extends ActorChild {
       } else {
         let offset = (doc.documentElement.clientHeight / 2) - (textContainer.clientHeight / 2);
         if (offset > 0) {
           textContainer.style.marginTop = `${offset}px`;
         }
       }
     }
 
+    // Check if the connection is being man-in-the-middled. When the parent
+    // detects an intercepted connection, the page may be reloaded with a new
+    // error code (MOZILLA_PKIX_ERROR_MITM_DETECTED).
+    if (newErrorPagesEnabled && mitmPrimingEnabled &&
+        msg.data.code == SEC_ERROR_UNKNOWN_ISSUER &&
+        // Only do this check for top-level failures.
+        doc.ownerGlobal.top === doc.ownerGlobal) {
+      this.mm.sendAsyncMessage("Browser:PrimeMitm");
+    }
+
     let div = doc.getElementById("certificateErrorText");
     div.textContent = msg.data.info;
     this._setTechDetails(msg, doc);
     let learnMoreLink = doc.getElementById("learnMoreLink");
     let baseURL = Services.urlFormatter.formatURLPref("app.support.baseURL");
     learnMoreLink.setAttribute("href", baseURL + "connection-not-secure");
     let errWhatToDo = doc.getElementById("es_nssBadCert_" + msg.data.codeString);
     let es = doc.getElementById("errorWhatToDoText");
@@ -448,16 +461,24 @@ class NetErrorChild extends ActorChild {
         descriptionContainer.append(adminDescription);
 
         learnMoreLink.href = baseURL + "symantec-warning";
 
         updateContainerPosition();
         break;
       case MOZILLA_PKIX_ERROR_MITM_DETECTED:
         if (newErrorPagesEnabled && mitmErrorPageEnabled) {
+          let autoEnabledEnterpriseRoots =
+            Services.prefs.getBoolPref("security.enterprise_roots.auto-enabled", false);
+          if (mitmPrimingEnabled && autoEnabledEnterpriseRoots) {
+            // If we automatically tried to import enterprise root certs but it didn't
+            // fix the MITM, reset the pref.
+            this.mm.sendAsyncMessage("Browser:ResetEnterpriseRootsPref");
+          }
+
           // We don't actually know what the MitM is called (since we don't
           // maintain a list), so we'll try and display the common name of the
           // root issuer to the user. In the worst case they are as clueless as
           // before, in the best case this gives them an actionable hint.
           // This may be revised in the future.
           let {securityInfo} = docShell.failedChannel;
           securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
           let mitmName = null;
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -966,16 +966,19 @@ pref("app.productInfo.baseURL", "https:/
 pref("security.alternate_certificate_error_page", "certerror");
 
 // Enable the new certificate error pages.
 pref("browser.security.newcerterrorpage.enabled", true);
 
 pref("browser.security.newcerterrorpage.mitm.enabled", true);
 pref("security.certerrors.recordEventTelemetry", true);
 pref("security.certerrors.permanentOverride", true);
+pref("security.certerrors.mitm.priming.enabled", true);
+pref("security.certerrors.mitm.priming.endpoint", "https://mitmdetection.services.mozilla.com/");
+pref("security.certerrors.mitm.auto_enable_enterprise_roots", false);
 
 // Whether to start the private browsing mode at application startup
 pref("browser.privatebrowsing.autostart", false);
 
 // Whether to show the new private browsing UI with in-content search box.
 pref("browser.privatebrowsing.searchUI", true);
 
 // Whether the bookmark panel should be shown when bookmarking a page.
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2930,16 +2930,19 @@ function PageProxyClickHandler(aEvent) {
   if (aEvent.button == 1 && Services.prefs.getBoolPref("middlemouse.paste"))
     middleMousePaste(aEvent);
 }
 
 // Values for telemtery bins: see TLS_ERROR_REPORT_UI in Histograms.json
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_CHECKED   = 2;
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_UNCHECKED = 3;
 
+const SEC_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SEC_ERROR_BASE;
+const SEC_ERROR_UNKNOWN_ISSUER = SEC_ERROR_BASE + 13;
+
 const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.", "security.ssl3."];
 
 /**
  * Handle command events bubbling up from error page content
  * or from about:newtab or from remote error pages that invoke
  * us via async messaging.
  */
 var BrowserOnClick = {
@@ -2948,30 +2951,34 @@ var BrowserOnClick = {
     mm.addMessageListener("Browser:CertExceptionError", this);
     mm.addMessageListener("Browser:OpenCaptivePortalPage", this);
     mm.addMessageListener("Browser:SiteBlockedError", this);
     mm.addMessageListener("Browser:EnableOnlineMode", this);
     mm.addMessageListener("Browser:SetSSLErrorReportAuto", this);
     mm.addMessageListener("Browser:ResetSSLPreferences", this);
     mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
     mm.addMessageListener("Browser:SSLErrorGoBack", this);
+    mm.addMessageListener("Browser:PrimeMitm", this);
+    mm.addMessageListener("Browser:ResetEnterpriseRootsPref", this);
 
     Services.obs.addObserver(this, "captive-portal-login-abort");
     Services.obs.addObserver(this, "captive-portal-login-success");
   },
 
   uninit() {
     let mm = window.messageManager;
     mm.removeMessageListener("Browser:CertExceptionError", this);
     mm.removeMessageListener("Browser:SiteBlockedError", this);
     mm.removeMessageListener("Browser:EnableOnlineMode", this);
     mm.removeMessageListener("Browser:SetSSLErrorReportAuto", this);
     mm.removeMessageListener("Browser:ResetSSLPreferences", this);
     mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
     mm.removeMessageListener("Browser:SSLErrorGoBack", this);
+    mm.removeMessageListener("Browser:PrimeMitm", this);
+    mm.removeMessageListener("Browser:ResetEnterpriseRootsPref", this);
 
     Services.obs.removeObserver(this, "captive-portal-login-abort");
     Services.obs.removeObserver(this, "captive-portal-login-success");
   },
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "captive-portal-login-abort":
@@ -3026,17 +3033,84 @@ var BrowserOnClick = {
       case "Browser:SSLErrorReportTelemetry":
         let reportStatus = msg.data.reportStatus;
         Services.telemetry.getHistogramById("TLS_ERROR_REPORT_UI")
           .add(reportStatus);
       break;
       case "Browser:SSLErrorGoBack":
         goBackFromErrorPage();
       break;
-    }
+      case "Browser:PrimeMitm":
+        this.primeMitm(msg.target);
+      break;
+      case "Browser:ResetEnterpriseRootsPref":
+        Services.prefs.clearUserPref("security.enterprise_roots.enabled");
+        Services.prefs.clearUserPref("security.enterprise_roots.auto-enabled");
+      break;
+    }
+  },
+
+  /**
+   * This function does a canary request to a reliable, maintained endpoint, in
+   * order to help network code detect a system-wide man-in-the-middle.
+   */
+  primeMitm(browser) {
+    // If we already have a mitm canary issuer stored, then don't bother with the
+    // extra request. This will be cleared on every update ping.
+    if (Services.prefs.getStringPref("security.pki.mitm_canary_issuer", null)) {
+      return;
+    }
+
+    let url = Services.prefs.getStringPref("security.certerrors.mitm.priming.endpoint");
+    let request = new XMLHttpRequest({mozAnon: true});
+    request.open("HEAD", url);
+    request.channel.loadFlags |= Ci.nsIRequest.LOAD_BYPASS_CACHE;
+    request.channel.loadFlags |= Ci.nsIRequest.INHIBIT_CACHING;
+
+    request.addEventListener("error", event => {
+      // Make sure the user is still on the cert error page.
+      if (!browser.documentURI.spec.startsWith("about:certerror")) {
+        return;
+      }
+
+      let secInfo = request.channel.securityInfo.QueryInterface(Ci.nsITransportSecurityInfo);
+      if (secInfo.errorCode != SEC_ERROR_UNKNOWN_ISSUER) {
+        return;
+      }
+
+      // When we get to this point there's already something deeply wrong, it's very likely
+      // that there is indeed a system-wide MitM.
+      if (secInfo.serverCert && secInfo.serverCert.issuerName) {
+        // Grab the issuer of the certificate used in the exchange and store it so that our
+        // network-level MitM detection code has a comparison baseline.
+        Services.prefs.setStringPref("security.pki.mitm_canary_issuer", secInfo.serverCert.issuerName);
+
+        // MitM issues are sometimes caused by software not registering their root certs in the
+        // Firefox root store. We might opt for using third party roots from the system root store.
+        if (Services.prefs.getBoolPref("security.certerrors.mitm.auto_enable_enterprise_roots")) {
+          if (!Services.prefs.getBoolPref("security.enterprise_roots.enabled")) {
+            // Loading enterprise roots happens on a background thread, so wait for import to finish.
+            BrowserUtils.promiseObserved("psm:enterprise-certs-imported").then(() => {
+              if (browser.documentURI.spec.startsWith("about:certerror")) {
+                browser.reload();
+              }
+            });
+
+            Services.prefs.setBoolPref("security.enterprise_roots.enabled", true);
+            // Record that this pref was automatically set.
+            Services.prefs.setBoolPref("security.enterprise_roots.auto-enabled", true);
+          }
+        } else {
+          // Need to reload the page to make sure network code picks up the canary issuer pref.
+          browser.reload();
+        }
+      }
+    });
+
+    request.send(null);
   },
 
   onCertError(browser, elementId, isTopFrame, location, securityInfoAsString, frameId) {
     let securityInfo;
     let cert;
 
     switch (elementId) {
       case "viewCertificate":
--- a/browser/base/content/test/about/browser.ini
+++ b/browser/base/content/test/about/browser.ini
@@ -7,16 +7,17 @@ support-files =
   POSTSearchEngine.xml
   dummy_page.html
 prefs =
   browser.newtabpage.activity-stream.improvesearch.handoffToAwesomebar=false
 
 [browser_aboutCertError.js]
 [browser_aboutCertError_clockSkew.js]
 [browser_aboutCertError_exception.js]
+[browser_aboutCertError_mitm.js]
 [browser_aboutCertError_telemetry.js]
 [browser_aboutHome_search_POST.js]
 [browser_aboutHome_search_composing.js]
 [browser_aboutHome_search_searchbar.js]
 [browser_aboutHome_search_suggestion.js]
 skip-if = os == "mac" || (os == "linux" && (!debug || bits == 64)) || (os == 'win' && os_version == '10.0' && bits == 64 && !debug) # Bug 1399648, bug 1402502
 [browser_aboutHome_search_telemetry.js]
 [browser_aboutNetError.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/about/browser_aboutCertError_mitm.js
@@ -0,0 +1,97 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const PREF_NEW_CERT_ERRORS = "browser.security.newcerterrorpage.enabled";
+const PREF_MITM_PRIMING = "security.certerrors.mitm.priming.enabled";
+const PREF_MITM_PRIMING_ENDPOINT = "security.certerrors.mitm.priming.endpoint";
+const PREF_MITM_CANARY_ISSUER = "security.pki.mitm_canary_issuer";
+const PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS = "security.certerrors.mitm.auto_enable_enterprise_roots";
+const PREF_ENTERPRISE_ROOTS = "security.enterprise_roots.enabled";
+
+const UNKNOWN_ISSUER = "https://untrusted.example.com";
+
+// Check that basic MitM priming works and the MitM error page is displayed successfully.
+add_task(async function checkMitmPriming() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    [PREF_NEW_CERT_ERRORS, true],
+    [PREF_MITM_PRIMING, true],
+    [PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
+  ]});
+
+  let browser;
+  let certErrorLoaded;
+  await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+    gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
+    browser = gBrowser.selectedBrowser;
+    certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
+  }, false);
+
+  await certErrorLoaded;
+
+  // The page will reload after the initial canary request, so we'll just
+  // wait until we're seeing the dedicated MitM page.
+  await TestUtils.waitForCondition(function() {
+    return ContentTask.spawn(browser, {}, () => {
+      return content.document.body.getAttribute("code") == "MOZILLA_PKIX_ERROR_MITM_DETECTED";
+    });
+  }, "Loads the MitM error page.");
+
+  ok(true, "Successfully loaded the MitM error page.");
+
+  is(Services.prefs.getStringPref(PREF_MITM_CANARY_ISSUER), "CN=Unknown CA", "Stored the correct issuer");
+
+  await ContentTask.spawn(browser, {}, () => {
+    let mitmName1 = content.document.querySelector("#errorShortDescText .mitm-name");
+    ok(ContentTaskUtils.is_visible(mitmName1), "Potential man in the middle is displayed");
+    is(mitmName1.textContent, "Unknown CA", "Shows the name of the issuer.");
+
+    let mitmName2 = content.document.querySelector("#errorWhatToDoText .mitm-name");
+    ok(ContentTaskUtils.is_visible(mitmName2), "Potential man in the middle is displayed");
+    is(mitmName2.textContent, "Unknown CA", "Shows the name of the issuer.");
+  });
+
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+
+  Services.prefs.clearUserPref(PREF_MITM_CANARY_ISSUER);
+});
+
+// Check that we set the enterprise roots pref correctly on MitM
+add_task(async function checkMitmAutoEnableEnterpriseRoots() {
+  await SpecialPowers.pushPrefEnv({"set": [
+    [PREF_NEW_CERT_ERRORS, true],
+    [PREF_MITM_PRIMING, true],
+    [PREF_MITM_PRIMING_ENDPOINT, UNKNOWN_ISSUER],
+    [PREF_MITM_AUTO_ENABLE_ENTERPRISE_ROOTS, true],
+  ]});
+
+  let browser;
+  let certErrorLoaded;
+
+  let prefChanged = TestUtils.waitForPrefChange(PREF_ENTERPRISE_ROOTS, value => value === true);
+  await BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+    gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser, UNKNOWN_ISSUER);
+    browser = gBrowser.selectedBrowser;
+    certErrorLoaded = BrowserTestUtils.waitForErrorPage(browser);
+  }, false);
+
+  await certErrorLoaded;
+  await prefChanged;
+
+  // The page will reload after the initial canary request, so we'll just
+  // wait until we're seeing the dedicated MitM page.
+  await TestUtils.waitForCondition(function() {
+    return ContentTask.spawn(browser, {}, () => {
+      return content.document.body.getAttribute("code") == "MOZILLA_PKIX_ERROR_MITM_DETECTED";
+    });
+  }, "Loads the MitM error page.");
+
+  ok(true, "Successfully loaded the MitM error page.");
+
+  ok(!Services.prefs.prefHasUserValue(PREF_ENTERPRISE_ROOTS), "Flipped the enterprise roots pref back");
+
+  BrowserTestUtils.removeTab(gBrowser.selectedTab);
+
+  Services.prefs.clearUserPref(PREF_MITM_CANARY_ISSUER);
+});
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -251,17 +251,17 @@ skip-if = true # Disabled due to the cli
 [browser_contentAreaClick.js]
 skip-if = e10s # Clicks in content don't go through contentAreaClick with e10s.
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_contentAltClick.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_contextmenu.js]
 subsuite = clipboard
 tags = fullscreen
-skip-if = toolkit == "gtk3" || verify # disabled on Linux due to bug 513558
+skip-if = toolkit == "gtk3" || verify || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1531590
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_contextmenu_input.js]
 skip-if = toolkit == "gtk3" || (os == "win" && processor == "aarch64") # disabled on Linux due to bug 513558, aarch64 due to 1533161
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_ctrlTab.js]
 # DO NOT ADD MORE TESTS HERE. USE A TOPICAL DIRECTORY INSTEAD.
 [browser_datachoices_notification.js]
 skip-if = !datareporting || (verify && !debug && (os == 'win'))
--- a/browser/components/extensions/test/browser/browser-common.ini
+++ b/browser/components/extensions/test/browser/browser-common.ini
@@ -179,17 +179,17 @@ skip-if = !e10s || !crashreporter # the 
 [browser_ext_sidebarAction_context.js]
 [browser_ext_sidebarAction_contextMenu.js]
 [browser_ext_sidebarAction_incognito.js]
 [browser_ext_sidebarAction_runtime.js]
 [browser_ext_sidebarAction_tabs.js]
 [browser_ext_sidebarAction_windows.js]
 [browser_ext_simple.js]
 [browser_ext_slow_script.js]
-skip-if = !e10s || debug || asan
+skip-if = !e10s || debug || asan || (os == "win" && processor == "aarch64") # windows10-aarch64 due to 1534857
 [browser_ext_tab_runtimeConnect.js]
 [browser_ext_tabs_attention.js]
 [browser_ext_tabs_audio.js]
 [browser_ext_tabs_captureTab.js]
 [browser_ext_tabs_captureVisibleTab.js]
 [browser_ext_tabs_create.js]
 skip-if = os == "linux" && debug && bits == 32 # Bug 1350189
 [browser_ext_tabs_create_url.js]
--- a/browser/components/search/test/browser/browser.ini
+++ b/browser/components/search/test/browser/browser.ini
@@ -18,17 +18,17 @@ support-files =
   webapi.html
 
 [browser_426329.js]
 [browser_483086.js]
 [browser_addEngine.js]
 [browser_amazon.js]
 [browser_bing.js]
 [browser_contextmenu.js]
-skip-if = verify
+skip-if = verify || (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1531590
 [browser_contextSearchTabPosition.js]
 skip-if = os == "mac" || (verify && debug && os == 'win') # bug 967013
 [browser_ddg.js]
 [browser_eBay.js]
 [browser_google.js]
 [browser_google_behavior.js]
 [browser_healthreport.js]
 skip-if = (verify && debug && (os == 'win' || os == 'linux'))
--- a/browser/config/mozconfigs/win64-aarch64/common-opt
+++ b/browser/config/mozconfigs/win64-aarch64/common-opt
@@ -15,8 +15,12 @@ ac_add_options --with-mozilla-api-keyfil
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 . $topsrcdir/build/win64-aarch64/mozconfig.vs-latest
 
 # Package js shell.
 export MOZ_PACKAGE_JSSHELL=1
+
+if test -n "$MOZ_ARTIFACT_TASK_WIN32_OPT"; then
+  ac_add_options --enable-eme=widevine
+fi
--- a/browser/extensions/formautofill/locales/en-US/formautofill.properties
+++ b/browser/extensions/formautofill/locales/en-US/formautofill.properties
@@ -75,17 +75,17 @@ phishingWarningMessage = Also autofills 
 phishingWarningMessage2 = Autofills %S
 # LOCALIZATION NOTE (insecureFieldWarningDescription): %S is brandShortName. This string is used in drop down
 # suggestion when users try to autofill credit card on an insecure website (without https).
 insecureFieldWarningDescription = %S has detected an insecure site. Form Autofill is temporarily disabled.
 # LOCALIZATION NOTE (clearFormBtnLabel2): Label for the button in the dropdown menu that used to clear the populated
 # form.
 clearFormBtnLabel2 = Clear Autofill Form
 
-autofillHeader = Forms & Autofill
+autofillHeader = Forms and Autofill
 # LOCALIZATION NOTE (autofillAddressesCheckbox): Label for the checkbox that enables autofilling addresses.
 autofillAddressesCheckbox = Autofill addresses
 # LOCALIZATION NOTE (learnMoreLabel): Label for the link that leads users to the Form Autofill SUMO page.
 learnMoreLabel = Learn more
 # LOCALIZATION NOTE (savedAddressesBtnLabel): Label for the button that opens a dialog that shows the
 # list of saved addresses.
 savedAddressesBtnLabel = Saved Addresses…
 # LOCALIZATION NOTE (autofillCreditCardsCheckbox): Label for the checkbox that enables autofilling credit cards.
--- a/browser/installer/Makefile.in
+++ b/browser/installer/Makefile.in
@@ -51,16 +51,20 @@ endif
 ifdef NSS_DISABLE_DBM
 DEFINES += -DNSS_DISABLE_DBM=1
 endif
 
 ifdef MOZ_ARTIFACT_BUILDS
 DEFINES += -DMOZ_ARTIFACT_BUILDS=1
 endif
 
+ifdef MOZ_EME_WIN32_ARTIFACT
+DEFINES += -DMOZ_EME_WIN32_ARTIFACT=1
+endif
+
 DEFINES += -DJAREXT=
 
 ifdef MOZ_ANGLE_RENDERER
 DEFINES += -DMOZ_ANGLE_RENDERER=$(MOZ_ANGLE_RENDERER)
 ifdef MOZ_D3DCOMPILER_VISTA_DLL
 DEFINES += -DMOZ_D3DCOMPILER_VISTA_DLL=$(MOZ_D3DCOMPILER_VISTA_DLL)
 endif
 endif
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -147,8 +147,12 @@ browser/chrome/browser/res/payments/form
 browser/features/formautofill@mozilla.org/chrome/content/autofillEditForms.js
 browser/chrome/browser/res/payments/formautofill/autofillEditForms.js
 # Bug 1451050 - Remote settings empty dumps (will be populated with data eventually)
 browser/defaults/settings/pinning/pins.json
 browser/defaults/settings/main/example.json
 # Bug 1463748 - Fork and pref-off the new error pages
 browser/chrome/browser/content/browser/aboutNetError-new.xhtml
 browser/chrome/browser/content/browser/aboutNetError.xhtml
+#ifdef MOZ_EME_WIN32_ARTIFACT
+gmp-clearkey/0.1/manifest.json
+i686/gmp-clearkey/0.1/manifest.json
+#endif
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -451,8 +451,23 @@ bin/libfreebl_32int64_3.so
 #ifdef XP_LINUX
 @RESPATH@/fix_linux_stack.py
 #endif
 #endif
 
 #ifdef PKG_LOCALE_MANIFEST
 #include @PKG_LOCALE_MANIFEST@
 #endif
+
+#ifdef MOZ_EME_WIN32_ARTIFACT
+i686/plugin-container.exe
+i686/xul.dll
+i686/nss3.dll
+i686/mozglue.dll
+i686/lgpllibs.dll
+i686/msvcp140.dll
+i686/vcruntime140.dll
+i686/gmp-clearkey/0.1/clearkey.dll
+[eme destdir="i686"]
+; We assume the file we generate locally is the same as what was in the win32
+; build, which, practically speaking, is the case.
+@BINPATH@/gmp-clearkey/0.1/manifest.json
+#endif
--- a/browser/locales/en-US/browser/preferences/preferences.ftl
+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
@@ -230,17 +230,17 @@ containers-remove-alert-msg =
 containers-remove-ok-button = Remove this Container
 containers-remove-cancel-button = Don’t remove this Container
 
 
 ## General Section - Language & Appearance
 
 language-and-appearance-header = Language and Appearance
 
-fonts-and-colors-header = Fonts & Colors
+fonts-and-colors-header = Fonts and Colors
 
 default-font = Default font
     .accesskey = D
 default-font-size = Size
     .accesskey = S
 
 advanced-fonts =
     .label = Advanced…
@@ -677,17 +677,17 @@ sync-tos-link = Terms of Service
 sync-fxa-privacy-notice = Privacy Notice
 
 ## Privacy Section
 
 privacy-header = Browser Privacy
 
 ## Privacy Section - Forms
 
-logins-header = Logins & Passwords
+logins-header = Logins and Passwords
 forms-ask-to-save-logins =
     .label = Ask to save logins and passwords for websites
     .accesskey = r
 forms-exceptions =
     .label = Exceptions…
     .accesskey = x
 forms-saved-logins =
     .label = Saved Logins…
@@ -717,17 +717,17 @@ history-remember-label = { -brand-short-
 
 history-remember-option-all =
     .label = Remember history
 history-remember-option-never =
     .label = Never remember history
 history-remember-option-custom =
     .label = Use custom settings for history
 
-history-remember-description = { -brand-short-name } will remember your browsing, download, form and search history.
+history-remember-description = { -brand-short-name } will remember your browsing, download, form, and search history.
 history-dontremember-description = { -brand-short-name } will use the same settings as private browsing, and will not remember any history as you browse the Web.
 
 history-private-browsing-permanent =
     .label = Always use private browsing mode
     .accesskey = p
 
 history-remember-browser-option =
     .label = Remember browsing and download history
@@ -753,17 +753,17 @@ history-clear-button =
 
 sitedata-header = Cookies and Site Data
 
 sitedata-total-size-calculating = Calculating site data and cache size…
 
 # Variables:
 #   $value (Number) - Value of the unit (for example: 4.6, 500)
 #   $unit (String) - Name of the unit (for example: "bytes", "KB")
-sitedata-total-size = Your stored cookies, site data and cache are currently using { $value } { $unit } of disk space.
+sitedata-total-size = Your stored cookies, site data, and cache are currently using { $value } { $unit } of disk space.
 
 sitedata-learn-more = Learn more
 
 sitedata-delete-on-close =
     .label = Delete cookies and site data when { -brand-short-name } is closed
     .accesskey = c
 
 sitedata-delete-on-close-private-browsing = In permanent private browsing mode, cookies and site data will always be cleared when { -brand-short-name } is closed.
--- a/browser/themes/shared/controlcenter/cryptominers-disabled.svg
+++ b/browser/themes/shared/controlcenter/cryptominers-disabled.svg
@@ -1,7 +1,7 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
   <path d="M14.71 1.29a1 1 0 0 0-1.42 0l-.7.71H9v-.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5V2H5a2 2 0 0 0-1.6.8L2.2 4.4A1 1 0 0 0 3 6h4v1.59l-5.71 5.7a1 1 0 0 0 0 1.42 1 1 0 0 0 1.42 0l12-12a1 1 0 0 0 0-1.42z"/>
   <path d="M7 14.5a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5V10l-2 2z"/>
 </svg>
--- a/browser/themes/shared/controlcenter/cryptominers.svg
+++ b/browser/themes/shared/controlcenter/cryptominers.svg
@@ -1,6 +1,6 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
   <path d="M13 2H9v-.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5V2H5a2 2 0 0 0-1.6.8L2.2 4.4A1 1 0 0 0 3 6h4v8.5a.5.5 0 0 0 .5.5h1a.5.5 0 0 0 .5-.5V6h4z"/>
 </svg>
--- a/browser/themes/shared/controlcenter/fingerprinters-disabled.svg
+++ b/browser/themes/shared/controlcenter/fingerprinters-disabled.svg
@@ -1,8 +1,8 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
   <path d="M14.71 1.29a1 1 0 0 0-1.42 0l-.56.57A7 7 0 0 0 1 7a1 1 0 0 0 2 0 5 5 0 0 1 5-5 5 5 0 0 1 3.31 1.28l-.7.7A4 4 0 0 0 8 3a4 4 0 0 0-4 4 2 2 0 0 1-2 2 1 1 0 0 0 0 2 3.86 3.86 0 0 0 2.33-.75l-3 3a.91.91 0 0 0-.08.13.82.82 0 0 0-.11.17 1.17 1.17 0 0 0-.06.2A.86.86 0 0 0 1 14a.61.61 0 0 0 0 .23.62.62 0 0 0 0 .13v.08a.76.76 0 0 0 .12.19s0 .06.06.09a1 1 0 0 0 1.42 0l12-12a1 1 0 0 0 .11-1.43zM6 7a2 2 0 0 1 2-2 1.94 1.94 0 0 1 1.18.41l-.72.72A.91.91 0 0 0 8 6a1 1 0 0 0-1 1 4.76 4.76 0 0 1-.06.65L5.12 9.47A4.1 4.1 0 0 0 6 7z"/>
   <path d="M9.68 9.32a8.06 8.06 0 0 1-1.42 2.48 11 11 0 0 0-1.15 1.75 1 1 0 0 0 .44 1.34A.93.93 0 0 0 8 15a1 1 0 0 0 .89-.55 9.74 9.74 0 0 1 1-1.44A8.84 8.84 0 0 0 12 7z"/>
   <path d="M12.91 6.09A5.5 5.5 0 0 1 13 7a8.24 8.24 0 0 1-1.14 4.28A5.75 5.75 0 0 0 11 14a1 1 0 0 0 2 0 3.91 3.91 0 0 1 .63-1.79A10.18 10.18 0 0 0 15 7a6.81 6.81 0 0 0-.48-2.52z"/>
 </svg>
--- a/browser/themes/shared/controlcenter/fingerprinters.svg
+++ b/browser/themes/shared/controlcenter/fingerprinters.svg
@@ -1,8 +1,8 @@
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16" fill="context-fill" fill-opacity="context-fill-opacity">
   <path d="M8 0a7 7 0 0 0-7 7 1 1 0 0 0 2 0 5 5 0 0 1 10 0 8.24 8.24 0 0 1-1.14 4.28A5.75 5.75 0 0 0 11 14a1 1 0 0 0 2 0 3.91 3.91 0 0 1 .63-1.79A10.18 10.18 0 0 0 15 7a7 7 0 0 0-7-7z"/>
   <path d="M8 3a4 4 0 0 0-4 4 2 2 0 0 1-2 2 1 1 0 0 0 0 2 4 4 0 0 0 4-4 2 2 0 0 1 4 0 6.88 6.88 0 0 1-1.74 4.8 11 11 0 0 0-1.15 1.75 1 1 0 0 0 .44 1.34A.93.93 0 0 0 8 15a1 1 0 0 0 .89-.55 9.74 9.74 0 0 1 1-1.44A8.84 8.84 0 0 0 12 7a4 4 0 0 0-4-4z"/>
   <path d="M8 6a1 1 0 0 0-1 1c0 4.21-5.26 6-5.32 6.05a1 1 0 0 0-.63 1.27A1 1 0 0 0 2 15a1.25 1.25 0 0 0 .32 0C2.59 14.86 9 12.66 9 7a1 1 0 0 0-1-1z"/>
 </svg>
--- a/browser/themes/shared/controlcenter/panel.inc.css
+++ b/browser/themes/shared/controlcenter/panel.inc.css
@@ -449,16 +449,18 @@ description#identity-popup-content-verif
 
 .identity-popup-content-blocking-list-state-label {
   -moz-box-flex: 1;
   text-align: end;
   margin-inline-start: 5px;
   margin-inline-end: 2px;
 }
 
+.identity-popup-fingerprintersView-icon,
+.identity-popup-cryptominersView-icon,
 .identity-popup-trackersView-icon,
 .identity-popup-cookiesView-icon {
   margin-inline-end: 10px;
   -moz-context-properties: fill, fill-opacity;
 }
 
 .identity-popup-trackersView-icon {
   list-style-image: url(chrome://browser/skin/controlcenter/trackers-disabled.svg);
--- a/build/macosx/cross-mozconfig.common
+++ b/build/macosx/cross-mozconfig.common
@@ -2,17 +2,17 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 MOZ_AUTOMATION_L10N_CHECK=0
 
 . "$topsrcdir/build/mozconfig.common"
 
 # cctools for ld, ar, and other related tools ; dsymutil for rust.
-mk_add_options "export PATH=$topsrcdir/cctools/bin:$topsrcdir/llvm-dsymutil/bin:$PATH"
+mk_add_options "export PATH=$topsrcdir/cctools/bin:$topsrcdir/binutils/bin:$topsrcdir/llvm-dsymutil/bin:$PATH"
 
 # ld needs libLTO.so from llvm
 mk_add_options "export LD_LIBRARY_PATH=$topsrcdir/clang/lib"
 
 # This SDK was copied from a local XCode install and uploaded to tooltool.
 # Generate the tarball by running this command with the proper SDK version:
 #   sdk_path=$(xcrun --sdk macosx10.12 --show-sdk-path)
 #   tar -C $(dirname ${sdk_path}) -cHjf /tmp/$(basename ${sdk_path}).tar.bz2 $(basename ${sdk_path})
--- a/config/baseconfig.mk
+++ b/config/baseconfig.mk
@@ -37,17 +37,17 @@ ifeq (a,$(firstword a$(subst /, ,$(srcdi
 $(error MSYS-style srcdir are not supported for Windows builds.)
 endif
 endif
 endif # WINNT
 
 ifndef INCLUDED_AUTOCONF_MK
 default::
 else
-TIERS := $(if $(MOZ_ARTIFACT_BUILDS),artifact )pre-export export $(if $(COMPILE_ENVIRONMENT),compile )misc libs tools$(if $(filter check recurse_check,$(MAKECMDGOALS)), check)
+TIERS := $(if $(MOZ_ARTIFACT_BUILDS),artifact )$(if $(MOZ_EME_WIN32_ARTIFACT),win32-artifact )pre-export export $(if $(COMPILE_ENVIRONMENT),compile )misc libs tools$(if $(filter check recurse_check,$(MAKECMDGOALS)), check)
 endif
 
 # These defines are used to support the twin-topsrcdir model for comm-central.
 ifdef MOZILLA_SRCDIR
   MOZILLA_DIR = $(MOZILLA_SRCDIR)
 else
   MOZILLA_DIR = $(topsrcdir)
 endif
--- a/devtools/client/debugger/new/src/actions/sources/tests/loadSource.spec.js
+++ b/devtools/client/debugger/new/src/actions/sources/tests/loadSource.spec.js
@@ -2,16 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import {
   actions,
   selectors,
+  watchForState,
   createStore,
   makeSource
 } from "../../../utils/test-head";
 import { sourceThreadClient } from "../../tests/helpers/threadClient.js";
 
 describe("loadSourceText", () => {
   it("should load source text", async () => {
     const store = createStore(sourceThreadClient);
@@ -112,23 +113,30 @@ describe("loadSourceText", () => {
 
     await dispatch(actions.loadSourceText(prevSource));
     const curSource = selectors.getSource(getState(), "foo1");
 
     expect(prevSource === curSource).toBeTruthy();
   });
 
   it("should indicate a loading source", async () => {
-    const { dispatch, getState } = createStore(sourceThreadClient);
+    const store = createStore(sourceThreadClient);
+    const { dispatch } = store;
+
+    const source = makeSource("foo2");
+    await dispatch(actions.newSource(source));
 
-    // Don't block on this so we can check the loading state.
-    const source = makeSource("foo1");
-    dispatch(actions.loadSourceText(source));
-    const fooSource = selectors.getSource(getState(), "foo1");
-    expect(fooSource && fooSource.loadedState).toEqual("loading");
+    const wasLoading = watchForState(store, state => {
+      const fooSource = selectors.getSource(state, "foo2");
+      return fooSource && fooSource.loadedState === "loading";
+    });
+
+    await dispatch(actions.loadSourceText(source));
+
+    expect(wasLoading()).toBe(true);
   });
 
   it("should indicate an errored source text", async () => {
     const { dispatch, getState } = createStore(sourceThreadClient);
 
     const source = makeSource("bad-id");
     await dispatch(actions.newSource(source));
     await dispatch(actions.loadSourceText(source));
--- a/devtools/client/debugger/new/src/client/index.js
+++ b/devtools/client/debugger/new/src/client/index.js
@@ -2,17 +2,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
 
 // @flow
 
 import * as firefox from "./firefox";
 import * as chrome from "./chrome";
 
-import { prefs, asyncStore } from "../utils/prefs";
+import { prefs, asyncStore, verifyPrefSchema } from "../utils/prefs";
 import { setupHelper } from "../utils/dbg";
 
 import {
   bootstrapApp,
   bootstrapStore,
   bootstrapWorkers
 } from "../utils/bootstrap";
 import { initialBreakpointsState } from "../reducers/breakpoints";
@@ -72,16 +72,18 @@ export async function onConnect(
   sourceMaps: Object,
   panel: Panel
 ) {
   // NOTE: the landing page does not connect to a JS process
   if (!connection) {
     return;
   }
 
+  verifyPrefSchema();
+
   const client = getClient(connection);
   const commands = client.clientCommands;
 
   const initialState = await loadInitialState();
 
   const { store, actions, selectors } = bootstrapStore(
     commands,
     sourceMaps,
--- a/devtools/client/debugger/new/src/reducers/sources.js
+++ b/devtools/client/debugger/new/src/reducers/sources.js
@@ -174,16 +174,25 @@ function update(
 }
 
 /*
  * Update a source when its state changes
  * e.g. the text was loaded, it was blackboxed
  */
 function updateSource(state: SourcesState, source: Object) {
   const existingSource = state.sources[source.id];
+
+  // If there is no existing version of the source, it means that we probably
+  // ended up here as a result of an async action, and the sources were cleared
+  // between the action starting and the source being updated.
+  if (!existingSource) {
+    // TODO: We may want to consider throwing here once we have a better
+    // handle on async action flow control.
+    return state;
+  }
   return {
     ...state,
     sources: {
       ...state.sources,
       [source.id]: { ...existingSource, ...source }
     }
   };
 }
--- a/devtools/client/debugger/new/src/utils/prefs.js
+++ b/devtools/client/debugger/new/src/utils/prefs.js
@@ -1,20 +1,20 @@
 /* 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/>. */
 
 // @flow
 
 import { PrefsHelper } from "devtools-modules";
-import { isDevelopment, isTesting } from "devtools-environment";
+import { isDevelopment } from "devtools-environment";
 import Services from "devtools-services";
 import { asyncStoreHelper } from "./asyncStoreHelper";
 
-const prefsSchemaVersion = "1.0.8";
+const prefsSchemaVersion = "1.0.9";
 const pref = Services.pref;
 
 if (isDevelopment()) {
   pref("devtools.debugger.logging", false);
   pref("devtools.debugger.alphabetize-outline", false);
   pref("devtools.debugger.auto-pretty-print", false);
   pref("devtools.source-map.client-service.enabled", true);
   pref("devtools.chrome.enabled", false);
@@ -127,15 +127,17 @@ export const features = new PrefsHelper(
 
 export const asyncStore = asyncStoreHelper("debugger", {
   pendingBreakpoints: ["pending-breakpoints", {}],
   tabs: ["tabs", []],
   xhrBreakpoints: ["xhr-breakpoints", []],
   eventListenerBreakpoints: ["event-listener-breakpoints", []]
 });
 
-if (!isTesting && prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {
-  // clear pending Breakpoints
-  asyncStore.pendingBreakpoints = {};
-  asyncStore.tabs = [];
-  asyncStore.xhrBreakpoints = [];
-  prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion;
+export function verifyPrefSchema() {
+  if (prefs.debuggerPrefsSchemaVersion !== prefsSchemaVersion) {
+    // clear pending Breakpoints
+    asyncStore.pendingBreakpoints = {};
+    asyncStore.tabs = [];
+    asyncStore.xhrBreakpoints = [];
+    prefs.debuggerPrefsSchemaVersion = prefsSchemaVersion;
+  }
 }
--- a/devtools/client/debugger/new/src/utils/test-head.js
+++ b/devtools/client/debugger/new/src/utils/test-head.js
@@ -99,17 +99,18 @@ function makeSource(name: string, props:
     ]
   };
   return (rv: any);
 }
 
 function makeOriginalSource(name: string, props?: Object): Source {
   const rv = {
     ...makeSourceRaw(name, props),
-    id: `${name}/originalSource`
+    id: `${name}/originalSource`,
+    actors: []
   };
   return (rv: any);
 }
 
 function makeFuncLocation(startLine, endLine) {
   if (!endLine) {
     endLine = startLine + 1;
   }
@@ -153,26 +154,54 @@ function waitForState(store: any, predic
       if (ret) {
         unsubscribe();
         resolve(ret);
       }
     });
   });
 }
 
+function watchForState(store: any, predicate: any): () => boolean {
+  let sawState = false;
+  const checkState = function() {
+    if (!sawState && predicate(store.getState())) {
+      sawState = true;
+    }
+    return sawState;
+  };
+
+  let unsubscribe;
+  if (!checkState()) {
+    unsubscribe = store.subscribe(() => {
+      if (checkState()) {
+        unsubscribe();
+      }
+    });
+  }
+
+  return function read() {
+    if (unsubscribe) {
+      unsubscribe();
+    }
+
+    return sawState;
+  };
+}
+
 function getTelemetryEvents(eventName: string) {
   return window.dbg._telemetry.events[eventName] || [];
 }
 
 export {
   actions,
   selectors,
   reducers,
   createStore,
   commonLog,
   getTelemetryEvents,
   makeFrame,
   makeSource,
   makeOriginalSource,
   makeSymbolDeclaration,
   waitForState,
+  watchForState,
   getHistory
 };
--- a/devtools/client/inspector/markup/test/browser.ini
+++ b/devtools/client/inspector/markup/test/browser.ini
@@ -101,17 +101,17 @@ skip-if = (os == 'win' && processor == '
 [browser_markup_anonymous_03.js]
 skip-if = (os == 'win' && processor == 'aarch64') # bug 1531584
 [browser_markup_anonymous_04.js]
 skip-if = (os == 'win' && processor == 'aarch64') # bug 1531584
 [browser_markup_copy_html.js]
 subsuite = clipboard
 [browser_markup_copy_image_data.js]
 subsuite = clipboard
-skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
+skip-if = (os == 'linux' && bits == 32 && debug) || (os == "win" && processor == "aarch64") # bug 1328915, disable linux32 debug devtools for timeouts, disabled on aarch64 due to 1531598
 [browser_markup_css_completion_style_attribute_01.js]
 [browser_markup_css_completion_style_attribute_02.js]
 [browser_markup_css_completion_style_attribute_03.js]
 [browser_markup_display_node_01.js]
 [browser_markup_display_node_02.js]
 [browser_markup_dragdrop_autoscroll_01.js]
 [browser_markup_dragdrop_autoscroll_02.js]
 [browser_markup_dragdrop_distance.js]
@@ -153,17 +153,17 @@ skip-if = true # Bug 1177550
 [browser_markup_grid_display_badge_01.js]
 [browser_markup_grid_display_badge_02.js]
 [browser_markup_grid_display_badge_telemetry.js]
 [browser_markup_links_01.js]
 [browser_markup_links_02.js]
 [browser_markup_links_03.js]
 [browser_markup_links_04.js]
 subsuite = clipboard
-skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
+skip-if = (os == 'linux' && bits == 32 && debug) || (os == "win" && processor == "aarch64") # bug 1328915, disable linux32 debug devtools for timeouts, aarch64 due to 1531598
 [browser_markup_links_05.js]
 [browser_markup_links_06.js]
 [browser_markup_links_07.js]
 [browser_markup_load_01.js]
 skip-if = verify
 [browser_markup_html_edit_01.js]
 [browser_markup_html_edit_02.js]
 [browser_markup_html_edit_03.js]
--- a/devtools/client/inspector/test/browser.ini
+++ b/devtools/client/inspector/test/browser.ini
@@ -146,17 +146,17 @@ skip-if = (e10s && debug) # Bug 1250058 
 [browser_inspector_inspect_node_contextmenu.js]
 [browser_inspector_invalidate.js]
 [browser_inspector_keyboard-shortcuts-copy-outerhtml.js]
 subsuite = clipboard
 skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
 [browser_inspector_keyboard-shortcuts.js]
 [browser_inspector_menu-01-sensitivity.js]
 subsuite = clipboard
-skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
+skip-if = (os == 'linux' && bits == 32 && debug) || (os == "win" && processor == "aarch64") # bug 1328915, disable linux32 debug devtools for timeouts, aarch64 due to 1531598
 [browser_inspector_menu-03-paste-items.js]
 subsuite = clipboard
 skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
 [browser_inspector_menu-03-paste-items-svg.js]
 subsuite = clipboard
 skip-if = (os == 'linux' && bits == 32 && debug) # bug 1328915, disable linux32 debug devtools for timeouts
 [browser_inspector_menu-04-use-in-console.js]
 [browser_inspector_menu-05-attribute-items.js]
--- a/devtools/client/webconsole/test/mochitest/browser.ini
+++ b/devtools/client/webconsole/test/mochitest/browser.ini
@@ -187,53 +187,58 @@ skip-if = verify
 [browser_jsterm_completion_bracket_cached_results.js]
 [browser_jsterm_completion_bracket.js]
 [browser_jsterm_completion_case_sensitivity.js]
 [browser_jsterm_completion_dollar_underscore.js]
 [browser_jsterm_completion_dollar_zero.js]
 [browser_jsterm_completion.js]
 [browser_jsterm_content_defined_helpers.js]
 [browser_jsterm_context_menu_labels.js]
+skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1531571
 [browser_jsterm_copy_command.js]
 [browser_jsterm_ctrl_a_select_all.js]
 [browser_jsterm_ctrl_key_nav.js]
 skip-if = os != 'mac' # The tested ctrl+key shortcuts are OSX only
 [browser_jsterm_document_no_xray.js]
 [browser_jsterm_editor_execute.js]
 [browser_jsterm_error_docs.js]
 [browser_jsterm_error_outside_valid_range.js]
 [browser_jsterm_focus_reload.js]
 [browser_jsterm_helper_clear.js]
 [browser_jsterm_helper_dollar_dollar.js]
+skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1535082
 [browser_jsterm_helper_dollar_x.js]
+skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1531572
 [browser_jsterm_helper_dollar.js]
 [browser_jsterm_helper_help.js]
 [browser_jsterm_helper_keys_values.js]
 [browser_jsterm_helper_pprint.js]
 [browser_jsterm_hide_when_devtools_chrome_enabled_false.js]
 [browser_jsterm_history.js]
 [browser_jsterm_history_arrow_keys.js]
 [browser_jsterm_history_nav.js]
 [browser_jsterm_history_persist.js]
 [browser_jsterm_inspect.js]
 [browser_jsterm_instance_of.js]
 [browser_jsterm_middle_click_paste.js]
 subsuite = clipboard
 [browser_jsterm_multiline.js]
 [browser_jsterm_no_input_and_tab_key_pressed.js]
+skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1531573
 [browser_jsterm_null_undefined.js]
 [browser_jsterm_popup_close_on_tab_switch.js]
 [browser_jsterm_screenshot_command_clipboard.js]
 subsuite = clipboard
 [browser_jsterm_screenshot_command_user.js]
 subsuite = clipboard
 [browser_jsterm_screenshot_command_file.js]
 [browser_jsterm_selfxss.js]
 subsuite = clipboard
 [browser_jsterm_syntax_highlight_output.js]
+skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1531574
 [browser_webconsole_allow_mixedcontent_securityerrors.js]
 tags = mcb
 [browser_webconsole_batching.js]
 [browser_webconsole_block_mixedcontent_securityerrors.js]
 tags = mcb
 [browser_webconsole_cached_messages.js]
 [browser_webconsole_cd_iframe.js]
 [browser_webconsole_certificate_messages.js]
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5620,17 +5620,44 @@ nsresult nsDocShell::SetCurScrollPosEx(i
   NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
 
   nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
   if (sf->GetScrollStyles().mScrollBehavior ==
       NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
     scrollMode = nsIScrollableFrame::SMOOTH_MSD;
   }
 
-  sf->ScrollTo(nsPoint(aCurHorizontalPos, aCurVerticalPos), scrollMode);
+  nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
+  sf->ScrollTo(targetPos, scrollMode);
+
+  // Set the visual viewport offset as well.
+
+  nsCOMPtr<nsIPresShell> shell = GetPresShell();
+  NS_ENSURE_TRUE(shell, NS_ERROR_FAILURE);
+
+  nsPresContext* presContext = shell->GetPresContext();
+  NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
+
+  // Only the root content document can have a distinct visual viewport offset.
+  if (!presContext->IsRootContentDocument()) {
+    return NS_OK;
+  }
+
+  // Not on a platform with a distinct visual viewport - don't bother setting
+  // the visual viewport offset.
+  if (!shell->IsVisualViewportSizeSet()) {
+    return NS_OK;
+  }
+
+  // TODO: If scrollMode == SMOOTH_MSD, this will effectively override that
+  // and jump to the target position instantly. A proper solution here would
+  // involve giving nsIScrollableFrame a visual viewport smooth scrolling API.
+  shell->SetPendingVisualScrollUpdate(targetPos,
+                                      layers::FrameMetrics::eMainThread);
+
   return NS_OK;
 }
 
 //*****************************************************************************
 // nsDocShell::nsIScrollable
 //*****************************************************************************
 
 NS_IMETHODIMP
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -2370,17 +2370,17 @@ void nsGlobalWindowOuter::ClearStatus() 
 
 void nsGlobalWindowOuter::SetDocShell(nsDocShell* aDocShell) {
   MOZ_ASSERT(aDocShell);
 
   if (aDocShell == mDocShell) {
     return;
   }
 
-  mDocShell = aDocShell;  // Weak Reference
+  mDocShell = aDocShell;
   mBrowsingContext = aDocShell->GetBrowsingContext();
 
   nsCOMPtr<nsPIDOMWindowOuter> parentWindow = GetScriptableParentOrNull();
   MOZ_RELEASE_ASSERT(!parentWindow || !mTabGroup ||
                      mTabGroup ==
                          nsGlobalWindowOuter::Cast(parentWindow)->mTabGroup);
 
   mTopLevelOuterContentWindow =
@@ -2463,17 +2463,17 @@ void nsGlobalWindowOuter::DetachFromDocS
     // param. We also trigger a full GC for chrome windows.
     nsJSContext::PokeGC(JS::GCReason::SET_DOC_SHELL,
                         (mTopLevelOuterContentWindow || mIsChrome)
                             ? nullptr
                             : GetWrapperPreserveColor());
     mContext = nullptr;
   }
 
-  mDocShell = nullptr;  // Weak Reference
+  mDocShell = nullptr;
 
   if (mFrames) {
     mFrames->SetDocShell(nullptr);
   }
 
   MaybeForgiveSpamCount();
   CleanUp();
 }
@@ -7801,17 +7801,16 @@ mozilla::dom::DocGroup* nsPIDOMWindowOut
   if (doc) {
     return doc->GetDocGroup();
   }
   return nullptr;
 }
 
 nsPIDOMWindowOuter::nsPIDOMWindowOuter(uint64_t aWindowID)
     : mFrameElement(nullptr),
-      mDocShell(nullptr),
       mModalStateDepth(0),
       mIsActive(false),
       mIsBackground(false),
       mMediaSuspend(
           Preferences::GetBool("media.block-autoplay-until-in-foreground", true)
               ? nsISuspendedTypes::SUSPENDED_BLOCK
               : nsISuspendedTypes::NONE_SUSPENDED),
       mAudioMuted(false),
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -3631,81 +3631,41 @@ void EventStateManager::SetPresContext(n
 }
 
 void EventStateManager::ClearFrameRefs(nsIFrame* aFrame) {
   if (aFrame && aFrame == mCurrentTarget) {
     mCurrentTargetContent = aFrame->GetContent();
   }
 }
 
-static Maybe<gfx::IntPoint> ComputeHotspot(const nsIFrame::Cursor& aCursor) {
-  if (!aCursor.mContainer) {
-    return {};
-  }
-
-  // css3-ui says to use the CSS-specified hotspot if present,
-  // otherwise use the intrinsic hotspot, otherwise use the top left
-  // corner.
-  uint32_t hotspotX, hotspotY;
-  if (aCursor.mHaveHotspot) {
-    int32_t imgWidth, imgHeight;
-    aCursor.mContainer->GetWidth(&imgWidth);
-    aCursor.mContainer->GetHeight(&imgHeight);
-
-    // XXX std::max(NS_lround(x), 0)?
-    hotspotX = aCursor.mHotspotX > 0.0f ? uint32_t(aCursor.mHotspotX + 0.5f)
-                                        : uint32_t(0);
-    if (hotspotX >= uint32_t(imgWidth)) hotspotX = imgWidth - 1;
-    hotspotY = aCursor.mHotspotY > 0.0f ? uint32_t(aCursor.mHotspotY + 0.5f)
-                                        : uint32_t(0);
-    if (hotspotY >= uint32_t(imgHeight)) hotspotY = imgHeight - 1;
-  } else {
-    hotspotX = 0;
-    hotspotY = 0;
-    nsCOMPtr<nsIProperties> props(do_QueryInterface(aCursor.mContainer));
-    if (props) {
-      nsCOMPtr<nsISupportsPRUint32> hotspotXWrap, hotspotYWrap;
-
-      props->Get("hotspotX", NS_GET_IID(nsISupportsPRUint32),
-                 getter_AddRefs(hotspotXWrap));
-      props->Get("hotspotY", NS_GET_IID(nsISupportsPRUint32),
-                 getter_AddRefs(hotspotYWrap));
-
-      if (hotspotXWrap) hotspotXWrap->GetData(&hotspotX);
-      if (hotspotYWrap) hotspotYWrap->GetData(&hotspotY);
-    }
-  }
-
-  return Some(gfx::IntPoint{hotspotX, hotspotY});
-}
+struct CursorImage {
+  gfx::IntPoint mHotspot;
+  nsCOMPtr<imgIContainer> mContainer;
+  bool mEarlierCursorLoading = false;
+};
 
 // Given the event that we're processing, and the computed cursor and hotspot,
 // determine whether the custom CSS cursor should be blocked (that is, not
 // honored).
 //
 // We will not honor it all of the following are true:
 //
 //  * layout.cursor.block.enabled is true.
 //  * the size of the custom cursor is bigger than layout.cursor.block.max-size.
 //  * the bounds of the cursor would end up outside of the viewport of the
 //    top-level content document.
 //
 // This is done in order to prevent hijacking the cursor, see bug 1445844 and
 // co.
 static bool ShouldBlockCustomCursor(nsPresContext* aPresContext,
                                     WidgetEvent* aEvent,
-                                    const nsIFrame::Cursor& aCursor,
-                                    const Maybe<gfx::IntPoint>& aHotspot) {
+                                    const CursorImage& aCursor) {
   if (!StaticPrefs::layout_cursor_block_enabled()) {
     return false;
   }
-  if (!aCursor.mContainer) {
-    return false;
-  }
-  MOZ_ASSERT(aHotspot);
 
   int32_t width = 0;
   int32_t height = 0;
   aCursor.mContainer->GetWidth(&width);
   aCursor.mContainer->GetHeight(&height);
 
   int32_t maxSize = StaticPrefs::layout_cursor_block_max_size();
 
@@ -3723,72 +3683,154 @@ static bool ShouldBlockCustomCursor(nsPr
   if (!topLevel) {
     return false;
   }
 
   nsPoint point = nsLayoutUtils::GetEventCoordinatesRelativeTo(
       aEvent, topLevel->PresShell()->GetRootFrame());
 
   nsSize size(CSSPixel::ToAppUnits(width), CSSPixel::ToAppUnits(height));
-  nsPoint hotspot(CSSPixel::ToAppUnits(aHotspot->x),
-                  CSSPixel::ToAppUnits(aHotspot->y));
+  nsPoint hotspot(CSSPixel::ToAppUnits(aCursor.mHotspot.x),
+                  CSSPixel::ToAppUnits(aCursor.mHotspot.y));
 
   nsRect cursorRect(point - hotspot, size);
   return !topLevel->GetVisibleArea().Contains(cursorRect);
 }
 
+static gfx::IntPoint ComputeHotspot(imgIContainer* aContainer,
+                                    const Maybe<gfx::Point>& aHotspot) {
+  MOZ_ASSERT(aContainer);
+  // css3-ui says to use the CSS-specified hotspot if present,
+  // otherwise use the intrinsic hotspot, otherwise use the top left
+  // corner.
+  uint32_t hotspotX, hotspotY;
+  if (aHotspot) {
+    int32_t imgWidth, imgHeight;
+    aContainer->GetWidth(&imgWidth);
+    aContainer->GetHeight(&imgHeight);
+
+    // XXX std::max(NS_lround(x), 0)?
+    hotspotX = aHotspot->x > 0.0f ? uint32_t(aHotspot->x + 0.5f) : uint32_t(0);
+    if (hotspotX >= uint32_t(imgWidth)) hotspotX = imgWidth - 1;
+    hotspotY = aHotspot->y > 0.0f ? uint32_t(aHotspot->y + 0.5f) : uint32_t(0);
+    if (hotspotY >= uint32_t(imgHeight)) hotspotY = imgHeight - 1;
+  } else {
+    hotspotX = 0;
+    hotspotY = 0;
+    nsCOMPtr<nsIProperties> props(do_QueryInterface(aContainer));
+    if (props) {
+      nsCOMPtr<nsISupportsPRUint32> hotspotXWrap, hotspotYWrap;
+
+      props->Get("hotspotX", NS_GET_IID(nsISupportsPRUint32),
+                 getter_AddRefs(hotspotXWrap));
+      props->Get("hotspotY", NS_GET_IID(nsISupportsPRUint32),
+                 getter_AddRefs(hotspotYWrap));
+
+      if (hotspotXWrap) hotspotXWrap->GetData(&hotspotX);
+      if (hotspotYWrap) hotspotYWrap->GetData(&hotspotY);
+    }
+  }
+  return {hotspotX, hotspotY};
+}
+
+static CursorImage ComputeCustomCursor(nsPresContext* aPresContext,
+                                       WidgetEvent* aEvent,
+                                       const nsIFrame& aFrame,
+                                       const nsIFrame::Cursor& aCursor) {
+  if (aCursor.mAllowCustomCursor == nsIFrame::AllowCustomCursorImage::No) {
+    return {};
+  }
+  const ComputedStyle& style =
+      aCursor.mStyle ? *aCursor.mStyle : *aFrame.Style();
+
+  // If we are falling back because any cursor before us is loading, let the
+  // consumer know.
+  bool loading = false;
+  for (const nsCursorImage& image : style.StyleUI()->mCursorImages) {
+    uint32_t status;
+    imgRequestProxy* req = image.GetImage();
+    if (!req || NS_FAILED(req->GetImageStatus(&status))) {
+      continue;
+    }
+    if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
+      loading = true;
+      continue;
+    }
+    if (status & imgIRequest::STATUS_ERROR) {
+      continue;
+    }
+    nsCOMPtr<imgIContainer> container;
+    req->GetImage(getter_AddRefs(container));
+    if (!container) {
+      continue;
+    }
+    Maybe<gfx::Point> specifiedHotspot =
+        image.mHaveHotspot ? Some(gfx::Point{image.mHotspotX, image.mHotspotY})
+                           : Nothing();
+    gfx::IntPoint hotspot = ComputeHotspot(container, specifiedHotspot);
+    CursorImage result{hotspot, std::move(container), loading};
+    if (ShouldBlockCustomCursor(aPresContext, aEvent, result)) {
+      continue;
+    }
+    // This is the one we want!
+    return result;
+  }
+  return {{}, nullptr, loading};
+}
+
 void EventStateManager::UpdateCursor(nsPresContext* aPresContext,
                                      WidgetEvent* aEvent,
                                      nsIFrame* aTargetFrame,
                                      nsEventStatus* aStatus) {
   if (aTargetFrame && IsRemoteTarget(aTargetFrame->GetContent())) {
     return;
   }
 
   auto cursor = StyleCursorKind::Default;
-  imgIContainer* container = nullptr;
+  nsCOMPtr<imgIContainer> container;
   Maybe<gfx::IntPoint> hotspot;
 
   // If cursor is locked just use the locked one
   if (mLockCursor != kInvalidCursorKind) {
     cursor = mLockCursor;
   }
   // If not locked, look for correct cursor
   else if (aTargetFrame) {
-    nsIFrame::Cursor framecursor;
     nsPoint pt =
         nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, aTargetFrame);
+    Maybe<nsIFrame::Cursor> framecursor = aTargetFrame->GetCursor(pt);
     // Avoid setting cursor when the mouse is over a windowless plugin.
-    if (NS_FAILED(aTargetFrame->GetCursor(pt, framecursor))) {
+    if (!framecursor) {
       if (XRE_IsContentProcess()) {
         mLastFrameConsumedSetCursor = true;
       }
       return;
     }
     // Make sure cursors get reset after the mouse leaves a
     // windowless plugin frame.
     if (mLastFrameConsumedSetCursor) {
       ClearCachedWidgetCursor(aTargetFrame);
       mLastFrameConsumedSetCursor = false;
     }
+
+    CursorImage customCursor =
+        ComputeCustomCursor(aPresContext, aEvent, *aTargetFrame, *framecursor);
+
     // If the current cursor is from the same frame, and it is now
     // loading some new image for the cursor, we should wait for a
     // while rather than taking its fallback cursor directly.
-    if (framecursor.mLoading && gLastCursorSourceFrame == aTargetFrame &&
+    if (customCursor.mEarlierCursorLoading &&
+        gLastCursorSourceFrame == aTargetFrame &&
         TimeStamp::NowLoRes() - gLastCursorUpdateTime <
             TimeDuration::FromMilliseconds(kCursorLoadingTimeout)) {
       return;
     }
-    cursor = framecursor.mCursor;
-    container = framecursor.mContainer;
-    hotspot = ComputeHotspot(framecursor);
-
-    if (ShouldBlockCustomCursor(aPresContext, aEvent, framecursor, hotspot)) {
-      container = nullptr;
-    }
+    cursor = framecursor->mCursor;
+    container = customCursor.mContainer.forget();
+    hotspot = Some(customCursor.mHotspot);
   }
 
   if (nsContentUtils::UseActivityCursor()) {
     // Check whether or not to show the busy cursor
     nsCOMPtr<nsIDocShell> docShell(aPresContext->GetDocShell());
     if (!docShell) return;
     auto busyFlags = docShell->GetBusyFlags();
 
--- a/dom/media/PeerConnection.jsm
+++ b/dom/media/PeerConnection.jsm
@@ -1532,20 +1532,36 @@ class RTCPeerConnection {
     if (state != this._iceConnectionState) {
       this._iceConnectionState = state;
       _globalPCList.notifyLifecycleObservers(this, "iceconnectionstatechange");
       this.dispatchEvent(new this._win.Event("iceconnectionstatechange"));
     }
   }
 
   getStats(selector, onSucc, onErr) {
+    if (selector !== null) {
+      let matchingSenders =
+        this.getSenders().filter(s => s.track === selector);
+      let matchingReceivers =
+        this.getReceivers().filter(r => r.track === selector);
+
+      if (matchingSenders.length + matchingReceivers.length != 1) {
+        throw new this._win.DOMException(
+            "track must be associated with a unique sender or receiver, but "
+            + " is associated with " + matchingSenders.length
+            + " senders and " + matchingReceivers.length + " receivers.",
+            "InvalidAccessError");
+      }
+    }
+
     if (this._iceConnectionState === "completed" ||
         this._iceConnectionState === "connected") {
       this._pcTelemetry.recordGetStats();
     }
+
     return this._auto(onSucc, onErr, () => this._getStats(selector));
   }
 
   async _getStats(selector) {
     // getStats is allowed even in closed state.
     return this._chain(() => new Promise((resolve, reject) => {
       this._onGetStatsSuccess = resolve;
       this._onGetStatsFailure = reject;
--- a/dom/media/gtest/TestGroupId.cpp
+++ b/dom/media/gtest/TestGroupId.cpp
@@ -9,16 +9,17 @@
 #include "gtest/gtest-printers.h"
 #include "gtest/gtest.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/UniquePtr.h"
 #include "nsTArray.h"
 #include "webrtc/MediaEngineSource.h"
 
 using ::testing::Return;
+using namespace mozilla;
 
 void PrintTo(const nsString& aValue, ::std::ostream* aStream) {
   NS_ConvertUTF16toUTF8 str(aValue);
   (*aStream) << str.get();
 }
 void PrintTo(const nsCString& aValue, ::std::ostream* aStream) {
   (*aStream) << aValue.get();
 }
--- a/dom/media/systemservices/moz.build
+++ b/dom/media/systemservices/moz.build
@@ -43,22 +43,16 @@ if CONFIG['OS_TARGET'] == 'Android':
     UNIFIED_SOURCES += [
         'OpenSLESProvider.cpp',
     ]
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
   UNIFIED_SOURCES += ['OSXRunLoopSingleton.cpp']
   EXPORTS += ['OSXRunLoopSingleton.h']
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary workaround to enable building with VS2015.
-    # media\webrtc\trunk\webrtc/base/criticalsection.h(59): warning C4312:
-    # 'reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size
-    CXXFLAGS += ['-wd4312']
-
 EXPORTS.mozilla += ['ShmemPool.h',]
 
 EXPORTS.mozilla.media += ['CamerasTypes.h',
                           'DeviceChangeCallback.h',
                           'MediaChild.h',
                           'MediaParent.h',
                           'MediaSystemResourceClient.h',
                           'MediaSystemResourceManager.h',
--- a/dom/media/webrtc/moz.build
+++ b/dom/media/webrtc/moz.build
@@ -83,15 +83,8 @@ include('/ipc/chromium/chromium-config.m
 #    android API types
 CXXFLAGS += [
     '-Wno-error=attributes',
     '-Wno-error=shadow',
 ]
 
 DEFINES['TRACING'] = True
 FINAL_LIBRARY = 'xul'
-
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    CXXFLAGS += [
-        '-wd4275', # non dll-interface class used as base for dll-interface class
-        '-wd4312', # This is intended as a temporary hack to support building with VS2015
-                   # 'reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size
-    ]
--- a/dom/plugins/ipc/moz.build
+++ b/dom/plugins/ipc/moz.build
@@ -142,16 +142,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gtk3
 else:
     # Force build against gtk+2 for struct offsets and such.
     CXXFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
-
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary hack to support building with VS2015.
-    # conversion from 'X' to 'Y' requires a narrowing conversion
-    CXXFLAGS += ['-wd4838']
-
-    # 'type cast': conversion from 'unsigned int' to 'HIMC' of greater size
-    CXXFLAGS += ['-wd4312']
--- a/dom/plugins/test/testplugin/testplugin.mozbuild
+++ b/dom/plugins/test/testplugin/testplugin.mozbuild
@@ -50,21 +50,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gtk3':
     CXXFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
     CFLAGS += CONFIG['MOZ_GTK2_CFLAGS']
     OS_LIBS += CONFIG['MOZ_GTK2_LIBS']
     OS_LIBS += CONFIG['XLDFLAGS']
     OS_LIBS += CONFIG['XLIBS']
     OS_LIBS += CONFIG['XEXT_LIBS']
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary hack to support building with VS2015.
-    # conversion from 'X' to 'Y' requires a narrowing conversion
-    CXXFLAGS += ['-wd4838']
-
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
     FINAL_TARGET = 'dist/plugins/%s.plugin/Contents/MacOS' % cocoa_name
     OBJDIR_FILES.dist.plugins['%s.plugin' % cocoa_name].Contents += ['%s/Info.plist' % relative_path]
 else:
     FINAL_TARGET = 'dist/plugins'
 
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/dom/tests/browser/browser.ini
+++ b/dom/tests/browser/browser.ini
@@ -49,17 +49,17 @@ skip-if = e10s
 [browser_frame_elements.js]
 [browser_hasbeforeunload.js]
 support-files =
   beforeunload_test_page.html
 run-if = e10s
 [browser_largeAllocation_win32.js]
 skip-if = !e10s || os != "win" || processor != "x86" # Large-Allocation requires e10s
 [browser_largeAllocation_non_win32.js]
-skip-if = !e10s || (os == "win" && processor == "x86") || (verify && debug && (os == 'linux')) || (os == 'linux') || (os == 'mac' && debug)  # Large-Allocation requires e10s # Bug 1336075
+skip-if = !e10s || (os == "win" && (processor == "x86" || processor == "aarch64")) || (verify && debug && (os == 'linux')) || (os == 'linux') || (os == 'mac' && debug)  # Large-Allocation requires e10s # Bug 1336075
 [browser_localStorage_e10s.js]
 skip-if = !e10s || verify # This is a test of e10s functionality.
 [browser_localStorage_privatestorageevent.js]
 [browser_localStorage_snapshotting_e10s.js]
 skip-if = !e10s # This is a test of e10s functionality.
 [browser_persist_cookies.js]
 support-files =
   set-samesite-cookies-and-redirect.sjs
--- a/dom/webidl/RTCPeerConnection.webidl
+++ b/dom/webidl/RTCPeerConnection.webidl
@@ -162,17 +162,17 @@ interface RTCPeerConnection : EventTarge
   attribute EventHandler onsignalingstatechange;
   attribute EventHandler onaddstream; // obsolete
   attribute EventHandler onaddtrack;  // obsolete
   attribute EventHandler ontrack;     // replaces onaddtrack and onaddstream.
   attribute EventHandler onremovestream;
   attribute EventHandler oniceconnectionstatechange;
   attribute EventHandler onicegatheringstatechange;
 
-  Promise<RTCStatsReport> getStats (optional MediaStreamTrack? selector);
+  Promise<RTCStatsReport> getStats (optional MediaStreamTrack? selector = null);
 
   // Data channel.
   RTCDataChannel createDataChannel (DOMString label,
                                     optional RTCDataChannelInit dataChannelDict);
   attribute EventHandler ondatachannel;
 };
 
 // Legacy callback API
--- a/gfx/layers/apz/src/APZCTreeManager.cpp
+++ b/gfx/layers/apz/src/APZCTreeManager.cpp
@@ -385,16 +385,19 @@ APZCTreeManager::UpdateHitTestingTreeImp
   // and so maintaining a list and removing APZCs that are still alive is much
   // simpler.
   ForEachNode<ReverseIterator>(mRootNode.get(),
                                [&state](HitTestingTreeNode* aNode) {
                                  state.mNodesToDestroy.AppendElement(aNode);
                                });
   mRootNode = nullptr;
   mUsingAsyncZoomContainer = false;
+  int asyncZoomContainerNestingDepth = 0;
+  bool haveMultipleAsyncZoomContainers = false;
+  bool haveRootContentOutsideAsyncZoomContainer = false;
 
   if (aRoot) {
     std::stack<gfx::TreeAutoIndent> indents;
     std::stack<AncestorTransform> ancestorTransforms;
     HitTestingTreeNode* parent = nullptr;
     HitTestingTreeNode* next = nullptr;
     LayersId layersId = aRootLayerTreeId;
     ancestorTransforms.push(AncestorTransform());
@@ -404,17 +407,26 @@ APZCTreeManager::UpdateHitTestingTreeImp
     mTreeLock.AssertCurrentThreadIn();
 
     ForEachNode<ReverseIterator>(
         aRoot,
         [&](ScrollNode aLayerMetrics) {
           mApzcTreeLog << aLayerMetrics.Name() << '\t';
 
           if (aLayerMetrics.IsAsyncZoomContainer()) {
+            if (mUsingAsyncZoomContainer) {
+              haveMultipleAsyncZoomContainers = true;
+            }
             mUsingAsyncZoomContainer = true;
+            ++asyncZoomContainerNestingDepth;
+          }
+
+          if (aLayerMetrics.Metrics().IsRootContent() &&
+              asyncZoomContainerNestingDepth == 0) {
+            haveRootContentOutsideAsyncZoomContainer = true;
           }
 
           HitTestingTreeNode* node = PrepareNodeForLayer(
               lock, aLayerMetrics, aLayerMetrics.Metrics(), layersId,
               ancestorTransforms.top(), parent, next, state);
           MOZ_ASSERT(node);
           AsyncPanZoomController* apzc = node->GetApzc();
           aLayerMetrics.SetApzc(apzc);
@@ -462,26 +474,41 @@ APZCTreeManager::UpdateHitTestingTreeImp
             layersId = *newLayersId;
           }
 
           indents.push(gfx::TreeAutoIndent(mApzcTreeLog));
           state.mParentHasPerspective.push(
               aLayerMetrics.TransformIsPerspective());
         },
         [&](ScrollNode aLayerMetrics) {
+          if (aLayerMetrics.IsAsyncZoomContainer()) {
+            --asyncZoomContainerNestingDepth;
+          }
+
           next = parent;
           parent = parent->GetParent();
           layersId = next->GetLayersId();
           ancestorTransforms.pop();
           indents.pop();
           state.mParentHasPerspective.pop();
         });
 
     mApzcTreeLog << "[end]\n";
 
+    MOZ_ASSERT(
+        !mUsingAsyncZoomContainer || !haveRootContentOutsideAsyncZoomContainer,
+        "If there is an async zoom container, all scroll nodes with root "
+        "content scroll metadata should be inside it");
+    // TODO(bug 1534459): Avoid multiple async zoom containers. They
+    // can't currently occur in production code, but that will become
+    // possible with either OOP iframes or desktop zooming (due to
+    // RDM), and will need to be guarded against.
+    // MOZ_ASSERT(!haveMultipleAsyncZoomContainers,
+    //           "Should only have one async zoom container");
+
     // If we have perspective transforms deferred to children, do another
     // walk of the tree and actually apply them to the children.
     // We can't do this "as we go" in the previous traversal, because by the
     // time we realize we need to defer a perspective transform for an APZC,
     // we may already have processed a previous layer (including children
     // found in its subtree) that shares that APZC.
     if (!state.mPerspectiveTransformsDeferredToChildren.empty()) {
       ForEachNode<ReverseIterator>(
new file mode 100644
--- /dev/null
+++ b/gfx/layers/apz/test/mochitest/helper_hittest_clipped_fixed_modal.html
@@ -0,0 +1,84 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Hit-testing on content covered by a fullscreen fixed-position item clipped away</title>
+  <script type="application/javascript" src="apz_test_utils.js"></script>
+  <script type="application/javascript" src="apz_test_native_event_utils.js"></script>
+  <script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
+  <meta name="viewport" content="width=device-width"/>
+<style>
+.modal
+{
+    position:fixed;
+    z-index:10;
+    width:100%;
+    height:100%;
+    left:0;
+    top:0;
+    clip:rect(1px,1px,1px,1px);
+}
+.modal__content
+{
+    overflow:auto;
+    position:fixed;
+    top:0;
+    left:0;
+    width:100%;
+    height:100%;
+}
+.modal__body
+{
+    position:absolute;
+    top:0;
+    left:0;
+    width:100%;
+    height:100%;
+}
+.content
+{
+    position:fixed;
+    top:0;
+    left:0;
+    width:100%;
+    height:100%;
+    overflow-y:auto
+}
+</style>
+</head>
+<body>
+<div class="content">
+ <div style="height: 5000px; background-image: linear-gradient(red,blue)">
+    Filler to make the content div scrollable
+ </div>
+</div>
+<div class="modal">
+ <div class="modal__content">
+  <div class="modal__body">
+  </div>
+ </div>
+</div>
+</body>
+<script type="application/javascript">
+
+function* test(testDriver) {
+  var config = getHitTestConfig();
+  var utils = config.utils;
+
+  // layerize the scrollable frame
+  var subframe = document.querySelector(".content");
+  utils.setDisplayPortForElement(0, 0, 800, 2000, subframe, 1);
+  yield waitForApzFlushedRepaints(testDriver);
+
+  var target = document.querySelector(".content");
+  checkHitResult(hitTest(centerOf(target)),
+                 APZHitResultFlags.VISIBLE,
+                 utils.getViewId(subframe),
+                 "content covered by a clipped fixed div");
+
+  subtestDone();
+}
+
+waitUntilApzStable().then(runContinuation(test));
+
+</script>
+</html>
--- a/gfx/layers/apz/test/mochitest/test_group_hittest.html
+++ b/gfx/layers/apz/test/mochitest/test_group_hittest.html
@@ -31,16 +31,17 @@ var subtests = [
   {"file": "helper_hittest_fixed_in_scrolled_transform.html", "prefs": prefs},
   {"file": "helper_hittest_float_bug1434846.html", "prefs": prefs},
   {"file": "helper_hittest_float_bug1443518.html", "prefs": prefs},
   {"file": "helper_hittest_checkerboard.html", "prefs": prefs},
   {"file": "helper_hittest_backface_hidden.html", "prefs": prefs},
   {"file": "helper_hittest_touchaction.html", "prefs": prefs},
   {"file": "helper_hittest_nested_transforms_bug1459696.html", "prefs": prefs},
   {"file": "helper_hittest_sticky_bug1478304.html", "prefs": prefs},
+  {"file": "helper_hittest_clipped_fixed_modal.html", "prefs": prefs},
 ];
 
 if (isApzEnabled()) {
   SimpleTest.waitForExplicitFinish();
   window.onload = function() {
     runSubtestsSeriallyInFreshWindows(subtests)
     .then(SimpleTest.finish, SimpleTest.finish);
   };
--- a/gfx/layers/apz/test/reftest/reftest.list
+++ b/gfx/layers/apz/test/reftest/reftest.list
@@ -16,18 +16,17 @@ fuzzy-if(Android,0-45,0-27) skip-if(!And
 # Test scrollbars working properly with pinch-zooming, i.e. different document resolutions.
 # As above, the end of the scrollthumb won't match perfectly, but the bulk of the scrollbar should be present and identical.
 fuzzy-if(Android,0-54,0-14) skip-if(!Android) pref(apz.allow_zooming,true) == scrollbar-zoom-resolution-1.html scrollbar-zoom-resolution-1-ref.html
 fuzzy-if(Android,0-51,0-22) skip-if(!Android) pref(apz.allow_zooming,true) == scrollbar-zoom-resolution-2.html scrollbar-zoom-resolution-2-ref.html
 
 # Meta-viewport tag support
 skip-if(!Android) pref(apz.allow_zooming,true) == initial-scale-1.html initial-scale-1-ref.html
 
-# Bug 1520320 is tracking the effort to make this test pass again.
-skip-if(!asyncPan) random-if(Android) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
+skip-if(!asyncPan) == frame-reconstruction-scroll-clamping.html frame-reconstruction-scroll-clamping-ref.html
 
 # Test that position:fixed and position:sticky elements are attached to the
 # layout viewport.
 #
 # We skip these tests on Desktop platforms since they require container
 # scrolling, which is enabled by default on Android, but behind a "Once" pref
 # and cannot be enabled for individual reftests.
 skip-if(!Android) pref(apz.allow_zooming,true) == pinch-zoom-position-fixed.html pinch-zoom-position-fixed-ref.html
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -168,21 +168,23 @@ static ScreenMargin ScrollFrame(nsIConte
                                 const RepaintRequest& aRequest) {
   // Scroll the window to the desired spot
   nsIScrollableFrame* sf =
       nsLayoutUtils::FindScrollableFrameFor(aRequest.GetScrollId());
   if (sf) {
     sf->ResetScrollInfoIfGeneration(aRequest.GetScrollGeneration());
     sf->SetScrollableByAPZ(!aRequest.IsScrollInfoLayer());
     if (sf->IsRootScrollFrameOfDocument()) {
-      if (nsCOMPtr<nsIPresShell> shell = GetPresShell(aContent)) {
-        if (shell->SetVisualViewportOffset(
-                CSSPoint::ToAppUnits(aRequest.GetScrollOffset()),
-                shell->GetLayoutViewportOffset())) {
-          sf->MarkEverScrolled();
+      if (!APZCCallbackHelper::IsScrollInProgress(sf)) {
+        if (nsCOMPtr<nsIPresShell> shell = GetPresShell(aContent)) {
+          if (shell->SetVisualViewportOffset(
+                  CSSPoint::ToAppUnits(aRequest.GetScrollOffset()),
+                  shell->GetLayoutViewportOffset())) {
+            sf->MarkEverScrolled();
+          }
         }
       }
     }
   }
   bool scrollUpdated = false;
   ScreenMargin displayPortMargins = aRequest.GetDisplayPortMargins();
   CSSPoint apzScrollOffset = aRequest.GetScrollOffset();
   CSSPoint actualScrollOffset = ScrollFrameTo(sf, aRequest, scrollUpdated);
--- a/gfx/vr/service/moz.build
+++ b/gfx/vr/service/moz.build
@@ -33,14 +33,8 @@ if CONFIG['OS_TARGET'] in ('WINNT', 'Lin
     # OpenVRSession includes MacIOSurface.h which includes Mac headers
     # which define Size and Points types in the root namespace that
     # often conflict with our own types.
     SOURCES += [
         'OpenVRSession.cpp'
     ]
 
 FINAL_LIBRARY = 'xul'
-
-# This is intended as a temporary hack to enable VS2015 builds.
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # ovr_capi_dynamic.h '<unnamed-tag>': Alignment specifier is less than
-    # actual alignment (8), and will be ignored
-    CXXFLAGS += ['-wd4359']
--- a/gfx/wr/webrender/res/clip_shared.glsl
+++ b/gfx/wr/webrender/res/clip_shared.glsl
@@ -1,50 +1,53 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include rect,render_task,gpu_cache,snap,transform
 
 #ifdef WR_VERTEX_SHADER
 
-in int aClipRenderTaskAddress;
-in int aClipTransformId;
-in int aPrimTransformId;
-in int aClipSegment;
+in ivec2 aTransformIds;
 in ivec4 aClipDataResourceAddress;
 in vec2 aClipLocalPos;
 in vec4 aClipTileRect;
 in vec4 aClipDeviceArea;
 in vec4 aClipSnapOffsets;
+in vec4 aClipOrigins;
+in float aDevicePixelScale;
 
 struct ClipMaskInstance {
-    int render_task_address;
     int clip_transform_id;
     int prim_transform_id;
     ivec2 clip_data_address;
     ivec2 resource_address;
     vec2 local_pos;
     RectWithSize tile_rect;
     RectWithSize sub_rect;
     vec4 snap_offsets;
+    vec2 task_origin;
+    vec2 screen_origin;
+    float device_pixel_scale;
 };
 
 ClipMaskInstance fetch_clip_item() {
     ClipMaskInstance cmi;
 
-    cmi.render_task_address = aClipRenderTaskAddress;
-    cmi.clip_transform_id = aClipTransformId;
-    cmi.prim_transform_id = aPrimTransformId;
+    cmi.clip_transform_id = aTransformIds.x;
+    cmi.prim_transform_id = aTransformIds.y;
     cmi.clip_data_address = aClipDataResourceAddress.xy;
     cmi.resource_address = aClipDataResourceAddress.zw;
     cmi.local_pos = aClipLocalPos;
     cmi.tile_rect = RectWithSize(aClipTileRect.xy, aClipTileRect.zw);
     cmi.sub_rect = RectWithSize(aClipDeviceArea.xy, aClipDeviceArea.zw);
     cmi.snap_offsets = aClipSnapOffsets;
+    cmi.task_origin = aClipOrigins.xy;
+    cmi.screen_origin = aClipOrigins.zw;
+    cmi.device_pixel_scale = aDevicePixelScale;
 
     return cmi;
 }
 
 struct ClipVertexInfo {
     vec3 local_pos;
     RectWithSize clipped_local_rect;
 };
@@ -54,43 +57,44 @@ RectWithSize intersect_rect(RectWithSize
     return RectWithSize(p.xy, max(vec2(0.0), p.zw - p.xy));
 }
 
 // The transformed vertex function that always covers the whole clip area,
 // which is the intersection of all clip instances of a given primitive
 ClipVertexInfo write_clip_tile_vertex(RectWithSize local_clip_rect,
                                       Transform prim_transform,
                                       Transform clip_transform,
-                                      ClipArea area,
                                       RectWithSize sub_rect,
-                                      vec4 snap_offsets) {
-    vec2 device_pos = area.screen_origin + sub_rect.p0 +
-                      aPosition.xy * sub_rect.size;
+                                      vec4 snap_offsets,
+                                      vec2 task_origin,
+                                      vec2 screen_origin,
+                                      float device_pixel_scale) {
+    vec2 device_pos = screen_origin + sub_rect.p0 + aPosition.xy * sub_rect.size;
 
     // If the primitive we are drawing a clip mask for was snapped, then
     // remove the effect of that snapping, so that the local position
     // interpolation below works correctly relative to the clip item.
     vec2 snap_offset = mix(
         snap_offsets.xy,
         snap_offsets.zw,
         aPosition.xy
     );
 
     device_pos -= snap_offset;
 
-    vec2 world_pos = device_pos / area.device_pixel_scale;
+    vec2 world_pos = device_pos / device_pixel_scale;
 
     vec4 pos = prim_transform.m * vec4(world_pos, 0.0, 1.0);
     pos.xyz /= pos.w;
 
     vec4 p = get_node_pos(pos.xy, clip_transform);
     vec3 local_pos = p.xyw * pos.w;
 
     vec4 vertex_pos = vec4(
-        area.common_data.task_rect.p0 + sub_rect.p0 + aPosition.xy * sub_rect.size,
+        task_origin + sub_rect.p0 + aPosition.xy * sub_rect.size,
         0.0,
         1.0
     );
 
     gl_Position = uTransform * vertex_pos;
 
     init_transform_vs(vec4(local_clip_rect.p0, local_clip_rect.p0 + local_clip_rect.size));
 
--- a/gfx/wr/webrender/res/cs_clip_box_shadow.glsl
+++ b/gfx/wr/webrender/res/cs_clip_box_shadow.glsl
@@ -35,32 +35,33 @@ BoxShadowData fetch_data(ivec2 address) 
         int(data[1].y),
         dest_rect
     );
     return bs_data;
 }
 
 void main(void) {
     ClipMaskInstance cmi = fetch_clip_item();
-    ClipArea area = fetch_clip_area(cmi.render_task_address);
     Transform clip_transform = fetch_transform(cmi.clip_transform_id);
     Transform prim_transform = fetch_transform(cmi.prim_transform_id);
     BoxShadowData bs_data = fetch_data(cmi.clip_data_address);
     ImageResource res = fetch_image_resource_direct(cmi.resource_address);
 
     RectWithSize dest_rect = bs_data.dest_rect;
     dest_rect.p0 += cmi.local_pos;
 
     ClipVertexInfo vi = write_clip_tile_vertex(
         dest_rect,
         prim_transform,
         clip_transform,
-        area,
         cmi.sub_rect,
-        cmi.snap_offsets
+        cmi.snap_offsets,
+        cmi.task_origin,
+        cmi.screen_origin,
+        cmi.device_pixel_scale
     );
     vLocalPos = vi.local_pos;
     vLayer = res.layer;
     vClipMode = bs_data.clip_mode;
 
     vec2 uv0 = res.uv_rect.p0;
     vec2 uv1 = res.uv_rect.p1;
 
--- a/gfx/wr/webrender/res/cs_clip_image.glsl
+++ b/gfx/wr/webrender/res/cs_clip_image.glsl
@@ -19,30 +19,31 @@ struct ImageMaskData {
 ImageMaskData fetch_mask_data(ivec2 address) {
     vec4 data = fetch_from_gpu_cache_1_direct(address);
     ImageMaskData mask_data = ImageMaskData(data.xy);
     return mask_data;
 }
 
 void main(void) {
     ClipMaskInstance cmi = fetch_clip_item();
-    ClipArea area = fetch_clip_area(cmi.render_task_address);
     Transform clip_transform = fetch_transform(cmi.clip_transform_id);
     Transform prim_transform = fetch_transform(cmi.prim_transform_id);
     ImageMaskData mask = fetch_mask_data(cmi.clip_data_address);
     RectWithSize local_rect = RectWithSize(cmi.local_pos, mask.local_mask_size);
     ImageResource res = fetch_image_resource_direct(cmi.resource_address);
 
     ClipVertexInfo vi = write_clip_tile_vertex(
         local_rect,
         prim_transform,
         clip_transform,
-        area,
         cmi.sub_rect,
-        cmi.snap_offsets
+        cmi.snap_offsets,
+        cmi.task_origin,
+        cmi.screen_origin,
+        cmi.device_pixel_scale
     );
     vLocalPos = vi.local_pos.xy / vi.local_pos.z;
     vLayer = res.layer;
     vClipMaskImageUv = (vLocalPos - cmi.tile_rect.p0) / cmi.tile_rect.size;
     vec2 texture_size = vec2(textureSize(sColor0, 0));
     vClipMaskUvRect = vec4(res.uv_rect.p0, res.uv_rect.p1 - res.uv_rect.p0) / texture_size.xyxy;
     // applying a half-texel offset to the UV boundaries to prevent linear samples from the outside
     vec4 inner_rect = vec4(res.uv_rect.p0, res.uv_rect.p1);
--- a/gfx/wr/webrender/res/cs_clip_rectangle.glsl
+++ b/gfx/wr/webrender/res/cs_clip_rectangle.glsl
@@ -54,31 +54,32 @@ ClipData fetch_clip(ivec2 address) {
     clip.bottom_left = fetch_clip_corner(address, 2.0);
     clip.bottom_right = fetch_clip_corner(address, 3.0);
 
     return clip;
 }
 
 void main(void) {
     ClipMaskInstance cmi = fetch_clip_item();
-    ClipArea area = fetch_clip_area(cmi.render_task_address);
     Transform clip_transform = fetch_transform(cmi.clip_transform_id);
     Transform prim_transform = fetch_transform(cmi.prim_transform_id);
     ClipData clip = fetch_clip(cmi.clip_data_address);
 
     RectWithSize local_rect = clip.rect.rect;
     local_rect.p0 = cmi.local_pos;
 
     ClipVertexInfo vi = write_clip_tile_vertex(
         local_rect,
         prim_transform,
         clip_transform,
-        area,
         cmi.sub_rect,
-        cmi.snap_offsets
+        cmi.snap_offsets,
+        cmi.task_origin,
+        cmi.screen_origin,
+        cmi.device_pixel_scale
     );
 
     vLocalPos = vi.local_pos;
     vClipMode = clip.rect.mode.x;
 
     RectWithEndpoint clip_rect = to_rect_with_endpoint(local_rect);
 
     vec2 r_tl = clip.top_left.outer_inner_radius.xy;
--- a/gfx/wr/webrender/src/batch.rs
+++ b/gfx/wr/webrender/src/batch.rs
@@ -2701,31 +2701,35 @@ impl ClipBatcher {
             primary_clips: ClipBatchList::new(),
             secondary_clips: ClipBatchList::new(),
             gpu_supports_fast_clears,
         }
     }
 
     pub fn add_clip_region(
         &mut self,
-        task_address: RenderTaskAddress,
         clip_data_address: GpuCacheAddress,
         local_pos: LayoutPoint,
         sub_rect: DeviceRect,
+        task_origin: DevicePoint,
+        screen_origin: DevicePoint,
+        device_pixel_scale: f32,
     ) {
         let instance = ClipMaskInstance {
-            render_task_address: task_address,
             clip_transform_id: TransformPaletteId::IDENTITY,
             prim_transform_id: TransformPaletteId::IDENTITY,
             clip_data_address,
             resource_address: GpuCacheAddress::invalid(),
             local_pos,
             tile_rect: LayoutRect::zero(),
             sub_rect,
             snap_offsets: SnapOffsets::empty(),
+            task_origin,
+            screen_origin,
+            device_pixel_scale,
         };
 
         self.primary_clips.rectangles.push(instance);
     }
 
     /// Where appropriate, draw a clip rectangle as a small series of tiles,
     /// instead of one large rectangle.
     fn add_tiled_clip_mask(
@@ -2827,29 +2831,30 @@ impl ClipBatcher {
             &mut self.primary_clips
         } else {
             &mut self.secondary_clips
         }
     }
 
     pub fn add(
         &mut self,
-        task_address: RenderTaskAddress,
         clip_node_range: ClipNodeRange,
         root_spatial_node_index: SpatialNodeIndex,
         resource_cache: &ResourceCache,
         gpu_cache: &GpuCache,
         clip_store: &ClipStore,
         clip_scroll_tree: &ClipScrollTree,
         transforms: &mut TransformPalette,
         clip_data_store: &ClipDataStore,
         actual_rect: DeviceIntRect,
         world_rect: &WorldRect,
         device_pixel_scale: DevicePixelScale,
         snap_offsets: SnapOffsets,
+        task_origin: DevicePoint,
+        screen_origin: DevicePoint,
     ) {
         let mut is_first_clip = true;
 
         for i in 0 .. clip_node_range.count {
             let clip_instance = clip_store.get_instance_from_range(&clip_node_range, i);
             let clip_node = &clip_data_store[clip_instance.handle];
 
             let clip_transform_id = transforms.get_id(
@@ -2860,28 +2865,30 @@ impl ClipBatcher {
 
             let prim_transform_id = transforms.get_id(
                 root_spatial_node_index,
                 ROOT_SPATIAL_NODE_INDEX,
                 clip_scroll_tree,
             );
 
             let instance = ClipMaskInstance {
-                render_task_address: task_address,
                 clip_transform_id,
                 prim_transform_id,
                 clip_data_address: GpuCacheAddress::invalid(),
                 resource_address: GpuCacheAddress::invalid(),
                 local_pos: clip_instance.local_pos,
                 tile_rect: LayoutRect::zero(),
                 sub_rect: DeviceRect::new(
                     DevicePoint::zero(),
                     actual_rect.size.to_f32(),
                 ),
                 snap_offsets,
+                task_origin,
+                screen_origin,
+                device_pixel_scale: device_pixel_scale.0,
             };
 
             let added_clip = match clip_node.item {
                 ClipItem::Image { image, size, .. } => {
                     let request = ImageRequest {
                         key: image,
                         rendering: ImageRendering::Auto,
                         tile: None,
--- a/gfx/wr/webrender/src/gpu_types.rs
+++ b/gfx/wr/webrender/src/gpu_types.rs
@@ -132,25 +132,27 @@ pub struct BorderInstance {
 /// A clipping primitive drawn into the clipping mask.
 /// Could be an image or a rectangle, which defines the
 /// way `address` is treated.
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub struct ClipMaskInstance {
-    pub render_task_address: RenderTaskAddress,
     pub clip_transform_id: TransformPaletteId,
     pub prim_transform_id: TransformPaletteId,
     pub clip_data_address: GpuCacheAddress,
     pub resource_address: GpuCacheAddress,
     pub local_pos: LayoutPoint,
     pub tile_rect: LayoutRect,
     pub sub_rect: DeviceRect,
     pub snap_offsets: SnapOffsets,
+    pub task_origin: DevicePoint,
+    pub screen_origin: DevicePoint,
+    pub device_pixel_scale: f32,
 }
 
 /// A border corner dot or dash drawn into the clipping mask.
 #[derive(Debug, Copy, Clone)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 #[repr(C)]
 pub struct ClipMaskBorderCornerDotDash {
--- a/gfx/wr/webrender/src/render_task.rs
+++ b/gfx/wr/webrender/src/render_task.rs
@@ -275,17 +275,17 @@ pub struct CacheMaskTask {
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct ClipRegionTask {
     pub clip_data_address: GpuCacheAddress,
     pub local_pos: LayoutPoint,
-    device_pixel_scale: DevicePixelScale,
+    pub device_pixel_scale: DevicePixelScale,
 }
 
 #[derive(Debug)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct TileBlit {
     pub target: CacheItem,
     pub src_offset: DeviceIntPoint,
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -584,28 +584,18 @@ pub(crate) mod desc {
             VertexAttribute {
                 name: "aPosition",
                 count: 2,
                 kind: VertexAttributeKind::F32,
             },
         ],
         instance_attributes: &[
             VertexAttribute {
-                name: "aClipRenderTaskAddress",
-                count: 1,
-                kind: VertexAttributeKind::I32,
-            },
-            VertexAttribute {
-                name: "aClipTransformId",
-                count: 1,
-                kind: VertexAttributeKind::I32,
-            },
-            VertexAttribute {
-                name: "aPrimTransformId",
-                count: 1,
+                name: "aTransformIds",
+                count: 2,
                 kind: VertexAttributeKind::I32,
             },
             VertexAttribute {
                 name: "aClipDataResourceAddress",
                 count: 4,
                 kind: VertexAttributeKind::U16,
             },
             VertexAttribute {
@@ -622,17 +612,27 @@ pub(crate) mod desc {
                 name: "aClipDeviceArea",
                 count: 4,
                 kind: VertexAttributeKind::F32,
             },
             VertexAttribute {
                 name: "aClipSnapOffsets",
                 count: 4,
                 kind: VertexAttributeKind::F32,
-            }
+            },
+            VertexAttribute {
+                name: "aClipOrigins",
+                count: 4,
+                kind: VertexAttributeKind::F32,
+            },
+            VertexAttribute {
+                name: "aDevicePixelScale",
+                count: 1,
+                kind: VertexAttributeKind::F32,
+            },
         ],
     };
 
     pub const GPU_CACHE_UPDATE: VertexDescriptor = VertexDescriptor {
         vertex_attributes: &[
             VertexAttribute {
                 name: "aPosition",
                 count: 2,
--- a/gfx/wr/webrender/src/tiling.rs
+++ b/gfx/wr/webrender/src/tiling.rs
@@ -630,16 +630,17 @@ impl RenderTarget for AlphaRenderTarget 
         ctx: &RenderTargetContext,
         gpu_cache: &mut GpuCache,
         render_tasks: &RenderTaskTree,
         clip_store: &ClipStore,
         transforms: &mut TransformPalette,
         _: &mut Vec<DeferredResolve>,
     ) {
         let task = &render_tasks[task_id];
+        let (target_rect, _) = task.get_target_rect();
 
         match task.clear_mode {
             ClearMode::Zero => {
                 self.zero_clears.push(task_id);
             }
             ClearMode::One => {
                 self.one_clears.push(task_id);
             }
@@ -671,44 +672,45 @@ impl RenderTarget for AlphaRenderTarget 
                 info.add_instances(
                     &mut self.horizontal_blurs,
                     BlurDirection::Horizontal,
                     render_tasks.get_task_address(task_id),
                     render_tasks.get_task_address(task.children[0]),
                 );
             }
             RenderTaskKind::CacheMask(ref task_info) => {
-                let task_address = render_tasks.get_task_address(task_id);
                 self.clip_batcher.add(
-                    task_address,
                     task_info.clip_node_range,
                     task_info.root_spatial_node_index,
                     ctx.resource_cache,
                     gpu_cache,
                     clip_store,
                     ctx.clip_scroll_tree,
                     transforms,
                     &ctx.data_stores.clip,
                     task_info.actual_rect,
                     &ctx.screen_world_rect,
                     task_info.device_pixel_scale,
                     task_info.snap_offsets,
+                    target_rect.origin.to_f32(),
+                    task_info.actual_rect.origin.to_f32(),
                 );
             }
             RenderTaskKind::ClipRegion(ref region_task) => {
-                let task_address = render_tasks.get_task_address(task_id);
                 let device_rect = DeviceRect::new(
                     DevicePoint::zero(),
-                    task.get_dynamic_size().to_f32(),
+                    target_rect.size.to_f32(),
                 );
                 self.clip_batcher.add_clip_region(
-                    task_address,
                     region_task.clip_data_address,
                     region_task.local_pos,
                     device_rect,
+                    target_rect.origin.to_f32(),
+                    DevicePoint::zero(),
+                    region_task.device_pixel_scale.0,
                 );
             }
             RenderTaskKind::Scaling(ref info) => {
                 info.add_instances(
                     &mut self.scalings,
                     render_tasks.get_task_address(task_id),
                     render_tasks.get_task_address(task.children[0]),
                 );
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -184,22 +184,16 @@ if CONFIG['OS_ARCH'] == 'Darwin':
     SOURCES += [
         'GeckoChildProcessHost.cpp',
     ]
 else:
     UNIFIED_SOURCES += [
         'GeckoChildProcessHost.cpp',
     ]
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary hack to support building with VS2015.
-    # 'reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size
-    SOURCES['BackgroundChildImpl.cpp'].flags += ['-wd4312']
-    SOURCES['BackgroundParentImpl.cpp'].flags += ['-wd4312']
-
 LOCAL_INCLUDES += [
     '/caps',
     '/dom/broadcastchannel',
     '/dom/indexedDB',
     '/dom/storage',
     '/media/webrtc/trunk',
     '/media/webrtc/trunk/webrtc',
     '/xpcom/build',
--- a/js/src/js-cxxflags.mozbuild
+++ b/js/src/js-cxxflags.mozbuild
@@ -2,32 +2,16 @@
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # ICU pkg-config flags
 CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # C4805 warns mixing bool with other integral types in computation.
-    # But given the conversion from bool is specified, and this is a
-    # pattern widely used in code in js/src, suppress this warning here.
-    CXXFLAGS += ['-wd4805']
-    # C4661 ("no suitable definition provided for explicit template
-    # instantiation request") is emitted for all Parser methods that
-    # have a Parser<FullParseHandler> definition but no
-    # Parser<SyntaxParseHandler> definition, see bug 1167030.
-    CXXFLAGS += ['-wd4661']
-    # FIXME: unary minus operator applied to unsigned type (bug 1229189)
-    CXXFLAGS += ['-wd4146']
-    # FIXME: 'operation' : conversion from 'type1' to 'type2' of
-    # greater size (bug 1259304)
-    CXXFLAGS += ['-wd4312']
-
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     # Also disable strict-aliasing for GCC compiler, that is enabled by default
     # starting with version 7.1, see Bug 1363009
     CXXFLAGS += ['-fno-strict-aliasing']
     # Error on bad printf-like format strings
     CXXFLAGS += ['-Werror=format']
     # Ignore shadowed variable warnings as there are too many.
     CXXFLAGS += ['-Wno-shadow']
--- a/js/src/old-configure.in
+++ b/js/src/old-configure.in
@@ -129,25 +129,19 @@ case "$target" in
         _WIN32_MSVC=1
 
         # Make sure compilers are valid
         CFLAGS="$CFLAGS -nologo"
         CXXFLAGS="$CXXFLAGS -TP -nologo"
         if test -z "$CLANG_CL"; then
             CPPFLAGS="$CPPFLAGS -utf-8"
         fi
-        # MSVC warning C4800 warns when a value is implicitly cast to bool,
-        # because this also forces narrowing to a single byte, which can be a
-        # perf hit.  But this matters so little in practice (and often we want
-        # that behavior) that it's better to turn it off.
         # _CRT_SECURE_NO_WARNINGS disables warnings about using MSVC-specific
         # secure CRT functions.
-        # MSVC warning C4595 warns non-member operator new or delete functions
-        # may not be declared inline, as of VS2015 Update 2.
-        CXXFLAGS="$CXXFLAGS -wd4800 -wd4595 -D_CRT_SECURE_NO_WARNINGS"
+        CXXFLAGS="$CXXFLAGS -D_CRT_SECURE_NO_WARNINGS"
         AC_LANG_SAVE
         AC_LANG_C
         AC_TRY_COMPILE([#include <stdio.h>],
             [ printf("Hello World\n"); ],,
             AC_MSG_ERROR([\$(CC) test failed.  You must have MS VC++ in your path to build.]) )
 
         AC_LANG_CPLUSPLUS
         AC_TRY_COMPILE([#include <new.h>],
@@ -158,34 +152,20 @@ case "$target" in
         changequote(,)
         _MSVC_VER_FILTER='s|.*[^!-~]([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?).*|\1|p'
         changequote([,])
 
         AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
         AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
         AC_DEFINE(_USE_MATH_DEFINES) # Otherwise MSVC's math.h doesn't #define M_PI.
 
-        # C5038: Enable initializer list order warnings
-        # The -w1#### flag treats warning C#### as if it was a warning level
-        # 1 warning, and thus enables it because we enable /W3 warnings. We
-        # don't use -we#### because it would enable warning C#### but treat
-        # it as an error, even in third-party code.
-        # https://docs.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level
-        CXXFLAGS="$CXXFLAGS -w15038"
-
         _CC_SUITE=14
         MSVC_C_RUNTIME_DLL=vcruntime140.dll
         MSVC_CXX_RUNTIME_DLL=msvcp140.dll
 
-        # C5026: move constructor was implicitly defined as deleted
-        CXXFLAGS="$CXXFLAGS -wd5026"
-
-        # C5027: move assignment operator was implicitly defined as deleted
-        CXXFLAGS="$CXXFLAGS -wd5027"
-
         # -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146)
         CXXFLAGS="$CXXFLAGS -Zc:sizedDealloc-"
 
         AC_SUBST(MSVC_C_RUNTIME_DLL)
         AC_SUBST(MSVC_CXX_RUNTIME_DLL)
 
         # Check linker version, except in lld builds
         case "$LINKER" in
@@ -619,29 +599,16 @@ case "$target" in
         dnl Disabled on ASan because it causes false-positive ODR violations.
         if test -z "$MOZ_ASAN"; then
             CFLAGS="$CFLAGS -Gw"
             CXXFLAGS="$CXXFLAGS -Gw"
         else
             # String tail merging doesn't play nice with ASan's ODR checker.
             LDFLAGS="$LDFLAGS -opt:nolldtailmerge"
         fi
-        # khuey says we can safely ignore MSVC warning C4251
-        # MSVC warning C4244 (implicit type conversion may lose data) warns
-        # and requires workarounds for perfectly valid code.  Also, GCC/clang
-        # don't warn about it by default. So for consistency/sanity, we turn
-        # it off on MSVC, too.
-        # MSVC warning C4267 warns for narrowing type conversions from size_t
-        # to 32-bit integer types on 64-bit platforms.  Since this is virtually
-        # the same thing as C4244, we disable C4267, too.
-        CFLAGS="$CFLAGS -wd4244 -wd4267"
-        CXXFLAGS="$CXXFLAGS -wd4244 -wd4267 -wd4251"
-        # Silence "warning C4065: switch statement contains 'default' but no
-        # 'case' labels".  See bug 1461304.
-        CXXFLAGS="$CXXFLAGS -wd4065"
         if test -n "$CLANG_CL"; then
             # XXX We should combine some of these with our generic GCC-style
             # warning checks.
             #
             # Suppress the clang-cl warning for the inline 'new' and 'delete' in mozalloc
             CXXFLAGS="$CXXFLAGS -Wno-inline-new-delete"
             # We use offsetof on non-POD objects all the time.
             # We also suppress this warning on other platforms.
@@ -697,19 +664,16 @@ case "$target" in
             CXXFLAGS="$CXXFLAGS -Wno-ignored-attributes"
             # __attribute__((unused)) really means "might be unused" and
             # we use it to avoid warnings about things that are unused
             # in some compilation units, but used in many others.  This
             # warning insists on complaining about the latter case, which
             # is annoying, and rather noisy.
             CXXFLAGS="$CXXFLAGS -Wno-used-but-marked-unused"
         fi
-        # make 'foo == bar;' error out
-        CFLAGS="$CFLAGS -we4553"
-        CXXFLAGS="$CXXFLAGS -we4553"
         LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib"
         MOZ_DEBUG_LDFLAGS='-DEBUG'
         WARNINGS_AS_ERRORS='-WX'
         MOZ_OPTIMIZE_FLAGS="-O2"
         MOZ_FIX_LINK_PATHS=
         LDFLAGS="$LDFLAGS -LARGEADDRESSAWARE"
         if test -z "$DEVELOPER_OPTIONS"; then
             LDFLAGS="$LDFLAGS -RELEASE"
--- a/js/xpconnect/wrappers/moz.build
+++ b/js/xpconnect/wrappers/moz.build
@@ -16,22 +16,16 @@ UNIFIED_SOURCES += [
     'WrapperFactory.cpp',
 ]
 
 # XrayWrapper needs to be built separately becaue of template instantiations.
 SOURCES += [
     'XrayWrapper.cpp',
 ]
 
-# warning C4661 for FilteringWrapper
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    CXXFLAGS += [
-        '-wd4661', # no suitable definition provided for explicit template instantiation request
-    ]
-
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '../../../dom/base',
     '../src',
     '/caps',
--- a/layout/base/moz.build
+++ b/layout/base/moz.build
@@ -160,15 +160,10 @@ IPDL_SOURCES += [
 
 FINAL_LIBRARY = 'xul'
 
 BROWSER_CHROME_MANIFESTS += ['tests/browser.ini']
 MARIONETTE_LAYOUT_MANIFESTS += ['tests/marionette/manifest.ini']
 MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome/chrome.ini']
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary hack to support building with VS2015.
-    # 'type cast': conversion from 'unsigned int' to 'void *' of greater size
-    CXXFLAGS += ['-wd4312']
-
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -44,18 +44,18 @@ class nsImageControlFrame final : public
 #endif
 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override {
     return MakeFrameName(NS_LITERAL_STRING("ImageControl"), aResult);
   }
 #endif
 
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
+  Maybe<Cursor> GetCursor(const nsPoint&) override;
+
   // nsIFormContromFrame
   virtual void SetFocus(bool aOn, bool aRepaint) override;
   virtual nsresult SetFormProperty(nsAtom* aName,
                                    const nsAString& aValue) override;
 };
 
 nsImageControlFrame::nsImageControlFrame(ComputedStyle* aStyle,
                                          nsPresContext* aPresContext)
@@ -147,25 +147,20 @@ nsresult nsImageControlFrame::HandleEven
       TranslateEventCoords(pt, *lastClickPoint);
     }
   }
   return nsImageFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
 }
 
 void nsImageControlFrame::SetFocus(bool aOn, bool aRepaint) {}
 
-nsresult nsImageControlFrame::GetCursor(const nsPoint& aPoint,
-                                        nsIFrame::Cursor& aCursor) {
-  // Use style defined cursor if one is provided, otherwise when
-  // the cursor style is "auto" we use the pointer cursor.
-  FillCursorInformationFromStyle(StyleUI(), aCursor);
-
-  if (StyleCursorKind::Auto == aCursor.mCursor) {
-    aCursor.mCursor = StyleCursorKind::Pointer;
+Maybe<nsIFrame::Cursor> nsImageControlFrame::GetCursor(const nsPoint&) {
+  StyleCursorKind kind = StyleUI()->mCursor;
+  if (kind == StyleCursorKind::Auto) {
+    kind = StyleCursorKind::Pointer;
   }
-
-  return NS_OK;
+  return Some(Cursor{kind, AllowCustomCursorImage::Yes});
 }
 
 nsresult nsImageControlFrame::SetFormProperty(nsAtom* aName,
                                               const nsAString& aValue) {
   return NS_OK;
 }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5130,32 +5130,30 @@ void nsIFrame::AssociateImage(const nsSt
   }
   mozilla::css::ImageLoader* loader =
       aPresContext->Document()->StyleImageLoader();
 
   // If this fails there's not much we can do ...
   loader->AssociateRequestToFrame(req, this, aImageLoaderFlags);
 }
 
-nsresult nsFrame::GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor) {
-  FillCursorInformationFromStyle(StyleUI(), aCursor);
-  if (StyleCursorKind::Auto == aCursor.mCursor) {
+Maybe<nsIFrame::Cursor> nsIFrame::GetCursor(const nsPoint&) {
+  StyleCursorKind kind = StyleUI()->mCursor;
+  if (kind == StyleCursorKind::Auto) {
     // If this is editable, I-beam cursor is better for most elements.
-    aCursor.mCursor = (mContent && mContent->IsEditable())
-                          ? StyleCursorKind::Text
-                          : StyleCursorKind::Default;
-  }
-  if (StyleCursorKind::Text == aCursor.mCursor &&
-      GetWritingMode().IsVertical()) {
+    kind = (mContent && mContent->IsEditable()) ? StyleCursorKind::Text
+                                                : StyleCursorKind::Default;
+  }
+  if (kind == StyleCursorKind::Text && GetWritingMode().IsVertical()) {
     // Per CSS UI spec, UA may treat value 'text' as
     // 'vertical-text' for vertical text.
-    aCursor.mCursor = StyleCursorKind::VerticalText;
-  }
-
-  return NS_OK;
+    kind = StyleCursorKind::VerticalText;
+  }
+
+  return Some(Cursor{kind, AllowCustomCursorImage::Yes});
 }
 
 // Resize and incremental reflow
 
 /* virtual */
 void nsFrame::MarkIntrinsicISizesDirty() {
   // This version is meant only for what used to be box-to-block adaptors.
   // It should not be called by other derived classes.
@@ -9745,45 +9743,16 @@ uint8_t nsIFrame::VerticalAlignEnum() co
   const nsStyleCoord& verticalAlign = StyleDisplay()->mVerticalAlign;
   if (verticalAlign.GetUnit() == eStyleUnit_Enumerated) {
     return verticalAlign.GetIntValue();
   }
 
   return eInvalidVerticalAlign;
 }
 
-/* static */
-void nsFrame::FillCursorInformationFromStyle(const nsStyleUI* ui,
-                                             nsIFrame::Cursor& aCursor) {
-  aCursor.mCursor = ui->mCursor;
-  aCursor.mHaveHotspot = false;
-  aCursor.mLoading = false;
-  aCursor.mHotspotX = aCursor.mHotspotY = 0.0f;
-
-  for (const nsCursorImage& item : ui->mCursorImages) {
-    uint32_t status;
-    imgRequestProxy* req = item.GetImage();
-    if (!req || NS_FAILED(req->GetImageStatus(&status))) {
-      continue;
-    }
-    if (!(status & imgIRequest::STATUS_LOAD_COMPLETE)) {
-      // If we are falling back because any cursor before is loading,
-      // let the consumer know.
-      aCursor.mLoading = true;
-    } else if (!(status & imgIRequest::STATUS_ERROR)) {
-      // This is the one we want
-      req->GetImage(getter_AddRefs(aCursor.mContainer));
-      aCursor.mHaveHotspot = item.mHaveHotspot;
-      aCursor.mHotspotX = item.mHotspotX;
-      aCursor.mHotspotY = item.mHotspotY;
-      break;
-    }
-  }
-}
-
 NS_IMETHODIMP
 nsFrame::RefreshSizeCache(nsBoxLayoutState& aState) {
   // XXXbz this comment needs some rewriting to make sense in the
   // post-reflow-branch world.
 
   // Ok we need to compute our minimum, preferred, and maximum sizes.
   // 1) Maximum size. This is easy. Its infinite unless it is overloaded by CSS.
   // 2) Preferred size. This is a little harder. This is the size the
--- a/layout/generic/nsFrame.h
+++ b/layout/generic/nsFrame.h
@@ -172,17 +172,16 @@ class nsFrame : public nsBox {
   const nsFrameList& GetChildList(ChildListID aListID) const override;
   void GetChildLists(nsTArray<ChildList>* aLists) const override;
 
   nsresult HandleEvent(nsPresContext* aPresContext,
                        mozilla::WidgetGUIEvent* aEvent,
                        nsEventStatus* aEventStatus) override;
   nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
                               nsIContent** aContent) override;
-  nsresult GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor) override;
 
   nsresult GetPointFromOffset(int32_t inOffset, nsPoint* outPoint) override;
   nsresult GetCharacterRectsInRange(int32_t aInOffset, int32_t aLength,
                                     nsTArray<nsRect>& aOutRect) override;
 
   nsresult GetChildFrameContainingOffset(int32_t inContentOffset, bool inHint,
                                          int32_t* outFrameContentOffset,
                                          nsIFrame** outChildFrame) override;
@@ -650,19 +649,16 @@ class nsFrame : public nsBox {
   //  table supported) (enums for this are defined in nsIFrame.h)
   nsresult GetDataForTableSelection(const nsFrameSelection* aFrameSelection,
                                     nsIPresShell* aPresShell,
                                     mozilla::WidgetMouseEvent* aMouseEvent,
                                     nsIContent** aParentContent,
                                     int32_t* aContentOffset,
                                     mozilla::TableSelection* aTarget);
 
-  // Fills aCursor with the appropriate information from ui
-  static void FillCursorInformationFromStyle(const nsStyleUI* ui,
-                                             nsIFrame::Cursor& aCursor);
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
 
   nsBoxLayoutMetrics* BoxMetrics() const;
 
   // Fire DOM event. If no aContent argument use frame's mContent.
   void FireDOMEvent(const nsAString& aDOMEventName,
                     nsIContent* aContent = nullptr);
 
--- a/layout/generic/nsFrameSetFrame.cpp
+++ b/layout/generic/nsFrameSetFrame.cpp
@@ -82,18 +82,17 @@ class nsHTMLFramesetBorderFrame final : 
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
+  Maybe<Cursor> GetCursor(const nsPoint&) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus& aStatus) override;
 
@@ -625,26 +624,23 @@ nsresult nsHTMLFramesetFrame::HandleEven
     }
     *aEventStatus = nsEventStatus_eConsumeNoDefault;
   } else {
     *aEventStatus = nsEventStatus_eIgnore;
   }
   return NS_OK;
 }
 
-nsresult nsHTMLFramesetFrame::GetCursor(const nsPoint& aPoint,
-                                        nsIFrame::Cursor& aCursor) {
-  aCursor.mLoading = false;
+Maybe<nsIFrame::Cursor> nsHTMLFramesetFrame::GetCursor(const nsPoint&) {
+  auto kind = StyleCursorKind::Default;
   if (mDragger) {
-    aCursor.mCursor = (mDragger->mVertical) ? StyleCursorKind::EwResize
-                                            : StyleCursorKind::NsResize;
-  } else {
-    aCursor.mCursor = StyleCursorKind::Default;
+    kind = mDragger->mVertical ? StyleCursorKind::EwResize
+                               : StyleCursorKind::NsResize;
   }
-  return NS_OK;
+  return Some(Cursor{kind, AllowCustomCursorImage::No});
 }
 
 void nsHTMLFramesetFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                            const nsDisplayListSet& aLists) {
   BuildDisplayListForInline(aBuilder, aLists);
 
   if (mDragger && aBuilder->IsForEventDelivery()) {
     aLists.Content()->AppendToTop(
@@ -1461,26 +1457,22 @@ nsresult nsHTMLFramesetBorderFrame::Hand
     if (parentFrame) {
       parentFrame->StartMouseDrag(aPresContext, this, aEvent);
       *aEventStatus = nsEventStatus_eConsumeNoDefault;
     }
   }
   return NS_OK;
 }
 
-nsresult nsHTMLFramesetBorderFrame::GetCursor(const nsPoint& aPoint,
-                                              nsIFrame::Cursor& aCursor) {
-  aCursor.mLoading = false;
-  if (!mCanResize) {
-    aCursor.mCursor = StyleCursorKind::Default;
-  } else {
-    aCursor.mCursor =
-        (mVertical) ? StyleCursorKind::EwResize : StyleCursorKind::NsResize;
+Maybe<nsIFrame::Cursor> nsHTMLFramesetBorderFrame::GetCursor(const nsPoint&) {
+  auto kind = StyleCursorKind::Default;
+  if (mCanResize) {
+    kind = mVertical ? StyleCursorKind::EwResize : StyleCursorKind::NsResize;
   }
-  return NS_OK;
+  return Some(Cursor{kind, AllowCustomCursorImage::No});
 }
 
 #ifdef DEBUG_FRAME_DUMP
 nsresult nsHTMLFramesetBorderFrame::GetFrameName(nsAString& aResult) const {
   return MakeFrameName(NS_LITERAL_STRING("FramesetBorder"), aResult);
 }
 #endif
 
--- a/layout/generic/nsFrameSetFrame.h
+++ b/layout/generic/nsFrameSetFrame.h
@@ -83,18 +83,17 @@ class nsHTMLFramesetFrame final : public
 
   void GetSizeOfChildAt(int32_t aIndexInParent, mozilla::WritingMode aWM,
                         mozilla::LogicalSize& aSize, nsIntPoint& aCellIndex);
 
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
+  mozilla::Maybe<Cursor> GetCursor(const nsPoint&) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus& aStatus) override;
 
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2671,30 +2671,62 @@ bool ScrollFrameHelper::GetDisplayPortAt
   if (mHadDisplayPortAtLastFrameUpdate) {
     *aDisplayPort = mDisplayPortAtLastFrameUpdate;
   }
   return mHadDisplayPortAtLastFrameUpdate;
 }
 
 void ScrollFrameHelper::ScrollToImpl(nsPoint aPt, const nsRect& aRange,
                                      nsAtom* aOrigin) {
+  // Figure out the effective origin for this scroll request.
   if (aOrigin == nullptr) {
     // If no origin was specified, we still want to set it to something that's
     // non-null, so that we can use nullness to distinguish if the frame was
     // scrolled at all. Default it to some generic placeholder.
     aOrigin = nsGkAtoms::other;
   }
 
+  // If this scroll is |relative|, but we've already had a user scroll that
+  // was not relative, promote this origin to |other|. This ensures that we
+  // may only transmit a relative update to APZ if all scrolls since the last
+  // transaction or repaint request have been relative.
+  if (aOrigin == nsGkAtoms::relative &&
+      (mLastScrollOrigin && mLastScrollOrigin != nsGkAtoms::relative &&
+       mLastScrollOrigin != nsGkAtoms::apz)) {
+    aOrigin = nsGkAtoms::other;
+  }
+
+  // If the origin is a downgrade, and downgrades are allowed, process the
+  // downgrade even if we're going to early-exit because we're already at
+  // the correct scroll position. This ensures that if there wasn't a main-
+  // thread scroll update pending before a frame reconstruction (as indicated
+  // by mAllowScrollOriginDowngrade=true), then after the frame reconstruction
+  // the origin is downgraded to "restore" even if the layout scroll offset to
+  // be restored is (0,0) (which will take the early-exit below). This is
+  // important so that restoration of a *visual* scroll offset (which might be
+  // to something other than (0,0)) isn't clobbered.
+  bool isScrollOriginDowngrade =
+      nsLayoutUtils::CanScrollOriginClobberApz(mLastScrollOrigin) &&
+      !nsLayoutUtils::CanScrollOriginClobberApz(aOrigin);
+  bool allowScrollOriginChange =
+      mAllowScrollOriginDowngrade && isScrollOriginDowngrade;
+
+  if (allowScrollOriginChange) {
+    mLastScrollOrigin = aOrigin;
+    mAllowScrollOriginDowngrade = false;
+  }
+
   nsPresContext* presContext = mOuter->PresContext();
   nscoord appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
   // 'scale' is our estimate of the scale factor that will be applied
   // when rendering the scrolled content to its own PaintedLayer.
   gfxSize scale =
       FrameLayerBuilder::GetPaintedLayerScaleForFrame(mScrolledFrame);
   nsPoint curPos = GetScrollPosition();
+
   nsPoint alignWithPos = mScrollPosForLayerPixelAlignment == nsPoint(-1, -1)
                              ? curPos
                              : mScrollPosForLayerPixelAlignment;
   // Try to align aPt with curPos so they have an integer number of layer
   // pixels between them. This gives us the best chance of scrolling without
   // having to invalidate due to changes in subpixel rendering.
   // Note that when we actually draw into a PaintedLayer, the coordinates
   // that get mapped onto the layer buffer pixels are from the display list,
@@ -2733,35 +2765,22 @@ void ScrollFrameHelper::ScrollToImpl(nsP
   nsRect oldDisplayPort;
   nsIContent* content = mOuter->GetContent();
   nsLayoutUtils::GetHighResolutionDisplayPort(content, &oldDisplayPort);
   oldDisplayPort.MoveBy(-mScrolledFrame->GetPosition());
 
   // Update frame position for scrolling
   mScrolledFrame->SetPosition(mScrollPort.TopLeft() - pt);
 
-  // If this scroll is |relative|, but we've already had a user scroll that
-  // was not relative, promote this origin to |other|. This ensures that we
-  // may only transmit a relative update to APZ if all scrolls since the last
-  // transaction or repaint request have been relative.
-  if (aOrigin == nsGkAtoms::relative &&
-      (mLastScrollOrigin && mLastScrollOrigin != nsGkAtoms::relative &&
-       mLastScrollOrigin != nsGkAtoms::apz)) {
-    aOrigin = nsGkAtoms::other;
-  }
-
   // If |mLastScrollOrigin| is already set to something that can clobber APZ's
   // scroll offset, then we don't want to change it to something that can't.
   // If we allowed this, then we could end up in a state where APZ ignores
   // legitimate scroll offset updates because the origin has been masked by
   // a later change within the same refresh driver tick.
-  bool isScrollOriginDowngrade =
-      nsLayoutUtils::CanScrollOriginClobberApz(mLastScrollOrigin) &&
-      !nsLayoutUtils::CanScrollOriginClobberApz(aOrigin);
-  bool allowScrollOriginChange =
+  allowScrollOriginChange =
       mAllowScrollOriginDowngrade || !isScrollOriginDowngrade;
 
   if (allowScrollOriginChange) {
     mLastScrollOrigin = aOrigin;
     mAllowScrollOriginDowngrade = false;
   }
   mLastSmoothScrollOrigin = nullptr;
   mScrollGeneration = ++sScrollGenerationCounter;
@@ -4465,16 +4484,20 @@ void ScrollFrameHelper::ScrollToRestored
       AutoWeakFrame weakFrame(mOuter);
       // It's very important to pass nsGkAtoms::restore here, so
       // ScrollToWithOrigin won't clear out mRestorePos.
       ScrollToWithOrigin(scrollToPos, nsIScrollableFrame::INSTANT,
                          nsGkAtoms::restore, nullptr);
       if (!weakFrame.IsAlive()) {
         return;
       }
+      if (mIsRoot && mOuter->PresContext()->IsRootContentDocument()) {
+        mOuter->PresShell()->SetPendingVisualScrollUpdate(
+            scrollToPos, FrameMetrics::eRestore);
+      }
       if (state == LoadingState::Loading || NS_SUBTREE_DIRTY(mOuter)) {
         // If we're trying to do a history scroll restore, then we want to
         // keep trying this until we succeed, because the page can be loading
         // incrementally. So re-get the scroll position for the next iteration,
         // it might not be exactly equal to mRestorePos due to rounding and
         // clamping.
         mLastPos = GetLogicalVisualViewportOffset();
         return;
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1987,32 +1987,38 @@ class nsIFrame : public nsQueryFrame {
 
   /**
    * Ensure that aImage gets notifed when the underlying image request loads
    * or animates.
    */
   void AssociateImage(const nsStyleImage& aImage, nsPresContext* aPresContext,
                       uint32_t aImageLoaderFlags);
 
-  /**
-   * This structure holds information about a cursor. mContainer represents a
-   * loaded image that should be preferred. If it is not possible to use it, or
-   * if it is null, mCursor should be used.
+  enum class AllowCustomCursorImage {
+    No,
+    Yes,
+  };
+
+  /**
+   * This structure holds information about a cursor. AllowCustomCursorImage
+   * is `No`, then no cursor image should be loaded from the style specified on
+   * `mStyle`, or the frame's style.
+   *
+   * The `mStyle` member is used for `<area>` elements.
    */
   struct MOZ_STACK_CLASS Cursor {
-    nsCOMPtr<imgIContainer> mContainer;
     mozilla::StyleCursorKind mCursor = mozilla::StyleCursorKind::Auto;
-    bool mHaveHotspot = false;
-    bool mLoading = false;
-    float mHotspotX = 0.0f, mHotspotY = 0.0f;
+    AllowCustomCursorImage mAllowCustomCursor = AllowCustomCursorImage::Yes;
+    RefPtr<mozilla::ComputedStyle> mStyle;
   };
+
   /**
    * Get the cursor for a given frame.
    */
-  virtual nsresult GetCursor(const nsPoint& aPoint, Cursor& aCursor) = 0;
+  virtual mozilla::Maybe<Cursor> GetCursor(const nsPoint&);
 
   /**
    * Get a point (in the frame's coordinate space) given an offset into
    * the content. This point should be on the baseline of text with
    * the correct horizontal offset
    */
   virtual nsresult GetPointFromOffset(int32_t inOffset, nsPoint* outPoint) = 0;
 
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -2298,39 +2298,36 @@ nsresult nsImageFrame::HandleEvent(nsPre
       }
     }
   }
 
   return nsAtomicContainerFrame::HandleEvent(aPresContext, aEvent,
                                              aEventStatus);
 }
 
-nsresult nsImageFrame::GetCursor(const nsPoint& aPoint,
-                                 nsIFrame::Cursor& aCursor) {
-  if (nsImageMap* map = GetImageMap()) {
-    nsIntPoint p;
-    TranslateEventCoords(aPoint, p);
-    nsCOMPtr<nsIContent> area = map->GetArea(p.x, p.y);
-    if (area) {
-      // Use the cursor from the style of the *area* element.
-      // XXX Using the image as the parent ComputedStyle isn't
-      // technically correct, but it's probably the right thing to do
-      // here, since it means that areas on which the cursor isn't
-      // specified will inherit the style from the image.
-      RefPtr<ComputedStyle> areaStyle =
-          PresShell()->StyleSet()->ResolveStyleFor(area->AsElement(),
-                                                   LazyComputeBehavior::Allow);
-      FillCursorInformationFromStyle(areaStyle->StyleUI(), aCursor);
-      if (StyleCursorKind::Auto == aCursor.mCursor) {
-        aCursor.mCursor = StyleCursorKind::Default;
-      }
-      return NS_OK;
-    }
+Maybe<nsIFrame::Cursor> nsImageFrame::GetCursor(const nsPoint& aPoint) {
+  nsImageMap* map = GetImageMap();
+  if (!map) {
+    return nsFrame::GetCursor(aPoint);
   }
-  return nsFrame::GetCursor(aPoint, aCursor);
+  nsIntPoint p;
+  TranslateEventCoords(aPoint, p);
+  nsCOMPtr<nsIContent> area = map->GetArea(p.x, p.y);
+  if (!area) {
+    return nsFrame::GetCursor(aPoint);
+  }
+
+  // Use the cursor from the style of the *area* element.
+  RefPtr<ComputedStyle> areaStyle = PresShell()->StyleSet()->ResolveStyleFor(
+      area->AsElement(), LazyComputeBehavior::Allow);
+  StyleCursorKind kind = areaStyle->StyleUI()->mCursor;
+  if (kind == StyleCursorKind::Auto) {
+    kind = StyleCursorKind::Default;
+  }
+  return Some(Cursor{kind, AllowCustomCursorImage::Yes, std::move(areaStyle)});
 }
 
 nsresult nsImageFrame::AttributeChanged(int32_t aNameSpaceID,
                                         nsAtom* aAttribute, int32_t aModType) {
   nsresult rv = nsAtomicContainerFrame::AttributeChanged(aNameSpaceID,
                                                          aAttribute, aModType);
   if (NS_FAILED(rv)) {
     return rv;
--- a/layout/generic/nsImageFrame.h
+++ b/layout/generic/nsImageFrame.h
@@ -89,18 +89,17 @@ class nsImageFrame : public nsAtomicCont
                       const ReflowInput& aReflowInput,
                       nsReflowStatus& aStatus) override;
 
   virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
                                       nsIContent** aContent) override;
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
+  mozilla::Maybe<Cursor> GetCursor(const nsPoint&) override;
   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
                                     int32_t aModType) override;
 
   void OnVisibilityChange(
       Visibility aNewVisibility,
       const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
 
   void ResponsiveContentDensityChanged();
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -1583,34 +1583,33 @@ bool nsPluginFrame::WantsToHandleWheelEv
 nsNPAPIPluginInstance* nsPluginFrame::GetPluginInstance() {
   if (!mInstanceOwner) {
     return nullptr;
   }
 
   return mInstanceOwner->GetInstance();
 }
 
-nsresult nsPluginFrame::GetCursor(const nsPoint& aPoint,
-                                  nsIFrame::Cursor& aCursor) {
+Maybe<nsIFrame::Cursor> nsPluginFrame::GetCursor(const nsPoint& aPoint) {
   if (!mInstanceOwner) {
-    return NS_ERROR_FAILURE;
+    return Nothing();
   }
 
   RefPtr<nsNPAPIPluginInstance> inst = mInstanceOwner->GetInstance();
   if (!inst) {
-    return NS_ERROR_FAILURE;
+    return Nothing();
   }
 
   bool useDOMCursor =
       static_cast<nsNPAPIPluginInstance*>(inst.get())->UsesDOMForCursor();
   if (!useDOMCursor) {
-    return NS_ERROR_FAILURE;
+    return Nothing();
   }
 
-  return nsFrame::GetCursor(aPoint, aCursor);
+  return nsFrame::GetCursor(aPoint);
 }
 
 void nsPluginFrame::SetIsDocumentActive(bool aIsActive) {
   if (mInstanceOwner) {
     mInstanceOwner->UpdateDocumentActiveState(aIsActive);
   }
 }
 
--- a/layout/generic/nsPluginFrame.h
+++ b/layout/generic/nsPluginFrame.h
@@ -101,18 +101,17 @@ class nsPluginFrame final : public nsFra
                            PostDestroyData& aPostDestroyData) override;
 
   virtual void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) override;
 
   nsNPAPIPluginInstance* GetPluginInstance() override;
 
   virtual void SetIsDocumentActive(bool aIsActive) override;
 
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
+  mozilla::Maybe<Cursor> GetCursor(const nsPoint&) override;
 
   // APIs used by nsRootPresContext to set up the widget position/size/clip
   // region.
   /**
    * Set the next widget configuration for the plugin to the desired
    * position of the plugin's widget, on the assumption that it is not visible
    * (clipped out or covered by opaque content).
    * This will only be called for plugins which have been registered
--- a/layout/generic/nsTextFrame.cpp
+++ b/layout/generic/nsTextFrame.cpp
@@ -4589,31 +4589,27 @@ nsIFrame* NS_NewContinuingTextFrame(nsIP
   return new (aPresShell)
       nsContinuingTextFrame(aStyle, aPresShell->GetPresContext());
 }
 
 NS_IMPL_FRAMEARENA_HELPERS(nsContinuingTextFrame)
 
 nsTextFrame::~nsTextFrame() {}
 
-nsresult nsTextFrame::GetCursor(const nsPoint& aPoint,
-                                nsIFrame::Cursor& aCursor) {
-  FillCursorInformationFromStyle(StyleUI(), aCursor);
-  if (StyleCursorKind::Auto == aCursor.mCursor) {
+Maybe<nsIFrame::Cursor> nsTextFrame::GetCursor(const nsPoint& aPoint) {
+  StyleCursorKind kind = StyleUI()->mCursor;
+  if (kind == StyleCursorKind::Auto) {
     if (!IsSelectable(nullptr)) {
-      aCursor.mCursor = StyleCursorKind::Default;
+      kind = StyleCursorKind::Default;
     } else {
-      aCursor.mCursor = GetWritingMode().IsVertical()
-                            ? StyleCursorKind::VerticalText
-                            : StyleCursorKind::Text;
-    }
-    return NS_OK;
-  } else {
-    return nsFrame::GetCursor(aPoint, aCursor);
-  }
+      kind = GetWritingMode().IsVertical() ? StyleCursorKind::VerticalText
+                                           : StyleCursorKind::Text;
+    }
+  }
+  return Some(Cursor{kind, AllowCustomCursorImage::Yes});
 }
 
 nsTextFrame* nsTextFrame::LastInFlow() const {
   nsTextFrame* lastInFlow = const_cast<nsTextFrame*>(this);
   while (lastInFlow->GetNextInFlow()) {
     lastInFlow = lastInFlow->GetNextInFlow();
   }
   MOZ_ASSERT(lastInFlow, "post-condition failed");
--- a/layout/generic/nsTextFrame.h
+++ b/layout/generic/nsTextFrame.h
@@ -74,17 +74,17 @@ class nsTextFrame : public nsFrame {
                         const nsDisplayListSet& aLists) final;
 
   void Init(nsIContent* aContent, nsContainerFrame* aParent,
             nsIFrame* aPrevInFlow) override;
 
   void DestroyFrom(nsIFrame* aDestructRoot,
                    PostDestroyData& aPostDestroyData) override;
 
-  nsresult GetCursor(const nsPoint& aPoint, nsIFrame::Cursor& aCursor) final;
+  mozilla::Maybe<Cursor> GetCursor(const nsPoint&) final;
 
   nsresult CharacterDataChanged(const CharacterDataChangeInfo&) final;
 
   nsTextFrame* GetPrevContinuation() const override { return nullptr; }
   nsTextFrame* GetNextContinuation() const final { return mNextContinuation; }
   void SetNextContinuation(nsIFrame* aNextContinuation) final {
     NS_ASSERTION(!aNextContinuation || Type() == aNextContinuation->Type(),
                  "setting a next continuation with incorrect type!");
--- a/layout/painting/moz.build
+++ b/layout/painting/moz.build
@@ -63,15 +63,10 @@ LOCAL_INCLUDES += [
     '/layout/tables',
     '/layout/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
 CXXFLAGS += CONFIG['MOZ_CAIRO_CFLAGS']
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary hack to support building with VS2015.
-    # 'type cast': conversion from 'unsigned int' to 'void *' of greater size
-    CXXFLAGS += ['-wd4312']
-
 if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += ['-Wno-error=shadow']
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -444,16 +444,17 @@ cbindgen-types = [
     { gecko = "StylePerspective", servo = "values::computed::Perspective" },
     { gecko = "StyleGenericPerspective", servo = "values::generics::box_::Perspective" },
     { gecko = "StyleZIndex", servo = "values::computed::ZIndex" },
     { gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
     { gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
     { gecko = "StyleGenericBorderRadius", servo = "values::generics::border::BorderRadius" },
     { gecko = "StyleLetterSpacing", servo = "values::computed::text::LetterSpacing" },
     { gecko = "StyleGenericLineHeight", servo = "values::generics::text::LineHeight" },
+    { gecko = "StyleContain", servo = "values::computed::Contain" },
 ]
 
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::RustCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -309,31 +309,16 @@ enum class StyleContent : uint8_t {
 // values here accidentally use it in their binary representation.)
 #define NS_STYLE_WRITING_MODE_SIDEWAYS_MASK 4
 
 #define NS_STYLE_WRITING_MODE_SIDEWAYS_RL \
   (NS_STYLE_WRITING_MODE_VERTICAL_RL | NS_STYLE_WRITING_MODE_SIDEWAYS_MASK)
 #define NS_STYLE_WRITING_MODE_SIDEWAYS_LR \
   (NS_STYLE_WRITING_MODE_VERTICAL_LR | NS_STYLE_WRITING_MODE_SIDEWAYS_MASK)
 
-// See nsStyleDisplay
-// If these are re-ordered, nsComputedDOMStyle::DoGetContain() must be updated.
-#define NS_STYLE_CONTAIN_NONE 0
-#define NS_STYLE_CONTAIN_SIZE 0x01
-#define NS_STYLE_CONTAIN_LAYOUT 0x02
-#define NS_STYLE_CONTAIN_PAINT 0x04
-#define NS_STYLE_CONTAIN_STRICT 0x08
-#define NS_STYLE_CONTAIN_CONTENT 0x10
-// NS_STYLE_CONTAIN_ALL_BITS does not correspond to a keyword.
-#define NS_STYLE_CONTAIN_ALL_BITS \
-  (NS_STYLE_CONTAIN_LAYOUT | NS_STYLE_CONTAIN_PAINT | NS_STYLE_CONTAIN_SIZE)
-// NS_STYLE_CONTAIN_CONTENT_BITS does not correspond to a keyword.
-#define NS_STYLE_CONTAIN_CONTENT_BITS \
-  (NS_STYLE_CONTAIN_LAYOUT | NS_STYLE_CONTAIN_PAINT)
-
 // Shared constants for all align/justify properties (nsStylePosition):
 #define NS_STYLE_ALIGN_AUTO 0
 #define NS_STYLE_ALIGN_NORMAL 1
 #define NS_STYLE_ALIGN_START 2
 #define NS_STYLE_ALIGN_END 3
 #define NS_STYLE_ALIGN_FLEX_START 4
 #define NS_STYLE_ALIGN_FLEX_END 5
 #define NS_STYLE_ALIGN_CENTER 6
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2901,17 +2901,17 @@ bool StyleAnimation::operator==(const St
 }
 
 // --------------------
 // nsStyleDisplay
 //
 nsStyleDisplay::nsStyleDisplay(const Document& aDocument)
     : mDisplay(StyleDisplay::Inline),
       mOriginalDisplay(StyleDisplay::Inline),
-      mContain(NS_STYLE_CONTAIN_NONE),
+      mContain(StyleContain_NONE),
       mAppearance(StyleAppearance::None),
       mPosition(NS_STYLE_POSITION_STATIC),
       mFloat(StyleFloat::None),
       mOriginalFloat(StyleFloat::None),
       mBreakType(StyleClear::None),
       mBreakInside(StyleBreakWithin::Auto),
       mBreakBefore(StyleBreakBetween::Auto),
       mBreakAfter(StyleBreakBetween::Auto),
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1854,17 +1854,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   // mBinding->mOriginPrincipal.
   RefPtr<mozilla::css::URLValue> mBinding;
   mozilla::StyleDisplay mDisplay;
   mozilla::StyleDisplay mOriginalDisplay;  // saved mDisplay for
                                            //         position:absolute/fixed
                                            //         and float:left/right;
                                            //         otherwise equal to
                                            //         mDisplay
-  uint8_t mContain;                        // NS_STYLE_CONTAIN_*
+  mozilla::StyleContain mContain;
   mozilla::StyleAppearance mAppearance;
   uint8_t mPosition;  // NS_STYLE_POSITION_*
 
   mozilla::StyleFloat mFloat;
   // Save mFloat for position:absolute/fixed; otherwise equal to mFloat.
   mozilla::StyleFloat mOriginalFloat;
 
   mozilla::StyleClear mBreakType;
@@ -2111,41 +2111,42 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   bool IsScrollableOverflow() const {
     // mOverflowX and mOverflowY always match when one of them is
     // Visible or MozHiddenUnscrollable.
     return mOverflowX != mozilla::StyleOverflow::Visible &&
            mOverflowX != mozilla::StyleOverflow::MozHiddenUnscrollable;
   }
 
   bool IsContainPaint() const {
-    return (NS_STYLE_CONTAIN_PAINT & mContain) &&
+    return (mContain & mozilla::StyleContain_PAINT) &&
            !IsInternalRubyDisplayType() && !IsInternalTableStyleExceptCell();
   }
 
   bool IsContainLayout() const {
     // Note: The spec for layout containment says it should
     // have no effect on non-atomic, inline-level boxes. We
     // don't check for these here because we don't know
     // what type of element is involved. Callers are
     // responsible for checking if the box in question is
     // non-atomic and inline-level, and creating an
     // exemption as necessary.
-    return (NS_STYLE_CONTAIN_LAYOUT & mContain) &&
+    return (mContain & mozilla::StyleContain_LAYOUT) &&
            !IsInternalRubyDisplayType() && !IsInternalTableStyleExceptCell();
   }
 
   bool IsContainSize() const {
     // Note: The spec for size containment says it should
     // have no effect on non-atomic, inline-level boxes. We
     // don't check for these here because we don't know
     // what type of element is involved. Callers are
     // responsible for checking if the box in question is
     // non-atomic and inline-level, and creating an
     // exemption as necessary.
-    return (NS_STYLE_CONTAIN_SIZE & mContain) && !IsInternalRubyDisplayType() &&
+    return (mContain & mozilla::StyleContain_SIZE) &&
+           !IsInternalRubyDisplayType() &&
            (mozilla::StyleDisplay::Table != mDisplay) && !IsInnerTableStyle();
   }
 
   /* Returns whether the element has the -moz-transform property
    * or a related property. */
   bool HasTransformStyle() const {
     return mSpecifiedTransform || mSpecifiedRotate || mSpecifiedTranslate ||
            mSpecifiedScale ||
--- a/layout/xul/nsSplitterFrame.cpp
+++ b/layout/xul/nsSplitterFrame.cpp
@@ -211,30 +211,16 @@ void nsSplitterFrame::DestroyFrom(nsIFra
     mInner->RemoveListener();
     mInner->Disconnect();
     mInner->Release();
     mInner = nullptr;
   }
   nsBoxFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
 }
 
-nsresult nsSplitterFrame::GetCursor(const nsPoint& aPoint,
-                                    nsIFrame::Cursor& aCursor) {
-  return nsBoxFrame::GetCursor(aPoint, aCursor);
-
-  /*
-    if (IsXULHorizontal())
-      aCursor = NS_STYLE_CURSOR_N_RESIZE;
-    else
-      aCursor = NS_STYLE_CURSOR_W_RESIZE;
-
-    return NS_OK;
-  */
-}
-
 nsresult nsSplitterFrame::AttributeChanged(int32_t aNameSpaceID,
                                            nsAtom* aAttribute,
                                            int32_t aModType) {
   nsresult rv =
       nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute, aModType);
   if (aAttribute == nsGkAtoms::state) {
     mInner->UpdateState();
   }
--- a/layout/xul/nsSplitterFrame.h
+++ b/layout/xul/nsSplitterFrame.h
@@ -35,19 +35,16 @@ class nsSplitterFrame final : public nsB
 
   // nsIFrame overrides
   virtual nsresult AttributeChanged(int32_t aNameSpaceID, nsAtom* aAttribute,
                                     int32_t aModType) override;
 
   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
                     nsIFrame* aPrevInFlow) override;
 
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
-
   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) override;
 
   NS_IMETHOD HandlePress(nsPresContext* aPresContext,
                          mozilla::WidgetGUIEvent* aEvent,
                          nsEventStatus* aEventStatus) override;
 
   NS_IMETHOD HandleMultiplePress(nsPresContext* aPresContext,
                                  mozilla::WidgetGUIEvent* aEvent,
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -2214,40 +2214,38 @@ nscoord nsTreeBodyFrame::CalcHorzWidth(c
   }
 
   // If no horz scrolling periphery is present, then just return our width
   if (width == 0) width = mRect.width;
 
   return width;
 }
 
-nsresult nsTreeBodyFrame::GetCursor(const nsPoint& aPoint,
-                                    nsIFrame::Cursor& aCursor) {
+Maybe<nsIFrame::Cursor> nsTreeBodyFrame::GetCursor(const nsPoint& aPoint) {
   // Check the GetScriptHandlingObject so we don't end up running code when
   // the document is a zombie.
   bool dummy;
   if (mView && GetContent()->GetComposedDoc()->GetScriptHandlingObject(dummy)) {
     int32_t row;
     nsTreeColumn* col;
     nsCSSAnonBoxPseudoStaticAtom* child;
     GetCellAt(aPoint.x, aPoint.y, &row, &col, &child);
 
     if (child) {
       // Our scratch array is already prefilled.
-      ComputedStyle* childContext = GetPseudoComputedStyle(child);
-
-      FillCursorInformationFromStyle(childContext->StyleUI(), aCursor);
-      if (aCursor.mCursor == StyleCursorKind::Auto)
-        aCursor.mCursor = StyleCursorKind::Default;
-
-      return NS_OK;
+      RefPtr<ComputedStyle> childContext = GetPseudoComputedStyle(child);
+      StyleCursorKind kind = childContext->StyleUI()->mCursor;
+      if (kind == StyleCursorKind::Auto) {
+        kind = StyleCursorKind::Default;
+      }
+      return Some(
+          Cursor{kind, AllowCustomCursorImage::Yes, std::move(childContext)});
     }
   }
-
-  return nsLeafBoxFrame::GetCursor(aPoint, aCursor);
+  return nsLeafBoxFrame::GetCursor(aPoint);
 }
 
 static uint32_t GetDropEffect(WidgetGUIEvent* aEvent) {
   NS_ASSERTION(aEvent->mClass == eDragEventClass, "wrong event type");
   WidgetDragEvent* dragEvent = aEvent->AsDragEvent();
   nsContentUtils::SetDataTransferInEvent(dragEvent);
 
   uint32_t action = 0;
--- a/layout/xul/tree/nsTreeBodyFrame.h
+++ b/layout/xul/tree/nsTreeBodyFrame.h
@@ -151,18 +151,17 @@ class nsTreeBodyFrame final : public nsL
   }
 
   // Overridden from nsIFrame to cache our pres context.
   virtual void Init(nsIContent* aContent, nsContainerFrame* aParent,
                     nsIFrame* aPrevInFlow) override;
   virtual void DestroyFrom(nsIFrame* aDestructRoot,
                            PostDestroyData& aPostDestroyData) override;
 
-  virtual nsresult GetCursor(const nsPoint& aPoint,
-                             nsIFrame::Cursor& aCursor) override;
+  mozilla::Maybe<Cursor> GetCursor(const nsPoint&) override;
 
   virtual nsresult HandleEvent(nsPresContext* aPresContext,
                                mozilla::WidgetGUIEvent* aEvent,
                                nsEventStatus* aEventStatus) override;
 
   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
                                 const nsDisplayListSet& aLists) override;
 
--- a/media/webrtc/signaling/gtest/moz.build
+++ b/media/webrtc/signaling/gtest/moz.build
@@ -36,17 +36,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'uiki
 
     # See Bug 1372950, mediapipeline tests seem to cause crashes on Windows
     if CONFIG['OS_TARGET'] != 'WINNT':
         SOURCES += [
             'mediapipeline_unittest.cpp',
         ]
 
     FINAL_LIBRARY = 'xul-gtest'
-
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary workaround to enable warning free building
-    # with VS2015.
-    # reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size
-    CXXFLAGS += ['-wd4312']
-
-    # Disable warning for decorated name length exceeded, name was truncated
-    CXXFLAGS += ['-wd4503']
--- a/media/webrtc/trunk/gtest/moz.build
+++ b/media/webrtc/trunk/gtest/moz.build
@@ -476,15 +476,9 @@ if CONFIG['OS_TARGET'] in ['Darwin', 'Li
     if CONFIG['CC_TYPE'] in ('clang', 'gcc'):
         CXXFLAGS += [
             '-Wno-inconsistent-missing-override',
             '-Wno-overloaded-virtual',
         ]
         if CONFIG['CC_TYPE'] == 'clang':
             CXXFLAGS += ['-Wno-comma']
 
-    if CONFIG['CC_TYPE'] == 'clang-cl':
-        # This is intended as a temporary workaround to enable warning free building
-        # with VS2015.
-        # reinterpret_cast': conversion from 'DWORD' to 'HANDLE' of greater size
-        CXXFLAGS += ['-wd4312']
-
     GeckoProgram('webrtc-gtest', linkage=None)
--- a/memory/build/moz.build
+++ b/memory/build/moz.build
@@ -41,18 +41,15 @@ Library('memory')
 if CONFIG['OS_TARGET'] == 'Android' and CONFIG['CC_TYPE'] == 'clang':
     CXXFLAGS += [
         '-Wno-tautological-pointer-compare',
     ]
 
 if CONFIG['MOZ_BUILD_APP'] != 'memory':
     FINAL_LIBRARY = 'mozglue'
 
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    CXXFLAGS += ['-wd4273'] # inconsistent dll linkage (bug 558163)
-
 if CONFIG['MOZ_REPLACE_MALLOC_STATIC']:
     DEFINES['MOZ_REPLACE_MALLOC_STATIC'] = True
 
 DisableStlWrapping()
 
 if CONFIG['CC_TYPE'] == 'clang-cl':
     AllowCompilerWarnings()  # workaround for bug 1090497
--- a/mobile/android/mach_commands.py
+++ b/mobile/android/mach_commands.py
@@ -50,17 +50,17 @@ def REMOVED(cls):
 @CommandProvider
 class MachCommands(MachCommandBase):
     def _root_url(self, artifactdir=None, objdir=None):
         """Generate a publicly-accessible URL for the tasks's artifacts, or an objdir path"""
         if 'TASK_ID' in os.environ and 'RUN_ID' in os.environ:
             import taskcluster_urls
             from taskgraph.util.taskcluster import get_root_url
             return taskcluster_urls.api(
-                get_root_url(), 'queue', 'v1', 'task/{}/runs/{}/artifacts/{}'.format(
+                get_root_url(False), 'queue', 'v1', 'task/{}/runs/{}/artifacts/{}'.format(
                     os.environ['TASK_ID'], os.environ['RUN_ID'], artifactdir))
         else:
             return os.path.join(self.topobjdir, objdir)
 
     @Command('android', category='devenv',
              description='Run Android-specific commands.',
              conditions=[conditions.is_android])
     def android(self):
--- a/mobile/android/tests/browser/chrome/head_scroll.js
+++ b/mobile/android/tests/browser/chrome/head_scroll.js
@@ -11,22 +11,31 @@ function getFrame(browser, { frame = nul
     window = browser.contentWindow.frames[frame];
   } else {
     window = browser.contentWindow;
   }
   return window;
 }
 
 function setScrollPosition(browser,
-                           { x = 0, y = 0, zoom = 0, frame }) {
+                           { x = 0, y = 0, zoom = 0, frame = null }) {
   let window = getFrame(browser, {frame});
+  let topLevelUtils = browser.contentWindow.windowUtils;
   if (zoom) {
-    browser.contentWindow.windowUtils.setResolutionAndScaleTo(zoom);
+    topLevelUtils.setResolutionAndScaleTo(zoom);
   }
-  window.scrollTo(x, y);
+  // The root content document has a distinction between visual and layout
+  // scroll positions. We want to set the visual one.
+  // For frames, there is no such distinction and scrollToVisual() does
+  // not support them, so use window.scrollTo().
+  if (frame !== null) {
+    window.scrollTo(x, y);
+  } else {
+    topLevelUtils.scrollToVisual(x, y, topLevelUtils.UPDATE_TYPE_MAIN_THREAD);
+  }
 }
 
 function checkScroll(browser, data) {
   let {x, y, zoom} = data;
   let scrollPos = getScrollPosition(browser, data);
 
   if (data.hasOwnProperty("x")) {
     is(scrollPos.x, x, "scrollX set correctly");
--- a/mobile/android/tests/browser/chrome/test_session_scroll_position.html
+++ b/mobile/android/tests/browser/chrome/test_session_scroll_position.html
@@ -55,16 +55,21 @@ https://bugzilla.mozilla.org/show_bug.cg
 
   function cleanupTabs() {
     if (tabScroll) {
       BrowserApp.closeTab(tabScroll);
       tabScroll = null;
     }
   }
 
+  function promiseVisualScrollEvent(browser) {
+    return promiseBrowserEvent(browser, "mozvisualscroll",
+                               { mozSystemGroup: true });
+  }
+
   SimpleTest.registerCleanupFunction(function() {
     cleanupTabs();
   });
 
   let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
 
   add_task(async function test_sessionStoreScrollPositionReaderMode() {
     let testData = {x: 0, y: SCROLL_Y};
@@ -73,17 +78,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       return Task.spawn(function* () {
         // Create a new tab.
         tabScroll = BrowserApp.addTab(URL_reader);
         let browser = tabScroll.browser;
         yield promiseBrowserEvent(browser, "AboutReaderContentReady");
 
         // Modify scroll position.
         setScrollPosition(browser, testData);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(browser);
 
         // Check that we've actually scrolled.
         checkScroll(browser, testData);
 
         // Remove the tab.
         BrowserApp.closeTab(tabScroll);
         yield promiseTabEvent(browser, "SSTabCloseProcessed");
       });
@@ -114,27 +119,27 @@ https://bugzilla.mozilla.org/show_bug.cg
       return Task.spawn(function* () {
         // Create a new tab.
         tabScroll = BrowserApp.addTab(URL);
         let browser = tabScroll.browser;
         yield promiseBrowserEvent(browser, "pageshow");
 
         // Modify scroll position and zoom level.
         setScrollPosition(browser, testData1);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(browser);
 
         // Check that we've actually scrolled and zoomed.
         checkScroll(browser, testData1);
 
         // Navigate to a different page and scroll/zoom there as well.
         browser.loadURI(URL2);
         yield promiseBrowserEvent(browser, "pageshow");
 
         setScrollPosition(browser, testData2);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(browser);
 
         checkScroll(browser, testData2);
 
         // Remove the tab.
         BrowserApp.closeTab(tabScroll);
         yield promiseTabEvent(browser, "SSTabCloseProcessed");
       });
     }
@@ -144,30 +149,28 @@ https://bugzilla.mozilla.org/show_bug.cg
     let [{scrolldata}] = state;
     is(scrolldata.scroll, getScrollString(testData2), "stored scroll position is correct");
     ok(fuzzyEquals(scrolldata.zoom.resolution, ZOOM2), "stored zoom level is correct");
 
     // Restore the closed tab.
     let closedTabData = ss.getClosedTabs(chromeWin)[0];
     let browser = ss.undoCloseTab(chromeWin, closedTabData);
     let pageshow = promiseBrowserEvent(browser, "pageshow");
-    let scroll = promiseBrowserEvent(browser, "mozvisualscroll",
-                                     { mozSystemGroup: true });
+    let scroll = promiseVisualScrollEvent(browser);
     await pageshow;
     await scroll;
 
     // Check the scroll position and zoom level.
     checkScroll(browser, testData2);
 
     // Now go back in history and check that the scroll position
     // is restored there as well.
     is(browser.canGoBack, true, "can go back");
     pageshow = promiseBrowserEvent(browser, "pageshow");
-    scroll = promiseBrowserEvent(browser, "mozvisualscroll",
-                                 { mozSystemGroup: true });
+    scroll = promiseVisualScrollEvent(browser);
     browser.goBack();
     await pageshow;
     await scroll;
 
     checkScroll(browser, testData1);
 
     // Remove the tab.
     BrowserApp.closeTab(BrowserApp.getTabForBrowser(browser));
@@ -180,17 +183,17 @@ https://bugzilla.mozilla.org/show_bug.cg
       return Task.spawn(function* () {
         // Create a new tab.
         tabScroll = BrowserApp.addTab(URL);
         let browser = tabScroll.browser;
         yield promiseBrowserEvent(browser, "pageshow");
 
         // Modify scroll position and zoom level.
         setScrollPosition(browser, testData);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(browser);
 
         // Check that we've actually scrolled and zoomed.
         checkScroll(browser, testData);
 
         // Remove the tab.
         BrowserApp.closeTab(tabScroll);
         yield promiseTabEvent(browser, "SSTabCloseProcessed");
       });
@@ -230,27 +233,27 @@ https://bugzilla.mozilla.org/show_bug.cg
       return Task.spawn(function* () {
         // Create a new tab.
         tabScroll = BrowserApp.addTab(URL_FRAMESET);
         let browser = tabScroll.browser;
         yield promiseBrowserEvent(browser, "pageshow");
 
         // Move the frameset itself.
         setScrollPosition(browser, testDataParent);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(browser);
         checkScroll(browser, testDataParent);
 
         // Modify scroll position and zoom level for one frame...
         setScrollPosition(browser, testData1);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(getFrame(browser, testData1));
         checkScroll(browser, testData1);
 
         // ... and the other.
         setScrollPosition(browser, testData2);
-        yield promiseTabEvent(browser, "SSTabScrollCaptured");
+        yield promiseVisualScrollEvent(getFrame(browser, testData2));
         checkScroll(browser, testData2);
 
         // Remove the tab.
         BrowserApp.closeTab(tabScroll);
         yield promiseTabEvent(browser, "SSTabCloseProcessed");
       });
     }
 
@@ -263,25 +266,19 @@ https://bugzilla.mozilla.org/show_bug.cg
 
     // Restore the closed tab.
     let closedTabData = ss.getClosedTabs(chromeWin)[0];
     let browser = ss.undoCloseTab(chromeWin, closedTabData);
     let pageshow = promiseBrowserEvent(browser, "pageshow");
     // We can't add event listeners for the frames until we're sure that they've actually loaded.
     let load = promiseBrowserEvent(browser, "load");
     await load;
-    let scrollParent = promiseBrowserEvent(getFrame(browser, testDataParent),
-                                           "mozvisualscroll",
-                                           { mozSystemGroup: true });
-    let scroll1 = promiseBrowserEvent(getFrame(browser, testData1),
-                                      "mozvisualscroll",
-                                      { mozSystemGroup: true });
-    let scroll2 = promiseBrowserEvent(getFrame(browser, testData2),
-                                      "mozvisualscroll",
-                                      { mozSystemGroup: true });
+    let scrollParent = promiseVisualScrollEvent(getFrame(browser, testDataParent));
+    let scroll1 = promiseVisualScrollEvent(getFrame(browser, testData1));
+    let scroll2 = promiseVisualScrollEvent(getFrame(browser, testData2));
     await pageshow;
     await scrollParent;
     await scroll1;
     await scroll2;
 
     // Check the scroll position and zoom level.
     checkScroll(browser, testDataParent);
     checkScroll(browser, testData1);
--- a/mobile/android/themes/core/aboutReader.css
+++ b/mobile/android/themes/core/aboutReader.css
@@ -31,50 +31,19 @@ body.dark {
 body.sans-serif {
   font-family: sans-serif;
 }
 
 body.serif {
   font-family: serif;
 }
 
-.container.font-size1 {
-  font-size: 10px;
-}
-
-.container.font-size2 {
-  font-size: 12px;
-}
-
-.container.font-size3 {
-  font-size: 14px;
-}
-
-.container.font-size4  {
-  font-size: 16px;
-}
-
-.container.font-size5 {
-  font-size: 18px;
-}
-
-.container.font-size6 {
-  font-size: 20px;
-}
-
-.container.font-size7 {
-  font-size: 22px;
-}
-
-.container.font-size8 {
-  font-size: 24px;
-}
-
-.container.font-size9 {
-  font-size: 26px;
+.container {
+  --font-size: 12;
+  font-size: var(--font-size);
 }
 
 /* Override some controls and content styles based on color scheme */
 
 body.light > .container > .header > .domain {
   color: #ee7600;
   border-bottom-color: #d0d0d0; 
 }
--- a/netwerk/ipc/NeckoChannelParams.ipdlh
+++ b/netwerk/ipc/NeckoChannelParams.ipdlh
@@ -12,17 +12,16 @@ include BlobTypes;
 include ClientIPCTypes;
 include URIParams;
 include IPCServiceWorkerDescriptor;
 include IPCStream;
 include PBackgroundSharedTypes;
 include DOMTypes;
 
 using mozilla::OriginAttributes from "mozilla/ipc/BackgroundUtils.h";
-using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using RequestHeaderTuples from "mozilla/net/PHttpChannelParams.h";
 using struct nsHttpAtom from "nsHttp.h";
 using class mozilla::net::nsHttpResponseHead from "nsHttpResponseHead.h";
 using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
 using nsILoadInfo::CrossOriginOpenerPolicy from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace net {
@@ -203,33 +202,21 @@ struct ChildLoadInfoForwarderArgs
   // a redirect.
   OptionalIPCServiceWorkerDescriptor controller;
 };
 
 //-----------------------------------------------------------------------------
 // HTTP IPDL structs
 //-----------------------------------------------------------------------------
 
-union OptionalHttpResponseHead
-{
-  void_t;
-  nsHttpResponseHead;
-};
-
 struct CorsPreflightArgs
 {
   nsCString[]   unsafeHeaders;
 };
 
-union OptionalCorsPreflightArgs
-{
-  void_t;
-  CorsPreflightArgs;
-};
-
 struct HttpChannelOpenArgs
 {
   URIParams                   uri;
   // - TODO: bug 571161: unclear if any HTTP channel clients ever
   // set originalURI != uri (about:credits?); also not clear if
   // chrome channel would ever need to know.  Get rid of next arg?
   URIParams?                  original;
   URIParams?                  doc;
@@ -253,21 +240,21 @@ struct HttpChannelOpenArgs
   nsCString                   entityID;
   bool                        chooseApplicationCache;
   nsCString                   appCacheClientID;
   bool                        allowSpdy;
   bool                        allowAltSvc;
   bool                        beConservative;
   uint32_t                    tlsFlags;
   LoadInfoArgs?               loadInfo;
-  OptionalHttpResponseHead    synthesizedResponseHead;
+  nsHttpResponseHead?         synthesizedResponseHead;
   nsCString                   synthesizedSecurityInfoSerialization;
   uint32_t                    cacheKey;
   uint64_t                    requestContextID;
-  OptionalCorsPreflightArgs   preflightArgs;
+  CorsPreflightArgs?          preflightArgs;
   uint32_t                    initialRwin;
   bool                        blockAuthPrompt;
   bool                        suspendAfterSynthesizeResponse;
   bool                        allowStaleCacheContent;
   nsCString                   contentTypeHint;
   uint32_t                    corsMode;
   uint32_t                    redirectMode;
   uint64_t                    channelId;
--- a/netwerk/protocol/http/HttpChannelChild.cpp
+++ b/netwerk/protocol/http/HttpChannelChild.cpp
@@ -2208,17 +2208,17 @@ HttpChannelChild::OnRedirectVerifyCallba
         NS_DISPATCH_NORMAL);
 
     return NS_OK;
   }
 
   RequestHeaderTuples emptyHeaders;
   RequestHeaderTuples* headerTuples = &emptyHeaders;
   nsLoadFlags loadFlags = 0;
-  OptionalCorsPreflightArgs corsPreflightArgs = mozilla::void_t();
+  Maybe<CorsPreflightArgs> corsPreflightArgs;
 
   nsCOMPtr<nsIHttpChannelChild> newHttpChannelChild =
       do_QueryInterface(mRedirectChannelChild);
   if (newHttpChannelChild && NS_SUCCEEDED(result)) {
     rv = newHttpChannelChild->AddCookiesToRequest();
     MOZ_ASSERT(NS_SUCCEEDED(rv));
     rv = newHttpChannelChild->GetClientSetRequestHeaders(&headerTuples);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
@@ -2670,31 +2670,30 @@ nsresult HttpChannelChild::ContinueAsync
 
   AutoIPCStream autoStream(openArgs.uploadStream());
   if (mUploadStream) {
     autoStream.Serialize(mUploadStream, ContentChild::GetSingleton());
     autoStream.TakeOptionalValue();
   }
 
   if (mResponseHead) {
-    openArgs.synthesizedResponseHead() = *mResponseHead;
+    openArgs.synthesizedResponseHead() = Some(*mResponseHead);
     openArgs.suspendAfterSynthesizeResponse() =
         mSuspendParentAfterSynthesizeResponse;
   } else {
-    openArgs.synthesizedResponseHead() = mozilla::void_t();
     openArgs.suspendAfterSynthesizeResponse() = false;
   }
 
   nsCOMPtr<nsISerializable> secInfoSer = do_QueryInterface(mSecurityInfo);
   if (secInfoSer) {
     NS_SerializeToString(secInfoSer,
                          openArgs.synthesizedSecurityInfoSerialization());
   }
 
-  OptionalCorsPreflightArgs optionalCorsPreflightArgs;
+  Maybe<CorsPreflightArgs> optionalCorsPreflightArgs;
   GetClientSetCorsPreflightParameters(optionalCorsPreflightArgs);
 
   // NB: This call forces us to cache mTopWindowURI if we haven't already.
   nsCOMPtr<nsIURI> uri;
   GetTopWindowURI(mURI, getter_AddRefs(uri));
 
   SerializeURI(mTopWindowURI, openArgs.topWindowURI());
 
@@ -3338,23 +3337,23 @@ NS_IMETHODIMP HttpChannelChild::AddCooki
 
 NS_IMETHODIMP HttpChannelChild::GetClientSetRequestHeaders(
     RequestHeaderTuples** aRequestHeaders) {
   *aRequestHeaders = &mClientSetRequestHeaders;
   return NS_OK;
 }
 
 void HttpChannelChild::GetClientSetCorsPreflightParameters(
-    OptionalCorsPreflightArgs& aArgs) {
+    Maybe<CorsPreflightArgs>& aArgs) {
   if (mRequireCORSPreflight) {
     CorsPreflightArgs args;
     args.unsafeHeaders() = mUnsafeHeaders;
-    aArgs = args;
+    aArgs.emplace(args);
   } else {
-    aArgs = mozilla::void_t();
+    aArgs = Nothing();
   }
 }
 
 NS_IMETHODIMP
 HttpChannelChild::RemoveCorsPreflightCacheEntry(nsIURI* aURI,
                                                 nsIPrincipal* aPrincipal) {
   URIParams uri;
   SerializeURI(aURI, uri);
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -391,20 +391,20 @@ bool HttpChannelParent::DoAsyncOpen(
     const nsCString& requestMethod, const Maybe<IPCStream>& uploadStream,
     const bool& uploadStreamHasHeaders, const int16_t& priority,
     const uint32_t& classOfService, const uint8_t& redirectionLimit,
     const bool& allowSTS, const uint32_t& thirdPartyFlags,
     const bool& doResumeAt, const uint64_t& startPos, const nsCString& entityID,
     const bool& chooseApplicationCache, const nsCString& appCacheClientID,
     const bool& allowSpdy, const bool& allowAltSvc, const bool& beConservative,
     const uint32_t& tlsFlags, const Maybe<LoadInfoArgs>& aLoadInfoArgs,
-    const OptionalHttpResponseHead& aSynthesizedResponseHead,
+    const Maybe<nsHttpResponseHead>& aSynthesizedResponseHead,
     const nsCString& aSecurityInfoSerialization, const uint32_t& aCacheKey,
     const uint64_t& aRequestContextID,
-    const OptionalCorsPreflightArgs& aCorsPreflightArgs,
+    const Maybe<CorsPreflightArgs>& aCorsPreflightArgs,
     const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt,
     const bool& aSuspendAfterSynthesizeResponse,
     const bool& aAllowStaleCacheContent, const nsCString& aContentTypeHint,
     const uint32_t& aCorsMode, const uint32_t& aRedirectMode,
     const uint64_t& aChannelId, const nsString& aIntegrityMetadata,
     const uint64_t& aContentWindowId,
     const nsTArray<PreferredAlternativeDataTypeParams>&
         aPreferredAlternativeTypes,
@@ -512,19 +512,18 @@ bool HttpChannelParent::DoAsyncOpen(
     }
   }
 
   RefPtr<HttpChannelParentListener> parentListener =
       new HttpChannelParentListener(this);
 
   httpChannel->SetRequestMethod(nsDependentCString(requestMethod.get()));
 
-  if (aCorsPreflightArgs.type() ==
-      OptionalCorsPreflightArgs::TCorsPreflightArgs) {
-    const CorsPreflightArgs& args = aCorsPreflightArgs.get_CorsPreflightArgs();
+  if (aCorsPreflightArgs.isSome()) {
+    const CorsPreflightArgs& args = aCorsPreflightArgs.ref();
     httpChannel->SetCorsPreflightParameters(args.unsafeHeaders());
   }
 
   nsCOMPtr<nsIInputStream> stream = DeserializeIPCStream(uploadStream);
   if (stream) {
     int64_t length;
     if (InputStreamLengthHelper::GetSyncLength(stream, &length)) {
       httpChannel->InternalSetUploadStreamLength(length >= 0 ? length : 0);
@@ -541,20 +540,18 @@ bool HttpChannelParent::DoAsyncOpen(
         self->TryInvokeAsyncOpen(NS_OK);
       });
     }
 
     httpChannel->InternalSetUploadStream(stream);
     httpChannel->SetUploadStreamHasHeaders(uploadStreamHasHeaders);
   }
 
-  if (aSynthesizedResponseHead.type() ==
-      OptionalHttpResponseHead::TnsHttpResponseHead) {
-    parentListener->SetupInterception(
-        aSynthesizedResponseHead.get_nsHttpResponseHead());
+  if (aSynthesizedResponseHead.isSome()) {
+    parentListener->SetupInterception(aSynthesizedResponseHead.ref());
     mWillSynthesizeResponse = true;
     httpChannelImpl->SetCouldBeSynthesized();
 
     if (!aSecurityInfoSerialization.IsEmpty()) {
       nsCOMPtr<nsISupports> secInfo;
       rv = NS_DeserializeObject(aSecurityInfoSerialization,
                                 getter_AddRefs(secInfo));
       MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv),
@@ -824,17 +821,17 @@ mozilla::ipc::IPCResult HttpChannelParen
 }
 
 mozilla::ipc::IPCResult HttpChannelParent::RecvRedirect2Verify(
     const nsresult& aResult, const RequestHeaderTuples& changedHeaders,
     const ChildLoadInfoForwarderArgs& aLoadInfoForwarder,
     const uint32_t& loadFlags, const uint32_t& referrerPolicy,
     const Maybe<URIParams>& aReferrerURI,
     const Maybe<URIParams>& aAPIRedirectURI,
-    const OptionalCorsPreflightArgs& aCorsPreflightArgs,
+    const Maybe<CorsPreflightArgs>& aCorsPreflightArgs,
     const bool& aChooseAppcache) {
   LOG(("HttpChannelParent::RecvRedirect2Verify [this=%p result=%" PRIx32 "]\n",
        this, static_cast<uint32_t>(aResult)));
 
   // Result from the child.  If something fails here, we might overwrite a
   // success with a further failure.
   nsresult result = aResult;
 
@@ -865,23 +862,21 @@ mozilla::ipc::IPCResult HttpChannelParen
       }
 
       // A successfully redirected channel must have the LOAD_REPLACE flag.
       MOZ_ASSERT(loadFlags & nsIChannel::LOAD_REPLACE);
       if (loadFlags & nsIChannel::LOAD_REPLACE) {
         newHttpChannel->SetLoadFlags(loadFlags);
       }
 
-      if (aCorsPreflightArgs.type() ==
-          OptionalCorsPreflightArgs::TCorsPreflightArgs) {
+      if (aCorsPreflightArgs.isSome()) {
         nsCOMPtr<nsIHttpChannelInternal> newInternalChannel =
             do_QueryInterface(newHttpChannel);
         MOZ_RELEASE_ASSERT(newInternalChannel);
-        const CorsPreflightArgs& args =
-            aCorsPreflightArgs.get_CorsPreflightArgs();
+        const CorsPreflightArgs& args = aCorsPreflightArgs.ref();
         newInternalChannel->SetCorsPreflightParameters(args.unsafeHeaders());
       }
 
       nsCOMPtr<nsIURI> referrerUri = DeserializeURI(aReferrerURI);
       rv = newHttpChannel->SetReferrerWithPolicy(referrerUri, referrerPolicy);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
 
       nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel =
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -149,20 +149,20 @@ class HttpChannelParent final : public n
       const bool& uploadStreamHasHeaders, const int16_t& priority,
       const uint32_t& classOfService, const uint8_t& redirectionLimit,
       const bool& allowSTS, const uint32_t& thirdPartyFlags,
       const bool& doResumeAt, const uint64_t& startPos,
       const nsCString& entityID, const bool& chooseApplicationCache,
       const nsCString& appCacheClientID, const bool& allowSpdy,
       const bool& allowAltSvc, const bool& beConservative,
       const uint32_t& tlsFlags, const Maybe<LoadInfoArgs>& aLoadInfoArgs,
-      const OptionalHttpResponseHead& aSynthesizedResponseHead,
+      const Maybe<nsHttpResponseHead>& aSynthesizedResponseHead,
       const nsCString& aSecurityInfoSerialization, const uint32_t& aCacheKey,
       const uint64_t& aRequestContextID,
-      const OptionalCorsPreflightArgs& aCorsPreflightArgs,
+      const Maybe<CorsPreflightArgs>& aCorsPreflightArgs,
       const uint32_t& aInitialRwin, const bool& aBlockAuthPrompt,
       const bool& aSuspendAfterSynthesizeResponse,
       const bool& aAllowStaleCacheContent, const nsCString& aContentTypeHint,
       const uint32_t& aCorsMode, const uint32_t& aRedirectMode,
       const uint64_t& aChannelId, const nsString& aIntegrityMetadata,
       const uint64_t& aContentWindowId,
       const nsTArray<PreferredAlternativeDataTypeParams>&
           aPreferredAlternativeTypes,
@@ -186,17 +186,17 @@ class HttpChannelParent final : public n
   virtual mozilla::ipc::IPCResult RecvResume() override;
   virtual mozilla::ipc::IPCResult RecvCancel(const nsresult& status) override;
   virtual mozilla::ipc::IPCResult RecvRedirect2Verify(
       const nsresult& result, const RequestHeaderTuples& changedHeaders,
       const ChildLoadInfoForwarderArgs& aLoadInfoForwarder,
       const uint32_t& loadFlags, const uint32_t& referrerPolicy,
       const Maybe<URIParams>& aReferrerURI,
       const Maybe<URIParams>& apiRedirectUri,
-      const OptionalCorsPreflightArgs& aCorsPreflightArgs,
+      const Maybe<CorsPreflightArgs>& aCorsPreflightArgs,
       const bool& aChooseAppcache) override;
   virtual mozilla::ipc::IPCResult RecvDocumentChannelCleanup(
       const bool& clearCacheEntry) override;
   virtual mozilla::ipc::IPCResult RecvMarkOfflineCacheEntryAsForeign() override;
   virtual mozilla::ipc::IPCResult RecvDivertOnDataAvailable(
       const nsCString& data, const uint64_t& offset,
       const uint32_t& count) override;
   virtual mozilla::ipc::IPCResult RecvDivertOnStopRequest(
--- a/netwerk/protocol/http/PHttpChannel.ipdl
+++ b/netwerk/protocol/http/PHttpChannel.ipdl
@@ -41,17 +41,17 @@ parent:
 
   async Cancel(nsresult status);
 
   // Reports approval/veto of redirect by child process redirect observers
   async Redirect2Verify(nsresult result, RequestHeaderTuples changedHeaders,
                         ChildLoadInfoForwarderArgs loadInfoForwarder,
                         uint32_t loadFlags, uint32_t referrerPolicy,
                         URIParams? referrerUri, URIParams? apiRedirectTo,
-                        OptionalCorsPreflightArgs corsPreflightArgs,
+                        CorsPreflightArgs? corsPreflightArgs,
                         bool chooseAppcache);
 
   // Sent to the parent in order signal that the child side listeners have been
   // set up and the parent side of the channel can be opened.
   async CrossProcessRedirectDone(nsresult result);
 
   // For document loads we keep this protocol open after child's
   // OnStopRequest, and send this msg (instead of __delete__) to allow
--- a/netwerk/protocol/http/nsIHttpChannelChild.idl
+++ b/netwerk/protocol/http/nsIHttpChannelChild.idl
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
 [ptr] native RequestHeaderTuples(mozilla::net::RequestHeaderTuples);
-[ref] native OptionalCorsPreflightArgsRef(mozilla::net::OptionalCorsPreflightArgs);
+[ref] native MaybeCorsPreflightArgsRef(mozilla::Maybe<mozilla::net::CorsPreflightArgs>);
 
 interface nsIPrincipal;
 interface nsIURI;
 
 [uuid(d02b96ed-2789-4f42-a25c-7abe63de7c18)]
 interface nsIHttpChannelChild : nsISupports
 {
   [must_use] void addCookiesToRequest();
@@ -22,15 +22,15 @@ interface nsIHttpChannelChild : nsISuppo
   void forceIntercepted(in boolean postRedirectChannelShouldIntercept,
                         in boolean postRedirectChannelShouldUpgrade);
 
   // Headers that the channel client has set via SetRequestHeader.
   [must_use] readonly attribute RequestHeaderTuples clientSetRequestHeaders;
 
   // Headers that the channel client has set via SetRequestHeader.
   [notxpcom, nostdcall]
-  void GetClientSetCorsPreflightParameters(in OptionalCorsPreflightArgsRef args);
+  void GetClientSetCorsPreflightParameters(in MaybeCorsPreflightArgsRef args);
 
   // This method is called by nsCORSListenerProxy if we need to remove
   // an entry from the CORS preflight cache in the parent process.
   [must_use]
   void removeCorsPreflightCacheEntry(in nsIURI aURI, in nsIPrincipal aRequestingPrincipal);
 };
--- a/netwerk/protocol/websocket/PWebSocket.ipdl
+++ b/netwerk/protocol/websocket/PWebSocket.ipdl
@@ -12,27 +12,20 @@ include IPCStream;
 include URIParams;
 include NeckoChannelParams;
 
 include protocol PFileDescriptorSet; //FIXME: bug #792908
 include protocol PChildToParentStream; //FIXME: bug #792908
 include protocol PParentToChildStream; //FIXME: bug #792908
 
 using class IPC::SerializedLoadContext from "SerializedLoadContext.h";
-using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
 namespace mozilla {
 namespace net {
 
-union OptionalTransportProvider
-{
-  PTransportProvider;
-  void_t;
-};
-
 async protocol PWebSocket
 {
   manager PNecko;
 
 parent:
   // Forwarded methods corresponding to methods on nsIWebSocketChannel
   async AsyncOpen(URIParams? aURI,
                   nsCString aOrigin,
@@ -40,17 +33,17 @@ parent:
                   nsCString aProtocol,
                   bool aSecure,
                   // ping values only meaningful if client set them
                   uint32_t aPingInterval,
                   bool aClientSetPingInterval,
                   uint32_t aPingTimeout,
                   bool aClientSetPingTimeout,
                   LoadInfoArgs? aLoadInfoArgs,
-                  OptionalTransportProvider aProvider,
+                  PTransportProvider? aProvider,
                   nsCString aNegotiatedExtensions);
   async Close(uint16_t code, nsCString reason);
   async SendMsg(nsCString aMsg);
   async SendBinaryMsg(nsCString aMsg);
   async SendBinaryStream(IPCStream aStream, uint32_t aLength);
 
   async DeleteSelf();
 
--- a/netwerk/protocol/websocket/WebSocketChannelChild.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannelChild.cpp
@@ -441,32 +441,32 @@ WebSocketChannelChild::AsyncOpen(nsIURI*
     return NS_ERROR_FAILURE;
   }
 
   // Corresponding release in DeallocPWebSocket
   AddIPDLReference();
 
   Maybe<URIParams> uri;
   Maybe<LoadInfoArgs> loadInfoArgs;
-  OptionalTransportProvider transportProvider;
+  Maybe<PTransportProviderChild*> transportProvider;
 
   if (!mIsServerSide) {
     uri.emplace(URIParams());
     SerializeURI(aURI, uri.ref());
     nsresult rv = LoadInfoToLoadInfoArgs(mLoadInfo, &loadInfoArgs);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    transportProvider = void_t();
+    transportProvider = Nothing();
   } else {
     MOZ_ASSERT(mServerTransportProvider);
     PTransportProviderChild* ipcChild;
     nsresult rv = mServerTransportProvider->GetIPCChild(&ipcChild);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    transportProvider = ipcChild;
+    transportProvider = Some(ipcChild);
   }
 
   // This must be called before sending constructor message.
   SetupNeckoTarget();
 
   gNeckoChild->SendPWebSocketConstructor(
       this, tabChild, IPC::SerializedLoadContext(this), mSerial);
   if (!SendAsyncOpen(uri, nsCString(aOrigin), aInnerWindowID, mProtocol,
--- a/netwerk/protocol/websocket/WebSocketChannelParent.cpp
+++ b/netwerk/protocol/websocket/WebSocketChannelParent.cpp
@@ -48,17 +48,17 @@ mozilla::ipc::IPCResult WebSocketChannel
 }
 
 mozilla::ipc::IPCResult WebSocketChannelParent::RecvAsyncOpen(
     const Maybe<URIParams>& aURI, const nsCString& aOrigin,
     const uint64_t& aInnerWindowID, const nsCString& aProtocol,
     const bool& aSecure, const uint32_t& aPingInterval,
     const bool& aClientSetPingInterval, const uint32_t& aPingTimeout,
     const bool& aClientSetPingTimeout, const Maybe<LoadInfoArgs>& aLoadInfoArgs,
-    const OptionalTransportProvider& aTransportProvider,
+    const Maybe<PTransportProviderParent*>& aTransportProvider,
     const nsCString& aNegotiatedExtensions) {
   LOG(("WebSocketChannelParent::RecvAsyncOpen() %p\n", this));
 
   nsresult rv;
   nsCOMPtr<nsIURI> uri;
   nsCOMPtr<nsILoadInfo> loadInfo;
 
   rv = LoadInfoArgsToLoadInfo(aLoadInfoArgs, getter_AddRefs(loadInfo));
@@ -86,20 +86,19 @@ mozilla::ipc::IPCResult WebSocketChannel
   }
 
   rv = mChannel->SetNotificationCallbacks(this);
   if (NS_FAILED(rv)) goto fail;
 
   rv = mChannel->SetProtocol(aProtocol);
   if (NS_FAILED(rv)) goto fail;
 
-  if (aTransportProvider.type() != OptionalTransportProvider::Tvoid_t) {
+  if (aTransportProvider.isSome()) {
     RefPtr<TransportProviderParent> provider =
-        static_cast<TransportProviderParent*>(
-            aTransportProvider.get_PTransportProviderParent());
+        static_cast<TransportProviderParent*>(aTransportProvider.value());
     rv = mChannel->SetServerParameters(provider, aNegotiatedExtensions);
     if (NS_FAILED(rv)) {
       goto fail;
     }
   } else {
     uri = DeserializeURI(aURI);
     if (!uri) {
       rv = NS_ERROR_FAILURE;
--- a/netwerk/protocol/websocket/WebSocketChannelParent.h
+++ b/netwerk/protocol/websocket/WebSocketChannelParent.h
@@ -40,17 +40,17 @@ class WebSocketChannelParent : public PW
  private:
   mozilla::ipc::IPCResult RecvAsyncOpen(
       const Maybe<URIParams>& aURI, const nsCString& aOrigin,
       const uint64_t& aInnerWindowID, const nsCString& aProtocol,
       const bool& aSecure, const uint32_t& aPingInterval,
       const bool& aClientSetPingInterval, const uint32_t& aPingTimeout,
       const bool& aClientSetPingTimeout,
       const Maybe<LoadInfoArgs>& aLoadInfoArgs,
-      const OptionalTransportProvider& aTransportProvider,
+      const Maybe<PTransportProviderParent*>& aTransportProvider,
       const nsCString& aNegotiatedExtensions);
   mozilla::ipc::IPCResult RecvClose(const uint16_t& code,
                                     const nsCString& reason);
   mozilla::ipc::IPCResult RecvSendMsg(const nsCString& aMsg);
   mozilla::ipc::IPCResult RecvSendBinaryMsg(const nsCString& aMsg);
   mozilla::ipc::IPCResult RecvSendBinaryStream(const IPCStream& aStream,
                                                const uint32_t& aLength);
   mozilla::ipc::IPCResult RecvDeleteSelf();
--- a/old-configure.in
+++ b/old-configure.in
@@ -163,44 +163,19 @@ case "$target" in
         AC_DEFINE(_CRT_SECURE_NO_WARNINGS)
         AC_DEFINE(_CRT_NONSTDC_NO_WARNINGS)
         AC_DEFINE(_USE_MATH_DEFINES) # Otherwise MSVC's math.h doesn't #define M_PI.
 
         _CC_SUITE=14
         MSVC_C_RUNTIME_DLL=vcruntime140.dll
         MSVC_CXX_RUNTIME_DLL=msvcp140.dll
 
-        # C5038: Enable initializer list order warnings
-        # The -w1#### flag treats warning C#### as if it was a warning level
-        # 1 warning, and thus enables it because we enable /W3 warnings. We
-        # don't use -we#### because it would enable warning C#### but treat
-        # it as an error, even in third-party code.
-        # https://docs.microsoft.com/en-us/cpp/build/reference/compiler-option-warning-level
-        CXXFLAGS="$CXXFLAGS -w15038"
-
-        # C5026: move constructor was implicitly defined as deleted
-        CXXFLAGS="$CXXFLAGS -wd5026"
-
-        # C5027: move assignment operator was implicitly defined as deleted
-        CXXFLAGS="$CXXFLAGS -wd5027"
-
         # -Zc:sizedDealloc- disables C++14 global sized deallocation (see bug 1160146)
         CXXFLAGS="$CXXFLAGS -Zc:sizedDealloc-"
 
-        # https://connect.microsoft.com/VisualStudio/feedback/details/888527/warnings-on-dbghelp-h
-        # for dbghelp.h, imagehlp.h, and shobj.h
-        # C4091: 'typedef ': ignored on left of '' when no variable is declared
-        CFLAGS="$CFLAGS -wd4091"
-        CXXFLAGS="$CXXFLAGS -wd4091"
-
-        # This is intended as a temporary hack to support building with VS2015.
-        # 'noexcept' used with no exception handling mode specified;
-        # termination on exception is not guaranteed. Specify /EHsc
-        CXXFLAGS="$CXXFLAGS -wd4577"
-
         if test -n "$WIN_UCRT_REDIST_DIR"; then
           if test ! -d "$WIN_UCRT_REDIST_DIR"; then
             AC_MSG_ERROR([Invalid Windows UCRT Redist directory: ${WIN_UCRT_REDIST_DIR}])
           fi
           WIN_UCRT_REDIST_DIR=`cd "$WIN_UCRT_REDIST_DIR" && pwd -W`
         fi
 
         AC_SUBST(MSVC_C_RUNTIME_DLL)
@@ -762,35 +737,16 @@ case "$target" in
         dnl Disabled on ASan because it causes false-positive ODR violations.
         if test -z "$MOZ_ASAN"; then
             CFLAGS="$CFLAGS -Gw"
             CXXFLAGS="$CXXFLAGS -Gw"
         else
             # String tail merging doesn't play nice with ASan's ODR checker.
             LDFLAGS="$LDFLAGS -opt:nolldtailmerge"
         fi
-        # khuey says we can safely ignore MSVC warning C4251
-        # MSVC warning C4244 (implicit type conversion may lose data) warns
-        # and requires workarounds for perfectly valid code.  Also, GCC/clang
-        # don't warn about it by default. So for consistency/sanity, we turn
-        # it off on MSVC, too.
-        # MSVC warning C4267 warns for narrowing type conversions from size_t
-        # to 32-bit integer types on 64-bit platforms.  Since this is virtually
-        # the same thing as C4244, we disable C4267, too.
-        # MSVC warning C4800 warns when a value is implicitly cast to bool,
-        # because this also forces narrowing to a single byte, which can be a
-        # perf hit.  But this matters so little in practice (and often we want
-        # that behavior) that it's better to turn it off.
-        # MSVC warning C4595 warns non-member operator new or delete functions
-        # may not be declared inline, as of VS2015 Update 2.
-        CFLAGS="$CFLAGS -wd4244 -wd4267"
-        CXXFLAGS="$CXXFLAGS -wd4251 -wd4244 -wd4267 -wd4800 -wd4595"
-        # Silence "warning C4065: switch statement contains 'default' but no
-        # 'case' labels".  See bug 1461304.
-        CXXFLAGS="$CXXFLAGS -wd4065"
         if test -n "$CLANG_CL"; then
             # XXX We should combine some of these with our generic GCC-style
             # warning checks.
             #
             # Suppress the clang-cl warning for the inline 'new' and 'delete' in mozalloc
             CXXFLAGS="$CXXFLAGS -Wno-inline-new-delete"
             # We use offsetof on non-POD objects all the time.
             # We also suppress this warning on other platforms.
@@ -846,19 +802,16 @@ case "$target" in
             CXXFLAGS="$CXXFLAGS -Wno-ignored-attributes"
             # __attribute__((unused)) really means "might be unused" and
             # we use it to avoid warnings about things that are unused
             # in some compilation units, but used in many others.  This
             # warning insists on complaining about the latter case, which
             # is annoying, and rather noisy.
             CXXFLAGS="$CXXFLAGS -Wno-used-but-marked-unused"
         fi
-        # make 'foo == bar;' error out
-        CFLAGS="$CFLAGS -we4553"
-        CXXFLAGS="$CXXFLAGS -we4553"
         # Silence VS2017 15.5+ TR1 deprecation warnings hit by older gtest versions
         CXXFLAGS="$CXXFLAGS -D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING"
         LIBS="$LIBS kernel32.lib user32.lib gdi32.lib winmm.lib wsock32.lib advapi32.lib secur32.lib"
         MOZ_DEBUG_LDFLAGS='-DEBUG'
         WARNINGS_AS_ERRORS='-WX'
         # Use a higher optimization level for clang-cl, so we can come closer
         # to MSVC's performance numbers (see bug 1443590).
         if test -n "$CLANG_CL"; then
--- a/python/mozbuild/mozbuild/artifacts.py
+++ b/python/mozbuild/mozbuild/artifacts.py
@@ -1266,18 +1266,22 @@ class Artifacts(object):
             return self.install_from_url(source, distdir)
         else:
             if source is None and 'MOZ_ARTIFACT_REVISION' in os.environ:
                 source = os.environ['MOZ_ARTIFACT_REVISION']
 
             if source:
                 return self.install_from_revset(source, distdir)
 
-            if 'MOZ_ARTIFACT_TASK' in os.environ:
-                return self.install_from_task(os.environ['MOZ_ARTIFACT_TASK'], distdir)
+            for var in (
+                'MOZ_ARTIFACT_TASK_%s' % self._job.upper().replace('-', '_'),
+                'MOZ_ARTIFACT_TASK',
+            ):
+                if var in os.environ:
+                    return self.install_from_task(os.environ[var], distdir)
 
             return self.install_from_recent(distdir)
 
 
     def clear_cache(self):
         self.log(logging.INFO, 'artifact',
             {},
             'Deleting cached artifacts and caches.')
--- a/python/mozrelease/mozrelease/buglist_creator.py
+++ b/python/mozrelease/mozrelease/buglist_creator.py
@@ -213,18 +213,17 @@ Task group: [{task_group_id}](https://to
     subject_prefix = ""
     if product in {"fennec"}:
         subject_prefix = "[mobile] "
     if product in {"firefox", "devedition"}:
         subject_prefix = "[desktop] "
 
     subject = '{} Build of {} {} build {}'.format(subject_prefix, product, version, build_number)
 
-    notify_options = optionsFromEnvironment({'rootUrl': get_root_url()})
-    if 'TASKCLUSTER_PROXY_URL' in os.environ:
-        notify_options['rootUrl'] = os.environ['TASKCLUSTER_PROXY_URL']
+    use_proxy = 'TASKCLUSTER_PROXY_URL' in os.environ
+    notify_options = optionsFromEnvironment({'rootUrl': get_root_url(use_proxy)})
     notify = Notify(notify_options)
     for address in addresses:
         notify.email({
             'address': address,
             'subject': subject,
             'content': content,
         })
--- a/security/sandbox/moz.build
+++ b/security/sandbox/moz.build
@@ -167,15 +167,10 @@ elif CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += ['/security/sandbox/chromium']
     LOCAL_INCLUDES += ['/nsprpub']
 
     DisableStlWrapping()
 
     # Suppress warnings in third-party code.
     if CONFIG['CC_TYPE'] == 'clang-cl':
         CXXFLAGS += [
-            '-wd4275', # non dll-interface class exception used as base for dll-interface class
-            '-wd4717', # recursive on all control paths, function will cause runtime stack overflow
             '-Wno-deprecated-declarations', # 'GetVersionExW': was declared deprecated
-            '-wd4302', # 'reinterpret_cast': truncation from 'LPCSTR' to 'WORD'
-            '-wd4311', # 'reinterpret_cast': pointer truncation from 'LPOVERLAPPED' to 'DWORD'
-            '-wd4312', # 'reinterpret_cast': conversion from 'DWORD' to 'LPOVERLAPPED' of greater size
         ]
--- a/servo/components/style/cbindgen.toml
+++ b/servo/components/style/cbindgen.toml
@@ -98,16 +98,17 @@ include = [
   "BorderImageSlice",
   "BorderSpacing",
   "BorderRadius",
   "NonNegativeLengthOrNumberRect",
   "Perspective",
   "ZIndex",
   "TransformOrigin",
   "WordBreak",
+  "Contain",
 ]
 item_types = ["enums", "structs", "typedefs"]
 
 [export.body]
 "CSSPixelLength" = """
   inline nscoord ToAppUnits() const;
   inline bool IsZero() const;
 """
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -2746,17 +2746,17 @@ fn static_assert() {
                           animation-name animation-delay animation-duration
                           animation-direction animation-fill-mode animation-play-state
                           animation-iteration-count animation-timing-function
                           clear transition-duration transition-delay
                           transition-timing-function transition-property
                           transform-style
                           rotate scroll-snap-points-x scroll-snap-points-y
                           scroll-snap-coordinate -moz-binding will-change
-                          offset-path shape-outside contain touch-action
+                          offset-path shape-outside touch-action
                           translate scale""" %>
 <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
     #[inline]
     pub fn generate_combined_transform(&mut self) {
         unsafe { bindings::Gecko_StyleDisplay_GenerateCombinedTransform(&mut self.gecko) };
     }
 
     #[inline]
@@ -3166,101 +3166,16 @@ fn static_assert() {
         T::AnimateableFeatures {
             features: custom_idents.into_boxed_slice(),
             bits: WillChangeBits::from_bits_truncate(self.gecko.mWillChangeBitField),
         }
     }
 
     <% impl_shape_source("shape_outside", "mShapeOutside") %>
 
-    pub fn set_contain(&mut self, v: longhands::contain::computed_value::T) {
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_NONE;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_STRICT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_LAYOUT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_PAINT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
-        use crate::properties::longhands::contain::SpecifiedValue;
-
-        if v.is_empty() {
-            self.gecko.mContain = NS_STYLE_CONTAIN_NONE as u8;
-            return;
-        }
-
-        if v.contains(SpecifiedValue::STRICT) {
-            self.gecko.mContain = (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS) as u8;
-            return;
-        }
-        if v.contains(SpecifiedValue::CONTENT) {
-            self.gecko.mContain = (NS_STYLE_CONTAIN_CONTENT | NS_STYLE_CONTAIN_CONTENT_BITS) as u8;
-            return;
-        }
-
-        let mut bitfield = 0;
-        if v.contains(SpecifiedValue::LAYOUT) {
-            bitfield |= NS_STYLE_CONTAIN_LAYOUT;
-        }
-        if v.contains(SpecifiedValue::PAINT) {
-            bitfield |= NS_STYLE_CONTAIN_PAINT;
-        }
-        if v.contains(SpecifiedValue::SIZE) {
-            bitfield |= NS_STYLE_CONTAIN_SIZE;
-        }
-
-        self.gecko.mContain = bitfield as u8;
-    }
-
-    pub fn clone_contain(&self) -> longhands::contain::computed_value::T {
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_STRICT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_SIZE;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_LAYOUT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_PAINT;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_ALL_BITS;
-        use crate::gecko_bindings::structs::NS_STYLE_CONTAIN_CONTENT_BITS;
-        use crate::properties::longhands::contain::{self, SpecifiedValue};
-
-        let mut servo_flags = contain::computed_value::T::empty();
-        let gecko_flags = self.gecko.mContain;
-
-        if gecko_flags & (NS_STYLE_CONTAIN_STRICT as u8) != 0 {
-            debug_assert_eq!(
-                gecko_flags & (NS_STYLE_CONTAIN_ALL_BITS as u8),
-                NS_STYLE_CONTAIN_ALL_BITS as u8,
-                "When strict is specified, ALL_BITS should be specified as well"
-            );
-            servo_flags.insert(SpecifiedValue::STRICT | SpecifiedValue::STRICT_BITS);
-            return servo_flags;
-        }
-        if gecko_flags & (NS_STYLE_CONTAIN_CONTENT as u8) != 0 {
-            debug_assert_eq!(
-                gecko_flags & (NS_STYLE_CONTAIN_CONTENT_BITS as u8),
-                NS_STYLE_CONTAIN_CONTENT_BITS as u8,
-                "When content is specified, CONTENT_BITS should be specified as well"
-            );
-            servo_flags.insert(SpecifiedValue::CONTENT | SpecifiedValue::CONTENT_BITS);
-            return servo_flags;
-        }
-        if gecko_flags & (NS_STYLE_CONTAIN_LAYOUT as u8) != 0 {
-            servo_flags.insert(SpecifiedValue::LAYOUT);
-        }
-        if gecko_flags & (NS_STYLE_CONTAIN_PAINT as u8) != 0 {
-            servo_flags.insert(SpecifiedValue::PAINT);
-        }
-        if gecko_flags & (NS_STYLE_CONTAIN_SIZE as u8) != 0 {
-            servo_flags.insert(SpecifiedValue::SIZE);
-        }
-
-        return servo_flags;
-    }
-
-    ${impl_simple_copy("contain", "mContain")}
-
     ${impl_simple_type_with_conversion("touch_action")}
 
     pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) {
         use crate::gecko_bindings::bindings::{Gecko_NewStyleMotion, Gecko_SetStyleMotion};
         use crate::gecko_bindings::structs::StyleShapeSourceType;
         use crate::values::generics::basic_shape::FillRule;
         use crate::values::specified::OffsetPath;
 
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -748,28 +748,31 @@ pub fn assert_touch_action_matches() {
         NS_STYLE_TOUCH_ACTION_PAN_Y => TouchAction::TOUCH_ACTION_PAN_Y,
         NS_STYLE_TOUCH_ACTION_MANIPULATION => TouchAction::TOUCH_ACTION_MANIPULATION,
     }
 }
 
 bitflags! {
     #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
     #[value_info(other_values = "none,strict,content,size,layout,paint")]
+    #[repr(C)]
     /// Constants for contain: https://drafts.csswg.org/css-contain/#contain-property
     pub struct Contain: u8 {
+        /// `none` variant, just for convenience.
+        const NONE = 0;
         /// 'size' variant, turns on size containment
-        const SIZE = 0x01;
+        const SIZE = 1 << 0;
         /// `layout` variant, turns on layout containment
-        const LAYOUT = 0x02;
+        const LAYOUT = 1 << 1;
         /// `paint` variant, turns on paint containment
-        const PAINT = 0x04;
+        const PAINT = 1 << 2;
         /// `strict` variant, turns on all types of containment
-        const STRICT = 0x08;
+        const STRICT = 1 << 3;
         /// 'content' variant, turns on layout and paint containment
-        const CONTENT = 0x10;
+        const CONTENT = 1 << 4;
         /// variant with all the bits that contain: strict turns on
         const STRICT_BITS = Contain::LAYOUT.bits | Contain::PAINT.bits | Contain::SIZE.bits;
         /// variant with all the bits that contain: content turns on
         const CONTENT_BITS = Contain::LAYOUT.bits | Contain::PAINT.bits;
     }
 }
 
 impl ToCss for Contain {
--- a/taskcluster/ci/build/linux.yml
+++ b/taskcluster/ci/build/linux.yml
@@ -344,16 +344,17 @@ linux64-base-toolchains-clang/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: public
         need-xvfb: true
     toolchains:
+        - linux64-binutils
         - linux64-clang-4.0
         - linux64-rust-1.32
         - linux64-cbindgen
         - linux64-nasm-2.13.02
         - linux64-node
 
 linux64-base-toolchains-clang/debug:
     description: "Linux64 base toolchains clang Debug"
@@ -377,16 +378,17 @@ linux64-base-toolchains-clang/debug:
             - builds/releng_base_linux_64_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: debug
         mozconfig-variant: debug
         tooltool-downloads: public
         need-xvfb: true
     toolchains:
+        - linux64-binutils
         - linux64-clang-4.0
         - linux64-rust-1.32
         - linux64-cbindgen
         - linux64-nasm-2.13.02
         - linux64-node
 
 linux/opt:
     description: "Linux32 Opt"
--- a/taskcluster/ci/build/macosx.yml
+++ b/taskcluster/ci/build/macosx.yml
@@ -21,16 +21,17 @@ macosx64/debug:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-debug
         mozconfig-variant: debug
         tooltool-downloads: internal
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -59,16 +60,17 @@ macosx64/opt:
         actions: [get-secrets, build]
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -97,16 +99,17 @@ macosx64-asan-fuzzing/opt:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-fuzzing-asan
         mozconfig-variant: nightly-fuzzing-asan
         tooltool-downloads: internal
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang-macosx-cross
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -144,16 +147,17 @@ macosx64-devedition-nightly/opt:
         extra-config:
             stage_platform: macosx64-devedition
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
         mozconfig-variant: devedition
     run-on-projects: ['mozilla-beta']
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -183,16 +187,17 @@ macosx64-noopt/debug:
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: cross-noopt-debug
         mozconfig-variant: cross-noopt-debug
         tooltool-downloads: internal
         keep-artifacts: false
     run-on-projects: ['trunk', 'try']
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -222,16 +227,17 @@ macosx64-add-on-devel/opt:
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: add-on-devel
         mozconfig-variant: add-on-devel
         tooltool-downloads: internal
     run-on-projects: ['mozilla-beta', 'mozilla-release', 'mozilla-esr45']
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -265,16 +271,17 @@ macosx64-nightly/opt:
         config:
             - builds/releng_base_firefox.py
             - builds/releng_base_mac_64_cross_builds.py
             - taskcluster_nightly.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         tooltool-downloads: internal
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-macos
         - linux64-rust-size
         - linux64-cbindgen
@@ -303,16 +310,17 @@ macosx64-ccov/debug:
             - builds/releng_base_mac_64_cross_builds.py
         script: "mozharness/scripts/fx_desktop_build.py"
         secrets: true
         custom-build-variant-cfg: code-coverage-debug
         mozconfig-variant: code-coverage-debug
         tooltool-downloads: internal
     run-on-projects: ['mozilla-central', 'try']
     toolchains:
+        - linux64-binutils
         - linux64-cctools-port
         - linux64-clang-macosx-cross
         - linux64-hfsplus
         - linux64-libdmg
         - linux64-llvm-dsymutil
         - linux64-rust-nightly-macos
         - linux64-rust-size
         - linux64-cbindgen
--- a/taskcluster/ci/build/windows.yml
+++ b/taskcluster/ci/build/windows.yml
@@ -1039,16 +1039,52 @@ win64-aarch64/opt:
     toolchains:
         - win64-clang-cl
         - win64-aarch64-rust
         - win64-cbindgen
         - win64-sccache
         - win64-nasm
         - win64-node
 
+win64-aarch64-eme/opt:
+    description: "AArch64 Win64 Opt w/ EME"
+    index:
+        product: firefox
+        job-name: win64-aarch64-eme-opt
+    treeherder:
+        platform: windows2012-aarch64/opt
+        symbol: Be
+        tier: 1
+    worker-type: aws-provisioner-v1/gecko-{level}-b-win2012
+    worker:
+        max-run-time: 7200
+        env:
+            TOOLTOOL_MANIFEST: "browser/config/tooltool-manifests/win64/aarch64.manifest"
+            PERFHERDER_EXTRA_OPTIONS: aarch64-eme
+            MOZ_ARTIFACT_TASK: {task-reference: '<win64-aarch64-opt>'}
+            MOZ_ARTIFACT_TASK_WIN32_OPT: {task-reference: '<win32-opt>'}
+            USE_ARTIFACT: '1'
+    run:
+        actions: [get-secrets, build]
+        options: [append-env-variables-from-configs]
+        script: mozharness/scripts/fx_desktop_build.py
+        secrets: true
+        config:
+            - builds/releng_base_firefox.py
+            - builds/taskcluster_base_windows.py
+            - builds/taskcluster_base_win64.py
+        extra-config:
+            stage_platform: win64-aarch64
+            mozconfig_platform: win64-aarch64
+    dependencies:
+        win32-opt: build-win32/opt
+        win64-aarch64-opt: build-win64-aarch64/opt
+    toolchains:
+        - win64-node
+
 win64-aarch64-nightly/opt:
     description: "AArch64 Win64 Nightly"
     index:
         product: firefox
         job-name: win64-aarch64-opt
         type: nightly
     attributes:
         nightly: true
--- a/taskcluster/ci/diffoscope/kind.yml
+++ b/taskcluster/ci/diffoscope/kind.yml
@@ -27,23 +27,52 @@ job-defaults:
     --max-page-size 100000000
     --max-page-diff-block-lines 10000
     --exclude-directory-metadata
     --exclude-command .--line-numbers
     --exclude **/*freeblpriv3.chk
     --exclude **/*nssdbm3.chk
     --exclude **/*softokn3.chk
 
+jobs:
+  artifact-win64-aarch64-eme-validation:
+    symbol: DWE
+    new: build-win64-aarch64-eme/opt
+    original: build-win64-aarch64/opt
+    unpack: true
+    fail-on-diff: true
+    pre-diff-commands:
+      # The EME version has extra files under i686/.
+      - rm -rf b/firefox/i686
+      # The i686/ files appear in precomplete, so after removing those references,
+      # we expect the same content as the non-EME build.
+      - sed -i '/i686\//d' b/firefox/precomplete
+      # Remove noise from differences in line numbers in preprocessor output
+      # due to #if/#else branches.
+      - sed -i '/^\/\/@line /d' {a,b}/firefox/browser/defaults/preferences/firefox.js
+      # Removing media.gmp-widevinecdm.* preferences, and setting
+      # browser.eme.ui.enabled to false should give us the same preferences as
+      # the non-EME build.
+      - sed -i '/browser\.eme\.ui\.enabled/s/true/false/;/media\.gmp-widevinecdm\./d' b/firefox/browser/defaults/preferences/firefox.js
+    # Extra diffoscope arguments to account for:
+    # - about:buildconfig being expectedly different.
+    # - There are some differences in PE metadata in helper.exe because
+    #   it's (re)built in the EME build, and that part of the build is
+    #   not reproducible.
+    extra-args: >-
+      --exclude-directory-metadata=recursive
+      --exclude b/firefox/chrome/toolkit/content/global/buildconfig.html
+      --exclude b/firefox/uninstall/helper.exe
+
+
 # Make a task for each diff we might want. The following are just examples,
 # Both original and new can point to builds from the full set of tasks or
 # from other sets through an index-search. Other kinds than `build` can be
 # compared (for example, static-analysis), provided you adjust the
 # kind-dependencies above.
-
-# jobs:
 #   android-build-vs-previous-try:
 #     symbol: A
 #     new: build-android-api-16/opt
 #     original: {index-search: gecko.v2.try.revision.aabd5deb0156f9b55ab60ad6a01ebfc4580bf2e1.mobile.android-api-16-opt}
 #   linux64-build-vs-previous-try:
 #     symbol: L
 #     new: build-linux64/opt
 #     original: {index-search: gecko.v2.try.revision.aabd5deb0156f9b55ab60ad6a01ebfc4580bf2e1.firefox.linux64-opt}
--- a/taskcluster/ci/spidermonkey/linux.yml
+++ b/taskcluster/ci/spidermonkey/linux.yml
@@ -137,16 +137,17 @@ sm-tsan-linux64/opt:
     index:
         job-name: sm-tsan-linux64-opt
     treeherder:
         symbol: SM(tsan)
         platform: linux64/opt
     run:
         spidermonkey-variant: tsan
     toolchains:
+        - linux64-binutils
         - linux64-clang
         - linux64-rust
 
 sm-rootanalysis-linux64/debug:
     description: "Spidermonkey Root Analysis"
     index:
         job-name: sm-rootanalysis-linux64-debug
     treeherder:
--- a/testing/geckodriver/src/capabilities.rs
+++ b/testing/geckodriver/src/capabilities.rs
@@ -343,17 +343,17 @@ impl FirefoxOptions {
         if let Some(profile_json) = options.get("profile") {
             let profile_base64 = profile_json.as_str().ok_or(WebDriverError::new(
                 ErrorStatus::UnknownError,
                 "Profile is not a string"
             ))?;
             let profile_zip = &*base64::decode(profile_base64)?;
 
             // Create an emtpy profile directory
-            let profile = Profile::new(None)?;
+            let profile = Profile::new()?;
             unzip_buffer(
                 profile_zip,
                 profile
                     .temp_dir
                     .as_ref()
                     .expect("Profile doesn't have a path")
                     .path()
             )?;
--- a/testing/geckodriver/src/marionette.rs
+++ b/testing/geckodriver/src/marionette.rs
@@ -140,17 +140,17 @@ impl MarionetteHandler {
              'moz:firefoxOptions.binary' capability provided, and \
              no binary flag set on the command line",
         ))?;
 
         let is_custom_profile = options.profile.is_some();
 
         let mut profile = match options.profile {
             Some(x) => x,
-            None => Profile::new(None)?,
+            None => Profile::new()?,
         };
 
         self.set_prefs(port, &mut profile, is_custom_profile, options.prefs)
             .map_err(|e| {
                 WebDriverError::new(
                     ErrorStatus::SessionNotCreated,
                     format!("Failed to set preferences: {}", e),
                 )
@@ -1518,17 +1518,17 @@ mod tests {
     use mozprofile::preferences::PrefValue;
     use mozprofile::profile::Profile;
 
     // This is not a pretty test, mostly due to the nature of
     // mozprofile's and MarionetteHandler's APIs, but we have had
     // several regressions related to marionette.log.level.
     #[test]
     fn test_marionette_log_level() {
-        let mut profile = Profile::new(None).unwrap();
+        let mut profile = Profile::new().unwrap();
         let handler = MarionetteHandler::new(MarionetteSettings::default());
         handler.set_prefs(2828, &mut profile, false, vec![]).ok();
         let user_prefs = profile.user_prefs().unwrap();
 
         let pref = user_prefs.get("marionette.log.level").unwrap();
         let value = match pref.value {
             PrefValue::String(ref s) => s,
             _ => panic!(),
--- a/testing/geckodriver/src/prefs.rs
+++ b/testing/geckodriver/src/prefs.rs
@@ -136,16 +136,19 @@ lazy_static! {
         // Make sure SNTP requests do not hit the network
         ("network.sntp.pools", Pref::new("%(server)s")),
 
         // Disable Flash.  The plugin container it is run in is
         // causing problems when quitting Firefox from geckodriver,
         // c.f. https://github.com/mozilla/geckodriver/issues/225.
         ("plugin.state.flash", Pref::new(0)),
 
+        // Don't do network connections for mitm priming
+        ("security.certerrors.mitm.priming.enabled", Pref::new(false)),
+
         // Ensure blocklist updates don't hit the network
         ("services.settings.server", Pref::new("http://%(server)s/dummy/blocklist/")),
 
         // Disable first run pages
         ("startup.homepage_welcome_url", Pref::new("about:blank")),
         ("startup.homepage_welcome_url.additional", Pref::new("")),
 
         // Prevent starting into safe mode after application crashes
--- a/testing/marionette/client/marionette_driver/geckoinstance.py
+++ b/testing/marionette/client/marionette_driver/geckoinstance.py
@@ -111,16 +111,19 @@ class GeckoInstance(object):
         # Disable speculative connections so they aren"t reported as leaking when they"re
         # hanging around
         "network.http.speculative-parallel-limit": 0,
         # Do not automatically switch between offline and online
         "network.manage-offline-status": False,
         # Make sure SNTP requests don't hit the network
         "network.sntp.pools": "%(server)s",
 
+        # Don't do network connections for mitm priming
+        "security.certerrors.mitm.priming.enabled": False,
+
         # Tests don't wait for the notification button security delay
         "security.notification_enable_delay": 0,
 
         # Ensure blocklist updates don't hit the network
         "services.settings.server": "http://%(server)s/dummy/blocklist/",
 
         # Disable password capture, so that tests that include forms aren"t
         # influenced by the presence of the persistent doorhanger notification
--- a/testing/marionette/components/marionette.js
+++ b/testing/marionette/components/marionette.js
@@ -236,16 +236,19 @@ const RECOMMENDED_PREFS = new Map([
   ["network.http.speculative-parallel-limit", 0],
 
   // Do not automatically switch between offline and online
   ["network.manage-offline-status", false],
 
   // Make sure SNTP requests do not hit the network
   ["network.sntp.pools", "%(server)s"],
 
+  // Don't do network connections for mitm priming
+  ["security.certerrors.mitm.priming.enabled", false],
+
   // Local documents have access to all other local documents,
   // including directory listings
   ["security.fileuri.strict_origin_policy", false],
 
   // Tests do not wait for the notification button security delay
   ["security.notification_enable_delay", 0],
 
   // Ensure blocklist updates do not hit the network
--- a/testing/modules/TestUtils.jsm
+++ b/testing/modules/TestUtils.jsm
@@ -65,16 +65,63 @@ var TestUtils = {
           Services.obs.removeObserver(observer, topic);
           reject(ex);
         }
       }, topic);
     });
   },
 
   /**
+   * Waits for the specified preference to be change.
+   *
+   * @param {string} prefName
+   *        The pref to observe.
+   * @param {function} checkFn [optional]
+   *        Called with the new preference value as argument, should return true if the
+   *        notification is the expected one, or false if it should be ignored
+   *        and listening should continue. If not specified, the first
+   *        notification for the specified topic resolves the returned promise.
+   *
+   * @note Because this function is intended for testing, any error in checkFn
+   *       will cause the returned promise to be rejected instead of waiting for
+   *       the next notification, since this is probably a bug in the test.
+   *
+   * @return {Promise}
+   * @resolves The value of the preference.
+   */
+  waitForPrefChange(prefName, checkFn) {
+    return new Promise((resolve, reject) => {
+      Services.prefs.addObserver(prefName, function observer(subject, topic, data) {
+        try {
+          let prefValue = null;
+          switch (Services.prefs.getPrefType(prefName)) {
+          case Services.prefs.PREF_STRING:
+            prefValue = Services.prefs.getStringPref(prefName);
+            break;
+          case Services.prefs.PREF_INT:
+            prefValue = Services.prefs.getIntPref(prefName);
+            break;
+          case Services.prefs.PREF_BOOL:
+            prefValue = Services.prefs.getBoolPref(prefName);
+            break;
+          }
+          if (checkFn && !checkFn(prefValue)) {
+            return;
+          }
+          Services.prefs.removeObserver(prefName, observer);
+          resolve(prefValue);
+        } catch (ex) {
+          Services.prefs.removeObserver(prefName, observer);
+          reject(ex);
+        }
+      });
+    });
+  },
+
+  /**
    * Takes a screenshot of an area and returns it as a data URL.
    *
    * @param eltOrRect
    *        The DOM node or rect ({left, top, width, height}) to screenshot.
    * @param win
    *        The current window.
    */
   screenshotArea(eltOrRect, win) {
--- a/testing/mozbase/rust/mozprofile/src/profile.rs
+++ b/testing/mozbase/rust/mozprofile/src/profile.rs
@@ -11,28 +11,31 @@ use tempdir::TempDir;
 pub struct Profile {
     pub path: PathBuf,
     pub temp_dir: Option<TempDir>,
     prefs: Option<PrefFile>,
     user_prefs: Option<PrefFile>,
 }
 
 impl Profile {
-    pub fn new(opt_path: Option<&Path>) -> IoResult<Profile> {
-        let mut temp_dir = None;
-        let path = match opt_path {
-            Some(p) => p.to_path_buf(),
-            None => {
-                let dir = TempDir::new("rust_mozprofile")?;
-                let temp_path = dir.path().to_path_buf();
-                temp_dir = Some(dir);
-                temp_path
-            }
-        };
+    pub fn new() -> IoResult<Profile> {
+        let dir = TempDir::new("rust_mozprofile")?;
+        let path = dir.path().to_path_buf();
+        let temp_dir = Some(dir);
+        Ok(Profile {
+            path,
+            temp_dir,
+            prefs: None,
+            user_prefs: None,
+        })
+    }
 
+     pub fn new_from_path(p: &Path) -> IoResult<Profile> {
+        let path = p.to_path_buf();
+        let temp_dir = None;
         Ok(Profile {
             path,
             temp_dir,
             prefs: None,
             user_prefs: None,
         })
     }
 
--- a/testing/profiles/common/user.js
+++ b/testing/profiles/common/user.js
@@ -38,16 +38,18 @@ user_pref("extensions.legacy.enabled", t
 // Turn off extension updates so they don't bother tests
 user_pref("extensions.update.enabled", false);
 // Disable useragent updates.
 user_pref("general.useragent.updates.enabled", false);
 // Ensure WR doesn't get enabled in tests unless we do it explicitly with the MOZ_WEBRENDER envvar.
 user_pref("gfx.webrender.all.qualified", false);
 user_pref("hangmonitor.timeout", 0); // no hang monitor
 user_pref("media.gmp-manager.updateEnabled", false);
+// Don't do network connections for mitm priming
+user_pref("security.certerrors.mitm.priming.enabled", false);
 // Make enablePrivilege continue to work for test code. :-(
 user_pref("security.turn_off_all_security_so_that_viruses_can_take_over_this_computer", true);
 user_pref("xpinstall.signatures.required", false);
 // Prevent Remote Settings to issue non local connections.
 user_pref("services.settings.server", "http://localhost/remote-settings-dummy/v1");
 // Ensure autoplay is enabled for all platforms.
 user_pref("media.autoplay.default", 0); // 0=Allowed, 1=Blocked, 2=Prompt
 user_pref("media.autoplay.enabled.user-gestures-needed", true);
--- a/testing/web-platform/meta/webrtc/RTCPeerConnection-getStats.https.html.ini
+++ b/testing/web-platform/meta/webrtc/RTCPeerConnection-getStats.https.html.ini
@@ -1,21 +1,9 @@
 [RTCPeerConnection-getStats.https.html]
-  [getStats() with track not added to connection should reject with InvalidAccessError]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531084
-
-  [getStats() with track associated with more than one sender should reject with InvalidAccessError]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531084
-
-  [getStats() with track associated with both sender and receiver should reject with InvalidAccessError]
-    expected: FAIL
-    bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531084
-
   [getStats() with no argument should return stats report containing peer-connection stats on an empty PC]
     expected: FAIL
     bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1531087
 
   [getStats() with no argument should return stats report containing peer-connection stats and outbound-track-stats]
     expected: FAIL
     bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1225720
 
--- a/toolkit/components/protobuf/moz.build
+++ b/toolkit/components/protobuf/moz.build
@@ -135,20 +135,16 @@ if CONFIG['CC_TYPE'] in ('clang', 'gcc')
             '-Wno-comma',
             '-Wno-null-conversion',
             '-Wno-unused-local-typedef',
         ]
 elif CONFIG['CC_TYPE'] == 'clang-cl':
     CXXFLAGS += [
         '-Wno-macro-redefined',  # 'WIN32_LEAN_AND_MEAN' : macro redefinition
         '-Wno-sign-compare',
-        '-wd4065',  # switch statement contains 'default' but no 'case' labels
-        '-wd4099',  # mismatched class/struct tags
-        '-wd4305',  # double to float truncation
-        '-wd4506',  # no definition for inline function (protobuf issue #240)
     ]
 
 if CONFIG['OS_TARGET'] == 'WINNT':
     DEFINES['NOGDI'] = True  # wingdi.h defines ERROR as 0 and conflicts with logging.h
 
 if CONFIG['MOZ_USE_PTHREADS']:
     DEFINES['HAVE_PTHREAD'] = True
 
--- a/toolkit/components/sessionstore/SessionStoreUtils.cpp
+++ b/toolkit/components/sessionstore/SessionStoreUtils.cpp
@@ -282,16 +282,28 @@ void SessionStoreUtils::RestoreScrollPos
   }
 
   nsCCharSeparatedTokenizer tokenizer(aData.mScroll.Value(), ',');
   nsAutoCString token(tokenizer.nextToken());
   int pos_X = atoi(token.get());
   token = tokenizer.nextToken();
   int pos_Y = atoi(token.get());
   aWindow.ScrollTo(pos_X, pos_Y);
+
+  if (nsCOMPtr<Document> doc = aWindow.GetExtantDoc()) {
+    if (nsPresContext* presContext = doc->GetPresContext()) {
+      if (presContext->IsRootContentDocument()) {
+        // Use eMainThread so this takes precedence over session history
+        // (ScrollFrameHelper::ScrollToRestoredPosition()).
+        presContext->PresShell()->SetPendingVisualScrollUpdate(
+            CSSPoint::ToAppUnits(CSSPoint(pos_X, pos_Y)),
+            layers::FrameMetrics::eMainThread);
+      }
+    }
+  }
 }
 
 // Implements the Luhn checksum algorithm as described at
 // http://wikipedia.org/wiki/Luhn_algorithm
 // Number digit lengths vary with network, but should fall within 12-19 range.
 // [2] More details at https://en.wikipedia.org/wiki/Payment_card_number
 static bool IsValidCCNumber(nsAString& aValue) {
   uint32_t total = 0;
--- a/toolkit/components/viewsource/test/browser/browser.ini
+++ b/toolkit/components/viewsource/test/browser/browser.ini
@@ -1,12 +1,13 @@
 [DEFAULT]
 support-files = head.js
   file_bug464222.html
 
 [browser_bug464222.js]
 [browser_bug713810.js]
 [browser_contextmenu.js]
 subsuite = clipboard
+skip-if = (os == "win" && processor == "aarch64") # disabled on aarch64 due to 1531590
 [browser_gotoline.js]
 [browser_open_docgroup.js]
 [browser_srcdoc.js]
 [browser_viewsourceprefs.js]
--- a/toolkit/crashreporter/crashreporter.mozbuild
+++ b/toolkit/crashreporter/crashreporter.mozbuild
@@ -8,22 +8,16 @@ LOCAL_INCLUDES += [
     '/toolkit/crashreporter/breakpad-client',
     '/toolkit/crashreporter/google-breakpad/src',
 ]
 
 # Suppress warnings in third-party code.
 if CONFIG['CC_TYPE'] == 'clang-cl':
     CXXFLAGS += [
         '-Wno-macro-redefined',
-        '-wd4146', # negative unsigned
-        '-wd4334', # 32-bit shift to 64 bits
-        '-wd4804', # unsafe use of type 'bool'
-    ]
-    CFLAGS += [
-        '-wd4312', # conversion to greater size
     ]
 elif CONFIG['CC_TYPE'] in ('clang', 'gcc'):
     CXXFLAGS += [
         '-Wno-unused-local-typedefs',
         '-Wno-shadow',
         '-Wno-deprecated-declarations',
         '-Wno-bool-compare',
         '-Wno-unused-but-set-variable',
--- a/toolkit/crashreporter/test/moz.build
+++ b/toolkit/crashreporter/test/moz.build
@@ -50,12 +50,8 @@ DEFINES['SHARED_LIBRARY'] = '%s%s%s' % (
 )
 
 TEST_HARNESS_FILES.xpcshell.toolkit.crashreporter.test.unit += ['CrashTestUtils.jsm']
 TEST_HARNESS_FILES.xpcshell.toolkit.crashreporter.test.unit_ipc += ['CrashTestUtils.jsm']
 
 include('/toolkit/crashreporter/crashreporter.mozbuild')
 
 NO_PGO = True
-
-# Temporary workaround for an issue in upstream breakpad
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    CXXFLAGS += ['-wd4334']
--- a/toolkit/locales/en-US/chrome/global/intl.properties
+++ b/toolkit/locales/en-US/chrome/global/intl.properties
@@ -19,17 +19,17 @@
 # For example, the Breton [br] locale might consider including French and
 # British English in their list, since those languages are commonly spoken in
 # the same area as Breton:
 # intl.accept_languages=br, fr-FR, fr, en-GB, en
 intl.accept_languages=en-US, en
 
 # LOCALIZATION NOTE (font.language.group):
 # This preference controls the initial setting of the language drop-down menu
-# in the Content > Fonts & Colors > Advanced preference panel.
+# in the Fonts and Colors > Advanced preference panel.
 #
 # Set it to the value of one of the menuitems in the "selectLangs" menulist in
 # http://dxr.mozilla.org/mozilla-central/source/browser/components/preferences/fonts.xul
 font.language.group=x-western
 
 # LOCALIZATION NOTE (intl.charset.detector):
 # This preference controls the initial setting for the character encoding
 # detector. Valid values are ja_parallel_state_machine for Japanese, ruprob
--- a/toolkit/modules/BrowserUtils.jsm
+++ b/toolkit/modules/BrowserUtils.jsm
@@ -682,9 +682,33 @@ var BrowserUtils = {
           fragment.appendChild(doc.createTextNode(part));
         }
       } else {
         fragment.appendChild(part);
       }
     }
     return fragment;
   },
+
+  /**
+   * Returns a Promise which resolves when the given observer topic has been
+   * observed.
+   *
+   * @param {string} topic
+   *        The topic to observe.
+   * @param {function(nsISupports, string)} [test]
+   *        An optional test function which, when called with the
+   *        observer's subject and data, should return true if this is the
+   *        expected notification, false otherwise.
+   * @returns {Promise<object>}
+   */
+  promiseObserved(topic, test = () => true) {
+    return new Promise(resolve => {
+      let observer = (subject, topic, data) => {
+        if (test(subject, data)) {
+          Services.obs.removeObserver(observer, topic);
+          resolve({subject, data});
+        }
+      };
+      Services.obs.addObserver(observer, topic);
+    });
+  },
 };
--- a/toolkit/moz.configure
+++ b/toolkit/moz.configure
@@ -517,23 +517,27 @@ set_define('MOZ_OMX', openmax)
 # EME Support
 # ==============================================================
 @depends(target)
 def eme_choices(target):
     if (target.kernel in ('Darwin', 'WINNT', 'Linux') and
         target.os not in ('Android', 'iOS') and
         target.cpu in ('x86', 'x86_64')):
         return ('widevine',)
+    if target.kernel == 'WINNT' and target.cpu == 'aarch64':
+        return ('widevine',)
 
 
-# Widevine is enabled by default in desktop browser builds.
-@depends(build_project, eme_choices)
-def eme_default(build_project, choices):
+# Widevine is enabled by default in desktop browser builds, except
+# on aarch64 Windows.
+@depends(build_project, eme_choices, target)
+def eme_default(build_project, choices, target):
     if build_project == 'browser':
-        return choices
+        if target.kernel != 'WINNT' or target.cpu != 'aarch64':
+            return choices
 
 
 option('--enable-eme',
        nargs='+',
        choices=eme_choices,
        default=eme_default,
        when=eme_choices,
        help='{Enable|Disable} support for Encrypted Media Extensions')
@@ -550,16 +554,25 @@ def eme(enabled, fmp4):
 def eme_modules(value):
     return value
 
 
 # Fallback to an empty list when eme_choices is empty, setting eme_modules to
 # None.
 set_config('MOZ_EME_MODULES', eme_modules | dependable([]))
 
+
+@depends(eme_modules, target, when=eme_modules)
+def eme_win32_artifact(modules, target):
+    if 'widevine' in modules and target.kernel == 'WINNT' and target.cpu == 'aarch64':
+        return True
+
+
+set_config('MOZ_EME_WIN32_ARTIFACT', eme_win32_artifact)
+
 option(name='--enable-chrome-format',
        help='Select FORMAT of chrome files during packaging.',
        nargs=1,
        choices=('omni', 'jar', 'flat'),
        default='omni')
 
 @depends('--enable-chrome-format')
 def packager_format(value):
--- a/toolkit/themes/shared/media/videocontrols.css
+++ b/toolkit/themes/shared/media/videocontrols.css
@@ -419,24 +419,26 @@
 }
 
 .statusIcon[type="error"] {
   min-width: 70px;
   min-height: 60px;
   background-image: url(chrome://global/skin/media/error.png);
 }
 
+%ifdef NIGHTLY_BUILD
 .statusIcon[type="pictureInPicture"] {
   min-width: 84px;
   min-height: 84px;
   background-image: url(chrome://global/skin/media/pictureinpicture.svg);
   -moz-context-properties: fill, stroke;
   fill: #fff;
   stroke: #fff;
 }
+%endif
 
 /* Overlay Play button */
 .clickToPlay {
   min-width: var(--clickToPlay-size);
   min-height: var(--clickToPlay-size);
   border-radius: 50%;
   background-image: url(chrome://global/skin/media/playButton.svg);
   background-repeat: no-repeat;
--- a/toolkit/xre/nsAppRunner.cpp
+++ b/toolkit/xre/nsAppRunner.cpp
@@ -3896,68 +3896,16 @@ int XREMain::XRE_mainStartup(bool* aExit
 #endif
 
   // Support exiting early for testing startup sequence. Bug 1360493
   if (CheckArg("test-launch-without-hang")) {
     *aExitFlag = true;
     return 0;
   }
 
-#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
-  // Check for and process any available updates
-  nsCOMPtr<nsIFile> updRoot;
-  bool persistent;
-  rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
-                            getter_AddRefs(updRoot));
-  // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
-  if (NS_FAILED(rv)) updRoot = mDirProvider.GetAppDir();
-
-  // If the MOZ_TEST_PROCESS_UPDATES environment variable already exists, then
-  // we are being called from the callback application.
-  if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
-    // If the caller has asked us to log our arguments, do so.  This is used
-    // to make sure that the maintenance service successfully launches the
-    // callback application.
-    const char* logFile = nullptr;
-    if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
-      FILE* logFP = fopen(logFile, "wb");
-      if (logFP) {
-        for (int i = 1; i < gRestartArgc; ++i) {
-          fprintf(logFP, "%s\n", gRestartArgv[i]);
-        }
-        fclose(logFP);
-      }
-    }
-    *aExitFlag = true;
-    return 0;
-  }
-
-  // Support for processing an update and exiting. The MOZ_TEST_PROCESS_UPDATES
-  // environment variable will be part of the updater's environment and the
-  // application that is relaunched by the updater. When the application is
-  // relaunched by the updater it will be removed below and the application
-  // will exit.
-  if (CheckArg("test-process-updates")) {
-    SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
-  }
-  nsCOMPtr<nsIFile> exeFile, exeDir;
-  rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
-                            getter_AddRefs(exeFile));
-  NS_ENSURE_SUCCESS(rv, 1);
-  rv = exeFile->GetParent(getter_AddRefs(exeDir));
-  NS_ENSURE_SUCCESS(rv, 1);
-  ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
-                 gRestartArgv, mAppData->version);
-  if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
-    SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
-    *aExitFlag = true;
-    return 0;
-  }
-#endif
-
   rv = NS_NewToolkitProfileService(getter_AddRefs(mProfileSvc));
   if (rv == NS_ERROR_FILE_ACCESS_DENIED) {
     PR_fprintf(PR_STDERR,
                "Error: Access was denied while trying to open files in "
                "your profile directory.\n");
   }
   if (NS_FAILED(rv)) {
     // We failed to choose or create profile - notify user and quit
@@ -4008,16 +3956,70 @@ int XREMain::XRE_mainStartup(bool* aExit
       return 0;
     }
     if (rr == REMOTE_ARG_BAD) {
       return 1;
     }
   }
 #endif
 
+#if defined(MOZ_UPDATER) && !defined(MOZ_WIDGET_ANDROID)
+  // Check for and process any available updates
+  nsCOMPtr<nsIFile> updRoot;
+  bool persistent;
+  rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR, &persistent,
+                            getter_AddRefs(updRoot));
+  // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
+  if (NS_FAILED(rv)) {
+    updRoot = mDirProvider.GetAppDir();
+  }
+
+  // If the MOZ_TEST_PROCESS_UPDATES environment variable already exists, then
+  // we are being called from the callback application.
+  if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
+    // If the caller has asked us to log our arguments, do so.  This is used
+    // to make sure that the maintenance service successfully launches the
+    // callback application.
+    const char* logFile = nullptr;
+    if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
+      FILE* logFP = fopen(logFile, "wb");
+      if (logFP) {
+        for (int i = 1; i < gRestartArgc; ++i) {
+          fprintf(logFP, "%s\n", gRestartArgv[i]);
+        }
+        fclose(logFP);
+      }
+    }
+    *aExitFlag = true;
+    return 0;
+  }
+
+  // Support for processing an update and exiting. The MOZ_TEST_PROCESS_UPDATES
+  // environment variable will be part of the updater's environment and the
+  // application that is relaunched by the updater. When the application is
+  // relaunched by the updater it will be removed below and the application
+  // will exit.
+  if (CheckArg("test-process-updates")) {
+    SaveToEnv("MOZ_TEST_PROCESS_UPDATES=1");
+  }
+  nsCOMPtr<nsIFile> exeFile, exeDir;
+  rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE, &persistent,
+                            getter_AddRefs(exeFile));
+  NS_ENSURE_SUCCESS(rv, 1);
+  rv = exeFile->GetParent(getter_AddRefs(exeDir));
+  NS_ENSURE_SUCCESS(rv, 1);
+  ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
+                 gRestartArgv, mAppData->version);
+  if (EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
+    SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
+    *aExitFlag = true;
+    return 0;
+  }
+#endif
+
   // We always want to lock the profile even if we're actually going to reset
   // it later.
   rv = LockProfile(mNativeApp, mProfD, mProfLD, profile,
                    getter_AddRefs(mProfileLock));
   if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
     *aExitFlag = true;
     return 0;
   } else if (NS_FAILED(rv)) {
--- a/widget/windows/moz.build
+++ b/widget/windows/moz.build
@@ -156,12 +156,8 @@ OS_LIBS += [
     'rpcrt4',
 ]
 
 if CONFIG['CC_TYPE'] == 'clang-cl':
     SOURCES += [
         'ToastNotification.cpp',
         'ToastNotificationHandler.cpp',
     ]
-    # C5038: Suppress initializer list order warnings from wrl.h
-    SOURCES['ToastNotification.cpp'].flags += ['-wd5038']
-    SOURCES['ToastNotificationHandler.cpp'].flags += ['-wd5038']
-    SOURCES['WindowsUIUtils.cpp'].flags += ['-wd5038']
--- a/xpcom/io/moz.build
+++ b/xpcom/io/moz.build
@@ -145,14 +145,8 @@ FINAL_LIBRARY = 'xul'
 
 if CONFIG['OS_ARCH'] == 'Linux' and 'lib64' in CONFIG['libdir']:
     DEFINES['HAVE_USR_LIB64_DIR'] = True
 
 LOCAL_INCLUDES += [
     '!..',
     '../build',
 ]
-
-if CONFIG['CC_TYPE'] == 'clang-cl':
-    # This is intended as a temporary hack to support building with VS2015.
-    # '_snwprintf' : format string '%s' requires an argument of type 'wchar_t *',
-    # but variadic argument 3 has type 'char16ptr_t'
-    CXXFLAGS += ['-wd4477']