merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 13 May 2016 11:59:20 +0200
changeset 323576 5a2deb5a9b09df9ad2ca3ac1d0c480be250d31e4
parent 323408 943ca7ad1ea35e01a6ba6bfa0a4f3896f1150e15 (current diff)
parent 323575 386c786e0354983dad20fe10da5aae584621ba89 (diff)
child 323577 1f1a8b96d5167153d1f750439ba6a1063155a4bc
child 323622 2372285af9b2b0babf85f1b606d4697398902bee
push idunknown
push userunknown
push dateunknown
reviewersmerge
milestone49.0a1
first release with
nightly linux32
5a2deb5a9b09 / 49.0a1 / 20160513030539 / files
nightly linux64
5a2deb5a9b09 / 49.0a1 / 20160513030539 / files
nightly mac
5a2deb5a9b09 / 49.0a1 / 20160513030539 / files
nightly win32
5a2deb5a9b09 / 49.0a1 / 20160513030539 / files
nightly win64
5a2deb5a9b09 / 49.0a1 / 20160513030539 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
dom/animation/test/css-animations/file_keyframeeffect-getframes.html
dom/animation/test/css-animations/test_keyframeeffect-getframes.html
dom/animation/test/css-transitions/file_keyframeeffect-getframes.html
dom/animation/test/css-transitions/test_keyframeeffect-getframes.html
ipc/chromium/src/base/observer_list_threadsafe.h
security/manager/ssl/tests/unit/test_cert_eku/ee-int-nsSGC.pem
security/manager/ssl/tests/unit/test_cert_eku/ee-int-nsSGC.pem.certspec
security/manager/ssl/tests/unit/test_cert_eku/int-nsSGC.pem
security/manager/ssl/tests/unit/test_cert_eku/int-nsSGC.pem.certspec
testing/web-platform/meta/web-animations/keyframe-effect/setFrames.html.ini
testing/web-platform/tests/web-animations/keyframe-effect/setFrames.html
--- a/accessible/ipc/DocAccessibleParent.cpp
+++ b/accessible/ipc/DocAccessibleParent.cpp
@@ -251,17 +251,18 @@ DocAccessibleParent::RecvTextChangeEvent
   ProxyTextChangeEvent(target, aStr, aStart, aLen, aIsInsert, aFromUser);
 
   if (!nsCoreUtils::AccEventObserversExist()) {
     return true;
   }
 
   xpcAccessibleGeneric* xpcAcc = GetXPCAccessible(target);
   xpcAccessibleDocument* doc = GetAccService()->GetXPCDocument(this);
-  uint32_t type = nsIAccessibleEvent::EVENT_TEXT_CHANGED;
+  uint32_t type = aIsInsert ? nsIAccessibleEvent::EVENT_TEXT_INSERTED :
+                              nsIAccessibleEvent::EVENT_TEXT_REMOVED;
   nsIDOMNode* node = nullptr;
   RefPtr<xpcAccTextChangeEvent> event =
     new xpcAccTextChangeEvent(type, xpcAcc, doc, node, aFromUser, aStart, aLen,
                               aIsInsert, aStr);
   nsCoreUtils::DispatchAccEvent(Move(event));
 
   return true;
 }
--- a/accessible/tests/browser/browser.ini
+++ b/accessible/tests/browser/browser.ini
@@ -20,17 +20,16 @@ skip-if = e10s
 # Events tests
 [browser_events_caretmove.js]
 [browser_events_hide.js]
 skip-if = e10s
 [browser_events_show.js]
 skip-if = e10s
 [browser_events_statechange.js]
 [browser_events_textchange.js]
-skip-if = e10s
 
 # Tree update tests
 [browser_treeupdate_ariadialog.js]
 skip-if = e10s
 [browser_treeupdate_ariaowns.js]
 skip-if = e10s
 [browser_treeupdate_canvas.js]
 skip-if = e10s
--- a/b2g/confvars.sh
+++ b/b2g/confvars.sh
@@ -13,17 +13,16 @@ MOZ_UA_OS_AGNOSTIC=1
 MOZ_B2G_VERSION=2.6.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=1
-MOZ_SERVICES_COMMON=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_NO_SMART_CARDS=1
 MOZ_APP_STATIC_INI=1
 NSS_DISABLE_DBM=1
 MOZ_NO_EV_CERTS=1
 
 MOZ_WEBSPEECH=1
@@ -46,17 +45,16 @@ MOZ_XULRUNNER=
 
 MOZ_APP_ID={3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 
 MOZ_TIME_MANAGER=1
 
 MOZ_SIMPLEPUSH=1
 MOZ_PAY=1
 MOZ_TOOLKIT_SEARCH=
-MOZ_PLACES=
 MOZ_B2G=1
 
 if test "$OS_TARGET" = "Android"; then
 MOZ_NUWA_PROCESS=1
 MOZ_B2G_LOADER=1
 MOZ_ENABLE_WARNINGS_AS_ERRORS=1
 fi
 
--- a/b2g/graphene/confvars.sh
+++ b/b2g/graphene/confvars.sh
@@ -20,17 +20,16 @@ MOZ_APP_UA_NAME=Firefox
 MOZ_B2G_VERSION=2.6.0.0-prerelease
 MOZ_B2G_OS_NAME=Boot2Gecko
 
 MOZ_BRANDING_DIRECTORY=b2g/branding/unofficial
 MOZ_OFFICIAL_BRANDING_DIRECTORY=b2g/branding/official
 # MOZ_APP_DISPLAYNAME is set by branding/configure.sh
 
 MOZ_SAFE_BROWSING=1
-MOZ_SERVICES_COMMON=1
 MOZ_CAPTIVEDETECT=1
 
 MOZ_WEBSMS_BACKEND=1
 MOZ_NO_SMART_CARDS=1
 MOZ_APP_STATIC_INI=1
 NSS_NO_LIBPKIX=1
 NSS_DISABLE_DBM=1
 
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -287,19 +287,16 @@
 #ifdef MOZ_ENABLE_PROFILER_SPS
 @RESPATH@/components/profiler.xpt
 #endif
 @RESPATH@/components/proxyObject.xpt
 @RESPATH@/components/rdf.xpt
 @RESPATH@/components/satchel.xpt
 @RESPATH@/components/saxparser.xpt
 @RESPATH@/components/sessionstore.xpt
-#ifdef MOZ_SERVICES_SYNC
-@RESPATH@/components/services-crypto.xpt
-#endif
 @RESPATH@/components/services-crypto-component.xpt
 @RESPATH@/components/captivedetect.xpt
 @RESPATH@/components/shellservice.xpt
 @RESPATH@/components/shistory.xpt
 @RESPATH@/components/spellchecker.xpt
 @RESPATH@/components/storage.xpt
 @RESPATH@/components/telemetry.xpt
 @RESPATH@/components/toolkit_asyncshutdown.xpt
@@ -592,22 +589,16 @@
 #ifdef MOZ_SECUREELEMENT
 @RESPATH@/components/DOMSecureElement.manifest
 @RESPATH@/components/DOMSecureElement.js
 #endif
 @RESPATH@/components/nsINIProcessor.manifest
 @RESPATH@/components/nsINIProcessor.js
 @RESPATH@/components/nsPrompter.manifest
 @RESPATH@/components/nsPrompter.js
-#ifdef MOZ_SERVICES_SYNC
-@RESPATH@/components/SyncComponents.manifest
-@RESPATH@/components/Weave.js
-@RESPATH@/components/WeaveCrypto.manifest
-@RESPATH@/components/WeaveCrypto.js
-#endif
 @RESPATH@/components/servicesComponents.manifest
 @RESPATH@/components/cryptoComponents.manifest
 @RESPATH@/components/CaptivePortalDetectComponents.manifest
 @RESPATH@/components/captivedetect.js
 @RESPATH@/components/TelemetryStartup.js
 @RESPATH@/components/TelemetryStartup.manifest
 @RESPATH@/components/XULStore.js
 @RESPATH@/components/XULStore.manifest
@@ -732,21 +723,16 @@
 @RESPATH@/browser/@PREF_DIR@/b2g.js
 #else
 @RESPATH@/@PREF_DIR@/b2g.js
 #endif
 @RESPATH@/@PREF_DIR@/channel-prefs.js
 @RESPATH@/greprefs.js
 @RESPATH@/defaults/autoconfig/prefcalls.js
 
-; Services (gre) prefs
-#ifdef MOZ_SERVICES_SYNC
-@RESPATH@/defaults/pref/services-sync.js
-#endif
-
 ; [Layout Engine Resources]
 ; Style Sheets, Graphics and other Resources used by the layout engine.
 @RESPATH@/res/EditorOverride.css
 @RESPATH@/res/contenteditable.css
 @RESPATH@/res/designmode.css
 @RESPATH@/res/ImageDocument.css
 @RESPATH@/res/TopLevelImageDocument.css
 @RESPATH@/res/TopLevelVideoDocument.css
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -97,26 +97,35 @@
       function doOverride(buttonEl) {
         var event = new CustomEvent("AboutNetErrorOverride", {bubbles:true});
         document.dispatchEvent(event);
         retryThis(buttonEl);
       }
 
       function toggleDisplay(node) {
         toggle = {
-          '': 'block',
-          'none': 'block',
-          'block': 'none'
+          "": "block",
+          "none": "block",
+          "block": "none"
         };
         return (node.style.display = toggle[node.style.display]);
       }
 
       function showCertificateErrorReporting() {
         // Display error reporting UI
-        document.getElementById('certificateErrorReporting').style.display = 'block';
+        document.getElementById("certificateErrorReporting").style.display = "block";
+      }
+
+      function showPrefChangeContainer() {
+        const panel = document.getElementById("prefChangeContainer");
+        panel.style.display = "block";
+        document.getElementById("prefResetButton").addEventListener("click", function resetPreferences(e) {
+          const event = new CustomEvent("AboutNetErrorResetPreferences", {bubbles:true});
+          document.dispatchEvent(event);
+        });
       }
 
       function showAdvancedButton(allowOverride) {
         // Get the hostname and add it to the panel
         var panelId = gIsCertError ? "badCertAdvancedPanel" : "weakCryptoAdvancedPanel";
         var panel = document.getElementById(panelId);
         for (var span of panel.querySelectorAll("span.hostname")) {
           span.textContent = document.location.hostname;
@@ -302,29 +311,40 @@
               learnMoreLink.href = "https://support.mozilla.org/kb/certificate-pinning-reports";
             }
             if (getErrorCode() == "weakCryptoUsed") {
               learnMoreLink.href = "https://support.mozilla.org/kb/how-resolve-weak-crypto-error-messages-firefox";
             }
 
             var options = JSON.parse(evt.detail);
             if (options && options.enabled) {
-              var checkbox = document.getElementById('automaticallyReportInFuture');
+              var checkbox = document.getElementById("automaticallyReportInFuture");
               showCertificateErrorReporting();
               if (options.automatic) {
                 // set the checkbox
                 checkbox.checked = true;
               }
 
-              checkbox.addEventListener('change', function(evt) {
+              checkbox.addEventListener("change", function(evt) {
                   var event = new CustomEvent("AboutNetErrorSetAutomatic",
                     {bubbles:true, detail:evt.target.checked});
                   document.dispatchEvent(event);
                 }, false);
             }
+            const hasPrefStyleError = [
+              "interrupted", // This happens with subresources that are above the max tls
+              "SSL_ERROR_PROTOCOL_VERSION_ALERT",
+              "SSL_ERROR_UNSUPPORTED_VERSION",
+              "SSL_ERROR_NO_CYPHER_OVERLAP",
+              "SSL_ERROR_NO_CIPHERS_SUPPORTED"
+            ].some((substring) => getDescription().includes(substring));
+            // If it looks like an error that is user config based
+            if (getErrorCode() == "nssFailure2" && hasPrefStyleError && options && options.changedCertPrefs) {
+              showPrefChangeContainer();
+            }
           }
           if (getErrorCode() == "weakCryptoUsed" || getErrorCode() == "sslv3Used") {
             showAdvancedButton(getErrorCode() == "weakCryptoUsed");
           }
         }.bind(this), true, true);
 
         var event = new CustomEvent("AboutNetErrorLoad", {bubbles:true});
         document.dispatchEvent(event);
@@ -404,17 +424,17 @@
               if (toggleDisplay(div) == "block") {
                 div.scrollIntoView({block: "start", behavior: "smooth"});
               }
             }, false);
           }
         }
 
         // Initialize the cert domain link.
-        var link = document.getElementById('cert_domain_link');
+        var link = document.getElementById("cert_domain_link");
         if (!link)
           return;
 
         var okHost = link.getAttribute("title");
         var thisHost = document.location.hostname;
         var proto = document.location.protocol;
 
         // If okHost is a wildcard domain ("*.example.com") let's
@@ -556,16 +576,21 @@
 
         <div id="wrongSystemTimePanel" style="display: none;">
           &certerror.wrongSystemTime;
         </div>
 
         <!-- Long Description (Note: See netError.dtd for used XHTML tags) -->
         <div id="errorLongDesc" />
 
+        <div id="prefChangeContainer">
+          <p>&prefReset.longDesc;</p>
+          <button id="prefResetButton" autocomplete="off">&prefReset.label;</button>
+        </div>
+
         <div id="learnMoreContainer">
           <p><a href="https://support.mozilla.org/kb/what-does-your-connection-is-not-secure-mean" id="learnMoreLink" target="new">&errorReporting.learnMore;</a></p>
         </div>
 
         <div id="certErrorButtonContainer" class="button-container">
           <button id="returnButton" class="primary" autocomplete="off" autofocus="true">&returnToPreviousPage.label;</button>
           <div class="button-spacer"></div>
           <button id="advancedButton" autocomplete="off" autofocus="true">&advanced.label;</button>
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -2651,41 +2651,49 @@ var gMenuButtonUpdateBadge = {
 };
 
 // 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 TLS_ERROR_REPORT_TELEMETRY_MANUAL_SEND    = 4;
 const TLS_ERROR_REPORT_TELEMETRY_AUTO_SEND      = 5;
 
+const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.min", "security.tls.version.max", "security.ssl3."];
+
+const PREF_SSL_IMPACT = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => {
+  return prefs.concat(Services.prefs.getChildList(root));
+}, []);
+
 /**
  * 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 = {
   init: function () {
     let mm = window.messageManager;
     mm.addMessageListener("Browser:CertExceptionError", this);
     mm.addMessageListener("Browser:SiteBlockedError", this);
     mm.addMessageListener("Browser:EnableOnlineMode", this);
     mm.addMessageListener("Browser:SendSSLErrorReport", this);
     mm.addMessageListener("Browser:SetSSLErrorReportAuto", this);
+    mm.addMessageListener("Browser:ResetSSLPreferences", this);
     mm.addMessageListener("Browser:SSLErrorReportTelemetry", this);
     mm.addMessageListener("Browser:OverrideWeakCrypto", this);
     mm.addMessageListener("Browser:SSLErrorGoBack", this);
   },
 
   uninit: function () {
     let mm = window.messageManager;
     mm.removeMessageListener("Browser:CertExceptionError", this);
     mm.removeMessageListener("Browser:SiteBlockedError", this);
     mm.removeMessageListener("Browser:EnableOnlineMode", this);
     mm.removeMessageListener("Browser:SendSSLErrorReport", this);
     mm.removeMessageListener("Browser:SetSSLErrorReportAuto", this);
+    mm.removeMessageListener("Browser:ResetSSLPreferences", this);
     mm.removeMessageListener("Browser:SSLErrorReportTelemetry", this);
     mm.removeMessageListener("Browser:OverrideWeakCrypto", this);
     mm.removeMessageListener("Browser:SSLErrorGoBack", this);
   },
 
   handleEvent: function (event) {
     if (!event.isTrusted || // Don't trust synthetic events
         event.button == 2) {
@@ -2722,16 +2730,22 @@ var BrowserOnClick = {
           msg.target.reload();
         }
       break;
       case "Browser:SendSSLErrorReport":
         this.onSSLErrorReport(msg.target,
                               msg.data.uri,
                               msg.data.securityInfo);
       break;
+      case "Browser:ResetSSLPreferences":
+        for (let prefName of PREF_SSL_IMPACT) {
+          Services.prefs.clearUserPref(prefName);
+        }
+        msg.target.reload();
+      break;
       case "Browser:SetSSLErrorReportAuto":
         Services.prefs.setBoolPref("security.ssl.errorReporting.automatic", msg.json.automatic);
         let bin = TLS_ERROR_REPORT_TELEMETRY_AUTO_UNCHECKED;
         if (msg.json.automatic) {
           bin = TLS_ERROR_REPORT_TELEMETRY_AUTO_CHECKED;
         }
         Services.telemetry.getHistogramById("TLS_ERROR_REPORT_UI").add(bin);
       break;
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -228,22 +228,30 @@ const SEC_ERROR_EXPIRED_CERTIFICATE     
 const SEC_ERROR_UNKNOWN_ISSUER                     = SEC_ERROR_BASE + 13;
 const SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE         = SEC_ERROR_BASE + 30;
 const SEC_ERROR_OCSP_FUTURE_RESPONSE               = SEC_ERROR_BASE + 131;
 const SEC_ERROR_OCSP_OLD_RESPONSE                  = SEC_ERROR_BASE + 132;
 const MOZILLA_PKIX_ERROR_NOT_YET_VALID_CERTIFICATE = MOZILLA_PKIX_ERROR_BASE + 5;
 
 const PREF_KINTO_CLOCK_SKEW_SECONDS = "services.kinto.clock_skew_seconds";
 
+const PREF_SSL_IMPACT_ROOTS = ["security.tls.version.min", "security.tls.version.max", "security.ssl3."];
+
+const PREF_SSL_IMPACT = PREF_SSL_IMPACT_ROOTS.reduce((prefs, root) => {
+  return prefs.concat(Services.prefs.getChildList(root));
+}, []);
+
+
 var AboutNetAndCertErrorListener = {
   init: function(chromeGlobal) {
     addMessageListener("CertErrorDetails", this);
     chromeGlobal.addEventListener('AboutNetErrorLoad', this, false, true);
     chromeGlobal.addEventListener('AboutNetErrorSetAutomatic', this, false, true);
     chromeGlobal.addEventListener('AboutNetErrorOverride', this, false, true);
+    chromeGlobal.addEventListener('AboutNetErrorResetPreferences', this, false, true);
   },
 
   get isAboutNetError() {
     return content.document.documentURI.startsWith("about:neterror");
   },
 
   get isAboutCertError() {
     return content.document.documentURI.startsWith("about:certerror");
@@ -318,38 +326,57 @@ var AboutNetAndCertErrorListener = {
       this.onPageLoad(aEvent);
       break;
     case "AboutNetErrorSetAutomatic":
       this.onSetAutomatic(aEvent);
       break;
     case "AboutNetErrorOverride":
       this.onOverride(aEvent);
       break;
+    case "AboutNetErrorResetPreferences":
+      this.onResetPreferences(aEvent);
+      break;
     }
   },
 
+  changedCertPrefs: function () {
+    for (let prefName of PREF_SSL_IMPACT) {
+      if (Services.prefs.prefHasUserValue(prefName)) {
+        return true;
+      }
+    }
+
+    return false;
+  },
+
   onPageLoad: function(evt) {
     if (this.isAboutCertError) {
       let originalTarget = evt.originalTarget;
       let ownerDoc = originalTarget.ownerDocument;
       ClickEventHandler.onCertError(originalTarget, ownerDoc);
     }
 
     let automatic = Services.prefs.getBoolPref("security.ssl.errorReporting.automatic");
     content.dispatchEvent(new content.CustomEvent("AboutNetErrorOptions", {
       detail: JSON.stringify({
         enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
+        changedCertPrefs: this.changedCertPrefs(),
         automatic: automatic
       })
     }));
 
     sendAsyncMessage("Browser:SSLErrorReportTelemetry",
                      {reportStatus: TLS_ERROR_REPORT_TELEMETRY_UI_SHOWN});
   },
 
+
+  onResetPreferences: function(evt) {
+    sendAsyncMessage("Browser:ResetSSLPreferences");
+  },
+
   onSetAutomatic: function(evt) {
     sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
       automatic: evt.detail
     });
 
     // if we're enabling reports, send a report for this failure
     if (evt.detail) {
       let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -502,34 +502,37 @@ var PageStyleHandler = {
         let mediaQueryList = currentStyleSheet.media.mediaText;
         if (!content.matchMedia(mediaQueryList).matches) {
           continue;
         }
       }
 
       let URI;
       try {
-        URI = Services.io.newURI(currentStyleSheet.href, null, null);
+        if (!currentStyleSheet.ownerNode ||
+            // special-case style nodes, which have no href
+            currentStyleSheet.ownerNode.nodeName.toLowerCase() != "style") {
+          URI = Services.io.newURI(currentStyleSheet.href, null, null);
+        }
       } catch(e) {
         if (e.result != Cr.NS_ERROR_MALFORMED_URI) {
           throw e;
         }
+        continue;
       }
 
-      if (URI) {
-        // We won't send data URIs all of the way up to the parent, as these
-        // can be arbitrarily large.
-        let sentURI = URI.scheme == "data" ? null : URI.spec;
+      // We won't send data URIs all of the way up to the parent, as these
+      // can be arbitrarily large.
+      let sentURI = (!URI || URI.scheme == "data") ? null : URI.spec;
 
-        result.push({
-          title: currentStyleSheet.title,
-          disabled: currentStyleSheet.disabled,
-          href: sentURI,
-        });
-      }
+      result.push({
+        title: currentStyleSheet.title,
+        disabled: currentStyleSheet.disabled,
+        href: sentURI,
+      });
     }
 
     return result;
   },
 };
 PageStyleHandler.init();
 
 // Keep a reference to the translation content handler to avoid it it being GC'ed.
index 4e8b4d3a3d8e27dc6592427e7560a9be23645c3c..477544875d28a2005ae730b5caced8c24ae12631
GIT binary patch
literal 14293
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
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -135,16 +135,17 @@ support-files =
   !/toolkit/mozapps/extensions/test/xpinstall/restartless.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/theme.xpi
 
 [browser_aboutAccounts.js]
 skip-if = os == "linux" # Bug 958026
 support-files =
   content_aboutAccounts.js
 [browser_aboutCertError.js]
+[browser_aboutNetError.js]
 [browser_aboutSupport_newtab_security_state.js]
 [browser_aboutHealthReport.js]
 skip-if = os == "linux" # Bug 924307
 [browser_aboutHome.js]
 [browser_aboutHome_wrapsCorrectly.js]
 [browser_addKeywordSearch.js]
 [browser_alltabslistener.js]
 [browser_audioTabIcon.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_aboutNetError.js
@@ -0,0 +1,42 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Set ourselves up for TLS error
+Services.prefs.setIntPref("security.tls.version.max", 3);
+Services.prefs.setIntPref("security.tls.version.min", 3);
+
+const LOW_TLS_VERSION = "https://tls1.example.com/";
+const {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
+const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+
+add_task(function* checkReturnToPreviousPage() {
+  info("Loading a TLS page that isn't supported, ensure we have a fix button and clicking it then loads the page");
+  let browser;
+  let pageLoaded;
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, () => {
+    gBrowser.selectedTab = gBrowser.addTab(LOW_TLS_VERSION);
+    browser = gBrowser.selectedBrowser;
+    pageLoaded = BrowserTestUtils.waitForErrorPage(browser);
+  }, false);
+
+  info("Loading and waiting for the net error");
+  yield pageLoaded;
+
+  Assert.ok(content.document.getElementById("prefResetButton").getBoundingClientRect().left >= 0,
+    "Should have a visible button");
+
+  Assert.ok(content.document.documentURI.startsWith("about:neterror"), "Should be showing error page");
+
+  let pageshowPromise = promiseWaitForEvent(browser, "pageshow");
+  yield ContentTask.spawn(browser, null, function* () {
+    content.document.getElementById("prefResetButton").click();
+  });
+  yield pageshowPromise;
+
+  Assert.equal(content.document.documentURI, LOW_TLS_VERSION, "Should not be showing page");
+
+  yield BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
--- a/browser/base/content/test/general/browser_page_style_menu.js
+++ b/browser/base/content/test/general/browser_page_style_menu.js
@@ -1,67 +1,97 @@
-function test() {
-  waitForExplicitFinish();
+"use strict";
 
-  var tab = gBrowser.addTab();
-  gBrowser.selectedTab = tab;
-  tab.linkedBrowser.addEventListener("pageshow", function () {
-    tab.linkedBrowser.removeEventListener("pageshow", arguments.callee, true);
-    checkPageStyleMenu();
-  }, true);
-  let rootDir = getRootDirectory(gTestPath);
-  content.location = rootDir + "page_style_sample.html";
+/**
+ * Stylesheets are updated for a browser after the pageshow event.
+ * This helper function returns a Promise that waits for that pageshow
+ * event, and then resolves on the next tick to ensure that gPageStyleMenu
+ * has had a chance to update the stylesheets.
+ *
+ * @param browser
+ *        The <xul:browser> to wait for.
+ * @return Promise
+ */
+function promiseStylesheetsUpdated(browser) {
+  return ContentTask.spawn(browser, { PAGE }, function*(args) {
+    return new Promise((resolve) => {
+      addEventListener("pageshow", function onPageShow(e) {
+        if (e.target.location == args.PAGE) {
+          removeEventListener("pageshow", onPageShow);
+          content.setTimeout(resolve, 0);
+        }
+      });
+    })
+  });
 }
 
-function checkPageStyleMenu() {
-  var menupopup = document.getElementById("pageStyleMenu")
-                          .getElementsByTagName("menupopup")[0];
+const PAGE = "http://example.com/browser/browser/base/content/test/general/page_style_sample.html";
+
+/*
+ * Test that the right stylesheets do (and others don't) show up
+ * in the page style menu.
+ */
+add_task(function*() {
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "about:blank", false);
+  let browser = tab.linkedBrowser;
+  yield BrowserTestUtils.loadURI(browser, PAGE);
+  yield promiseStylesheetsUpdated(browser);
+
+  let menupopup = document.getElementById("pageStyleMenu").menupopup;
   gPageStyleMenu.fillPopup(menupopup);
 
   var items = [];
   var current = menupopup.getElementsByTagName("menuseparator")[0];
   while (current.nextSibling) {
     current = current.nextSibling;
     items.push(current);
   }
 
-  var validLinks = 0;
-  Array.forEach(content.document.getElementsByTagName("link"), function (link) {
-    var title = link.getAttribute("title");
-    var rel = link.getAttribute("rel");
-    var media = link.getAttribute("media");
-    var idstring = "link " + (title ? title : "without title and") +
-                   " with rel=\"" + rel + "\"" +
-                   (media ? " and media=\"" + media + "\"" : "");
+  items = items.map(el => ({
+    label: el.getAttribute("label"),
+    checked: el.getAttribute("checked") == "true",
+  }));
 
-    var item = items.filter(item => item.getAttribute("label") == title);
-    var found = item.length == 1;
-    var checked = found && (item[0].getAttribute("checked") == "true");
+  let validLinks = yield ContentTask.spawn(gBrowser.selectedBrowser, items, function(items) {
+    let validLinks = 0;
+    Array.forEach(content.document.querySelectorAll("link, style"), function (el) {
+      var title = el.getAttribute("title");
+      var rel = el.getAttribute("rel");
+      var media = el.getAttribute("media");
+      var idstring = el.nodeName + " " + (title ? title : "without title and") +
+                     " with rel=\"" + rel + "\"" +
+                     (media ? " and media=\"" + media + "\"" : "");
+
+      var item = items.filter(item => item.label == title);
+      var found = item.length == 1;
+      var checked = found && item[0].checked;
 
-    switch (link.getAttribute("data-state")) {
-      case "0":
-        ok(!found, idstring + " does not show up in page style menu");
-        break;
-      case "0-todo":
-        validLinks++;
-        todo(!found, idstring + " should not show up in page style menu");
-        ok(!checked, idstring + " is not selected");
-        break;
-      case "1":
-        validLinks++;
-        ok(found, idstring + " shows up in page style menu");
-        ok(!checked, idstring + " is not selected");
-        break;
-      case "2":
-        validLinks++;
-        ok(found, idstring + " shows up in page style menu");
-        ok(checked, idstring + " is selected");
-        break;
-      default:
-        throw "data-state attribute is missing or has invalid value";
-    }
+      switch (el.getAttribute("data-state")) {
+        case "0":
+          ok(!found, idstring + " should not show up in page style menu");
+          break;
+        case "0-todo":
+          validLinks++;
+          todo(!found, idstring + " should not show up in page style menu");
+          ok(!checked, idstring + " should not be selected");
+          break;
+        case "1":
+          validLinks++;
+          ok(found, idstring + " should show up in page style menu");
+          ok(!checked, idstring + " should not be selected");
+          break;
+        case "2":
+          validLinks++;
+          ok(found, idstring + " should show up in page style menu");
+          ok(checked, idstring + " should be selected");
+          break;
+        default:
+          throw "data-state attribute is missing or has invalid value";
+      }
+    });
+    return validLinks;
   });
 
-  is(validLinks, items.length, "all valid links found");
+  ok(items.length, "At least one item in the menu");
+  is(items.length, validLinks, "all valid links found");
 
-  gBrowser.removeCurrentTab();
-  finish();
-}
+  yield BrowserTestUtils.removeTab(tab);
+});
--- a/browser/base/content/test/general/page_style_sample.html
+++ b/browser/base/content/test/general/page_style_sample.html
@@ -30,11 +30,12 @@
     <link data-state="0" href="404.css" title="20" rel="alternate stylesheet" media="all  screen">
     <link data-state="0" href="404.css" title="21" rel="alternate stylesheet" media="foo">
     <link data-state="0" href="404.css" title="22" rel="alternate stylesheet" media="allscreen">
     <link data-state="0" href="404.css" title="23" rel="alternate stylesheet" media="_all">
     <link data-state="0" href="404.css" title="24" rel="alternate stylesheet" media="not screen">
     <link data-state="1" href="404.css" title="25" rel="alternate stylesheet" media="only screen">
     <link data-state="1" href="404.css" title="26" rel="alternate stylesheet" media="screen and (min-device-width: 1px)">
     <link data-state="0" href="404.css" title="27" rel="alternate stylesheet" media="screen and (max-device-width: 1px)">
+    <style data-state="1" title="28">/* some more styles */</style>
   </head>
   <body></body>
 </html>
--- a/browser/components/newtab/NewTabMessages.jsm
+++ b/browser/components/newtab/NewTabMessages.jsm
@@ -1,58 +1,89 @@
 /*global
   NewTabWebChannel,
   NewTabPrefsProvider,
   PlacesProvider,
+  PreviewProvider,
+  NewTabSearchProvider,
   Preferences,
-  XPCOMUtils
+  XPCOMUtils,
+  Task
 */
 
 /* exported NewTabMessages */
 
 "use strict";
 
 const {utils: Cu} = Components;
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesProvider",
                                   "resource:///modules/PlacesProvider.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PreviewProvider",
                                   "resource:///modules/PreviewProvider.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabPrefsProvider",
                                   "resource:///modules/NewTabPrefsProvider.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabSearchProvider",
+                                  "resource:///modules/NewTabSearchProvider.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
                                   "resource:///modules/NewTabWebChannel.jsm");
 
 this.EXPORTED_SYMBOLS = ["NewTabMessages"];
 
 const PREF_ENABLED = "browser.newtabpage.remote";
+const CURRENT_ENGINE = "browser-search-engine-modified";
 
 // Action names are from the content's perspective. in from chrome == out from content
 // Maybe replace the ACTION objects by a bi-directional Map a bit later?
 const ACTIONS = {
   inboundActions: [
     "REQUEST_PREFS",
     "REQUEST_THUMB",
     "REQUEST_FRECENT",
+    "REQUEST_UISTRINGS",
+    "REQUEST_SEARCH_SUGGESTIONS",
+    "REQUEST_MANAGE_ENGINES",
+    "REQUEST_SEARCH_STATE",
+    "REQUEST_REMOVE_FORM_HISTORY",
+    "REQUEST_PERFORM_SEARCH",
+    "REQUEST_CYCLE_ENGINE",
   ],
   prefs: {
     inPrefs: "REQUEST_PREFS",
     outPrefs: "RECEIVE_PREFS",
   },
   preview: {
     inThumb: "REQUEST_THUMB",
     outThumb: "RECEIVE_THUMB",
   },
   links: {
     inFrecent: "REQUEST_FRECENT",
     outFrecent: "RECEIVE_FRECENT",
     outPlacesChange: "RECEIVE_PLACES_CHANGE",
   },
+  search: {
+    inSearch: {
+        UIStrings: "REQUEST_UISTRINGS",
+        suggestions: "REQUEST_SEARCH_SUGGESTIONS",
+        manageEngines: "REQUEST_MANAGE_ENGINES",
+        state: "REQUEST_SEARCH_STATE",
+        removeFormHistory: "REQUEST_REMOVE_FORM_HISTORY",
+        performSearch: "REQUEST_PERFORM_SEARCH",
+        cycleEngine: "REQUEST_CYCLE_ENGINE"
+    },
+    outSearch: {
+      UIStrings: "RECEIVE_UISTRINGS",
+      suggestions: "RECEIVE_SEARCH_SUGGESTIONS",
+      state: "RECEIVE_SEARCH_STATE",
+      currentEngine: "RECEIVE_CURRENT_ENGINE"
+    },
+  }
 };
 
 let NewTabMessages = {
 
   _prefs: {},
 
   /** NEWTAB EVENT HANDLERS **/
 
@@ -70,27 +101,80 @@ let NewTabMessages = {
         });
         break;
       case ACTIONS.links.inFrecent:
         // Return to the originator the top frecent links
         PlacesProvider.links.getLinks().then(links => {
           NewTabWebChannel.send(ACTIONS.links.outFrecent, links, target);
         });
         break;
+      case ACTIONS.search.inSearch.UIStrings:
+        // Return to the originator all search strings to display
+        let strings = NewTabSearchProvider.search.searchSuggestionUIStrings;
+        NewTabWebChannel.send(ACTIONS.search.outSearch.UIStrings, strings, target);
+        break;
+      case ACTIONS.search.inSearch.suggestions:
+        // Return to the originator all search suggestions
+        Task.spawn(function*() {
+          try {
+            let {engineName, searchString} = data;
+            let suggestions = yield NewTabSearchProvider.search.asyncGetSuggestions(engineName, searchString, target);
+            NewTabWebChannel.send(ACTIONS.search.outSearch.suggestions, suggestions, target);
+          } catch (e) {
+            Cu.reportError(e);
+          }
+        });
+        break;
+      case ACTIONS.search.inSearch.manageEngines:
+        // Open about:preferences to manage search state
+        NewTabSearchProvider.search.manageEngines(target.browser);
+        break;
+      case ACTIONS.search.inSearch.state:
+        // Return the state of the search component (i.e current engine and visible engine details)
+        Task.spawn(function*() {
+          try {
+            let state = yield NewTabSearchProvider.search.asyncGetState();
+            NewTabWebChannel.broadcast(ACTIONS.search.outSearch.state, state);
+          } catch (e) {
+            Cu.reportError(e);
+          }
+        });
+        break;
+      case ACTIONS.search.inSearch.removeFormHistory:
+        // Remove a form history entry from the search component
+        let suggestion = data;
+        NewTabSearchProvider.search.removeFormHistory(target, suggestion);
+        break;
+      case ACTIONS.search.inSearch.performSearch:
+        // Perform a search
+        NewTabSearchProvider.search.asyncPerformSearch(target, data).catch(Cu.reportError);
+        break;
+      case ACTIONS.search.inSearch.cycleEngine:
+        // Set the new current engine
+        NewTabSearchProvider.search.asyncCycleEngine(data).catch(Cu.reportError);
+        break;
     }
   },
 
   /*
    * Broadcast places change to all open newtab pages
    */
   handlePlacesChange(type, data) {
     NewTabWebChannel.broadcast(ACTIONS.links.outPlacesChange, {type, data});
   },
 
   /*
+   * Broadcast current engine has changed to all open newtab pages
+   */
+  _handleCurrentEngineChange(name, value) { //jshint unused: false
+    let engine = value;
+    NewTabWebChannel.broadcast(ACTIONS.search.outSearch.currentEngine, engine);
+  },
+
+  /*
    * Broadcast preference changes to all open newtab pages
    */
   handlePrefChange(actionName, value) {
     let prefChange = {};
     prefChange[actionName] = value;
     NewTabWebChannel.broadcast(ACTIONS.prefs.outPrefs, prefChange);
   },
 
@@ -102,28 +186,32 @@ let NewTabMessages = {
         this.init();
       }
     }
   },
 
   init() {
     this.handleContentRequest = this.handleContentRequest.bind(this);
     this._handleEnabledChange = this._handleEnabledChange.bind(this);
+    this._handleCurrentEngineChange = this._handleCurrentEngineChange.bind(this);
 
     PlacesProvider.links.init();
     NewTabPrefsProvider.prefs.init();
+    NewTabSearchProvider.search.init();
     NewTabWebChannel.init();
 
     this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
 
     if (this._prefs.enabled) {
       for (let action of ACTIONS.inboundActions) {
         NewTabWebChannel.on(action, this.handleContentRequest);
       }
+
       NewTabPrefsProvider.prefs.on(PREF_ENABLED, this._handleEnabledChange);
+      NewTabSearchProvider.search.on(CURRENT_ENGINE, this._handleCurrentEngineChange);
 
       for (let pref of NewTabPrefsProvider.newtabPagePrefSet) {
         NewTabPrefsProvider.prefs.on(pref, this.handlePrefChange);
       }
 
       PlacesProvider.links.on("deleteURI", this.handlePlacesChange);
       PlacesProvider.links.on("clearHistory", this.handlePlacesChange);
       PlacesProvider.links.on("linkChanged", this.handlePlacesChange);
@@ -131,23 +219,25 @@ let NewTabMessages = {
     }
   },
 
   uninit() {
     this._prefs.enabled = Preferences.get(PREF_ENABLED, false);
 
     if (this._prefs.enabled) {
       NewTabPrefsProvider.prefs.off(PREF_ENABLED, this._handleEnabledChange);
+      NewTabSearchProvider.search.off(CURRENT_ENGINE, this._handleCurrentEngineChange);
 
       for (let action of ACTIONS.inboundActions) {
         NewTabWebChannel.off(action, this.handleContentRequest);
       }
 
       for (let pref of NewTabPrefsProvider.newtabPagePrefSet) {
         NewTabPrefsProvider.prefs.off(pref, this.handlePrefChange);
       }
     }
 
     PlacesProvider.links.uninit();
     NewTabPrefsProvider.prefs.uninit();
+    NewTabSearchProvider.search.uninit();
     NewTabWebChannel.uninit();
   }
 };
--- a/browser/components/newtab/NewTabPrefsProvider.jsm
+++ b/browser/components/newtab/NewTabPrefsProvider.jsm
@@ -23,26 +23,28 @@ const gPrefsMap = new Map([
   ["browser.newtabpage.enabled", "bool"],
   ["browser.newtabpage.enhanced", "bool"],
   ["browser.newtabpage.introShown", "bool"],
   ["browser.newtabpage.updateIntroShown", "bool"],
   ["browser.newtabpage.pinned", "str"],
   ["browser.newtabpage.blocked", "str"],
   ["intl.locale.matchOS", "bool"],
   ["general.useragent.locale", "localized"],
+  ["browser.search.hiddenOneOffs", "str"],
 ]);
 
 // prefs that are important for the newtab page
 const gNewtabPagePrefs = new Set([
   "browser.newtabpage.enabled",
   "browser.newtabpage.enhanced",
   "browser.newtabpage.pinned",
   "browser.newtabpage.blocked",
   "browser.newtabpage.introShown",
-  "browser.newtabpage.updateIntroShown"
+  "browser.newtabpage.updateIntroShown",
+  "browser.search.hiddenOneOffs",
 ]);
 
 let PrefsProvider = function PrefsProvider() {
   EventEmitter.decorate(this);
 };
 
 PrefsProvider.prototype = {
 
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/NewTabSearchProvider.jsm
@@ -0,0 +1,112 @@
+/* global XPCOMUtils, ContentSearch, Task, Services, EventEmitter */
+/* exported NewTabSearchProvider */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = ["NewTabSearchProvider"];
+
+const {utils: Cu, interfaces: Ci} = Components;
+const CURRENT_ENGINE = "browser-search-engine-modified";
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Task.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
+                                  "resource:///modules/ContentSearch.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "EventEmitter", function() {
+  const {EventEmitter} = Cu.import("resource://devtools/shared/event-emitter.js", {});
+  return EventEmitter;
+});
+
+function SearchProvider() {
+  EventEmitter.decorate(this);
+}
+
+SearchProvider.prototype = {
+
+  observe(subject, topic, data) { // jshint unused:false
+    switch (data) {
+      case "engine-current":
+        if (topic === CURRENT_ENGINE) {
+          Task.spawn(function* () {
+            try {
+              let state = yield ContentSearch.currentStateObj(true);
+              let engine = state.currentEngine;
+              this.emit(CURRENT_ENGINE, engine);
+            } catch (e) {
+              Cu.reportError(e);
+            }
+          }.bind(this));
+        }
+        break;
+      case "engine-default":
+        // engine-default is always sent with engine-current and isn't
+        // relevant to content searches.
+        break;
+      default:
+        Cu.reportError(new Error("NewTabSearchProvider observing unknown topic"));
+        break;
+    }
+  },
+
+  init() {
+    try {
+      Services.obs.addObserver(this, CURRENT_ENGINE, true);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
+    Ci.nsISupportsWeakReference
+  ]),
+
+  uninit() {
+    try {
+      Services.obs.removeObserver(this, CURRENT_ENGINE, true);
+    } catch (e) {
+      Cu.reportError(e);
+    }
+  },
+
+  get searchSuggestionUIStrings() {
+    return ContentSearch.searchSuggestionUIStrings;
+  },
+
+  removeFormHistory({browser}, suggestion) {
+    ContentSearch.removeFormHistoryEntry({target: browser}, suggestion);
+  },
+
+  manageEngines(browser) {
+    const browserWin = browser.ownerDocument.defaultView;
+    browserWin.openPreferences("paneSearch");
+  },
+
+  asyncGetState: Task.async(function*() {
+    let state = yield ContentSearch.currentStateObj(true);
+    return state;
+  }),
+
+  asyncPerformSearch: Task.async(function*({browser}, searchData) {
+    ContentSearch.performSearch({target: browser}, searchData);
+    yield ContentSearch.addFormHistoryEntry({target: browser}, searchData.searchString);
+  }),
+
+  asyncCycleEngine: Task.async(function*(engineName) {
+    Services.search.currentEngine = Services.search.getEngineByName(engineName);
+    let state = yield ContentSearch.currentStateObj(true);
+    let newEngine = state.currentEngine;
+    this.emit(CURRENT_ENGINE, newEngine);
+  }),
+
+  asyncGetSuggestions: Task.async(function*(engineName, searchString, target) {
+    let suggestions = ContentSearch.getSuggestions(engineName, searchString, target.browser);
+    return suggestions;
+  }),
+};
+
+const NewTabSearchProvider = {
+  search: new SearchProvider(),
+};
--- a/browser/components/newtab/moz.build
+++ b/browser/components/newtab/moz.build
@@ -9,16 +9,17 @@ BROWSER_CHROME_MANIFESTS += ['tests/brow
 XPCSHELL_TESTS_MANIFESTS += [
     'tests/xpcshell/xpcshell.ini',
 ]
 
 EXTRA_JS_MODULES += [
     'NewTabMessages.jsm',
     'NewTabPrefsProvider.jsm',
     'NewTabRemoteResources.jsm',
+    'NewTabSearchProvider.jsm',
     'NewTabURL.jsm',
     'NewTabWebChannel.jsm',
     'PlacesProvider.jsm',
     'PreviewProvider.jsm'
 ]
 
 XPIDL_SOURCES += [
     'nsIAboutNewTabService.idl',
--- a/browser/components/newtab/tests/browser/browser.ini
+++ b/browser/components/newtab/tests/browser/browser.ini
@@ -1,14 +1,15 @@
 [DEFAULT]
 support-files =
   blue_page.html
   dummy_page.html
   newtabwebchannel_basic.html
   newtabmessages_places.html
   newtabmessages_prefs.html
   newtabmessages_preview.html
+  newtabmessages_search.html
 
 [browser_PreviewProvider.js]
 [browser_remotenewtab_pageloads.js]
 [browser_newtab_overrides.js]
 [browser_newtabmessages.js]
 [browser_newtabwebchannel.js]
--- a/browser/components/newtab/tests/browser/browser_newtabmessages.js
+++ b/browser/components/newtab/tests/browser/browser_newtabmessages.js
@@ -1,13 +1,15 @@
-/* globals Cu, XPCOMUtils, Preferences, is, registerCleanupFunction, NewTabWebChannel, PlacesTestUtils, Task */
+/* globals Cu, XPCOMUtils, Preferences, is, registerCleanupFunction, NewTabWebChannel,
+PlacesTestUtils, NewTabMessages, ok, Services, PlacesUtils, NetUtil, Task */
 
 "use strict";
 
 Cu.import("resource://gre/modules/Preferences.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabWebChannel",
                                   "resource:///modules/NewTabWebChannel.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NewTabMessages",
                                   "resource:///modules/NewTabMessages.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
                                   "resource://testing-common/PlacesTestUtils.jsm");
 
@@ -156,8 +158,65 @@ add_task(function* placesMessages_reques
         resolve();
       });
     });
     yield PlacesTestUtils.clearHistory();
     yield placesChangeAck;
   });
   yield cleanup();
 });
+
+/*
+ * Sanity tests for search messages
+ */
+add_task(function* searchMessages_request() {
+  yield setup();
+  let testURL = "https://example.com/browser/browser/components/newtab/tests/browser/newtabmessages_search.html";
+
+  // create dummy test engines
+  Services.search.addEngineWithDetails("Engine1", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
+  Services.search.addEngineWithDetails("Engine2", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
+
+  let tabOptions = {
+    gBrowser,
+    url: testURL
+  };
+
+  let UIStringsResponseAck = new Promise(resolve => {
+    NewTabWebChannel.once("UIStringsAck", (_, msg) => {
+      ok(true, "a search request response for UI string has been received");
+      ok(msg.data, "received the UI Strings");
+      resolve();
+    });
+  });
+  let suggestionsResponseAck = new Promise(resolve => {
+    NewTabWebChannel.once("suggestionsAck", (_, msg) => {
+      ok(true, "a search request response for suggestions has been received");
+      ok(msg.data, "received the suggestions");
+      resolve();
+    });
+  });
+  let stateResponseAck = new Promise(resolve => {
+    NewTabWebChannel.once("stateAck", (_, msg) => {
+      ok(true, "a search request response for state has been received");
+      ok(msg.data, "received a state object");
+      resolve();
+    });
+  });
+  let currentEngineResponseAck = new Promise(resolve => {
+    NewTabWebChannel.once("currentEngineAck", (_, msg) => {
+      ok(true, "a search request response for current engine has been received");
+      ok(msg.data, "received a current engine");
+      resolve();
+    });
+  });
+
+  yield BrowserTestUtils.withNewTab(tabOptions, function*() {
+    yield UIStringsResponseAck;
+    yield suggestionsResponseAck;
+    yield stateResponseAck;
+    yield currentEngineResponseAck;
+  });
+
+  cleanup();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/browser/newtabmessages_search.html
@@ -0,0 +1,113 @@
+<html>
+  <head>
+    <meta charset="utf8">
+    <title>Newtab WebChannel test</title>
+  </head>
+  <body>
+    <script>
+      let suggestionsData = {
+        engineName: "Engine1",
+        searchString: "test",
+      };
+      let removeFormHistoryData = "test";
+      let performSearchData = {
+        engineName: "Engine1",
+        healthReportKey: "1",
+        searchPurpose: "d",
+        searchString: "test",
+      };
+      let cycleEngineData = "Engine2";
+
+      window.addEventListener("WebChannelMessageToContent", function(e) {
+        if (e.detail.message) {
+          let reply;
+          switch (e.detail.message.type) {
+            case "RECEIVE_UISTRINGS":
+              reply = new window.CustomEvent("WebChannelMessageToChrome", {
+                detail: {
+                  id: "newtab",
+                  message: JSON.stringify({type: "UIStringsAck", data: e.detail.message.data}),
+                }
+              });
+              window.dispatchEvent(reply);
+              break;
+            case "RECEIVE_SEARCH_SUGGESTIONS":
+              reply = new window.CustomEvent("WebChannelMessageToChrome", {
+                detail: {
+                  id: "newtab",
+                  message: JSON.stringify({type: "suggestionsAck", data: e.detail.message.data}),
+                }
+              });
+              window.dispatchEvent(reply);
+              break;
+            case "RECEIVE_SEARCH_STATE":
+              reply = new window.CustomEvent("WebChannelMessageToChrome", {
+                detail: {
+                  id: "newtab",
+                  message: JSON.stringify({type: "stateAck", data: e.detail.message.data}),
+                }
+              });
+              window.dispatchEvent(reply);
+              break;
+            case "RECEIVE_CURRENT_ENGINE":
+              reply = new window.CustomEvent("WebChannelMessageToChrome", {
+                detail: {
+                  id: "newtab",
+                  message: JSON.stringify({type: "currentEngineAck", data: e.detail.message.data}),
+                }
+              });
+              window.dispatchEvent(reply);
+              break;
+          }
+        }
+      }, true);
+
+      document.onreadystatechange = function () {
+        if (document.readyState === "complete") {
+          let msg = new window.CustomEvent("WebChannelMessageToChrome", {
+            detail: {
+              id: "newtab",
+              message: JSON.stringify({type: "REQUEST_UISTRINGS"}),
+            }
+          });
+          window.dispatchEvent(msg);
+          msg = new window.CustomEvent("WebChannelMessageToChrome", {
+            detail: {
+              id: "newtab",
+              message: JSON.stringify({type: "REQUEST_SEARCH_SUGGESTIONS", data: suggestionsData}),
+            }
+          });
+          window.dispatchEvent(msg);
+          msg = new window.CustomEvent("WebChannelMessageToChrome", {
+            detail: {
+              id: "newtab",
+              message: JSON.stringify({type: "REQUEST_SEARCH_STATE"}),
+            }
+          });
+          window.dispatchEvent(msg);
+          msg = new window.CustomEvent("WebChannelMessageToChrome", {
+            detail: {
+              id: "newtab",
+              message: JSON.stringify({type: "REQUEST_REMOVE_FORM_HISTORY", data: removeFormHistoryData}),
+            }
+          });
+          window.dispatchEvent(msg);
+          msg = new window.CustomEvent("WebChannelMessageToChrome", {
+            detail: {
+              id: "newtab",
+              message: JSON.stringify({type: "REQUEST_PERFORM_SEARCH", data: performSearchData}),
+            }
+          });
+          window.dispatchEvent(msg);
+          msg = new window.CustomEvent("WebChannelMessageToChrome", {
+            detail: {
+              id: "newtab",
+              message: JSON.stringify({type: "REQUEST_CYCLE_ENGINE", data: cycleEngineData}),
+            }
+          });
+          window.dispatchEvent(msg);
+        }
+      }
+    </script>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/browser/components/newtab/tests/xpcshell/test_NewTabSearchProvider.js
@@ -0,0 +1,84 @@
+"use strict";
+
+/* global XPCOMUtils, NewTabSearchProvider, run_next_test, ok, equal, do_check_true, do_get_profile, Services */
+/* exported run_test */
+/* jscs:disable requireCamelCaseOrUpperCaseIdentifiers */
+
+const Cu = Components.utils;
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabSearchProvider",
+    "resource:///modules/NewTabSearchProvider.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
+                                  "resource:///modules/ContentSearch.jsm");
+
+// ensure a profile exists
+do_get_profile();
+
+function run_test() {
+  run_next_test();
+}
+
+function hasProp(obj) {
+  return function(aProp) {
+    ok(obj.hasOwnProperty(aProp), `expect to have property ${aProp}`);
+  };
+}
+
+add_task(function* test_search() {
+  ContentSearch.init();
+  let observerPromise = new Promise(resolve => {
+    Services.obs.addObserver(function observer(aSubject, aTopic, aData) {
+      if (aData === "init-complete" && aTopic === "browser-search-service") {
+        Services.obs.removeObserver(observer, "browser-search-service");
+        resolve();
+      }
+    }, "browser-search-service", false);
+  });
+  Services.search.init();
+  yield observerPromise;
+  do_check_true(Services.search.isInitialized);
+
+  // get initial state of search and check it has correct properties
+  let state = yield NewTabSearchProvider.search.asyncGetState();
+  let stateProps = hasProp(state);
+  ["engines", "currentEngine"].forEach(stateProps);
+
+  // check that the current engine is correct and has correct properties
+  let {currentEngine} = state;
+  equal(currentEngine.name, Services.search.currentEngine.name, "Current engine has been correctly set");
+  var engineProps = hasProp(currentEngine);
+  ["name", "placeholder", "iconBuffer"].forEach(engineProps);
+
+  //create dummy test engines to test observer
+  Services.search.addEngineWithDetails("TestSearch1", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
+  Services.search.addEngineWithDetails("TestSearch2", "", "", "", "GET",
+    "http://example.com/?q={searchTerms}");
+
+  // set one of the dummy test engines to the default engine
+  Services.search.defaultEngine = Services.search.getEngineByName("TestSearch1");
+
+  // test that the event emitter is working by setting a new current engine "TestSearch2"
+  let engineName = "TestSearch2";
+  NewTabSearchProvider.search.init();
+
+  // event emitter will fire when current engine is changed
+  let promise = new Promise(resolve => {
+    NewTabSearchProvider.search.once("browser-search-engine-modified", (name, data) => { // jshint ignore:line
+      resolve([name, data.name]);
+    });
+  });
+
+  // set a new current engine
+  Services.search.currentEngine = Services.search.getEngineByName(engineName);
+  let expectedEngineName = Services.search.currentEngine.name;
+
+  // emitter should fire and return the new engine
+  let [eventName, actualEngineName] = yield promise;
+  equal(eventName, "browser-search-engine-modified", `emitter sent the correct event ${eventName}`);
+  equal(expectedEngineName, actualEngineName, `emitter set the correct engine ${expectedEngineName}`);
+  NewTabSearchProvider.search.uninit();
+});
+
--- a/browser/components/newtab/tests/xpcshell/xpcshell.ini
+++ b/browser/components/newtab/tests/xpcshell/xpcshell.ini
@@ -1,10 +1,11 @@
 [DEFAULT]
 head =
 tail =
 firefox-appdir = browser
 skip-if = toolkit == 'android' || toolkit == 'gonk'
 
 [test_AboutNewTabService.js]
 [test_NewTabPrefsProvider.js]
+[test_NewTabSearchProvider.js]
 [test_NewTabURL.js]
 [test_PlacesProvider.js]
--- a/browser/components/sessionstore/test/browser_339445.js
+++ b/browser/components/sessionstore/test/browser_339445.js
@@ -1,32 +1,32 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-function test() {
+add_task(function* test() {
   /** Test for Bug 339445 **/
 
-  waitForExplicitFinish();
-
   let testURL = "http://mochi.test:8888/browser/" +
     "browser/components/sessionstore/test/browser_339445_sample.html";
 
   let tab = gBrowser.addTab(testURL);
-  promiseBrowserLoaded(tab.linkedBrowser).then(() => {
-    let doc = tab.linkedBrowser.contentDocument;
+  yield promiseBrowserLoaded(tab.linkedBrowser);
+
+  yield ContentTask.spawn(tab.linkedBrowser, null, function() {
+    let doc = content.document;
     is(doc.getElementById("storageTestItem").textContent, "PENDING",
        "sessionStorage value has been set");
+  });
 
-    let tab2 = gBrowser.duplicateTab(tab);
-    promiseTabRestored(tab2).then(() => {
-      let doc2 = tab2.linkedBrowser.contentDocument;
-      is(doc2.getElementById("storageTestItem").textContent, "SUCCESS",
-         "sessionStorage value has been duplicated");
+  let tab2 = gBrowser.duplicateTab(tab);
+  yield promiseTabRestored(tab2);
 
-      // clean up
-      gBrowser.removeTab(tab2);
-      gBrowser.removeTab(tab);
+  yield ContentTask.spawn(tab2.linkedBrowser, null, function() {
+    let doc2 = content.document;
+    is(doc2.getElementById("storageTestItem").textContent, "SUCCESS",
+       "sessionStorage value has been duplicated");
+  });
 
-      finish();
-    });
-  });
-}
+  // clean up
+  yield Promise.all([ BrowserTestUtils.removeTab(tab2),
+                      BrowserTestUtils.removeTab(tab) ]);
+});
--- a/browser/confvars.sh
+++ b/browser/confvars.sh
@@ -23,21 +23,16 @@ if test "$OS_ARCH" = "WINNT"; then
     fi
   fi
 fi
 
 # Enable building ./signmar and running libmar signature tests
 MOZ_ENABLE_SIGNMAR=1
 
 MOZ_SAFE_BROWSING=1
-MOZ_SERVICES_COMMON=1
-MOZ_SERVICES_CRYPTO=1
-MOZ_SERVICES_HEALTHREPORT=1
-MOZ_SERVICES_SYNC=1
-MOZ_SERVICES_CLOUDSYNC=1
 MOZ_APP_VERSION=$FIREFOX_VERSION
 MOZ_APP_VERSION_DISPLAY=$FIREFOX_VERSION_DISPLAY
 MOZ_EXTENSIONS_DEFAULT=" gio"
 # MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
 # MOZ_BRANDING_DIRECTORY is the default branding directory used when none is
 # specified. It should never point to the "official" branding directory.
 # For mozilla-beta, mozilla-release, or mozilla-central repositories, use
 # "unofficial" branding.
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -677,19 +677,16 @@
 @RESPATH@/browser/defaults/permissions
 
 ; Warning: changing the path to channel-prefs.js can cause bugs (Bug 756325)
 ; Technically this is an app pref file, but we are keeping it in the original
 ; gre location for now.
 @RESPATH@/defaults/pref/channel-prefs.js
 
 ; Services (gre) prefs
-#ifdef MOZ_SERVICES_NOTIFICATIONS
-@RESPATH@/defaults/pref/services-notifications.js
-#endif
 @RESPATH@/defaults/pref/services-sync.js
 
 ; [Layout Engine Resources]
 ; Style Sheets, Graphics and other Resources used by the layout engine.
 @RESPATH@/res/EditorOverride.css
 @RESPATH@/res/contenteditable.css
 @RESPATH@/res/designmode.css
 @RESPATH@/res/ImageDocument.css
--- a/browser/locales/en-US/chrome/overrides/netError.dtd
+++ b/browser/locales/en-US/chrome/overrides/netError.dtd
@@ -200,8 +200,11 @@ Strict Transport Security (HSTS) to spec
 to it securely. As a result, it is not possible to add an exception for this
 certificate.">
 <!ENTITY certerror.copyToClipboard.label "Copy text to clipboard">
 
 <!ENTITY inadequateSecurityError.title "Your connection is not secure">
 <!-- LOCALIZATION NOTE (inadequateSecurityError.longDesc) - Do not translate
      "NS_ERROR_NET_INADEQUATE_SECURITY". -->
 <!ENTITY inadequateSecurityError.longDesc "<p><span class='hostname'></span> uses security technology that is outdated and vulnerable to attack. An attacker could easily reveal information which you thought to be safe. The website administrator will need to fix the server first before you can visit the site.</p><p>Error code: NS_ERROR_NET_INADEQUATE_SECURITY</p>">
+
+<!ENTITY prefReset.longDesc "It looks like your network security settings might be causing this. Do you want the default settings to be restored?">
+<!ENTITY prefReset.label "Restore default settings">
--- a/browser/modules/ContentSearch.jsm
+++ b/browser/modules/ContentSearch.jsm
@@ -1,12 +1,12 @@
 /* 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/. */
-
+/* globals XPCOMUtils, Services, Task, Promise, SearchSuggestionController, FormHistory, PrivateBrowsingUtils */
 "use strict";
 
 this.EXPORTED_SYMBOLS = [
   "ContentSearch",
 ];
 
 const { classes: Cc, interfaces: Ci, utils: Cu } = Components;
 
@@ -68,20 +68,20 @@ const MAX_SUGGESTIONS = 6;
  *
  * Outbound messages have the following types:
  *
  *   CurrentEngine
  *     Broadcast when the current engine changes.
  *     data: see _currentEngineObj
  *   CurrentState
  *     Broadcast when the current search state changes.
- *     data: see _currentStateObj
+ *     data: see currentStateObj
  *   State
  *     Sent in reply to GetState.
- *     data: see _currentStateObj
+ *     data: see currentStateObj
  *   Strings
  *     Sent in reply to GetStrings
  *     data: Object containing string names and values for the current locale.
  *   Suggestions
  *     Sent in reply to GetSuggestions.
  *     data: see _onMessageGetSuggestions
  *   SuggestionsCancelled
  *     Sent in reply to GetSuggestions when pending GetSuggestions events are
@@ -121,16 +121,17 @@ this.ContentSearch = {
   get searchSuggestionUIStrings() {
     if (this._searchSuggestionUIStrings) {
       return this._searchSuggestionUIStrings;
     }
     this._searchSuggestionUIStrings = {};
     let searchBundle = Services.strings.createBundle("chrome://browser/locale/search.properties");
     let stringNames = ["searchHeader", "searchPlaceholder", "searchForSomethingWith",
                        "searchWithHeader", "searchSettings"];
+
     for (let name of stringNames) {
       this._searchSuggestionUIStrings[name] = searchBundle.GetStringFromName(name);
     }
     return this._searchSuggestionUIStrings;
   },
 
   destroy: function () {
     if (this._destroyedPromise) {
@@ -139,17 +140,18 @@ this.ContentSearch = {
 
     Cc["@mozilla.org/globalmessagemanager;1"].
       getService(Ci.nsIMessageListenerManager).
       removeMessageListener(INBOUND_MESSAGE, this);
     Services.obs.removeObserver(this, "browser-search-engine-modified");
     Services.obs.removeObserver(this, "shutdown-leaks-before-check");
 
     this._eventQueue.length = 0;
-    return this._destroyedPromise = Promise.resolve(this._currentEventPromise);
+    this._destroyedPromise = Promise.resolve(this._currentEventPromise);
+    return this._destroyedPromise;
   },
 
   /**
    * Focuses the search input in the page with the given message manager.
    * @param  messageManager
    *         The MessageManager object of the selected browser.
    */
   focusInput: function (messageManager) {
@@ -172,17 +174,17 @@ this.ContentSearch = {
       msg.target.removeEventListener("SwapDocShells", msg, true);
       msg.target = event.detail;
       msg.target.addEventListener("SwapDocShells", msg, true);
     };
     msg.target.addEventListener("SwapDocShells", msg, true);
 
     // Search requests cause cancellation of all Suggestion requests from the
     // same browser.
-    if (msg.data.type == "Search") {
+    if (msg.data.type === "Search") {
       this._cancelSuggestions(msg);
     }
 
     this._eventQueue.push({
       type: "Message",
       data: msg,
     });
     this._processEventQueue();
@@ -200,16 +202,165 @@ this.ContentSearch = {
       break;
     case "shutdown-leaks-before-check":
       subj.wrappedJSObject.client.addBlocker(
         "ContentSearch: Wait until the service is destroyed", () => this.destroy());
       break;
     }
   },
 
+  removeFormHistoryEntry: function (msg, entry) {
+    let browserData = this._suggestionDataForBrowser(msg.target);
+    if (browserData && browserData.previousFormHistoryResult) {
+      let { previousFormHistoryResult } = browserData;
+      for (let i = 0; i < previousFormHistoryResult.matchCount; i++) {
+        if (previousFormHistoryResult.getValueAt(i) === entry) {
+          previousFormHistoryResult.removeValueAt(i, true);
+          break;
+        }
+      }
+    }
+  },
+
+  performSearch: function (msg, data) {
+    this._ensureDataHasProperties(data, [
+      "engineName",
+      "searchString",
+      "healthReportKey",
+      "searchPurpose",
+    ]);
+    let engine = Services.search.getEngineByName(data.engineName);
+    let submission = engine.getSubmission(data.searchString, "", data.searchPurpose);
+    let browser = msg.target;
+    let win;
+    try {
+      win = browser.ownerDocument.defaultView;
+    }
+    catch (err) {
+      // The browser may have been closed between the time its content sent the
+      // message and the time we handle it.  In that case, trying to call any
+      // method on it will throw.
+      return;
+    }
+
+    let where = win.whereToOpenLink(data.originalEvent);
+
+    // There is a chance that by the time we receive the search message, the user
+    // has switched away from the tab that triggered the search. If, based on the
+    // event, we need to load the search in the same tab that triggered it (i.e.
+    // where === "current"), openUILinkIn will not work because that tab is no
+    // longer the current one. For this case we manually load the URI.
+    if (where === "current") {
+      browser.loadURIWithFlags(submission.uri.spec,
+                               Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
+                               submission.postData);
+    } else {
+      let params = {
+        postData: submission.postData,
+        inBackground: Services.prefs.getBoolPref("browser.tabs.loadInBackground"),
+      };
+      win.openUILinkIn(submission.uri.spec, where, params);
+    }
+    win.BrowserSearch.recordSearchInTelemetry(engine, data.healthReportKey,
+                                              data.selection || null);
+    return;
+  },
+
+  getSuggestions: Task.async(function* (engineName, searchString, browser, remoteTimeout=null) {
+    let engine = Services.search.getEngineByName(engineName);
+    if (!engine) {
+      throw new Error("Unknown engine name: " + engineName);
+    }
+
+    let browserData = this._suggestionDataForBrowser(browser, true);
+    let { controller } = browserData;
+    let ok = SearchSuggestionController.engineOffersSuggestions(engine);
+    controller.maxLocalResults = ok ? MAX_LOCAL_SUGGESTIONS : MAX_SUGGESTIONS;
+    controller.maxRemoteResults = ok ? MAX_SUGGESTIONS : 0;
+    controller.remoteTimeout = remoteTimeout || undefined;
+    let priv = PrivateBrowsingUtils.isBrowserPrivate(browser);
+    // fetch() rejects its promise if there's a pending request, but since we
+    // process our event queue serially, there's never a pending request.
+    this._currentSuggestion = { controller: controller, target: browser };
+    let suggestions = yield controller.fetch(searchString, priv, engine);
+    this._currentSuggestion = null;
+
+    // suggestions will be null if the request was cancelled
+    let result = {};
+    if (!suggestions) {
+      return result;
+    }
+
+    // Keep the form history result so RemoveFormHistoryEntry can remove entries
+    // from it.  Keeping only one result isn't foolproof because the client may
+    // try to remove an entry from one set of suggestions after it has requested
+    // more but before it's received them.  In that case, the entry may not
+    // appear in the new suggestions.  But that should happen rarely.
+    browserData.previousFormHistoryResult = suggestions.formHistoryResult;
+    result = {
+      engineName,
+      term: suggestions.term,
+      local: suggestions.local,
+      remote: suggestions.remote,
+    };
+    return result;
+  }),
+
+  addFormHistoryEntry: Task.async(function* (browser, entry="") {
+    let isPrivate = false;
+    try {
+      // isBrowserPrivate assumes that the passed-in browser has all the normal
+      // properties, which won't be true if the browser has been destroyed.
+      // That may be the case here due to the asynchronous nature of messaging.
+      isPrivate = PrivateBrowsingUtils.isBrowserPrivate(browser.target);
+    } catch (err) {
+      return false;
+    }
+    if (isPrivate || entry === "") {
+      return false;
+    }
+    let browserData = this._suggestionDataForBrowser(browser.target, true);
+    FormHistory.update({
+      op: "bump",
+      fieldname: browserData.controller.formHistoryParam,
+      value: entry,
+    }, {
+      handleCompletion: () => {},
+      handleError: err => {
+        Cu.reportError("Error adding form history entry: " + err);
+      },
+    });
+    return true;
+  }),
+
+  currentStateObj: Task.async(function* (uriFlag=false) {
+    let state = {
+      engines: [],
+      currentEngine: yield this._currentEngineObj(),
+    };
+    if (uriFlag) {
+      state.currentEngine.iconBuffer = Services.search.currentEngine.getIconURLBySize(16, 16);
+    }
+    let pref = Services.prefs.getCharPref("browser.search.hiddenOneOffs");
+    let hiddenList = pref ? pref.split(",") : [];
+    for (let engine of Services.search.getVisibleEngines()) {
+      let uri = engine.getIconURLBySize(16, 16);
+      let iconBuffer = uri;
+      if (!uriFlag) {
+        iconBuffer = yield this._arrayBufferFromDataURI(uri);
+      }
+      state.engines.push({
+        name: engine.name,
+        iconBuffer,
+        hidden: hiddenList.indexOf(engine.name) !== -1,
+      });
+    }
+    return state;
+  }),
+
   _processEventQueue: function () {
     if (this._currentEventPromise || !this._eventQueue.length) {
       return;
     }
 
     let event = this._eventQueue.shift();
 
     this._currentEventPromise = Task.spawn(function* () {
@@ -222,24 +373,24 @@ this.ContentSearch = {
         this._processEventQueue();
       }
     }.bind(this));
   },
 
   _cancelSuggestions: function (msg) {
     let cancelled = false;
     // cancel active suggestion request
-    if (this._currentSuggestion && this._currentSuggestion.target == msg.target) {
+    if (this._currentSuggestion && this._currentSuggestion.target === msg.target) {
       this._currentSuggestion.controller.stop();
       cancelled = true;
     }
     // cancel queued suggestion requests
     for (let i = 0; i < this._eventQueue.length; i++) {
       let m = this._eventQueue[i].data;
-      if (msg.target == m.target && m.data.type == "GetSuggestions") {
+      if (msg.target === m.target && m.data.type === "GetSuggestions") {
         this._eventQueue.splice(i, 1);
         cancelled = true;
         i--;
       }
     }
     if (cancelled) {
       this._reply(msg, "SuggestionsCancelled");
     }
@@ -250,186 +401,83 @@ this.ContentSearch = {
     if (methodName in this) {
       yield this._initService();
       yield this[methodName](msg, msg.data.data);
       msg.target.removeEventListener("SwapDocShells", msg, true);
     }
   }),
 
   _onMessageGetState: function (msg, data) {
-    return this._currentStateObj().then(state => {
+    return this.currentStateObj().then(state => {
       this._reply(msg, "State", state);
     });
   },
 
   _onMessageGetStrings: function (msg, data) {
     this._reply(msg, "Strings", this.searchSuggestionUIStrings);
   },
 
   _onMessageSearch: function (msg, data) {
-    this._ensureDataHasProperties(data, [
-      "engineName",
-      "searchString",
-      "healthReportKey",
-      "searchPurpose",
-    ]);
-    let engine = Services.search.getEngineByName(data.engineName);
-    let submission = engine.getSubmission(data.searchString, "", data.searchPurpose);
-    let browser = msg.target;
-    let win;
-    try {
-      win = browser.ownerDocument.defaultView;
-    }
-    catch (err) {
-      // The browser may have been closed between the time its content sent the
-      // message and the time we handle it.  In that case, trying to call any
-      // method on it will throw.
-      return Promise.resolve();
-    }
-
-    let where = win.whereToOpenLink(data.originalEvent);
-
-    // There is a chance that by the time we receive the search message, the user
-    // has switched away from the tab that triggered the search. If, based on the
-    // event, we need to load the search in the same tab that triggered it (i.e.
-    // where == "current"), openUILinkIn will not work because that tab is no
-    // longer the current one. For this case we manually load the URI.
-    if (where == "current") {
-      browser.loadURIWithFlags(submission.uri.spec,
-                               Ci.nsIWebNavigation.LOAD_FLAGS_NONE, null, null,
-                               submission.postData);
-    } else {
-      let params = {
-        postData: submission.postData,
-        inBackground: Services.prefs.getBoolPref("browser.tabs.loadInBackground"),
-      };
-      win.openUILinkIn(submission.uri.spec, where, params);
-    }
-    win.BrowserSearch.recordSearchInTelemetry(engine, data.healthReportKey,
-                                              data.selection || null);
-    return Promise.resolve();
+    this.performSearch(msg, data);
   },
 
   _onMessageSetCurrentEngine: function (msg, data) {
     Services.search.currentEngine = Services.search.getEngineByName(data);
-    return Promise.resolve();
   },
 
   _onMessageManageEngines: function (msg, data) {
     let browserWin = msg.target.ownerDocument.defaultView;
     browserWin.openPreferences("paneSearch");
-    return Promise.resolve();
   },
 
   _onMessageGetSuggestions: Task.async(function* (msg, data) {
     this._ensureDataHasProperties(data, [
       "engineName",
       "searchString",
     ]);
-
-    let engine = Services.search.getEngineByName(data.engineName);
-    if (!engine) {
-      throw new Error("Unknown engine name: " + data.engineName);
-    }
-
-    let browserData = this._suggestionDataForBrowser(msg.target, true);
-    let { controller } = browserData;
-    let ok = SearchSuggestionController.engineOffersSuggestions(engine);
-    controller.maxLocalResults = ok ? MAX_LOCAL_SUGGESTIONS : MAX_SUGGESTIONS;
-    controller.maxRemoteResults = ok ? MAX_SUGGESTIONS : 0;
-    controller.remoteTimeout = data.remoteTimeout || undefined;
-    let priv = PrivateBrowsingUtils.isBrowserPrivate(msg.target);
-    // fetch() rejects its promise if there's a pending request, but since we
-    // process our event queue serially, there's never a pending request.
-    this._currentSuggestion = { controller: controller, target: msg.target };
-    let suggestions = yield controller.fetch(data.searchString, priv, engine);
-    this._currentSuggestion = null;
-
-    // suggestions will be null if the request was cancelled
-    if (!suggestions) {
-      return;
-    }
-
-    // Keep the form history result so RemoveFormHistoryEntry can remove entries
-    // from it.  Keeping only one result isn't foolproof because the client may
-    // try to remove an entry from one set of suggestions after it has requested
-    // more but before it's received them.  In that case, the entry may not
-    // appear in the new suggestions.  But that should happen rarely.
-    browserData.previousFormHistoryResult = suggestions.formHistoryResult;
+    let {engineName, searchString} = data;
+    let suggestions = yield this.getSuggestions(engineName, searchString, msg.target);
 
     this._reply(msg, "Suggestions", {
       engineName: data.engineName,
       searchString: suggestions.term,
       formHistory: suggestions.local,
       remote: suggestions.remote,
     });
   }),
 
-  _onMessageAddFormHistoryEntry: function (msg, entry) {
-    let isPrivate = true;
-    try {
-      // isBrowserPrivate assumes that the passed-in browser has all the normal
-      // properties, which won't be true if the browser has been destroyed.
-      // That may be the case here due to the asynchronous nature of messaging.
-      isPrivate = PrivateBrowsingUtils.isBrowserPrivate(msg.target);
-    } catch (err) {}
-    if (isPrivate || entry === "") {
-      return Promise.resolve();
-    }
-    let browserData = this._suggestionDataForBrowser(msg.target, true);
-    if (FormHistory.enabled) {
-      FormHistory.update({
-        op: "bump",
-        fieldname: browserData.controller.formHistoryParam,
-        value: entry,
-      }, {
-        handleCompletion: () => {},
-        handleError: err => {
-          Cu.reportError("Error adding form history entry: " + err);
-        },
-      });
-    }
-    return Promise.resolve();
-  },
+  _onMessageAddFormHistoryEntry: Task.async(function* (msg, entry) {
+    yield this.addFormHistoryEntry(msg, entry);
+  }),
 
   _onMessageRemoveFormHistoryEntry: function (msg, entry) {
-    let browserData = this._suggestionDataForBrowser(msg.target);
-    if (browserData && browserData.previousFormHistoryResult) {
-      let { previousFormHistoryResult } = browserData;
-      for (let i = 0; i < previousFormHistoryResult.matchCount; i++) {
-        if (previousFormHistoryResult.getValueAt(i) == entry) {
-          previousFormHistoryResult.removeValueAt(i, true);
-          break;
-        }
-      }
-    }
-    return Promise.resolve();
+    this.removeFormHistoryEntry(msg, entry);
   },
 
   _onMessageSpeculativeConnect: function (msg, engineName) {
     let engine = Services.search.getEngineByName(engineName);
     if (!engine) {
       throw new Error("Unknown engine name: " + engineName);
     }
     if (msg.target.contentWindow) {
       engine.speculativeConnect({
         window: msg.target.contentWindow,
       });
     }
   },
 
   _onObserve: Task.async(function* (data) {
-    if (data == "engine-current") {
+    if (data === "engine-current") {
       let engine = yield this._currentEngineObj();
       this._broadcast("CurrentEngine", engine);
     }
-    else if (data != "engine-default") {
+    else if (data !== "engine-default") {
       // engine-default is always sent with engine-current and isn't otherwise
       // relevant to content searches.
-      let state = yield this._currentStateObj();
+      let state = yield this.currentStateObj();
       this._broadcast("CurrentState", state);
     }
   }),
 
   _suggestionDataForBrowser: function (browser, create=false) {
     let data = this._suggestionMap.get(browser);
     if (!data && create) {
       // Since one SearchSuggestionController instance is meant to be used per
@@ -459,34 +507,16 @@ this.ContentSearch = {
 
   _msgArgs: function (type, data) {
     return [OUTBOUND_MESSAGE, {
       type: type,
       data: data,
     }];
   },
 
-  _currentStateObj: Task.async(function* () {
-    let state = {
-      engines: [],
-      currentEngine: yield this._currentEngineObj(),
-    };
-    let pref = Services.prefs.getCharPref("browser.search.hiddenOneOffs");
-    let hiddenList = pref ? pref.split(",") : [];
-    for (let engine of Services.search.getVisibleEngines()) {
-      let uri = engine.getIconURLBySize(16, 16);
-      state.engines.push({
-        name: engine.name,
-        iconBuffer: yield this._arrayBufferFromDataURI(uri),
-        hidden: hiddenList.indexOf(engine.name) != -1,
-      });
-    }
-    return state;
-  }),
-
   _currentEngineObj: Task.async(function* () {
     let engine = Services.search.currentEngine;
     let favicon = engine.getIconURLBySize(16, 16);
     let placeholder = this._stringBundle.formatStringFromName(
       "searchWithEngine", [engine.name], 1);
     let obj = {
       name: engine.name,
       placeholder: placeholder,
--- a/browser/moz.configure
+++ b/browser/moz.configure
@@ -1,7 +1,12 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+imply_option('MOZ_PLACES', True)
+imply_option('MOZ_SERVICES_HEALTHREPORT', True)
+imply_option('MOZ_SERVICES_SYNC', True)
+imply_option('MOZ_SERVICES_CLOUDSYNC', True)
+
 include('../toolkit/moz.configure')
--- a/browser/themes/shared/aboutNetError.css
+++ b/browser/themes/shared/aboutNetError.css
@@ -26,16 +26,20 @@ body.certerror .title {
 
 /* Pressing the retry button will cause the cursor to flicker from a pointer to
  * not-allowed. Override the disabled cursor behaviour since we will never show
  * the button disabled as the initial state. */
 button:disabled {
   cursor: pointer;
 }
 
+#prefChangeContainer {
+  display: none;
+}
+
 #learnMoreContainer {
   display: none;
 }
 
 #certErrorButtonContainer {
   display: none;
 }
 
--- a/build/moz.configure/checks.configure
+++ b/build/moz.configure/checks.configure
@@ -76,26 +76,31 @@ def checking(what, callback=None):
 # - `what` is a human readable description of what is being looked for. It
 #   defaults to the lowercase version of `var`.
 # - `input` is a string reference to an existing option or a reference to a
 #   @depends function resolving to explicit input for the program check.
 #   The default is to create an option for the environment variable `var`.
 #   This argument allows to use a different kind of option (possibly using a
 #   configure flag), or doing some pre-processing with a @depends function.
 # - `allow_missing` indicates whether not finding the program is an error.
+# - `paths` is a list of paths or @depends function returning a list of paths
+#   that will cause the given path(s) to be searched rather than $PATH. Input
+#   paths may either be individual paths or delimited by os.pathsep, to allow
+#   passing $PATH (for example) as an element.
 #
 # The simplest form is:
 #   check_prog('PROG', ('a', 'b'))
 # This will look for 'a' or 'b' in $PATH, and set_config PROG to the one
 # it can find. If PROG is already set from the environment or command line,
 # use that value instead.
 @template
 @imports(_from='mozbuild.shellutil', _import='quote')
 @imports(_from='mozbuild.configure', _import='DependsFunction')
-def check_prog(var, progs, what=None, input=None, allow_missing=False):
+def check_prog(var, progs, what=None, input=None, allow_missing=False,
+               paths=None):
     if input:
         # Wrap input with type checking and normalization.
         @depends(input)
         def input(value):
             if not value:
                 return
             if isinstance(value, str):
                 return (value,)
@@ -104,32 +109,34 @@ def check_prog(var, progs, what=None, in
             configure_error('input must resolve to a tuple or a list with a '
                             'single element, or a string')
     else:
         option(env=var, nargs=1,
                help='Path to %s' % (what or 'the %s program' % var.lower()))
         input = var
     what = what or var.lower()
 
+    # Trick to make a @depends function out of an immediate value.
     if not isinstance(progs, DependsFunction):
-        # Trick to make a @depends function out of an immediate value.
         progs = depends('--help')(lambda h: progs)
+    if not isinstance(paths, DependsFunction):
+        paths = depends('--help')(lambda h: paths)
 
-    @depends_if(input, progs)
+    @depends_if(input, progs, paths)
     @checking('for %s' % what, lambda x: quote(x) if x else 'not found')
-    def check(value, progs):
+    def check(value, progs, paths):
         if progs is None:
             progs = ()
 
         if not isinstance(progs, (tuple, list)):
             configure_error('progs must resolve to a list or tuple!')
 
         for prog in value or progs:
             log.debug('%s: Trying %s', var.lower(), quote(prog))
-            result = find_program(prog)
+            result = find_program(prog, paths)
             if result:
                 return result
 
         if not allow_missing or value:
             raise FatalCheckError('Cannot find %s' % what)
 
     @depends_if(check, progs)
     def normalized_for_config(value, progs):
--- a/build/moz.configure/init.configure
+++ b/build/moz.configure/init.configure
@@ -679,31 +679,32 @@ set_config('NIGHTLY_BUILD', delayed_geta
 set_define('NIGHTLY_BUILD', delayed_getattr(milestone, 'is_nightly'))
 add_old_configure_assignment('NIGHTLY_BUILD',
                              delayed_getattr(milestone, 'is_nightly'))
 set_config('RELEASE_BUILD', delayed_getattr(milestone, 'is_release'))
 set_define('RELEASE_BUILD', delayed_getattr(milestone, 'is_release'))
 add_old_configure_assignment('RELEASE_BUILD',
                              delayed_getattr(milestone, 'is_release'))
 
-# A template providing a shorthand for tying an environment-set option to
-# the corresponding variable in set_config, where the value of that variable
-# passed to set_config only depends on the provided value and default.
+# A template providing a shorthand for setting a variable. The created
+# option will only be settable with imply_option.
+# It is expected that a project-specific moz.configure will call imply_option
+# to set a value other than the default.
 # If required, the set_as_define and set_for_old_configure arguments
 # will additionally cause the variable to be set using set_define and
 # add_old_configure_assignment. util.configure would be an appropriate place for
 # this, but it uses add_old_configure_assignment, which is defined in this file.
 @template
-def env_flag(env=None, set_for_old_configure=False, set_as_define=False,
-             **kwargs):
+def project_flag(env=None, set_for_old_configure=False,
+                 set_as_define=False, **kwargs):
 
     if not env:
-        configure_error("An env_flag must be passed a variable name to set.")
+        configure_error("A project_flag must be passed a variable name to set.")
 
-    opt = option(env=env, **kwargs)
+    opt = option(env=env, possible_origins=('implied',), **kwargs)
 
     @depends(opt.option)
     def option_implementation(value):
         if value:
             if len(value):
                 return value
             return bool(value)
 
new file mode 100644
--- /dev/null
+++ b/build/moz.configure/java.configure
@@ -0,0 +1,62 @@
+# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+
+# Java detection
+# ========================================================
+option('--with-java-bin-path', nargs=1,
+       help='Location of Java binaries (java, javac, jar)')
+
+@depends('--with-java-bin-path')
+@imports(_from='os', _import='environ')
+def java_search_paths(path):
+    if path:
+        # Look for javac and jar in the specified path.
+        return path
+    # With no path specified, look for javac and jar in $JAVA_HOME (if set)
+    # and $PATH.
+    if 'JAVA_HOME' in environ:
+        return [os.path.join(environ['JAVA_HOME'], 'bin'),
+                environ.get('PATH', '')]
+    return [environ.get('PATH')]
+
+# Finds the given java tool, failing with a custom error message if we can't
+# find it.
+@template
+def check_java_tool(tool):
+    check = check_prog(tool.upper(), (tool,), paths=java_search_paths,
+                       allow_missing=True)
+
+    @depends(check)
+    def require_tool(result):
+        if result is None:
+            die("The program %s was not found.  Set $JAVA_HOME to your Java "
+                "SDK directory or use '--with-java-bin-path={java-bin-dir}'"
+                % tool)
+        return result
+
+    return require_tool
+
+check_java_tool('java')
+check_java_tool('javah')
+check_java_tool('jar')
+check_java_tool('jarsigner')
+check_java_tool('keytool')
+javac = check_java_tool('javac')
+
+@depends(javac)
+@checking('for javac version')
+@imports('subprocess')
+def javac_version(javac):
+    try:
+        output = subprocess.check_output([javac, '-version'],
+                                         stderr=subprocess.STDOUT).rstrip()
+        version = Version(output.split(' ')[-1])
+        if version < '1.7':
+            die('javac 1.7 or higher is required (found %s)' % version)
+        return version
+    except subprocess.CalledProcessError as e:
+        die('Failed to get javac version: %s', e.output)
--- a/build/moz.configure/old.configure
+++ b/build/moz.configure/old.configure
@@ -295,17 +295,16 @@ def old_configure_options(*options):
     '--with-doc-input-dirs',
     '--with-doc-output-dir',
     '--with-float-abi',
     '--with-fpu',
     '--with-google-api-keyfile',
     '--with-google-oauth-api-keyfile',
     '--with-intl-api',
     '--with-ios-sdk',
-    '--with-java-bin-path',
     '--with-jitreport-granularity',
     '--with-linux-headers',
     '--with-macbundlename-prefix',
     '--with-macos-private-frameworks',
     '--with-macos-sdk',
     '--with-mozilla-api-keyfile',
     '--with-nspr-cflags',
     '--with-nspr-exec-prefix',
--- a/build/moz.configure/util.configure
+++ b/build/moz.configure/util.configure
@@ -25,24 +25,35 @@ def is_absolute_or_relative(path):
         return True
     return os.sep in path
 
 
 @imports(_import='mozpack.path', _as='mozpath')
 def normsep(path):
     return mozpath.normsep(path)
 
-
+# Locates the given program using which, or returns the given path if it
+# exists.
+# The `paths` parameter may be passed to search the given paths instead of
+# $PATH.
 @imports(_from='which', _import='which')
 @imports(_from='which', _import='WhichError')
-def find_program(file):
+@imports('itertools')
+@imports(_from='os', _import='pathsep')
+def find_program(file, paths=None):
     if is_absolute_or_relative(file):
         return os.path.abspath(file) if os.path.isfile(file) else None
     try:
-        return normsep(which(file))
+        if paths:
+            if not isinstance(paths, (list, tuple)):
+                die("Paths provided to find_program must be a list of strings, "
+                    "not %r", paths)
+            paths = list(itertools.chain(
+                *(p.split(pathsep) for p in paths if p)))
+        return normsep(which(file, path=paths))
     except WhichError:
         return None
 
 
 def unique_list(l):
     result = []
     for i in l:
         if l not in result:
index 3f2ef8379e08899323018f367e705ae17979a09c..1e65b619d39e6c4488202b1fef68a72b82ef9323
GIT binary patch
literal 65536
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
index 6a9f39883387a120396cbdb881e1b87065ce2427..a45004df89fcb3daea9fcd76101d11a7d4eaf4d8
GIT binary patch
literal 176128
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%0DcAj{##!V0%f`l?4E19Q)Mrg;
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
z(0t$~$?^oln0M1J2Qv{XzM5J_6Jn;AblQqspI+nSf_TRFUy#EYK}TeX*Ks#zISSfs
zce&GFWl82>Vz&38&<q`v+E(hVp`%>U@;-AXC6`iJD*?@C&WyB38bA8?1EFjfm@diR
zsrTJwBOFt%Xt|(dQ-mVJs7F2H`ThUhLj|Q`e%(Ji9;O&M%4kHUm!?W867GhaP7lBh
zYHa2o7;T}^H}<@&f9F0XOUT)*vWyWejkXm<4aT6~(_nz=hYY@TP5}2A8vI{))dv6o
z00000000000000000000000000000000000000000000000000000000000000000
z00000000000000000000000000000000000000000000000000000000000000000
z00000000000000000000000000000000000000000000000000000000O0>NU?3pK
zU~tc{U~pdm00000004mhUjPRI1z`?`cx0x5f~O6a4u3)fMSuhaXU2uVFdi-a!Qxo@
ztD;U|7n|dRP<u~19}E-}A{b(<`<p+Kaa)}q7l-9HMW3Yj!NP<=y<Mw#*mY75L#G_=
zJT9RE66H($z)9?3XWMyLF~7k*^?8n!$f%L&Gtd>{D0>Fn+5w2}%XKp!I*Y1N$(!c7
zfPXM$&Ch~$HS52w=UQr}#V}ZSa+<<?6E)Wjc9geKW1@fW_&LGV!Ev7HP+x&fYkjKC
z<v!>+`3OQ*(CUY)^$b{N+NnY55G^O3zcxU9Ctt!za&UBb5<+K`*PZh5)FUj!me>;=
z>h)449r{_ikJ#8Z{l0-`(W`nng_D;V(!Gf36WVAF-=sXHyk1#mJ>y2e<SF&b$nn9*
z-BeD@)&Oxrb<(sM@=C;W4o2mYA7lpB5=psOBT-h&)$dk@GuL7acC99J^D`OJ$%Bm`
z<hmCI#ajIfy3aq{c4KRs4mH}$joE;^B-C7~DUZzz$JQ7g9Ga5z>_V3Cw{4)^C<dWp
z*OHMcE5j#jN3Xn6{<=j5ud%LWq1AYML{K$^o*$kx<dt}WjmNDJry6pBSK-o*v+Mx0
zfWX%8U)?v&$Fn~y+^I|(or^{UqTwN}i0QRg(#tUarO8idh24tT{O&;K#k$p&i<%n3
zP~)tg;E+rLRf?S;pk{;*$4V>tId_y`PtcA^u~dWj`31e+>%v8{Ugh7rVwGv-jiq$+
zt%f&_*;*R;ZuTx5&0N_>sjvs)G-W@&*DE2U?q(?=7>9y4v&Z#Qsr~C`&Yb`jUTQY=
zU;y4ZqGrQH7s>eWb<bNfgK8`!GVz;+(J!cX=Rm{4LG-&;biW;!yTjDZgw|7oql2Ib
zwp%-OwRPn&QRr{)H*(6_phdruf7@&E`LDI`L1S<PI`XxkN^qF{sOO1GmWO#9WFenx
z^GbB#ZwT!lG^^d;f+J&uvCGbdnUstXg}H?ih#N07e}kfs$`$g70IN4*$$|iBKS6-L
z?R=%n4Caj>4tU|pXO4sV!K59M&_h!842dPY7f&UT5UdNuqJ@^RrX5UP{L_Vp1Le1V
zC{Ir-pPUzGBK^}}rOuVS6z^n2ME3jJ%{|mVEys~uP$wmd7rY%U8&Wkk|8~77uOn2?
z9G`-vePY<`-Nmd2N)?BG5@Dw(%v)E>FjObBJepqn*o`E4(U&Peo?$#L5uGf)Ade>q
zU_XqMXfgNY<1@5*3E4k0pZ#K;vZ_!0-Sbc+=hd01Xw*|+O%*gGp8lgKAT8T)*1m5)
zTJ%H*h70FYT&?+=p&Y^?#EL;Np_8Dod?lo@fl!oc9Sc|9%;UXRZ&j|>p<D8AflF5I
z(k3R74W7X|7seYVDYx^#i;D@lavT}d;|;YEqv{0*1$2$o!d;r*yO4f;p6YZBb9WZV
zYIq{4f@59PfO3{Mv=>23uI2K)r4Ee_rL>g=MGQ92g?(&Vg?_k+!+M@xalcC&Ao+w(
z!uRNGF6eBXM+v<;-=Mp0)PAmGpv}9NRv3(~)|b{aEKKmxO>)sZ`}^N{lM^tv)zPe`
zGyL3%lE6EH;!o28FD|67Tir;;{gbS))_m@iad)q+$G0n9>q03y|JRaNQzhfn1kcSc
zo{>*b_xASe^roZF`1az8^H&6}J+Wl|540Bofq?C0x2BBX@^b7T7`y3TV@)>s;6tQi
ziai4@L`{cqw>s4Nh;$~sp!$vrMSAR8xhe-waai{lE6yI^e>|mpY8Av4X59&tQPrjQ
z;CntWM-bjKVj{#BrOAFD+N|;P%iLy(yOhn<lib#EX+7SqlUw=4bN_?P*%dNzcWou5
zO!Ab1J&4M9N}596M_c<KlaEf63XVA$Mh@aaP0X3vr(t{#rzgy&7@f!4N;&C<UJTe_
z#|Rp0d5mPkAakGC`f}1@yFK+M(F(Vr5r0)we`Ke!6hx<wn3Vy|Qv4dyhaa2w11G7V
z1xKuXi{XH@Ag!l(B^7qU%g0z_?I>;#Ec?xd`O~FSBk%+@=KHcr0XNr!?BfJ|OWywm
DDX5K2
--- a/build/pgo/server-locations.txt
+++ b/build/pgo/server-locations.txt
@@ -255,11 +255,12 @@ https://fail-handshake.example.com:443  
 # Hosts for sha1 console warning tests
 https://sha1ee.example.com:443                                    privileged,cert=sha1_end_entity
 https://sha256ee.example.com:443                                  privileged,cert=sha256_end_entity
 
 # Hosts for ssl3/rc4 console warning tests
 https://ssl3.example.com:443        privileged,ssl3
 https://rc4.example.com:443         privileged,rc4
 https://ssl3rc4.example.com:443     privileged,ssl3,rc4
+https://tls1.example.com:443        privileged,tls1
 
 # Hosts for youtube rewrite tests
 https://mochitest.youtube.com:443
--- a/devtools/client/framework/sidebar.js
+++ b/devtools/client/framework/sidebar.js
@@ -491,16 +491,17 @@ ToolSidebar.prototype = {
   },
 
   /**
    * Show the sidebar.
    */
   hide: function() {
     Services.prefs.setIntPref("devtools.toolsidebar-width." + this._uid, this._tabbox.width);
     this._tabbox.setAttribute("hidden", "true");
+    this._panelDoc.activeElement.blur();
 
     this.emit("hide");
   },
 
   /**
    * Return the window containing the tab content.
    */
   getWindowForTab: function(id) {
--- a/devtools/client/framework/test/browser_toolbox_sidebar.js
+++ b/devtools/client/framework/test/browser_toolbox_sidebar.js
@@ -113,17 +113,22 @@ function test() {
     is(label, 4, "Found the right amount of tabs.");
     is(panel.sidebar._tabbox.selectedPanel, panels[0], "First tab is selected");
     is(panel.sidebar.getCurrentTabID(), "tab1", "getCurrentTabID() is correct");
 
     panel.sidebar.once("tab1-unselected", function() {
       ok(true, "received 'unselected' event");
       panel.sidebar.once("tab2-selected", function() {
         ok(true, "received 'selected' event");
+        tabs[1].focus();
+        is(panel.sidebar._panelDoc.activeElement, tabs[1],
+          "Focus is set to second tab");
         panel.sidebar.hide();
+        isnot(panel.sidebar._panelDoc.activeElement, tabs[1],
+          "Focus is reset for sidebar");
         is(panel.sidebar._tabbox.getAttribute("hidden"), "true", "Sidebar hidden");
         is(panel.sidebar.getWindowForTab("tab1").location.href, tab1URL, "Window is accessible");
         testRemoval(panel);
       });
     });
 
     panel.sidebar.select("tab2");
   }
--- a/devtools/server/actors/animation.js
+++ b/devtools/server/actors/animation.js
@@ -443,17 +443,17 @@ var AnimationPlayerActor = ActorClass({
   }),
 
   /**
    * Get data about the keyframes of this animation player.
    * @return {Object} Returns a list of frames, each frame containing the list
    * animated properties as well as the frame's offset.
    */
   getFrames: method(function() {
-    return this.player.effect.getFrames();
+    return this.player.effect.getKeyframes();
   }, {
     request: {},
     response: {
       frames: RetVal("json")
     }
   }),
 
   /**
--- a/dom/animation/CSSPseudoElement.cpp
+++ b/dom/animation/CSSPseudoElement.cpp
@@ -60,23 +60,23 @@ CSSPseudoElement::GetAnimations(const An
 
   Element::GetAnimationsUnsorted(mParentElement, mPseudoType, aRetVal);
   aRetVal.Sort(AnimationPtrComparator<RefPtr<Animation>>());
 }
 
 already_AddRefed<Animation>
 CSSPseudoElement::Animate(
     JSContext* aContext,
-    JS::Handle<JSObject*> aFrames,
+    JS::Handle<JSObject*> aKeyframes,
     const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
     ErrorResult& aError)
 {
   Nullable<ElementOrCSSPseudoElement> target;
   target.SetValue().SetAsCSSPseudoElement() = this;
-  return Element::Animate(target, aContext, aFrames, aOptions, aError);
+  return Element::Animate(target, aContext, aKeyframes, aOptions, aError);
 }
 
 /* static */ already_AddRefed<CSSPseudoElement>
 CSSPseudoElement::GetCSSPseudoElement(Element* aElement,
                                       CSSPseudoElementType aType)
 {
   if (!aElement) {
     return nullptr;
--- a/dom/animation/CSSPseudoElement.h
+++ b/dom/animation/CSSPseudoElement.h
@@ -56,17 +56,17 @@ public:
     RefPtr<Element> retVal(mParentElement);
     return retVal.forget();
   }
 
   void GetAnimations(const AnimationFilter& filter,
                      nsTArray<RefPtr<Animation>>& aRetVal);
   already_AddRefed<Animation>
     Animate(JSContext* aContext,
-            JS::Handle<JSObject*> aFrames,
+            JS::Handle<JSObject*> aKeyframes,
             const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
             ErrorResult& aError);
 
   // Given an element:pseudoType pair, returns the CSSPseudoElement stored as a
   // property on |aElement|. If there is no CSSPseudoElement for the specified
   // pseudo-type on element, a new CSSPseudoElement will be created and stored
   // on the element.
   static already_AddRefed<CSSPseudoElement>
--- a/dom/animation/KeyframeEffect.cpp
+++ b/dom/animation/KeyframeEffect.cpp
@@ -417,58 +417,58 @@ KeyframesEqualIgnoringComputedOffsets(co
         a.mTimingFunction != b.mTimingFunction ||
         a.mPropertyValues != b.mPropertyValues) {
       return false;
     }
   }
   return true;
 }
 
-// https://w3c.github.io/web-animations/#dom-keyframeeffect-setframes
+// https://w3c.github.io/web-animations/#dom-keyframeeffect-setkeyframes
 void
-KeyframeEffectReadOnly::SetFrames(JSContext* aContext,
-                                  JS::Handle<JSObject*> aFrames,
-                                  ErrorResult& aRv)
+KeyframeEffectReadOnly::SetKeyframes(JSContext* aContext,
+                                     JS::Handle<JSObject*> aKeyframes,
+                                     ErrorResult& aRv)
 {
   nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aContext);
   if (!doc) {
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   nsTArray<Keyframe> keyframes =
-    KeyframeUtils::GetKeyframesFromObject(aContext, aFrames, aRv);
+    KeyframeUtils::GetKeyframesFromObject(aContext, aKeyframes, aRv);
   if (aRv.Failed()) {
     return;
   }
 
   RefPtr<nsStyleContext> styleContext;
   nsIPresShell* shell = doc->GetShell();
   if (shell && mTarget) {
     nsIAtom* pseudo =
       mTarget->mPseudoType < CSSPseudoElementType::Count ?
       nsCSSPseudoElements::GetPseudoAtom(mTarget->mPseudoType) : nullptr;
     styleContext =
       nsComputedDOMStyle::GetStyleContextForElement(mTarget->mElement,
                                                     pseudo, shell);
   }
 
-  SetFrames(Move(keyframes), styleContext);
+  SetKeyframes(Move(keyframes), styleContext);
 }
 
 void
-KeyframeEffectReadOnly::SetFrames(nsTArray<Keyframe>&& aFrames,
+KeyframeEffectReadOnly::SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
                                   nsStyleContext* aStyleContext)
 {
-  if (KeyframesEqualIgnoringComputedOffsets(aFrames, mFrames)) {
+  if (KeyframesEqualIgnoringComputedOffsets(aKeyframes, mKeyframes)) {
     return;
   }
 
-  mFrames = Move(aFrames);
-  KeyframeUtils::ApplyDistributeSpacing(mFrames);
+  mKeyframes = Move(aKeyframes);
+  KeyframeUtils::ApplyDistributeSpacing(mKeyframes);
 
   if (mAnimation && mAnimation->IsRelevant()) {
     nsNodeUtils::AnimationChanged(mAnimation);
   }
 
   if (aStyleContext) {
     UpdateProperties(aStyleContext);
   }
@@ -509,17 +509,17 @@ KeyframeEffectReadOnly::UpdateProperties
   MOZ_ASSERT(aStyleContext);
 
   nsTArray<AnimationProperty> properties;
   if (mTarget) {
     properties =
       KeyframeUtils::GetAnimationPropertiesFromKeyframes(aStyleContext,
                                                          mTarget->mElement,
                                                          mTarget->mPseudoType,
-                                                         mFrames);
+                                                         mKeyframes);
   }
 
   if (mProperties == properties) {
     return;
   }
 
   // Preserve the state of mWinsInCascade and mIsRunningOnCompositor flags.
   nsCSSPropertySet winningInCascadeProperties;
@@ -717,17 +717,17 @@ ConvertTarget(const Nullable<ElementOrCS
   return result;
 }
 
 template <class KeyframeEffectType, class OptionsType>
 /* static */ already_AddRefed<KeyframeEffectType>
 KeyframeEffectReadOnly::ConstructKeyframeEffect(
     const GlobalObject& aGlobal,
     const Nullable<ElementOrCSSPseudoElement>& aTarget,
-    JS::Handle<JSObject*> aFrames,
+    JS::Handle<JSObject*> aKeyframes,
     const OptionsType& aOptions,
     ErrorResult& aRv)
 {
   nsIDocument* doc = AnimationUtils::GetCurrentRealmDocument(aGlobal.Context());
   if (!doc) {
     aRv.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
@@ -737,17 +737,17 @@ KeyframeEffectReadOnly::ConstructKeyfram
   if (aRv.Failed()) {
     return nullptr;
   }
 
   Maybe<OwningAnimationTarget> target = ConvertTarget(aTarget);
   RefPtr<KeyframeEffectType> effect =
     new KeyframeEffectType(doc, target, timingParams);
 
-  effect->SetFrames(aGlobal.Context(), aFrames, aRv);
+  effect->SetKeyframes(aGlobal.Context(), aKeyframes, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
   return effect.forget();
 }
 
 void
@@ -837,22 +837,22 @@ DumpAnimationProperties(nsTArray<Animati
   }
 }
 #endif
 
 /* static */ already_AddRefed<KeyframeEffectReadOnly>
 KeyframeEffectReadOnly::Constructor(
     const GlobalObject& aGlobal,
     const Nullable<ElementOrCSSPseudoElement>& aTarget,
-    JS::Handle<JSObject*> aFrames,
+    JS::Handle<JSObject*> aKeyframes,
     const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
     ErrorResult& aRv)
 {
   return ConstructKeyframeEffect<KeyframeEffectReadOnly>(aGlobal, aTarget,
-                                                         aFrames, aOptions,
+                                                         aKeyframes, aOptions,
                                                          aRv);
 }
 
 void
 KeyframeEffectReadOnly::GetTarget(
     Nullable<OwningElementOrCSSPseudoElement>& aRv) const
 {
   if (!mTarget) {
@@ -961,29 +961,29 @@ KeyframeEffectReadOnly::GetProperties(
       }
     }
 
     aProperties.AppendElement(propertyDetails);
   }
 }
 
 void
-KeyframeEffectReadOnly::GetFrames(JSContext*& aCx,
-                                  nsTArray<JSObject*>& aResult,
-                                  ErrorResult& aRv)
+KeyframeEffectReadOnly::GetKeyframes(JSContext*& aCx,
+                                     nsTArray<JSObject*>& aResult,
+                                     ErrorResult& aRv)
 {
   MOZ_ASSERT(aResult.IsEmpty());
   MOZ_ASSERT(!aRv.Failed());
 
-  if (!aResult.SetCapacity(mFrames.Length(), mozilla::fallible)) {
+  if (!aResult.SetCapacity(mKeyframes.Length(), mozilla::fallible)) {
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     return;
   }
 
-  for (const Keyframe& keyframe : mFrames) {
+  for (const Keyframe& keyframe : mKeyframes) {
     // Set up a dictionary object for the explicit members
     BaseComputedKeyframe keyframeDict;
     if (keyframe.mOffset) {
       keyframeDict.mOffset.SetValue(keyframe.mOffset.value());
     }
     keyframeDict.mComputedOffset.Construct(keyframe.mComputedOffset);
     if (keyframe.mTimingFunction) {
       keyframeDict.mEasing.Truncate();
@@ -1334,33 +1334,33 @@ KeyframeEffect::WrapObject(JSContext* aC
 {
   return KeyframeEffectBinding::Wrap(aCx, this, aGivenProto);
 }
 
 /* static */ already_AddRefed<KeyframeEffect>
 KeyframeEffect::Constructor(
     const GlobalObject& aGlobal,
     const Nullable<ElementOrCSSPseudoElement>& aTarget,
-    JS::Handle<JSObject*> aFrames,
+    JS::Handle<JSObject*> aKeyframes,
     const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
     ErrorResult& aRv)
 {
-  return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aFrames,
+  return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aKeyframes,
                                                  aOptions, aRv);
 }
 
 /* static */ already_AddRefed<KeyframeEffect>
 KeyframeEffect::Constructor(
     const GlobalObject& aGlobal,
     const Nullable<ElementOrCSSPseudoElement>& aTarget,
-    JS::Handle<JSObject*> aFrames,
+    JS::Handle<JSObject*> aKeyframes,
     const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
     ErrorResult& aRv)
 {
-  return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aFrames,
+  return ConstructKeyframeEffect<KeyframeEffect>(aGlobal, aTarget, aKeyframes,
                                                  aOptions, aRv);
 }
 
 void
 KeyframeEffect::NotifySpecifiedTimingUpdated()
 {
   // Use the same document for a pseudo element and its parent element.
   // Use nullptr if we don't have mTarget, so disable the mutation batch.
--- a/dom/animation/KeyframeEffect.h
+++ b/dom/animation/KeyframeEffect.h
@@ -69,17 +69,18 @@ struct PropertyValuePair
            mValue == aOther.mValue;
   }
 };
 
 /**
  * A single keyframe.
  *
  * This is the canonical form in which keyframe effects are stored and
- * corresponds closely to the type of objects returned via the getFrames() API.
+ * corresponds closely to the type of objects returned via the getKeyframes()
+ * API.
  *
  * Before computing an output animation value, however, we flatten these frames
  * down to a series of per-property value arrays where we also resolve any
  * overlapping shorthands/longhands, convert specified CSS values to computed
  * values, etc.
  *
  * When the target element or style context changes, however, we rebuild these
  * per-property arrays from the original list of keyframes objects. As a result,
@@ -206,32 +207,32 @@ public:
   {
     return nullptr;
   }
 
   // KeyframeEffectReadOnly interface
   static already_AddRefed<KeyframeEffectReadOnly>
   Constructor(const GlobalObject& aGlobal,
               const Nullable<ElementOrCSSPseudoElement>& aTarget,
-              JS::Handle<JSObject*> aFrames,
+              JS::Handle<JSObject*> aKeyframes,
               const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
               ErrorResult& aRv);
 
   void GetTarget(Nullable<OwningElementOrCSSPseudoElement>& aRv) const;
   Maybe<NonOwningAnimationTarget> GetTarget() const
   {
     Maybe<NonOwningAnimationTarget> result;
     if (mTarget) {
       result.emplace(*mTarget);
     }
     return result;
   }
-  void GetFrames(JSContext*& aCx,
-                 nsTArray<JSObject*>& aResult,
-                 ErrorResult& aRv);
+  void GetKeyframes(JSContext*& aCx,
+                    nsTArray<JSObject*>& aResult,
+                    ErrorResult& aRv);
   void GetProperties(nsTArray<AnimationPropertyDetails>& aProperties,
                      ErrorResult& aRv) const;
 
   IterationCompositeOperation IterationComposite() const;
   CompositeOperation Composite() const;
   void GetSpacing(nsString& aRetVal) const {
     aRetVal.AssignLiteral("distribute");
   }
@@ -275,35 +276,36 @@ public:
 
   bool IsInPlay() const;
   bool IsCurrent() const;
   bool IsInEffect() const;
 
   void SetAnimation(Animation* aAnimation);
   Animation* GetAnimation() const { return mAnimation; }
 
-  void SetFrames(JSContext* aContext, JS::Handle<JSObject*> aFrames,
-                 ErrorResult& aRv);
-  void SetFrames(nsTArray<Keyframe>&& aFrames, nsStyleContext* aStyleContext);
+  void SetKeyframes(JSContext* aContext, JS::Handle<JSObject*> aKeyframes,
+                    ErrorResult& aRv);
+  void SetKeyframes(nsTArray<Keyframe>&& aKeyframes,
+                    nsStyleContext* aStyleContext);
   const AnimationProperty*
   GetAnimationOfProperty(nsCSSProperty aProperty) const;
   bool HasAnimationOfProperty(nsCSSProperty aProperty) const {
     return GetAnimationOfProperty(aProperty) != nullptr;
   }
   bool HasAnimationOfProperties(const nsCSSProperty* aProperties,
                                 size_t aPropertyCount) const;
   const InfallibleTArray<AnimationProperty>& Properties() const {
     return mProperties;
   }
   InfallibleTArray<AnimationProperty>& Properties() {
     return mProperties;
   }
 
-  // Update |mProperties| by recalculating from |mFrames| using |aStyleContext|
-  // to resolve specified values.
+  // Update |mProperties| by recalculating from |mKeyframes| using
+  // |aStyleContext| to resolve specified values.
   void UpdateProperties(nsStyleContext* aStyleContext);
 
   // Updates |aStyleRule| with the animation values produced by this
   // AnimationEffect for the current time except any properties already
   // contained in |aSetProperties|.
   // Any updated properties are added to |aSetProperties|.
   void ComposeStyle(RefPtr<AnimValuesStyleRule>& aStyleRule,
                     nsCSSPropertySet& aSetProperties);
@@ -341,17 +343,17 @@ protected:
                          AnimationEffectTimingReadOnly* aTiming);
 
   virtual ~KeyframeEffectReadOnly();
 
   template<class KeyframeEffectType, class OptionsType>
   static already_AddRefed<KeyframeEffectType>
   ConstructKeyframeEffect(const GlobalObject& aGlobal,
                           const Nullable<ElementOrCSSPseudoElement>& aTarget,
-                          JS::Handle<JSObject*> aFrames,
+                          JS::Handle<JSObject*> aKeyframes,
                           const OptionsType& aOptions,
                           ErrorResult& aRv);
 
   void ResetIsRunningOnCompositor();
   void ResetWinsInCascade();
 
   // This effect is registered with its target element so long as:
   //
@@ -370,19 +372,19 @@ protected:
   void RequestRestyle(EffectCompositor::RestyleType aRestyleType);
 
   Maybe<OwningAnimationTarget> mTarget;
   RefPtr<Animation> mAnimation;
 
   RefPtr<AnimationEffectTimingReadOnly> mTiming;
 
   // The specified keyframes.
-  nsTArray<Keyframe>          mFrames;
+  nsTArray<Keyframe>          mKeyframes;
 
-  // A set of per-property value arrays, derived from |mFrames|.
+  // A set of per-property value arrays, derived from |mKeyframes|.
   nsTArray<AnimationProperty> mProperties;
 
   // The computed progress last time we composed the style rule. This is
   // used to detect when the progress is not changing (e.g. due to a step
   // timing function) so we can avoid unnecessary style updates.
   Nullable<double> mProgressOnLastCompose;
 
   // We need to track when we go to or from being "in effect" since
@@ -414,27 +416,27 @@ public:
                  const TimingParams& aTiming);
 
   JSObject* WrapObject(JSContext* aCx,
                        JS::Handle<JSObject*> aGivenProto) override;
 
   static already_AddRefed<KeyframeEffect>
   Constructor(const GlobalObject& aGlobal,
               const Nullable<ElementOrCSSPseudoElement>& aTarget,
-              JS::Handle<JSObject*> aFrames,
+              JS::Handle<JSObject*> aKeyframes,
               const UnrestrictedDoubleOrKeyframeEffectOptions& aOptions,
               ErrorResult& aRv);
 
   // Variant of Constructor that accepts a KeyframeAnimationOptions object
   // for use with for Animatable.animate.
   // Not exposed to content.
   static already_AddRefed<KeyframeEffect>
   Constructor(const GlobalObject& aGlobal,
               const Nullable<ElementOrCSSPseudoElement>& aTarget,
-              JS::Handle<JSObject*> aFrames,
+              JS::Handle<JSObject*> aKeyframes,
               const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
               ErrorResult& aRv);
 
   void NotifySpecifiedTimingUpdated();
 
   // This method calls MaybeUpdateProperties which is not safe to use when
   // we are in the middle of updating style. If we need to use this when
   // updating style, we should pass the nsStyleContext into this method and use
--- a/dom/animation/KeyframeUtils.cpp
+++ b/dom/animation/KeyframeUtils.cpp
@@ -298,16 +298,40 @@ public:
   }
 
   static bool LessThan(const Keyframe& aLhs, const Keyframe& aRhs)
   {
     return aLhs.mComputedOffset < aRhs.mComputedOffset;
   }
 };
 
+// ------------------------------------------------------------------
+//
+// Inlined helper methods
+//
+// ------------------------------------------------------------------
+
+inline bool
+IsInvalidValuePair(const PropertyValuePair& aPair)
+{
+  // There are three types of values we store as token streams:
+  //
+  // * Shorthand values (where we manually extract the token stream's string
+  //   value) and pass that along to various parsing methods
+  // * Longhand values with variable references
+  // * Invalid values
+  //
+  // We can distinguish between the last two cases because for invalid values
+  // we leave the token stream's mPropertyID as eCSSProperty_UNKNOWN.
+  return !nsCSSProps::IsShorthand(aPair.mProperty) &&
+         aPair.mValue.GetUnit() == eCSSUnit_TokenStream &&
+         aPair.mValue.GetTokenStreamValue()->mPropertyID
+           == eCSSProperty_UNKNOWN;
+}
+
 
 // ------------------------------------------------------------------
 //
 // Internal helper method declarations
 //
 // ------------------------------------------------------------------
 
 static void
@@ -471,20 +495,17 @@ KeyframeUtils::GetAnimationPropertiesFro
   MOZ_ASSERT(aElement);
 
   nsTArray<KeyframeValueEntry> entries;
 
   for (const Keyframe& frame : aFrames) {
     nsCSSPropertySet propertiesOnThisKeyframe;
     for (const PropertyValuePair& pair :
            PropertyPriorityIterator(frame.mPropertyValues)) {
-      // We currently store invalid longhand values on keyframes as a token
-      // stream so if we see one of them, just keep moving.
-      if (!nsCSSProps::IsShorthand(pair.mProperty) &&
-          pair.mValue.GetUnit() == eCSSUnit_TokenStream) {
+      if (IsInvalidValuePair(pair)) {
         continue;
       }
 
       // Expand each value into the set of longhands and produce
       // a KeyframeValueEntry for each value.
       nsTArray<PropertyStyleAnimationValuePair> values;
 
       // For shorthands, we store the string as a token stream so we need to
@@ -814,16 +835,25 @@ MakePropertyValuePair(nsCSSProperty aPro
                                   value);
   }
 
   if (value.GetUnit() == eCSSUnit_Null) {
     // Either we have a shorthand, or we failed to parse a longhand.
     // In either case, store the string value as a token stream.
     nsCSSValueTokenStream* tokenStream = new nsCSSValueTokenStream;
     tokenStream->mTokenStream = aStringValue;
+
+    // We are about to convert a null value to a token stream value but
+    // by leaving the mPropertyID as unknown, we will be able to
+    // distinguish between invalid values and valid token stream values
+    // (e.g. values with variable references).
+    MOZ_ASSERT(tokenStream->mPropertyID == eCSSProperty_UNKNOWN,
+               "The property of a token stream should be initialized"
+               " to unknown");
+
     // By leaving mShorthandPropertyID as unknown, we ensure that when
     // we call nsCSSValue::AppendToString we get back the string stored
     // in mTokenStream.
     MOZ_ASSERT(tokenStream->mShorthandPropertyID == eCSSProperty_UNKNOWN,
                "The shorthand property of a token stream should be initialized"
                " to unknown");
     value.SetTokenStreamValue(tokenStream);
   }
@@ -1097,31 +1127,32 @@ RequiresAdditiveAnimation(const nsTArray
     double computedOffset = i == len - 1
                             ? 1.0
                             : i == 0 ? 0.0 : 0.5;
     double offsetToUse = frame.mOffset
                          ? frame.mOffset.value()
                          : computedOffset;
 
     for (const PropertyValuePair& pair : frame.mPropertyValues) {
+      if (IsInvalidValuePair(pair)) {
+        continue;
+      }
+
       if (nsCSSProps::IsShorthand(pair.mProperty)) {
         nsCSSValueTokenStream* tokenStream = pair.mValue.GetTokenStreamValue();
         nsCSSParser parser(aDocument->CSSLoader());
         if (!parser.IsValueValidForProperty(pair.mProperty,
                                             tokenStream->mTokenStream)) {
           continue;
         }
         CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(
             prop, pair.mProperty, CSSEnabledState::eForAllContent) {
           addToPropertySets(*prop, offsetToUse);
         }
       } else {
-        if (pair.mValue.GetUnit() == eCSSUnit_TokenStream) {
-          continue;
-        }
         addToPropertySets(pair.mProperty, offsetToUse);
       }
     }
   }
 
   return !propertiesWithFromValue.Equals(properties) ||
          !propertiesWithToValue.Equals(properties);
 }
--- a/dom/animation/test/chrome/test_animate_xrays.html
+++ b/dom/animation/test/chrome/test_animate_xrays.html
@@ -17,15 +17,15 @@
 var win = document.getElementById('iframe').contentWindow;
 
 async_test(function(t) {
   window.addEventListener('load', t.step_func(function() {
     var target = win.document.getElementById('target');
     var anim = target.animate({ opacity: [ 0, 1 ] }, 100 * MS_PER_SEC);
     // In the x-ray case, the frames object will be given an opaque wrapper
     // so it won't be possible to fetch any frames from it.
-    assert_equals(anim.effect.getFrames().length, 0);
+    assert_equals(anim.effect.getKeyframes().length, 0);
     t.done();
   }));
 }, 'Calling animate() across x-rays');
 
 </script>
 </body>
--- a/dom/animation/test/chrome/test_animation_properties.html
+++ b/dom/animation/test/chrome/test_animation_properties.html
@@ -7,16 +7,21 @@
 <script type="application/javascript" src="../testharnessreport.js"></script>
 <script type="application/javascript" src="../testcommon.js"></script>
 </head>
 <body>
 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=1254419"
   target="_blank">Mozilla Bug 1254419</a>
 <div id="log"></div>
 <style>
+
+:root {
+  --var-100px: 100px;
+  --var-100px-200px: 100px 200px;
+}
 div {
   font-size: 10px; /* For calculating em-based units */
 }
 </style>
 <script>
 'use strict';
 
 function assert_properties_equal(actual, expected) {
@@ -440,17 +445,17 @@ var gTests = [
                             value(1, '3px', 'replace') ] },
                 { property: 'border-right-width',
                   values: [ value(0, '2px', 'replace', 'linear'),
                             value(1, '3px', 'replace') ] },
                 { property: 'border-top-width',
                   values: [ value(0, '2px', 'replace', 'linear'),
                             value(1, '3px', 'replace') ] } ]
   },
-  { desc:     'a keyframe sequence where greater shorthand precedes' +
+  { desc:     'a keyframe sequence where greater shorthand precedes'
               + ' lesser shorthand',
     frames:   [ { offset: 0, border: '2px dotted rgb(4, 5, 6)',
                              borderLeft: '1px solid rgb(1, 2, 3)' },
                 { offset: 1, border: '3px dashed rgb(7, 8, 9)' } ],
     expected: [ { property: 'border-bottom-color',
                   values: [ value(0, 'rgb(4, 5, 6)', 'replace', 'linear'),
                             value(1, 'rgb(7, 8, 9)', 'replace') ] },
                 { property: 'border-left-color',
@@ -482,17 +487,57 @@ var gTests = [
   //
   // ---------------------------------------------------------------------
 
   { desc:     'em units are resolved to px values',
     frames:   { left: ['10em', '20em'] },
     expected: [ { property: 'left',
                   values: [ value(0, '100px', 'replace', 'linear'),
                             value(1, '200px', 'replace') ] } ]
-  }
+  },
+  { desc:     'calc() expressions are resolved to the equivalent units',
+    frames:   { left: ['calc(10em + 10px)', 'calc(10em + 10%)'] },
+    expected: [ { property: 'left',
+                  values: [ value(0, 'calc(110px)', 'replace', 'linear'),
+                            value(1, 'calc(100px + 10%)', 'replace') ] } ]
+  },
+
+  // ---------------------------------------------------------------------
+  //
+  // Tests for CSS variable handling conversion
+  //
+  // ---------------------------------------------------------------------
+  { desc:     'CSS variables are resolved to their corresponding values',
+    frames:   { left: ['10px', 'var(--var-100px)'] },
+    expected: [ { property: 'left',
+                  values: [ value(0, '10px', 'replace', 'linear'),
+                            value(1, '100px', 'replace') ] } ]
+  },
+  { desc:     'CSS variables in calc() expressions are resolved',
+    frames:   { left: ['10px', 'calc(var(--var-100px) / 2 - 10%)'] },
+    expected: [ { property: 'left',
+                  values: [ value(0, '10px', 'replace', 'linear'),
+                            value(1, 'calc(50px + -10%)', 'replace') ] } ]
+  },
+  { desc:     'CSS variables in shorthands are resolved to their corresponding'
+              + ' values',
+    frames:   { margin: ['10px', 'var(--var-100px-200px)'] },
+    expected: [ { property: 'margin-top',
+                  values: [ value(0, '10px', 'replace', 'linear'),
+                            value(1, '100px', 'replace') ] },
+                { property: 'margin-right',
+                  values: [ value(0, '10px', 'replace', 'linear'),
+                            value(1, '200px', 'replace') ] },
+                { property: 'margin-bottom',
+                  values: [ value(0, '10px', 'replace', 'linear'),
+                            value(1, '100px', 'replace') ] },
+                { property: 'margin-left',
+                  values: [ value(0, '10px', 'replace', 'linear'),
+                            value(1, '200px', 'replace') ] } ]
+  },
 ];
 
 gTests.forEach(function(subtest) {
   test(function(t) {
     var div = addDiv(t);
     var animation = div.animate(subtest.frames, 100 * MS_PER_SEC);
     assert_properties_equal(animation.effect.getProperties(),
                             subtest.expected);
--- a/dom/animation/test/chrome/test_restyles.html
+++ b/dom/animation/test/chrome/test_restyles.html
@@ -447,27 +447,27 @@ waitForAllPaints(function() {
     var animation = div.animate({ }, 100 * MS_PER_SEC);
 
     yield animation.ready;
     var markers = yield observeStyling(5);
 
     is(markers.length, 0,
        'Animations with no keyframes should not cause restyles');
 
-    animation.effect.setFrames({ backgroundColor: ['red', 'blue'] });
+    animation.effect.setKeyframes({ backgroundColor: ['red', 'blue'] });
     markers = yield observeStyling(5);
 
     // There are 5 eRestyle_CSSAnimations and 1 eRestyle_CSSTransitions.
     // 1 eRestyle_CSSTransitions comes from
     // EffectCompositor::UpdateCascadeResults.
     ok(markers.length == 6,
        'Setting valid keyframes should cause regular animation restyles to ' +
        'occur');
 
-    animation.effect.setFrames({ });
+    animation.effect.setKeyframes({ });
     markers = yield observeStyling(5);
 
     is(markers.length, 1,
        'Setting an empty set of keyframes should trigger a single restyle ' +
        'to remove the previous animated style');
 
     yield ensureElementRemoval(div);
   });
rename from dom/animation/test/css-animations/file_keyframeeffect-getframes.html
rename to dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
--- a/dom/animation/test/css-animations/file_keyframeeffect-getframes.html
+++ b/dom/animation/test/css-animations/file_keyframeeffect-getkeyframes.html
@@ -123,23 +123,33 @@
 
 @keyframes anim-text-shadow {
   to { text-shadow: none; }
 }
 
 @keyframes anim-background-size {
   to { background-size: 50%, 6px, contain }
 }
+
+:root {
+  --var-100px: 100px;
+}
+@keyframes anim-variables {
+  to { transform: translate(var(--var-100px), 0) }
+}
+@keyframes anim-variables-shorthand {
+  to { margin: var(--var-100px) }
+}
 </style>
 <body>
 <script>
 "use strict";
 
-function getFrames(e) {
-  return e.getAnimations()[0].effect.getFrames();
+function getKeyframes(e) {
+  return e.getAnimations()[0].effect.getKeyframes();
 }
 
 function assert_frames_equal(a, b, name) {
   assert_equals(Object.keys(a).sort().toString(),
                 Object.keys(b).sort().toString(),
                 "properties on " + name);
   for (var p in a) {
     if (p === 'offset' || p === 'computedOffset') {
@@ -148,17 +158,17 @@ function assert_frames_equal(a, b, name)
     } else {
       assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
     }
   }
 }
 
 // animation-timing-function values to test with, where the value
 // is exactly the same as its serialization, sorted by the order
-// getFrames() will group frames with the same easing function
+// getKeyframes() will group frames with the same easing function
 // together (by nsTimingFunction::Compare).
 const kTimingFunctionValues = [
   "ease",
   "linear",
   "ease-in",
   "ease-out",
   "ease-in-out",
   "step-start",
@@ -172,319 +182,324 @@ const kTimingFunctionValues = [
   "cubic-bezier(0, 0, 1, 1)",
   "cubic-bezier(0, 0.25, 0.75, 1)",
 ];
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-empty 100s';
-  assert_equals(getFrames(div).length, 0,
+  assert_equals(getKeyframes(div).length, 0,
                 "number of frames with empty @keyframes");
 
   div.style.animation = 'anim-empty-frames 100s';
-  assert_equals(getFrames(div).length, 0,
+  assert_equals(getKeyframes(div).length, 0,
                 "number of frames when @keyframes has empty keyframes");
 
   div.style.animation = 'anim-only-timing 100s';
-  assert_equals(getFrames(div).length, 0,
+  assert_equals(getKeyframes(div).length, 0,
                 "number of frames when @keyframes only has keyframes with " +
                 "animation-timing-function");
 
   div.style.animation = 'anim-only-non-animatable 100s';
-  assert_equals(getFrames(div).length, 0,
+  assert_equals(getKeyframes(div).length, 0,
                 "number of frames when @keyframes only has frames with " +
                 "non-animatable properties");
-}, 'KeyframeEffectReadOnly.getFrames() returns no frames for various kinds ' +
-   'of empty enimations');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns no frames for various kinds'
+   + ' of empty enimations');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-simple 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", color: "black" },
-    { offset: 1, computedOffset: 1, easing: "ease", color: "white" },
+    { offset: 0, computedOffset: 0, easing: "ease",
+      color: "rgb(0, 0, 0)" },
+    { offset: 1, computedOffset: 1, easing: "ease",
+      color: "rgb(255, 255, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
-   'animation');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple'
+   + 'animation');
 
 test(function(t) {
   kTimingFunctionValues.forEach(function(easing) {
     var div = addDiv(t);
 
     div.style.animation = 'anim-simple-three 100s ' + easing;
-    var frames = getFrames(div);
+    var frames = getKeyframes(div);
 
     assert_equals(frames.length, 3, "number of frames");
 
     for (var i = 0; i < frames.length; i++) {
       assert_equals(frames[i].easing, easing,
                     "value for 'easing' on ComputedKeyframe #" + i);
     }
   });
-}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
-   'values, when the easing comes from animation-timing-function on the ' +
-   'element');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns frames with expected easing'
+   + ' values, when the easing comes from animation-timing-function on the'
+   + ' element');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-simple-timing 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 3, "number of frames");
   assert_equals(frames[0].easing, "linear",
                 "value of 'easing' on ComputedKeyframe #0");
   assert_equals(frames[1].easing, "ease-in-out",
                 "value of 'easing' on ComputedKeyframe #1");
   assert_equals(frames[2].easing, "step-end",
                 "value of 'easing' on ComputedKeyframe #2");
-}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
-   'values, when the easing is specified on each keyframe');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns frames with expected easing'
+   + ' values, when the easing is specified on each keyframe');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-simple-timing-some 100s step-start';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 3, "number of frames");
   assert_equals(frames[0].easing, "linear",
                 "value of 'easing' on ComputedKeyframe #0");
   assert_equals(frames[1].easing, "step-start",
                 "value of 'easing' on ComputedKeyframe #1");
   assert_equals(frames[2].easing, "step-start",
                 "value of 'easing' on ComputedKeyframe #2");
-}, 'KeyframeEffectReadOnly.getFrames() returns frames with expected easing ' +
-   'values, when the easing is specified on some keyframes');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns frames with expected easing'
+   + ' values, when the easing is specified on some keyframes');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-simple-shorthand 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       marginBottom: "8px", marginLeft: "8px",
       marginRight: "8px", marginTop: "8px" },
     { offset: 1, computedOffset: 1, easing: "ease",
       marginBottom: "16px", marginLeft: "16px",
       marginRight: "16px", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
-   'animation that specifies a single shorthand property');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple'
+   + ' animation that specifies a single shorthand property');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-omit-to 100s';
   div.style.color = 'white';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
-    { offset: 0, computedOffset: 0, easing: "ease", color: "blue" },
+    { offset: 0, computedOffset: 0, easing: "ease",
+      color: "rgb(0, 0, 255)" },
     { offset: 1, computedOffset: 1, easing: "ease",
       color: "rgb(255, 255, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with a 0% keyframe and no 100% keyframe');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-omit-from 100s';
   div.style.color = 'white';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       color: "rgb(255, 255, 255)" },
-    { offset: 1, computedOffset: 1, easing: "ease", color: "blue" },
+    { offset: 1, computedOffset: 1, easing: "ease",
+      color: "rgb(0, 0, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with a 100% keyframe and no 0% keyframe');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-omit-from-to 100s';
   div.style.color = 'white';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 3, "number of frames");
 
   var expected = [
     { offset: 0,   computedOffset: 0,   easing: "ease",
       color: "rgb(255, 255, 255)" },
-    { offset: 0.5, computedOffset: 0.5, easing: "ease", color: "blue" },
+    { offset: 0.5, computedOffset: 0.5, easing: "ease",
+      color: "rgb(0, 0, 255)" },
     { offset: 1,   computedOffset: 1,   easing: "ease",
       color: "rgb(255, 255, 255)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with no 0% or 100% keyframe but with a 50% keyframe');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-partially-omit-to 100s';
   div.style.marginTop = '250px';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       marginTop: '50px', marginBottom: '100px' },
     { offset: 1, computedOffset: 1, easing: "ease",
       marginTop: '250px', marginBottom: '200px' },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with a partially complete 100% keyframe (because the ' +
    '!important rule is ignored)');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-different-props 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 4, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
-      color: "black", marginTop: "8px" },
+      color: "rgb(0, 0, 0)", marginTop: "8px" },
     { offset: 0.25, computedOffset: 0.25, easing: "ease",
-      color: "blue" },
+      color: "rgb(0, 0, 255)" },
     { offset: 0.75, computedOffset: 0.75, easing: "ease",
       marginTop: "12px" },
     { offset: 1, computedOffset: 1, easing: "ease",
-      color: "white", marginTop: "16px" },
+      color: "rgb(255, 255, 255)", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with different properties on different keyframes, all ' +
    'with the same easing function');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-different-props-and-easing 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 4, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "linear",
-      color: "black", marginTop: "8px" },
+      color: "rgb(0, 0, 0)", marginTop: "8px" },
     { offset: 0.25, computedOffset: 0.25, easing: "step-end",
-      color: "blue" },
+      color: "rgb(0, 0, 255)" },
     { offset: 0.75, computedOffset: 0.75, easing: "ease-in",
       marginTop: "12px" },
     { offset: 1, computedOffset: 1, easing: "ease",
-      color: "white", marginTop: "16px" },
+      color: "rgb(255, 255, 255)", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with different properties on different keyframes, with ' +
    'a different easing function on each');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-merge-offset 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
-      color: "black", marginTop: "8px" },
+      color: "rgb(0, 0, 0)", marginTop: "8px" },
     { offset: 1, computedOffset: 1, easing: "ease",
-      color: "white", marginTop: "16px" },
+      color: "rgb(255, 255, 255)", marginTop: "16px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with multiple keyframes for the same time, and all with ' +
    'the same easing function');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-merge-offset-and-easing 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 3, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "step-end",
-      color: "black", fontSize: "16px" },
+      color: "rgb(0, 0, 0)", fontSize: "16px" },
     { offset: 0, computedOffset: 0, easing: "linear",
       marginTop: "8px", paddingLeft: "2px" },
     { offset: 1, computedOffset: 1, easing: "ease",
-      color: "white", fontSize: "32px", marginTop: "16px",
+      color: "rgb(255, 255, 255)", fontSize: "32px", marginTop: "16px",
       paddingLeft: "4px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with multiple keyframes for the same time and with ' +
    'different easing functions');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-no-merge-equiv-easing 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 5, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "steps(1, end)",
       marginTop: "0px" },
     { offset: 0, computedOffset: 0, easing: "step-end",
       marginRight: "0px" },
@@ -494,25 +509,25 @@ test(function(t) {
       marginTop: "10px", marginRight: "10px", marginBottom: "10px" },
     { offset: 1, computedOffset: 1, easing: "ease",
       marginTop: "20px", marginRight: "20px", marginBottom: "20px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for an ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for an ' +
    'animation with multiple keyframes for the same time and with ' +
    'different but equivalent easing functions');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-overriding 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 6, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       paddingTop: "30px" },
     { offset: 0.5, computedOffset: 0.5, easing: "ease",
       paddingTop: "20px" },
@@ -524,79 +539,79 @@ test(function(t) {
       paddingTop: "60px" },
     { offset: 1, computedOffset: 1, easing: "ease",
       paddingTop: "70px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for ' +
    'overlapping keyframes');
 
 // Gecko-specific test case: We are specifically concerned here that the
 // computed value for filter, "none", is correctly represented.
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-filter 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       filter: "none" },
     { offset: 1, computedOffset: 1, easing: "ease",
       filter: "blur(5px) sepia(60%) saturate(30%)" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected values for ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
    'animations with filter properties and missing keyframes');
 
 // Gecko-specific test case: We are specifically concerned here that the
 // computed value for text-shadow and a "none" specified on a keyframe
 // are correctly represented.
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.textShadow = '1px 1px 2px black, 0 0 16px blue, 0 0 3.2px blue';
   div.style.animation = 'anim-text-shadow 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       textShadow: "1px 1px 2px 0px rgb(0, 0, 0),"
                   + " 0px 0px 16px 0px rgb(0, 0, 255),"
                   + " 0px 0px 3.2px 0px rgb(0, 0, 255)" },
     { offset: 1, computedOffset: 1, easing: "ease", textShadow: "none" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected values for ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
    'animations with text-shadow properties and missing keyframes');
 
 // Gecko-specific test case: We are specifically concerned here that the
 // initial value for background-size and the specified list are correctly
 // represented.
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.animation = 'anim-background-size 100s';
-  var frames = getFrames(div);
+  var frames = getKeyframes(div);
 
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease",
       backgroundSize: "auto auto" },
     { offset: 1, computedOffset: 1, easing: "ease",
       backgroundSize: "50% auto, 6px auto, contain" },
@@ -605,20 +620,62 @@ test(function(t) {
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
 
   // Test inheriting a background-size value
 
   expected[0].backgroundSize = div.style.backgroundSize =
     "30px auto, 40% auto, auto auto";
-  frames = getFrames(div);
+  frames = getKeyframes(div);
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i
                         + " after updating current style");
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected values for ' +
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
    'animations with background-size properties and missing keyframes');
 
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim-variables 100s';
+
+  var frames = getKeyframes(div);
+
+  var expected = [
+    { offset: 0, computedOffset: 0, easing: "ease",
+      transform: "none" },
+    { offset: 1, computedOffset: 1, easing: "ease",
+      transform: "translate(100px, 0px)" },
+  ];
+  for (var i = 0; i < frames.length; i++) {
+    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+  }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
+   'animations with CSS variables as keyframe values');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.animation = 'anim-variables-shorthand 100s';
+
+  var frames = getKeyframes(div);
+
+  var expected = [
+    { offset: 0, computedOffset: 0, easing: "ease",
+      marginBottom: "0px",
+      marginLeft: "0px",
+      marginRight: "0px",
+      marginTop: "0px" },
+    { offset: 1, computedOffset: 1, easing: "ease",
+      marginBottom: "100px",
+      marginLeft: "100px",
+      marginRight: "100px",
+      marginTop: "100px" },
+  ];
+  for (var i = 0; i < frames.length; i++) {
+    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+  }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected values for ' +
+   'animations with CSS variables as keyframe values in a shorthand property');
+
 done();
 </script>
 </body>
rename from dom/animation/test/css-animations/test_keyframeeffect-getframes.html
rename to dom/animation/test/css-animations/test_keyframeeffect-getkeyframes.html
--- a/dom/animation/test/css-animations/test_keyframeeffect-getframes.html
+++ b/dom/animation/test/css-animations/test_keyframeeffect-getkeyframes.html
@@ -4,12 +4,12 @@
 <script src="/resources/testharnessreport.js"></script>
 <div id="log"></div>
 <script>
 'use strict';
 setup({explicit_done: true});
 SpecialPowers.pushPrefEnv(
   { "set": [["dom.animations-api.core.enabled", true]]},
   function() {
-    window.open("file_keyframeeffect-getframes.html");
+    window.open("file_keyframeeffect-getkeyframes.html");
   });
 </script>
 </html>
rename from dom/animation/test/css-transitions/file_keyframeeffect-getframes.html
rename to dom/animation/test/css-transitions/file_keyframeeffect-getkeyframes.html
--- a/dom/animation/test/css-transitions/file_keyframeeffect-getframes.html
+++ b/dom/animation/test/css-transitions/file_keyframeeffect-getkeyframes.html
@@ -1,17 +1,22 @@
 <!doctype html>
 <meta charset=utf-8>
 <script src="../testcommon.js"></script>
+<style>
+:root {
+  --var-100px: 100px;
+}
+</style>
 <body>
 <script>
 'use strict';
 
-function getFrames(e) {
-  return e.getAnimations()[0].effect.getFrames();
+function getKeyframes(e) {
+  return e.getAnimations()[0].effect.getKeyframes();
 }
 
 function assert_frames_equal(a, b, name) {
   assert_equals(Object.keys(a).sort().toString(),
                 Object.keys(b).sort().toString(),
                 "properties on " + name);
   for (var p in a) {
     assert_equals(a[p], b[p], "value for '" + p + "' on " + name);
@@ -21,49 +26,70 @@ function assert_frames_equal(a, b, name)
 test(function(t) {
   var div = addDiv(t);
 
   div.style.left = '0px';
   window.getComputedStyle(div).transitionProperty;
   div.style.transition = 'left 100s';
   div.style.left = '100px';
 
-  var frames = getFrames(div);
-  
+  var frames = getKeyframes(div);
+
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "ease", left: "0px" },
     { offset: 1, computedOffset: 1, easing: "linear", left: "100px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
-   'transition');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple'
+   + ' transition');
 
 test(function(t) {
   var div = addDiv(t);
 
   div.style.left = '0px';
   window.getComputedStyle(div).transitionProperty;
   div.style.transition = 'left 100s steps(2,end)';
   div.style.left = '100px';
 
-  var frames = getFrames(div);
-  
+  var frames = getKeyframes(div);
+
   assert_equals(frames.length, 2, "number of frames");
 
   var expected = [
     { offset: 0, computedOffset: 0, easing: "steps(2, end)", left: "0px" },
     { offset: 1, computedOffset: 1, easing: "linear", left: "100px" },
   ];
 
   for (var i = 0; i < frames.length; i++) {
     assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
   }
-}, 'KeyframeEffectReadOnly.getFrames() returns expected frames for a simple ' +
-   'transition with a non-default easing function');
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a simple'
+   + ' transition with a non-default easing function');
+
+test(function(t) {
+  var div = addDiv(t);
+  div.style.left = '0px';
+  window.getComputedStyle(div).transitionProperty;
+  div.style.transition = 'left 100s';
+  div.style.left = 'var(--var-100px)';
+
+  var frames = getKeyframes(div);
+
+  // CSS transition endpoints are based on the computed value so we
+  // shouldn't see the variable reference
+  var expected = [
+    { offset: 0, computedOffset: 0, easing: 'ease', left: '0px' },
+    { offset: 1, computedOffset: 1, easing: 'linear', left: '100px' },
+  ];
+  for (var i = 0; i < frames.length; i++) {
+    assert_frames_equal(frames[i], expected[i], "ComputedKeyframe #" + i);
+  }
+}, 'KeyframeEffectReadOnly.getKeyframes() returns expected frames for a'
+   + ' transition with a CSS variable endpoint');
 
 done();
 </script>
 </body>
rename from dom/animation/test/css-transitions/test_keyframeeffect-getframes.html
rename to dom/animation/test/css-transitions/test_keyframeeffect-getkeyframes.html
--- a/dom/animation/test/css-transitions/test_keyframeeffect-getframes.html
+++ b/dom/animation/test/css-transitions/test_keyframeeffect-getkeyframes.html
@@ -4,11 +4,11 @@
 <script src="/resources/testharnessreport.js"></script>
 <div id="log"></div>
 <script>
 'use strict';
 setup({explicit_done: true});
 SpecialPowers.pushPrefEnv(
   { "set": [["dom.animations-api.core.enabled", true]]},
   function() {
-    window.open("file_keyframeeffect-getframes.html");
+    window.open("file_keyframeeffect-getkeyframes.html");
   });
 </script>
--- a/dom/animation/test/mochitest.ini
+++ b/dom/animation/test/mochitest.ini
@@ -14,30 +14,30 @@ support-files =
   css-animations/file_animation-ready.html
   css-animations/file_animation-reverse.html
   css-animations/file_animation-starttime.html
   css-animations/file_animations-dynamic-changes.html
   css-animations/file_cssanimation-animationname.html
   css-animations/file_document-get-animations.html
   css-animations/file_effect-target.html
   css-animations/file_element-get-animations.html
-  css-animations/file_keyframeeffect-getframes.html
+  css-animations/file_keyframeeffect-getkeyframes.html
   css-animations/file_pseudoElement-get-animations.html
   css-transitions/file_animation-cancel.html
   css-transitions/file_animation-computed-timing.html
   css-transitions/file_animation-currenttime.html
   css-transitions/file_animation-finished.html
   css-transitions/file_animation-pausing.html
   css-transitions/file_animation-ready.html
   css-transitions/file_animation-starttime.html
   css-transitions/file_csstransition-transitionproperty.html
   css-transitions/file_document-get-animations.html
   css-transitions/file_effect-target.html
   css-transitions/file_element-get-animations.html
-  css-transitions/file_keyframeeffect-getframes.html
+  css-transitions/file_keyframeeffect-getkeyframes.html
   css-transitions/file_pseudoElement-get-animations.html
   document-timeline/file_document-timeline.html
   mozilla/file_deferred_start.html
   mozilla/file_disabled_properties.html
   mozilla/file_hide_and_show.html
   mozilla/file_partial_keyframes.html
   testcommon.js
 
@@ -53,31 +53,31 @@ support-files =
 [css-animations/test_animation-ready.html]
 [css-animations/test_animation-reverse.html]
 [css-animations/test_animation-starttime.html]
 [css-animations/test_cssanimation-animationname.html]
 [css-animations/test_document-get-animations.html]
 [css-animations/test_effect-target.html]
 [css-animations/test_element-get-animations.html]
 skip-if = buildapp == 'mulet'
-[css-animations/test_keyframeeffect-getframes.html]
+[css-animations/test_keyframeeffect-getkeyframes.html]
 [css-animations/test_pseudoElement-get-animations.html]
 [css-transitions/test_animation-cancel.html]
 [css-transitions/test_animation-computed-timing.html]
 [css-transitions/test_animation-currenttime.html]
 [css-transitions/test_animation-finished.html]
 [css-transitions/test_animation-pausing.html]
 [css-transitions/test_animation-ready.html]
 [css-transitions/test_animation-starttime.html]
 [css-transitions/test_csstransition-transitionproperty.html]
 [css-transitions/test_document-get-animations.html]
 [css-transitions/test_effect-target.html]
 [css-transitions/test_element-get-animations.html]
 skip-if = buildapp == 'mulet'
-[css-transitions/test_keyframeeffect-getframes.html]
+[css-transitions/test_keyframeeffect-getkeyframes.html]
 [css-transitions/test_pseudoElement-get-animations.html]
 [document-timeline/test_document-timeline.html]
 [document-timeline/test_request_animation_frame.html]
 skip-if = buildapp == 'mulet'
 [mozilla/test_deferred_start.html]
 skip-if = (toolkit == 'gonk' && debug)
 [mozilla/test_disabled_properties.html]
 [mozilla/test_hide_and_show.html]
--- a/dom/animation/test/mozilla/file_disabled_properties.html
+++ b/dom/animation/test/mozilla/file_disabled_properties.html
@@ -15,47 +15,47 @@ function waitForSetPref(pref, value) {
  * These tests rely on the fact that the -webkit-text-fill-color property
  * is disabled by the layout.css.prefixes.webkit pref. If we ever remove that
  * pref we will need to substitute some other pref:property combination.
  */
 
 promise_test(function(t) {
   return waitForSetPref('layout.css.prefixes.webkit', true).then(() => {
     var anim = addDiv(t).animate({ webkitTextFillColor: [ 'green', 'blue' ]});
-    assert_equals(anim.effect.getFrames().length, 2,
+    assert_equals(anim.effect.getKeyframes().length, 2,
                   'A property-indexed keyframe specifying only enabled'
                   + ' properties produces keyframes');
     return waitForSetPref('layout.css.prefixes.webkit', false);
   }).then(() => {
     var anim = addDiv(t).animate({ webkitTextFillColor: [ 'green', 'blue' ]});
-    assert_equals(anim.effect.getFrames().length, 0,
+    assert_equals(anim.effect.getKeyframes().length, 0,
                   'A property-indexed keyframe specifying only disabled'
                   + ' properties produces no keyframes');
   });
 }, 'Specifying a disabled property using a property-indexed keyframe');
 
 promise_test(function(t) {
   var createAnim = () => {
     var anim = addDiv(t).animate([ { webkitTextFillColor: 'green' },
                                    { webkitTextFillColor: 'blue' } ]);
-    assert_equals(anim.effect.getFrames().length, 2,
+    assert_equals(anim.effect.getKeyframes().length, 2,
                   'Animation specified using a keyframe sequence should'
                   + ' return the same number of keyframes regardless of'
                   + ' whether or not the specified properties are disabled');
     return anim;
   };
 
   var assert_has_property = (anim, index, descr, property) => {
     assert_true(
-      anim.effect.getFrames()[index].hasOwnProperty(property),
+      anim.effect.getKeyframes()[index].hasOwnProperty(property),
       `${descr} should have the '${property}' property`);
   };
   var assert_does_not_have_property = (anim, index, descr, property) => {
     assert_false(
-      anim.effect.getFrames()[index].hasOwnProperty(property),
+      anim.effect.getKeyframes()[index].hasOwnProperty(property),
       `${descr} should NOT have the '${property}' property`);
   };
 
   return waitForSetPref('layout.css.prefixes.webkit', true).then(() => {
     var anim = createAnim();
     assert_has_property(anim, 0, 'Initial keyframe', 'webkitTextFillColor');
     assert_has_property(anim, 1, 'Final keyframe', 'webkitTextFillColor');
     return waitForSetPref('layout.css.prefixes.webkit', false);
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -659,20 +659,19 @@ this.DOMApplicationRegistry = {
         return;
       }
 
       // b : core apps are not removable.
       for (let id in this.webapps) {
         if (id in data || this.webapps[id].removable)
           continue;
         // Remove the permissions, cookies and private data for this app.
+        // Both permission and cookie managers observe the "clear-origin-data"
+        // event.
         let localId = this.webapps[id].localId;
-        let attrs = { appId: localId };
-        permMgr.removePermissionsWithAttributes(JSON.stringify(attrs));
-        Services.cookies.removeCookiesForApp(localId, false);
         this._clearPrivateData(localId, false);
         delete this.webapps[id];
       }
 
       let appDir = FileUtils.getDir("coreAppsDir", ["webapps"], false);
       // c
       for (let id in data) {
         // Core apps have ids matching their domain name (eg: dialer.gaiamobile.org)
--- a/dom/base/DOMException.cpp
+++ b/dom/base/DOMException.cpp
@@ -84,17 +84,17 @@ enum DOM4ErrorTypeCodeMap {
   BtUnsupportedError       = 0,
   BtParmInvalidError       = 0,
   BtUnhandledError         = 0,
   BtAuthFailureError       = 0,
   BtRmtDevDownError        = 0,
   BtAuthRejectedError      = 0,
 
   /* Push API errors */
-  PermissionDeniedError    = 0,
+  NotAllowedError          = 0,
 };
 
 #define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message},
 #define DOM_MSG_DEF(val, message) {(val), NS_ERROR_GET_CODE(val), #val, message},
 
 static const struct ResultStruct
 {
   nsresult mNSResult;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -3299,29 +3299,29 @@ Element::RequestFullscreen(JSContext* aC
 void
 Element::MozRequestPointerLock()
 {
   OwnerDoc()->RequestPointerLock(this);
 }
 
 already_AddRefed<Animation>
 Element::Animate(JSContext* aContext,
-                 JS::Handle<JSObject*> aFrames,
+                 JS::Handle<JSObject*> aKeyframes,
                  const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
                  ErrorResult& aError)
 {
   Nullable<ElementOrCSSPseudoElement> target;
   target.SetValue().SetAsElement() = this;
-  return Animate(target, aContext, aFrames, aOptions, aError);
+  return Animate(target, aContext, aKeyframes, aOptions, aError);
 }
 
 /* static */ already_AddRefed<Animation>
 Element::Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
                  JSContext* aContext,
-                 JS::Handle<JSObject*> aFrames,
+                 JS::Handle<JSObject*> aKeyframes,
                  const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
                  ErrorResult& aError)
 {
   MOZ_ASSERT(!aTarget.IsNull() &&
              (aTarget.Value().IsElement() ||
               aTarget.Value().IsCSSPseudoElement()),
              "aTarget should be initialized");
 
@@ -3335,30 +3335,30 @@ Element::Animate(const Nullable<ElementO
   nsCOMPtr<nsIGlobalObject> ownerGlobal = referenceElement->GetOwnerGlobal();
   if (!ownerGlobal) {
     aError.Throw(NS_ERROR_FAILURE);
     return nullptr;
   }
   GlobalObject global(aContext, ownerGlobal->GetGlobalJSObject());
   MOZ_ASSERT(!global.Failed());
 
-  // Wrap the aFrames object for the cross-compartment case.
-  JS::Rooted<JSObject*> frames(aContext);
-  frames = aFrames;
+  // Wrap the aKeyframes object for the cross-compartment case.
+  JS::Rooted<JSObject*> keyframes(aContext);
+  keyframes = aKeyframes;
   Maybe<JSAutoCompartment> ac;
   if (js::GetContextCompartment(aContext) !=
       js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) {
     ac.emplace(aContext, ownerGlobal->GetGlobalJSObject());
-    if (!JS_WrapObject(aContext, &frames)) {
+    if (!JS_WrapObject(aContext, &keyframes)) {
       return nullptr;
     }
   }
 
   RefPtr<KeyframeEffect> effect =
-    KeyframeEffect::Constructor(global, aTarget, frames, aOptions, aError);
+    KeyframeEffect::Constructor(global, aTarget, keyframes, aOptions, aError);
   if (aError.Failed()) {
     return nullptr;
   }
 
   RefPtr<Animation> animation =
     Animation::Constructor(global, effect,
                            referenceElement->OwnerDoc()->Timeline(), aError);
   if (aError.Failed()) {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -847,26 +847,26 @@ public:
   }
 
   virtual void SetUndoScope(bool aUndoScope, ErrorResult& aError)
   {
   }
 
   already_AddRefed<Animation>
   Animate(JSContext* aContext,
-          JS::Handle<JSObject*> aFrames,
+          JS::Handle<JSObject*> aKeyframes,
           const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
           ErrorResult& aError);
 
   // A helper method that factors out the common functionality needed by
   // Element::Animate and CSSPseudoElement::Animate
   static already_AddRefed<Animation>
   Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
           JSContext* aContext,
-          JS::Handle<JSObject*> aFrames,
+          JS::Handle<JSObject*> aKeyframes,
           const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
           ErrorResult& aError);
 
   // Note: GetAnimations will flush style while GetAnimationsUnsorted won't.
   void GetAnimations(const AnimationFilter& filter,
                      nsTArray<RefPtr<Animation>>& aAnimations);
   static void GetAnimationsUnsorted(Element* aElement,
                                     CSSPseudoElementType aPseudoType,
--- a/dom/base/UseCounters.conf
+++ b/dom/base/UseCounters.conf
@@ -43,8 +43,21 @@ property FillOpacity
 
 // Push API
 method PushManager.subscribe
 method PushSubscription.unsubscribe
 
 // window.sidebar.addSearchEngine
 attribute Window.sidebar
 method External.addSearchEngine
+
+// AppCache API
+method OfflineResourceList.swapCache
+method OfflineResourceList.update
+attribute OfflineResourceList.status
+attribute OfflineResourceList.onchecking
+attribute OfflineResourceList.onerror
+attribute OfflineResourceList.onnoupdate
+attribute OfflineResourceList.ondownloading
+attribute OfflineResourceList.onprogress
+attribute OfflineResourceList.onupdateready
+attribute OfflineResourceList.oncached
+attribute OfflineResourceList.onobsolete
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -2806,16 +2806,22 @@ WebSocketImpl::Dispatch(already_AddRefed
   if (!event->Dispatch()) {
     return NS_ERROR_FAILURE;
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
+WebSocketImpl::DelayedDispatch(already_AddRefed<nsIRunnable>&&, uint32_t)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 WebSocketImpl::IsOnCurrentThread(bool* aResult)
 {
   *aResult = IsTargetThread();
   return NS_OK;
 }
 
 bool
 WebSocketImpl::IsTargetThread() const
--- a/dom/base/domerr.msg
+++ b/dom/base/domerr.msg
@@ -149,16 +149,16 @@ DOM4_MSG_DEF(FileHandleInactiveError, "A
 DOM4_MSG_DEF(ReadOnlyError, "A mutation operation was attempted in a READ_ONLY file handle.", NS_ERROR_DOM_FILEHANDLE_READ_ONLY_ERR)
 
 DOM4_MSG_DEF(InvalidStateError, "A mutation operation was attempted on a file storage that did not allow mutations.", NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR)
 DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to FileHandle.abort.", NS_ERROR_DOM_FILEHANDLE_ABORT_ERR)
 DOM4_MSG_DEF(QuotaExceededError, "The current file handle exceeded its quota limitations.", NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR)
 
 /* Push API errors. */
 DOM4_MSG_DEF(InvalidStateError, "Invalid service worker registration.", NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR)
-DOM4_MSG_DEF(PermissionDeniedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR)
+DOM4_MSG_DEF(NotAllowedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR)
 DOM4_MSG_DEF(AbortError, "Error retrieving push subscription.", NS_ERROR_DOM_PUSH_ABORT_ERR)
 DOM4_MSG_DEF(NetworkError, "Push service unreachable.", NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE)
 DOM4_MSG_DEF(InvalidAccessError, "Invalid raw ECDSA P-256 public key.", NS_ERROR_DOM_PUSH_INVALID_KEY_ERR)
 DOM4_MSG_DEF(InvalidStateError, "A subscription with a different application server key already exists.", NS_ERROR_DOM_PUSH_MISMATCHED_KEY_ERR)
 
 DOM_MSG_DEF(NS_ERROR_DOM_JS_EXCEPTION, "A callback threw an exception")
 DOM_MSG_DEF(NS_ERROR_DOM_DOMEXCEPTION, "A DOMException was thrown")
--- a/dom/base/nsDocumentWarningList.h
+++ b/dom/base/nsDocumentWarningList.h
@@ -6,8 +6,9 @@
 // IWYU pragma: private, include "nsIDocument.h"
 
 /*
  * This file contains the list of document DOM operations warnings.  It is
  * designed to be used as input to the C preprocessor *only*.
  */
 
 DOCUMENT_WARNING(IgnoringWillChangeOverBudget)
+DOCUMENT_WARNING(PreventDefaultFromPassiveListener)
--- a/dom/base/nsXMLHttpRequest.h
+++ b/dom/base/nsXMLHttpRequest.h
@@ -136,17 +136,17 @@ public:
 
   IMPL_EVENT_HANDLER(loadstart)
   IMPL_EVENT_HANDLER(progress)
   IMPL_EVENT_HANDLER(abort)
   IMPL_EVENT_HANDLER(error)
   IMPL_EVENT_HANDLER(load)
   IMPL_EVENT_HANDLER(timeout)
   IMPL_EVENT_HANDLER(loadend)
-  
+
   virtual void DisconnectFromOwner() override;
 };
 
 class nsXMLHttpRequestUpload final : public nsXHREventTarget,
                                      public nsIXMLHttpRequestUpload
 {
 public:
   explicit nsXMLHttpRequestUpload(mozilla::DOMEventTargetHelper* aOwner)
index 4e8b4d3a3d8e27dc6592427e7560a9be23645c3c..bed764fbf132f29c1004c3215730ceec956c8684
GIT binary patch
literal 14293
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
index dc136f1494024145ffa05952140216a878c9c5cb..6ae65448d88993e9b080147145bf07a090859fc9
GIT binary patch
literal 53840
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
b;N97bki{N+yL&b_I&W|P-pKf|NhlovNP<rE
--- a/dom/base/test/test_audioNotificationSilent_audioFile.html
+++ b/dom/base/test/test_audioNotificationSilent_audioFile.html
@@ -50,33 +50,28 @@ function audioPlayingStart() {
 
 function audioBecomeSilentDuringPlaying() {
   info("Audio would become silent during playing");
 
   expectedPlaybackActive = 'inactive';
   expectedPlaying = true;
 }
 
-function audioPlayingEnd() {
-  audio.onended = function() {
-    info("Audio playback ended");
-    audio.onended = null;
+function finish() {
+  observerService.removeObserver(observer, "audio-playback");
+  ok(true, "Observer removed");
 
-    observerService.removeObserver(observer, "audio-playback");
-    ok(true, "Observer removed");
-
-    SimpleTest.finish();
-  };
+  SimpleTest.finish();
 }
 
 function runTest() {
   yield audioPlayingStart();
 
   yield audioBecomeSilentDuringPlaying();
 
-  yield audioPlayingEnd();
+  yield finish();
 }
 
 continueTest();
 
 </script>
 </body>
 </html>
\ No newline at end of file
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2268,17 +2268,17 @@ template<typename T>
 void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq)
 {
   SequenceTracer<T>::TraceSequence(trc, seq.Elements(),
                                    seq.Elements() + seq.Length());
 }
 
 // Rooter class for sequences; this is what we mostly use in the codegen
 template<typename T>
-class MOZ_RAII SequenceRooter : private JS::CustomAutoRooter
+class MOZ_RAII SequenceRooter final : private JS::CustomAutoRooter
 {
 public:
   SequenceRooter(JSContext *aCx, FallibleTArray<T>* aSequence
                  MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
     : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
       mFallibleArray(aSequence),
       mSequenceType(eFallibleArray)
   {
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -92,8 +92,9 @@ MSG_DEF(MSG_SW_INSTALL_ERROR, 2, JSEXN_T
 MSG_DEF(MSG_SW_SCRIPT_THREW, 2, JSEXN_TYPEERR, "ServiceWorker script at {0} for scope {1} threw an exception during script evaluation.")
 MSG_DEF(MSG_TYPEDARRAY_IS_SHARED, 1, JSEXN_TYPEERR, "{0} can't be a typed array on SharedArrayBuffer")
 MSG_DEF(MSG_CACHE_ADD_FAILED_RESPONSE, 3, JSEXN_TYPEERR, "Cache got {0} response with bad status {1} while trying to add request {2}")
 MSG_DEF(MSG_SW_UPDATE_BAD_REGISTRATION, 2, JSEXN_TYPEERR, "Failed to update the ServiceWorker for scope {0] because the registration has been {1} since the update was scheduled.")
 MSG_DEF(MSG_INVALID_DURATION_ERROR, 1, JSEXN_TYPEERR, "Invalid duration '{0}'.")
 MSG_DEF(MSG_INVALID_EASING_ERROR, 1, JSEXN_TYPEERR, "Invalid easing '{0}'.")
 MSG_DEF(MSG_USELESS_SETTIMEOUT, 1, JSEXN_TYPEERR, "Useless {0} call (missing quotes around argument?)")
 MSG_DEF(MSG_TOKENLIST_NO_SUPPORTED_TOKENS, 2, JSEXN_TYPEERR, "{0} attribute of <{1}> does not define any supported tokens")
+MSG_DEF(MSG_CACHE_STREAM_CLOSED, 0, JSEXN_TYPEERR, "Response body is a cache file stream that has already been closed.")
--- a/dom/bindings/RootedDictionary.h
+++ b/dom/bindings/RootedDictionary.h
@@ -10,34 +10,34 @@
 #include "mozilla/GuardObjects.h"
 #include "mozilla/dom/Nullable.h"
 #include "jsapi.h"
 
 namespace mozilla {
 namespace dom {
 
 template<typename T>
-class MOZ_RAII RootedDictionary : public T,
+class MOZ_RAII RootedDictionary final : public T,
                                          private JS::CustomAutoRooter
 {
 public:
   explicit RootedDictionary(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
     T(),
     JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
   {
   }
 
   virtual void trace(JSTracer *trc) override
   {
     this->TraceDictionary(trc);
   }
 };
 
 template<typename T>
-class MOZ_RAII NullableRootedDictionary : public Nullable<T>,
+class MOZ_RAII NullableRootedDictionary final : public Nullable<T>,
                                                  private JS::CustomAutoRooter
 {
 public:
   explicit NullableRootedDictionary(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
     Nullable<T>(),
     JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT)
   {
   }
index 4e8b4d3a3d8e27dc6592427e7560a9be23645c3c..44ab64f81153cb46ec5b2db5efbf91fa1a2401b4
GIT binary patch
literal 14293
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
--- a/dom/cache/AutoUtils.cpp
+++ b/dom/cache/AutoUtils.cpp
@@ -617,14 +617,16 @@ AutoParentOpResult::SerializeReadStream(
       return;
     }
   }
 
   aStreamList->SetStreamControl(mStreamControl);
 
   RefPtr<ReadStream> readStream = ReadStream::Create(mStreamControl,
                                                        aId, stream);
-  readStream->Serialize(aReadStreamOut);
+  ErrorResult rv;
+  readStream->Serialize(aReadStreamOut, rv);
+  MOZ_ASSERT(!rv.Failed());
 }
 
 } // namespace cache
 } // namespace dom
 } // namespace mozilla
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -904,17 +904,17 @@ StorageMatch(mozIStorageConnection* aCon
   // and perform the match.
   if (!aParams.cacheName().EqualsLiteral("")) {
     bool foundCache = false;
     // no invalid CacheId, init to least likely real value
     CacheId cacheId = INVALID_CACHE_ID;
     rv = StorageGetCacheId(aConn, aNamespace, aParams.cacheName(), &foundCache,
                            &cacheId);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
-    if (!foundCache) { return NS_ERROR_DOM_NOT_FOUND_ERR; }
+    if (!foundCache) { return NS_OK; }
 
     rv = CacheMatch(aConn, cacheId, aRequest, aParams, aFoundResponseOut,
                     aSavedResponseOut);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
     return rv;
   }
 
--- a/dom/cache/ReadStream.cpp
+++ b/dom/cache/ReadStream.cpp
@@ -30,20 +30,20 @@ using mozilla::ipc::FileDescriptor;
 // guaranteed by our outer ReadStream class.
 class ReadStream::Inner final : public ReadStream::Controllable
 {
 public:
   Inner(StreamControl* aControl, const nsID& aId,
         nsIInputStream* aStream);
 
   void
-  Serialize(CacheReadStreamOrVoid* aReadStreamOut);
+  Serialize(CacheReadStreamOrVoid* aReadStreamOut, ErrorResult& aRv);
 
   void
-  Serialize(CacheReadStream* aReadStreamOut);
+  Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv);
 
   // ReadStream::Controllable methods
   virtual void
   CloseStream() override;
 
   virtual void
   CloseStreamWithoutReporting() override;
 
@@ -192,31 +192,37 @@ ReadStream::Inner::Inner(StreamControl* 
   , mState(Open)
 {
   MOZ_ASSERT(mStream);
   MOZ_ASSERT(mControl);
   mControl->AddReadStream(this);
 }
 
 void
-ReadStream::Inner::Serialize(CacheReadStreamOrVoid* aReadStreamOut)
+ReadStream::Inner::Serialize(CacheReadStreamOrVoid* aReadStreamOut,
+                             ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
   MOZ_ASSERT(aReadStreamOut);
   CacheReadStream stream;
-  Serialize(&stream);
+  Serialize(&stream, aRv);
   *aReadStreamOut = stream;
 }
 
 void
-ReadStream::Inner::Serialize(CacheReadStream* aReadStreamOut)
+ReadStream::Inner::Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread);
   MOZ_ASSERT(aReadStreamOut);
-  MOZ_ASSERT(mState == Open);
+
+  if (mState != Open) {
+    aRv.ThrowTypeError<MSG_CACHE_STREAM_CLOSED>();
+    return;
+  }
+
   MOZ_ASSERT(mControl);
 
   // If we are sending a ReadStream, then we never want to set the
   // pushStream actors at the same time.
   aReadStreamOut->pushStreamChild() = nullptr;
   aReadStreamOut->pushStreamParent() = nullptr;
 
   aReadStreamOut->id() = mId;
@@ -477,25 +483,25 @@ ReadStream::Create(PCacheStreamControlPa
   MOZ_ASSERT(aControl);
   auto actor = static_cast<CacheStreamControlParent*>(aControl);
   RefPtr<Inner> inner = new Inner(actor, aId, aStream);
   RefPtr<ReadStream> ref = new ReadStream(inner);
   return ref.forget();
 }
 
 void
-ReadStream::Serialize(CacheReadStreamOrVoid* aReadStreamOut)
+ReadStream::Serialize(CacheReadStreamOrVoid* aReadStreamOut, ErrorResult& aRv)
 {
-  mInner->Serialize(aReadStreamOut);
+  mInner->Serialize(aReadStreamOut, aRv);
 }
 
 void
-ReadStream::Serialize(CacheReadStream* aReadStreamOut)
+ReadStream::Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv)
 {
-  mInner->Serialize(aReadStreamOut);
+  mInner->Serialize(aReadStreamOut, aRv);
 }
 
 ReadStream::ReadStream(ReadStream::Inner* aInner)
   : mInner(aInner)
 {
   MOZ_ASSERT(mInner);
 }
 
--- a/dom/cache/ReadStream.h
+++ b/dom/cache/ReadStream.h
@@ -76,18 +76,18 @@ public:
 
   static already_AddRefed<ReadStream>
   Create(const CacheReadStream& aReadStream);
 
   static already_AddRefed<ReadStream>
   Create(PCacheStreamControlParent* aControl, const nsID& aId,
          nsIInputStream* aStream);
 
-  void Serialize(CacheReadStreamOrVoid* aReadStreamOut);
-  void Serialize(CacheReadStream* aReadStreamOut);
+  void Serialize(CacheReadStreamOrVoid* aReadStreamOut, ErrorResult& aRv);
+  void Serialize(CacheReadStream* aReadStreamOut, ErrorResult& aRv);
 
 private:
   class Inner;
 
   explicit ReadStream(Inner* aInner);
   ~ReadStream();
 
   // Hold a strong ref to an inner class that actually implements the
--- a/dom/cache/TypeUtils.cpp
+++ b/dom/cache/TypeUtils.cpp
@@ -505,17 +505,17 @@ TypeUtils::SerializeCacheStream(nsIInput
   *aStreamOut = void_t();
   if (!aStream) {
     return;
   }
 
   // Option 1: Send a cache-specific ReadStream if we can.
   RefPtr<ReadStream> controlled = do_QueryObject(aStream);
   if (controlled) {
-    controlled->Serialize(aStreamOut);
+    controlled->Serialize(aStreamOut, aRv);
     return;
   }
 
   CacheReadStream readStream;
   readStream.controlChild() = nullptr;
   readStream.controlParent() = nullptr;
   readStream.pushStreamChild() = nullptr;
   readStream.pushStreamParent() = nullptr;
--- a/dom/cache/test/mochitest/test_cache_matchAll_request.js
+++ b/dom/cache/test/mochitest/test_cache_matchAll_request.js
@@ -124,19 +124,20 @@ function testRequest(request1, request2,
     is(r.length, 2, "Should find 2 items");
     return Promise.all([
       checkResponse(r[0], response1, response1Text),
       checkResponse(r[1], response3, response3Text)
     ]);
   }).then(function() {
     return caches.match(request1, {cacheName: name + "mambojambo"})
       .then(function() {
-        ok(false, "Promise should be rejected");
-      }, function(err) {
-        is(err.name, "NotFoundError", "Searching in the wrong cache should not succeed");
+        is(typeof r, "undefined", 'Searching in the wrong cache should resolve to undefined');
+        return caches.has(name + "mambojambo");
+      }).then(function(hasCache) {
+        ok(!hasCache, 'The wrong cache should still not exist');
       });
   }).then(function() {
     return c.matchAll(unknownRequest);
   }).then(function(r) {
     is(r.length, 0, "Searching for an unknown request should not succeed");
     return caches.match(unknownRequest, {cacheName: name});
   }).then(function(r) {
     is(typeof r, "undefined", "Searching for an unknown request should not succeed");
--- a/dom/cache/test/mochitest/test_cache_match_request.js
+++ b/dom/cache/test/mochitest/test_cache_match_request.js
@@ -99,20 +99,21 @@ function testRequest(request, unknownReq
   }).then(function(r) {
     return checkResponse(r);
   }).then(function() {
     return caches.match(request, {cacheName: name});
   }).then(function(r) {
     return checkResponse(r);
   }).then(function() {
     return caches.match(request, {cacheName: name + "mambojambo"})
-      .then(function() {
-        ok(false, "Promise should be rejected");
-      }, function(err) {
-        is(err.name, "NotFoundError", "Searching in the wrong cache should not succeed");
+      .then(function(result) {
+        is(typeof r, "undefined", 'Searching in the wrong cache should resolve to undefined');
+        return caches.has(name + "mambojambo");
+      }).then(function(hasCache) {
+        ok(!hasCache, 'The wrong cache should still not exist');
       });
   }).then(function() {
     // Make sure that cacheName is ignored on Cache
     return c.match(request, {cacheName: name + "mambojambo"});
   }).then(function(r) {
     return checkResponse(r);
   }).then(function() {
     return c.match(unknownRequest);
--- a/dom/cache/test/mochitest/test_cache_orphaned_body.html
+++ b/dom/cache/test/mochitest/test_cache_orphaned_body.html
@@ -158,14 +158,30 @@ SpecialPowers.pushPrefEnv({
   }).then(function() {
     return storageUsage();
   }).then(function(usage) {
     endUsage = usage;
     dump("### ### initial:" + initialUsage + ", full:" + fullUsage +
          ", end:" + endUsage + "\n");
     ok(endUsage < fullUsage, 'disk usage should have shrank');
     is(endUsage, initialUsage, 'disk usage should return to original');
+  })
+
+  // Verify that the stale, orphaned response cannot be put back into
+  // the cache.
+  .then(function() {
+    ok(!response.bodyUsed, 'response body should not be considered used');
+    return cache.put(url, response).then(function() {
+        ok(false, 'Should not be able to store stale orphaned body.');
+      }).catch(function(e) {
+        is(e.name, 'TypeError', 'storing a stale orphaned body should throw TypeError');
+      });
+  }).then(function() {
+    ok(response.bodyUsed, 'attempting to store response should mark body used');
+  })
+
+  .then(function() {
     SimpleTest.finish();
   });
 });
 </script>
 </body>
 </html>
--- a/dom/canvas/TexUnpackBlob.cpp
+++ b/dom/canvas/TexUnpackBlob.cpp
@@ -306,17 +306,23 @@ TexUnpackImage::TexOrSubImage(bool isSub
                                                       dstOrigin))
         {
             break;
         }
 
         return; // Blitting was successful, so we're done!
     } while (false);
 
-    TexUnpackSurface surfBlob(mImage->GetAsSourceSurface(), mIsAlphaPremult);
+    RefPtr<SourceSurface> surface = mImage->GetAsSourceSurface();
+    if (!surface) {
+        *out_glError = LOCAL_GL_OUT_OF_MEMORY;
+        return;
+    }
+
+    TexUnpackSurface surfBlob(surface, mIsAlphaPremult);
 
     surfBlob.TexOrSubImage(isSubImage, needsRespec, funcName, tex, target, level, dui,
                            xOffset, yOffset, zOffset, out_glError);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////////////
 // TexUnpackSurface
--- a/dom/canvas/WebGLContextLossHandler.cpp
+++ b/dom/canvas/WebGLContextLossHandler.cpp
@@ -73,16 +73,23 @@ ContextLossWorkerEventTarget::Dispatch(a
 {
     nsCOMPtr<nsIRunnable> eventRef(aEvent);
     RefPtr<ContextLossWorkerRunnable> wrappedEvent =
         new ContextLossWorkerRunnable(eventRef);
     return mEventTarget->Dispatch(wrappedEvent, aFlags);
 }
 
 NS_IMETHODIMP
+ContextLossWorkerEventTarget::DelayedDispatch(already_AddRefed<nsIRunnable>&&,
+                                              uint32_t)
+{
+    return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 ContextLossWorkerEventTarget::IsOnCurrentThread(bool* aResult)
 {
     return mEventTarget->IsOnCurrentThread(aResult);
 }
 
 nsresult
 ContextLossWorkerRunnable::Cancel()
 {
--- a/dom/canvas/test/webgl-conf/generated-mochitest.ini
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.ini
@@ -2955,17 +2955,17 @@ fail-if = (os == 'android') || (os == 'l
 [generated/test_conformance__ogles__GL__length__length_001_to_006.html]
 [generated/test_conformance__ogles__GL__lessThanEqual__lessThanEqual_001_to_008.html]
 [generated/test_conformance__ogles__GL__lessThan__lessThan_001_to_008.html]
 [generated/test_conformance__ogles__GL__log2__log2_001_to_008.html]
 [generated/test_conformance__ogles__GL__log2__log2_009_to_012.html]
 [generated/test_conformance__ogles__GL__log__log_001_to_008.html]
 [generated/test_conformance__ogles__GL__log__log_009_to_012.html]
 [generated/test_conformance__ogles__GL__mat3__mat3_001_to_006.html]
-skip-if = (os == 'win' && (os_version == '6.2' || os_version == '6.3'))
+skip-if = (os == 'win' && os_version != '5.1')
 [generated/test_conformance__ogles__GL__mat__mat_001_to_008.html]
 [generated/test_conformance__ogles__GL__mat__mat_009_to_016.html]
 [generated/test_conformance__ogles__GL__mat__mat_017_to_024.html]
 [generated/test_conformance__ogles__GL__mat__mat_025_to_032.html]
 [generated/test_conformance__ogles__GL__mat__mat_033_to_040.html]
 [generated/test_conformance__ogles__GL__mat__mat_041_to_046.html]
 [generated/test_conformance__ogles__GL__matrixCompMult__matrixCompMult_001_to_004.html]
 [generated/test_conformance__ogles__GL__max__max_001_to_006.html]
@@ -3077,17 +3077,17 @@ skip-if = (os == 'mac') || (os == 'andro
 [generated/test_conformance__state__gl-enum-tests.html]
 [generated/test_conformance__state__gl-get-calls.html]
 [generated/test_conformance__state__gl-geterror.html]
 [generated/test_conformance__state__gl-getstring.html]
 [generated/test_conformance__state__gl-object-get-calls.html]
 [generated/test_conformance__state__state-uneffected-after-compositing.html]
 [generated/test_conformance__textures__compressed-tex-image.html]
 [generated/test_conformance__textures__copy-tex-image-2d-formats.html]
-skip-if = (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+skip-if = (os == 'win' && os_version == '5.1')
 [generated/test_conformance__textures__copy-tex-image-and-sub-image-2d.html]
 [generated/test_conformance__textures__default-texture.html]
 [generated/test_conformance__textures__gl-get-tex-parameter.html]
 [generated/test_conformance__textures__gl-pixelstorei.html]
 [generated/test_conformance__textures__gl-teximage.html]
 skip-if = 1
 [generated/test_conformance__textures__mipmap-fbo.html]
 [generated/test_conformance__textures__origin-clean-conformance.html]
@@ -3176,9 +3176,9 @@ skip-if = 1
 [generated/test_conformance__uniforms__null-uniform-location.html]
 [generated/test_conformance__uniforms__out-of-bounds-uniform-array-access.html]
 skip-if = (os == 'android') || (os == 'mac' && os_version == '10.6')
 [generated/test_conformance__uniforms__uniform-default-values.html]
 skip-if = (os == 'android') || (os == 'linux') || (os == 'win')
 [generated/test_conformance__uniforms__uniform-location.html]
 [generated/test_conformance__uniforms__uniform-samplers-test.html]
 [generated/test_conformance__uniforms__uniform-values-per-program.html]
-skip-if = (os == 'win' && (os_version == '6.2' || os_version == '6.3'))
+skip-if = (os == 'win' && os_version != '5.1')
--- a/dom/canvas/test/webgl-conf/mochitest-errata.ini
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.ini
@@ -71,18 +71,18 @@ skip-if = 1
 [generated/test_conformance__textures__texture-transparent-pixels-initialized.html]
 skip-if = 1
 [generated/test_conformance__textures__texture-upload-size.html]
 skip-if = 1
 [generated/test_conformance__uniforms__uniform-default-values.html]
 # Timeout on Windows, crash on Android/Linux.
 skip-if = (os == 'android') || (os == 'linux') || (os == 'win')
 [generated/test_conformance__ogles__GL__mat3__mat3_001_to_006.html]
-# Timeout on Windows 8
-skip-if = (os == 'win' && (os_version == '6.2' || os_version == '6.3'))
+# Timeout on D3D11
+skip-if = (os == 'win' && os_version != '5.1')
 
 ########################################################################
 # Complicated
 
 [generated/test_conformance__context__context-attributes-alpha-depth-stencil-antialias.html]
 fail-if = (os == 'mac' && os_version == '10.6')
 # Asserts on 'B2G ICS Emulator Debug' and linux debug. Crashes on Android.
 skip-if = (os == 'b2g') || (os == 'linux') || (os == 'android')
@@ -447,12 +447,12 @@ fail-if = (os == 'mac' && os_version == 
 ########################################################################
 ########################################################################
 # Win
 
 [generated/test_conformance__glsl__misc__large-loop-compile.html]
 fail-if = (os == 'win' && os_version == '5.1')
 [generated/test_conformance__textures__copy-tex-image-2d-formats.html]
 # Assert failure in DEBUG
-skip-if = (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+skip-if = (os == 'win' && os_version == '5.1')
 [generated/test_conformance__uniforms__uniform-values-per-program.html]
-# Crashes on Windows 8 debug.
-skip-if = (os == 'win' && (os_version == '6.2' || os_version == '6.3'))
+# Crashes on D3D11 debug.
+skip-if = (os == 'win' && os_version != '5.1')
--- a/dom/canvas/test/webgl-mochitest/mochitest.ini
+++ b/dom/canvas/test/webgl-mochitest/mochitest.ini
@@ -28,27 +28,25 @@ fail-if = (os == 'android') || (os == 'l
 fail-if = (os == 'android')
 [ensure-exts/test_WEBGL_color_buffer_float.html]
 fail-if = (os == 'android')
 [ensure-exts/test_WEBGL_compressed_texture_atc.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_es3.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_etc1.html]
-# Win7 is 6.1
-fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+fail-if = (os == 'linux') || (os == 'mac') || (os == 'win' && os_version == '5.1')
 [ensure-exts/test_WEBGL_compressed_texture_pvrtc.html]
 fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
 [ensure-exts/test_WEBGL_compressed_texture_s3tc.html]
 fail-if = (os == 'android') || (os == 'linux')
 [ensure-exts/test_WEBGL_depth_texture.html]
 fail-if = (os == 'mac' && os_version == '10.6')
 [ensure-exts/test_WEBGL_draw_buffers.html]
-# Win7 is 6.1
-fail-if = (os == 'android') || (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+fail-if = (os == 'android') || (os == 'win' && os_version == '5.1')
 
 [ensure-exts/test_common.html]
 
 
 [test_backends.html]
 [test_backbuffer_channels.html]
 fail-if = (os == 'b2g')
 [test_depth_readpixels.html]
@@ -59,17 +57,17 @@ support-files = ../captureStream_common.
 [test_cubemap_must_be_square.html]
 [test_depth_tex_lazy_clear.html]
 [test_draw.html]
 [test_fb_param.html]
 [test_fb_param_crash.html]
 [test_hidden_alpha.html]
 skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
 [test_hidden_depth_stencil.html]
-fail-if = (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
+fail-if = (os == 'win' && os_version == '5.1')
 [test_implicit_color_buffer_float.html]
 [test_highp_fs.html]
 [test_no_arr_points.html]
 skip-if = android_version == '18' #Android 4.3 aws only; bug 1030942
 [test_noprog_draw.html]
 [test_privileged_exts.html]
 [test_renderer_strings.html]
 [test_sab_with_webgl.html]
--- a/dom/canvas/test/webgl-mochitest/test_backends.html
+++ b/dom/canvas/test/webgl-mochitest/test_backends.html
@@ -24,18 +24,17 @@ var ANGLE_IS_SINGLETON = true;
 
 var expectD3DType;
 try {
   // code borrowed from browser/modules/test/browser_taskbar_preview.js
   var version = SpecialPowers.Services.sysinfo.getProperty('version');
   version = parseFloat(version);
 
   // Version 6.0 is Vista, 6.1 is 7.
-  // Our Win7 slaves prefer d3d9, though!
-  if (version <= 6.1)
+  if (version <= 6.0)
     expectD3DType = 'd3d9';
   else
     expectD3DType = 'd3d11';
 } catch (e) {
   expectD3DType = 'd3d11';
 }
 
 function GetRenderer() {
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -26,17 +26,22 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(DOMEventTargetHelper)
   if (MOZ_UNLIKELY(cb.WantDebugInfo())) {
     char name[512];
     nsAutoString uri;
     if (tmp->mOwnerWindow && tmp->mOwnerWindow->GetExtantDoc()) {
       tmp->mOwnerWindow->GetExtantDoc()->GetDocumentURI(uri);
     }
-    snprintf_literal(name, "DOMEventTargetHelper %s",
+
+    nsXPCOMCycleCollectionParticipant* participant = nullptr;
+    CallQueryInterface(tmp, &participant);
+
+    snprintf_literal(name, "%s %s",
+                     participant->ClassName(),
                      NS_ConvertUTF16toUTF8(uri).get());
     cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
   } else {
     NS_IMPL_CYCLE_COLLECTION_DESCRIBE(DOMEventTargetHelper, tmp->mRefCnt.get())
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mListenerManager)
--- a/dom/events/Event.cpp
+++ b/dom/events/Event.cpp
@@ -515,16 +515,29 @@ Event::PreventDefault(JSContext* aCx)
 }
 
 void
 Event::PreventDefaultInternal(bool aCalledByDefaultHandler)
 {
   if (!mEvent->mFlags.mCancelable) {
     return;
   }
+  if (mEvent->mFlags.mInPassiveListener) {
+    nsCOMPtr<nsPIDOMWindowInner> win(do_QueryInterface(mOwner));
+    if (win) {
+      if (nsIDocument* doc = win->GetExtantDoc()) {
+        nsString type;
+        GetType(type);
+        const char16_t* params[] = { type.get() };
+        doc->WarnOnceAbout(nsIDocument::ePreventDefaultFromPassiveListener,
+          false, params, ArrayLength(params));
+      }
+    }
+    return;
+  }
 
   mEvent->PreventDefault(aCalledByDefaultHandler);
 
   if (!IsTrusted()) {
     return;
   }
 
   WidgetDragEvent* dragEvent = mEvent->AsDragEvent();
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -259,17 +259,17 @@ EventListenerManager::AddEventListenerIn
   // to the listener.
 
   Listener* listener;
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; i++) {
     listener = &mListeners.ElementAt(i);
     // mListener == aListenerHolder is the last one, since it can be a bit slow.
     if (listener->mListenerIsHandler == aHandler &&
-        listener->mFlags == aFlags &&
+        listener->mFlags.EqualsForAddition(aFlags) &&
         EVENT_TYPE_EQUALS(listener, aEventMessage, aTypeAtom, aTypeString,
                           aAllEvents) &&
         listener->mListener == aListenerHolder) {
       return;
     }
   }
 
   mNoListenerForEvent = eVoidEvent;
@@ -415,17 +415,17 @@ EventListenerManager::AddEventListenerIn
              aTypeAtom == nsGkAtoms::oncompositionstart ||
              aTypeAtom == nsGkAtoms::oncompositionupdate ||
              aTypeAtom == nsGkAtoms::oninput) {
     if (!aFlags.mInSystemGroup) {
       mMayHaveInputOrCompositionEventListener = true;
     }
   }
 
-  if (IsApzAwareEvent(aTypeAtom)) {
+  if (IsApzAwareListener(listener)) {
     ProcessApzAwareEventListenerAdd();
   }
 
   if (aTypeAtom && mTarget) {
     mTarget->EventListenerAdded(aTypeAtom);
   }
 
   if (mIsMainThreadELM && mTarget) {
@@ -612,17 +612,17 @@ EventListenerManager::RemoveEventListene
 #endif // MOZ_B2G
 
   for (uint32_t i = 0; i < count; ++i) {
     listener = &mListeners.ElementAt(i);
     if (EVENT_TYPE_EQUALS(listener, aEventMessage, aUserType, aTypeString,
                           aAllEvents)) {
       ++typeCount;
       if (listener->mListener == aListenerHolder &&
-          listener->mFlags.EqualsIgnoringTrustness(aFlags)) {
+          listener->mFlags.EqualsForRemoval(aFlags)) {
         RefPtr<EventListenerManager> kungFuDeathGrip(this);
         mListeners.RemoveElementAt(i);
         --count;
         mNoListenerForEvent = eVoidEvent;
         mNoListenerForEventAtom = nullptr;
         if (mTarget && aUserType) {
           mTarget->EventListenerRemoved(aUserType);
         }
@@ -1274,19 +1274,21 @@ EventListenerManager::HandleEventInterna
                   (*aDOMEvent)->GetEventPhase(&phase);
                   timelines->AddMarkerForDocShell(docShell, Move(
                     MakeUnique<EventTimelineMarker>(
                       typeStr, phase, MarkerTracingType::START)));
                 }
               }
             }
 
+            aEvent->mFlags.mInPassiveListener = listener->mFlags.mPassive;
             if (NS_FAILED(HandleEventSubType(listener, *aDOMEvent, aCurrentTarget))) {
               aEvent->mFlags.mExceptionWasRaised = true;
             }
+            aEvent->mFlags.mInPassiveListener = false;
 
             if (needsEndEventMarker) {
               timelines->AddMarkerForDocShell(
                 docShell, "DOMEvent", MarkerTracingType::END);
             }
           }
         }
       }
@@ -1347,19 +1349,22 @@ EventListenerManager::AddEventListener(
 void
 EventListenerManager::AddEventListener(
                         const nsAString& aType,
                         const EventListenerHolder& aListenerHolder,
                         const dom::AddEventListenerOptionsOrBoolean& aOptions,
                         bool aWantsUntrusted)
 {
   EventListenerFlags flags;
-  flags.mCapture =
-    aOptions.IsBoolean() ? aOptions.GetAsBoolean()
-                         : aOptions.GetAsAddEventListenerOptions().mCapture;
+  if (aOptions.IsBoolean()) {
+    flags.mCapture = aOptions.GetAsBoolean();
+  } else {
+    flags.mCapture = aOptions.GetAsAddEventListenerOptions().mCapture;
+    flags.mPassive = aOptions.GetAsAddEventListenerOptions().mPassive;
+  }
   flags.mAllowUntrustedEvents = aWantsUntrusted;
   return AddEventListenerByType(aListenerHolder, aType, flags);
 }
 
 void
 EventListenerManager::RemoveEventListener(
                         const nsAString& aType,
                         const EventListenerHolder& aListenerHolder,
@@ -1684,24 +1689,30 @@ EventListenerManager::TraceListeners(JST
 }
 
 bool
 EventListenerManager::HasApzAwareListeners()
 {
   uint32_t count = mListeners.Length();
   for (uint32_t i = 0; i < count; ++i) {
     Listener* listener = &mListeners.ElementAt(i);
-    if (IsApzAwareEvent(listener->mTypeAtom)) {
+    if (IsApzAwareListener(listener)) {
       return true;
     }
   }
   return false;
 }
 
 bool
+EventListenerManager::IsApzAwareListener(Listener* aListener)
+{
+  return !aListener->mFlags.mPassive && IsApzAwareEvent(aListener->mTypeAtom);
+}
+
+bool
 EventListenerManager::IsApzAwareEvent(nsIAtom* aEvent)
 {
   return aEvent == nsGkAtoms::ontouchstart ||
          aEvent == nsGkAtoms::ontouchmove ||
          aEvent == nsGkAtoms::onwheel ||
          aEvent == nsGkAtoms::onDOMMouseScroll ||
          aEvent == nsHtml5Atoms::onmousewheel ||
          aEvent == nsGkAtoms::onMozMousePixelScroll;
--- a/dom/events/EventListenerManager.h
+++ b/dom/events/EventListenerManager.h
@@ -53,41 +53,42 @@ public:
   // it's listening at bubbling phase.
   bool mCapture : 1;
   // If mInSystemGroup is true, the listener is listening to the events in the
   // system group.
   bool mInSystemGroup : 1;
   // If mAllowUntrustedEvents is true, the listener is listening to the
   // untrusted events too.
   bool mAllowUntrustedEvents : 1;
+  // If mPassive is true, the listener will not be calling preventDefault on the
+  // event. (If it does call preventDefault, we should ignore it).
+  bool mPassive : 1;
 
   EventListenerFlags() :
     mListenerIsJSListener(false),
-    mCapture(false), mInSystemGroup(false), mAllowUntrustedEvents(false)
+    mCapture(false), mInSystemGroup(false), mAllowUntrustedEvents(false),
+    mPassive(false)
   {
   }
 
-  bool Equals(const EventListenerFlags& aOther) const
+  bool EqualsForAddition(const EventListenerFlags& aOther) const
   {
     return (mCapture == aOther.mCapture &&
             mInSystemGroup == aOther.mInSystemGroup &&
             mListenerIsJSListener == aOther.mListenerIsJSListener &&
             mAllowUntrustedEvents == aOther.mAllowUntrustedEvents);
+            // Don't compare mPassive
   }
 
-  bool EqualsIgnoringTrustness(const EventListenerFlags& aOther) const
+  bool EqualsForRemoval(const EventListenerFlags& aOther) const
   {
     return (mCapture == aOther.mCapture &&
             mInSystemGroup == aOther.mInSystemGroup &&
             mListenerIsJSListener == aOther.mListenerIsJSListener);
-  }
-
-  bool operator==(const EventListenerFlags& aOther) const
-  {
-    return Equals(aOther);
+            // Don't compare mAllowUntrustedEvents or mPassive
   }
 };
 
 inline EventListenerFlags TrustedEventsAtBubble()
 {
   EventListenerFlags flags;
   return flags;
 }
@@ -440,17 +441,17 @@ public:
 
   void MarkForCC();
 
   void TraceListeners(JSTracer* aTrc);
 
   dom::EventTarget* GetTarget() { return mTarget; }
 
   bool HasApzAwareListeners();
-
+  bool IsApzAwareListener(Listener* aListener);
   bool IsApzAwareEvent(nsIAtom* aEvent);
 
 protected:
   void HandleEventInternal(nsPresContext* aPresContext,
                            WidgetEvent* aEvent,
                            nsIDOMEvent** aDOMEvent,
                            dom::EventTarget* aCurrentTarget,
                            nsEventStatus* aEventStatus);
--- a/dom/events/test/mochitest.ini
+++ b/dom/events/test/mochitest.ini
@@ -194,8 +194,9 @@ support-files =
   bug1096146_embedded.html
 [test_offsetxy.html]
 [test_eventhandler_scoping.html]
 [test_bug1013412.html]
 skip-if = buildapp == 'b2g' # no wheel events on b2g
 [test_dom_activate_event.html]
 [test_bug1264380.html]
 run-if = (e10s && os != "win") # Bug 1270043, crash at windows platforms; Bug1264380 comment 20, nsDragService::InvokeDragSessionImpl behaves differently among platform implementations in non-e10s mode which prevents us to check the validity of nsIDragService::getCurrentSession() consistently via synthesize mouse clicks in non-e10s mode.
+[test_passive_listeners.html]
new file mode 100644
--- /dev/null
+++ b/dom/events/test/test_passive_listeners.html
@@ -0,0 +1,118 @@
+<html>
+<head>
+  <title>Tests for passive event listeners</title>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+
+<body>
+<p id="display"></p>
+<div id="dummy">
+</div>
+
+<script>
+var listenerHitCount;
+var doPreventDefault;
+
+function listener(e)
+{
+  listenerHitCount++;
+  if (doPreventDefault) {
+    // When this function is registered as a passive listener, this
+    // call should be a no-op and might report a console warning.
+    e.preventDefault();
+  }
+}
+
+function listener2(e)
+{
+  if (doPreventDefault) {
+    e.preventDefault();
+  }
+}
+
+var elem = document.getElementById('dummy');
+
+function doTest(description, passiveArg)
+{
+  listenerHitCount = 0;
+
+  elem.addEventListener('test', listener, { passive: passiveArg });
+
+  // Test with a cancelable event
+  var e1 = new Event('test', { cancelable: true });
+  elem.dispatchEvent(e1);
+  is(listenerHitCount, 1, description + ' | hit count');
+  var expectedDefaultPrevented = (doPreventDefault && !passiveArg);
+  is(e1.defaultPrevented, expectedDefaultPrevented, description + ' | default prevented');
+
+  // Test with a non-cancelable event
+  var e2 = new Event('test', { cancelable: false });
+  elem.dispatchEvent(e2);
+  is(listenerHitCount, 2, description + ' | hit count after non-cancelable event');
+  is(e2.defaultPrevented, false, description + ' | default prevented on non-cancelable event');
+
+  // Test combining passive-enabled and "traditional" listeners
+  elem.addEventListener('test', listener2, false);
+  var e3 = new Event('test', { cancelable: true });
+  elem.dispatchEvent(e3);
+  is(listenerHitCount, 3, description + ' | hit count with second listener');
+  is(e3.defaultPrevented, doPreventDefault, description + ' | default prevented with second listener');
+  elem.removeEventListener('test', listener2, false);
+
+  elem.removeEventListener('test', listener, false);
+}
+
+function testAddListenerKey(passiveListenerFirst)
+{
+  listenerHitCount = 0;
+  doPreventDefault = true;
+
+  elem.addEventListener('test', listener, { capture: false, passive: passiveListenerFirst });
+  // This second listener should not be registered, because the "key" of
+  // { type, callback, capture } is the same, even though the 'passive' flag
+  // is different.
+  elem.addEventListener('test', listener, { capture: false, passive: !passiveListenerFirst });
+
+  var e1 = new Event('test', { cancelable: true });
+  elem.dispatchEvent(e1);
+
+  is(listenerHitCount, 1, 'Duplicate addEventListener was correctly ignored');
+  is(e1.defaultPrevented, !passiveListenerFirst, 'Prevent-default result based on first registered listener');
+
+  // Even though passive is the opposite of the first addEventListener call, it
+  // should remove the listener registered above.
+  elem.removeEventListener('test', listener, { capture: false, passive: !passiveListenerFirst });
+
+  var e2 = new Event('test', { cancelable: true });
+  elem.dispatchEvent(e2);
+
+  is(listenerHitCount, 1, 'non-passive listener was correctly unregistered');
+  is(e2.defaultPrevented, false, 'no listener was registered to preventDefault this event');
+}
+
+function test()
+{
+  doPreventDefault = false;
+
+  doTest('base case', undefined);
+  doTest('non-passive listener', false);
+  doTest('passive listener', true);
+
+  doPreventDefault = true;
+
+  doTest('base case', undefined);
+  doTest('non-passive listener', false);
+  doTest('passive listener', true);
+
+  testAddListenerKey(false);
+  testAddListenerKey(true);
+}
+
+test();
+
+</script>
+
+</body>
+</html>
+
+
--- a/dom/indexedDB/test/helpers.js
+++ b/dom/indexedDB/test/helpers.js
@@ -107,17 +107,24 @@ function testHarnessSteps() {
 
     let workerScriptBlob =
       new Blob([ "(" + workerScript.toString() + ")();" ],
                { type: "text/javascript;version=1.7" });
     let workerScriptURL = URL.createObjectURL(workerScriptBlob);
 
     let worker = new Worker(workerScriptURL);
 
+    worker._expectingUncaughtException = false;
     worker.onerror = function(event) {
+      if (worker._expectingUncaughtException) {
+        ok(true, "Worker had an expected error: " + event.message);
+        worker._expectingUncaughtException = false;
+        event.preventDefault();
+        return;
+      }
       ok(false, "Worker had an error: " + event.message);
       worker.terminate();
       nextTestHarnessStep();
     };
 
     worker.onmessage = function(event) {
       let message = event.data;
       switch (message.op) {
@@ -141,27 +148,36 @@ function testHarnessSteps() {
           worker.postMessage({ op: "start" });
           break;
 
         case "done":
           ok(true, "Worker finished");
           nextTestHarnessStep();
           break;
 
+        case "expectUncaughtException":
+          worker._expectingUncaughtException = message.expecting;
+          break;
+
         default:
           ok(false,
              "Received a bad message from worker: " + JSON.stringify(message));
           nextTestHarnessStep();
       }
     };
 
     URL.revokeObjectURL(workerScriptURL);
 
     yield undefined;
 
+    if (worker._expectingUncaughtException) {
+      ok(false, "expectUncaughtException was called but no uncaught " +
+                "exception was detected!");
+    }
+
     worker.terminate();
     worker = null;
 
     clearAllDatabases(nextTestHarnessStep);
     yield undefined;
   } else if (testScriptFilename) {
     todo(false,
          "Skipping test in a worker because it is explicitly disabled: " +
@@ -228,16 +244,21 @@ function continueToNextStepSync()
 }
 
 function errorHandler(event)
 {
   ok(false, "indexedDB error, '" + event.target.error.name + "'");
   finishTest();
 }
 
+function expectUncaughtException(expecting)
+{
+  SimpleTest.expectUncaughtException(expecting);
+}
+
 function browserErrorHandler(event)
 {
   browserFinishTest();
   throw new Error("indexedDB error (" + event.code + "): " + event.message);
 }
 
 function unexpectedSuccessHandler()
 {
@@ -380,16 +401,20 @@ function workerScript() {
 
   self.executeSoon = function(_fun_) {
     var channel = new MessageChannel();
     channel.port1.postMessage("");
     channel.port2.onmessage = function(event) { _fun_(); };
   };
 
   self.finishTest = function() {
+    if (self._expectingUncaughtException) {
+      self.ok(false, "expectUncaughtException was called but no uncaught "
+                     + "exception was detected!");
+    }
     self.postMessage({ op: "done" });
   };
 
   self.grabEventAndContinueHandler = function(_event_) {
     testGenerator.send(_event_);
   };
 
   self.continueToNextStep = function() {
@@ -475,17 +500,29 @@ function workerScript() {
     is(buffer.byteLength, _size_, "Correct byte length");
     let view = new Uint8Array(buffer);
     for (let i = 0; i < _size_; i++) {
       view[i] = parseInt(Math.random() * 255)
     }
     return buffer;
   };
 
+  self._expectingUncaughtException = false;
+  self.expectUncaughtException = function(_expecting_) {
+    self._expectingUncaughtException = !!_expecting_;
+    self.postMessage({ op: "expectUncaughtException", expecting: !!_expecting_ });
+  };
+
   self.onerror = function(_message_, _file_, _line_) {
+    if (self._expectingUncaughtException) {
+      self._expectingUncaughtException = false;
+      ok(true, "Worker: expected exception [" + _file_ + ":" + _line_ + "]: '" +
+         _message_ + "'");
+      return;
+    }
     ok(false,
        "Worker: uncaught exception [" + _file_ + ":" + _line_ + "]: '" +
          _message_ + "'");
     self.finishTest();
     self.close();
     return true;
   };
 
--- a/dom/indexedDB/test/mochitest.ini
+++ b/dom/indexedDB/test/mochitest.ini
@@ -87,16 +87,17 @@ support-files =
   unit/test_remove_objectStore.js
   unit/test_rename_objectStore.js
   unit/test_rename_objectStore_errors.js
   unit/test_request_readyState.js
   unit/test_setVersion.js
   unit/test_setVersion_abort.js
   unit/test_setVersion_events.js
   unit/test_setVersion_exclusion.js
+  unit/test_setVersion_throw.js
   unit/test_success_events_after_abort.js
   unit/test_table_locks.js
   unit/test_table_rollback.js
   unit/test_temporary_storage.js
   unit/test_traffic_jam.js
   unit/test_transaction_abort.js
   unit/test_transaction_abort_hang.js
   unit/test_transaction_duplicate_store_names.js
@@ -338,16 +339,18 @@ skip-if = (buildapp == 'b2g' && toolkit 
 [test_setVersion.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_setVersion_abort.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_setVersion_events.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_setVersion_exclusion.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
+[test_setVersion_throw.html]
+skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_success_events_after_abort.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_table_locks.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_table_rollback.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
 [test_third_party.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/test_setVersion_throw.html
@@ -0,0 +1,19 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Indexed Database Property Test</title>
+
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+
+  <script type="text/javascript;version=1.7" src="unit/test_setVersion_throw.js"></script>
+  <script type="text/javascript;version=1.7" src="helpers.js"></script>
+
+</head>
+
+<body onload="runTest();"></body>
+
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/indexedDB/test/unit/test_setVersion_throw.js
@@ -0,0 +1,54 @@
+/**
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+var testGenerator = testSteps();
+
+function testSteps()
+{
+  const name = this.window ? window.location.pathname : "test_setVersion_throw";
+
+  // This test requires two databases. The first needs to be a low version
+  // number that gets closed when a second higher version number database is
+  // created. Then the upgradeneeded event for the second database throws an
+  // exception and triggers an abort/close.
+
+  let request = indexedDB.open(name, 1);
+  request.onerror = errorHandler;
+  request.onsuccess = grabEventAndContinueHandler;
+  request.onupgradeneeded = function(event) {
+    info("Got upgradeneeded event for db 1");
+  };
+  let event = yield undefined;
+
+  is(event.type, "success", "Got success event for db 1");
+
+  let db = event.target.result;
+  db.onversionchange = function(event) {
+    info("Got versionchange event for db 1");
+    event.target.close();
+  }
+
+  executeSoon(continueToNextStepSync);
+  yield undefined;
+
+  request = indexedDB.open(name, 2);
+  request.onerror = grabEventAndContinueHandler;
+  request.onsuccess = unexpectedSuccessHandler;
+  request.onupgradeneeded = function(event) {
+    info("Got upgradeneeded event for db 2");
+    expectUncaughtException(true);
+    trigger_js_exception_by_calling_a_nonexistent_function();
+  };
+  event = yield undefined;
+
+  event.preventDefault();
+
+  is(event.type, "error", "Got an error event for db 2");
+  ok(event.target.error instanceof DOMError, "Request has a DOMError");
+  is(event.target.error.name, "AbortError", "Request has AbortError");
+
+  finishTest();
+  yield undefined;
+}
--- a/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
+++ b/dom/indexedDB/test/unit/xpcshell-head-parent-process.js
@@ -111,16 +111,21 @@ function expectedErrorHandler(name)
   return function(event) {
     do_check_eq(event.type, "error");
     do_check_eq(event.target.error.name, name);
     event.preventDefault();
     grabEventAndContinueHandler(event);
   };
 }
 
+function expectUncaughtException(expecting)
+{
+  // This is dummy for xpcshell test.
+}
+
 function ExpectError(name)
 {
   this._name = name;
 }
 ExpectError.prototype = {
   handleEvent: function(event)
   {
     do_check_eq(event.type, "error");
--- a/dom/indexedDB/test/unit/xpcshell-shared.ini
+++ b/dom/indexedDB/test/unit/xpcshell-shared.ini
@@ -71,16 +71,17 @@ skip-if = toolkit == 'android' # bug 864
 [test_rename_objectStore.js]
 [test_rename_objectStore_errors.js]
 [test_request_readyState.js]
 [test_sandbox.js]
 [test_setVersion.js]
 [test_setVersion_abort.js]
 [test_setVersion_events.js]
 [test_setVersion_exclusion.js]
+[test_setVersion_throw.js]
 [test_success_events_after_abort.js]
 [test_table_locks.js]
 [test_table_rollback.js]
 [test_traffic_jam.js]
 [test_transaction_abort.js]
 [test_transaction_abort_hang.js]
 [test_transaction_duplicate_store_names.js]
 [test_transaction_error.js]
--- a/dom/ipc/ContentBridgeChild.cpp
+++ b/dom/ipc/ContentBridgeChild.cpp
@@ -6,16 +6,17 @@
 
 #include "mozilla/dom/ContentBridgeChild.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/TabChild.h"
 #include "mozilla/dom/ipc/BlobChild.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/ipc/InputStreamUtils.h"
+#include "base/task.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::jsipc;
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ISUPPORTS(ContentBridgeChild,
--- a/dom/ipc/ContentBridgeParent.cpp
+++ b/dom/ipc/ContentBridgeParent.cpp
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ContentBridgeParent.h"
 #include "mozilla/dom/TabParent.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "nsXULAppAPI.h"
 #include "nsIObserverService.h"
+#include "base/task.h"
 
 using namespace mozilla::ipc;
 using namespace mozilla::jsipc;
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_ISUPPORTS(ContentBridgeParent,
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -219,8 +219,10 @@ PatternAttributeCompileFailure=Unable to
 # LOCALIZATION NOTE: Do not translate "postMessage" or DOMWindow. %S values are origins, like https://domain.com:port
 TargetPrincipalDoesNotMatch=Failed to execute ‘postMessage’ on ‘DOMWindow’: The target origin provided (‘%S’) does not match the recipient window’s origin (‘%S’).
 # LOCALIZATION NOTE: Do not translate 'youtube'. %S values are origins, like https://domain.com:port
 RewriteYoutubeEmbed=Rewriting old-style Youtube Flash embed (%S) to iframe embed (%S). Please update page to use iframe instead of embed/object, if possible.
 # LOCALIZATION NOTE: Do not translate 'youtube'. %S values are origins, like https://domain.com:port
 RewriteYoutubeEmbedInvalidQuery=Rewriting old-style Youtube Flash embed (%S) to iframe embed (%S). Query was invalid and removed from URL. Please update page to use iframe instead of embed/object, if possible.
 # LOCALIZATION NOTE: Do not translate "ServiceWorker". %1$S is the ServiceWorker scope URL. %2$S is an error string.
 PushMessageDecryptionFailure=The ServiceWorker for scope ‘%1$S’ encountered an error decrypting a push message: ‘%2$S’. For help with encryption, please see https://developer.mozilla.org/en-US/docs/Web/API/Push_API/Using_the_Push_API#Encryption
+# LOCALIZATION NOTE: %1$S is the type of a DOM event. 'passive' is a literal parameter from the DOM spec.
+PreventDefaultFromPassiveListenerWarning=Ignoring ‘preventDefault()’ call on event of type ‘%1$S’ from a listener registered as ‘passive’.
--- a/dom/media/DecoderTraits.cpp
+++ b/dom/media/DecoderTraits.cpp
@@ -173,16 +173,17 @@ DecoderTraits::IsWebMAudioType(const nsA
   return aType.EqualsASCII("audio/webm");
 }
 
 static char const *const gHttpLiveStreamingTypes[] = {
   // For m3u8.
   // https://tools.ietf.org/html/draft-pantos-http-live-streaming-19#section-10
   "application/vnd.apple.mpegurl",
   // Some sites serve these as the informal m3u type.
+  "application/x-mpegurl",
   "audio/x-mpegurl",
   nullptr
 };
 
 static bool
 IsHttpLiveStreamingType(const nsACString& aType)
 {
   return CodecListContains(gHttpLiveStreamingTypes, aType);
--- a/dom/media/MP3Decoder.cpp
+++ b/dom/media/MP3Decoder.cpp
@@ -4,17 +4,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MP3Decoder.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaFormatReader.h"
 #include "MP3Demuxer.h"
-#include "mozilla/Preferences.h"
 #include "PDMFactory.h"
 
 namespace mozilla {
 
 MediaDecoder*
 MP3Decoder::Clone(MediaDecoderOwner* aOwner) {
   if (!IsEnabled()) {
     return nullptr;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -365,25 +365,35 @@ MediaDecoderStateMachine::Initialization
   mWatchManager.Watch(mObservedDuration, &MediaDecoderStateMachine::RecomputeDuration);
   mWatchManager.Watch(mPlayState, &MediaDecoderStateMachine::PlayStateChanged);
   mWatchManager.Watch(mIsVisible, &MediaDecoderStateMachine::VisibilityChanged);
 
   // Configure MediaDecoderReaderWrapper.
   SetMediaDecoderReaderWrapperCallback();
 }
 
+void
+MediaDecoderStateMachine::AudioAudibleChanged(bool aAudible)
+{
+  mIsAudioDataAudible = aAudible;
+}
+
 media::MediaSink*
 MediaDecoderStateMachine::CreateAudioSink()
 {
   RefPtr<MediaDecoderStateMachine> self = this;
   auto audioSinkCreator = [self] () {
     MOZ_ASSERT(self->OnTaskQueue());
-    return new DecodedAudioDataSink(
+    DecodedAudioDataSink* audioSink = new DecodedAudioDataSink(
       self->mTaskQueue, self->mAudioQueue, self->GetMediaTime(),
       self->mInfo.mAudio, self->mAudioChannel);
+
+    self->mAudibleListener = audioSink->AudibleEvent().Connect(
+      self->mTaskQueue, self.get(), &MediaDecoderStateMachine::AudioAudibleChanged);
+    return audioSink;
   };
   return new AudioSinkWrapper(mTaskQueue, audioSinkCreator);
 }
 
 already_AddRefed<media::MediaSink>
 MediaDecoderStateMachine::CreateMediaSink(bool aAudioCaptured)
 {
   RefPtr<media::MediaSink> audioSink = aAudioCaptured
@@ -636,39 +646,23 @@ MediaDecoderStateMachine::Push(MediaData
   } else {
     // TODO: Handle MediaRawData, determine which queue should be pushed.
   }
   UpdateNextFrameStatus();
   DispatchDecodeTasksIfNeeded();
 }
 
 void
-MediaDecoderStateMachine::CheckIsAudible(const MediaData* aSample)
-{
-  MOZ_ASSERT(OnTaskQueue());
-  MOZ_ASSERT(aSample->mType == MediaData::AUDIO_DATA);
-
-  const AudioData* data = aSample->As<AudioData>();
-  bool isAudible = data->IsAudible();
-  if (isAudible && !mIsAudioDataAudible) {
-    mIsAudioDataAudible = true;
-  } else if (!isAudible && mIsAudioDataAudible) {
-    mIsAudioDataAudible = false;
-  }
-}
-
-void
 MediaDecoderStateMachine::OnAudioPopped(const RefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
 
   mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   UpdateNextFrameStatus();
   DispatchAudioDecodeTaskIfNeeded();
-  CheckIsAudible(aSample);
 }
 
 void
 MediaDecoderStateMachine::OnVideoPopped(const RefPtr<MediaData>& aSample)
 {
   MOZ_ASSERT(OnTaskQueue());
   mPlaybackOffset = std::max(mPlaybackOffset.Ref(), aSample->mOffset);
   UpdateNextFrameStatus();
@@ -1492,16 +1486,18 @@ MediaDecoderStateMachine::InvokeSeek(See
                      &MediaDecoderStateMachine::Seek, aTarget);
 }
 
 void MediaDecoderStateMachine::StopMediaSink()
 {
   MOZ_ASSERT(OnTaskQueue());
   if (mMediaSink->IsStarted()) {
     DECODER_LOG("Stop MediaSink");
+    mAudibleListener.DisconnectIfExists();
+
     mMediaSink->Stop();
     mMediaSinkAudioPromise.DisconnectIfExists();
     mMediaSinkVideoPromise.DisconnectIfExists();
   }
 }
 
 void
 MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -380,17 +380,18 @@ protected:
   // Inserts MediaData* samples into their respective MediaQueues.
   // aSample must not be null.
 
   void Push(MediaData* aSample, MediaData::Type aSampleType);
 
   void OnAudioPopped(const RefPtr<MediaData>& aSample);
   void OnVideoPopped(const RefPtr<MediaData>& aSample);
 
-  void CheckIsAudible(const MediaData* aSample);
+  void AudioAudibleChanged(bool aAudible);
+
   void VolumeChanged();
   void LogicalPlaybackRateChanged();
   void PreservesPitchChanged();
 
   MediaQueue<MediaData>& AudioQueue() { return mAudioQueue; }
   MediaQueue<MediaData>& VideoQueue() { return mVideoQueue; }
 
   // True if our buffers of decoded audio are not full, and we should
@@ -936,16 +937,17 @@ private:
   RefPtr<MediaResource> mResource;
 
   // Track the complete & error for audio/video separately
   MozPromiseRequestHolder<GenericPromise> mMediaSinkAudioPromise;
   MozPromiseRequestHolder<GenericPromise> mMediaSinkVideoPromise;
 
   MediaEventListener mAudioQueueListener;
   MediaEventListener mVideoQueueListener;
+  MediaEventListener mAudibleListener;
 
   MediaEventProducerExc<nsAutoPtr<MediaInfo>,
                         nsAutoPtr<MetadataTags>,
                         MediaDecoderEventVisibility> mMetadataLoadedEvent;
   MediaEventProducerExc<nsAutoPtr<MediaInfo>,
                         MediaDecoderEventVisibility> mFirstFrameLoadedEvent;
 
   MediaEventProducer<MediaEventType> mOnPlaybackEvent;
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -163,37 +163,29 @@ MediaFormatReader::InitLayersBackendType
 
   RefPtr<LayerManager> layerManager =
     nsContentUtils::LayerManagerForDocument(element->OwnerDoc());
   NS_ENSURE_TRUE_VOID(layerManager);
 
   mLayersBackendType = layerManager->GetCompositorBackendType();
 }
 
-static bool sIsEMEEnabled = false;
-
 nsresult
 MediaFormatReader::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
   PDMFactory::Init();
 
   InitLayersBackendType();
 
   mAudio.mTaskQueue =
     new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
   mVideo.mTaskQueue =
     new FlushableTaskQueue(GetMediaThreadPool(MediaThreadType::PLATFORM_DECODER));
 
-  static bool sSetupPrefCache = false;
-  if (!sSetupPrefCache) {
-    sSetupPrefCache = true;
-    Preferences::AddBoolVarCache(&sIsEMEEnabled, "media.eme.enabled", false);
-  }
-
   return NS_OK;
 }
 
 #ifdef MOZ_EME
 class DispatchKeyNeededEvent : public Runnable {
 public:
   DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder,
                          nsTArray<uint8_t>& aInitData,
@@ -271,47 +263,68 @@ MediaFormatReader::OnDemuxerInitDone(nsr
 {
   MOZ_ASSERT(OnTaskQueue());
   mDemuxerInitRequest.Complete();
 
   mDemuxerInitDone = true;
 
   UniquePtr<MetadataTags> tags(MakeUnique<MetadataTags>());
 
+  RefPtr<PDMFactory> platform;
+  if (!IsWaitingOnCDMResource()) {
+    platform = new PDMFactory();
+  }
+
   // To decode, we need valid video and a place to put it.
   bool videoActive = !!mDemuxer->GetNumberTracks(TrackInfo::kVideoTrack) &&
     GetImageContainer();
 
   if (videoActive) {
     // We currently only handle the first video track.
     mVideo.mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
     if (!mVideo.mTrackDemuxer) {
       mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
       return;
     }
-    mInfo.mVideo = *mVideo.mTrackDemuxer->GetInfo()->GetAsVideoInfo();
-    UniquePtr<TrackInfo> info(mVideo.mTrackDemuxer->GetInfo());
-    for (const MetadataTag& tag : info->mTags) {
-      tags->Put(tag.mKey, tag.mValue);
+
+    UniquePtr<TrackInfo> videoInfo = mVideo.mTrackDemuxer->GetInfo();
+    videoActive = videoInfo && videoInfo->IsValid();
+    if (videoActive) {
+      if (platform && !platform->SupportsMimeType(videoInfo->mMimeType, nullptr)) {
+        // We have no decoder for this track. Error.
+        mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
+        return;
+      }
+      mInfo.mVideo = *videoInfo->GetAsVideoInfo();
+      for (const MetadataTag& tag : videoInfo->mTags) {
+        tags->Put(tag.mKey, tag.mValue);
+      }
+      mVideo.mCallback = new DecoderCallback(this, TrackInfo::kVideoTrack);
+      mVideo.mTimeRanges = mVideo.mTrackDemuxer->GetBuffered();
+      mTrackDemuxersMayBlock |= mVideo.mTrackDemuxer->GetSamplesMayBlock();
+    } else {
+      mVideo.mTrackDemuxer->BreakCycles();
+      mVideo.mTrackDemuxer = nullptr;
     }
-    mVideo.mCallback = new DecoderCallback(this, TrackInfo::kVideoTrack);
-    mVideo.mTimeRanges = mVideo.mTrackDemuxer->GetBuffered();
-    mTrackDemuxersMayBlock |= mVideo.mTrackDemuxer->GetSamplesMayBlock();
   }
 
   bool audioActive = !!mDemuxer->GetNumberTracks(TrackInfo::kAudioTrack);
   if (audioActive) {
     mAudio.mTrackDemuxer = mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
     if (!mAudio.mTrackDemuxer) {
       mMetadataPromise.Reject(ReadMetadataFailureReason::METADATA_ERROR, __func__);
       return;
     }
+
     UniquePtr<TrackInfo> audioInfo = mAudio.mTrackDemuxer->GetInfo();
     // We actively ignore audio tracks that we know we can't play.
-    audioActive = audioInfo && audioInfo->IsValid();
+    audioActive = audioInfo && audioInfo->IsValid() &&
+                  (!platform ||
+                   platform->SupportsMimeType(audioInfo->mMimeType, nullptr));
+
     if (audioActive) {
       mInfo.mAudio = *audioInfo->GetAsAudioInfo();
       for (const MetadataTag& tag : audioInfo->mTags) {
         tags->Put(tag.mKey, tag.mValue);
       }
       mAudio.mCallback = new DecoderCallback(this, TrackInfo::kAudioTrack);
       mAudio.mTimeRanges = mAudio.mTrackDemuxer->GetBuffered();
       mTrackDemuxersMayBlock |= mAudio.mTrackDemuxer->GetSamplesMayBlock();
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -38,17 +38,16 @@
 #include "mozilla/Types.h"
 #include "mozilla/PeerIdentity.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/MediaStreamBinding.h"
 #include "mozilla/dom/MediaStreamTrackBinding.h"
 #include "mozilla/dom/GetUserMediaRequestBinding.h"
 #include "mozilla/dom/Promise.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/Base64.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/media/MediaChild.h"
 #include "MediaTrackConstraints.h"
 #include "VideoUtils.h"
 #include "Latency.h"
 #include "nsProxyRelease.h"
 #include "nsNullPrincipal.h"
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaPrefs.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MediaPrefs.h"
+
+#include "mozilla/ClearOnShutdown.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/StaticPtr.h"
+#include "MainThreadUtils.h"
+
+namespace mozilla {
+
+StaticAutoPtr<MediaPrefs> MediaPrefs::sInstance;
+
+MediaPrefs&
+MediaPrefs::GetSingleton()
+{
+  if (!sInstance) {
+    sInstance = new MediaPrefs;
+    ClearOnShutdown(&sInstance);
+  }
+  MOZ_ASSERT(SingletonExists());
+  return *sInstance;
+}
+
+bool
+MediaPrefs::SingletonExists()
+{
+  return sInstance != nullptr;
+}
+
+MediaPrefs::MediaPrefs()
+{
+  MediaPrefs::AssertMainThread();
+}
+
+void MediaPrefs::AssertMainThread()
+{
+  MOZ_ASSERT(NS_IsMainThread(), "this code must be run on the main thread");
+}
+
+void MediaPrefs::PrefAddVarCache(bool* aVariable,
+                                 const char* aPref,
+                                 bool aDefault)
+{
+  Preferences::AddBoolVarCache(aVariable, aPref, aDefault);
+}
+
+void MediaPrefs::PrefAddVarCache(int32_t* aVariable,
+                                 const char* aPref,
+                                 int32_t aDefault)
+{
+  Preferences::AddIntVarCache(aVariable, aPref, aDefault);
+}
+
+void MediaPrefs::PrefAddVarCache(uint32_t* aVariable,
+                                 const char* aPref,
+                                 uint32_t aDefault)
+{
+  Preferences::AddUintVarCache(aVariable, aPref, aDefault);
+}
+
+void MediaPrefs::PrefAddVarCache(float* aVariable,
+                                 const char* aPref,
+                                 float aDefault)
+{
+  Preferences::AddFloatVarCache(aVariable, aPref, aDefault);
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/media/MediaPrefs.h
@@ -0,0 +1,142 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef MEDIA_PREFS_H
+#define MEDIA_PREFS_H
+
+// First time MediaPrefs::GetSingleton() needs to be called on the main thread,
+// before any of the methods accessing the values are used, but after
+// the Preferences system has been initialized.
+
+// The static methods to access the preference value are safe to call
+// from any thread after that first call.
+
+// To register a preference, you need to add a line in this file using
+// the DECL_MEDIA_PREF macro.
+//
+// For example this line in the .h:
+//   DECL_MEDIA_PREF("media.resampling.enabled",AudioSinkResampling,bool,false);
+// means that you can call
+//   const bool& var = MediaPrefs::AudioSinkResampling();
+// from any thread, you will get the most up to date preference value of
+// "media.resampling.enabled".  If the value is not set, the default would be
+// false.
+
+#define DECL_MEDIA_PREF(Pref, Name, Type, Default)                            \
+public:                                                                       \
+static const Type& Name() { MOZ_ASSERT(SingletonExists()); return GetSingleton().mPref##Name.mValue; } \
+private:                                                                      \
+static const char* Get##Name##PrefName() { return Pref; }                     \
+static Type Get##Name##PrefDefault() { return Default; }                      \
+PrefTemplate<Type, Get##Name##PrefDefault, Get##Name##PrefName> mPref##Name
+
+// Custom Definitions.
+#define GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT 3000
+#define TEST_PREFERENCE_FAKE_RECOGNITION_SERVICE "media.webspeech.test.fake_recognition_service"
+
+namespace mozilla {
+
+template<class T> class StaticAutoPtr;
+
+class MediaPrefs final
+{
+
+private:
+  // Since we cannot use const char*, use a function that returns it.
+  template <class T, T Default(), const char* Pref()>
+  class PrefTemplate
+  {
+  public:
+    PrefTemplate()
+    : mValue(Default())
+    {
+      Register(Pref());
+    }
+    T mValue;
+  private:
+    void Register(const char* aPreference)
+    {
+      AssertMainThread();
+      PrefAddVarCache(&mValue, aPreference, mValue);
+    }
+  };
+
+  // This is where DECL_MEDIA_PREF for each of the preferences should go.
+
+  // AudioSink
+  DECL_MEDIA_PREF("accessibility.monoaudio.enable",           MonoAudio, bool, false);
+  DECL_MEDIA_PREF("media.resampling.enabled",                 AudioSinkResampling, bool, false);
+  DECL_MEDIA_PREF("media.resampling.rate",                    AudioSinkResampleRate, uint32_t, 48000);
+  DECL_MEDIA_PREF("media.forcestereo.enabled",                AudioSinkForceStereo, bool, true);
+
+  // PlatformDecoderModule
+  DECL_MEDIA_PREF("media.apple.forcevda",                     AppleForceVDA, bool, false);
+  DECL_MEDIA_PREF("media.gmp.insecure.allow",                 GMPAllowInsecure, bool, false);
+  DECL_MEDIA_PREF("media.gmp.async-shutdown-timeout",         GMPAsyncShutdownTimeout, uint32_t, GMP_DEFAULT_ASYNC_SHUTDOWN_TIMEOUT);
+  DECL_MEDIA_PREF("media.eme.enabled",                        EMEEnabled, bool, false);
+  DECL_MEDIA_PREF("media.use-blank-decoder",                  PDMUseBlankDecoder, bool, false);
+#ifdef MOZ_GONK_MEDIACODEC
+  DECL_MEDIA_PREF("media.gonk.enabled",                       PDMGonkDecoderEnabled, bool, true);
+#endif
+#ifdef MOZ_WIDGET_ANDROID
+  DECL_MEDIA_PREF("media.android-media-codec.enabled",        PDMAndroidMediaCodecEnabled, bool, false);
+  DECL_MEDIA_PREF("media.android-media-codec.preferred",      PDMAndroidMediaCodecPreferred, bool, false);
+#endif
+#ifdef MOZ_FFMPEG
+  DECL_MEDIA_PREF("media.ffmpeg.enabled",                     PDMFFmpegEnabled, bool, true);
+#endif
+#ifdef MOZ_FFVPX
+  DECL_MEDIA_PREF("media.ffvpx.enabled",                      PDMFFVPXEnabled, bool, true);
+#endif
+#ifdef XP_WIN
+  DECL_MEDIA_PREF("media.wmf.enabled",                        PDMWMFEnabled, bool, true);
+  DECL_MEDIA_PREF("media.webm.intel_decoder.enabled",         PDMWMFIntelDecoderEnabled, bool, false);
+  DECL_MEDIA_PREF("media.wmf.low-latency.enabled",            PDMWMFLowLatencyEnabled, bool, false);
+  DECL_MEDIA_PREF("media.wmf.decoder.thread-count",           PDMWMFThreadCount, int32_t, -1);
+#endif
+  DECL_MEDIA_PREF("media.decoder.fuzzing.enabled",            PDMFuzzingEnabled, bool, false);
+  DECL_MEDIA_PREF("media.decoder.fuzzing.video-output-minimum-interval-ms", PDMFuzzingInterval, uint32_t, 0);
+  DECL_MEDIA_PREF("media.decoder.fuzzing.dont-delay-inputexhausted", PDMFuzzingDelayInputExhausted, bool, true);
+  DECL_MEDIA_PREF("media.gmp.decoder.enabled",                PDMGMPEnabled, bool, true);
+  DECL_MEDIA_PREF("media.gmp.decoder.aac",                    GMPAACPreferred, uint32_t, 0);
+  DECL_MEDIA_PREF("media.gmp.decoder.h264",                   GMPH264Preferred, uint32_t, 0);
+
+  // WebSpeech
+  DECL_MEDIA_PREF("media.webspeech.synth.force_global_queue", WebSpeechForceGlobal, bool, false);
+  DECL_MEDIA_PREF("media.webspeech.test.enable",              WebSpeechTestEnabled, bool, false);
+  DECL_MEDIA_PREF("media.webspeech.test.fake_fsm_events",     WebSpeechFakeFSMEvents, bool, false);
+  DECL_MEDIA_PREF(TEST_PREFERENCE_FAKE_RECOGNITION_SERVICE,   WebSpeechFakeRecognitionService, bool, false);
+  DECL_MEDIA_PREF("media.webspeech.recognition.enable",       WebSpeechRecognitionEnabled, bool, false);
+  DECL_MEDIA_PREF("media.webspeech.recognition.force_enable", WebSpeechRecognitionForceEnabled, bool, false);
+
+  DECL_MEDIA_PREF("media.num-decode-threads",                 MediaThreadPoolDefaultCount, uint32_t, 4);
+
+public:
+  // Manage the singleton:
+  static MediaPrefs& GetSingleton();
+  static bool SingletonExists();
+
+private:
+  template<class T> friend class StaticAutoPtr;
+  static StaticAutoPtr<MediaPrefs> sInstance;
+
+  // Creating these to avoid having to include Preferences.h in the .h
+  static void PrefAddVarCache(bool*, const char*, bool);
+  static void PrefAddVarCache(int32_t*, const char*, int32_t);
+  static void PrefAddVarCache(uint32_t*, const char*, uint32_t);
+  static void PrefAddVarCache(float*, const char*, float);
+
+  static void AssertMainThread();
+
+  MediaPrefs();
+  MediaPrefs(const MediaPrefs&) = delete;
+  MediaPrefs& operator=(const MediaPrefs&) = delete;
+};
+
+#undef DECL_MEDIA_PREF /* Don't need it outside of this file */
+
+} // namespace mozilla
+
+#endif /* MEDIA_PREFS_H */
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -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/. */
 
 #include "VideoUtils.h"
 
-#include "mozilla/Preferences.h"
 #include "mozilla/Base64.h"
 #include "mozilla/TaskQueue.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/Function.h"
 
+#include "MediaPrefs.h"
 #include "MediaResource.h"
 #include "TimeUnits.h"
 #include "nsMathUtils.h"
 #include "nsSize.h"
 #include "VorbisUtils.h"
 #include "ImageContainer.h"
 #include "mozilla/SharedThreadPool.h"
 #include "nsIRandomGenerator.h"
@@ -199,18 +199,17 @@ already_AddRefed<SharedThreadPool> GetMe
       break;
     default:
       MOZ_FALLTHROUGH_ASSERT("Unexpected MediaThreadType");
     case MediaThreadType::PLAYBACK:
       name = "MediaPlayback";
       break;
   }
   return SharedThreadPool::
-    Get(nsDependentCString(name),
-        Preferences::GetUint("media.num-decode-threads", 4));
+    Get(nsDependentCString(name), MediaPrefs::MediaThreadPoolDefaultCount());
 }
 
 bool
 ExtractH264CodecDetails(const nsAString& aCodec,
                         int16_t& aProfile,
                         int16_t& aLevel)
 {
   // H.264 codecs parameters have a type defined as avcN.PPCCLL, where
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/MediaKeySystemAccess.h"
 #include "mozilla/dom/MediaKeySystemAccessBinding.h"
 #include "mozilla/Preferences.h"
+#include "MediaPrefs.h"
 #include "nsContentTypeParser.h"
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
 #endif
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
 #include "WMFDecoderModule.h"
 #endif
@@ -256,17 +257,17 @@ EnsureMinCDMVersion(mozIGeckoMediaPlugin
 
 /* static */
 MediaKeySystemStatus
 MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
                                          int32_t aMinCdmVersion,
                                          nsACString& aOutMessage,
                                          nsACString& aOutCdmVersion)
 {
-  MOZ_ASSERT(Preferences::GetBool("media.eme.enabled", false));
+  MOZ_ASSERT(MediaPrefs::EMEEnabled());
   nsCOMPtr<mozIGeckoMediaPluginService> mps =
     do_GetService("@mozilla.org/gecko-media-plugin-service;1");
   if (NS_WARN_IF(!mps)) {
     aOutMessage = NS_LITERAL_CSTRING("Failed to get GMP service");
     return MediaKeySystemStatus::Error;
   }
 
   if (aKeySystem.EqualsLiteral("org.w3.clearkey")) {
@@ -281,36 +282,42 @@ MediaKeySystemAccess::GetKeySystemStatus
   if (aKeySystem.EqualsLiteral("com.adobe.primetime")) {
     if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
       aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled");
       return MediaKeySystemStatus::Cdm_disabled;
     }
 #ifdef XP_WIN
     // Win Vista and later only.
     if (!IsVistaOrLater()) {
-      aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version not met for Adobe EME");
+      aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Adobe EME");
       return MediaKeySystemStatus::Cdm_not_supported;
     }
 #endif
 #ifdef XP_MACOSX
     if (!nsCocoaFeatures::OnLionOrLater()) {
-      aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version not met for Adobe EME");
+      aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Adobe EME");
       return MediaKeySystemStatus::Cdm_not_supported;
     }
 #endif
     return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion);
   }
 #endif
 
 #ifdef MOZ_WIDEVINE_EME
   if (aKeySystem.EqualsLiteral("com.widevine.alpha")) {
 #ifdef XP_WIN
     // Win Vista and later only.
     if (!IsVistaOrLater()) {
-      aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version not met for Widevine EME");
+      aOutMessage = NS_LITERAL_CSTRING("Minimum Windows version (Vista) not met for Widevine EME");
+      return MediaKeySystemStatus::Cdm_not_supported;
+    }
+#endif
+#ifdef XP_MACOSX
+    if (!nsCocoaFeatures::OnLionOrLater()) {
+      aOutMessage = NS_LITERAL_CSTRING("Minimum MacOSX version (10.7) not met for Widevine EME");
       return MediaKeySystemStatus::Cdm_not_supported;
     }
 #endif
     if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) {
       aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled");
       return MediaKeySystemStatus::Cdm_disabled;
     }
     return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion);
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -1,15 +1,15 @@
 /* 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 "MediaKeySystemAccessManager.h"
 #include "DecoderDoctorDiagnostics.h"
-#include "mozilla/Preferences.h"
+#include "MediaPrefs.h"
 #include "mozilla/EMEUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsComponentManagerUtils.h"
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/DetailedPromise.h"
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
@@ -92,17 +92,17 @@ MediaKeySystemAccessManager::Request(Det
     aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
                           NS_LITERAL_CSTRING("Key system string is invalid,"
                                              " or key system is unsupported"));
     diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(),
                                           aKeySystem, false, __func__);
     return;
   }
 
-  if (!Preferences::GetBool("media.eme.enabled", false)) {
+  if (!MediaPrefs::EMEEnabled()) {
     // EME disabled by user, send notification to chrome so UI can inform user.
     MediaKeySystemAccess::NotifyObservers(mWindow,
                                           aKeySystem,
                                           MediaKeySystemStatus::Api_disabled);
     aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR,
                           NS_LITERAL_CSTRING("EME has been preffed off"));
     diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(),
                                           aKeySystem, false, __func__);
--- a/dom/media/eme/MediaKeys.cpp
+++ b/dom/media/eme/MediaKeys.cpp
@@ -12,17 +12,16 @@
 #include "mozilla/dom/MediaKeyError.h"
 #include "mozilla/dom/MediaKeySession.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/CDMProxy.h"
 #include "mozilla/EMEUtils.h"
 #include "nsContentUtils.h"
 #include "nsIScriptObjectPrincipal.h"
-#include "mozilla/Preferences.h"
 #include "nsContentTypeParser.h"
 #ifdef MOZ_FMP4
 #include "MP4Decoder.h"
 #endif
 #ifdef XP_WIN
 #include "mozilla/WindowsVersion.h"
 #endif
 #include "nsContentCID.h"
--- a/dom/media/gmp/GMPChild.cpp
+++ b/dom/media/gmp/GMPChild.cpp
@@ -17,16 +17,17 @@
 #include "nsXULAppAPI.h"
 #include "gmp-video-decode.h"
 #include "gmp-video-encode.h"
 #include "GMPPlatform.h"
 #include "mozilla/dom/CrashReporterChild.h"
 #include "mozilla/ipc/ProcessChild.h"
 #include "GMPUtils.h"
 #include "prio.h"
+#include "base/task.h"
 #ifdef MOZ_WIDEVINE_EME
 #include "widevine-adapter/WidevineAdapter.h"
 #endif
 
 using namespace mozilla::ipc;
 using mozilla::dom::CrashReporterChild;
 
 static const int MAX_VOUCHER_LENGTH = 500000;
--- a/dom/media/gmp/GMPContentChild.cpp
+++ b/dom/media/gmp/GMPContentChild.cpp
@@ -4,16 +4,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPContentChild.h"
 #include "GMPChild.h"
 #include "GMPAudioDecoderChild.h"
 #include "GMPDecryptorChild.h"
 #include "GMPVideoDecoderChild.h"
 #include "GMPVideoEncoderChild.h"
+#include "base/task.h"
 
 namespace mozilla {
 namespace gmp {
 
 GMPContentChild::GMPContentChild(GMPChild* aChild)
   : mGMPChild(aChild)
 {
   MOZ_COUNT_CTOR(GMPContentChild);
--- a/dom/media/gmp/GMPContentParent.cpp
+++ b/dom/media/gmp/GMPContentParent.cpp
@@ -8,16 +8,17 @@
 #include "GMPDecryptorParent.h"
 #include "GMPParent.h"
 #include "GMPServiceChild.h"
 #include "GMPVideoDecoderParent.h"
 #include "GMPVideoEncoderParent.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "mozilla/Logging.h"
 #include "mozilla/unused.h"
+#include "base/task.h"
 
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
 
 extern LogModule* GetGMPLog();
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPDecryptorChild.h"
 #include "GMPContentChild.h"
 #include "GMPChild.h"
+#include "base/task.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/unused.h"
 #include "runnable_utils.h"
 #include <ctime>
 
 #define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current())
 
 #define CALL_ON_GMP_THREAD(_func, ...) \
--- a/dom/media/gmp/GMPParent.cpp
+++ b/dom/media/gmp/GMPParent.cpp
@@ -17,16 +17,17 @@
 #include "mozilla/unused.h"
 #include "nsIObserverService.h"
 #include "GMPTimerParent.h"
 #include "runnable_utils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 #include "mozilla/SandboxInfo.h"
 #endif
 #include "GMPContentParent.h"
+#include "MediaPrefs.h"
 
 #include "mozilla/dom/CrashReporterParent.h"
 using mozilla::dom::CrashReporterParent;
 using mozilla::ipc::GeckoChildProcessHost;
 
 #ifdef MOZ_CRASHREPORTER
 #include "nsPrintfCString.h"
 using CrashReporter::AnnotationTable;
@@ -247,17 +248,17 @@ GMPParent::EnsureAsyncShutdownTimeoutSet
 
   // Set timer to abort waiting for plugin to shutdown if it takes
   // too long.
   rv = mAsyncShutdownTimeout->SetTarget(mGMPThread);
   if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
   }
 
-  int32_t timeout = GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT;
+  int32_t timeout = MediaPrefs::GMPAsyncShutdownTimeout();
   RefPtr<GeckoMediaPluginServiceParent> service =
     GeckoMediaPluginServiceParent::GetSingleton();
   if (service) {
     timeout = service->AsyncShutdownTimeoutMs();
   }
   rv = mAsyncShutdownTimeout->InitWithFuncCallback(
     &AbortWaitingForGMPAsyncShutdown, this, timeout,
     nsITimer::TYPE_ONE_SHOT);
--- a/dom/media/gmp/GMPService.cpp
+++ b/dom/media/gmp/GMPService.cpp
@@ -8,28 +8,26 @@
 #include "GMPServiceChild.h"
 #include "GMPContentParent.h"
 #include "prio.h"
 #include "mozilla/Logging.h"
 #include "GMPParent.h"
 #include "GMPVideoDecoderParent.h"
 #include "nsIObserverService.h"
 #include "GeckoChildProcessHost.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/SyncRunnable.h"
 #include "nsXPCOMPrivate.h"
 #include "mozilla/Services.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIConsoleService.h"
 #include "mozilla/unused.h"
 #include "GMPDecryptorParent.h"
 #include "GMPAudioDecoderParent.h"
 #include "nsComponentManagerUtils.h"
-#include "mozilla/Preferences.h"
 #include "runnable_utils.h"
 #include "VideoUtils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 #include "mozilla/SandboxInfo.h"
 #endif
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
--- a/dom/media/gmp/GMPService.h
+++ b/dom/media/gmp/GMPService.h
@@ -26,18 +26,16 @@ template <class> struct already_AddRefed
 namespace mozilla {
 
 extern LogModule* GetGMPLog();
 
 namespace gmp {
 
 class GetGMPContentParentCallback;
 
-#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
-
 class GeckoMediaPluginService : public mozIGeckoMediaPluginService
                               , public nsIObserver
 {
 public:
   static already_AddRefed<GeckoMediaPluginService> GetGeckoMediaPluginService();
 
   virtual nsresult Init();
 
--- a/dom/media/gmp/GMPServiceChild.cpp
+++ b/dom/media/gmp/GMPServiceChild.cpp
@@ -8,16 +8,17 @@
 #include "mozIGeckoMediaPluginService.h"
 #include "mozIGeckoMediaPluginChromeService.h"
 #include "nsCOMPtr.h"
 #include "GMPParent.h"
 #include "GMPContentParent.h"
 #include "nsXPCOMPrivate.h"
 #include "mozilla/SyncRunnable.h"
 #include "runnable_utils.h"
+#include "base/task.h"
 
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
 
 #define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
--- a/dom/media/gmp/GMPServiceChild.h
+++ b/dom/media/gmp/GMPServiceChild.h
@@ -10,18 +10,16 @@
 #include "base/process.h"
 #include "mozilla/ipc/Transport.h"
 #include "mozilla/gmp/PGMPServiceChild.h"
 #include "nsRefPtrHashtable.h"
 
 namespace mozilla {
 namespace gmp {
 
-#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
-
 class GMPContentParent;
 class GMPServiceChild;
 
 class GetServiceChildCallback
 {
 public:
   GetServiceChildCallback()
   {
--- a/dom/media/gmp/GMPServiceParent.cpp
+++ b/dom/media/gmp/GMPServiceParent.cpp
@@ -1,33 +1,33 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPServiceParent.h"
 #include "GMPService.h"
 #include "prio.h"
+#include "base/task.h"
 #include "mozilla/Logging.h"
 #include "GMPParent.h"
 #include "GMPVideoDecoderParent.h"
 #include "nsIObserverService.h"
 #include "GeckoChildProcessHost.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/SyncRunnable.h"
 #include "nsXPCOMPrivate.h"
 #include "mozilla/Services.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIConsoleService.h"
 #include "mozilla/unused.h"
 #include "GMPDecryptorParent.h"
 #include "GMPAudioDecoderParent.h"
 #include "nsComponentManagerUtils.h"
-#include "mozilla/Preferences.h"
 #include "runnable_utils.h"
 #include "VideoUtils.h"
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
 #include "mozilla/SandboxInfo.h"
 #endif
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsDirectoryServiceDefs.h"
@@ -36,16 +36,17 @@
 #include "nsISimpleEnumerator.h"
 #if defined(MOZ_CRASHREPORTER)
 #include "nsExceptionHandler.h"
 #include "nsPrintfCString.h"
 #endif
 #include "nsIXULRuntime.h"
 #include "GMPDecoderModule.h"
 #include <limits>
+#include "MediaPrefs.h"
 
 namespace mozilla {
 
 #ifdef LOG
 #undef LOG
 #endif
 
 #define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
@@ -75,53 +76,40 @@ GeckoMediaPluginServiceParent::GetSingle
 #endif
   return service.forget().downcast<GeckoMediaPluginServiceParent>();
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(GeckoMediaPluginServiceParent,
                             GeckoMediaPluginService,
                             mozIGeckoMediaPluginChromeService)
 
-static int32_t sMaxAsyncShutdownWaitMs = 0;
-static bool sAllowInsecureGMP = false;
-static bool sHaveSetGMPServiceParentPrefCaches = false;
-
 GeckoMediaPluginServiceParent::GeckoMediaPluginServiceParent()
   : mShuttingDown(false)
 #ifdef MOZ_CRASHREPORTER
   , mAsyncShutdownPluginStatesMutex("GeckoMediaPluginService::mAsyncShutdownPluginStatesMutex")
 #endif
   , mScannedPluginOnDisk(false)
   , mWaitingForPluginsSyncShutdown(false)
   , mInitPromiseMonitor("GeckoMediaPluginServiceParent::mInitPromiseMonitor")
   , mLoadPluginsFromDiskComplete(false)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  if (!sHaveSetGMPServiceParentPrefCaches) {
-    sHaveSetGMPServiceParentPrefCaches = true;
-    Preferences::AddIntVarCache(&sMaxAsyncShutdownWaitMs,
-                                "media.gmp.async-shutdown-timeout",
-                                GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT);
-    Preferences::AddBoolVarCache(&sAllowInsecureGMP,
-                                 "media.gmp.insecure.allow", false);
-  }
   mInitPromise.SetMonitor(&mInitPromiseMonitor);
 }
 
 GeckoMediaPluginServiceParent::~GeckoMediaPluginServiceParent()
 {
   MOZ_ASSERT(mPlugins.IsEmpty());
   MOZ_ASSERT(mAsyncShutdownPlugins.IsEmpty());
 }
 
 int32_t
 GeckoMediaPluginServiceParent::AsyncShutdownTimeoutMs()
 {
-  MOZ_ASSERT(sHaveSetGMPServiceParentPrefCaches);
-  return sMaxAsyncShutdownWaitMs;
+  return MediaPrefs::GMPAsyncShutdownTimeout();
 }
 
 nsresult
 GeckoMediaPluginServiceParent::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
@@ -1052,17 +1040,17 @@ GeckoMediaPluginServiceParent::SelectPlu
   return nullptr;
 }
 
 RefPtr<GMPParent>
 CreateGMPParent()
 {
 #if defined(XP_LINUX) && defined(MOZ_GMP_SANDBOX)
   if (!SandboxInfo::Get().CanSandboxMedia()) {
-    if (!sAllowInsecureGMP) {
+    if (!MediaPrefs::GMPAllowInsecure()) {
       NS_WARNING("Denying media plugin load due to lack of sandboxing.");
       return nullptr;
     }
     NS_WARNING("Loading media plugin despite lack of sandboxing.");
   }
 #endif
   return new GMPParent();
 }
--- a/dom/media/gmp/GMPServiceParent.h
+++ b/dom/media/gmp/GMPServiceParent.h
@@ -18,18 +18,16 @@
 
 template <class> struct already_AddRefed;
 
 namespace mozilla {
 namespace gmp {
 
 class GMPParent;
 
-#define GMP_DEFAULT_ASYNC_SHUTDONW_TIMEOUT 3000
-
 class GeckoMediaPluginServiceParent final : public GeckoMediaPluginService
                                           , public mozIGeckoMediaPluginChromeService
 {
 public:
   static already_AddRefed<GeckoMediaPluginServiceParent> GetSingleton();
 
   GeckoMediaPluginServiceParent();
   nsresult Init() override;
--- a/dom/media/gmp/GMPStorageChild.cpp
+++ b/dom/media/gmp/GMPStorageChild.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "GMPStorageChild.h"
 #include "GMPChild.h"
 #include "gmp-storage.h"
+#include "base/task.h"
 
 #define ON_GMP_THREAD() (mPlugin->GMPMessageLoop() == MessageLoop::current())
 
 #define CALL_ON_GMP_THREAD(_func, ...) \
   do { \
     if (ON_GMP_THREAD()) { \
       _func(__VA_ARGS__); \
     } else { \
--- a/dom/media/gtest/TestGMPCrossOrigin.cpp
+++ b/dom/media/gtest/TestGMPCrossOrigin.cpp
@@ -8,16 +8,17 @@
 #include "nsIObserverService.h"
 #include "mozilla/Services.h"
 #include "mozilla/StaticPtr.h"
 #include "GMPTestMonitor.h"
 #include "GMPVideoDecoderProxy.h"
 #include "GMPVideoEncoderProxy.h"
 #include "GMPDecryptorProxy.h"
 #include "GMPServiceParent.h"
+#include "MediaPrefs.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsIFile.h"
 #include "nsISimpleEnumerator.h"
 #include "mozilla/Atomics.h"
 #include "nsNSSComponent.h"
 #include "mozilla/DebugOnly.h"
 
 #if defined(XP_WIN)
@@ -28,16 +29,17 @@ using namespace std;
 
 using namespace mozilla;
 using namespace mozilla::gmp;
 
 struct GMPTestRunner
 {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPTestRunner)
 
+  GMPTestRunner() { MediaPrefs::GetSingleton(); }
   void DoTest(void (GMPTestRunner::*aTestMethod)(GMPTestMonitor&));
   void RunTestGMPTestCodec1(GMPTestMonitor& aMonitor);
   void RunTestGMPTestCodec2(GMPTestMonitor& aMonitor);
   void RunTestGMPTestCodec3(GMPTestMonitor& aMonitor);
   void RunTestGMPCrossOrigin1(GMPTestMonitor& aMonitor);
   void RunTestGMPCrossOrigin2(GMPTestMonitor& aMonitor);
   void RunTestGMPCrossOrigin3(GMPTestMonitor& aMonitor);
   void RunTestGMPCrossOrigin4(GMPTestMonitor& aMonitor);
--- a/dom/media/gtest/TestGMPRemoveAndDelete.cpp
+++ b/dom/media/gtest/TestGMPRemoveAndDelete.cpp
@@ -11,16 +11,17 @@
 #include "mozilla/Services.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIObserverService.h"
 #include "GMPVideoDecoderProxy.h"
 #include "GMPServiceParent.h"
 #include "GMPService.h"
 #include "GMPUtils.h"
 #include "mozilla/StaticPtr.h"
+#include "MediaPrefs.h"
 
 #define GMP_DIR_NAME NS_LITERAL_STRING("gmp-fakeopenh264")
 #define GMP_OLD_VERSION NS_LITERAL_STRING("1.0")
 #define GMP_NEW_VERSION NS_LITERAL_STRING("1.1")
 
 #define GMP_DELETED_TOPIC "gmp-directory-deleted"
 
 #define EXPECT_OK(X) EXPECT_TRUE(NS_SUCCEEDED(X))
@@ -222,16 +223,18 @@ GMPRemoveTest::~GMPRemoveTest()
   EXPECT_TRUE(NS_SUCCEEDED(mTmpDir->Exists(&exists)) && !exists);
 
   EXPECT_OK(GetServiceParent()->AddPluginDirectory(mOriginalPath));
 }
 
 void
 GMPRemoveTest::Setup()
 {
+  // Initialize media preferences.
+  MediaPrefs::GetSingleton();
   GeneratePlugin();
   GetService()->GetThread(getter_AddRefs(mGMPThread));
 
   // Spin the event loop until the GMP service has had a chance to complete
   // adding GMPs from MOZ_GMP_PATH. Otherwise, the RemovePluginDirectory()
   // below may complete before we're finished adding GMPs from MOZ_GMP_PATH,
   // and we'll end up not removing the GMP, and the test will fail.
   RefPtr<AbstractThread> thread(GetServiceParent()->GetAbstractGMPThread());
--- a/dom/media/gtest/TestGMPUtils.cpp
+++ b/dom/media/gtest/TestGMPUtils.cpp
@@ -2,28 +2,31 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gtest/gtest.h"
 #include "GMPUtils.h"
 #include "nsString.h"
+#include "MediaPrefs.h"
 
 #include <string>
 #include <vector>
 
 using namespace std;
 using namespace mozilla;
 
 void TestSplitAt(const char* aInput,
                  const char* aDelims,
                  size_t aNumExpectedTokens,
                  const char* aExpectedTokens[])
 {
+  // Initialize media preferences.
+  MediaPrefs::GetSingleton();
   nsCString input(aInput);
   nsTArray<nsCString> tokens;
   SplitAt(aDelims, input, tokens);
   EXPECT_EQ(tokens.Length(), aNumExpectedTokens) << "Should get expected number of tokens";
   for (size_t i = 0; i < tokens.Length(); i++) {
     EXPECT_TRUE(tokens[i].EqualsASCII(aExpectedTokens[i]))
       << "Tokenize fail; expected=" << aExpectedTokens[i] << " got=" <<
       tokens[i].BeginReading();
--- a/dom/media/mediasink/DecodedAudioDataSink.cpp
+++ b/dom/media/mediasink/DecodedAudioDataSink.cpp
@@ -7,17 +7,17 @@
 #include "nsPrintfCString.h"
 #include "MediaQueue.h"
 #include "DecodedAudioDataSink.h"
 #include "VideoUtils.h"
 #include "AudioConverter.h"
 
 #include "mozilla/CheckedInt.h"
 #include "mozilla/DebugOnly.h"
-#include "gfxPrefs.h"
+#include "MediaPrefs.h"
 
 namespace mozilla {
 
 extern LazyLogModule gMediaDecoderLog;
 #define SINK_LOG(msg, ...) \
   MOZ_LOG(gMediaDecoderLog, LogLevel::Debug, \
     ("DecodedAudioDataSink=%p " msg, this, ##__VA_ARGS__))
 #define SINK_LOG_V(msg, ...) \
@@ -46,37 +46,38 @@ DecodedAudioDataSink::DecodedAudioDataSi
   , mMonitor("DecodedAudioDataSink")
   , mWritten(0)
   , mErrored(false)
   , mPlaybackComplete(false)
   , mOwnerThread(aThread)
   , mProcessedQueueLength(0)
   , mFramesParsed(0)
   , mLastEndTime(0)
+  , mIsAudioDataAudible(false)
 {
-  bool resampling = gfxPrefs::AudioSinkResampling();
+  bool resampling = MediaPrefs::AudioSinkResampling();
 
   if (resampling) {
-    mOutputRate = gfxPrefs::AudioSinkResampleRate();
+    mOutputRate = MediaPrefs::AudioSinkResampleRate();
   } else if (mInfo.mRate == 44100 || mInfo.mRate == 48000) {
     // The original rate is of good quality and we want to minimize unecessary
     // resampling. The common scenario being that the sampling rate is one or
     // the other, this allows to minimize audio quality regression and hoping
     // content provider want change from those rates mid-stream.
     mOutputRate = mInfo.mRate;
   } else {
     // We will resample all data to match cubeb's preferred sampling rate.
     mOutputRate = AudioStream::GetPreferredRate();
   }
   MOZ_DIAGNOSTIC_ASSERT(mOutputRate, "output rate can't be 0.");
 
-  bool monoAudioEnabled = gfxPrefs::MonoAudio();
+  bool monoAudioEnabled = MediaPrefs::MonoAudio();
 
   mOutputChannels = monoAudioEnabled
-    ? 1 : (gfxPrefs::AudioSinkForceStereo() ? 2 : mInfo.mChannels);
+    ? 1 : (MediaPrefs::AudioSinkForceStereo() ? 2 : mInfo.mChannels);
 }
 
 DecodedAudioDataSink::~DecodedAudioDataSink()
 {
 }
 
 RefPtr<GenericPromise>
 DecodedAudioDataSink::Init(const PlaybackParams& aParams)
@@ -313,16 +314,17 @@ DecodedAudioDataSink::PopFrames(uint32_t
   if (!mCursor->Available()) {
     mCurrentData = nullptr;
   }
 
   if (needPopping) {
     // We can now safely pop the audio packet from the processed queue.
     // This will fire the popped event, triggering a call to NotifyAudioNeeded.
     RefPtr<AudioData> releaseMe = mProcessedQueue.PopFront();
+    CheckIsAudible(releaseMe);
   }
 
   return chunk;
 }
 
 bool
 DecodedAudioDataSink::Ended() const
 {
@@ -334,16 +336,28 @@ void
 DecodedAudioDataSink::Drained()
 {
   SINK_LOG("Drained");
   mPlaybackComplete = true;
   mEndPromise.ResolveIfExists(true, __func__);
 }
 
 void
+DecodedAudioDataSink::CheckIsAudible(const AudioData* aData)
+{
+  MOZ_ASSERT(aData);
+
+  bool isAudible = aData->IsAudible();
+  if (isAudible != mIsAudioDataAudible) {
+    mIsAudioDataAudible = isAudible;
+    mAudibleEvent.Notify(mIsAudioDataAudible);
+  }
+}
+
+void
 DecodedAudioDataSink::OnAudioPopped(const RefPtr<MediaData>& aSample)
 {
   SINK_LOG_V("AudioStream has used an audio packet.");
   NotifyAudioNeeded();
 }
 
 void
 DecodedAudioDataSink::OnAudioPushed(const RefPtr<MediaData>& aSample)
--- a/dom/media/mediasink/DecodedAudioDataSink.h
+++ b/dom/media/mediasink/DecodedAudioDataSink.h
@@ -53,28 +53,34 @@ public:
   // Shut down the DecodedAudioDataSink's resources.
   void Shutdown() override;
 
   void SetVolume(double aVolume) override;
   void SetPlaybackRate(double aPlaybackRate) override;
   void SetPreservesPitch(bool aPreservesPitch) override;
   void SetPlaying(bool aPlaying) override;
 
+  MediaEventSource<bool>& AudibleEvent() {
+    return mAudibleEvent;
+  }
+
 private:
   virtual ~DecodedAudioDataSink();
 
   // Allocate and initialize mAudioStream. Returns NS_OK on success.
   nsresult InitializeAudioStream(const PlaybackParams& aParams);
 
   // Interface of AudioStream::DataSource.
   // Called on the callback thread of cubeb.
   UniquePtr<AudioStream::Chunk> PopFrames(uint32_t aFrames) override;
   bool Ended() const override;
   void Drained() override;
 
+  void CheckIsAudible(const AudioData* aData);
+
   // The audio stream resource. Used on the task queue of MDSM only.
   RefPtr<AudioStream> mAudioStream;
 
   // The presentation time of the first audio frame that was played in
   // microseconds. We can add this to the audio stream position to determine
   // the current audio time.
   const int64_t mStartTime;
 
@@ -141,14 +147,19 @@ private:
   // the input stream. It indicates the time in frames since playback started
   // at the current input framerate.
   int64_t mFramesParsed;
   Maybe<RefPtr<AudioData>> mLastProcessedPacket;
   int64_t mLastEndTime;
   // Never modifed after construction.
   uint32_t mOutputRate;
   uint32_t mOutputChannels;
+
+  // True when audio is producing audible sound, false when audio is silent.
+  bool mIsAudioDataAudible;
+
+  MediaEventProducer<bool> mAudibleEvent;
 };
 
 } // namespace media
 } // namespace mozilla
 
 #endif
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "MediaSourceDecoder.h"
 
 #include "mozilla/Logging.h"
 #include "mozilla/dom/HTMLMediaElement.h"
-#include "mozilla/Preferences.h"
 #include "MediaDecoderStateMachine.h"
 #include "MediaSource.h"
 #include "MediaSourceResource.h"
 #include "MediaSourceUtils.h"
 #include "VideoUtils.h"
 #include "MediaSourceDemuxer.h"
 #include "SourceBufferList.h"
 #include <algorithm>
--- a/dom/media/moz.build
+++ b/dom/media/moz.build
@@ -114,16 +114,17 @@ EXPORTS += [
     'MediaDecoder.h',
     'MediaDecoderOwner.h',
     'MediaDecoderReader.h',
     'MediaDecoderStateMachine.h',
     'MediaEventSource.h',
     'MediaFormatReader.h',
     'MediaInfo.h',
     'MediaMetadataManager.h',
+    'MediaPrefs.h',
     'MediaQueue.h',
     'MediaRecorder.h',
     'MediaResource.h',
     'MediaResourceCallback.h',
     'MediaSegment.h',
     'MediaStatistics.h',
     'MediaStreamGraph.h',
     'MediaTimer.h',
@@ -225,16 +226,17 @@ UNIFIED_SOURCES += [
     'MediaDecoderReader.cpp',
     'MediaDecoderReaderWrapper.cpp',
     'MediaDecoderStateMachine.cpp',
     'MediaDeviceInfo.cpp',
     'MediaDevices.cpp',
     'MediaFormatReader.cpp',
     'MediaInfo.cpp',
     'MediaManager.cpp',
+    'MediaPrefs.cpp',
     'MediaRecorder.cpp',
     'MediaResource.cpp',
     'MediaShutdownManager.cpp',
     'MediaStreamError.cpp',
     'MediaStreamGraph.cpp',
     'MediaStreamTrack.cpp',
     'MediaTimer.cpp',
     'MediaTrack.cpp',
--- a/dom/media/omx/OmxDecoder.cpp
+++ b/dom/media/omx/OmxDecoder.cpp
@@ -22,17 +22,16 @@
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 #include <gui/Surface.h>
 #else
 #include <gui/SurfaceTextureClient.h>
 #endif
 
 #include "mozilla/layers/GrallocTextureClient.h"
 #include "mozilla/layers/TextureClient.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/Types.h"
 #include "mozilla/Monitor.h"
 #include "nsMimeTypes.h"
 #include "MPAPI.h"
 #include "mozilla/Logging.h"
 
 #include "GonkNativeWindow.h"
 #include "OMXCodecProxy.h"
--- a/dom/media/platforms/PDMFactory.cpp
+++ b/dom/media/platforms/PDMFactory.cpp
@@ -21,22 +21,22 @@
 #ifdef MOZ_GONK_MEDIACODEC
 #include "GonkDecoderModule.h"
 #endif
 #ifdef MOZ_WIDGET_ANDROID
 #include "AndroidDecoderModule.h"
 #endif
 #include "GMPDecoderModule.h"
 
-#include "mozilla/Preferences.h"
 #include "mozilla/TaskQueue.h"
 
 #include "mozilla/SharedThreadPool.h"
 
 #include "MediaInfo.h"
+#include "MediaPrefs.h"
 #include "FuzzingWrapper.h"
 #include "H264Converter.h"
 
 #include "AgnosticDecoderModule.h"
 
 #ifdef MOZ_EME
 #include "EMEDecoderModule.h"
 #include "mozilla/CDMProxy.h"
@@ -44,84 +44,29 @@
 
 #include "DecoderDoctorDiagnostics.h"
 
 namespace mozilla {
 
 extern already_AddRefed<PlatformDecoderModule> CreateAgnosticDecoderModule();
 extern already_AddRefed<PlatformDecoderModule> CreateBlankDecoderModule();
 
-bool PDMFactory::sUseBlankDecoder = false;
-#ifdef MOZ_GONK_MEDIACODEC
-bool PDMFactory::sGonkDecoderEnabled = false;
-#endif
-#ifdef MOZ_WIDGET_ANDROID
-bool PDMFactory::sAndroidMCDecoderEnabled = false;
-bool PDMFactory::sAndroidMCDecoderPreferred = false;
-#endif
-bool PDMFactory::sGMPDecoderEnabled = false;
-#ifdef MOZ_FFVPX
-bool PDMFactory::sFFVPXDecoderEnabled = false;
-#endif
-#ifdef MOZ_FFMPEG
-bool PDMFactory::sFFmpegDecoderEnabled = false;
-#endif
-#ifdef XP_WIN
-bool PDMFactory::sWMFDecoderEnabled = false;
-#endif
-
-bool PDMFactory::sEnableFuzzingWrapper = false;
-uint32_t PDMFactory::sVideoOutputMinimumInterval_ms = 0;
-bool PDMFactory::sDontDelayInputExhausted = false;
-
 /* static */
 void
 PDMFactory::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
   static bool alreadyInitialized = false;
   if (alreadyInitialized) {
     return;
   }
   alreadyInitialized = true;
 
-  Preferences::AddBoolVarCache(&sUseBlankDecoder,
-                               "media.use-blank-decoder", false);
-#ifdef MOZ_GONK_MEDIACODEC
-  Preferences::AddBoolVarCache(&sGonkDecoderEnabled,
-                               "media.gonk.enabled", true);
-#endif
-#ifdef MOZ_WIDGET_ANDROID
-  Preferences::AddBoolVarCache(&sAndroidMCDecoderEnabled,
-                               "media.android-media-codec.enabled", false);
-  Preferences::AddBoolVarCache(&sAndroidMCDecoderPreferred,
-                               "media.android-media-codec.preferred", false);
-#endif
-
-  Preferences::AddBoolVarCache(&sGMPDecoderEnabled,
-                               "media.gmp.decoder.enabled", true);
-#ifdef MOZ_FFMPEG
-  Preferences::AddBoolVarCache(&sFFmpegDecoderEnabled,
-                               "media.ffmpeg.enabled", true);
-#endif
-#ifdef MOZ_FFVPX
-  Preferences::AddBoolVarCache(&sFFVPXDecoderEnabled,
-                               "media.ffvpx.enabled", true);
-#endif
-#ifdef XP_WIN
-  Preferences::AddBoolVarCache(&sWMFDecoderEnabled,
-                               "media.wmf.enabled", true);
-#endif
-
-  Preferences::AddBoolVarCache(&sEnableFuzzingWrapper,
-                               "media.decoder.fuzzing.enabled", false);
-  Preferences::AddUintVarCache(&sVideoOutputMinimumInterval_ms,
-                               "media.decoder.fuzzing.video-output-minimum-interval-ms", 0);
-  Preferences::AddBoolVarCache(&sDontDelayInputExhausted,
-                               "media.decoder.fuzzing.dont-delay-inputexhausted", false);
+  // Ensure MediaPrefs are initialized.
+  MediaPrefs::GetSingleton();
 
 #ifdef XP_WIN
   WMFDecoderModule::Init();
 #endif
 #ifdef MOZ_APPLEMEDIA
   AppleDecoderModule::Init();
 #endif
 #ifdef MOZ_FFVPX
@@ -217,21 +162,21 @@ PDMFactory::CreateDecoderWithPDM(Platfor
   }
 
   if (!aConfig.GetAsVideoInfo()) {
     return nullptr;
   }
 
   MediaDataDecoderCallback* callback = aCallback;
   RefPtr<DecoderCallbackFuzzingWrapper> callbackWrapper;
-  if (sEnableFuzzingWrapper) {
+  if (MediaPrefs::PDMFuzzingEnabled()) {
     callbackWrapper = new DecoderCallbackFuzzingWrapper(aCallback);
     callbackWrapper->SetVideoOutputMinimumInterval(
-      TimeDuration::FromMilliseconds(sVideoOutputMinimumInterval_ms));
-    callbackWrapper->SetDontDelayInputExhausted(sDontDelayInputExhausted);
+      TimeDuration::FromMilliseconds(MediaPrefs::PDMFuzzingInterval()));
+    callbackWrapper->SetDontDelayInputExhausted(!MediaPrefs::PDMFuzzingDelayInputExhausted());
     callback = callbackWrapper.get();
   }
 
   if (H264Converter::IsH264(aConfig)) {
     RefPtr<H264Converter> h
       = new H264Converter(aPDM,
                           *aConfig.GetAsVideoInfo(),
                           aLayersBackend,
@@ -273,74 +218,75 @@ PDMFactory::SupportsMimeType(const nsACS
   return !!current;
 }
 
 void
 PDMFactory::CreatePDMs()
 {
   RefPtr<PlatformDecoderModule> m;
 
-  if (sUseBlankDecoder) {
+  if (MediaPrefs::PDMUseBlankDecoder()) {
     m = CreateBlankDecoderModule();
     StartupPDM(m);
     // The Blank PDM SupportsMimeType reports true for all codecs; the creation
     // of its decoder is infallible. As such it will be used for all media, we
     // can stop creating more PDM from this point.
     return;
   }
 
 #ifdef MOZ_WIDGET_ANDROID
-  if(sAndroidMCDecoderPreferred && sAndroidMCDecoderEnabled) {
+  if(MediaPrefs::PDMAndroidMediaCodecPreferred() &&
+     MediaPrefs::PDMAndroidMediaCodecEnabled()) {
     m = new AndroidDecoderModule();
     StartupPDM(m);
   }
 #endif
 #ifdef XP_WIN
-  if (sWMFDecoderEnabled) {
+  if (MediaPrefs::PDMWMFEnabled()) {
     m = new WMFDecoderModule();
     if (!StartupPDM(m)) {
       mWMFFailedToLoad = true;
     }
   }
 #endif
 #ifdef MOZ_FFVPX
-  if (sFFVPXDecoderEnabled) {
+  if (MediaPrefs::PDMFFVPXEnabled()) {
     m = FFVPXRuntimeLinker::CreateDecoderModule();
     StartupPDM(m);
   }
 #endif
 #ifdef MOZ_FFMPEG
-  if (sFFmpegDecoderEnabled) {
+  if (MediaPrefs::PDMFFmpegEnabled()) {
     m = FFmpegRuntimeLinker::CreateDecoderModule();
     if (!StartupPDM(m)) {
       mFFmpegFailedToLoad = true;
     }
   }
 #endif
 #ifdef MOZ_APPLEMEDIA
   m = new AppleDecoderModule();
   StartupPDM(m);
 #endif
 #ifdef MOZ_GONK_MEDIACODEC
-  if (sGonkDecoderEnabled) {
+  if (MediaPrefs::PDMGonkDecoderEnabled()) {
     m = new GonkDecoderModule();
     StartupPDM(m);
   }
 #endif
 #ifdef MOZ_WIDGET_ANDROID
-  if(sAndroidMCDecoderEnabled){
+  if(MediaPrefs::PDMAndroidMediaCodecEnabled()){
     m = new AndroidDecoderModule();
     StartupPDM(m);
   }
 #endif
 
   m = new AgnosticDecoderModule();
   StartupPDM(m);
 
-  if (sGMPDecoderEnabled) {
+  if (MediaPrefs::PDMGMPEnabled()) {
     m = new GMPDecoderModule();
     if (!StartupPDM(m)) {
       mGMPPDMFailedToStartup = true;
     }
   }
 }
 
 bool
--- a/dom/media/platforms/PDMFactory.h
+++ b/dom/media/platforms/PDMFactory.h
@@ -64,39 +64,16 @@ private:
   CreateDecoderWithPDM(PlatformDecoderModule* aPDM,
                        const TrackInfo& aConfig,
                        FlushableTaskQueue* aTaskQueue,
                        MediaDataDecoderCallback* aCallback,
                        DecoderDoctorDiagnostics* aDiagnostics,
                        layers::LayersBackend aLayersBackend,
                        layers::ImageContainer* aImageContainer);
 
-  // PDM pref caches...
-  static bool sUseBlankDecoder;
-#ifdef MOZ_GONK_MEDIACODEC
-  static bool sGonkDecoderEnabled;
-#endif
-#ifdef MOZ_WIDGET_ANDROID
-  static bool sAndroidMCDecoderPreferred;
-  static bool sAndroidMCDecoderEnabled;
-#endif
-  static bool sGMPDecoderEnabled;
-#ifdef MOZ_FFVPX
-  static bool sFFVPXDecoderEnabled;
-#endif
-#ifdef MOZ_FFMPEG
-  static bool sFFmpegDecoderEnabled;
-#endif
-#ifdef XP_WIN
-  static bool sWMFDecoderEnabled;
-#endif
-  static bool sEnableFuzzingWrapper;
-  static uint32_t sVideoOutputMinimumInterval_ms;
-  static bool sDontDelayInputExhausted;
-
   nsTArray<RefPtr<PlatformDecoderModule>> mCurrentPDMs;
   RefPtr<PlatformDecoderModule> mEMEPDM;
 
   bool mWMFFailedToLoad = false;
   bool mFFmpegFailedToLoad = false;
   bool mGMPPDMFailedToStartup = false;
 };
 
--- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp
@@ -39,17 +39,20 @@ public:
 
   RefPtr<InitPromise> Init() override {
     MOZ_ASSERT(!mIsShutdown);
     return mDecoder->Init();
   }
 
   nsresult Input(MediaRawData* aSample) override {
     MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
-    MOZ_ASSERT(!mIsShutdown);
+    if (mIsShutdown) {
+      NS_WARNING("EME encrypted sample arrived after shutdown");
+      return NS_OK;
+    }
     if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) {
       return NS_OK;
     }
 
     nsAutoPtr<MediaRawDataWriter> writer(aSample->CreateWriter());
     mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId,
                                   writer->mCrypto.mSessionIds);
 
--- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp
@@ -4,19 +4,19 @@
  * 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 "GMPDecoderModule.h"
 #include "DecoderDoctorDiagnostics.h"
 #include "GMPAudioDecoder.h"
 #include "GMPVideoDecoder.h"
 #include "MediaDataDecoderProxy.h"
+#include "MediaPrefs.h"
 #include "mozIGeckoMediaPluginService.h"
 #include "nsServiceManagerUtils.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/StaticMutex.h"
 #include "gmp-audio-decode.h"
 #include "gmp-video-decode.h"
 #ifdef XP_WIN
 #include "WMFDecoderModule.h"
 #endif
 
 namespace mozilla {
@@ -170,52 +170,44 @@ GMPDecoderModule::UpdateUsableCodecs()
                             NS_LITERAL_CSTRING("aac"),
                             nsDependentCString(gmp.mKeySystem));
     gmp.mHasH264 = HasGMPFor(NS_LITERAL_CSTRING(GMP_API_VIDEO_DECODER),
                              NS_LITERAL_CSTRING("h264"),
                              nsDependentCString(gmp.mKeySystem));
   }
 }
 
-static uint32_t sPreferredAacGmp = 0;
-static uint32_t sPreferredH264Gmp = 0;
-
 /* static */
 void
 GMPDecoderModule::Init()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // GMPService::HasPluginForAPI is main thread only, so to implement
   // SupportsMimeType() we build a table of the codecs which each whitelisted
   // GMP has and update it when any GMPs are removed or added at runtime.
   UpdateUsableCodecs();
-
-  Preferences::AddUintVarCache(&sPreferredAacGmp,
-                               "media.gmp.decoder.aac", 0);
-  Preferences::AddUintVarCache(&sPreferredH264Gmp,
-                               "media.gmp.decoder.h264", 0);
 }
 
 /* static */
 const Maybe<nsCString>
 GMPDecoderModule::PreferredGMP(const nsACString& aMimeType)
 {
   Maybe<nsCString> rv;
   if (aMimeType.EqualsLiteral("audio/mp4a-latm")) {
-    switch (sPreferredAacGmp) {
+    switch (MediaPrefs::GMPAACPreferred()) {
       case 1: rv.emplace(NS_LITERAL_CSTRING("org.w3.clearkey")); break;
       case 2: rv.emplace(NS_LITERAL_CSTRING("com.adobe.primetime")); break;
       default: break;
     }
   }
 
   if (aMimeType.EqualsLiteral("video/avc") ||
       aMimeType.EqualsLiteral("video/mp4")) {
-    switch (sPreferredH264Gmp) {
+    switch (MediaPrefs::GMPH264Preferred()) {
       case 1: rv.emplace(NS_LITERAL_CSTRING("org.w3.clearkey")); break;
       case 2: rv.emplace(NS_LITERAL_CSTRING("com.adobe.primetime")); break;
       default: break;
     }
   }
 
   return rv;
 }
--- a/dom/media/platforms/apple/AppleDecoderModule.cpp
+++ b/dom/media/platforms/apple/AppleDecoderModule.cpp
@@ -7,28 +7,27 @@
 #include "AppleATDecoder.h"
 #include "AppleCMLinker.h"
 #include "AppleDecoderModule.h"
 #include "AppleVDADecoder.h"
 #include "AppleVDALinker.h"
 #include "AppleVTDecoder.h"
 #include "AppleVTLinker.h"
 #include "MacIOSurfaceImage.h"
-#include "mozilla/Preferences.h"
+#include "MediaPrefs.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Logging.h"
 
 namespace mozilla {
 
 bool AppleDecoderModule::sInitialized = false;
 bool AppleDecoderModule::sIsCoreMediaAvailable = false;
 bool AppleDecoderModule::sIsVTAvailable = false;
 bool AppleDecoderModule::sIsVTHWAvailable = false;
 bool AppleDecoderModule::sIsVDAAvailable = false;
-bool AppleDecoderModule::sForceVDA = false;
 bool AppleDecoderModule::sCanUseHardwareVideoDecoder = true;
 
 AppleDecoderModule::AppleDecoderModule()
 {
 }
 
 AppleDecoderModule::~AppleDecoderModule()
 {
@@ -39,18 +38,16 @@ void
 AppleDecoderModule::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
 
   if (sInitialized) {
     return;
   }
 
-  Preferences::AddBoolVarCache(&sForceVDA, "media.apple.forcevda", false);
-
   // Ensure IOSurface framework is loaded.
   MacIOSurfaceLib::LoadLibrary();
   const bool loaded = MacIOSurfaceLib::isInit();
 
   // dlopen VideoDecodeAcceleration.framework if it's available.
   sIsVDAAvailable = loaded && AppleVDALinker::Link();
 
   // dlopen CoreMedia.framework if it's available.
@@ -83,17 +80,17 @@ AppleDecoderModule::CreateVideoDecoder(c
                                        layers::LayersBackend aLayersBackend,
                                        layers::ImageContainer* aImageContainer,
                                        FlushableTaskQueue* aVideoTaskQueue,
                                        MediaDataDecoderCallback* aCallback,
                                        DecoderDoctorDiagnostics* aDiagnostics)
 {
   RefPtr<MediaDataDecoder> decoder;
 
-  if (sIsVDAAvailable && (!sIsVTHWAvailable || sForceVDA)) {
+  if (sIsVDAAvailable && (!sIsVTHWAvailable || MediaPrefs::AppleForceVDA())) {
     decoder =
       AppleVDADecoder::CreateVDADecoder(aConfig,
                                         aVideoTaskQueue,
                                         aCallback,
                                         aImageContainer);
     if (decoder) {
       return decoder.forget();
     }
--- a/dom/media/platforms/apple/AppleDecoderModule.h
+++ b/dom/media/platforms/apple/AppleDecoderModule.h
@@ -45,14 +45,13 @@ public:
   static bool sCanUseHardwareVideoDecoder;
 
 private:
   static bool sInitialized;
   static bool sIsCoreMediaAvailable;
   static bool sIsVTAvailable;
   static bool sIsVTHWAvailable;
   static bool sIsVDAAvailable;
-  static bool sForceVDA;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_AppleDecoderModule_h
--- a/dom/media/platforms/gonk/GonkDecoderModule.cpp
+++ b/dom/media/platforms/gonk/GonkDecoderModule.cpp
@@ -1,17 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "GonkDecoderModule.h"
 #include "GonkVideoDecoderManager.h"
 #include "GonkAudioDecoderManager.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/DebugOnly.h"
 #include "GonkMediaDataDecoder.h"
 
 namespace mozilla {
 GonkDecoderModule::GonkDecoderModule()
 {
 }
 
--- a/dom/media/platforms/wmf/WMFDecoderModule.cpp
+++ b/dom/media/platforms/wmf/WMFDecoderModule.cpp
@@ -4,95 +4,73 @@
  * 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 "WMF.h"
 #include "WMFDecoderModule.h"
 #include "WMFVideoMFTManager.h"
 #include "WMFAudioMFTManager.h"
 #include "MFTDecoder.h"
-#include "mozilla/Preferences.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/Services.h"
 #include "WMFMediaDataDecoder.h"
 #include "nsIWindowsRegKey.h"
 #include "nsComponentManagerUtils.h"
 #include "nsServiceManagerUtils.h"
 #include "nsIGfxInfo.h"
 #include "nsWindowsHelpers.h"
 #include "GfxDriverInfo.h"
 #include "gfxWindowsPlatform.h"
 #include "MediaInfo.h"
+#include "MediaPrefs.h"
 #include "prsystem.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/StaticMutex.h"
 
 namespace mozilla {
 
 static bool sDXVAEnabled = false;
-static int  sNumDecoderThreads = -1;
-static bool sIsIntelDecoderEnabled = false;
-static bool sLowLatencyMFTEnabled = false;
 
 WMFDecoderModule::WMFDecoderModule()
   : mWMFInitialized(false)
 {
 }
 
 WMFDecoderModule::~WMFDecoderModule()
 {
   if (mWMFInitialized) {
     DebugOnly<HRESULT> hr = wmf::MFShutdown();
     NS_ASSERTION(SUCCEEDED(hr), "MFShutdown failed");
   }
 }
 
-static void
-SetNumOfDecoderThreads()
-{
-  MOZ_ASSERT(NS_IsMainThread(), "Preferences can only be read on main thread");
-  int32_t numCores = PR_GetNumberOfProcessors();
-
-  // If we have more than 4 cores, let the decoder decide how many threads.
-  // On an 8 core machine, WMF chooses 4 decoder threads
-  const int WMF_DECODER_DEFAULT = -1;
-  int32_t prefThreadCount = Preferences::GetInt("media.wmf.decoder.thread-count", -1);
-  if (prefThreadCount != WMF_DECODER_DEFAULT) {
-    sNumDecoderThreads = std::max(prefThreadCount, 1);
-  } else if (numCores > 4) {
-    sNumDecoderThreads = WMF_DECODER_DEFAULT;
-  } else {
-    sNumDecoderThreads = std::max(numCores - 1, 1);
-  }
-}
-
 /* static */
 void
 WMFDecoderModule::Init()
 {
   MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
   sDXVAEnabled = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
-  Preferences::AddBoolVarCache(&sIsIntelDecoderEnabled,
-                               "media.webm.intel_decoder.enabled");
-  sLowLatencyMFTEnabled = Preferences::GetBool("media.wmf.low-latency.enabled", false);
-  SetNumOfDecoderThreads();
 }
 
 /* static */
 int
 WMFDecoderModule::GetNumDecoderThreads()
 {
-  return sNumDecoderThreads;
-}
+  int32_t numCores = PR_GetNumberOfProcessors();
 
-/* static */
-bool
-WMFDecoderModule::LowLatencyMFTEnabled()
-{
-  return sLowLatencyMFTEnabled;
+  // If we have more than 4 cores, let the decoder decide how many threads.
+  // On an 8 core machine, WMF chooses 4 decoder threads
+  const int WMF_DECODER_DEFAULT = -1;
+  int32_t prefThreadCount = MediaPrefs::PDMWMFThreadCount();
+  if (prefThreadCount != WMF_DECODER_DEFAULT) {
+    return std::max(prefThreadCount, 1);
+  } else if (numCores > 4) {
+    return WMF_DECODER_DEFAULT;
+  }
+  return std::max(numCores - 1, 1);
 }
 
 nsresult
 WMFDecoderModule::Startup()
 {
   mWMFInitialized = SUCCEEDED(wmf::MFStartup());
   return mWMFInitialized ? NS_OK : NS_ERROR_FAILURE;
 }
@@ -227,17 +205,17 @@ WMFDecoderModule::SupportsMimeType(const
        aMimeType.EqualsLiteral("video/mp4")) &&
        WMFDecoderModule::HasH264()) {
     return true;
   }
   if (aMimeType.EqualsLiteral("audio/mpeg") &&
       CanCreateWMFDecoder<CLSID_CMP3DecMediaObject>()) {
     return true;
   }
-  if (sIsIntelDecoderEnabled && sDXVAEnabled) {
+  if (MediaPrefs::PDMWMFIntelDecoderEnabled() && sDXVAEnabled) {
     if (aMimeType.EqualsLiteral("video/webm; codecs=vp8") &&
         CanCreateWMFDecoder<CLSID_WebmMfVp8Dec>()) {
       return true;
     }
     if (aMimeType.EqualsLiteral("video/webm; codecs=vp9") &&
         CanCreateWMFDecoder<CLSID_WebmMfVp9Dec>()) {
       return true;
     }
--- a/dom/media/platforms/wmf/WMFDecoderModule.h
+++ b/dom/media/platforms/wmf/WMFDecoderModule.h
@@ -39,17 +39,16 @@ public:
   ConversionRequired
   DecoderNeedsConversion(const TrackInfo& aConfig) const override;
 
   // Called on main thread.
   static void Init();
 
   // Called from any thread, must call init first
   static int GetNumDecoderThreads();
-  static bool LowLatencyMFTEnabled();
 
   // Accessors that report whether we have the required MFTs available
   // on the system to play various codecs. Windows Vista doesn't have the
   // H.264/AAC decoders if the "Platform Update Supplement for Windows Vista"
   // is not installed, and Window N and KN variants also require a "Media
   // Feature Pack" to be installed. Windows XP doesn't have WMF.
   static bool HasAAC();
   static bool HasH264();
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 <algorithm>
 #include "WMFVideoMFTManager.h"
 #include "MediaDecoderReader.h"
+#include "MediaPrefs.h"
 #include "WMFUtils.h"
 #include "ImageContainer.h"
 #include "VideoUtils.h"
 #include "DXVA2Manager.h"
 #include "nsThreadUtils.h"
 #include "Layers.h"
 #include "mozilla/layers/LayersTypes.h"
 #include "MediaInfo.h"
@@ -244,17 +245,17 @@ WMFVideoMFTManager::InitInternal(bool aF
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   RefPtr<IMFAttributes> attr(decoder->GetAttributes());
   UINT32 aware = 0;
   if (attr) {
     attr->GetUINT32(MF_SA_D3D_AWARE, &aware);
     attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads,
       WMFDecoderModule::GetNumDecoderThreads());
-    if (WMFDecoderModule::LowLatencyMFTEnabled()) {
+    if (MediaPrefs::PDMWMFLowLatencyEnabled()) {
       hr = attr->SetUINT32(CODECAPI_AVLowLatencyMode, TRUE);
       if (SUCCEEDED(hr)) {
         LOG("Enabling Low Latency Mode");
       } else {
         LOG("Couldn't enable Low Latency Mode");
       }
     }
   }
--- a/dom/media/tests/mochitest/dataChannel.js
+++ b/dom/media/tests/mochitest/dataChannel.js
@@ -179,13 +179,13 @@ var commandsCheckLargeXfer = [
       ok(result.data instanceof Blob, "Received data is of instance Blob");
       is(result.data.size, size, "Received data has the correct size.");
     });
   },
 ];
 
 function addInitialDataChannel(chain) {
   chain.insertBefore('PC_LOCAL_CREATE_OFFER', commandsCreateDataChannel);
-  chain.insertBefore('PC_LOCAL_CHECK_MEDIA_TRACKS', commandsWaitForDataChannel);
+  chain.insertBefore('PC_LOCAL_WAIT_FOR_MEDIA_FLOW', commandsWaitForDataChannel);
   chain.removeAfter('PC_REMOTE_CHECK_ICE_CONNECTIONS');
   chain.append(commandsCheckLargeXfer);
   chain.append(commandsCheckDataChannel);
 }
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -404,16 +404,17 @@ function(peer, desc, stateExpected) {
            "mismatch between event received " + state +
            " and event expected " + stateExpected);
       }
     };
   });
 
   var stateChanged = peer.setRemoteDescription(desc).then(() => {
     peer.setRemoteDescDate = new Date();
+    peer.checkMediaTracks();
   });
 
   return Promise.all([eventFired, stateChanged]);
 };
 
 /**
  * Adds and removes steps to/from the execution chain based on the configured
  * testOptions.
@@ -1124,38 +1125,34 @@ PeerConnectionWrapper.prototype = {
     var observedKind = track.kind;
     var expectedKind = expectedTrackInfoById[track.id].type;
     is(observedKind, expectedKind,
         "track id " + track.id + " was of kind " +
         observedKind + ", which matches " + expectedKind);
     observedTrackInfoById[track.id] = expectedTrackInfoById[track.id];
   },
 
+  isTrackOnPC: function(track) {
+    return this._pc.getRemoteStreams().some(stream => {
+      return stream.getTracks().some(pcTrack => pcTrack.id == track.id);
+    });
+  },
+
   allExpectedTracksAreObserved: function(expected, observed) {
     return Object.keys(expected).every(trackId => observed[trackId]);
   },
 
   setupTrackEventHandler: function() {
-    var resolveAllTrackEventsDone;
-
-    // checkMediaTracks waits on this promise later on in the test.
-    this.allTrackEventsDonePromise =
-      new Promise(resolve => resolveAllTrackEventsDone = resolve);
-
     this._pc.addEventListener('track', event => {
       info(this + ": 'ontrack' event fired for " + JSON.stringify(event.track));
 
       this.checkTrackIsExpected(event.track,
                                 this.expectedRemoteTrackInfoById,
                                 this.observedRemoteTrackInfoById);
-
-      if (this.allExpectedTracksAreObserved(this.expectedRemoteTrackInfoById,
-                                            this.observedRemoteTrackInfoById)) {
-        resolveAllTrackEventsDone();
-      }
+      ok(this.isTrackOnPC(event.track), "Found track " + event.track.id);
 
       this.ensureMediaElement(event.track, event.streams[0], 'remote');
     });
   },
 
   /**
    * Either adds a given ICE candidate right away or stores it to be added
    * later, depending on the state of the PeerConnection.
@@ -1327,33 +1324,28 @@ PeerConnectionWrapper.prototype = {
     });
 
     Object.keys(this.expectedLocalTrackInfoById).forEach(
         id => ok(observed[id], this + " local id " + id + " was observed"));
   },
 
   /**
    * Checks that we are getting the media tracks we expect.
-   *
-   * @param {object} constraints
-   *        The media constraints of the remote peer connection object
    */
   checkMediaTracks : function() {
     this.checkLocalMediaTracks();
 
     info(this + " Checking remote tracks " +
          JSON.stringify(this.expectedRemoteTrackInfoById));
 
-    // No tracks are expected
-    if (this.allExpectedTracksAreObserved(this.expectedRemoteTrackInfoById,
-                                          this.observedRemoteTrackInfoById)) {
-      return;
-    }
-
-    return timerGuard(this.allTrackEventsDonePromise, 60000, "The expected ontrack events never fired");
+    ok(this.allExpectedTracksAreObserved(this.expectedRemoteTrackInfoById,
+                                         this.observedRemoteTrackInfoById),
+       "All expected tracks have been observed"
+       + "\nexpected: " + JSON.stringify(this.expectedRemoteTrackInfoById)
+       + "\nobserved: " + JSON.stringify(this.observedRemoteTrackInfoById));
   },
 
   checkMsids: function() {
     var checkSdpForMsids = (desc, expectedTrackInfo, side) => {
       Object.keys(expectedTrackInfo).forEach(trackId => {
         var streamId = expectedTrackInfo[trackId].streamId;
         ok(desc.sdp.match(new RegExp("a=msid:" + streamId + " " + trackId)),
            this + ": " + side + " SDP contains stream " + streamId +
@@ -1369,17 +1361,21 @@ PeerConnectionWrapper.prototype = {
 
   markRemoteTracksAsNegotiated: function() {
     Object.values(this.observedRemoteTrackInfoById).forEach(
         trackInfo => trackInfo.negotiated = true);
   },
 
   rollbackRemoteTracksIfNotNegotiated: function() {
     Object.keys(this.observedRemoteTrackInfoById).forEach(
-        id => delete this.observedRemoteTrackInfoById[id]);
+        id => {
+          if (!this.observedRemoteTrackInfoById[id].negotiated) {
+            delete this.observedRemoteTrackInfoById[id];
+          }
+        });
   },
 
   /**
    * Check that media flow is present on the given media element by waiting for
    * it to reach ready state HAVE_ENOUGH_DATA and progress time further than
    * the start of the check.
    *
    * This ensures, that the stream being played is producing
--- a/dom/media/tests/mochitest/templates.js
+++ b/dom/media/tests/mochitest/templates.js
@@ -374,16 +374,17 @@ var commandsPeerConnectionOfferAnswer = 
   function PC_LOCAL_SET_REMOTE_DESCRIPTION(test) {
     return test.setRemoteDescription(test.pcLocal, test._remote_answer, STABLE)
       .then(() => {
         is(test.pcLocal.signalingState, STABLE,
            "signalingState after local setRemoteDescription is 'stable'");
       })
       .then(() => test.pcLocal.markRemoteTracksAsNegotiated());
   },
+
   function PC_REMOTE_SANE_LOCAL_SDP(test) {
     test.pcRemote.localRequiresTrickleIce =
       sdputils.verifySdp(test._remote_answer, "answer",
                          test._offer_constraints, test._offer_options,
                          test.testOptions);
   },
   function PC_LOCAL_SANE_REMOTE_SDP(test) {
     test.pcLocal.remoteRequiresTrickleIce =
@@ -408,24 +409,16 @@ var commandsPeerConnectionOfferAnswer = 
   function PC_LOCAL_VERIFY_ICE_GATHERING(test) {
     return waitForAnIceCandidate(test.pcLocal);
   },
 
   function PC_REMOTE_VERIFY_ICE_GATHERING(test) {
     return waitForAnIceCandidate(test.pcRemote);
   },
 
-  function PC_LOCAL_CHECK_MEDIA_TRACKS(test) {
-    return test.pcLocal.checkMediaTracks();