Merge autoland to central, a=merge
authorWes Kocher <wkocher@mozilla.com>
Tue, 07 Feb 2017 15:56:57 -0800
changeset 341247 c80c2c7bc043d438f11a32ca08a2fc6743b9152f
parent 341246 e677ba018b22558fef1d07b74d416fd3a28a5dc3 (current diff)
parent 341244 414739984c09671ee55e40121589fbd1c26ed0d1 (diff)
child 341248 f4f374622111022d41dd8d5eb9220624135c534a
push id86667
push userkwierso@gmail.com
push dateWed, 08 Feb 2017 00:55:58 +0000
treeherdermozilla-inbound@497e7f87f137 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone54.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to central, a=merge MozReview-Commit-ID: 8yDHss0OAAq
browser/themes/osx/places/toolbar-lion.png
browser/themes/osx/tabbrowser/alltabs-box-bkgnd-icon-lion.png
browser/themes/osx/tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png
browser/themes/osx/toolbarbutton-dropmarker-lion.png
browser/themes/osx/toolbarbutton-dropmarker-lion@2x.png
security/apps/marketplace-dev-public.crt
security/apps/marketplace-dev-reviewers.crt
security/apps/marketplace-prod-public.crt
security/apps/marketplace-prod-reviewers.crt
security/apps/marketplace-stage.crt
security/apps/trusted-app-public.der
security/manager/ssl/tests/unit/test_signed_apps-marketplace.js
security/manager/ssl/tests/unit/test_signed_manifest/README.md
security/manager/ssl/tests/unit/test_signed_manifest/create_test_files.sh
security/manager/ssl/tests/unit/test_signed_manifest/manifest.webapp
security/manager/ssl/tests/unit/test_signed_manifest/nss_ctypes.py
security/manager/ssl/tests/unit/test_signed_manifest/sign_b2g_manifest.py
security/manager/ssl/tests/unit/test_signed_manifest/testInvalidSignedManifest/manifest.sig
security/manager/ssl/tests/unit/test_signed_manifest/testValidSignedManifest/manifest.sig
security/manager/ssl/tests/unit/test_signed_manifest/trusted_ca1.der
--- a/.taskcluster.yml
+++ b/.taskcluster.yml
@@ -44,17 +44,17 @@ scopes:
 
 tasks:
   - taskId: '{{#as_slugid}}decision task{{/as_slugid}}'
     task:
       created: '{{now}}'
       deadline: '{{#from_now}}1 day{{/from_now}}'
       expires: '{{#from_now}}365 day{{/from_now}}'
       metadata:
-        owner: {{owner}}
+        owner: mozilla-taskcluster-maintenance@mozilla.com
         source: {{{source}}}
         name: "Gecko Decision Task"
         description: |
             The task that creates all of the other tasks in the task graph
 
       workerType: "gecko-decision"
       provisionerId: "aws-provisioner-v1"
 
--- a/addon-sdk/source/python-lib/cuddlefish/prefs.py
+++ b/addon-sdk/source/python-lib/cuddlefish/prefs.py
@@ -18,17 +18,17 @@ DEFAULT_COMMON_PREFS = {
     'extensions.checkCompatibility.nightly' : False,
 
     # Disable extension updates and notifications.
     'extensions.update.enabled' : False,
     'lightweightThemes.update.enabled' : False,
     'extensions.update.notifyUser' : False,
 
     # From:
-    # http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l372
+    # https://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l372
     # Only load extensions from the application and user profile.
     # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
     'extensions.enabledScopes' : 5,
     # Disable metadata caching for installed add-ons by default
     'extensions.getAddons.cache.enabled' : False,
     # Disable intalling any distribution add-ons
     'extensions.installDistroAddons' : False,
     # Allow installing extensions dropped into the profile folder
@@ -110,17 +110,17 @@ DEFAULT_FENNEC_PREFS = {
 # When launching a temporary new Firefox profile, use these preferences.
 DEFAULT_FIREFOX_PREFS = {
     'browser.startup.homepage' : 'about:blank',
     'startup.homepage_welcome_url' : 'about:blank',
     'devtools.browsertoolbox.panel': 'jsdebugger',
     'devtools.chrome.enabled' : True,
 
     # From:
-    # http://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l388
+    # https://hg.mozilla.org/mozilla-central/file/1dd81c324ac7/build/automation.py.in#l388
     # Make url-classifier updates so rare that they won't affect tests.
     'urlclassifier.updateinterval' : 172800,
     # Point the url-classifier to a nonexistent local URL for fast failures.
     'browser.safebrowsing.provider.google.gethashURL' : 'http://localhost/safebrowsing-dummy/gethash',
     'browser.safebrowsing.provider.google.updateURL' : 'http://localhost/safebrowsing-dummy/update',
     'browser.safebrowsing.provider.google4.gethashURL' : 'http://localhost/safebrowsing4-dummy/gethash',
     'browser.safebrowsing.provider.google4.updateURL' : 'http://localhost/safebrowsing4-dummy/update',
     'browser.safebrowsing.provider.mozilla.gethashURL': 'http://localhost/safebrowsing-dummy/gethash',
--- a/addon-sdk/source/test/addons/content-permissions/httpd.js
+++ b/addon-sdk/source/test/addons/content-permissions/httpd.js
@@ -4792,17 +4792,17 @@ nsHttpHeaders.prototype =
 */
   setHeader: function(fieldName, fieldValue, merge)
   {
     var name = headerUtils.normalizeFieldName(fieldName);
     var value = headerUtils.normalizeFieldValue(fieldValue);
 
     // The following three headers are stored as arrays because their real-world
     // syntax prevents joining individual headers into a single header using
-    // ",". See also <http://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
+    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
     if (merge && name in this._headers)
     {
       if (name === "www-authenticate" ||
           name === "proxy-authenticate" ||
           name === "set-cookie")
       {
         this._headers[name].push(value);
       }
--- a/addon-sdk/source/test/addons/content-script-messages-latency/httpd.js
+++ b/addon-sdk/source/test/addons/content-script-messages-latency/httpd.js
@@ -4792,17 +4792,17 @@ nsHttpHeaders.prototype =
 */
   setHeader: function(fieldName, fieldValue, merge)
   {
     var name = headerUtils.normalizeFieldName(fieldName);
     var value = headerUtils.normalizeFieldValue(fieldValue);
 
     // The following three headers are stored as arrays because their real-world
     // syntax prevents joining individual headers into a single header using
-    // ",". See also <http://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
+    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
     if (merge && name in this._headers)
     {
       if (name === "www-authenticate" ||
           name === "proxy-authenticate" ||
           name === "set-cookie")
       {
         this._headers[name].push(value);
       }
--- a/addon-sdk/source/test/addons/e10s-content/lib/httpd.js
+++ b/addon-sdk/source/test/addons/e10s-content/lib/httpd.js
@@ -4793,17 +4793,17 @@ nsHttpHeaders.prototype =
 */
   setHeader: function(fieldName, fieldValue, merge)
   {
     var name = headerUtils.normalizeFieldName(fieldName);
     var value = headerUtils.normalizeFieldValue(fieldValue);
 
     // The following three headers are stored as arrays because their real-world
     // syntax prevents joining individual headers into a single header using
-    // ",". See also <http://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
+    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
     if (merge && name in this._headers)
     {
       if (name === "www-authenticate" ||
           name === "proxy-authenticate" ||
           name === "set-cookie")
       {
         this._headers[name].push(value);
       }
--- a/addon-sdk/source/test/addons/places/lib/httpd.js
+++ b/addon-sdk/source/test/addons/places/lib/httpd.js
@@ -4792,17 +4792,17 @@ nsHttpHeaders.prototype =
 */
   setHeader: function(fieldName, fieldValue, merge)
   {
     var name = headerUtils.normalizeFieldName(fieldName);
     var value = headerUtils.normalizeFieldValue(fieldValue);
 
     // The following three headers are stored as arrays because their real-world
     // syntax prevents joining individual headers into a single header using
-    // ",". See also <http://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
+    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
     if (merge && name in this._headers)
     {
       if (name === "www-authenticate" ||
           name === "proxy-authenticate" ||
           name === "set-cookie")
       {
         this._headers[name].push(value);
       }
--- a/addon-sdk/source/test/lib/httpd.js
+++ b/addon-sdk/source/test/lib/httpd.js
@@ -4793,17 +4793,17 @@ nsHttpHeaders.prototype =
 */
   setHeader: function(fieldName, fieldValue, merge)
   {
     var name = headerUtils.normalizeFieldName(fieldName);
     var value = headerUtils.normalizeFieldValue(fieldValue);
 
     // The following three headers are stored as arrays because their real-world
     // syntax prevents joining individual headers into a single header using
-    // ",". See also <http://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
+    // ",". See also <https://hg.mozilla.org/mozilla-central/diff/9b2a99adc05e/netwerk/protocol/http/src/nsHttpHeaderArray.cpp#l77>
     if (merge && name in this._headers)
     {
       if (name === "www-authenticate" ||
           name === "proxy-authenticate" ||
           name === "set-cookie")
       {
         this._headers[name].push(value);
       }
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -1,17 +1,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/. */
 
 var gFxAccounts = {
 
   _initialized: false,
   _inCustomizationMode: false,
-  _profileFetched: false,
+  _cachedProfile: null,
 
   get weave() {
     delete this.weave;
     return this.weave = Cc["@mozilla.org/weave/service;1"]
                           .getService(Ci.nsISupports)
                           .wrappedJSObject;
   },
 
@@ -137,17 +137,17 @@ var gFxAccounts = {
     }
 
     this._initialized = false;
   },
 
   observe(subject, topic, data) {
     switch (topic) {
       case this.FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION:
-        this._profileFetched = false;
+        this._cachedProfile = null;
         // Fallthrough intended
       default:
         this.updateUI();
         break;
     }
   },
 
   handleEvent(event) {
@@ -250,29 +250,32 @@ var gFxAccounts = {
       }
     }
 
     return fxAccounts.getSignedInUser().then(userData => {
       // userData may be null here when the user is not signed-in, but that's expected
       updateWithUserData(userData);
       // unverified users cause us to spew log errors fetching an OAuth token
       // to fetch the profile, so don't even try in that case.
-      if (!userData || !userData.verified || !profileInfoEnabled || this._profileFetched) {
+      if (!userData || !userData.verified || !profileInfoEnabled) {
         return null; // don't even try to grab the profile.
       }
+      if (this._cachedProfile) {
+        return this._cachedProfile;
+      }
       return fxAccounts.getSignedInUserProfile().catch(err => {
         // Not fetching the profile is sad but the FxA logs will already have noise.
         return null;
       });
     }).then(profile => {
       if (!profile) {
         return;
       }
       updateWithProfile(profile);
-      this._profileFetched = true; // Try to avoid fetching the profile on every UI update
+      this._cachedProfile = profile; // Try to avoid fetching the profile on every UI update
     }).catch(error => {
       // This is most likely in tests, were we quickly log users in and out.
       // The most likely scenario is a user logged out, so reflect that.
       // Bug 995134 calls for better errors so we could retry if we were
       // sure this was the failure reason.
       this.FxAccountsCommon.log.error("Error updating FxA account info", error);
       updateWithUserData(null);
     });
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -141,16 +141,17 @@
     <tooltip id="remoteBrowserTooltip"/>
 
     <!-- for search and content formfill/pw manager -->
 
     <panel type="autocomplete-richlistbox"
            id="PopupAutoComplete"
            noautofocus="true"
            hidden="true"
+           overflowpadding="4"
            norolluponanchor="true" />
 
     <!-- for search with one-off buttons -->
     <panel type="autocomplete" id="PopupSearchAutoComplete" noautofocus="true" hidden="true"/>
 
     <!-- for url bar autocomplete -->
     <panel type="autocomplete-richlistbox"
            id="PopupAutoCompleteRichResult"
--- a/browser/base/content/test/general/browser_audioTabIcon.js
+++ b/browser/base/content/test/general/browser_audioTabIcon.js
@@ -153,19 +153,20 @@ function* test_muting_using_menu(tab, ex
   // Show the popup menu
   let contextMenu = document.getElementById("tabContextMenu");
   let popupShownPromise = BrowserTestUtils.waitForEvent(contextMenu, "popupshown");
   EventUtils.synthesizeMouseAtCenter(tab, {type: "contextmenu", button: 2});
   yield popupShownPromise;
 
   // Check the menu
   let expectedLabel = expectMuted ? "Unmute Tab" : "Mute Tab";
+  let expectedAccessKey = expectMuted ? "m" : "M";
   let toggleMute = document.getElementById("context_toggleMuteTab");
   is(toggleMute.label, expectedLabel, "Correct label expected");
-  is(toggleMute.accessKey, "M", "Correct accessKey expected");
+  is(toggleMute.accessKey, expectedAccessKey, "Correct accessKey expected");
 
   is(toggleMute.hasAttribute("muted"), expectMuted, "Should have the correct state for the muted attribute");
   ok(!toggleMute.hasAttribute("soundplaying"), "Should not have the soundplaying attribute");
 
   yield play(tab);
 
   is(toggleMute.hasAttribute("muted"), expectMuted, "Should have the correct state for the muted attribute");
   ok(toggleMute.hasAttribute("soundplaying"), "Should have the soundplaying attribute");
--- a/browser/base/content/test/general/browser_fxaccounts.js
+++ b/browser/base/content/test/general/browser_fxaccounts.js
@@ -111,17 +111,17 @@ add_task(function* test_unverifiedUser()
 });
 */
 
 add_task(function* test_verifiedUserEmptyProfile() {
   // We see 2 updateUI() calls - one for the signedInUser and one after
   // we first fetch the profile. We want them both to fire or we aren't testing
   // the state we think we are testing.
   let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 2);
-  gFxAccounts._profileFetched = false;
+  gFxAccounts._cachedProfile = null;
   configureProfileURL({}); // successful but empty profile.
   yield setSignedInUser(true); // this will fire the observer that does the update.
   yield promiseUpdateDone;
 
   // Check the world.
   Assert.ok(isFooterVisible())
   Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
   Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
@@ -131,32 +131,33 @@ add_task(function* test_verifiedUserEmpt
   let promisePreferencesOpened = promiseObserver("test:browser_fxaccounts:openPreferences");
   panelUIStatus.click();
   yield promisePreferencesOpened;
   yield signOut();
 });
 
 add_task(function* test_verifiedUserDisplayName() {
   let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 2);
-  gFxAccounts._profileFetched = false;
+  gFxAccounts._cachedProfile = null;
   configureProfileURL({ displayName: "Test User Display Name" });
   yield setSignedInUser(true); // this will fire the observer that does the update.
   yield promiseUpdateDone;
 
   Assert.ok(isFooterVisible())
   Assert.equal(panelUILabel.getAttribute("label"), "Test User Display Name");
   Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
                panelUIStatus.getAttribute("signedinTooltiptext"));
   Assert.equal(panelUIFooter.getAttribute("fxastatus"), "signedin");
   yield signOut();
 });
 
 add_task(function* test_verifiedUserProfileFailure() {
   // profile failure means only one observer fires.
   let promiseUpdateDone = promiseObserver("test:browser_fxaccounts:updateUI", 1);
+  gFxAccounts._cachedProfile = null;
   configureProfileURL(null, 500);
   yield setSignedInUser(true); // this will fire the observer that does the update.
   yield promiseUpdateDone;
 
   Assert.ok(isFooterVisible())
   Assert.equal(panelUILabel.getAttribute("label"), "foo@example.com");
   Assert.equal(panelUIStatus.getAttribute("tooltiptext"),
                panelUIStatus.getAttribute("signedinTooltiptext"));
--- a/browser/components/downloads/DownloadsViewUI.jsm
+++ b/browser/components/downloads/DownloadsViewUI.jsm
@@ -164,76 +164,78 @@ this.DownloadsViewUI.DownloadElementShel
 
     // Dispatch the ValueChange event for accessibility, if possible.
     if (this._progressElement) {
       let event = this.element.ownerDocument.createEvent("Events");
       event.initEvent("ValueChange", true, true);
       this._progressElement.dispatchEvent(event);
     }
 
-    let status = this.statusTextAndTip;
-    this.element.setAttribute("status", status.text);
-    this.element.setAttribute("statusTip", status.tip);
+    let labels = this.statusLabels;
+    this.element.setAttribute("status", labels.status);
+    this.element.setAttribute("hoverStatus", labels.hoverStatus);
+    this.element.setAttribute("fullStatus", labels.fullStatus);
   },
 
   lastEstimatedSecondsLeft: Infinity,
 
   /**
-   * Returns the text for the status line and the associated tooltip. These are
-   * returned by a single property because they are computed together. The
-   * result may be overridden by derived objects.
+   * Returns the labels for the status of normal, full, and hovering cases. These
+   * are returned by a single property because they are computed together.
    */
-  get statusTextAndTip() {
-    return this.rawStatusTextAndTip;
-  },
-
-  /**
-   * Derived objects may call this to get the status text.
-   */
-  get rawStatusTextAndTip() {
+  get statusLabels() {
     let s = DownloadsCommon.strings;
 
-    let text = "";
-    let tip = "";
+    let status = "";
+    let hoverStatus = "";
+    let fullStatus = "";
 
     if (!this.download.stopped) {
       let totalBytes = this.download.hasProgress ? this.download.totalBytes
                                                  : -1;
       let newEstimatedSecondsLeft;
-      [text, newEstimatedSecondsLeft] = DownloadUtils.getDownloadStatus(
+      [status, newEstimatedSecondsLeft] = DownloadUtils.getDownloadStatus(
                                           this.download.currentBytes,
                                           totalBytes,
                                           this.download.speed,
                                           this.lastEstimatedSecondsLeft);
       this.lastEstimatedSecondsLeft = newEstimatedSecondsLeft;
+      hoverStatus = status;
     } else if (this.download.canceled && this.download.hasPartialData) {
       let totalBytes = this.download.hasProgress ? this.download.totalBytes
                                                  : -1;
       let transfer = DownloadUtils.getTransferTotal(this.download.currentBytes,
                                                     totalBytes);
 
       // We use the same XUL label to display both the state and the amount
       // transferred, for example "Paused -  1.1 MB".
-      text = s.statusSeparatorBeforeNumber(s.statePaused, transfer);
+      status = s.statusSeparatorBeforeNumber(s.statePaused, transfer);
+      hoverStatus = status;
     } else if (!this.download.succeeded && !this.download.canceled &&
                !this.download.error) {
-      text = s.stateStarting;
+      status = s.stateStarting;
+      hoverStatus = status;
     } else {
       let stateLabel;
 
-      if (this.download.succeeded) {
+      if (this.download.succeeded && !this.download.target.exists) {
+        stateLabel = s.fileMovedOrMissing;
+        hoverStatus = stateLabel;
+      } else if (this.download.succeeded) {
         // For completed downloads, show the file size (e.g. "1.5 MB").
         if (this.download.target.size !== undefined) {
           let [size, unit] =
             DownloadUtils.convertByteUnits(this.download.target.size);
           stateLabel = s.sizeWithUnits(size, unit);
         } else {
           // History downloads may not have a size defined.
           stateLabel = s.sizeUnknown;
         }
+        status = s.stateCompleted;
+        hoverStatus = status;
       } else if (this.download.canceled) {
         stateLabel = s.stateCanceled;
       } else if (this.download.error.becauseBlockedByParentalControls) {
         stateLabel = s.stateBlockedParentalControls;
       } else if (this.download.error.becauseBlockedByReputationCheck) {
         stateLabel = this.rawBlockedTitleAndDetails[0];
       } else {
         stateLabel = s.stateFailed;
@@ -241,21 +243,25 @@ this.DownloadsViewUI.DownloadElementShel
 
       let referrer = this.download.source.referrer || this.download.source.url;
       let [displayHost, fullHost] = DownloadUtils.getURIHost(referrer);
 
       let date = new Date(this.download.endTime);
       let [displayDate, fullDate] = DownloadUtils.getReadableDates(date);
 
       let firstPart = s.statusSeparator(stateLabel, displayHost);
-      text = s.statusSeparator(firstPart, displayDate);
-      tip = s.statusSeparator(fullHost, fullDate);
+      fullStatus = s.statusSeparator(firstPart, displayDate);
+      status = status || stateLabel;
     }
 
-    return { text, tip: tip || text };
+    return {
+      status,
+      hoverStatus: hoverStatus || fullStatus,
+      fullStatus: fullStatus || status,
+    };
   },
 
   /**
    * Returns [title, [details1, details2]] for blocked downloads.
    */
   get rawBlockedTitleAndDetails() {
     let s = DownloadsCommon.strings;
     if (!this.download.error ||
--- a/browser/components/downloads/content/allDownloadsViewOverlay.js
+++ b/browser/components/downloads/content/allDownloadsViewOverlay.js
@@ -279,29 +279,16 @@ HistoryDownloadElementShell.prototype = 
     }
 
     // Since the state changed, we may need to check the target file again.
     this._targetFileChecked = false;
 
     this._updateState();
   },
 
-  get statusTextAndTip() {
-    let status = this.rawStatusTextAndTip;
-
-    // The base object would show extended progress information in the tooltip,
-    // but we move this to the main view and never display a tooltip.
-    if (!this.download.stopped) {
-      status.text = status.tip;
-    }
-    status.tip = "";
-
-    return status;
-  },
-
   onStateChanged() {
     this._updateState();
 
     if (this.element.selected) {
       goUpdateDownloadCommands();
     } else {
       // If a state change occurs in an item that is not currently selected,
       // this is the only command that may be affected.
--- a/browser/components/downloads/content/download.xml
+++ b/browser/components/downloads/content/download.xml
@@ -41,19 +41,47 @@
                            crop="center"
                            style="min-width: &downloadsSummary.minWidth2;"
                            xbl:inherits="value=displayName,tooltiptext=displayName"/>
           <xul:progressmeter anonid="progressmeter"
                              class="downloadProgress"
                              min="0"
                              max="100"
                              xbl:inherits="mode=progressmode,value=progress,paused=progresspaused"/>
-          <xul:description class="downloadDetails"
+          <xul:description class="downloadDetails downloadDetailsNormal"
+                           crop="end"
+                           xbl:inherits="value=status"/>
+          <xul:description class="downloadDetails downloadDetailsHover"
+                           crop="end"
+                           xbl:inherits="value=hoverStatus"/>
+          <xul:description class="downloadDetails downloadDetailsFull"
+                           crop="end"
+                           xbl:inherits="value=fullStatus,tooltiptext=fullStatus"/>
+          <xul:description class="downloadDetails downloadOpenFile"
+                           crop="end"
+                           value="&openFile.label;"/>
+          <xul:description class="downloadDetails downloadShowMoreInfo"
                            crop="end"
-                           xbl:inherits="value=status,tooltiptext=statusTip"/>
+                           value="&showMoreInformation.label;"/>
+          <xul:stack class="downloadButtonLabels">
+            <xul:description class="downloadDetails downloadShow"
+                             crop="end"
+#ifdef XP_MACOSX
+                             value="&cmd.showMac.label;"
+#else
+                             value="&cmd.show.label;"
+#endif
+                             />
+            <xul:description class="downloadDetails downloadCancel"
+                             crop="end"
+                             value="&cancelDownload.label;"/>
+            <xul:description class="downloadDetails downloadRetry"
+                             crop="end"
+                             value="&retryDownload.label;"/>
+          </xul:stack>
         </xul:vbox>
       </xul:hbox>
       <xul:toolbarseparator />
       <xul:stack class="downloadButtonArea">
         <xul:button class="downloadButton downloadCancel downloadIconCancel"
                     tooltiptext="&cmd.cancel.label;"
                     oncommand="DownloadsView.onDownloadCommand(event, 'downloadsCmd_cancel');"/>
         <xul:button class="downloadButton downloadRetry downloadIconRetry"
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -1032,23 +1032,36 @@ const DownloadsView = {
     DownloadsCommon.log("Context menu has hidden.");
     this.contextMenuOpen = false;
   },
 
   /**
    * Mouse listeners to handle selection on hover.
    */
   onDownloadMouseOver(aEvent) {
+    if (aEvent.originalTarget.classList.contains("downloadButton")) {
+      aEvent.target.classList.add("downloadHoveringButton");
+
+      let button = aEvent.originalTarget;
+      let tooltip = button.getAttribute("tooltiptext");
+      if (tooltip) {
+        button.setAttribute("aria-label", tooltip);
+        button.removeAttribute("tooltiptext");
+      }
+    }
     if (!(this.contextMenuOpen || this.subViewOpen) &&
         aEvent.target.parentNode == this.richListBox) {
       this.richListBox.selectedItem = aEvent.target;
     }
   },
 
   onDownloadMouseOut(aEvent) {
+    if (aEvent.originalTarget.classList.contains("downloadButton")) {
+      aEvent.target.classList.remove("downloadHoveringButton");
+    }
     if (!(this.contextMenuOpen || this.subViewOpen) &&
         aEvent.target.parentNode == this.richListBox) {
       // If the destination element is outside of the richlistitem, clear the
       // selection.
       let element = aEvent.relatedTarget;
       while (element && element != aEvent.target) {
         element = element.parentNode;
       }
--- a/browser/components/migration/AutoMigrate.jsm
+++ b/browser/components/migration/AutoMigrate.jsm
@@ -11,16 +11,19 @@ const { classes: Cc, interfaces: Ci, res
 const kAutoMigrateEnabledPref = "browser.migrate.automigrate.enabled";
 const kUndoUIEnabledPref = "browser.migrate.automigrate.ui.enabled";
 
 const kAutoMigrateBrowserPref = "browser.migrate.automigrate.browser";
 
 const kAutoMigrateLastUndoPromptDateMsPref = "browser.migrate.automigrate.lastUndoPromptDateMs";
 const kAutoMigrateDaysToOfferUndoPref = "browser.migrate.automigrate.daysToOfferUndo";
 
+const kAutoMigrateUndoSurveyPref = "browser.migrate.automigrate.undo-survey";
+const kAutoMigrateUndoSurveyLocalePref = "browser.migrate.automigrate.undo-survey-locales";
+
 const kNotificationId = "automigration-undo";
 
 Cu.import("resource:///modules/MigrationUtils.jsm");
 Cu.import("resource://gre/modules/Preferences.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
@@ -350,16 +353,17 @@ const AutoMigrate = {
           this._purgeUndoState(this.UNDO_REMOVED_REASON_OFFER_REJECTED);
           this._removeNotificationBars();
         },
       },
       {
         label: MigrationUtils.getLocalizedString("automigration.undo.dontkeep.label"),
         accessKey: MigrationUtils.getLocalizedString("automigration.undo.dontkeep.accesskey"),
         callback: () => {
+          this._maybeOpenUndoSurveyTab(win);
           this.undo();
         },
       },
     ];
     notificationBox.appendNotification(
       message, kNotificationId, null, notificationBox.PRIORITY_INFO_HIGH, buttons
     );
     let remainingDays = Preferences.get(kAutoMigrateDaysToOfferUndoPref, 0);
@@ -546,14 +550,57 @@ const AutoMigrate = {
           visitData.url = visitData.url.href;
         } catch (ignoredEx) {}
         Cu.reportError("Failed to remove a visit: " + JSON.stringify(visitData));
         Cu.reportError(ex);
       }
     }
   }),
 
+  /**
+   * Maybe open a new tab with a survey. The tab will only be opened if all of
+   * the following are true:
+   * - the 'browser.migrate.automigrate.undo-survey' pref is not empty.
+   *   It should contain the URL of the survey to open.
+   * - the 'browser.migrate.automigrate.undo-survey-locales' pref, a
+   *   comma-separated list of language codes, contains the language code
+   *   that is currently in use for the 'global' chrome pacakge (ie the
+   *   locale in which the user is currently using Firefox).
+   *   The URL will be passed through nsIURLFormatter to allow including
+   *   build ids etc. The special additional formatting variable
+   *   "%IMPORTEDBROWSER" is also replaced with the name of the browser
+   *   from which we imported data.
+   *
+   * @param {Window} chromeWindow   A reference to the window in which to open a link.
+   */
+  _maybeOpenUndoSurveyTab(chromeWindow) {
+    let canDoSurveyInLocale = false;
+    try {
+      let surveyLocales = Preferences.get(kAutoMigrateUndoSurveyLocalePref, "");
+      surveyLocales = surveyLocales.split(",").map(str => str.trim());
+      // Strip out any empty elements, so an empty pref doesn't
+      // lead to a an array with 1 empty string in it.
+      surveyLocales = new Set(surveyLocales.filter(str => !!str));
+      let chromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"]
+                             .getService(Ci.nsIXULChromeRegistry);
+      canDoSurveyInLocale =
+        surveyLocales.has(chromeRegistry.getSelectedLocale("global"));
+    } catch (ex) {
+      /* ignore exceptions and just don't do the survey. */
+    }
+
+    let migrationBrowser = this.getBrowserUsedForMigration();
+    let rawURL = Preferences.get(kAutoMigrateUndoSurveyPref, "");
+    if (!canDoSurveyInLocale || !migrationBrowser || !rawURL) {
+      return;
+    }
+
+    let url = Services.urlFormatter.formatURL(rawURL);
+    url = url.replace("%IMPORTEDBROWSER%", encodeURIComponent(migrationBrowser));
+    chromeWindow.openUILinkIn(url, "tab");
+  },
+
   QueryInterface: XPCOMUtils.generateQI(
     [Ci.nsIObserver, Ci.nsINavBookmarkObserver, Ci.nsISupportsWeakReference]
   ),
 };
 
 AutoMigrate.init();
--- a/browser/components/migration/tests/browser/browser_undo_notification.js
+++ b/browser/components/migration/tests/browser/browser_undo_notification.js
@@ -33,26 +33,35 @@ add_task(function* autoMigrationUndoNoti
     let notification = getNotification(browser);
     let notificationBox = notification.parentNode;
     notification.querySelector("button.notification-button-default").click();
     ok(!undoCalled, "Undo should not be called when clicking the default button");
     is(notification, notificationBox._closedNotification, "Notification should be closing");
     yield BrowserTestUtils.removeTab(tab);
 
     undoCalled = false;
-    Services.prefs.setCharPref("browser.migrate.automigrate.browser", "someunknownbrowser");
+    Services.prefs.setCharPref("browser.migrate.automigrate.browser", "chrome");
     tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, url, false);
     browser = tab.linkedBrowser;
     if (!getNotification(browser)) {
       info(`Notification for ${url} not immediately present, waiting for it.`);
       yield BrowserTestUtils.waitForNotificationBar(gBrowser, browser, kExpectedNotificationId);
     }
 
     ok(true, `Got notification for ${url}`);
     notification = getNotification(browser);
     notificationBox = notification.parentNode;
+    // Set up the survey:
+    yield SpecialPowers.pushPrefEnv({set: [
+      ["browser.migrate.automigrate.undo-survey", "https://example.com/?browser=%IMPORTEDBROWSER%"],
+      ["browser.migrate.automigrate.undo-survey-locales", "en-US"],
+    ]});
+    let tabOpenedPromise = BrowserTestUtils.waitForNewTab(gBrowser, "https://example.com/?browser=Google%20Chrome");
     notification.querySelector("button:not(.notification-button-default)").click();
     ok(undoCalled, "Undo should be called when clicking the non-default (Don't Keep) button");
     is(notification, notificationBox._closedNotification, "Notification should be closing");
+    let surveyTab = yield tabOpenedPromise;
+    ok(surveyTab, "Should have opened a tab with a survey");
+    yield BrowserTestUtils.removeTab(surveyTab);
     yield BrowserTestUtils.removeTab(tab);
   }
 });
 
--- a/browser/components/migration/tests/unit/test_Chrome_passwords.js
+++ b/browser/components/migration/tests/unit/test_Chrome_passwords.js
@@ -75,17 +75,17 @@ const TEST_LOGINS = [
     timesUsed: 1,
   },
 ];
 
 var crypto = new OSCrypto();
 var dbConn;
 
 function promiseSetPassword(login) {
-  let passwordValue = crypto.stringToArray(crypto.encryptData(login.password));
+  let passwordValue = new Uint8Array(crypto.stringToArray(crypto.encryptData(login.password)));
   return dbConn.execute(`UPDATE logins
                          SET password_value = :password_value
                          WHERE rowid = :rowid
                         `, { password_value: passwordValue,
                              rowid: login.id });
 }
 
 function checkLoginsAreEqual(passwordManagerLogin, chromeLogin, id) {
--- a/browser/components/newtab/NewTabWebChannel.jsm
+++ b/browser/components/newtab/NewTabWebChannel.jsm
@@ -140,16 +140,20 @@ NewTabWebChannelImpl.prototype = {
 
     return false;
   },
 
   /*
    * Obtains all known browser refs
    */
   _getBrowserRefs() {
+    // Some code may try to emit messages after teardown.
+    if (!this._browsers) {
+      return [];
+    }
     let refs = [];
     for (let bRef of this._browsers) {
       /*
        * even though we hold a weak ref to browser, it seems that browser
        * objects aren't gc'd immediately after a tab closes. They stick around
        * in memory, but thankfully they don't have a documentURI in that case
        */
       let browser = bRef.get();
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -809,17 +809,17 @@ userContextNone.accesskey = N
 userContext.aboutPage.label = Manage containers
 userContext.aboutPage.accesskey = O
 
 userContextOpenLink.label = Open Link in New %S Tab
 
 muteTab.label = Mute Tab
 muteTab.accesskey = M
 unmuteTab.label = Unmute Tab
-unmuteTab.accesskey = M
+unmuteTab.accesskey = m
 playTab.label = Play Tab
 playTab.accesskey = l
 
 # LOCALIZATION NOTE (weakCryptoOverriding.message): %S is brandShortName
 weakCryptoOverriding.message = %S recommends that you don’t enter your password, credit card and other personal information on this website.
 revokeOverride.label = Don’t Trust This Website
 revokeOverride.accesskey = D
 
--- a/browser/locales/en-US/chrome/browser/downloads/downloads.dtd
+++ b/browser/locales/en-US/chrome/browser/downloads/downloads.dtd
@@ -84,16 +84,40 @@
 <!ENTITY cmd.chooseUnblock.label          "Remove File or Allow Download">
 <!-- LOCALIZATION NOTE (cmd.chooseOpen.tooltip):
      This is the tooltip of the action button shown when uncommon downloads are
      blocked.This opens a dialog where the user can choose whether to open the
      file or remove the download. Opening is the default option.
      -->
 <!ENTITY cmd.chooseOpen.label             "Open or Remove File">
 
+<!-- LOCALIZATION NOTE (showMoreInformation.label):
+     Displayed when hovering a blocked download, indicates that it's possible to
+     show more information for user to take the next action.
+     -->
+<!ENTITY showMoreInformation.label        "Show more information">
+
+<!-- LOCALIZATION NOTE (openFile.label):
+     Displayed when hovering a complete download, indicates that it's possible to
+     open the file using an app available in the system.
+     -->
+<!ENTITY openFile.label                   "Open File">
+
+<!-- LOCALIZATION NOTE (retryDownload.label):
+     Displayed when hovering a download which is able to be retried by users,
+     indicates that it's possible to download this file again.
+     -->
+<!ENTITY retryDownload.label              "Retry Download">
+
+<!-- LOCALIZATION NOTE (cancelDownload.label):
+     Displayed when hovering a download which is able to be cancelled by users,
+     indicates that it's possible to cancel and stop the download.
+     -->
+<!ENTITY cancelDownload.label             "Cancel Download">
+
 <!-- LOCALIZATION NOTE (blocked.label):
      Shown as a tag before the file name for some types of blocked downloads.
      Note: This string doesn't exist in the UI yet.  See bug 1053890.
      -->
 <!ENTITY blocked.label                    "BLOCKED">
 
 <!-- LOCALIZATION NOTE (learnMore.label):
      Shown as a text link for some types of blocked downloads, for example
--- a/browser/locales/en-US/chrome/browser/downloads/downloads.properties
+++ b/browser/locales/en-US/chrome/browser/downloads/downloads.properties
@@ -12,16 +12,19 @@ stateScanning=Scanning for viruses…
 # Indicates that the download failed because of an error.
 stateFailed=Failed
 # LOCALIZATION NOTE (statePaused):
 # Indicates that the download was paused by the user.
 statePaused=Paused
 # LOCALIZATION NOTE (stateCanceled):
 # Indicates that the download was canceled by the user.
 stateCanceled=Canceled
+# LOCALIZATION NOTE (stateCompleted):
+# Indicates that the download was completed.
+stateCompleted=Completed
 # LOCALIZATION NOTE (stateBlockedParentalControls):
 # Indicates that the download was blocked by the Parental Controls feature of
 # Windows.  "Parental Controls" should be consistently named and capitalized
 # with the display of this feature in Windows.  The following article can
 # provide a reference for the translation of "Parental Controls" in various
 # languages:
 # http://windows.microsoft.com/en-US/windows-vista/Set-up-Parental-Controls
 stateBlockedParentalControls=Blocked by Parental Controls
@@ -44,16 +47,20 @@ stateDirty=Blocked: May contain a virus 
 # are immediately followed by the "Learn More" link, thus they must end with a
 # period.  You may need to adjust "downloadDetails.width" in "downloads.dtd" if
 # this turns out to be longer than the other existing status strings.
 # Note: These strings don't exist in the UI yet.  See bug 1053890.
 blockedMalware=This file contains a virus or malware.
 blockedPotentiallyUnwanted=This file may harm your computer.
 blockedUncommon2=This file is not commonly downloaded.
 
+# LOCALIZATION NOTE (fileMovedOrMissing):
+# Displayed when a complete download which is not at the original folder.
+fileMovedOrMissing=File moved or missing
+
 # LOCALIZATION NOTE (unblockHeaderUnblock, unblockHeaderOpen,
 #                    unblockTypeMalware, unblockTypePotentiallyUnwanted2,
 #                    unblockTypeUncommon2, unblockTip2, unblockButtonOpen,
 #                    unblockButtonUnblock, unblockButtonConfirmBlock):
 # These strings are displayed in the dialog shown when the user asks a blocked
 # download to be unblocked.  The severity of the threat is expressed in
 # descending order by the unblockType strings, it is higher for files detected
 # as malware and lower for uncommon downloads.
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -41,16 +41,17 @@ browser.jar:
   skin/classic/browser/reload-stop-go@2x.png
   skin/classic/browser/searchbar.css
   skin/classic/browser/slowStartup-16.png
   skin/classic/browser/Toolbar.png
   skin/classic/browser/Toolbar@2x.png
   skin/classic/browser/Toolbar-inverted.png
   skin/classic/browser/Toolbar-inverted@2x.png
   skin/classic/browser/toolbarbutton-dropmarker.png
+  skin/classic/browser/toolbarbutton-dropmarker@2x.png
   skin/classic/browser/urlbar-history-dropmarker.png
   skin/classic/browser/urlbar-history-dropmarker@2x.png
   skin/classic/browser/urlbar-popup-blocked.png
   skin/classic/browser/urlbar-popup-blocked@2x.png
   skin/classic/browser/webRTC-sharingDevice-menubar.png
   skin/classic/browser/webRTC-sharingDevice-menubar@2x.png
   skin/classic/browser/webRTC-sharingMicrophone-menubar.png
   skin/classic/browser/webRTC-sharingMicrophone-menubar@2x.png
@@ -115,16 +116,17 @@ browser.jar:
 * skin/classic/browser/preferences/in-content/preferences.css (preferences/in-content/preferences.css)
 * skin/classic/browser/preferences/in-content/dialog.css      (preferences/in-content/dialog.css)
   skin/classic/browser/preferences/applications.css         (preferences/applications.css)
   skin/classic/browser/social/services-16.png               (social/services-16.png)
   skin/classic/browser/social/services-16@2x.png            (social/services-16@2x.png)
   skin/classic/browser/social/services-64.png               (social/services-64.png)
   skin/classic/browser/social/services-64@2x.png            (social/services-64@2x.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon.png             (tabbrowser/alltabs-box-bkgnd-icon.png)
+  skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon@2x.png          (tabbrowser/alltabs-box-bkgnd-icon@2x.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted.png    (tabbrowser/alltabs-box-bkgnd-icon-inverted.png)
   skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png (tabbrowser/alltabs-box-bkgnd-icon-inverted@2x.png)
   skin/classic/browser/tabbrowser/newtab.png                             (tabbrowser/newtab.png)
   skin/classic/browser/tabbrowser/newtab@2x.png                          (tabbrowser/newtab@2x.png)
   skin/classic/browser/tabbrowser/newtab-inverted.png                    (tabbrowser/newtab-inverted.png)
   skin/classic/browser/tabbrowser/newtab-inverted@2x.png                 (tabbrowser/newtab-inverted@2x.png)
   skin/classic/browser/tabbrowser/tab-active-middle.png                  (tabbrowser/tab-active-middle.png)
   skin/classic/browser/tabbrowser/tab-active-middle@2x.png               (tabbrowser/tab-active-middle@2x.png)
@@ -160,21 +162,16 @@ browser.jar:
   skin/classic/browser/sync-128.png
   skin/classic/browser/sync-desktopIcon.svg  (../shared/sync-desktopIcon.svg)
   skin/classic/browser/sync-horizontalbar.png
   skin/classic/browser/sync-horizontalbar@2x.png
   skin/classic/browser/sync-mobileIcon.svg  (../shared/sync-mobileIcon.svg)
   skin/classic/browser/syncProgress-horizontalbar.png
   skin/classic/browser/syncProgress-horizontalbar@2x.png
   skin/classic/browser/Toolbar-background-noise.png         (Toolbar-background-noise.png)
-  skin/classic/browser/lion/toolbarbutton-dropmarker.png    (toolbarbutton-dropmarker-lion.png)
-  skin/classic/browser/toolbarbutton-dropmarker@2x.png      (toolbarbutton-dropmarker-lion@2x.png)
-  skin/classic/browser/lion/tabbrowser/alltabs-box-bkgnd-icon.png      (tabbrowser/alltabs-box-bkgnd-icon-lion.png)
-  skin/classic/browser/tabbrowser/alltabs-box-bkgnd-icon@2x.png        (tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png)
-  skin/classic/browser/lion/places/toolbar.png                         (places/toolbar-lion.png)
   skin/classic/browser/yosemite/Toolbar.png                            (Toolbar-yosemite.png)
   skin/classic/browser/yosemite/Toolbar@2x.png                         (Toolbar-yosemite@2x.png)
   skin/classic/browser/yosemite/menuPanel-customize.png                (menuPanel-customize-yosemite.png)
   skin/classic/browser/yosemite/menuPanel-customize@2x.png             (menuPanel-customize-yosemite@2x.png)
   skin/classic/browser/yosemite/menuPanel-exit.png                     (menuPanel-exit-yosemite.png)
   skin/classic/browser/yosemite/menuPanel-exit@2x.png                  (menuPanel-exit-yosemite@2x.png)
   skin/classic/browser/yosemite/menuPanel-help.png                     (menuPanel-help-yosemite.png)
   skin/classic/browser/yosemite/menuPanel-help@2x.png                  (menuPanel-help-yosemite@2x.png)
@@ -194,19 +191,16 @@ browser.jar:
   skin/classic/browser/e10s-64@2x.png (../shared/e10s-64@2x.png)
 #endif
 
 [extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}] chrome.jar:
 % override chrome://browser/skin/feeds/audioFeedIcon.png                   chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/audioFeedIcon16.png                 chrome://browser/skin/feeds/feedIcon16.png
 % override chrome://browser/skin/feeds/videoFeedIcon.png                   chrome://browser/skin/feeds/feedIcon.png
 % override chrome://browser/skin/feeds/videoFeedIcon16.png                 chrome://browser/skin/feeds/feedIcon16.png
-% override chrome://browser/skin/toolbarbutton-dropmarker.png              chrome://browser/skin/lion/toolbarbutton-dropmarker.png                 os=Darwin osversion>=10.7
-% override chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png     chrome://browser/skin/lion/tabbrowser/alltabs-box-bkgnd-icon.png        os=Darwin osversion>=10.7
-% override chrome://browser/skin/places/toolbar.png                        chrome://browser/skin/lion/places/toolbar.png                           os=Darwin osversion>=10.7
 % override chrome://browser/skin/Toolbar.png                               chrome://browser/skin/yosemite/Toolbar.png                              os=Darwin osversion>=10.10
 % override chrome://browser/skin/Toolbar@2x.png                            chrome://browser/skin/yosemite/Toolbar@2x.png                           os=Darwin osversion>=10.10
 % override chrome://browser/skin/menuPanel-customize.png                   chrome://browser/skin/yosemite/menuPanel-customize.png                  os=Darwin osversion>=10.10
 % override chrome://browser/skin/menuPanel-customize@2x.png                chrome://browser/skin/yosemite/menuPanel-customize@2x.png               os=Darwin osversion>=10.10
 % override chrome://browser/skin/menuPanel-exit.png                        chrome://browser/skin/yosemite/menuPanel-exit.png                       os=Darwin osversion>=10.10
 % override chrome://browser/skin/menuPanel-exit@2x.png                     chrome://browser/skin/yosemite/menuPanel-exit@2x.png                    os=Darwin osversion>=10.10
 % override chrome://browser/skin/menuPanel-help.png                        chrome://browser/skin/yosemite/menuPanel-help.png                       os=Darwin osversion>=10.10
 % override chrome://browser/skin/menuPanel-help@2x.png                     chrome://browser/skin/yosemite/menuPanel-help@2x.png                    os=Darwin osversion>=10.10
deleted file mode 100644
index ac3358c91bc00e87bd41e49e5cf9672ecd685103..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
index 168daf9cef766934a4be4a20c0db72ee8e36bc78..ac3358c91bc00e87bd41e49e5cf9672ecd685103
GIT binary patch
literal 1318
zc$@(y1=;$EP)<h;3K|Lk000e1NJLTq002+`000mO1^@s6fl2tm000E-Nkl<Zc-qaF
zZAhC}6vrnuzU!has8owXQPw&v_%1SyNEcB@{GhbMw_0afoUYvx=H}vT+Eg=*cCm>~
zVjG**YDBxjXq{l|Ms<_H94L%|!a!wT^@DzP{{tuNA)WQfmM|~;IC<{<-}{`L`*xDo
z_V@SyS6)#j!S8GjD*k+b1^A8af#oO#@Hi+JJU;=~*t!d~pWx5_oJ470VBm9D6I<y~
z58#P_fPf!iUjQT5*+C~;Dn@FDZV@)wp8=FeBqo@z!53ud`9B8`B^BHjp&KKuH_oS~
zrdGi`1l`~Puz()W!PY|c+&-3^oZJ8_9OF-Kc|`!v02c?ZgRP6}y$>KSUp-g~4i0`M
zLjMf>#C@b9^kmZ%3I#dY&#TVNE8sR;GuQW*m6c6EpW)$qx3_rsa2k999)s_|RpvVA
zV*4C?%evEt1`tI8T6oLc2i@V};bS5KG77ZRhx@hw$pLzyAIkjv{F~%>Y;5ev@bIu@
zZ*NaWmY%6TJ3D)jbiO=(IA}lc3hxEF$jC^0MMcG^QmJ%iWMnu|H{RCPHUw)W9qXSS
z=md%a%z!DL0X5JdfKCw(-QihMbKfZ*OL2gH0{jY=fD!cBY&HX}N^p#<)9LJ?)yFKc
zenK$Drnk8JCL|<0W<T3OXL@?NeRFfOizW(Gf~L8-IU}qb?L(~VN=izaekp(`r@#b9
zSI6Qu<|72qAtHcQ(hFz@Iv&#nPI>4b(b(V;Gq|v@06+dN>+9<&FgM*A)<5#a7M`7*
z?Fb7Cqod*qFwD%%Xd)saT6vOOAQHMbcEv)vkdP27>0Sz8d3m`!F)@+8&{sU*MWA9X
zVPLz60Nx_K8y@3h(4Uf$GF4SoRVdWw<>k@)to%+5xGt4Si-iFU4GqobGgZSnYgSg)
zH$J+BWqQ5d%$HTK!{JB@3JRjYX=`d~XeWdST<Ien>8am8ZQ<kK1EbMsiI0!B@xiSE
z=Rp$!Xb};>LD0y3E&?qkWyE5!+(LUJi1X<4KIkS23JUZzar^~}*y$oXPf|U#la8qs
zyz>ul@$ey|va)i7gZMLW@QR=0BV!r-LhaDmNq^WS^7hWoj=HtA^$xZz1>`aZ&?F*&
zeV_qciHeFcX*3%9?(Xhow7qpm4rbsl&<s8W)8GYJe!k#dB_#IkEsPm&Y}CQng&MV5
zP2XLO9bw$w-lq29y1Ke+V$&E2cxP>G?JBn2T}W?;JOgdW-fvV_S39=0wzR0r2geS%
zh2I5E&;&H4rKRL#D>zG5E|-(@YHl9|RlZK7OG-*;{BhtekusTV8cFnhl}cqp?wLYq
zRZ&sVXWk~#5#YV~`T0JaSL282b8>QAi;IiB_*@P`#W-&;8068>(f8<lqx1pwb$l~c
zlf`ob)l+*+Ow8!Oz<|OdkzV%}Palv%X*q+Sl167AxB#@PtE*>_16wJTD=aMh^56cH
ziv#CG=xTw?o7snrSy@@pn$6}RL7q1N&H*E9l+?bwyi5Uo!`EB5xVX5R-`T=9@I#;j
zdgQa;^Y3y^Zf<VRQT#1TpI-+j`H@zH3ucH`v_NwbMEm2<1e|y0vC5`!dERSoZoX?W
znLgjx*ih<py7v0|dRt~@<}lKi2S}(tJc<GIEW+El*57}G@K|qxPR<lcKr#p-%g;^R
co+k9+FA1)f{H_9Cg#Z8m07*qoM6N<$f+2l=ApigX
deleted file mode 100644
index 4d71308d278644ee9dda74ddac9207c0b1b26b3b..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
index 94a11fe5f9bf2b6b506de7e810893125d66b018c..4d71308d278644ee9dda74ddac9207c0b1b26b3b
GIT binary patch
literal 538
zc$@(m0_FXQP)<h;3K|Lk000e1NJLTq001)p000yS1^@s6AP5Dd0005uNkl<Zc-rlj
zze@sP9LBrzygV@rlEjRVB2zLWD8!Z$hyIMVh=P6${TL%CXpNwPhG;CJA!seCMFOcM
zS^^=Vr52HvhPUT|Z<AoxFR=39!^88u-;;Yd?)9xvO8ptCWqyLildn=O^W$YSpaTP#
zpcYtf&`WN}oL0$Ybl{W+_W~dAg8-FYa!cm)N-d)S2XKJ~DbNnOKsQx<K-OI{uT^Rp
zC-BHy=m33S5TvQ}lKW-OS+)$Wac}^3!48$4x!s4uwFGX#HMpYEGk>Ry3F<+sKRvnU
zPL3(h(5&*L<`tEmIoD;*EL)~fC`4kh*sPQqq0%$ATc%hn#v_r)7Vg~!YgBsXHr|XE
zw4UC*OeZI{?*pSps%7e2QR$gW8E@G)BWU@2z9$q4&EO$Msr1abZWAq+%MApB!A<<e
z29=)qJ7o;u0nN*2Dt>(PypovNf9#yQP*i&6T$ee+&NriHv)N=c8l9rjGyfotOeQlN
z4u{vN^fq=g2e3dRXj{Ed{fF77_0;rEo=VSL)-BH4-OZdJPNn}OCP+{}xHZ>-CJ@@V
zRJ~UZYJo~Gd0ho>%_W6Q;Fgcv#{yLGZduoV$8o0g6yPfP_y1*QGfmKmppoi9vs&iA
cm-!A}0h)`@YUO@9WdHyG07*qoM6N<$g0_nLLjV8(
rename from browser/themes/osx/tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png
rename to browser/themes/osx/tabbrowser/alltabs-box-bkgnd-icon@2x.png
deleted file mode 100644
index 09d80a1b25a84578587cc1d41afe6fd63dff2a93..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
index f4cdb664ba95d3d36ea4074de8dc2e7c4696a931..09d80a1b25a84578587cc1d41afe6fd63dff2a93
GIT binary patch
literal 150
zc%17D@N?(olHy`uVBq!ia0vp^>_E)Q!3HEdXMMW?q+&f?978H@nRagEY%maTUHm{U
zT#6&gx_54CZ^VxN8@o^WPUPI=@W=ne!N;HPvEJ2-``9u2=>Iq`$zU&Wr7*GO?NQm&
zi|3tvb0s;s(8~YC-P%q=IUT>}7bT7y+4ha`t-O<^eCv-;phXOxu6{1-oD!M<-g!B*
rename from browser/themes/osx/toolbarbutton-dropmarker-lion@2x.png
rename to browser/themes/osx/toolbarbutton-dropmarker@2x.png
--- a/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css
+++ b/browser/themes/shared/downloads/allDownloadsViewOverlay.inc.css
@@ -55,16 +55,24 @@
 .downloadDetails {
   opacity: 0.7;
   font-size: 95%;
   /* Use calc() to keep the height consistent with .downloadTarget, so that the
      progress bar can be vertically centered. */
   margin: 4px 0 calc(1em / 0.95 - 1em);
 }
 
+.downloadDetailsNormal,
+.downloadDetailsHover,
+.downloadOpenFile,
+.downloadShowMoreInfo,
+.downloadButtonLabels {
+  display: none;
+}
+
 .downloadButton {
   -moz-appearance: none;
   -moz-box-align: center;
   background: transparent;
   min-width: 0;
   min-height: 0;
   margin: 0;
   border: none;
--- a/browser/themes/shared/downloads/downloads.inc.css
+++ b/browser/themes/shared/downloads/downloads.inc.css
@@ -227,16 +227,58 @@ richlistitem[type="download"]:last-child
 #downloadsSummaryDetails,
 .downloadDetails {
   opacity: var(--downloads-item-details-opacity);
   /* Use calc() to keep the height consistent with .downloadTarget, so that the
      progress bar can be vertically centered. */
   margin: 4px 0 calc(1em / var(--downloads-item-font-size-factor) - 1em);
 }
 
+/* The following rules control which message is shown under the name of the
+   download, using a set of elements that share the class ".downloadDetails".
+   At any given time, only one of these elements is displayed. We use a set of
+   rules to hide the elements that shouldn't be displayed in each case. */
+
+/* The full status message is only displayed in the Downloads View. */
+.downloadDetailsFull {
+  display: none;
+}
+
+/* When hovering the mouse pointer over the item, instead of the normal message
+   we display a more detailed one. */
+@item@:hover > .downloadMainArea > .downloadContainer > .downloadDetailsNormal,
+@item@:not(:hover) > .downloadMainArea > .downloadContainer > .downloadDetailsHover {
+  display: none;
+}
+
+/* When hovering the action button in particular, instead of the usual hover
+   message we display the command associated with the button. */
+@item@.downloadHoveringButton > .downloadMainArea > .downloadContainer > .downloadDetailsHover,
+@item@:not(.downloadHoveringButton) > .downloadMainArea > .downloadContainer > .downloadButtonLabels {
+  display: none;
+}
+
+/* When hovering the main area of a finished download whose target exists,
+   instead of the usual hover message we display the "Open File" command. */
+@itemFinished@[exists] > .downloadMainArea:hover > .downloadContainer > .downloadDetailsHover,
+@itemNotFinished@ > .downloadMainArea > .downloadContainer > .downloadOpenFile,
+@item@:not([exists]) > .downloadMainArea > .downloadContainer > .downloadOpenFile,
+.downloadMainArea:not(:hover) > .downloadContainer > .downloadOpenFile {
+  display: none;
+}
+
+/* When hovering items blocked by Application Reputation, instead of the other
+   hover messages we display the "Show more information" label. */
+@item@[verdict] > .downloadMainArea > .downloadContainer > .downloadDetailsHover,
+@item@[verdict] > .downloadMainArea > .downloadContainer > .downloadButtonLabels,
+@item@:not([verdict]) > .downloadMainArea > .downloadContainer > .downloadShowMoreInfo,
+@item@:not(:hover) > .downloadMainArea > .downloadContainer > .downloadShowMoreInfo {
+  display: none;
+}
+
 @item@[verdict] > toolbarseparator {
   visibility: hidden;
 }
 
 .downloadButton {
   -moz-appearance: none;
   min-width: 58px;
   margin: 0;
--- a/build/compare-mozconfig/compare-mozconfigs.py
+++ b/build/compare-mozconfig/compare-mozconfigs.py
@@ -1,14 +1,14 @@
 #!/usr/bin/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/.
 
-# originally from http://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py
+# originally from https://hg.mozilla.org/build/tools/file/4ab9c1a4e05b/scripts/release/compare-mozconfigs.py
 
 from __future__ import unicode_literals
 
 import logging
 import os
 import site
 import sys
 import urllib2
--- a/build/util/count_ctors.py
+++ b/build/util/count_ctors.py
@@ -49,16 +49,16 @@ def count_ctors(filename):
 
 if __name__ == '__main__':
     for f in sys.argv[1:]:
         perfherder_data = {
             "framework": {"name": "build_metrics"},
             "suites": [{
                 "name": "compiler_metrics",
                 "subtests": [{
-                    "name": "num_constructors",
+                    "name": "num_static_constructors",
                     "value": count_ctors(f),
                     "alertThreshold": 0.25
                 }]}
             ]
         }
         print "PERFHERDER_DATA: %s" % json.dumps(perfherder_data)
 
--- a/devtools/client/netmonitor/components/toolbar.js
+++ b/devtools/client/netmonitor/components/toolbar.js
@@ -63,21 +63,22 @@ function Toolbar({
 
   const buttons = requestFilterTypes.entrySeq().map(([type, checked]) => {
     let classList = ["menu-filter-button"];
     checked && classList.push("checked");
 
     return (
       button({
         id: `requests-menu-filter-${type}-button`,
+        className: classList.join(" "),
         key: type,
-        className: classList.join(" "),
-        "data-key": type,
         onClick: toggleRequestFilterType,
         onKeyDown: toggleRequestFilterType,
+        "aria-pressed": checked,
+        "data-key": type,
       },
         L10N.getStr(`netmonitor.toolbar.filter.${type}`)
       )
     );
   }).toArray();
 
   return (
     span({ className: "devtools-toolbar devtools-toolbar-container" },
--- a/devtools/client/netmonitor/test/head.js
+++ b/devtools/client/netmonitor/test/head.js
@@ -421,19 +421,23 @@ function testFilterButtons(monitor, filt
 function testFilterButtonsCustom(aMonitor, aIsChecked) {
   let doc = aMonitor.panelWin.document;
   let buttons = doc.querySelectorAll(".menu-filter-button");
   for (let i = 0; i < aIsChecked.length; i++) {
     let button = buttons[i];
     if (aIsChecked[i]) {
       is(button.classList.contains("checked"), true,
         "The " + button.id + " button should have a 'checked' class.");
+      is(button.getAttribute("aria-pressed"), "true",
+        "The " + button.id + " button should set 'aria-pressed' = true.");
     } else {
       is(button.classList.contains("checked"), false,
         "The " + button.id + " button should not have a 'checked' class.");
+      is(button.getAttribute("aria-pressed"), "false",
+        "The " + button.id + " button should set 'aria-pressed' = false.");
     }
   }
 }
 
 /**
  * Loads shared/frame-script-utils.js in the specified tab.
  *
  * @param tab
--- a/devtools/client/shared/components/frame.js
+++ b/devtools/client/shared/components/frame.js
@@ -164,53 +164,60 @@ module.exports = createClass({
     if (showFunctionName) {
       let functionDisplayName = frame.functionDisplayName;
       if (!functionDisplayName && showAnonymousFunctionName) {
         functionDisplayName = webl10n.getStr("stacktrace.anonymousFunction");
       }
 
       if (functionDisplayName) {
         elements.push(
-          dom.span({ className: "frame-link-function-display-name" },
-            functionDisplayName),
+          dom.span({
+            key: "function-display-name",
+            className: "frame-link-function-display-name",
+          }, functionDisplayName),
           " "
         );
       }
     }
 
     let displaySource = showFullSourceUrl ? long : short;
     if (isSourceMapped) {
       displaySource = getSourceMappedFile(displaySource);
     } else if (showEmptyPathAsHost && (displaySource === "" || displaySource === "/")) {
       displaySource = host;
     }
 
     sourceElements.push(dom.span({
+      key: "filename",
       className: "frame-link-filename",
     }, displaySource));
 
     // If we have a line number > 0.
     if (line) {
       let lineInfo = `:${line}`;
       // Add `data-line` attribute for testing
       attributes["data-line"] = line;
 
       // Intentionally exclude 0
       if (column) {
         lineInfo += `:${column}`;
         // Add `data-column` attribute for testing
         attributes["data-column"] = column;
       }
 
-      sourceElements.push(dom.span({ className: "frame-link-line" }, lineInfo));
+      sourceElements.push(dom.span({
+        key: "line",
+        className: "frame-link-line"
+      }, lineInfo));
     }
 
     // Inner el is useful for achieving ellipsis on the left and correct LTR/RTL
     // ordering. See CSS styles for frame-link-source-[inner] and bug 1290056.
     let sourceInnerEl = dom.span({
+      key: "source-inner",
       className: "frame-link-source-inner",
       title: isLinkable ?
         l10n.getFormatStr("frame.viewsourceindebugger", tooltip) : tooltip,
     }, sourceElements);
 
     // If source is not a URL (self-hosted, eval, etc.), don't make
     // it an anchor link, as we can't link to it.
     if (isLinkable) {
@@ -220,20 +227,25 @@ module.exports = createClass({
           onClick(this.getSource(frame));
         },
         href: source,
         className: "frame-link-source",
         draggable: false,
       }, sourceInnerEl);
     } else {
       sourceEl = dom.span({
+        key: "source",
         className: "frame-link-source",
       }, sourceInnerEl);
     }
     elements.push(sourceEl);
 
     if (showHost && host) {
-      elements.push(" ", dom.span({ className: "frame-link-host" }, host));
+      elements.push(" ");
+      elements.push(dom.span({
+        key: "host",
+        className: "frame-link-host",
+      }, host));
     }
 
     return dom.span(attributes, ...elements);
   }
 });
--- a/devtools/client/shared/components/stack-trace.js
+++ b/devtools/client/shared/components/stack-trace.js
@@ -40,25 +40,27 @@ const StackTrace = createClass({
   render() {
     let {
       stacktrace,
       onViewSourceInDebugger,
       onViewSourceInScratchpad
     } = this.props;
 
     let frames = [];
-    stacktrace.forEach(s => {
+    stacktrace.forEach((s, i) => {
       if (s.asyncCause) {
         frames.push("\t", AsyncFrame({
+          key: `${i}-asyncframe`,
           asyncCause: s.asyncCause
         }), "\n");
       }
 
       let source = s.filename.split(" -> ").pop();
       frames.push("\t", Frame({
+        key: `${i}-frame`,
         frame: {
           functionDisplayName: s.functionName,
           source,
           line: s.lineNumber,
           column: s.columnNumber,
         },
         showFunctionName: true,
         showAnonymousFunctionName: true,
--- a/dom/animation/test/chrome/test_running_on_compositor.html
+++ b/dom/animation/test/chrome/test_running_on_compositor.html
@@ -249,17 +249,17 @@ promise_test(function(t) {
           t.step(function() {
             assert_animation_is_running_on_compositor(animation,
               'Animation reports that it is running on the compositor'
                + ' in requestAnimationFrame callback');
           });
 
           // we have to wait at least 200ms because this animation is
           // unthrottled on every 200ms.
-          // See http://hg.mozilla.org/mozilla-central/file/cafb1c90f794/layout/style/AnimationCommon.cpp#l863
+          // See https://hg.mozilla.org/mozilla-central/file/cafb1c90f794/layout/style/AnimationCommon.cpp#l863
           if (window.performance.now() - timeAtStart > 200) {
             resolve();
             return;
           }
           window.requestAnimationFrame(handleFrame);
         }
         window.requestAnimationFrame(handleFrame);
       });
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -196,16 +196,21 @@
 #include "mozilla/widget/PuppetBidiKeyboard.h"
 #include "mozilla/RemoteSpellCheckEngineChild.h"
 #include "GMPServiceChild.h"
 #include "GfxInfoBase.h"
 #include "gfxPlatform.h"
 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
 #include "VRManagerChild.h"
 
+#ifdef MOZ_WIDGET_GTK
+#include "nsAppRunner.h"
+#endif
+
+
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::ipc;
 using namespace mozilla::dom::workers;
 using namespace mozilla::media;
 using namespace mozilla::embedding;
 using namespace mozilla::gmp;
@@ -522,26 +527,26 @@ ContentChild::Init(MessageLoop* aIOLoop,
                    bool aIsForBrowser)
 {
 #ifdef MOZ_WIDGET_GTK
   // We need to pass a display down to gtk_init because it's not going to
   // use the one from the environment on its own when deciding which backend
   // to use, and when starting under XWayland, it may choose to start with
   // the wayland backend instead of the x11 backend.
   // The DISPLAY environment variable is normally set by the parent process.
-  char* display_name = PR_GetEnv("DISPLAY");
+  const char* display_name = DetectDisplay();
   if (display_name) {
     int argc = 3;
     char option_name[] = "--display";
     char* argv[] = {
       // argv0 is unused because g_set_prgname() was called in
       // XRE_InitChildProcess().
       nullptr,
       option_name,
-      display_name,
+      const_cast<char*>(display_name),
       nullptr
     };
     char** argvp = argv;
     gtk_init(&argc, &argvp);
   } else {
     gtk_init(nullptr, nullptr);
   }
 #endif
--- a/dom/locales/en-US/chrome/layout/htmlparser.properties
+++ b/dom/locales/en-US/chrome/layout/htmlparser.properties
@@ -12,17 +12,17 @@ EncLateMetaReload=The page was reloaded,
 EncLateMetaTooLate=The character encoding declaration of document was found too late for it to take effect. The encoding declaration needs to be moved to be within the first 1024 bytes of the file.
 EncMetaUnsupported=An unsupported character encoding was declared for the HTML document using a meta tag. The declaration was ignored.
 EncProtocolUnsupported=An unsupported character encoding was declared on the transfer protocol level. The declaration was ignored.
 EncBomlessUtf16=Detected UTF-16-encoded Basic Latin-only text without a byte order mark and without a transfer protocol-level declaration. Encoding this content in UTF-16 is inefficient and the character encoding should have been declared in any case.
 EncMetaUtf16=A meta tag was used to declare the character encoding as UTF-16. This was interpreted as an UTF-8 declaration instead.
 EncMetaUserDefined=A meta tag was used to declare the character encoding as x-user-defined. This was interpreted as a windows-1252 declaration instead for compatibility with intentionally mis-encoded legacy fonts. This site should migrate to Unicode.
 
 # The bulk of the messages below are derived from 
-# http://hg.mozilla.org/projects/htmlparser/file/1f633cef7de7/src/nu/validator/htmlparser/impl/ErrorReportingTokenizer.java
+# https://hg.mozilla.org/projects/htmlparser/file/1f633cef7de7/src/nu/validator/htmlparser/impl/ErrorReportingTokenizer.java
 # which is available under the MIT license.
 
 # Tokenizer errors
 errGarbageAfterLtSlash=Garbage after “</”.
 errLtSlashGt=Saw “</>”. Probable causes: Unescaped “<” (escape as “&lt;”) or mistyped end tag.
 errCharRefLacksSemicolon=Character reference was not terminated by a semicolon.
 errNoDigitsInNCR=No digits in numeric character reference.
 errGtInSystemId=“>” in system identifier.
--- a/dom/media/ADTSDemuxer.cpp
+++ b/dom/media/ADTSDemuxer.cpp
@@ -48,59 +48,63 @@ namespace adts {
 // M        13            frame length, this value must include 7 or 9 bytes of
 //                        header length: FrameLength =
 //                          (ProtectionAbsent == 1 ? 7 : 9) + size(AACFrame)
 // O        11            Buffer fullness
 // P        2             Number of AAC frames(RDBs) in ADTS frame minus 1, for
 //                        maximum compatibility always use 1 AAC frame per ADTS
 //                        frame
 // Q        16            CRC if protection absent is 0
-class FrameHeader {
+class FrameHeader
+{
 public:
   uint32_t mFrameLength;
   uint32_t mSampleRate;
   uint32_t mSamples;
   uint32_t mChannels;
   uint8_t  mObjectType;
   uint8_t  mSamplingIndex;
   uint8_t  mChannelConfig;
   uint8_t  mNumAACFrames;
   bool     mHaveCrc;
 
   // Returns whether aPtr matches a valid ADTS header sync marker
-  static bool MatchesSync(const uint8_t* aPtr) {
+  static bool MatchesSync(const uint8_t* aPtr)
+  {
     return aPtr[0] == 0xFF && (aPtr[1] & 0xF6) == 0xF0;
   }
 
   FrameHeader() { Reset(); }
 
   // Header size
   size_t HeaderSize() const { return (mHaveCrc) ? 9 : 7; }
 
   bool IsValid() const { return mFrameLength > 0; }
 
   // Resets the state to allow for a new parsing session.
   void Reset() { PodZero(this); }
 
   // Returns whether the byte creates a valid sequence up to this point.
-  bool Parse(const uint8_t* aPtr) {
+  bool Parse(const uint8_t* aPtr)
+  {
     const uint8_t* p = aPtr;
 
     if (!MatchesSync(p)) {
       return false;
     }
 
     // AAC has 1024 samples per frame per channel.
     mSamples = 1024;
 
     mHaveCrc = !(p[1] & 0x01);
     mObjectType = ((p[2] & 0xC0) >> 6) + 1;
     mSamplingIndex = (p[2] & 0x3C) >> 2;
     mChannelConfig = (p[2] & 0x01) << 2 | (p[3] & 0xC0) >> 6;
-    mFrameLength = (p[3] & 0x03) << 11 | (p[4] & 0xFF) << 3 | (p[5] & 0xE0) >> 5;
+    mFrameLength =
+      (p[3] & 0x03) << 11 | (p[4] & 0xFF) << 3 | (p[5] & 0xE0) >> 5;
     mNumAACFrames = (p[6] & 0x03) + 1;
 
     static const int32_t SAMPLE_RATES[16] = {
       96000, 88200, 64000, 48000,
       44100, 32000, 24000, 22050,
       16000, 12000, 11025,  8000,
       7350
     };
@@ -111,56 +115,56 @@ public:
 
     return true;
   }
 };
 
 
 // adts::Frame - Frame meta container used to parse and hold a frame
 // header and side info.
-class Frame {
+class Frame
+{
 public:
-  Frame() : mOffset(0), mHeader() {}
+  Frame() : mOffset(0), mHeader() { }
 
   int64_t Offset() const { return mOffset; }
-  size_t Length() const {
-    // TODO: If fields are zero'd when invalid, this check wouldn't be necessary.
+  size_t Length() const
+  {
+    // TODO: If fields are zero'd when invalid, this check wouldn't be
+    // necessary.
     if (!mHeader.IsValid()) {
       return 0;
     }
 
     return mHeader.mFrameLength;
   }
 
   // Returns the offset to the start of frame's raw data.
-  int64_t PayloadOffset() const {
-    return mOffset + mHeader.HeaderSize();
-  }
+  int64_t PayloadOffset() const { return mOffset + mHeader.HeaderSize(); }
 
   // Returns the length of the frame's raw data (excluding the header) in bytes.
-  size_t PayloadLength() const {
-    // TODO: If fields are zero'd when invalid, this check wouldn't be necessary.
+  size_t PayloadLength() const
+  {
+    // TODO: If fields are zero'd when invalid, this check wouldn't be
+    // necessary.
     if (!mHeader.IsValid()) {
       return 0;
     }
 
     return mHeader.mFrameLength - mHeader.HeaderSize();
   }
 
   // Returns the parsed frame header.
-  const FrameHeader& Header() const {
-    return mHeader;
-  }
+  const FrameHeader& Header() const { return mHeader; }
 
-  bool IsValid() const {
-    return mHeader.IsValid();
-  }
+  bool IsValid() const { return mHeader.IsValid(); }
 
   // Resets the frame header and data.
-  void Reset() {
+  void Reset()
+  {
     mHeader.Reset();
     mOffset = 0;
   }
 
   // Returns whether the valid
   bool Parse(int64_t aOffset, uint8_t* aStart, uint8_t* aEnd) {
     MOZ_ASSERT(aStart && aEnd);
 
@@ -182,45 +186,49 @@ private:
   // The offset to the start of the header.
   int64_t mOffset;
 
   // The currently parsed frame header.
   FrameHeader mHeader;
 };
 
 
-class FrameParser {
+class FrameParser
+{
 public:
 
   // Returns the currently parsed frame. Reset via Reset or EndFrameSession.
   const Frame& CurrentFrame() const { return mFrame; }
 
 
   // Returns the first parsed frame. Reset via Reset.
   const Frame& FirstFrame() const { return mFirstFrame; }
 
   // Resets the parser. Don't use between frames as first frame data is reset.
-  void Reset() {
+  void Reset()
+  {
     EndFrameSession();
     mFirstFrame.Reset();
   }
 
   // Clear the last parsed frame to allow for next frame parsing, i.e.:
   // - sets PrevFrame to CurrentFrame
   // - resets the CurrentFrame
   // - resets ID3Header if no valid header was parsed yet
-  void EndFrameSession() {
+  void EndFrameSession()
+  {
     mFrame.Reset();
   }
 
-  // Parses contents of given ByteReader for a valid frame header and returns true
-  // if one was found. After returning, the variable passed to 'aBytesToSkip' holds
-  // the amount of bytes to be skipped (if any) in order to jump across a large
-  // ID3v2 tag spanning multiple buffers.
-  bool Parse(int64_t aOffset, uint8_t* aStart, uint8_t* aEnd) {
+  // Parses contents of given ByteReader for a valid frame header and returns
+  // true if one was found. After returning, the variable passed to
+  // 'aBytesToSkip' holds the amount of bytes to be skipped (if any) in order to
+  // jump across a large ID3v2 tag spanning multiple buffers.
+  bool Parse(int64_t aOffset, uint8_t* aStart, uint8_t* aEnd)
+  {
     const bool found = mFrame.Parse(aOffset, aStart, aEnd);
 
     if (mFrame.Length() && !mFirstFrame.Length()) {
       mFirstFrame = mFrame;
     }
 
     return found;
   }
@@ -295,17 +303,18 @@ InitAudioSpecificConfig(const Frame& fra
 }
 
 } // namespace adts
 
 // ADTSDemuxer
 
 ADTSDemuxer::ADTSDemuxer(MediaResource* aSource)
   : mSource(aSource)
-{}
+{
+}
 
 bool
 ADTSDemuxer::InitInternal()
 {
   if (!mTrackDemuxer) {
     mTrackDemuxer = new ADTSTrackDemuxer(mSource);
   }
   return mTrackDemuxer->Init();
@@ -370,23 +379,21 @@ ADTSTrackDemuxer::ADTSTrackDemuxer(Media
   , mChannels(0)
 {
   Reset();
 }
 
 ADTSTrackDemuxer::~ADTSTrackDemuxer()
 {
   delete mParser;
-  mParser = nullptr;
 }
 
 bool
 ADTSTrackDemuxer::Init()
 {
-
   FastSeek(media::TimeUnit());
   // Read the first frame to fetch sample rate and other meta data.
   RefPtr<MediaRawData> frame(GetNextFrame(FindNextFrame(true)));
 
   ADTSLOG("Init StreamLength()=%" PRId64 " first-frame-found=%d",
           StreamLength(), !!frame);
 
   if (!frame) {
@@ -415,17 +422,18 @@ ADTSTrackDemuxer::Init()
   // wAudioProfileLevelIndication, which is passed mInfo->mProfile, is
   // a value from Table 1.12 -- audioProfileLevelIndication values, ISO/IEC 14496-3.
   mInfo->mProfile = ProfileLevelIndication(mParser->FirstFrame());
   // For AAC, mExtendedProfile contains the audioObjectType from Table
   // 1.3 -- Audio Profile definition, ISO/IEC 14496-3. Eg. 2 == AAC LC
   mInfo->mExtendedProfile = mParser->FirstFrame().Header().mObjectType;
   InitAudioSpecificConfig(mParser->FirstFrame(), mInfo->mCodecSpecificConfig);
 
-  ADTSLOG("Init mInfo={mRate=%u mChannels=%u mBitDepth=%u mDuration=%" PRId64 "}",
+  ADTSLOG("Init mInfo={mRate=%u mChannels=%u mBitDepth=%u mDuration=%" PRId64
+          "}",
           mInfo->mRate, mInfo->mChannels, mInfo->mBitDepth, mInfo->mDuration);
 
   return mSamplesPerSecond && mChannels;
 }
 
 UniquePtr<TrackInfo>
 ADTSTrackDemuxer::GetInfo() const
 {
@@ -505,40 +513,42 @@ ADTSTrackDemuxer::ScanUntil(const media:
 
   return Duration(mFrameIndex);
 }
 
 RefPtr<ADTSTrackDemuxer::SamplesPromise>
 ADTSTrackDemuxer::GetSamples(int32_t aNumSamples)
 {
   ADTSLOGV("GetSamples(%d) Begin mOffset=%" PRIu64 " mNumParsedFrames=%" PRIu64
-          " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64 " mSamplesPerFrame=%d "
-          "mSamplesPerSecond=%d mChannels=%d",
-          aNumSamples, mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
-          mSamplesPerFrame, mSamplesPerSecond, mChannels);
+           " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64
+           " mSamplesPerFrame=%d "
+           "mSamplesPerSecond=%d mChannels=%d",
+           aNumSamples, mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
+           mSamplesPerFrame, mSamplesPerSecond, mChannels);
 
   MOZ_ASSERT(aNumSamples);
 
   RefPtr<SamplesHolder> frames = new SamplesHolder();
 
   while (aNumSamples--) {
     RefPtr<MediaRawData> frame(GetNextFrame(FindNextFrame()));
     if (!frame)
       break;
 
     frames->mSamples.AppendElement(frame);
   }
 
   ADTSLOGV("GetSamples() End mSamples.Size()=%d aNumSamples=%d mOffset=%" PRIu64
-          " mNumParsedFrames=%" PRIu64 " mFrameIndex=%" PRId64
-          " mTotalFrameLen=%" PRIu64 " mSamplesPerFrame=%d mSamplesPerSecond=%d "
-          "mChannels=%d",
-          frames->mSamples.Length(), aNumSamples, mOffset, mNumParsedFrames,
-          mFrameIndex, mTotalFrameLen, mSamplesPerFrame, mSamplesPerSecond,
-          mChannels);
+           " mNumParsedFrames=%" PRIu64 " mFrameIndex=%" PRId64
+           " mTotalFrameLen=%" PRIu64
+           " mSamplesPerFrame=%d mSamplesPerSecond=%d "
+           "mChannels=%d",
+           frames->mSamples.Length(), aNumSamples, mOffset, mNumParsedFrames,
+           mFrameIndex, mTotalFrameLen, mSamplesPerFrame, mSamplesPerSecond,
+           mChannels);
 
   if (frames->mSamples.IsEmpty()) {
     return SamplesPromise::CreateAndReject(
       NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
   }
 
   return SamplesPromise::CreateAndResolve(frames, __func__);
 }
@@ -550,17 +560,18 @@ ADTSTrackDemuxer::Reset()
   MOZ_ASSERT(mParser);
   if (mParser) {
     mParser->Reset();
   }
   FastSeek(media::TimeUnit());
 }
 
 RefPtr<ADTSTrackDemuxer::SkipAccessPointPromise>
-ADTSTrackDemuxer::SkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreshold)
+ADTSTrackDemuxer::SkipToNextRandomAccessPoint(
+  const media::TimeUnit& aTimeThreshold)
 {
   // Will not be called for audio-only resources.
   return SkipAccessPointPromise::CreateAndReject(
     SkipFailureHolder(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, 0), __func__);
 }
 
 int64_t
 ADTSTrackDemuxer::GetResourceOffset() const
@@ -649,17 +660,18 @@ ADTSTrackDemuxer::FindNextFrame(bool fin
 
     const adts::Frame& currentFrame = mParser->CurrentFrame();
     foundFrame = mParser->Parse(frameHeaderOffset, buffer, buffer + read);
     if (findFirstFrame && foundFrame) {
       // Check for sync marker after the found frame, since it's
       // possible to find sync marker in AAC data. If sync marker
       // exists after the current frame then we've found a frame
       // header.
-      int64_t nextFrameHeaderOffset = currentFrame.Offset() + currentFrame.Length();
+      int64_t nextFrameHeaderOffset =
+        currentFrame.Offset() + currentFrame.Length();
       int32_t read = Read(buffer, nextFrameHeaderOffset, 2);
       if (read != 2 || !adts::FrameHeader::MatchesSync(buffer)) {
         frameHeaderOffset = currentFrame.Offset() + 1;
         mParser->Reset();
         foundFrame = false;
         continue;
       }
     }
@@ -747,46 +759,48 @@ ADTSTrackDemuxer::GetNextFrame(const adt
   frame->mDuration = Duration(1).ToMicroseconds();
   frame->mTimecode = frame->mTime;
   frame->mKeyframe = true;
 
   MOZ_ASSERT(frame->mTime >= 0);
   MOZ_ASSERT(frame->mDuration > 0);
 
   ADTSLOGV("GetNext() End mOffset=%" PRIu64 " mNumParsedFrames=%" PRIu64
-          " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64
-          " mSamplesPerFrame=%d mSamplesPerSecond=%d mChannels=%d",
-          mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
-          mSamplesPerFrame, mSamplesPerSecond, mChannels);
+           " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64
+           " mSamplesPerFrame=%d mSamplesPerSecond=%d mChannels=%d",
+           mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
+           mSamplesPerFrame, mSamplesPerSecond, mChannels);
 
   return frame.forget();
 }
 
 int64_t
 ADTSTrackDemuxer::FrameIndexFromOffset(int64_t aOffset) const
 {
   int64_t frameIndex = 0;
 
   if (AverageFrameLength() > 0) {
-    frameIndex = (aOffset - mParser->FirstFrame().Offset()) / AverageFrameLength();
+    frameIndex =
+      (aOffset - mParser->FirstFrame().Offset()) / AverageFrameLength();
   }
 
   ADTSLOGV("FrameIndexFromOffset(%" PRId64 ") -> %" PRId64, aOffset, frameIndex);
   return std::max<int64_t>(0, frameIndex);
 }
 
 int64_t
 ADTSTrackDemuxer::FrameIndexFromTime(const media::TimeUnit& aTime) const
 {
   int64_t frameIndex = 0;
   if (mSamplesPerSecond > 0 && mSamplesPerFrame > 0) {
     frameIndex = aTime.ToSeconds() * mSamplesPerSecond / mSamplesPerFrame - 1;
   }
 
-  ADTSLOGV("FrameIndexFromOffset(%fs) -> %" PRId64, aTime.ToSeconds(), frameIndex);
+  ADTSLOGV("FrameIndexFromOffset(%fs) -> %" PRId64,
+           aTime.ToSeconds(), frameIndex);
   return std::max<int64_t>(0, frameIndex);
 }
 
 void
 ADTSTrackDemuxer::UpdateState(const adts::Frame& aFrame)
 {
   int32_t frameLength = aFrame.Length();
   // Prevent overflow.
@@ -811,17 +825,18 @@ ADTSTrackDemuxer::UpdateState(const adts
   ++mNumParsedFrames;
   ++mFrameIndex;
   MOZ_ASSERT(mFrameIndex > 0);
 }
 
 int32_t
 ADTSTrackDemuxer::Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize)
 {
-  ADTSLOGV("ADTSTrackDemuxer::Read(%p %" PRId64 " %d)", aBuffer, aOffset, aSize);
+  ADTSLOGV("ADTSTrackDemuxer::Read(%p %" PRId64 " %d)",
+           aBuffer, aOffset, aSize);
 
   const int64_t streamLen = StreamLength();
   if (mInfo && streamLen > 0) {
     // Prevent blocking reads after successful initialization.
     aSize = std::min<int64_t>(aSize, streamLen - aOffset);
   }
 
   uint32_t read = 0;
--- a/dom/media/ADTSDemuxer.h
+++ b/dom/media/ADTSDemuxer.h
@@ -17,35 +17,37 @@ namespace mozilla {
 
 namespace adts {
 class Frame;
 class FrameParser;
 }
 
 class ADTSTrackDemuxer;
 
-class ADTSDemuxer : public MediaDataDemuxer {
+class ADTSDemuxer : public MediaDataDemuxer
+{
 public:
   // MediaDataDemuxer interface.
   explicit ADTSDemuxer(MediaResource* aSource);
   RefPtr<InitPromise> Init() override;
   bool HasTrackType(TrackInfo::TrackType aType) const override;
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
-  already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
-    TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
+  already_AddRefed<MediaTrackDemuxer>
+  GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
   bool IsSeekable() const override;
 
 private:
   bool InitInternal();
 
   RefPtr<MediaResource> mSource;
   RefPtr<ADTSTrackDemuxer> mTrackDemuxer;
 };
 
-class ADTSTrackDemuxer : public MediaTrackDemuxer {
+class ADTSTrackDemuxer : public MediaTrackDemuxer
+{
 public:
   explicit ADTSTrackDemuxer(MediaResource* aSource);
 
   // Initializes the track demuxer by reading the first frame for meta data.
   // Returns initialization success state.
   bool Init();
 
   // Returns the total stream length if known, -1 otherwise.
--- a/dom/media/MP3Demuxer.cpp
+++ b/dom/media/MP3Demuxer.cpp
@@ -32,73 +32,79 @@ using mozilla::media::TimeInterval;
 using mozilla::media::TimeIntervals;
 using mp4_demuxer::ByteReader;
 
 namespace mozilla {
 namespace mp3 {
 
 // MP3Demuxer
 
-MP3Demuxer::MP3Demuxer(MediaResource* aSource)
-  : mSource(aSource)
-{}
+MP3Demuxer::MP3Demuxer(MediaResource* aSource) : mSource(aSource) { }
 
 bool
-MP3Demuxer::InitInternal() {
+MP3Demuxer::InitInternal()
+{
   if (!mTrackDemuxer) {
     mTrackDemuxer = new MP3TrackDemuxer(mSource);
   }
   return mTrackDemuxer->Init();
 }
 
 RefPtr<MP3Demuxer::InitPromise>
-MP3Demuxer::Init() {
+MP3Demuxer::Init()
+{
   if (!InitInternal()) {
     MP3LOG("MP3Demuxer::Init() failure: waiting for data");
 
     return InitPromise::CreateAndReject(
       NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
   }
 
   MP3LOG("MP3Demuxer::Init() successful");
   return InitPromise::CreateAndResolve(NS_OK, __func__);
 }
 
 bool
-MP3Demuxer::HasTrackType(TrackInfo::TrackType aType) const {
+MP3Demuxer::HasTrackType(TrackInfo::TrackType aType) const
+{
   return aType == TrackInfo::kAudioTrack;
 }
 
 uint32_t
-MP3Demuxer::GetNumberTracks(TrackInfo::TrackType aType) const {
+MP3Demuxer::GetNumberTracks(TrackInfo::TrackType aType) const
+{
   return aType == TrackInfo::kAudioTrack ? 1u : 0u;
 }
 
 already_AddRefed<MediaTrackDemuxer>
-MP3Demuxer::GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber) {
+MP3Demuxer::GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber)
+{
   if (!mTrackDemuxer) {
     return nullptr;
   }
   return RefPtr<MP3TrackDemuxer>(mTrackDemuxer).forget();
 }
 
 bool
-MP3Demuxer::IsSeekable() const {
+MP3Demuxer::IsSeekable() const
+{
   return true;
 }
 
 void
-MP3Demuxer::NotifyDataArrived() {
+MP3Demuxer::NotifyDataArrived()
+{
   // TODO: bug 1169485.
   NS_WARNING("Unimplemented function NotifyDataArrived");
   MP3LOGV("NotifyDataArrived()");
 }
 
 void
-MP3Demuxer::NotifyDataRemoved() {
+MP3Demuxer::NotifyDataRemoved()
+{
   // TODO: bug 1169485.
   NS_WARNING("Unimplemented function NotifyDataRemoved");
   MP3LOGV("NotifyDataRemoved()");
 }
 
 
 // MP3TrackDemuxer
 
@@ -112,17 +118,18 @@ MP3TrackDemuxer::MP3TrackDemuxer(MediaRe
   , mSamplesPerFrame(0)
   , mSamplesPerSecond(0)
   , mChannels(0)
 {
   Reset();
 }
 
 bool
-MP3TrackDemuxer::Init() {
+MP3TrackDemuxer::Init()
+{
   Reset();
   FastSeek(TimeUnit());
   // Read the first frame to fetch sample rate and other meta data.
   RefPtr<MediaRawData> frame(GetNextFrame(FindFirstFrame()));
 
   MP3LOG("Init StreamLength()=%" PRId64 " first-frame-found=%d",
          StreamLength(), !!frame);
 
@@ -146,61 +153,69 @@ MP3TrackDemuxer::Init() {
   MP3LOG("Init mInfo={mRate=%d mChannels=%d mBitDepth=%d mDuration=%" PRId64 "}",
          mInfo->mRate, mInfo->mChannels, mInfo->mBitDepth,
          mInfo->mDuration);
 
   return mSamplesPerSecond && mChannels;
 }
 
 media::TimeUnit
-MP3TrackDemuxer::SeekPosition() const {
+MP3TrackDemuxer::SeekPosition() const
+{
   TimeUnit pos = Duration(mFrameIndex);
   if (Duration() > TimeUnit()) {
     pos = std::min(Duration(), pos);
   }
   return pos;
 }
 
 const FrameParser::Frame&
-MP3TrackDemuxer::LastFrame() const {
+MP3TrackDemuxer::LastFrame() const
+{
   return mParser.PrevFrame();
 }
 
 RefPtr<MediaRawData>
-MP3TrackDemuxer::DemuxSample() {
+MP3TrackDemuxer::DemuxSample()
+{
   return GetNextFrame(FindNextFrame());
 }
 
 const ID3Parser::ID3Header&
-MP3TrackDemuxer::ID3Header() const {
+MP3TrackDemuxer::ID3Header() const
+{
   return mParser.ID3Header();
 }
 
 const FrameParser::VBRHeader&
-MP3TrackDemuxer::VBRInfo() const {
+MP3TrackDemuxer::VBRInfo() const
+{
   return mParser.VBRInfo();
 }
 
 UniquePtr<TrackInfo>
-MP3TrackDemuxer::GetInfo() const {
+MP3TrackDemuxer::GetInfo() const
+{
   return mInfo->Clone();
 }
 
 RefPtr<MP3TrackDemuxer::SeekPromise>
-MP3TrackDemuxer::Seek(const TimeUnit& aTime) {
+MP3TrackDemuxer::Seek(const TimeUnit& aTime)
+{
   // Efficiently seek to the position.
   FastSeek(aTime);
   // Correct seek position by scanning the next frames.
   const TimeUnit seekTime = ScanUntil(aTime);
 
   return SeekPromise::CreateAndResolve(seekTime, __func__);
 }
 
 TimeUnit
-MP3TrackDemuxer::FastSeek(const TimeUnit& aTime) {
+MP3TrackDemuxer::FastSeek(const TimeUnit& aTime)
+{
   MP3LOG("FastSeek(%" PRId64 ") avgFrameLen=%f mNumParsedFrames=%" PRIu64
          " mFrameIndex=%" PRId64 " mOffset=%" PRIu64,
          aTime.ToMicroseconds(), AverageFrameLength(), mNumParsedFrames,
          mFrameIndex, mOffset);
 
   const auto& vbr = mParser.VBRInfo();
   if (!aTime.ToMicroseconds()) {
     // Quick seek to the beginning of the stream.
@@ -227,17 +242,18 @@ MP3TrackDemuxer::FastSeek(const TimeUnit
          " SL=%llu NumBytes=%u",
          vbr.IsTOCPresent(), AverageFrameLength(), mNumParsedFrames, mFrameIndex,
          mFirstFrameOffset, mOffset, StreamLength(), vbr.NumBytes().valueOr(0));
 
   return Duration(mFrameIndex);
 }
 
 TimeUnit
-MP3TrackDemuxer::ScanUntil(const TimeUnit& aTime) {
+MP3TrackDemuxer::ScanUntil(const TimeUnit& aTime)
+{
   MP3LOG("ScanUntil(%" PRId64 ") avgFrameLen=%f mNumParsedFrames=%" PRIu64
          " mFrameIndex=%" PRId64 " mOffset=%" PRIu64,
          aTime.ToMicroseconds(), AverageFrameLength(), mNumParsedFrames,
          mFrameIndex, mOffset);
 
   if (!aTime.ToMicroseconds()) {
     return FastSeek(aTime);
   }
@@ -262,20 +278,21 @@ MP3TrackDemuxer::ScanUntil(const TimeUni
   MP3LOG("ScanUntil End avgFrameLen=%f mNumParsedFrames=%" PRIu64
          " mFrameIndex=%" PRId64 " mOffset=%" PRIu64,
          AverageFrameLength(), mNumParsedFrames, mFrameIndex, mOffset);
 
   return SeekPosition();
 }
 
 RefPtr<MP3TrackDemuxer::SamplesPromise>
-MP3TrackDemuxer::GetSamples(int32_t aNumSamples) {
+MP3TrackDemuxer::GetSamples(int32_t aNumSamples)
+{
   MP3LOGV("GetSamples(%d) Begin mOffset=%" PRIu64 " mNumParsedFrames=%" PRIu64
-          " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64 " mSamplesPerFrame=%d "
-          "mSamplesPerSecond=%d mChannels=%d",
+          " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64
+          " mSamplesPerFrame=%d mSamplesPerSecond=%d mChannels=%d",
           aNumSamples, mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
           mSamplesPerFrame, mSamplesPerSecond, mChannels);
 
   if (!aNumSamples) {
     return SamplesPromise::CreateAndReject(
         NS_ERROR_DOM_MEDIA_DEMUXER_ERR, __func__);
   }
 
@@ -301,37 +318,41 @@ MP3TrackDemuxer::GetSamples(int32_t aNum
   if (frames->mSamples.IsEmpty()) {
     return SamplesPromise::CreateAndReject(
         NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
   }
   return SamplesPromise::CreateAndResolve(frames, __func__);
 }
 
 void
-MP3TrackDemuxer::Reset() {
+MP3TrackDemuxer::Reset()
+{
   MP3LOG("Reset()");
 
   FastSeek(TimeUnit());
   mParser.Reset();
 }
 
 RefPtr<MP3TrackDemuxer::SkipAccessPointPromise>
-MP3TrackDemuxer::SkipToNextRandomAccessPoint(const TimeUnit& aTimeThreshold) {
+MP3TrackDemuxer::SkipToNextRandomAccessPoint(const TimeUnit& aTimeThreshold)
+{
   // Will not be called for audio-only resources.
   return SkipAccessPointPromise::CreateAndReject(
     SkipFailureHolder(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, 0), __func__);
 }
 
 int64_t
-MP3TrackDemuxer::GetResourceOffset() const {
+MP3TrackDemuxer::GetResourceOffset() const
+{
   return mOffset;
 }
 
 TimeIntervals
-MP3TrackDemuxer::GetBuffered() {
+MP3TrackDemuxer::GetBuffered()
+{
   AutoPinned<MediaResource> stream(mSource.GetResource());
   TimeIntervals buffered;
 
   if (Duration() > TimeUnit() && stream->IsDataCachedToEndOfResource(0)) {
     // Special case completely cached files. This also handles local files.
     buffered += TimeInterval(TimeUnit(), Duration());
     MP3LOGV("buffered = [[%" PRId64 ", %" PRId64 "]]",
             TimeUnit().ToMicroseconds(), Duration().ToMicroseconds());
@@ -352,22 +373,24 @@ MP3TrackDemuxer::GetBuffered() {
             start.ToMicroseconds(), end.ToMicroseconds());
     buffered += TimeInterval(start, end);
   }
 
   return buffered;
 }
 
 int64_t
-MP3TrackDemuxer::StreamLength() const {
+MP3TrackDemuxer::StreamLength() const
+{
   return mSource.GetLength();
 }
 
 TimeUnit
-MP3TrackDemuxer::Duration() const {
+MP3TrackDemuxer::Duration() const
+{
   if (!mNumParsedFrames) {
     return TimeUnit::FromMicroseconds(-1);
   }
 
   int64_t numFrames = 0;
   const auto numAudioFrames = mParser.VBRInfo().NumAudioFrames();
   if (mParser.VBRInfo().IsValid() && numAudioFrames.valueOr(0) + 1 > 1) {
     // VBR headers don't include the VBR header frame.
@@ -381,90 +404,97 @@ MP3TrackDemuxer::Duration() const {
     if (AverageFrameLength() > 0) {
       numFrames = (streamLen - mFirstFrameOffset) / AverageFrameLength();
     }
   }
   return Duration(numFrames);
 }
 
 TimeUnit
-MP3TrackDemuxer::Duration(int64_t aNumFrames) const {
+MP3TrackDemuxer::Duration(int64_t aNumFrames) const
+{
   if (!mSamplesPerSecond) {
     return TimeUnit::FromMicroseconds(-1);
   }
 
   const double usPerFrame = USECS_PER_S * mSamplesPerFrame / mSamplesPerSecond;
   return TimeUnit::FromMicroseconds(aNumFrames * usPerFrame);
 }
 
 MediaByteRange
-MP3TrackDemuxer::FindFirstFrame() {
+MP3TrackDemuxer::FindFirstFrame()
+{
   static const int MIN_SUCCESSIVE_FRAMES = 4;
 
   MediaByteRange candidateFrame = FindNextFrame();
   int numSuccFrames = candidateFrame.Length() > 0;
   MediaByteRange currentFrame = candidateFrame;
-  MP3LOGV("FindFirst() first candidate frame: mOffset=%" PRIu64 " Length()=%" PRIu64,
+  MP3LOGV("FindFirst() first candidate frame: mOffset=%" PRIu64
+          " Length()=%" PRIu64,
           candidateFrame.mStart, candidateFrame.Length());
 
   while (candidateFrame.Length() && numSuccFrames < MIN_SUCCESSIVE_FRAMES) {
     mParser.EndFrameSession();
     mOffset = currentFrame.mEnd;
     const MediaByteRange prevFrame = currentFrame;
 
     // FindNextFrame() here will only return frames consistent with our candidate frame.
     currentFrame = FindNextFrame();
     numSuccFrames += currentFrame.Length() > 0;
     // Multiple successive false positives, which wouldn't be caught by the consistency
     // checks alone, can be detected by wrong alignment (non-zero gap between frames).
     const int64_t frameSeparation = currentFrame.mStart - prevFrame.mEnd;
 
     if (!currentFrame.Length() || frameSeparation != 0) {
       MP3LOGV("FindFirst() not enough successive frames detected, "
-              "rejecting candidate frame: successiveFrames=%d, last Length()=%" PRIu64
-              ", last frameSeparation=%" PRId64, numSuccFrames, currentFrame.Length(),
-              frameSeparation);
+              "rejecting candidate frame: successiveFrames=%d, last "
+              "Length()=%" PRIu64 ", last frameSeparation=%" PRId64,
+              numSuccFrames, currentFrame.Length(), frameSeparation);
 
       mParser.ResetFrameData();
       mOffset = candidateFrame.mStart + 1;
       candidateFrame = FindNextFrame();
       numSuccFrames = candidateFrame.Length() > 0;
       currentFrame = candidateFrame;
-      MP3LOGV("FindFirst() new candidate frame: mOffset=%" PRIu64 " Length()=%" PRIu64,
+      MP3LOGV("FindFirst() new candidate frame: mOffset=%" PRIu64
+              " Length()=%" PRIu64,
               candidateFrame.mStart, candidateFrame.Length());
     }
   }
 
   if (numSuccFrames >= MIN_SUCCESSIVE_FRAMES) {
     MP3LOG("FindFirst() accepting candidate frame: "
             "successiveFrames=%d", numSuccFrames);
   } else {
     MP3LOG("FindFirst() no suitable first frame found");
   }
   return candidateFrame;
 }
 
 static bool
-VerifyFrameConsistency(
-    const FrameParser::Frame& aFrame1, const FrameParser::Frame& aFrame2) {
+VerifyFrameConsistency(const FrameParser::Frame& aFrame1,
+                       const FrameParser::Frame& aFrame2)
+{
   const auto& h1 = aFrame1.Header();
   const auto& h2 = aFrame2.Header();
 
-  return h1.IsValid() && h2.IsValid() &&
-         h1.Layer() == h2.Layer() &&
-         h1.SlotSize() == h2.SlotSize() &&
-         h1.SamplesPerFrame() == h2.SamplesPerFrame() &&
-         h1.Channels() == h2.Channels() &&
-         h1.SampleRate() == h2.SampleRate() &&
-         h1.RawVersion() == h2.RawVersion() &&
-         h1.RawProtection() == h2.RawProtection();
+  return h1.IsValid()
+         && h2.IsValid()
+         && h1.Layer() == h2.Layer()
+         && h1.SlotSize() == h2.SlotSize()
+         && h1.SamplesPerFrame() == h2.SamplesPerFrame()
+         && h1.Channels() == h2.Channels()
+         && h1.SampleRate() == h2.SampleRate()
+         && h1.RawVersion() == h2.RawVersion()
+         && h1.RawProtection() == h2.RawProtection();
 }
 
 MediaByteRange
-MP3TrackDemuxer::FindNextFrame() {
+MP3TrackDemuxer::FindNextFrame()
+{
   static const int BUFFER_SIZE = 64;
   static const int MAX_SKIPPED_BYTES = 1024 * BUFFER_SIZE;
 
   MP3LOGV("FindNext() Begin mOffset=%" PRIu64 " mNumParsedFrames=%" PRIu64
           " mFrameIndex=%" PRId64 " mTotalFrameLen=%" PRIu64
           " mSamplesPerFrame=%d mSamplesPerSecond=%d mChannels=%d",
           mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
           mSamplesPerFrame, mSamplesPerSecond, mChannels);
@@ -472,35 +502,37 @@ MP3TrackDemuxer::FindNextFrame() {
   uint8_t buffer[BUFFER_SIZE];
   int32_t read = 0;
 
   bool foundFrame = false;
   int64_t frameHeaderOffset = 0;
 
   // Check whether we've found a valid MPEG frame.
   while (!foundFrame) {
-    if ((!mParser.FirstFrame().Length() &&
-         mOffset - mParser.ID3Header().Size() > MAX_SKIPPED_BYTES) ||
-        (read = Read(buffer, mOffset, BUFFER_SIZE)) == 0) {
+    if ((!mParser.FirstFrame().Length()
+         && mOffset - mParser.ID3Header().Size() > MAX_SKIPPED_BYTES)
+        || (read = Read(buffer, mOffset, BUFFER_SIZE)) == 0) {
       MP3LOG("FindNext() EOS or exceeded MAX_SKIPPED_BYTES without a frame");
       // This is not a valid MPEG audio stream or we've reached EOS, give up.
       break;
     }
 
     ByteReader reader(buffer, read);
     uint32_t bytesToSkip = 0;
     foundFrame = mParser.Parse(&reader, &bytesToSkip);
-    frameHeaderOffset = mOffset + reader.Offset() - FrameParser::FrameHeader::SIZE;
+    frameHeaderOffset =
+      mOffset + reader.Offset() - FrameParser::FrameHeader::SIZE;
 
     // If we've found neither an MPEG frame header nor an ID3v2 tag,
     // the reader shouldn't have any bytes remaining.
     MOZ_ASSERT(foundFrame || bytesToSkip || !reader.Remaining());
 
-    if (foundFrame && mParser.FirstFrame().Length() &&
-        !VerifyFrameConsistency(mParser.FirstFrame(), mParser.CurrentFrame())) {
+    if (foundFrame && mParser.FirstFrame().Length()
+        && !VerifyFrameConsistency(mParser.FirstFrame(),
+                                   mParser.CurrentFrame())) {
       // We've likely hit a false-positive, ignore it and proceed with the
       // search for the next valid frame.
       foundFrame = false;
       mOffset = frameHeaderOffset + 1;
       mParser.EndFrameSession();
     } else {
       // Advance mOffset by the amount of bytes read and if necessary,
       // skip an ID3v2 tag which stretches beyond the current buffer.
@@ -522,17 +554,18 @@ MP3TrackDemuxer::FindNextFrame() {
           " mChannels=%d",
           mOffset, mNumParsedFrames, mFrameIndex, frameHeaderOffset,
           mTotalFrameLen, mSamplesPerFrame, mSamplesPerSecond, mChannels);
 
   return { frameHeaderOffset, frameHeaderOffset + mParser.CurrentFrame().Length() };
 }
 
 bool
-MP3TrackDemuxer::SkipNextFrame(const MediaByteRange& aRange) {
+MP3TrackDemuxer::SkipNextFrame(const MediaByteRange& aRange)
+{
   if (!mNumParsedFrames || !aRange.Length()) {
     // We can't skip the first frame, since it could contain VBR headers.
     RefPtr<MediaRawData> frame(GetNextFrame(aRange));
     return frame;
   }
 
   UpdateState(aRange);
 
@@ -541,33 +574,35 @@ MP3TrackDemuxer::SkipNextFrame(const Med
           " mSamplesPerFrame=%d mSamplesPerSecond=%d mChannels=%d",
           mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
           mSamplesPerFrame, mSamplesPerSecond, mChannels);
 
   return true;
 }
 
 already_AddRefed<MediaRawData>
-MP3TrackDemuxer::GetNextFrame(const MediaByteRange& aRange) {
+MP3TrackDemuxer::GetNextFrame(const MediaByteRange& aRange)
+{
   MP3LOG("GetNext() Begin({mStart=%" PRId64 " Length()=%" PRId64 "})",
          aRange.mStart, aRange.Length());
   if (!aRange.Length()) {
     return nullptr;
   }
 
   RefPtr<MediaRawData> frame = new MediaRawData();
   frame->mOffset = aRange.mStart;
 
   nsAutoPtr<MediaRawDataWriter> frameWriter(frame->CreateWriter());
   if (!frameWriter->SetSize(aRange.Length())) {
     MP3LOG("GetNext() Exit failed to allocated media buffer");
     return nullptr;
   }
 
-  const uint32_t read = Read(frameWriter->Data(), frame->mOffset, frame->Size());
+  const uint32_t read =
+    Read(frameWriter->Data(), frame->mOffset, frame->Size());
 
   if (read != aRange.Length()) {
     MP3LOG("GetNext() Exit read=%u frame->Size()=%u", read, frame->Size());
     return nullptr;
   }
 
   UpdateState(aRange);
 
@@ -591,61 +626,68 @@ MP3TrackDemuxer::GetNextFrame(const Medi
           " mSamplesPerFrame=%d mSamplesPerSecond=%d mChannels=%d",
           mOffset, mNumParsedFrames, mFrameIndex, mTotalFrameLen,
           mSamplesPerFrame, mSamplesPerSecond, mChannels);
 
   return frame.forget();
 }
 
 int64_t
-MP3TrackDemuxer::OffsetFromFrameIndex(int64_t aFrameIndex) const {
+MP3TrackDemuxer::OffsetFromFrameIndex(int64_t aFrameIndex) const
+{
   int64_t offset = 0;
   const auto& vbr = mParser.VBRInfo();
 
   if (vbr.IsComplete()) {
-    offset = mFirstFrameOffset + aFrameIndex * vbr.NumBytes().value() /
-             vbr.NumAudioFrames().value();
+    offset = mFirstFrameOffset
+             + aFrameIndex * vbr.NumBytes().value()
+               / vbr.NumAudioFrames().value();
   } else if (AverageFrameLength() > 0) {
     offset = mFirstFrameOffset + aFrameIndex * AverageFrameLength();
   }
 
   MP3LOGV("OffsetFromFrameIndex(%" PRId64 ") -> %" PRId64, aFrameIndex, offset);
   return std::max<int64_t>(mFirstFrameOffset, offset);
 }
 
 int64_t
-MP3TrackDemuxer::FrameIndexFromOffset(int64_t aOffset) const {
+MP3TrackDemuxer::FrameIndexFromOffset(int64_t aOffset) const
+{
   int64_t frameIndex = 0;
   const auto& vbr = mParser.VBRInfo();
 
   if (vbr.IsComplete()) {
-    frameIndex = static_cast<float>(aOffset - mFirstFrameOffset) /
-                 vbr.NumBytes().value() * vbr.NumAudioFrames().value();
+    frameIndex = static_cast<float>(aOffset - mFirstFrameOffset)
+                 / vbr.NumBytes().value()
+                 * vbr.NumAudioFrames().value();
     frameIndex = std::min<int64_t>(vbr.NumAudioFrames().value(), frameIndex);
   } else if (AverageFrameLength() > 0) {
     frameIndex = (aOffset - mFirstFrameOffset) / AverageFrameLength();
   }
 
   MP3LOGV("FrameIndexFromOffset(%" PRId64 ") -> %" PRId64, aOffset, frameIndex);
   return std::max<int64_t>(0, frameIndex);
 }
 
 int64_t
-MP3TrackDemuxer::FrameIndexFromTime(const media::TimeUnit& aTime) const {
+MP3TrackDemuxer::FrameIndexFromTime(const media::TimeUnit& aTime) const
+{
   int64_t frameIndex = 0;
   if (mSamplesPerSecond > 0 && mSamplesPerFrame > 0) {
     frameIndex = aTime.ToSeconds() * mSamplesPerSecond / mSamplesPerFrame - 1;
   }
 
-  MP3LOGV("FrameIndexFromOffset(%fs) -> %" PRId64, aTime.ToSeconds(), frameIndex);
+  MP3LOGV("FrameIndexFromOffset(%fs) -> %" PRId64, aTime.ToSeconds(),
+          frameIndex);
   return std::max<int64_t>(0, frameIndex);
 }
 
 void
-MP3TrackDemuxer::UpdateState(const MediaByteRange& aRange) {
+MP3TrackDemuxer::UpdateState(const MediaByteRange& aRange)
+{
   // Prevent overflow.
   if (mTotalFrameLen + aRange.Length() < mTotalFrameLen) {
     // These variables have a linear dependency and are only used to derive the
     // average frame length.
     mTotalFrameLen /= 2;
     mNumParsedFrames /= 2;
   }
 
@@ -664,17 +706,18 @@ MP3TrackDemuxer::UpdateState(const Media
   ++mFrameIndex;
   MOZ_ASSERT(mFrameIndex > 0);
 
   // Prepare the parser for the next frame parsing session.
   mParser.EndFrameSession();
 }
 
 int32_t
-MP3TrackDemuxer::Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize) {
+MP3TrackDemuxer::Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize)
+{
   MP3LOGV("MP3TrackDemuxer::Read(%p %" PRId64 " %d)", aBuffer, aOffset, aSize);
 
   const int64_t streamLen = StreamLength();
   if (mInfo && streamLen > 0) {
     // Prevent blocking reads after successful initialization.
     aSize = std::min<int64_t>(aSize, streamLen - aOffset);
   }
 
@@ -682,24 +725,25 @@ MP3TrackDemuxer::Read(uint8_t* aBuffer, 
   MP3LOGV("MP3TrackDemuxer::Read        -> ReadAt(%d)", aSize);
   const nsresult rv = mSource.ReadAt(aOffset, reinterpret_cast<char*>(aBuffer),
                                      static_cast<uint32_t>(aSize), &read);
   NS_ENSURE_SUCCESS(rv, 0);
   return static_cast<int32_t>(read);
 }
 
 double
-MP3TrackDemuxer::AverageFrameLength() const {
+MP3TrackDemuxer::AverageFrameLength() const
+{
   if (mNumParsedFrames) {
     return static_cast<double>(mTotalFrameLen) / mNumParsedFrames;
   }
   const auto& vbr = mParser.VBRInfo();
   if (vbr.IsComplete() && vbr.NumAudioFrames().value() + 1) {
-    return static_cast<double>(vbr.NumBytes().value()) /
-           (vbr.NumAudioFrames().value() + 1);
+    return static_cast<double>(vbr.NumBytes().value())
+           / (vbr.NumAudioFrames().value() + 1);
   }
   return 0.0;
 }
 
 // FrameParser
 
 namespace frame_header {
 // FrameHeader mRaw byte offsets.
@@ -709,91 +753,102 @@ static const int BITRATE_SAMPLERATE_PADD
 static const int CHANNELMODE_MODEEXT_COPY_ORIG_EMPH = 3;
 } // namespace frame_header
 
 FrameParser::FrameParser()
 {
 }
 
 void
-FrameParser::Reset() {
+FrameParser::Reset()
+{
   mID3Parser.Reset();
   mFrame.Reset();
 }
 
 void
-FrameParser::ResetFrameData() {
+FrameParser::ResetFrameData()
+{
   mFrame.Reset();
   mFirstFrame.Reset();
   mPrevFrame.Reset();
 }
 
 void
-FrameParser::EndFrameSession() {
+FrameParser::EndFrameSession()
+{
   if (!mID3Parser.Header().IsValid()) {
     // Reset ID3 tags only if we have not parsed a valid ID3 header yet.
     mID3Parser.Reset();
   }
   mPrevFrame = mFrame;
   mFrame.Reset();
 }
 
 const FrameParser::Frame&
-FrameParser::CurrentFrame() const {
+FrameParser::CurrentFrame() const
+{
   return mFrame;
 }
 
 const FrameParser::Frame&
-FrameParser::PrevFrame() const {
+FrameParser::PrevFrame() const
+{
   return mPrevFrame;
 }
 
 const FrameParser::Frame&
-FrameParser::FirstFrame() const {
+FrameParser::FirstFrame() const
+{
   return mFirstFrame;
 }
 
 const ID3Parser::ID3Header&
-FrameParser::ID3Header() const {
+FrameParser::ID3Header() const
+{
   return mID3Parser.Header();
 }
 
 const FrameParser::VBRHeader&
-FrameParser::VBRInfo() const {
+FrameParser::VBRInfo() const
+{
   return mVBRHeader;
 }
 
 bool
-FrameParser::Parse(ByteReader* aReader, uint32_t* aBytesToSkip) {
+FrameParser::Parse(ByteReader* aReader, uint32_t* aBytesToSkip)
+{
   MOZ_ASSERT(aReader && aBytesToSkip);
   *aBytesToSkip = 0;
 
   if (!mID3Parser.Header().Size() && !mFirstFrame.Length()) {
     // No MP3 frames have been parsed yet, look for ID3v2 headers at file begin.
     // ID3v1 tags may only be at file end.
     // TODO: should we try to read ID3 tags at end of file/mid-stream, too?
     const size_t prevReaderOffset = aReader->Offset();
     const uint32_t tagSize = mID3Parser.Parse(aReader);
     if (tagSize) {
       // ID3 tag found, skip past it.
       const uint32_t skipSize = tagSize - ID3Parser::ID3Header::SIZE;
 
       if (skipSize > aReader->Remaining()) {
-        // Skipping across the ID3v2 tag would take us past the end of the buffer, therefore we
-        // return immediately and let the calling function handle skipping the rest of the tag.
+        // Skipping across the ID3v2 tag would take us past the end of the
+        // buffer, therefore we return immediately and let the calling function
+        // handle skipping the rest of the tag.
         MP3LOGV("ID3v2 tag detected, size=%d,"
                 " needing to skip %d bytes past the current buffer",
                 tagSize, skipSize - aReader->Remaining());
         *aBytesToSkip = skipSize - aReader->Remaining();
         return false;
       }
       MP3LOGV("ID3v2 tag detected, size=%d", tagSize);
       aReader->Read(skipSize);
     } else {
-      // No ID3v2 tag found, rewinding reader in order to search for a MPEG frame header.
+      // No ID3v2 tag found, rewinding reader in order to search for a MPEG
+      // frame header.
       aReader->Seek(prevReaderOffset);
     }
   }
 
   while (aReader->CanRead8() && !mFrame.ParseNext(aReader->ReadU8())) { }
 
   if (mFrame.Length()) {
     // MP3 frame found.
@@ -809,108 +864,123 @@ FrameParser::Parse(ByteReader* aReader, 
 // FrameParser::Header
 
 FrameParser::FrameHeader::FrameHeader()
 {
   Reset();
 }
 
 uint8_t
-FrameParser::FrameHeader::Sync1() const {
+FrameParser::FrameHeader::Sync1() const
+{
   return mRaw[frame_header::SYNC1];
 }
 
 uint8_t
-FrameParser::FrameHeader::Sync2() const {
+FrameParser::FrameHeader::Sync2() const
+{
   return 0x7 & mRaw[frame_header::SYNC2_VERSION_LAYER_PROTECTION] >> 5;
 }
 
 uint8_t
-FrameParser::FrameHeader::RawVersion() const {
+FrameParser::FrameHeader::RawVersion() const
+{
   return 0x3 & mRaw[frame_header::SYNC2_VERSION_LAYER_PROTECTION] >> 3;
 }
 
 uint8_t
-FrameParser::FrameHeader::RawLayer() const {
+FrameParser::FrameHeader::RawLayer() const
+{
   return 0x3 & mRaw[frame_header::SYNC2_VERSION_LAYER_PROTECTION] >> 1;
 }
 
 uint8_t
-FrameParser::FrameHeader::RawProtection() const {
+FrameParser::FrameHeader::RawProtection() const
+{
   return 0x1 & mRaw[frame_header::SYNC2_VERSION_LAYER_PROTECTION] >> 6;
 }
 
 uint8_t
-FrameParser::FrameHeader::RawBitrate() const {
+FrameParser::FrameHeader::RawBitrate() const
+{
   return 0xF & mRaw[frame_header::BITRATE_SAMPLERATE_PADDING_PRIVATE] >> 4;
 }
 
 uint8_t
-FrameParser::FrameHeader::RawSampleRate() const {
+FrameParser::FrameHeader::RawSampleRate() const
+{
   return 0x3 & mRaw[frame_header::BITRATE_SAMPLERATE_PADDING_PRIVATE] >> 2;
 }
 
 uint8_t
-FrameParser::FrameHeader::Padding() const {
+FrameParser::FrameHeader::Padding() const
+{
   return 0x1 & mRaw[frame_header::BITRATE_SAMPLERATE_PADDING_PRIVATE] >> 1;
 }
 
 uint8_t
-FrameParser::FrameHeader::Private() const {
+FrameParser::FrameHeader::Private() const
+{
   return 0x1 & mRaw[frame_header::BITRATE_SAMPLERATE_PADDING_PRIVATE];
 }
 
 uint8_t
-FrameParser::FrameHeader::RawChannelMode() const {
+FrameParser::FrameHeader::RawChannelMode() const
+{
   return 0x3 & mRaw[frame_header::CHANNELMODE_MODEEXT_COPY_ORIG_EMPH] >> 6;
 }
 
 int32_t
-FrameParser::FrameHeader::Layer() const {
+FrameParser::FrameHeader::Layer() const
+{
   static const uint8_t LAYERS[4] = { 0, 3, 2, 1 };
 
   return LAYERS[RawLayer()];
 }
 
 int32_t
-FrameParser::FrameHeader::SampleRate() const {
+FrameParser::FrameHeader::SampleRate() const
+{
   // Sample rates - use [version][srate]
   static const uint16_t SAMPLE_RATE[4][4] = {
     { 11025, 12000,  8000, 0 }, // MPEG 2.5
     {     0,     0,     0, 0 }, // Reserved
     { 22050, 24000, 16000, 0 }, // MPEG 2
     { 44100, 48000, 32000, 0 }  // MPEG 1
   };
 
   return SAMPLE_RATE[RawVersion()][RawSampleRate()];
 }
 
 int32_t
-FrameParser::FrameHeader::Channels() const {
+FrameParser::FrameHeader::Channels() const
+{
   // 3 is single channel (mono), any other value is some variant of dual
   // channel.
   return RawChannelMode() == 3 ? 1 : 2;
 }
 
 int32_t
-FrameParser::FrameHeader::SamplesPerFrame() const {
+FrameParser::FrameHeader::SamplesPerFrame() const
+{
   // Samples per frame - use [version][layer]
   static const uint16_t FRAME_SAMPLE[4][4] = {
     // Layer     3     2     1       Version
     {      0,  576, 1152,  384 }, // 2.5
     {      0,    0,    0,    0 }, // Reserved
     {      0,  576, 1152,  384 }, // 2
     {      0, 1152, 1152,  384 }  // 1
   };
 
   return FRAME_SAMPLE[RawVersion()][RawLayer()];
 }
 
 int32_t
-FrameParser::FrameHeader::Bitrate() const {
+FrameParser::FrameHeader::Bitrate() const
+{
   // Bitrates - use [version][layer][bitrate]
   static const uint16_t BITRATE[4][4][16] = {
     { // Version 2.5
       { 0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 0 }, // Reserved
       { 0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0 }, // Layer 3
       { 0,   8,  16,  24,  32,  40,  48,  56,  64,  80,  96, 112, 128, 144, 160, 0 }, // Layer 2
       { 0,  32,  48,  56,  64,  80,  96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }  // Layer 1
     },
@@ -933,36 +1003,39 @@ FrameParser::FrameHeader::Bitrate() cons
       { 0,  32,  64,  96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, // Layer 1
     }
   };
 
   return 1000 * BITRATE[RawVersion()][RawLayer()][RawBitrate()];
 }
 
 int32_t
-FrameParser::FrameHeader::SlotSize() const {
+FrameParser::FrameHeader::SlotSize() const
+{
   // Slot size (MPEG unit of measurement) - use [layer]
   static const uint8_t SLOT_SIZE[4] = { 0, 1, 1, 4 }; // Rsvd, 3, 2, 1
 
   return SLOT_SIZE[RawLayer()];
 }
 
 bool
-FrameParser::FrameHeader::ParseNext(uint8_t c) {
+FrameParser::FrameHeader::ParseNext(uint8_t c)
+{
   if (!Update(c)) {
     Reset();
     if (!Update(c)) {
       Reset();
     }
   }
   return IsValid();
 }
 
 bool
-FrameParser::FrameHeader::IsValid(int aPos) const {
+FrameParser::FrameHeader::IsValid(int aPos) const
+{
   if (aPos >= SIZE) {
     return true;
   }
   if (aPos == frame_header::SYNC1) {
     return Sync1() == 0xFF;
   }
   if (aPos == frame_header::SYNC2_VERSION_LAYER_PROTECTION) {
     return Sync2() == 7 &&
@@ -972,27 +1045,30 @@ FrameParser::FrameHeader::IsValid(int aP
   if (aPos == frame_header::BITRATE_SAMPLERATE_PADDING_PRIVATE) {
     return RawBitrate() != 0xF && RawBitrate() != 0 &&
            RawSampleRate() != 3;
   }
   return true;
 }
 
 bool
-FrameParser::FrameHeader::IsValid() const {
+FrameParser::FrameHeader::IsValid() const
+{
   return mPos >= SIZE;
 }
 
 void
-FrameParser::FrameHeader::Reset() {
+FrameParser::FrameHeader::Reset()
+{
   mPos = 0;
 }
 
 bool
-FrameParser::FrameHeader::Update(uint8_t c) {
+FrameParser::FrameHeader::Update(uint8_t c)
+{
   if (mPos < SIZE) {
     mRaw[mPos] = c;
   }
   return IsValid(mPos++);
 }
 
 // FrameParser::VBRHeader
 
@@ -1002,82 +1078,93 @@ static const uint32_t TOC_SIZE = 100;
 } // namespace vbr_header
 
 FrameParser::VBRHeader::VBRHeader()
   : mType(NONE)
 {
 }
 
 FrameParser::VBRHeader::VBRHeaderType
-FrameParser::VBRHeader::Type() const {
+FrameParser::VBRHeader::Type() const
+{
   return mType;
 }
 
 const Maybe<uint32_t>&
-FrameParser::VBRHeader::NumAudioFrames() const {
+FrameParser::VBRHeader::NumAudioFrames() const
+{
   return mNumAudioFrames;
 }
 
 const Maybe<uint32_t>&
-FrameParser::VBRHeader::NumBytes() const {
+FrameParser::VBRHeader::NumBytes() const
+{
   return mNumBytes;
 }
 
 const Maybe<uint32_t>&
-FrameParser::VBRHeader::Scale() const {
+FrameParser::VBRHeader::Scale() const
+{
   return mScale;
 }
 
 bool
-FrameParser::VBRHeader::IsTOCPresent() const {
+FrameParser::VBRHeader::IsTOCPresent() const
+{
   return mTOC.size() == vbr_header::TOC_SIZE;
 }
 
 bool
-FrameParser::VBRHeader::IsValid() const {
+FrameParser::VBRHeader::IsValid() const
+{
   return mType != NONE;
 }
 
 bool
-FrameParser::VBRHeader::IsComplete() const {
-  return IsValid() &&
-         mNumAudioFrames.valueOr(0) > 0 &&
-         mNumBytes.valueOr(0) > 0 &&
+FrameParser::VBRHeader::IsComplete() const
+{
+  return IsValid()
+         && mNumAudioFrames.valueOr(0) > 0
+         && mNumBytes.valueOr(0) > 0
          // We don't care about the scale for any computations here.
-         // mScale < 101 &&
-         true;
+         // && mScale < 101
+         && true;
 }
 
 int64_t
-FrameParser::VBRHeader::Offset(float aDurationFac) const {
+FrameParser::VBRHeader::Offset(float aDurationFac) const
+{
   if (!IsTOCPresent()) {
     return -1;
   }
 
   // Constrain the duration percentage to [0, 99].
-  const float durationPer = 100.0f * std::min(0.99f, std::max(0.0f, aDurationFac));
+  const float durationPer =
+    100.0f * std::min(0.99f, std::max(0.0f, aDurationFac));
   const size_t fullPer = durationPer;
   const float rest = durationPer - fullPer;
 
   MOZ_ASSERT(fullPer < mTOC.size());
   int64_t offset = mTOC.at(fullPer);
 
   if (rest > 0.0 && fullPer + 1 < mTOC.size()) {
     offset += rest * (mTOC.at(fullPer + 1) - offset);
   }
 
   return offset;
 }
 
 bool
-FrameParser::VBRHeader::ParseXing(ByteReader* aReader) {
+FrameParser::VBRHeader::ParseXing(ByteReader* aReader)
+{
   static const uint32_t XING_TAG = BigEndian::readUint32("Xing");
   static const uint32_t INFO_TAG = BigEndian::readUint32("Info");
 
-  enum Flags {
+  enum Flags
+  {
     NUM_FRAMES = 0x01,
     NUM_BYTES = 0x02,
     TOC = 0x04,
     VBR_SCALE = 0x08
   };
 
   MOZ_ASSERT(aReader);
   const size_t prevReaderOffset = aReader->Offset();
@@ -1119,25 +1206,27 @@ FrameParser::VBRHeader::ParseXing(ByteRe
     mScale = Some(aReader->ReadU32());
   }
 
   aReader->Seek(prevReaderOffset);
   return mType == XING;
 }
 
 bool
-FrameParser::VBRHeader::ParseVBRI(ByteReader* aReader) {
+FrameParser::VBRHeader::ParseVBRI(ByteReader* aReader)
+{
   static const uint32_t TAG = BigEndian::readUint32("VBRI");
   static const uint32_t OFFSET = 32 + FrameParser::FrameHeader::SIZE;
   static const uint32_t FRAME_COUNT_OFFSET = OFFSET + 14;
   static const uint32_t MIN_FRAME_SIZE = OFFSET + 26;
 
   MOZ_ASSERT(aReader);
-  // ParseVBRI assumes that the ByteReader offset points to the beginning of a frame,
-  // therefore as a simple check, we look for the presence of a frame sync at that position.
+  // ParseVBRI assumes that the ByteReader offset points to the beginning of a
+  // frame, therefore as a simple check, we look for the presence of a frame
+  // sync at that position.
   MOZ_ASSERT((aReader->PeekU16() & 0xFFE0) == 0xFFE0);
   const size_t prevReaderOffset = aReader->Offset();
 
   // VBRI have a fixed relative position, so let's check for it there.
   if (aReader->Remaining() > MIN_FRAME_SIZE) {
     aReader->Seek(prevReaderOffset + OFFSET);
     if (aReader->ReadU32() == TAG) {
       aReader->Seek(prevReaderOffset + FRAME_COUNT_OFFSET);
@@ -1147,59 +1236,65 @@ FrameParser::VBRHeader::ParseVBRI(ByteRe
       return true;
     }
   }
   aReader->Seek(prevReaderOffset);
   return false;
 }
 
 bool
-FrameParser::VBRHeader::Parse(ByteReader* aReader) {
+FrameParser::VBRHeader::Parse(ByteReader* aReader)
+{
   const bool rv = ParseVBRI(aReader) || ParseXing(aReader);
   if (rv) {
     MP3LOG("VBRHeader::Parse found valid VBR/CBR header: type=%s"
            " NumAudioFrames=%u NumBytes=%u Scale=%u TOC-size=%u",
            vbr_header::TYPE_STR[Type()], NumAudioFrames().valueOr(0),
            NumBytes().valueOr(0), Scale().valueOr(0), mTOC.size());
   }
   return rv;
 }
 
 // FrameParser::Frame
 
 void
-FrameParser::Frame::Reset() {
+FrameParser::Frame::Reset()
+{
   mHeader.Reset();
 }
 
 int32_t
-FrameParser::Frame::Length() const {
+FrameParser::Frame::Length() const
+{
   if (!mHeader.IsValid() || !mHeader.SampleRate()) {
     return 0;
   }
 
   const float bitsPerSample = mHeader.SamplesPerFrame() / 8.0f;
-  const int32_t frameLen = bitsPerSample * mHeader.Bitrate() /
-                           mHeader.SampleRate() +
-                           mHeader.Padding() * mHeader.SlotSize();
+  const int32_t frameLen = bitsPerSample * mHeader.Bitrate()
+                           / mHeader.SampleRate()
+                           + mHeader.Padding() * mHeader.SlotSize();
   return frameLen;
 }
 
 bool
-FrameParser::Frame::ParseNext(uint8_t c) {
+FrameParser::Frame::ParseNext(uint8_t c)
+{
   return mHeader.ParseNext(c);
 }
 
 const FrameParser::FrameHeader&
-FrameParser::Frame::Header() const {
+FrameParser::Frame::Header() const
+{
   return mHeader;
 }
 
 bool
-FrameParser::ParseVBRHeader(ByteReader* aReader) {
+FrameParser::ParseVBRHeader(ByteReader* aReader)
+{
   return mVBRHeader.Parse(aReader);
 }
 
 // ID3Parser
 
 // Constants
 namespace id3_header {
 static const int ID_LEN = 3;
@@ -1214,126 +1309,139 @@ static const int SIZE_END = FLAGS_END + 
 
 static const uint8_t ID[ID_LEN] = {'I', 'D', '3'};
 
 static const uint8_t MIN_MAJOR_VER = 2;
 static const uint8_t MAX_MAJOR_VER = 4;
 } // namespace id3_header
 
 uint32_t
-ID3Parser::Parse(ByteReader* aReader) {
+ID3Parser::Parse(ByteReader* aReader)
+{
   MOZ_ASSERT(aReader);
 
   while (aReader->CanRead8() && !mHeader.ParseNext(aReader->ReadU8())) { }
 
   if (mHeader.IsValid()) {
     // Header found, return total tag size.
     return ID3Header::SIZE + Header().Size() + Header().FooterSize();
   }
   return 0;
 }
 
 void
-ID3Parser::Reset() {
+ID3Parser::Reset()
+{
   mHeader.Reset();
 }
 
 const ID3Parser::ID3Header&
-ID3Parser::Header() const {
+ID3Parser::Header() const
+{
   return mHeader;
 }
 
 // ID3Parser::Header
 
 ID3Parser::ID3Header::ID3Header()
 {
   Reset();
 }
 
 void
-ID3Parser::ID3Header::Reset() {
+ID3Parser::ID3Header::Reset()
+{
   mSize = 0;
   mPos = 0;
 }
 
 uint8_t
-ID3Parser::ID3Header::MajorVersion() const {
+ID3Parser::ID3Header::MajorVersion() const
+{
   return mRaw[id3_header::ID_END];
 }
 
 uint8_t
-ID3Parser::ID3Header::MinorVersion() const {
+ID3Parser::ID3Header::MinorVersion() const
+{
   return mRaw[id3_header::ID_END + 1];
 }
 
 uint8_t
-ID3Parser::ID3Header::Flags() const {
+ID3Parser::ID3Header::Flags() const
+{
   return mRaw[id3_header::FLAGS_END - id3_header::FLAGS_LEN];
 }
 
 uint32_t
-ID3Parser::ID3Header::Size() const {
+ID3Parser::ID3Header::Size() const
+{
   if (!IsValid()) {
     return 0;
   }
   return mSize;
 }
 
 uint8_t
-ID3Parser::ID3Header::FooterSize() const {
+ID3Parser::ID3Header::FooterSize() const
+{
   if (Flags() & (1 << 4)) {
     return SIZE;
   }
   return 0;
 }
 
 bool
-ID3Parser::ID3Header::ParseNext(uint8_t c) {
+ID3Parser::ID3Header::ParseNext(uint8_t c)
+{
   if (!Update(c)) {
     Reset();
     if (!Update(c)) {
       Reset();
     }
   }
   return IsValid();
 }
 
 bool
-ID3Parser::ID3Header::IsValid(int aPos) const {
+ID3Parser::ID3Header::IsValid(int aPos) const
+{
   if (aPos >= SIZE) {
     return true;
   }
   const uint8_t c = mRaw[aPos];
   switch (aPos) {
     case 0: case 1: case 2:
       // Expecting "ID3".
       return id3_header::ID[aPos] == c;
     case 3:
-      return MajorVersion() >= id3_header::MIN_MAJOR_VER &&
-             MajorVersion() <= id3_header::MAX_MAJOR_VER;
+      return MajorVersion() >= id3_header::MIN_MAJOR_VER
+             && MajorVersion() <= id3_header::MAX_MAJOR_VER;
     case 4:
       return MinorVersion() < 0xFF;
     case 5:
       // Validate flags for supported versions, see bug 949036.
       return ((0xFF >> MajorVersion()) & c) == 0;
     case 6: case 7: case 8: case 9:
       return c < 0x80;
   }
   return true;
 }
 
 bool
-ID3Parser::ID3Header::IsValid() const {
+ID3Parser::ID3Header::IsValid() const
+{
   return mPos >= SIZE;
 }
 
 bool
-ID3Parser::ID3Header::Update(uint8_t c) {
-  if (mPos >= id3_header::SIZE_END - id3_header::SIZE_LEN &&
-      mPos < id3_header::SIZE_END) {
+ID3Parser::ID3Header::Update(uint8_t c)
+{
+  if (mPos >= id3_header::SIZE_END - id3_header::SIZE_LEN
+      && mPos < id3_header::SIZE_END) {
     mSize <<= 7;
     mSize |= c;
   }
   if (mPos < SIZE) {
     mRaw[mPos] = c;
   }
   return IsValid(mPos++);
 }
--- a/dom/media/MP3Demuxer.h
+++ b/dom/media/MP3Demuxer.h
@@ -12,17 +12,18 @@
 #include "mp4_demuxer/ByteReader.h"
 #include <vector>
 
 namespace mozilla {
 namespace mp3 {
 
 class MP3TrackDemuxer;
 
-class MP3Demuxer : public MediaDataDemuxer {
+class MP3Demuxer : public MediaDataDemuxer
+{
 public:
   // MediaDataDemuxer interface.
   explicit MP3Demuxer(MediaResource* aSource);
   RefPtr<InitPromise> Init() override;
   bool HasTrackType(TrackInfo::TrackType aType) const override;
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
   already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
       TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
@@ -37,20 +38,22 @@ private:
   RefPtr<MediaResource> mSource;
   RefPtr<MP3TrackDemuxer> mTrackDemuxer;
 };
 
 // ID3 header parser state machine used by FrameParser.
 // The header contains the following format (one byte per term):
 // 'I' 'D' '3' MajorVersion MinorVersion Flags Size1 Size2 Size3 Size4
 // For more details see http://id3.org/id3v2.3.0.
-class ID3Parser {
+class ID3Parser
+{
 public:
   // Holds the ID3 header and its parsing state.
-  class ID3Header {
+  class ID3Header
+  {
   public:
     // The header size is static, see class comment.
     static const int SIZE = 10;
 
     // Constructor.
     ID3Header();
 
     // Resets the state to allow for a new parsing session.
@@ -125,20 +128,22 @@ private:
 //   P          - Padding bit (0->not padded, 1->padded by 1 slot size)
 //   R          - Private bit (ignored)
 //   MM         - Channel mode (0->stereo, 1->joint stereo, 2->dual channel,
 //                3->single channel)
 //   EE         - Mode extension for joint stereo (ignored)
 //   T          - Copyright (0->disabled, 1->enabled)
 //   O          - Original (0->copy, 1->original)
 //   HH         - Emphasis (0->none, 1->50/15 ms, 2->reserved, 3->CCIT J.17)
-class FrameParser {
+class FrameParser
+{
 public:
   // Holds the frame header and its parsing state.
-  class FrameHeader {
+  class FrameHeader
+  {
   public:
     // The header size is static, see class comments.
     static const int SIZE = 4;
 
     // Constructor.
     FrameHeader();
 
     // Raw field access, see class comments for details.
@@ -195,20 +200,22 @@ public:
 
     // The current byte position in the parsed sequence. Reset via Reset and
     // incremented via Update.
     int mPos;
   };
 
   // VBR frames may contain Xing or VBRI headers for additional info, we use
   // this class to parse them and access this info.
-  class VBRHeader {
+  class VBRHeader
+  {
   public:
     // Synchronize with vbr_header TYPE_STR on change.
-    enum VBRHeaderType {
+    enum VBRHeaderType
+    {
       NONE = 0,
       XING,
       VBRI
     };
 
     // Constructor.
     VBRHeader();
 
@@ -226,27 +233,28 @@ public:
     const Maybe<uint32_t>& Scale() const;
 
     // Returns true iff Xing/Info TOC (table of contents) is present.
     bool IsTOCPresent() const;
 
     // Returns whether the header is valid (type XING or VBRI).
     bool IsValid() const;
 
-    // Returns whether the header is valid and contains reasonable non-zero field values.
+    // Returns whether the header is valid and contains reasonable non-zero
+    // field values.
     bool IsComplete() const;
 
     // Returns the byte offset for the given duration percentage as a factor
     // (0: begin, 1.0: end).
     int64_t Offset(float aDurationFac) const;
 
     // Parses contents of given ByteReader for a valid VBR header.
-    // The offset of the passed ByteReader needs to point to an MPEG frame begin,
-    // as a VBRI-style header is searched at a fixed offset relative to frame begin.
-    // Returns whether a valid VBR header was found in the range.
+    // The offset of the passed ByteReader needs to point to an MPEG frame
+    // begin, as a VBRI-style header is searched at a fixed offset relative to
+    // frame begin. Returns whether a valid VBR header was found in the range.
     bool Parse(mp4_demuxer::ByteReader* aReader);
 
   private:
     // Parses contents of given ByteReader for a valid Xing header.
     // The initial ByteReader offset will be preserved.
     // Returns whether a valid Xing header was found in the range.
     bool ParseXing(mp4_demuxer::ByteReader* aReader);
 
@@ -269,17 +277,18 @@ public:
     // The TOC table mapping duration percentage to byte offset.
     std::vector<int64_t> mTOC;
 
     // The detected VBR header type.
     VBRHeaderType mType;
   };
 
   // Frame meta container used to parse and hold a frame header and side info.
-  class Frame {
+  class Frame
+  {
   public:
     // Returns the length of the frame excluding the header in bytes.
     int32_t Length() const;
 
     // Returns the parsed frame header.
     const FrameHeader& Header() const;
 
     // Resets the frame header and data.
@@ -320,26 +329,26 @@ public:
   void ResetFrameData();
 
   // Clear the last parsed frame to allow for next frame parsing, i.e.:
   // - sets PrevFrame to CurrentFrame
   // - resets the CurrentFrame
   // - resets ID3Header if no valid header was parsed yet
   void EndFrameSession();
 
-  // Parses contents of given ByteReader for a valid frame header and returns true
-  // if one was found. After returning, the variable passed to 'aBytesToSkip' holds
-  // the amount of bytes to be skipped (if any) in order to jump across a large
-  // ID3v2 tag spanning multiple buffers.
+  // Parses contents of given ByteReader for a valid frame header and returns
+  // true if one was found. After returning, the variable passed to
+  // 'aBytesToSkip' holds the amount of bytes to be skipped (if any) in order to
+  // jump across a large ID3v2 tag spanning multiple buffers.
   bool Parse(mp4_demuxer::ByteReader* aReader, uint32_t* aBytesToSkip);
 
   // Parses contents of given ByteReader for a valid VBR header.
   // The offset of the passed ByteReader needs to point to an MPEG frame begin,
-  // as a VBRI-style header is searched at a fixed offset relative to frame begin.
-  // Returns whether a valid VBR header was found.
+  // as a VBRI-style header is searched at a fixed offset relative to frame
+  // begin. Returns whether a valid VBR header was found.
   bool ParseVBRHeader(mp4_demuxer::ByteReader* aReader);
 
 private:
   // ID3 header parser.
   ID3Parser mID3Parser;
 
   // VBR header parser.
   VBRHeader mVBRHeader;
@@ -348,17 +357,18 @@ private:
   // previously parsed frame for debugging and the currently parsed frame.
   Frame mFirstFrame;
   Frame mFrame;
   Frame mPrevFrame;
 };
 
 // The MP3 demuxer used to extract MPEG frames and side information out of
 // MPEG streams.
-class MP3TrackDemuxer : public MediaTrackDemuxer {
+class MP3TrackDemuxer : public MediaTrackDemuxer
+{
 public:
   // Constructor, expecting a valid media resource.
   explicit MP3TrackDemuxer(MediaResource* aSource);
 
   // Initializes the track demuxer by reading the first frame for meta data.
   // Returns initialization success state.
   bool Init();
 
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -84,74 +84,76 @@ AudioData::TransferAndUpdateTimestampAnd
                                       aOther->mChannels,
                                       aOther->mRate);
   return v.forget();
 }
 
 static bool
 ValidatePlane(const VideoData::YCbCrBuffer::Plane& aPlane)
 {
-  return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION &&
-         aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION &&
-         aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT &&
-         aPlane.mStride > 0;
+  return aPlane.mWidth <= PlanarYCbCrImage::MAX_DIMENSION
+         && aPlane.mHeight <= PlanarYCbCrImage::MAX_DIMENSION
+         && aPlane.mWidth * aPlane.mHeight < MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT
+         && aPlane.mStride > 0;
 }
 
 static bool ValidateBufferAndPicture(const VideoData::YCbCrBuffer& aBuffer,
                                      const IntRect& aPicture)
 {
   // The following situation should never happen unless there is a bug
   // in the decoder
-  if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth ||
-      aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
+  if (aBuffer.mPlanes[1].mWidth != aBuffer.mPlanes[2].mWidth
+      || aBuffer.mPlanes[1].mHeight != aBuffer.mPlanes[2].mHeight) {
     NS_ERROR("C planes with different sizes");
     return false;
   }
 
   // The following situations could be triggered by invalid input
   if (aPicture.width <= 0 || aPicture.height <= 0) {
     // In debug mode, makes the error more noticeable
     MOZ_ASSERT(false, "Empty picture rect");
     return false;
   }
-  if (!ValidatePlane(aBuffer.mPlanes[0]) ||
-      !ValidatePlane(aBuffer.mPlanes[1]) ||
-      !ValidatePlane(aBuffer.mPlanes[2])) {
+  if (!ValidatePlane(aBuffer.mPlanes[0])
+      || !ValidatePlane(aBuffer.mPlanes[1])
+      || !ValidatePlane(aBuffer.mPlanes[2])) {
     NS_WARNING("Invalid plane size");
     return false;
   }
 
   // Ensure the picture size specified in the headers can be extracted out of
   // the frame we've been supplied without indexing out of bounds.
   CheckedUint32 xLimit = aPicture.x + CheckedUint32(aPicture.width);
   CheckedUint32 yLimit = aPicture.y + CheckedUint32(aPicture.height);
-  if (!xLimit.isValid() || xLimit.value() > aBuffer.mPlanes[0].mStride ||
-      !yLimit.isValid() || yLimit.value() > aBuffer.mPlanes[0].mHeight)
+  if (!xLimit.isValid()
+      || xLimit.value() > aBuffer.mPlanes[0].mStride
+      || !yLimit.isValid()
+      || yLimit.value() > aBuffer.mPlanes[0].mHeight)
   {
     // The specified picture dimensions can't be contained inside the video
     // frame, we'll stomp memory if we try to copy it. Fail.
     NS_WARNING("Overflowing picture rect");
     return false;
   }
   return true;
 }
 
 #ifdef MOZ_WIDGET_GONK
 static bool
 IsYV12Format(const VideoData::YCbCrBuffer::Plane& aYPlane,
              const VideoData::YCbCrBuffer::Plane& aCbPlane,
              const VideoData::YCbCrBuffer::Plane& aCrPlane)
 {
   return
-    aYPlane.mWidth % 2 == 0 &&
-    aYPlane.mHeight % 2 == 0 &&
-    aYPlane.mWidth / 2 == aCbPlane.mWidth &&
-    aYPlane.mHeight / 2 == aCbPlane.mHeight &&
-    aCbPlane.mWidth == aCrPlane.mWidth &&
-    aCbPlane.mHeight == aCrPlane.mHeight;
+    aYPlane.mWidth % 2 == 0
+    && aYPlane.mHeight % 2 == 0
+    && aYPlane.mWidth / 2 == aCbPlane.mWidth
+    && aYPlane.mHeight / 2 == aCbPlane.mHeight
+    && aCbPlane.mWidth == aCrPlane.mWidth
+    && aCbPlane.mHeight == aCrPlane.mHeight;
 }
 
 static bool
 IsInEmulator()
 {
   char propQemu[PROPERTY_VALUE_MAX];
   property_get("ro.kernel.qemu", propQemu, "");
   return !strncmp(propQemu, "1", 1);
@@ -178,17 +180,18 @@ VideoData::VideoData(int64_t aOffset,
 
 VideoData::~VideoData()
 {
 }
 
 void
 VideoData::SetListener(UniquePtr<Listener> aListener)
 {
-  MOZ_ASSERT(!mSentToCompositor, "Listener should be registered before sending data");
+  MOZ_ASSERT(!mSentToCompositor,
+             "Listener should be registered before sending data");
 
   mListener = Move(aListener);
 }
 
 void
 VideoData::MarkSentToCompositor()
 {
   if (mSentToCompositor) {
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -61,17 +61,18 @@ template <typename Type, int Alignment =
 class AlignedBuffer
 {
 public:
   AlignedBuffer()
     : mData(nullptr)
     , mLength(0)
     , mBuffer(nullptr)
     , mCapacity(0)
-  {}
+  {
+  }
 
   explicit AlignedBuffer(size_t aLength)
     : mData(nullptr)
     , mLength(0)
     , mBuffer(nullptr)
     , mCapacity(0)
   {
     if (EnsureCapacity(aLength)) {
@@ -85,17 +86,18 @@ public:
     if (!mData) {
       return;
     }
     PodCopy(mData, aData, aLength);
   }
 
   AlignedBuffer(const AlignedBuffer& aOther)
     : AlignedBuffer(aOther.Data(), aOther.Length())
-  {}
+  {
+  }
 
   AlignedBuffer(AlignedBuffer&& aOther)
     : mData(aOther.mData)
     , mLength(aOther.mLength)
     , mBuffer(Move(aOther.mBuffer))
     , mCapacity(aOther.mCapacity)
   {
     aOther.mData = nullptr;
@@ -349,28 +351,29 @@ protected:
     , mTime(0)
     , mTimecode(0)
     , mDuration(0)
     , mFrames(aFrames)
     , mKeyframe(false)
   {
   }
 
-  virtual ~MediaData() {}
+  virtual ~MediaData() { }
 
 };
 
 // NullData is for decoder generating a sample which doesn't need to be
 // rendered.
 class NullData : public MediaData
 {
 public:
   NullData(int64_t aOffset, int64_t aTime, int64_t aDuration)
     : MediaData(NULL_DATA, aOffset, aTime, aDuration, 0)
-  {}
+  {
+  }
 
   static const Type sType = NULL_DATA;
 };
 
 // Holds chunk a decoded audio frames.
 class AudioData : public MediaData
 {
 public:
@@ -380,17 +383,19 @@ public:
             int64_t aDuration,
             uint32_t aFrames,
             AlignedAudioBuffer&& aData,
             uint32_t aChannels,
             uint32_t aRate)
     : MediaData(sType, aOffset, aTime, aDuration, aFrames)
     , mChannels(aChannels)
     , mRate(aRate)
-    , mAudioData(Move(aData)) {}
+    , mAudioData(Move(aData))
+  {
+  }
 
   static const Type sType = AUDIO_DATA;
   static const char* sTypeName;
 
   // Creates a new AudioData identical to aOther, but with a different
   // specified timestamp and duration. All data from aOther is copied
   // into the new AudioData but the audio data which is transferred.
   // After such call, the original aOther is unusable.
@@ -459,50 +464,50 @@ public:
     Plane mPlanes[3];
     YUVColorSpace mYUVColorSpace = YUVColorSpace::BT601;
   };
 
   class Listener
   {
   public:
     virtual void OnSentToCompositor() = 0;
-    virtual ~Listener() {}
+    virtual ~Listener() { }
   };
 
   // Constructs a VideoData object. If aImage is nullptr, creates a new Image
   // holding a copy of the YCbCr data passed in aBuffer. If aImage is not
   // nullptr, it's stored as the underlying video image and aBuffer is assumed
   // to point to memory within aImage so no copy is made. aTimecode is a codec
   // specific number representing the timestamp of the frame of video data.
   // Returns nsnull if an error occurs. This may indicate that memory couldn't
   // be allocated to create the VideoData object, or it may indicate some
   // problem with the input data (e.g. negative stride).
 
 
-  // Creates a new VideoData containing a deep copy of aBuffer. May use aContainer
-  // to allocate an Image to hold the copied data.
+  // Creates a new VideoData containing a deep copy of aBuffer. May use
+  // aContainer to allocate an Image to hold the copied data.
   static already_AddRefed<VideoData> CreateAndCopyData(
     const VideoInfo& aInfo,
     ImageContainer* aContainer,
     int64_t aOffset,
     int64_t aTime,
     int64_t aDuration,
-    const YCbCrBuffer &aBuffer,
+    const YCbCrBuffer& aBuffer,
     bool aKeyframe,
     int64_t aTimecode,
     const IntRect& aPicture);
 
   static already_AddRefed<VideoData> CreateAndCopyData(
     const VideoInfo& aInfo,
     ImageContainer* aContainer,
     int64_t aOffset,
     int64_t aTime,
     int64_t aDuration,
-    const YCbCrBuffer &aBuffer,
-    const YCbCrBuffer::Plane &aAlphaPlane,
+    const YCbCrBuffer& aBuffer,
+    const YCbCrBuffer::Plane& aAlphaPlane,
     bool aKeyframe,
     int64_t aTimecode,
     const IntRect& aPicture);
 
   static already_AddRefed<VideoData> CreateAndCopyIntoTextureClient(
     const VideoInfo& aInfo,
     int64_t aOffset,
     int64_t aTime,
@@ -521,17 +526,17 @@ public:
     bool aKeyframe,
     int64_t aTimecode,
     const IntRect& aPicture);
 
   // Initialize PlanarYCbCrImage. Only When aCopyData is true,
   // video data is copied to PlanarYCbCrImage.
   static bool SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
                                   const VideoInfo& aInfo,
-                                  const YCbCrBuffer &aBuffer,
+                                  const YCbCrBuffer& aBuffer,
                                   const IntRect& aPicture,
                                   bool aCopyData);
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
 
   // Dimensions at which to display the video frame. The picture region
   // will be scaled to this size. This is should be the picture region's
   // dimensions scaled with respect to its aspect ratio.
@@ -683,17 +688,18 @@ private:
   friend class MediaRawDataWriter;
   AlignedByteBuffer mBuffer;
   AlignedByteBuffer mAlphaBuffer;
   CryptoSample mCryptoInternal;
   MediaRawData(const MediaRawData&); // Not implemented
 };
 
   // MediaByteBuffer is a ref counted infallible TArray.
-class MediaByteBuffer : public nsTArray<uint8_t> {
+class MediaByteBuffer : public nsTArray<uint8_t>
+{
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaByteBuffer);
   MediaByteBuffer() = default;
   explicit MediaByteBuffer(size_t aCapacity) : nsTArray<uint8_t>(aCapacity) { }
 
 private:
   ~MediaByteBuffer() { }
 };
 
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2313,16 +2313,21 @@ SeekingState::SeekCompleted()
     AudioQueue().Finish();
     VideoQueue().Finish();
 
     // We won't start MediaSink when paused. m{Audio,Video}Completed will
     // remain false and 'playbackEnded' won't be notified. Therefore we
     // need to set these flags explicitly when seeking to the end.
     mMaster->mAudioCompleted = true;
     mMaster->mVideoCompleted = true;
+
+    // There might still be a pending audio request when doing video-only or
+    // next-frame seek. Discard it so we won't break the invariants of the
+    // COMPLETED state by adding audio samples to a finished queue.
+    mMaster->mAudioDataRequest.DisconnectIfExists();
   }
 
   // Cache mTarget for mSeekJob.Resolve() below will reset it.
   SeekTarget target = mSeekJob.mTarget.ref();
 
   // We want to resolve the seek request prior finishing the first frame
   // to ensure that the seeked event is fired prior loadeded.
   mSeekJob.Resolve(__func__);
--- a/dom/media/flac/FlacDemuxer.cpp
+++ b/dom/media/flac/FlacDemuxer.cpp
@@ -36,17 +36,18 @@ namespace flac {
 #define FLAC_MAX_CHANNELS           8
 #define FLAC_MIN_BLOCKSIZE         16
 #define FLAC_MAX_BLOCKSIZE      65535
 #define FLAC_MIN_FRAME_SIZE        11
 #define FLAC_MAX_FRAME_HEADER_SIZE 16
 #define FLAC_MAX_FRAME_SIZE (FLAC_MAX_FRAME_HEADER_SIZE \
                              +FLAC_MAX_BLOCKSIZE*FLAC_MAX_CHANNELS*3)
 
-class FrameHeader {
+class FrameHeader
+{
 public:
   const AudioInfo& Info() const { return mInfo; }
 
   uint32_t Size() const { return mSize; }
 
   bool IsValid() const { return mValid; }
 
   // Return the index (in samples) from the beginning of the track.
@@ -154,17 +155,18 @@ public:
       mInfo.mMimeType = "audio/flac";
     }
 
     return mValid;
   }
 
 private:
   friend class Frame;
-  enum {
+  enum
+  {
     FLAC_CHMODE_INDEPENDENT = 0,
     FLAC_CHMODE_LEFT_SIDE,
     FLAC_CHMODE_RIGHT_SIDE,
     FLAC_CHMODE_MID_SIDE,
   };
   AudioInfo mInfo;
   // Index in samples from start;
   int64_t mIndex = 0;
@@ -175,17 +177,18 @@ private:
 
   static const int FlacSampleRateTable[16];
   static const int32_t FlacBlocksizeTable[16];
   static const uint8_t FlacSampleSizeTable[8];
   static const uint8_t CRC8Table[256];
 };
 
 const int FrameHeader::FlacSampleRateTable[16] =
-{ 0,
+{
+  0,
   88200, 176400, 192000,
   8000, 16000, 22050, 24000, 32000, 44100, 48000, 96000,
   0, 0, 0, 0
 };
 
 const int32_t FrameHeader::FlacBlocksizeTable[16] =
 {
   0     , 192   , 576<<0, 576<<1, 576<<2, 576<<3,      0,      0,
@@ -227,17 +230,18 @@ const uint8_t FrameHeader::CRC8Table[256
   0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
   0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
   0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
   0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
 };
 
 // flac::Frame - Frame meta container used to parse and hold a frame
 // header and side info.
-class Frame {
+class Frame
+{
 public:
 
   // The FLAC signature is made of 14 bits set to 1; however the 15th bit is
   // mandatorily set to 0, so we need to find either of 0xfffc or 0xfffd 2-bytes
   // signature. We first use a bitmask to see if 0xfc or 0xfd is present. And if
   // so we check for the whole signature.
   // aData must be pointing to a buffer at least
   // aLength + FLAC_MAX_FRAME_HEADER_SIZE bytes.
@@ -379,17 +383,18 @@ private:
   uint32_t mDuration = 0;
   bool mEOS = false;
 
   // The currently parsed frame header.
   FrameHeader mHeader;
 
 };
 
-class FrameParser {
+class FrameParser
+{
 public:
 
   // Returns the currently parsed frame. Reset via EndFrameSession.
   const Frame& CurrentFrame() const { return mFrame; }
 
   // Returns the first parsed frame.
   const Frame& FirstFrame() const { return mFirstFrame; }
 
@@ -558,19 +563,17 @@ private:
   Frame mNextFrame;
   Frame mFrame;
 };
 
 } // namespace flac
 
 // FlacDemuxer
 
-FlacDemuxer::FlacDemuxer(MediaResource* aSource)
-  : mSource(aSource)
-{}
+FlacDemuxer::FlacDemuxer(MediaResource* aSource) : mSource(aSource) { }
 
 bool
 FlacDemuxer::InitInternal()
 {
   if (!mTrackDemuxer) {
     mTrackDemuxer = new FlacTrackDemuxer(mSource);
   }
   return mTrackDemuxer->Init();
@@ -633,17 +636,18 @@ FlacTrackDemuxer::~FlacTrackDemuxer()
 
 bool
 FlacTrackDemuxer::Init()
 {
   static const int BUFFER_SIZE = 4096;
 
   // First check if we have a valid Flac start.
   char buffer[BUFFER_SIZE];
-  const uint8_t* ubuffer = reinterpret_cast<uint8_t*>(buffer); // only needed due to type constraints of ReadAt.
+  const uint8_t* ubuffer = // only needed due to type constraints of ReadAt.
+    reinterpret_cast<uint8_t*>(buffer);
   int64_t offset = 0;
 
   do {
     uint32_t read = 0;
     nsresult ret = mSource.ReadAt(offset, buffer, BUFFER_SIZE, &read);
     if (NS_FAILED(ret) || read < BUFFER_SIZE) {
       // Assume that if we can't read that many bytes while parsing the header,
       // that something is wrong.
@@ -757,17 +761,18 @@ FlacTrackDemuxer::FastSeek(const TimeUni
   // We look for the seek position using a bisection search, starting where the
   // estimated position might be using the average frame length.
   // Typically, with flac such approximation is typically useless.
 
   // Estimate where the position might be.
   int64_t pivot =
     aTime.ToSeconds() * AverageFrameLength() + mParser->FirstFrame().Offset();
 
-  // Time in seconds where we can stop seeking and will continue using ScanUntil.
+  // Time in seconds where we can stop seeking and will continue using
+  // ScanUntil.
   static const int GAP_THRESHOLD = 5;
   int64_t first = mParser->FirstFrame().Offset();
   int64_t last = mSource.GetLength();
   Maybe<int64_t> lastFoundOffset;
   uint32_t iterations = 0;
   TimeUnit timeSeekedTo;
 
   do {
--- a/dom/media/flac/FlacDemuxer.h
+++ b/dom/media/flac/FlacDemuxer.h
@@ -14,17 +14,18 @@ namespace mozilla {
 
 namespace flac {
 class Frame;
 class FrameParser;
 }
 class FlacTrackDemuxer;
 
 
-class FlacDemuxer : public MediaDataDemuxer {
+class FlacDemuxer : public MediaDataDemuxer
+{
 public:
   // MediaDataDemuxer interface.
   explicit FlacDemuxer(MediaResource* aSource);
   RefPtr<InitPromise> Init() override;
   bool HasTrackType(TrackInfo::TrackType aType) const override;
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
   already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
     TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
@@ -35,17 +36,18 @@ public:
 
 private:
   bool InitInternal();
 
   RefPtr<MediaResource> mSource;
   RefPtr<FlacTrackDemuxer> mTrackDemuxer;
 };
 
-class FlacTrackDemuxer : public MediaTrackDemuxer {
+class FlacTrackDemuxer : public MediaTrackDemuxer
+{
 public:
   explicit FlacTrackDemuxer(MediaResource* aSource);
 
   // Initializes the track demuxer by reading the first frame for meta data.
   // Returns initialization success state.
   bool Init();
 
   // MediaTrackDemuxer interface.
@@ -66,17 +68,18 @@ private:
 
   // Returns the estimated stream duration, or a 0-duration if unknown.
   media::TimeUnit Duration() const;
   media::TimeUnit TimeAtEnd();
 
   // Fast approximate seeking to given time.
   media::TimeUnit FastSeek(const media::TimeUnit& aTime);
 
-  // Seeks by scanning the stream up to the given time for more accurate results.
+  // Seeks by scanning the stream up to the given time for more accurate
+  // results.
   media::TimeUnit ScanUntil(const media::TimeUnit& aTime);
 
   // Finds the next valid frame and return it.
   const flac::Frame& FindNextFrame();
 
   // Returns the next ADTS frame, if available.
   already_AddRefed<MediaRawData> GetNextFrame(const flac::Frame& aFrame);
 
--- a/dom/media/fmp4/MP4Demuxer.cpp
+++ b/dom/media/fmp4/MP4Demuxer.cpp
@@ -4,32 +4,32 @@
  * 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 <limits>
 #include <stdint.h>
 
 #include "MP4Demuxer.h"
+
+// Used for telemetry
+#include "mozilla/Telemetry.h"
+#include "mp4_demuxer/AnnexB.h"
+#include "mp4_demuxer/H264.h"
 #include "mp4_demuxer/MoofParser.h"
 #include "mp4_demuxer/MP4Metadata.h"
 #include "mp4_demuxer/ResourceStream.h"
 #include "mp4_demuxer/BufferStream.h"
 #include "mp4_demuxer/Index.h"
+#include "nsAutoPtr.h"
 #include "nsPrintfCString.h"
 
-// Used for telemetry
-#include "mozilla/Telemetry.h"
-#include "mp4_demuxer/AnnexB.h"
-#include "mp4_demuxer/H264.h"
-
-#include "nsAutoPtr.h"
-
 extern mozilla::LazyLogModule gMediaDemuxerLog;
-mozilla::LogModule* GetDemuxerLog() {
+mozilla::LogModule* GetDemuxerLog()
+{
   return gMediaDemuxerLog;
 }
 
 #define LOG(arg, ...) MOZ_LOG(gMediaDemuxerLog, mozilla::LogLevel::Debug, ("MP4Demuxer(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
 namespace mozilla {
 
 class MP4TrackDemuxer : public MediaTrackDemuxer
@@ -77,34 +77,35 @@ private:
 
 
 // Returns true if no SPS was found and search for it should continue.
 bool
 AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
 {
   mp4_demuxer::SPSData spsdata;
   if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
-    uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
-                          (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
-                          (spsdata.constraint_set2_flag ? (1 << 2) : 0) |
-                          (spsdata.constraint_set3_flag ? (1 << 3) : 0) |
-                          (spsdata.constraint_set4_flag ? (1 << 4) : 0) |
-                          (spsdata.constraint_set5_flag ? (1 << 5) : 0);
+    uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0)
+                          | (spsdata.constraint_set1_flag ? (1 << 1) : 0)
+                          | (spsdata.constraint_set2_flag ? (1 << 2) : 0)
+                          | (spsdata.constraint_set3_flag ? (1 << 3) : 0)
+                          | (spsdata.constraint_set4_flag ? (1 << 4) : 0)
+                          | (spsdata.constraint_set5_flag ? (1 << 5) : 0);
     Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_CONSTRAINT_SET_FLAG,
                           constraints);
 
     // Collect profile_idc values up to 244, otherwise 0 for unknown.
     Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_PROFILE,
                           spsdata.profile_idc <= 244 ? spsdata.profile_idc : 0);
 
     // Make sure level_idc represents a value between levels 1 and 5.2,
     // otherwise collect 0 for unknown level.
     Telemetry::Accumulate(Telemetry::VIDEO_DECODED_H264_SPS_LEVEL,
-                          (spsdata.level_idc >= 10 && spsdata.level_idc <= 52) ?
-                          spsdata.level_idc : 0);
+                          (spsdata.level_idc >= 10 && spsdata.level_idc <= 52)
+                          ? spsdata.level_idc
+                          : 0);
 
     // max_num_ref_frames should be between 0 and 16, anything larger will
     // be treated as invalid.
     Telemetry::Accumulate(Telemetry::VIDEO_H264_SPS_MAX_NUM_REF_FRAMES,
                           std::min(spsdata.max_num_ref_frames, 17u));
 
     return false;
   }
@@ -121,33 +122,36 @@ MP4Demuxer::MP4Demuxer(MediaResource* aR
 
 RefPtr<MP4Demuxer::InitPromise>
 MP4Demuxer::Init()
 {
   AutoPinned<mp4_demuxer::ResourceStream> stream(mStream);
 
   // Check that we have enough data to read the metadata.
   if (!mp4_demuxer::MP4Metadata::HasCompleteMetadata(stream)) {
-    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, __func__);
+    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
+                                        __func__);
   }
 
   mInitData = mp4_demuxer::MP4Metadata::Metadata(stream);
   if (!mInitData) {
     // OOM
-    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, __func__);
+    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
+                                        __func__);
   }
 
   RefPtr<mp4_demuxer::BufferStream> bufferstream =
     new mp4_demuxer::BufferStream(mInitData);
 
   mMetadata = MakeUnique<mp4_demuxer::MP4Metadata>(bufferstream);
 
-  if (!mMetadata->GetNumberTracks(mozilla::TrackInfo::kAudioTrack) &&
-      !mMetadata->GetNumberTracks(mozilla::TrackInfo::kVideoTrack)) {
-    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, __func__);
+  if (!mMetadata->GetNumberTracks(mozilla::TrackInfo::kAudioTrack)
+      && !mMetadata->GetNumberTracks(mozilla::TrackInfo::kVideoTrack)) {
+    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
+                                        __func__);
   }
 
   return InitPromise::CreateAndResolve(NS_OK, __func__);
 }
 
 bool
 MP4Demuxer::HasTrackType(TrackInfo::TrackType aType) const
 {
@@ -238,26 +242,26 @@ MP4TrackDemuxer::MP4TrackDemuxer(MP4Demu
                                   mInfo->IsAudio()))
   , mIterator(MakeUnique<mp4_demuxer::SampleIterator>(mIndex))
   , mNeedReIndex(true)
 {
   EnsureUpToDateIndex(); // Force update of index
 
   VideoInfo* videoInfo = mInfo->GetAsVideoInfo();
   // Collect telemetry from h264 AVCC SPS.
-  if (videoInfo &&
-      (mInfo->mMimeType.EqualsLiteral("video/mp4") ||
-       mInfo->mMimeType.EqualsLiteral("video/avc"))) {
+  if (videoInfo
+      && (mInfo->mMimeType.EqualsLiteral("video/mp4")
+          || mInfo->mMimeType.EqualsLiteral("video/avc"))) {
     mIsH264 = true;
     RefPtr<MediaByteBuffer> extraData = videoInfo->mExtraData;
     mNeedSPSForTelemetry = AccumulateSPSTelemetry(extraData);
     mp4_demuxer::SPSData spsdata;
-    if (mp4_demuxer::H264::DecodeSPSFromExtraData(extraData, spsdata) &&
-        spsdata.pic_width > 0 && spsdata.pic_height > 0 &&
-        mp4_demuxer::H264::EnsureSPSIsSane(spsdata)) {
+    if (mp4_demuxer::H264::DecodeSPSFromExtraData(extraData, spsdata)
+        && spsdata.pic_width > 0 && spsdata.pic_height > 0
+        && mp4_demuxer::H264::EnsureSPSIsSane(spsdata)) {
       videoInfo->mImage.width = spsdata.pic_width;
       videoInfo->mImage.height = spsdata.pic_height;
       videoInfo->mDisplay.width = spsdata.display_width;
       videoInfo->mDisplay.height = spsdata.display_height;
     }
   } else {
     // No SPS to be found.
     mNeedSPSForTelemetry = false;
@@ -294,31 +298,33 @@ MP4TrackDemuxer::Seek(const media::TimeU
 
   mIterator->Seek(seekTime);
 
   // Check what time we actually seeked to.
   RefPtr<MediaRawData> sample;
   do {
     sample = GetNextSample();
     if (!sample) {
-      return SeekPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
+      return SeekPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM,
+                                          __func__);
     }
     if (!sample->Size()) {
       // This sample can't be decoded, continue searching.
       continue;
     }
     if (sample->mKeyframe) {
       mQueuedSample = sample;
       seekTime = mQueuedSample->mTime;
     }
   } while (!mQueuedSample);
 
   SetNextKeyFrameTime();
 
-  return SeekPromise::CreateAndResolve(media::TimeUnit::FromMicroseconds(seekTime), __func__);
+  return SeekPromise::CreateAndResolve(
+    media::TimeUnit::FromMicroseconds(seekTime), __func__);
 }
 
 already_AddRefed<MediaRawData>
 MP4TrackDemuxer::GetNextSample()
 {
   RefPtr<MediaRawData> sample = mIterator->GetNext();
   if (!sample) {
     return nullptr;
@@ -329,30 +335,30 @@ MP4TrackDemuxer::GetNextSample()
       mp4_demuxer::H264::FrameType type =
         mp4_demuxer::H264::GetFrameType(sample);
       switch (type) {
         case mp4_demuxer::H264::FrameType::I_FRAME: MOZ_FALLTHROUGH;
         case mp4_demuxer::H264::FrameType::OTHER:
         {
           bool keyframe = type == mp4_demuxer::H264::FrameType::I_FRAME;
           if (sample->mKeyframe != keyframe) {
-            NS_WARNING(nsPrintfCString("Frame incorrectly marked as %skeyframe @ pts:%lld dur:%u dts:%lld",
-                                       keyframe ? "" : "non-",
-                                       sample->mTime,
-                                       sample->mDuration,
-                                       sample->mTimecode).get());
+            NS_WARNING(nsPrintfCString("Frame incorrectly marked as %skeyframe "
+                                       "@ pts:%lld dur:%u dts:%lld",
+                                       keyframe ? "" : "non-", sample->mTime,
+                                       sample->mDuration, sample->mTimecode)
+                         .get());
             sample->mKeyframe = keyframe;
           }
           break;
         }
         case mp4_demuxer::H264::FrameType::INVALID:
-          NS_WARNING(nsPrintfCString("Invalid H264 frame @ pts:%lld dur:%u dts:%lld",
-                                     sample->mTime,
-                                     sample->mDuration,
-                                     sample->mTimecode).get());
+          NS_WARNING(
+            nsPrintfCString("Invalid H264 frame @ pts:%lld dur:%u dts:%lld",
+                            sample->mTime, sample->mDuration, sample->mTimecode)
+              .get());
           // We could reject the sample now, however demuxer errors are fatal.
           // So we keep the invalid frame, relying on the H264 decoder to
           // handle the error later.
           // TODO: make demuxer errors non-fatal.
           break;
       }
     }
   }
@@ -372,17 +378,18 @@ MP4TrackDemuxer::GetNextSample()
 }
 
 RefPtr<MP4TrackDemuxer::SamplesPromise>
 MP4TrackDemuxer::GetSamples(int32_t aNumSamples)
 {
   EnsureUpToDateIndex();
   RefPtr<SamplesHolder> samples = new SamplesHolder;
   if (!aNumSamples) {
-    return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR, __func__);
+    return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_DEMUXER_ERR,
+                                           __func__);
   }
 
   if (mQueuedSample) {
     MOZ_ASSERT(mQueuedSample->mKeyframe,
                "mQueuedSample must be a keyframe");
     samples->mSamples.AppendElement(mQueuedSample);
     mQueuedSample = nullptr;
     aNumSamples--;
@@ -392,29 +399,31 @@ MP4TrackDemuxer::GetSamples(int32_t aNum
     if (!sample->Size()) {
       continue;
     }
     samples->mSamples.AppendElement(sample);
     aNumSamples--;
   }
 
   if (samples->mSamples.IsEmpty()) {
-    return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
+    return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM,
+                                           __func__);
   } else {
     for (const auto& sample : samples->mSamples) {
       // Collect telemetry from h264 Annex B SPS.
       if (mNeedSPSForTelemetry && mp4_demuxer::AnnexB::HasSPS(sample)) {
         RefPtr<MediaByteBuffer> extradata =
         mp4_demuxer::AnnexB::ExtractExtraData(sample);
         mNeedSPSForTelemetry = AccumulateSPSTelemetry(extradata);
       }
     }
 
-    if (mNextKeyframeTime.isNothing() ||
-        samples->mSamples.LastElement()->mTime >= mNextKeyframeTime.value().ToMicroseconds()) {
+    if (mNextKeyframeTime.isNothing()
+        || samples->mSamples.LastElement()->mTime
+           >= mNextKeyframeTime.value().ToMicroseconds()) {
       SetNextKeyFrameTime();
     }
     return SamplesPromise::CreateAndResolve(samples, __func__);
   }
 }
 
 void
 MP4TrackDemuxer::SetNextKeyFrameTime()
@@ -445,17 +454,18 @@ MP4TrackDemuxer::GetNextRandomAccessPoin
       media::TimeUnit::FromMicroseconds(std::numeric_limits<int64_t>::max());
   } else {
     *aTime = mNextKeyframeTime.value();
   }
   return NS_OK;
 }
 
 RefPtr<MP4TrackDemuxer::SkipAccessPointPromise>
-MP4TrackDemuxer::SkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreshold)
+MP4TrackDemuxer::SkipToNextRandomAccessPoint(
+  const media::TimeUnit& aTimeThreshold)
 {
   mQueuedSample = nullptr;
   // Loop until we reach the next keyframe after the threshold.
   uint32_t parsed = 0;
   bool found = false;
   RefPtr<MediaRawData> sample;
   while (!found && (sample = GetNextSample())) {
     parsed++;
--- a/dom/media/fmp4/MP4Demuxer.h
+++ b/dom/media/fmp4/MP4Demuxer.h
@@ -28,18 +28,18 @@ public:
   explicit MP4Demuxer(MediaResource* aResource);
 
   RefPtr<InitPromise> Init() override;
 
   bool HasTrackType(TrackInfo::TrackType aType) const override;
 
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
 
-  already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(TrackInfo::TrackType aType,
-                                                      uint32_t aTrackNumber) override;
+  already_AddRefed<MediaTrackDemuxer>
+  GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
 
   bool IsSeekable() const override;
 
   UniquePtr<EncryptionInfo> GetCrypto() override;
 
   void NotifyDataArrived() override;
 
   void NotifyDataRemoved() override;
--- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp
+++ b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp
@@ -105,39 +105,49 @@ WidevineVideoDecoder::Decode(GMPVideoEnc
   // may be some latency, i.e. we may need to input (say) 30 frames before
   // we receive output. So we need to store the durations of the frames input,
   // and retrieve them on output.
   mFrameDurations[aInputFrame->TimeStamp()] = aInputFrame->Duration();
 
   mSentInput = true;
   InputBuffer sample;
 
-  RefPtr<MediaRawData> raw(new MediaRawData(aInputFrame->Buffer(), aInputFrame->Size()));
+  RefPtr<MediaRawData> raw(
+    new MediaRawData(aInputFrame->Buffer(), aInputFrame->Size()));
+  if (!raw->Data()) {
+    // OOM.
+    mCallback->Error(GMPAllocErr);
+    return;
+  }
   raw->mExtraData = mExtraData;
   raw->mKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame);
   if (mCodecType == kGMPVideoCodecH264) {
     // Convert input from AVCC, which GMPAPI passes in, to AnnexB, which
     // Chromium uses internally.
     mp4_demuxer::AnnexB::ConvertSampleToAnnexB(raw);
   }
 
   const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData();
   nsTArray<SubsampleEntry> subsamples;
-  InitInputBuffer(crypto, aInputFrame->TimeStamp(), raw->Data(), raw->Size(), sample, subsamples);
+  InitInputBuffer(crypto, aInputFrame->TimeStamp(), raw->Data(), raw->Size(),
+                  sample, subsamples);
 
   // For keyframes, ConvertSampleToAnnexB will stick the AnnexB extra data
   // at the start of the input. So we need to account for that as clear data
   // in the subsamples.
-  if (raw->mKeyframe && !subsamples.IsEmpty() && mCodecType == kGMPVideoCodecH264) {
+  if (raw->mKeyframe
+      && !subsamples.IsEmpty()
+      && mCodecType == kGMPVideoCodecH264) {
     subsamples[0].clear_bytes += mAnnexB->Length();
   }
 
   WidevineVideoFrame frame;
   Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame);
-  Log("WidevineVideoDecoder::Decode(timestamp=%lld) rv=%d", sample.timestamp, rv);
+  Log("WidevineVideoDecoder::Decode(timestamp=%lld) rv=%d", sample.timestamp,
+      rv);
 
   // Destroy frame, so that the shmem is now free to be used to return
   // output to the Gecko process.
   aInputFrame->Destroy();
   aInputFrame = nullptr;
 
   if (rv == kSuccess) {
     if (!ReturnOutput(frame)) {
@@ -155,17 +165,18 @@ WidevineVideoDecoder::Decode(GMPVideoEnc
       mCallback->InputDataExhausted();
     }
   } else if (rv == kNeedMoreData) {
     MOZ_ASSERT(mCDMWrapper);
     mCallback->InputDataExhausted();
   } else {
     mCallback->Error(ToGMPErr(rv));
   }
-  // Finish a drain if pending and we have no pending ReturnOutput calls on the stack.
+  // Finish a drain if pending and we have no pending ReturnOutput calls on the
+  // stack.
   if (mDrainPending && mReturnOutputCallDepth == 0) {
     Drain();
   }
 }
 
 // Util class to assist with counting mReturnOutputCallDepth.
 class CounterHelper {
 public:
@@ -184,22 +195,20 @@ public:
 
 private:
   int32_t& mCounter;
 };
 
 // Util class to make sure GMP frames are freed. Holds a GMPVideoi420Frame*
 // and will destroy it when the helper is destroyed unless the held frame
 // if forgotten with ForgetFrame.
-class FrameDestroyerHelper {
+class FrameDestroyerHelper
+{
 public:
-  explicit FrameDestroyerHelper(GMPVideoi420Frame*& frame)
-    : frame(frame)
-  {
-  }
+  explicit FrameDestroyerHelper(GMPVideoi420Frame*& frame) : frame(frame) { }
 
   // RAII, destroy frame if held.
   ~FrameDestroyerHelper()
   {
     if (frame) {
       frame->Destroy();
     }
     frame = nullptr;
@@ -256,21 +265,23 @@ WidevineVideoDecoder::ReturnOutput(Widev
     // other IPC calls can happen during this call, resulting in calls
     // being made to the CDM. After this call state can have changed,
     // and should be reevaluated.
     err = gmpFrame->CreateEmptyFrame(size.width,
                                      size.height,
                                      yStride,
                                      uStride,
                                      vStride);
-    // Assert possible reentrant calls or resets haven't altered level unexpectedly.
+    // Assert possible reentrant calls or resets haven't altered level
+    // unexpectedly.
     MOZ_ASSERT(mReturnOutputCallDepth == 1);
     ENSURE_GMP_SUCCESS(err, false);
 
-    // If a reset started we need to dump the current frame and complete the reset.
+    // If a reset started we need to dump the current frame and complete the
+    // reset.
     if (mResetInProgress) {
       MOZ_ASSERT(mCDMWrapper);
       MOZ_ASSERT(mFrameAllocationQueue.empty());
       CompleteReset();
       return true;
     }
 
     err = gmpFrame->SetWidth(size.width);
--- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h
+++ b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h
@@ -15,17 +15,18 @@
 #include "nsTArray.h"
 #include "WidevineDecryptor.h"
 #include "WidevineVideoFrame.h"
 #include <map>
 #include <deque>
 
 namespace mozilla {
 
-class WidevineVideoDecoder : public GMPVideoDecoder {
+class WidevineVideoDecoder : public GMPVideoDecoder
+{
 public:
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineVideoDecoder)
 
   WidevineVideoDecoder(GMPVideoHost* aVideoHost,
                        RefPtr<CDMWrapper> aCDMWrapper);
   void InitDecode(const GMPVideoCodec& aCodecSettings,
                   const uint8_t* aCodecSpecific,
@@ -40,17 +41,18 @@ public:
   void Reset() override;
   void Drain() override;
   void DecodingComplete() override;
 
 private:
 
   ~WidevineVideoDecoder();
 
-  cdm::ContentDecryptionModule_8* CDM() const {
+  cdm::ContentDecryptionModule_8* CDM() const
+  {
     // CDM should only be accessed before 'DecodingComplete'.
     MOZ_ASSERT(mCDMWrapper);
     // CDMWrapper ensure the CDM is non-null, no need to check again.
     return mCDMWrapper->GetCDM();
   }
 
   bool ReturnOutput(WidevineVideoFrame& aFrame);
   void CompleteReset();
--- a/dom/media/ipc/VideoDecoderParent.cpp
+++ b/dom/media/ipc/VideoDecoderParent.cpp
@@ -72,17 +72,18 @@ VideoDecoderParent::VideoDecoderParent(V
 
   CreateDecoderParams params(aVideoInfo);
   params.mTaskQueue = mDecodeTaskQueue;
   params.mKnowsCompositor = mKnowsCompositor;
   params.mImageContainer = new layers::ImageContainer();
 
   mDecoder = pdm->CreateVideoDecoder(params);
 #else
-  MOZ_ASSERT(false, "Can't use RemoteVideoDecoder on non-Windows platforms yet");
+  MOZ_ASSERT(false,
+             "Can't use RemoteVideoDecoder on non-Windows platforms yet");
 #endif
 
   *aSuccess = !!mDecoder;
 }
 
 VideoDecoderParent::~VideoDecoderParent()
 {
   MOZ_COUNT_DTOR(VideoDecoderParent);
@@ -101,35 +102,42 @@ mozilla::ipc::IPCResult
 VideoDecoderParent::RecvInit()
 {
   MOZ_ASSERT(OnManagerThread());
   RefPtr<VideoDecoderParent> self = this;
   mDecoder->Init()->Then(mManagerTaskQueue, __func__,
     [self] (TrackInfo::TrackType aTrack) {
       if (self->mDecoder) {
         nsCString hardwareReason;
-        bool hardwareAccelerated = self->mDecoder->IsHardwareAccelerated(hardwareReason);
+        bool hardwareAccelerated =
+          self->mDecoder->IsHardwareAccelerated(hardwareReason);
         Unused << self->SendInitComplete(hardwareAccelerated, hardwareReason);
       }
     },
     [self] (MediaResult aReason) {
       if (!self->mDestroyed) {
         Unused << self->SendInitFailed(aReason);
       }
     });
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 VideoDecoderParent::RecvInput(const MediaRawDataIPDL& aData)
 {
   MOZ_ASSERT(OnManagerThread());
-  // XXX: This copies the data into a buffer owned by the MediaRawData. Ideally we'd just take ownership
-  // of the shmem.
-  RefPtr<MediaRawData> data = new MediaRawData(aData.buffer().get<uint8_t>(), aData.buffer().Size<uint8_t>());
+  // XXX: This copies the data into a buffer owned by the MediaRawData. Ideally
+  // we'd just take ownership of the shmem.
+  RefPtr<MediaRawData> data = new MediaRawData(aData.buffer().get<uint8_t>(),
+                                               aData.buffer().Size<uint8_t>());
+  if (!data->Data()) {
+    // OOM
+    Error(NS_ERROR_OUT_OF_MEMORY);
+    return IPC_OK();
+  }
   data->mOffset = aData.base().offset();
   data->mTime = aData.base().time();
   data->mTimecode = aData.base().timecode();
   data->mDuration = aData.base().duration();
   data->mKeyframe = aData.base().keyframe();
 
   DeallocShmem(aData.buffer());
 
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -264,18 +264,18 @@ MediaSourceDecoder::GetDuration()
   return ExplicitDuration();
 }
 
 MediaDecoderOwner::NextFrameStatus
 MediaSourceDecoder::NextFrameBufferedStatus()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
-  if (!mMediaSource ||
-      mMediaSource->ReadyState() == dom::MediaSourceReadyState::Closed) {
+  if (!mMediaSource
+      || mMediaSource->ReadyState() == dom::MediaSourceReadyState::Closed) {
     return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
   }
 
   // Next frame hasn't been decoded yet.
   // Use the buffered range to consider if we have the next frame available.
   TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
   TimeIntervals buffered = GetBuffered();
   buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
@@ -299,17 +299,18 @@ MediaSourceDecoder::CanPlayThrough()
 
   if (IsNaN(mMediaSource->Duration())) {
     // Don't have any data yet.
     return false;
   }
   TimeUnit duration = TimeUnit::FromSeconds(mMediaSource->Duration());
   TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
   if (duration.IsInfinite()) {
-    // We can't make an informed decision and just assume that it's a live stream
+    // We can't make an informed decision and just assume that it's a live
+    // stream
     return true;
   } else if (duration <= currentPosition) {
     return true;
   }
   // If we have data up to the mediasource's duration or 30s ahead, we can
   // assume that we can play without interruption.
   TimeIntervals buffered = GetBuffered();
   buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -30,18 +30,18 @@ public:
   explicit MediaSourceDemuxer(AbstractThread* aAbstractMainThread);
 
   RefPtr<InitPromise> Init() override;
 
   bool HasTrackType(TrackInfo::TrackType aType) const override;
 
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
 
-  already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(TrackInfo::TrackType aType,
-                                                              uint32_t aTrackNumber) override;
+  already_AddRefed<MediaTrackDemuxer>
+  GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
 
   bool IsSeekable() const override;
 
   UniquePtr<EncryptionInfo> GetCrypto() override;
 
   bool ShouldComputeStartTime() const override { return false; }
 
   void NotifyDataArrived() override;
@@ -100,31 +100,33 @@ public:
   RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
 
   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
 
   void Reset() override;
 
   nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
 
-  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreshold) override;
+  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
+    const media::TimeUnit& aTimeThreshold) override;
 
   media::TimeIntervals GetBuffered() override;
 
   void BreakCycles() override;
 
   bool GetSamplesMayBlock() const override
   {
     return false;
   }
 
 private:
   RefPtr<SeekPromise> DoSeek(const media::TimeUnit& aTime);
   RefPtr<SamplesPromise> DoGetSamples(int32_t aNumSamples);
-  RefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreadshold);
+  RefPtr<SkipAccessPointPromise> DoSkipToNextRandomAccessPoint(
+    const media::TimeUnit& aTimeThreadshold);
   already_AddRefed<MediaRawData> GetSample(MediaResult& aError);
   // Return the timestamp of the next keyframe after mLastSampleIndex.
   media::TimeUnit GetNextRandomAccessPoint();
 
   RefPtr<MediaSourceDemuxer> mParent;
   RefPtr<TrackBuffersManager> mManager;
   TrackInfo::TrackType mType;
   // Monitor protecting members below accessed from multiple threads.
--- a/dom/media/ogg/OggCodecState.cpp
+++ b/dom/media/ogg/OggCodecState.cpp
@@ -3,27 +3,26 @@
 /* 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 <string.h>
 
 #include "mozilla/EndianUtils.h"
 #include <stdint.h>
+#include <algorithm>
+#include <opus/opus.h>
 
-#include "nsDebug.h"
 #include "OggCodecState.h"
 #include "OpusDecoder.h"
 #include "OpusParser.h"
 #include "VideoUtils.h"
-#include <algorithm>
-
-#include <opus/opus.h>
+#include "XiphExtradata.h"
+#include "nsDebug.h"
 #include "opus/opus_multistream.h"
-#include "XiphExtradata.h"
 
 // On Android JellyBean, the hardware.h header redefines version_major and
 // version_minor, which breaks our build.  See:
 // https://bugzilla.mozilla.org/show_bug.cgi?id=912702#c6
 #ifdef MOZ_WIDGET_GONK
 #ifdef version_major
 #undef version_major
 #endif
@@ -200,18 +199,19 @@ Clone(ogg_packet* aPacket)
   p->packet = new unsigned char[p->bytes];
   memcpy(p->packet, aPacket->packet, p->bytes);
   return p;
 }
 
 void
 OggCodecState::ReleasePacket(ogg_packet* aPacket)
 {
-  if (aPacket)
+  if (aPacket) {
     delete [] aPacket->packet;
+  }
   delete aPacket;
 }
 
 void
 OggPacketQueue::Append(ogg_packet* aPacket)
 {
   nsDeque::Push(aPacket);
 }
@@ -236,33 +236,40 @@ OggCodecState::PacketPeek()
 {
   if (mPackets.IsEmpty()) {
     return nullptr;
   }
   return mPackets.PeekFront();
 }
 
 void
-OggCodecState::PushFront(OggPacketQueue &&aOther)
+OggCodecState::PushFront(OggPacketQueue&& aOther)
 {
   while (!aOther.IsEmpty()) {
     mPackets.PushFront(aOther.Pop());
   }
 }
 
 already_AddRefed<MediaRawData>
 OggCodecState::PacketOutAsMediaRawData()
 {
   ogg_packet* packet = PacketOut();
   if (!packet) {
     return nullptr;
   }
 
-  NS_ASSERTION(!IsHeader(packet), "PacketOutAsMediaRawData can only be called on non-header packets");
+  NS_ASSERTION(
+    !IsHeader(packet),
+    "PacketOutAsMediaRawData can only be called on non-header packets");
   RefPtr<MediaRawData> sample = new MediaRawData(packet->packet, packet->bytes);
+  if (!sample->Data()) {
+    // OOM.
+    ReleasePacket(packet);
+    return nullptr;
+  }
 
   int64_t end_tstamp = Time(packet->granulepos);
   NS_ASSERTION(end_tstamp >= 0, "timestamp invalid");
 
   int64_t duration = PacketDuration(packet);
   NS_ASSERTION(duration >= 0, "duration invalid");
 
   sample->mTimecode = packet->granulepos;
@@ -364,17 +371,18 @@ TheoraState::Init()
   int64_t d = mTheoraInfo.aspect_denominator;
 
   float aspectRatio =
     (n == 0 || d == 0) ? 1.0f : static_cast<float>(n) / static_cast<float>(d);
 
   // Ensure the frame and picture regions aren't larger than our prescribed
   // maximum, or zero sized.
   nsIntSize frame(mTheoraInfo.frame_width, mTheoraInfo.frame_height);
-  nsIntRect picture(mTheoraInfo.pic_x, mTheoraInfo.pic_y, mTheoraInfo.pic_width, mTheoraInfo.pic_height);
+  nsIntRect picture(mTheoraInfo.pic_x, mTheoraInfo.pic_y,
+                    mTheoraInfo.pic_width, mTheoraInfo.pic_height);
   nsIntSize display(mTheoraInfo.pic_width, mTheoraInfo.pic_height);
   ScaleDisplayByAspectRatio(display, aspectRatio);
   if (!IsValidVideoRegion(frame, picture, display)) {
     return mActive = false;
   }
 
   mCtx = th_decode_alloc(&mTheoraInfo, mSetup);
   if (!mCtx) {
@@ -445,19 +453,19 @@ TheoraState::Time(int64_t granulepos)
 
 bool
 TheoraState::IsHeader(ogg_packet* aPacket)
 {
   return th_packet_isheader(aPacket);
 }
 
 # define TH_VERSION_CHECK(_info,_maj,_min,_sub) \
- (((_info)->version_major>(_maj)||(_info)->version_major==(_maj))&& \
- (((_info)->version_minor>(_min)||(_info)->version_minor==(_min))&& \
- (_info)->version_subminor>=(_sub)))
+ (((_info)->version_major>(_maj)||(_info)->version_major==(_maj)) \
+  && (((_info)->version_minor>(_min)||(_info)->version_minor==(_min)) \
+  && (_info)->version_subminor>=(_sub)))
 
 int64_t
 TheoraState::Time(th_info* aInfo, int64_t aGranulepos)
 {
   if (aGranulepos < 0 || aInfo->fps_numerator == 0) {
     return -1;
   }
   // Implementation of th_granule_frame inlined here to operate
@@ -563,19 +571,19 @@ TheoraState::PageIn(ogg_page* aPage)
 // version (maj,min,sub) or later, otherwise returns 0.
 int
 TheoraVersion(th_info* info,
               unsigned char maj,
               unsigned char min,
               unsigned char sub)
 {
   ogg_uint32_t ver = (maj << 16) + (min << 8) + sub;
-  ogg_uint32_t th_ver = (info->version_major << 16) +
-                        (info->version_minor << 8) +
-                        info->version_subminor;
+  ogg_uint32_t th_ver = (info->version_major << 16)
+                        + (info->version_minor << 8)
+                        + info->version_subminor;
   return (th_ver >= ver) ? 1 : 0;
 }
 
 void
 TheoraState::ReconstructTheoraGranulepos()
 {
   if (mUnstamped.Length() == 0) {
     return;
@@ -584,18 +592,18 @@ TheoraState::ReconstructTheoraGranulepos
   NS_ASSERTION(lastGranulepos != -1, "Must know last granulepos");
 
   // Reconstruct the granulepos (and thus timestamps) of the decoded
   // frames. Granulepos are stored as ((keyframe<<shift)+offset). We
   // know the granulepos of the last frame in the list, so we can infer
   // the granulepos of the intermediate frames using their frame numbers.
   ogg_int64_t shift = mTheoraInfo.keyframe_granule_shift;
   ogg_int64_t version_3_2_1 = TheoraVersion(&mTheoraInfo,3,2,1);
-  ogg_int64_t lastFrame = th_granule_frame(mCtx,
-                                           lastGranulepos) + version_3_2_1;
+  ogg_int64_t lastFrame =
+    th_granule_frame(mCtx, lastGranulepos) + version_3_2_1;
   ogg_int64_t firstFrame = lastFrame - mUnstamped.Length() + 1;
 
   // Until we encounter a keyframe, we'll assume that the "keyframe"
   // segment of the granulepos is the first frame, or if that causes
   // the "offset" segment to overflow, we assume the required
   // keyframe is maximumally offset. Until we encounter a keyframe
   // the granulepos will probably be wrong, but we can't decode the
   // frame anyway (since we don't have its keyframe) so it doesn't really
@@ -610,52 +618,56 @@ TheoraState::ReconstructTheoraGranulepos
     ogg_int64_t frame = firstFrame + i;
     ogg_int64_t granulepos;
     ogg_packet* packet = mUnstamped[i];
     bool isKeyframe = th_packet_iskeyframe(packet) == 1;
 
     if (isKeyframe) {
       granulepos = frame << shift;
       keyframe = frame;
-    } else if (frame >= keyframe &&
-                frame - keyframe < ((ogg_int64_t)1 << shift))
+    } else if (frame >= keyframe
+               && frame - keyframe < ((ogg_int64_t)1 << shift))
     {
       // (frame - keyframe) won't overflow the "offset" segment of the
       // granulepos, so it's safe to calculate the granulepos.
       granulepos = (keyframe << shift) + (frame - keyframe);
     } else {
       // (frame - keyframeno) will overflow the "offset" segment of the
       // granulepos, so we take "keyframe" to be the max possible offset
       // frame instead.
-      ogg_int64_t k = std::max(frame - (((ogg_int64_t)1 << shift) - 1), version_3_2_1);
+      ogg_int64_t k =
+        std::max(frame - (((ogg_int64_t)1 << shift) - 1), version_3_2_1);
       granulepos = (k << shift) + (frame - k);
     }
     // Theora 3.2.1+ granulepos store frame number [1..N], so granulepos
     // should be > 0.
     // Theora 3.2.0 granulepos store the frame index [0..(N-1)], so
     // granulepos should be >= 0.
     NS_ASSERTION(granulepos >= version_3_2_1,
                   "Invalid granulepos for Theora version");
 
     // Check that the frame's granule number is one more than the
     // previous frame's.
-    NS_ASSERTION(i == 0 ||
-                 th_granule_frame(mCtx, granulepos) ==
-                 th_granule_frame(mCtx, mUnstamped[i-1]->granulepos) + 1,
+    NS_ASSERTION(i == 0
+                 || th_granule_frame(mCtx, granulepos)
+                    == th_granule_frame(mCtx, mUnstamped[i-1]->granulepos)
+                       + 1,
                  "Granulepos calculation is incorrect!");
 
     packet->granulepos = granulepos;
   }
 
   // Check that the second to last frame's granule number is one less than
   // the last frame's (the known granule number). If not our granulepos
   // recovery missed a beat.
-  NS_ASSERTION(mUnstamped.Length() < 2 ||
-    th_granule_frame(mCtx, mUnstamped[mUnstamped.Length()-2]->granulepos) + 1 ==
-    th_granule_frame(mCtx, lastGranulepos),
+  NS_ASSERTION(
+    mUnstamped.Length() < 2
+    || th_granule_frame(mCtx, mUnstamped[mUnstamped.Length() - 2]->granulepos)
+       + 1
+       == th_granule_frame(mCtx, lastGranulepos),
     "Granulepos recovery should catch up with packet->granulepos!");
 }
 
 nsresult
 VorbisState::Reset()
 {
   nsresult res = NS_OK;
   if (mActive && vorbis_synthesis_restart(&mDsp) != 0) {
@@ -950,18 +962,19 @@ VorbisState::ReconstructVorbisGranulepos
 
   ogg_packet* first = mUnstamped[0];
   long blockSize = vorbis_packet_blocksize(&mVorbisInfo, first);
   if (blockSize < 0) {
     mPrevVorbisBlockSize = 0;
     blockSize = 0;
   }
 
-  long samples = (mPrevVorbisBlockSize == 0) ? 0 :
-                  mPrevVorbisBlockSize / 4 + blockSize / 4;
+  long samples = (mPrevVorbisBlockSize == 0)
+                 ? 0
+                 : mPrevVorbisBlockSize / 4 + blockSize / 4;
   int64_t start = first->granulepos - samples;
   RecordVorbisPacketSamples(first, samples);
 
   if (last->e_o_s && start < mGranulepos) {
     // We've calculated that there are more samples in this page than its
     // granulepos claims, and it's the last page in the stream. This is legal,
     // and we will need to prune the trailing samples when we come to decode it.
     // We must correct the timestamps so that they follow the last Vorbis page's
@@ -1104,17 +1117,18 @@ OpusState::DecodeHeader(ogg_packet* aPac
 /* Construct and return a tags hashmap from our internal array */
 MetadataTags*
 OpusState::GetTags()
 {
   MetadataTags* tags;
 
   tags = new MetadataTags;
   for (uint32_t i = 0; i < mParser->mTags.Length(); i++) {
-    AddVorbisComment(tags, mParser->mTags[i].Data(), mParser->mTags[i].Length());
+    AddVorbisComment(tags, mParser->mTags[i].Data(),
+                     mParser->mTags[i].Length());
   }
 
   return tags;
 }
 
 /* Return the timestamp (in microseconds) equivalent to a granulepos. */
 int64_t
 OpusState::Time(int64_t aGranulepos)
@@ -1136,19 +1150,19 @@ OpusState::Time(int aPreSkip, int64_t aG
   // Ogg Opus always runs at a granule rate of 48 kHz.
   CheckedInt64 t = SaferMultDiv(aGranulepos - aPreSkip, USECS_PER_S, 48000);
   return t.isValid() ? t.value() : -1;
 }
 
 bool
 OpusState::IsHeader(ogg_packet* aPacket)
 {
-  return aPacket->bytes >= 16 &&
-         (!memcmp(aPacket->packet, "OpusHead", 8) ||
-          !memcmp(aPacket->packet, "OpusTags", 8));
+  return aPacket->bytes >= 16
+         && (!memcmp(aPacket->packet, "OpusHead", 8)
+             || !memcmp(aPacket->packet, "OpusTags", 8));
 }
 
 nsresult
 OpusState::PageIn(ogg_page* aPage)
 {
   if (!mActive) {
     return NS_OK;
   }
@@ -1300,16 +1314,19 @@ OpusState::PacketOutAsMediaRawData()
   uint32_t frames = 0;
   const int64_t endFrame = packet->granulepos;
 
   if (packet->e_o_s) {
     frames = GetOpusDeltaGP(packet);
   }
 
   RefPtr<MediaRawData> data = OggCodecState::PacketOutAsMediaRawData();
+  if (!data) {
+    return nullptr;
+  }
 
   if (data->mEOS && mPrevPacketGranulepos != -1) {
     // If this is the last packet, perform end trimming.
     int64_t startFrame = mPrevPacketGranulepos;
     frames -= std::max<int64_t>(
       0, std::min(endFrame - startFrame, static_cast<int64_t>(frames)));
     data->mDiscardPadding = frames;
   }
@@ -1419,17 +1436,17 @@ FlacState::ReconstructFlacGranulepos(voi
   int64_t gp;
 
   gp = last->granulepos;
   // Loop through the packets backwards, subtracting the next
   // packet's duration from its granulepos to get the value
   // for the current packet.
   for (uint32_t i = mUnstamped.Length() - 1; i > 0; i--) {
     int offset =
-        mParser.BlockDuration(mUnstamped[i]->packet, mUnstamped[i]->bytes);
+      mParser.BlockDuration(mUnstamped[i]->packet, mUnstamped[i]->bytes);
     // Check for error (negative offset) and overflow.
     if (offset >= 0) {
       if (offset <= gp) {
         gp -= offset;
       } else {
         // If the granule position of the first data page is smaller than the
         // number of decodable audio samples on that page, then we MUST reject
         // the stream.
@@ -1503,51 +1520,51 @@ static const size_t INDEX_KEYPOINT_OFFSE
 static const size_t FISBONE_MSG_FIELDS_OFFSET = 8;
 static const size_t FISBONE_SERIALNO_OFFSET = 12;
 
 static bool
 IsSkeletonBOS(ogg_packet* aPacket)
 {
   static_assert(SKELETON_MIN_HEADER_LEN >= 8,
                 "Minimum length of skeleton BOS header incorrect");
-  return aPacket->bytes >= SKELETON_MIN_HEADER_LEN &&
-         memcmp(reinterpret_cast<char*>(aPacket->packet), "fishead", 8) == 0;
+  return aPacket->bytes >= SKELETON_MIN_HEADER_LEN
+         && memcmp(reinterpret_cast<char*>(aPacket->packet), "fishead", 8) == 0;
 }
 
 static bool
 IsSkeletonIndex(ogg_packet* aPacket)
 {
   static_assert(SKELETON_4_0_MIN_INDEX_LEN >= 5,
                 "Minimum length of skeleton index header incorrect");
-  return aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN &&
-         memcmp(reinterpret_cast<char*>(aPacket->packet), "index", 5) == 0;
+  return aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN
+         && memcmp(reinterpret_cast<char*>(aPacket->packet), "index", 5) == 0;
 }
 
 static bool
 IsSkeletonFisbone(ogg_packet* aPacket)
 {
   static_assert(SKELETON_MIN_FISBONE_LEN >= 8,
                 "Minimum length of skeleton fisbone header incorrect");
-  return aPacket->bytes >= SKELETON_MIN_FISBONE_LEN &&
-         memcmp(reinterpret_cast<char*>(aPacket->packet), "fisbone", 8) == 0;
+  return aPacket->bytes >= SKELETON_MIN_FISBONE_LEN
+         && memcmp(reinterpret_cast<char*>(aPacket->packet), "fisbone", 8) == 0;
 }
 
 // Reads a variable length encoded integer at p. Will not read
 // past aLimit. Returns pointer to character after end of integer.
 static const unsigned char*
 ReadVariableLengthInt(const unsigned char* p,
                       const unsigned char* aLimit,
                       int64_t& n)
 {
   int shift = 0;
   int64_t byte = 0;
   n = 0;
-  while (p < aLimit &&
-         (byte & 0x80) != 0x80 &&
-         shift < 57)
+  while (p < aLimit
+         && (byte & 0x80) != 0x80
+         && shift < 57)
   {
     byte = static_cast<int64_t>(*p);
     n |= ((byte & 0x7f) << shift);
     shift += 7;
     p++;
   }
   return p;
 }
@@ -1556,23 +1573,26 @@ bool
 SkeletonState::DecodeIndex(ogg_packet* aPacket)
 {
   NS_ASSERTION(aPacket->bytes >= SKELETON_4_0_MIN_INDEX_LEN,
                "Index must be at least minimum size");
   if (!mActive) {
     return false;
   }
 
-  uint32_t serialno = LittleEndian::readUint32(aPacket->packet + INDEX_SERIALNO_OFFSET);
-  int64_t numKeyPoints = LittleEndian::readInt64(aPacket->packet + INDEX_NUM_KEYPOINTS_OFFSET);
+  uint32_t serialno =
+    LittleEndian::readUint32(aPacket->packet + INDEX_SERIALNO_OFFSET);
+  int64_t numKeyPoints =
+    LittleEndian::readInt64(aPacket->packet + INDEX_NUM_KEYPOINTS_OFFSET);
 
   int64_t endTime = 0, startTime = 0;
   const unsigned char* p = aPacket->packet;
 
-  int64_t timeDenom = LittleEndian::readInt64(aPacket->packet + INDEX_TIME_DENOM_OFFSET);
+  int64_t timeDenom =
+    LittleEndian::readInt64(aPacket->packet + INDEX_TIME_DENOM_OFFSET);
   if (timeDenom == 0) {
     LOG(LogLevel::Debug, ("Ogg Skeleton Index packet for stream %u has 0 "
                        "timestamp denominator.", serialno));
     return (mActive = false);
   }
 
   // Extract the start time.
   int64_t timeRawInt = LittleEndian::readInt64(p + INDEX_FIRST_NUMER_OFFSET);
@@ -1598,19 +1618,19 @@ SkeletonState::DecodeIndex(ogg_packet* a
     (CheckedInt64(numKeyPoints) * MIN_KEY_POINT_SIZE) + INDEX_KEYPOINT_OFFSET;
   if (!minPacketSize.isValid())
   {
     return (mActive = false);
   }
 
   int64_t sizeofIndex = aPacket->bytes - INDEX_KEYPOINT_OFFSET;
   int64_t maxNumKeyPoints = sizeofIndex / MIN_KEY_POINT_SIZE;
-  if (aPacket->bytes < minPacketSize.value() ||
-      numKeyPoints > maxNumKeyPoints ||
-      numKeyPoints < 0) {
+  if (aPacket->bytes < minPacketSize.value()
+      || numKeyPoints > maxNumKeyPoints
+      || numKeyPoints < 0) {
     // Packet size is less than the theoretical minimum size, or the packet is
     // claiming to store more keypoints than it's capable of storing. This means
     // that the numKeyPoints field is too large or small for the packet to
     // possibly contain as many packets as it claims to, so the numKeyPoints
     // field is possibly malicious. Don't try decoding this index, we may run
     // out of memory.
     LOG(LogLevel::Debug, ("Possibly malicious number of key points reported "
                        "(%lld) in index packet for stream %u.",
@@ -1625,27 +1645,27 @@ SkeletonState::DecodeIndex(ogg_packet* a
   const unsigned char* limit = aPacket->packet + aPacket->bytes;
   int64_t numKeyPointsRead = 0;
   CheckedInt64 offset = 0;
   CheckedInt64 time = 0;
   while (p < limit && numKeyPointsRead < numKeyPoints) {
     int64_t delta = 0;
     p = ReadVariableLengthInt(p, limit, delta);
     offset += delta;
-    if (p == limit ||
-        !offset.isValid() ||
-        offset.value() > mLength ||
-        offset.value() < 0) {
+    if (p == limit
+        || !offset.isValid()
+        || offset.value() > mLength
+        || offset.value() < 0) {
       return (mActive = false);
     }
     p = ReadVariableLengthInt(p, limit, delta);
     time += delta;
-    if (!time.isValid() ||
-        time.value() > endTime ||
-        time.value() < startTime) {
+    if (!time.isValid()
+        || time.value() > endTime
+        || time.value() < startTime) {
       return (mActive = false);
     }
     CheckedInt64 timeUsecs = SaferMultDiv(time.value(), USECS_PER_S, timeDenom);
     if (!timeUsecs.isValid()) {
       return (mActive = false);
     }
     keyPoints->Add(offset.value(), timeUsecs.value());
     numKeyPointsRead++;
@@ -1664,18 +1684,20 @@ SkeletonState::DecodeIndex(ogg_packet* a
 nsresult
 SkeletonState::IndexedSeekTargetForTrack(uint32_t aSerialno,
                                          int64_t aTarget,
                                          nsKeyPoint& aResult)
 {
   nsKeyFrameIndex* index = nullptr;
   mIndex.Get(aSerialno, &index);
 
-  if (!index || index->Length() == 0 ||
-      aTarget < index->mStartTime || aTarget > index->mEndTime) {
+  if (!index
+      || index->Length() == 0
+      || aTarget < index->mStartTime
+      || aTarget > index->mEndTime) {
     return NS_ERROR_FAILURE;
   }
 
   // Binary search to find the last key point with time less than target.
   int start = 0;
   int end = index->Length() - 1;
   while (end > start) {
     int mid = start + ((end - start + 1) >> 1);
@@ -1704,18 +1726,18 @@ SkeletonState::IndexedSeekTarget(int64_t
   }
   // Loop over all requested tracks' indexes, and get the keypoint for that
   // seek target. Record the keypoint with the lowest offset, this will be
   // our seek result. User must seek to the one with lowest offset to ensure we
   // pass "keyframes" on all tracks when we decode forwards to the seek target.
   nsSeekTarget r;
   for (uint32_t i=0; i<aTracks.Length(); i++) {
     nsKeyPoint k;
-    if (NS_SUCCEEDED(IndexedSeekTargetForTrack(aTracks[i], aTarget, k)) &&
-        k.mOffset < r.mKeyPoint.mOffset) {
+    if (NS_SUCCEEDED(IndexedSeekTargetForTrack(aTracks[i], aTarget, k))
+        && k.mOffset < r.mKeyPoint.mOffset) {
       r.mKeyPoint = k;
       r.mSerial = aTracks[i];
     }
   }
   if (r.IsNull()) {
     return NS_ERROR_FAILURE;
   }
   LOG(LogLevel::Debug, ("Indexed seek target for time %lld is offset %lld",
@@ -1723,20 +1745,20 @@ SkeletonState::IndexedSeekTarget(int64_t
   aResult = r;
   return NS_OK;
 }
 
 nsresult
 SkeletonState::GetDuration(const nsTArray<uint32_t>& aTracks,
                            int64_t& aDuration)
 {
-  if (!mActive ||
-      mVersion < SKELETON_VERSION(4,0) ||
-      !HasIndex() ||
-      aTracks.Length() == 0) {
+  if (!mActive
+      || mVersion < SKELETON_VERSION(4,0)
+      || !HasIndex()
+      || aTracks.Length() == 0) {
     return NS_ERROR_FAILURE;
   }
   int64_t endTime = INT64_MIN;
   int64_t startTime = INT64_MAX;
   for (uint32_t i=0; i<aTracks.Length(); i++) {
     nsKeyFrameIndex* index = nullptr;
     mIndex.Get(aTracks[i], &index);
     if (!index) {
@@ -1808,20 +1830,21 @@ SkeletonState::DecodeFisbone(ogg_packet*
           if (i != 0 && !isContentTypeParsed) {
             return false;
           }
 
           if ((i == 0 && IsASCII(strMsg)) || (i != 0 && IsUTF8(strMsg))) {
             EMsgHeaderType eHeaderType = kFieldTypeMaps[i].mMsgHeaderType;
             if (!field->mValuesStore.Contains(eHeaderType)) {
               uint32_t nameLen = strlen(kFieldTypeMaps[i].mPatternToRecognize);
-              field->mValuesStore.Put(eHeaderType, new nsCString(msgHead+nameLen,
-                                                                 msgProbe-msgHead-nameLen));
+              field->mValuesStore.Put(
+                eHeaderType,
+                new nsCString(msgHead + nameLen, msgProbe - msgHead - nameLen));
             }
-            isContentTypeParsed = i==0 ? true : isContentTypeParsed;
+            isContentTypeParsed = i == 0 ? true : isContentTypeParsed;
           }
           break;
         }
       }
       msgProbe += 2;
       msgLength -= 2;
       msgHead = msgProbe;
       continue;
@@ -1846,28 +1869,29 @@ SkeletonState::DecodeHeader(ogg_packet* 
   if (IsSkeletonBOS(aPacket)) {
     uint16_t verMajor =
       LittleEndian::readUint16(aPacket->packet + SKELETON_VERSION_MAJOR_OFFSET);
     uint16_t verMinor =
       LittleEndian::readUint16(aPacket->packet + SKELETON_VERSION_MINOR_OFFSET);
 
     // Read the presentation time. We read this before the version check as the
     // presentation time exists in all versions.
-    int64_t n =
-      LittleEndian::readInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
-    int64_t d =
-      LittleEndian::readInt64(aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
+    int64_t n = LittleEndian::readInt64(
+      aPacket->packet + SKELETON_PRESENTATION_TIME_NUMERATOR_OFFSET);
+    int64_t d = LittleEndian::readInt64(
+      aPacket->packet + SKELETON_PRESENTATION_TIME_DENOMINATOR_OFFSET);
     mPresentationTime =
-      d == 0 ? 0 : (static_cast<float>(n) / static_cast<float>(d)) * USECS_PER_S;
+      d == 0 ? 0
+             : (static_cast<float>(n) / static_cast<float>(d)) * USECS_PER_S;
 
     mVersion = SKELETON_VERSION(verMajor, verMinor);
     // We can only care to parse Skeleton version 4.0+.
-    if (mVersion < SKELETON_VERSION(4,0) ||
-        mVersion >= SKELETON_VERSION(5,0) ||
-        aPacket->bytes < SKELETON_4_0_MIN_HEADER_LEN) {
+    if (mVersion < SKELETON_VERSION(4,0)
+        || mVersion >= SKELETON_VERSION(5,0)
+        || aPacket->bytes < SKELETON_4_0_MIN_HEADER_LEN) {
       return false;
     }
 
     // Extract the segment length.
     mLength =
       LittleEndian::readInt64(aPacket->packet + SKELETON_FILE_LENGTH_OFFSET);
 
     LOG(LogLevel::Debug, ("Skeleton segment length: %lld", mLength));
--- a/dom/media/ogg/OggCodecState.h
+++ b/dom/media/ogg/OggCodecState.h
@@ -3,23 +3,23 @@
 /* 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/. */
 #if !defined(OggCodecState_h_)
 #define OggCodecState_h_
 
 #include <ogg/ogg.h>
 // For MOZ_SAMPLE_TYPE_*
+#include "FlacFrameParser.h"
+#include "VideoUtils.h"
 #include <nsAutoPtr.h>
 #include <nsAutoRef.h>
 #include <nsDeque.h>
 #include <nsTArray.h>
 #include <nsClassHashtable.h>
-#include "VideoUtils.h"
-#include "FlacFrameParser.h"
 
 #include <theora/theoradec.h>
 #ifdef MOZ_TREMOR
 #include <tremor/ivorbiscodec.h>
 #else
 #include <vorbis/codec.h>
 #endif
 
@@ -56,22 +56,28 @@ class OggPacketDeallocator : public nsDe
 // new 4KB page to the bitstream, which kills performance on Windows. This
 // also gives us the option to timestamp packets rather than decoded
 // frames/samples, reducing the amount of frames/samples we must decode to
 // determine start-time at a particular offset, and gives us finer control
 // over memory usage.
 class OggPacketQueue : private nsDeque
 {
 public:
-  OggPacketQueue() : nsDeque(new OggPacketDeallocator()) {}
+  OggPacketQueue() : nsDeque(new OggPacketDeallocator()) { }
   ~OggPacketQueue() { Erase(); }
   bool IsEmpty() { return nsDeque::GetSize() == 0; }
   void Append(ogg_packet* aPacket);
-  ogg_packet* PopFront() { return static_cast<ogg_packet*>(nsDeque::PopFront()); }
-  ogg_packet* PeekFront() { return static_cast<ogg_packet*>(nsDeque::PeekFront()); }
+  ogg_packet* PopFront()
+  {
+    return static_cast<ogg_packet*>(nsDeque::PopFront());
+  }
+  ogg_packet* PeekFront()
+  {
+    return static_cast<ogg_packet*>(nsDeque::PeekFront());
+  }
   ogg_packet* Pop() { return static_cast<ogg_packet*>(nsDeque::Pop()); }
   ogg_packet* operator[](size_t aIndex) const
   {
     return static_cast<ogg_packet*>(nsDeque::ObjectAt(aIndex));
   }
   size_t Length() const { return nsDeque::GetSize(); }
   void PushFront(ogg_packet* aPacket) { nsDeque::PushFront(aPacket); }
   void Erase() { nsDeque::Erase(); }
@@ -268,17 +274,18 @@ protected:
   // can be pushed over to mPackets. Used by PageIn() implementations in
   // subclasses.
   nsresult PacketOutUntilGranulepos(bool& aFoundGranulepos);
 
   // Temporary buffer in which to store packets while we're reading packets
   // in order to capture granulepos.
   nsTArray<ogg_packet*> mUnstamped;
 
-  bool SetCodecSpecificConfig(MediaByteBuffer* aBuffer, OggPacketQueue& aHeaders);
+  bool SetCodecSpecificConfig(MediaByteBuffer* aBuffer,
+                              OggPacketQueue& aHeaders);
 
 private:
   bool InternalInit();
 };
 
 class VorbisState : public OggCodecState
 {
 public:
@@ -392,17 +399,16 @@ private:
   OggPacketQueue mHeaders;
 
   // Reconstructs the granulepos of Theora packets stored in the
   // mUnstamped array. mUnstamped must be filled with consecutive packets from
   // the stream, with the last packet having a known granulepos. Using this
   // known granulepos, and the known frame numbers, we recover the granulepos
   // of all frames in the array. This enables us to determine their timestamps.
   void ReconstructTheoraGranulepos();
-
 };
 
 class OpusState : public OggCodecState
 {
 public:
   explicit OpusState(ogg_page* aBosPage);
   virtual ~OpusState();
 
@@ -446,17 +452,18 @@ private:
   AudioInfo mInfo;
   OggPacketQueue mHeaders;
 };
 
 // Constructs a 32bit version number out of two 16 bit major,minor
 // version numbers.
 #define SKELETON_VERSION(major, minor) (((major)<<16)|(minor))
 
-enum EMsgHeaderType {
+enum EMsgHeaderType
+{
   eContentType,
   eRole,
   eName,
   eLanguage,
   eTitle,
   eDisplayHint,
   eAltitude,
   eTrackOrder,
@@ -517,17 +524,17 @@ public:
     }
   };
 
   // Stores a keyframe's byte-offset, presentation time and the serialno
   // of the stream it belongs to.
   class nsSeekTarget
   {
   public:
-    nsSeekTarget() : mSerial(0) {}
+    nsSeekTarget() : mSerial(0) { }
     nsKeyPoint mKeyPoint;
     uint32_t mSerial;
     bool IsNull()
     {
       return mKeyPoint.IsNull() && mSerial == 0;
     }
   };
 
--- a/dom/media/ogg/OggDemuxer.cpp
+++ b/dom/media/ogg/OggDemuxer.cpp
@@ -1337,16 +1337,19 @@ OggTrackDemuxer::NextSample()
   ogg_packet* packet = mParent->GetNextPacket(mType);
   if (!packet) {
     return nullptr;
   }
   // Check the eos state in case we need to look for chained streams.
   bool eos = packet->e_o_s;
   OggCodecState* state = mParent->GetTrackCodecState(mType);
   RefPtr<MediaRawData> data = state->PacketOutAsMediaRawData();
+  if (!data) {
+    return nullptr;
+  }
   if (mType == TrackInfo::kAudioTrack) {
     data->mTrackInfo = mParent->mSharedAudioTrackInfo;
   }
   if (eos) {
     // We've encountered an end of bitstream packet; check for a chained
     // bitstream following this one.
     // This will also update mSharedAudioTrackInfo.
     mParent->ReadOggChain(TimeUnit::FromMicroseconds(data->GetEndTime()));
--- a/dom/media/wave/WaveDemuxer.cpp
+++ b/dom/media/wave/WaveDemuxer.cpp
@@ -192,17 +192,18 @@ WAVTrackDemuxer::HeaderParserInit()
 
 bool
 WAVTrackDemuxer::FmtChunkParserInit()
 {
   RefPtr<MediaRawData> fmtChunk = GetFileHeader(FindFmtChunk());
   if (!fmtChunk) {
     return false;
   }
-  ByteReader fmtReader(fmtChunk->Data(), mHeaderParser.GiveHeader().ChunkSize());
+  ByteReader fmtReader(fmtChunk->Data(),
+                       mHeaderParser.GiveHeader().ChunkSize());
   mFmtParser.Parse(fmtReader);
   return true;
 }
 
 bool
 WAVTrackDemuxer::ListChunkParserInit(uint32_t aChunkSize)
 {
   uint32_t bytesRead = 0;
@@ -255,26 +256,30 @@ WAVTrackDemuxer::ListChunkParserInit(uin
 
     if (!IsUTF8(val)) {
       mHeaderParser.Reset();
       continue;
     }
 
     switch (id) {
       case 0x49415254:                // IART
-        mInfo->mTags.AppendElement(MetadataTag(NS_LITERAL_CSTRING("artist"), val));
+        mInfo->mTags.AppendElement(
+          MetadataTag(NS_LITERAL_CSTRING("artist"), val));
         break;
       case 0x49434d54:                // ICMT
-        mInfo->mTags.AppendElement(MetadataTag(NS_LITERAL_CSTRING("comments"), val));
+        mInfo->mTags.AppendElement(
+          MetadataTag(NS_LITERAL_CSTRING("comments"), val));
         break;
       case 0x49474e52:                // IGNR
-        mInfo->mTags.AppendElement(MetadataTag(NS_LITERAL_CSTRING("genre"), val));
+        mInfo->mTags.AppendElement(
+          MetadataTag(NS_LITERAL_CSTRING("genre"), val));
         break;
       case 0x494e414d:                // INAM
-        mInfo->mTags.AppendElement(MetadataTag(NS_LITERAL_CSTRING("name"), val));
+        mInfo->mTags.AppendElement(
+          MetadataTag(NS_LITERAL_CSTRING("name"), val));
         break;
     }
 
     mHeaderParser.Reset();
   }
   return true;
 }
 
@@ -352,17 +357,17 @@ WAVTrackDemuxer::GetSamples(int32_t aNum
     if (!datachunk) {
       break;
     }
     datachunks->mSamples.AppendElement(datachunk);
   }
 
   if (datachunks->mSamples.IsEmpty()) {
     return SamplesPromise::CreateAndReject(
-        NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
+      NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
   }
 
   return SamplesPromise::CreateAndResolve(datachunks, __func__);
 }
 
 void
 WAVTrackDemuxer::Reset()
 {
@@ -425,19 +430,18 @@ WAVTrackDemuxer::Duration() const
 }
 
 TimeUnit
 WAVTrackDemuxer::Duration(int64_t aNumDataChunks) const
 {
   if (!mSamplesPerSecond || !mSamplesPerChunk) {
     return TimeUnit();
   }
-  const double usPerDataChunk = USECS_PER_S *
-                                static_cast<double>(mSamplesPerChunk) /
-                                mSamplesPerSecond;
+  const double usPerDataChunk =
+    USECS_PER_S * static_cast<double>(mSamplesPerChunk) / mSamplesPerSecond;
   return TimeUnit::FromMicroseconds(aNumDataChunks * usPerDataChunk);
 }
 
 TimeUnit
 WAVTrackDemuxer::DurationFromBytes(uint32_t aNumBytes) const
 {
   if (!mSamplesPerSecond || !mChannels || !mSampleFormat) {
     return TimeUnit();
@@ -511,19 +515,18 @@ WAVTrackDemuxer::GetNextChunk(const Medi
   RefPtr<MediaRawData> datachunk = new MediaRawData();
   datachunk->mOffset = aRange.mStart;
 
   nsAutoPtr<MediaRawDataWriter> chunkWriter(datachunk->CreateWriter());
   if (!chunkWriter->SetSize(aRange.Length())) {
     return nullptr;
   }
 
-  const uint32_t read = Read(chunkWriter->Data(),
-                             datachunk->mOffset,
-                             datachunk->Size());
+  const uint32_t read =
+    Read(chunkWriter->Data(), datachunk->mOffset, datachunk->Size());
 
   if (read != aRange.Length()) {
     return nullptr;
   }
 
   UpdateState(aRange);
   ++mNumParsedChunks;
   ++mChunkIndex;
@@ -556,19 +559,18 @@ WAVTrackDemuxer::GetFileHeader(const Med
   RefPtr<MediaRawData> fileHeader = new MediaRawData();
   fileHeader->mOffset = aRange.mStart;
 
   nsAutoPtr<MediaRawDataWriter> headerWriter(fileHeader->CreateWriter());
   if (!headerWriter->SetSize(aRange.Length())) {
     return nullptr;
   }
 
-  const uint32_t read = Read(headerWriter->Data(),
-                             fileHeader->mOffset,
-                             fileHeader->Size());
+  const uint32_t read =
+    Read(headerWriter->Data(), fileHeader->mOffset, fileHeader->Size());
 
   if (read != aRange.Length()) {
     return nullptr;
   }
 
   UpdateState(aRange);
 
   return fileHeader.forget();
@@ -752,25 +754,29 @@ bool
 HeaderParser::ChunkHeader::IsValid() const
 {
   return mPos >= CHUNK_HEAD_SIZE;
 }
 
 uint32_t
 HeaderParser::ChunkHeader::ChunkName() const
 {
-  return ((mRaw[0] << 24) | (mRaw[1] << 16) |
-          (mRaw[2] << 8 ) | (mRaw[3]));
+  return ((mRaw[0] << 24)
+          | (mRaw[1] << 16)
+          | (mRaw[2] << 8 )
+          | (mRaw[3]));
 }
 
 uint32_t
 HeaderParser::ChunkHeader::ChunkSize() const
 {
-  return ((mRaw[7] << 24) | (mRaw[6] << 16) |
-          (mRaw[5] << 8 ) | (mRaw[4]));
+  return ((mRaw[7] << 24)
+          | (mRaw[6] << 16)
+          | (mRaw[5] << 8 )
+          | (mRaw[4]));
 }
 
 void
 HeaderParser::ChunkHeader::Update(uint8_t c)
 {
   if (mPos < CHUNK_HEAD_SIZE) {
     mRaw[mPos++] = c;
   }
@@ -826,18 +832,20 @@ uint16_t
 FormatParser::FormatChunk::Channels() const
 {
   return (mRaw[3] << 8) | (mRaw[2]);
 }
 
 uint32_t
 FormatParser::FormatChunk::SampleRate() const
 {
-  return (mRaw[7] << 24) | (mRaw[6] << 16) |
-         (mRaw[5] << 8 ) | (mRaw[4]);
+  return (mRaw[7] << 24)
+         | (mRaw[6] << 16)
+         | (mRaw[5] << 8)
+         | (mRaw[4]);
 }
 
 uint16_t
 FormatParser::FormatChunk::FrameSize() const
 {
   return (mRaw[13] << 8) | (mRaw[12]);
 }
 
@@ -852,18 +860,18 @@ FormatParser::FormatChunk::ParseNext(uin
 {
   Update(c);
   return IsValid();
 }
 
 bool
 FormatParser::FormatChunk::IsValid() const
 {
-  return (FrameSize() == SampleRate() * Channels() / 8) &&
-         (mPos >= FMT_CHUNK_MIN_SIZE);
+  return (FrameSize() == SampleRate() * Channels() / 8)
+         && (mPos >= FMT_CHUNK_MIN_SIZE);
 }
 
 void
 FormatParser::FormatChunk::Update(uint8_t c)
 {
   if (mPos < FMT_CHUNK_MIN_SIZE) {
     mRaw[mPos++] = c;
   }
--- a/dom/media/wave/WaveDemuxer.h
+++ b/dom/media/wave/WaveDemuxer.h
@@ -25,47 +25,50 @@ static const uint8_t WAVE[4] = {'W', 'A'
 
 static const uint16_t RIFF_CHUNK_SIZE = 12;
 static const uint16_t CHUNK_HEAD_SIZE = 8;
 static const uint16_t FMT_CHUNK_MIN_SIZE = 16;
 static const uint16_t DATA_CHUNK_SIZE = 768;
 
 class WAVTrackDemuxer;
 
-class WAVDemuxer : public MediaDataDemuxer {
+class WAVDemuxer : public MediaDataDemuxer
+{
 public:
   // MediaDataDemuxer interface.
   explicit WAVDemuxer(MediaResource* aSource);
   RefPtr<InitPromise> Init() override;
   bool HasTrackType(TrackInfo::TrackType aType) const override;
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
   already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
-      TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
+    TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
   bool IsSeekable() const override;
 
 private:
   // Synchronous Initialization.
   bool InitInternal();
 
   MediaResourceIndex mSource;
   RefPtr<WAVTrackDemuxer> mTrackDemuxer;
 };
 
-class RIFFParser {
+class RIFFParser
+{
 private:
   class RIFFHeader;
 public:
   const RIFFHeader& RiffHeader() const;
 
   uint32_t Parse(ByteReader& aReader);
 
   void Reset();
 
 private:
-  class RIFFHeader {
+  class RIFFHeader
+  {
   public:
     RIFFHeader();
     void Reset();
 
     bool IsValid() const;
     bool IsValid(int aPos) const;
 
     bool ParseNext(uint8_t c);
@@ -76,28 +79,30 @@ private:
     uint8_t mRaw[RIFF_CHUNK_SIZE];
 
     int mPos;
   };
 
   RIFFHeader mRiffHeader;
 };
 
-class HeaderParser {
+class HeaderParser
+{
 private:
   class ChunkHeader;
 public:
   const ChunkHeader& GiveHeader() const;
 
   uint32_t Parse(ByteReader& aReader);
 
   void Reset();
 
 private:
-  class ChunkHeader {
+  class ChunkHeader
+  {
   public:
     ChunkHeader();
     void Reset();
 
     bool IsValid() const;
 
     uint32_t ChunkName() const;
     uint32_t ChunkSize() const;
@@ -110,28 +115,30 @@ private:
     uint8_t mRaw[CHUNK_HEAD_SIZE];
 
     int mPos;
   };
 
   ChunkHeader mHeader;
 };
 
-class FormatParser {
+class FormatParser
+{
 private:
   class FormatChunk;
 public:
   const FormatChunk& FmtChunk() const;
 
   uint32_t Parse(ByteReader& aReader);
 
   void Reset();
 
 private:
-  class FormatChunk {
+  class FormatChunk
+  {
   public:
     FormatChunk();
     void Reset();
 
     uint16_t WaveFormat() const;
     uint16_t Channels() const;
     uint32_t SampleRate() const;
     uint16_t FrameSize() const;
@@ -146,38 +153,41 @@ private:
     uint8_t mRaw[FMT_CHUNK_MIN_SIZE];
 
     int mPos;
   };
 
   FormatChunk mFmtChunk;
 };
 
-class DataParser {
+class DataParser
+{
 private:
   class DataChunk;
 public:
   DataParser();
 
   const DataChunk& CurrentChunk() const;
 
   void Reset();
 
 private:
-  class DataChunk {
+  class DataChunk
+  {
   public:
     void Reset();
   private:
     int mPos; // To Check Alignment
   };
 
   DataChunk mChunk;
 };
 
-class WAVTrackDemuxer : public MediaTrackDemuxer {
+class WAVTrackDemuxer : public MediaTrackDemuxer
+{
 public:
   explicit WAVTrackDemuxer(MediaResourceIndex aSource);
 
   bool Init();
 
   int64_t StreamLength() const;
 
   media::TimeUnit Duration() const;
@@ -194,17 +204,17 @@ public:
   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples) override;
   void Reset() override;
   RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
     const media::TimeUnit& aTimeThreshold) override;
   int64_t GetResourceOffset() const override;
   media::TimeIntervals GetBuffered() override;
 
 private:
-  ~WAVTrackDemuxer() {}
+  ~WAVTrackDemuxer() { }
 
   media::TimeUnit FastSeek(const media::TimeUnit& aTime);
   media::TimeUnit ScanUntil(const media::TimeUnit& aTime);
 
   MediaByteRange FindNextChunk();
 
   MediaByteRange FindChunkHeader();
   MediaByteRange FindRIFFHeader();
--- a/dom/media/webm/WebMDemuxer.cpp
+++ b/dom/media/webm/WebMDemuxer.cpp
@@ -71,25 +71,27 @@ static int webmdemux_read(void* aBuffer,
     context->GetResource()->Read(static_cast<char*>(aBuffer), count, &bytes);
   bool eof = bytes < aLength;
   return NS_FAILED(rv) ? -1 : eof ? 0 : 1;
 }
 
 static int webmdemux_seek(int64_t aOffset, int aWhence, void* aUserData)
 {
   MOZ_ASSERT(aUserData);
-  WebMDemuxer::NestEggContext* context = reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
+  WebMDemuxer::NestEggContext* context =
+    reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
   nsresult rv = context->GetResource()->Seek(aWhence, aOffset);
   return NS_SUCCEEDED(rv) ? 0 : -1;
 }
 
 static int64_t webmdemux_tell(void* aUserData)
 {
   MOZ_ASSERT(aUserData);
-  WebMDemuxer::NestEggContext* context = reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
+  WebMDemuxer::NestEggContext* context =
+    reinterpret_cast<WebMDemuxer::NestEggContext*>(aUserData);
   return context->GetResource()->Tell();
 }
 
 static void webmdemux_log(nestegg* aContext,
                           unsigned int aSeverity,
                           char const* aFormat, ...)
 {
   if (!MOZ_LOG_TEST(gNesteggLog, LogLevel::Debug)) {
@@ -183,22 +185,24 @@ WebMDemuxer::~WebMDemuxer()
 }
 
 RefPtr<WebMDemuxer::InitPromise>
 WebMDemuxer::Init()
 {
   InitBufferedState();
 
   if (NS_FAILED(ReadMetadata())) {
-    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
+    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+                                        __func__);
   }
 
-  if (!GetNumberTracks(TrackInfo::kAudioTrack) &&
-      !GetNumberTracks(TrackInfo::kVideoTrack)) {
-    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_METADATA_ERR, __func__);
+  if (!GetNumberTracks(TrackInfo::kAudioTrack)
+      && !GetNumberTracks(TrackInfo::kVideoTrack)) {
+    return InitPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_METADATA_ERR,
+                                        __func__);
   }
 
   return InitPromise::CreateAndResolve(NS_OK, __func__);
 }
 
 void
 WebMDemuxer::InitBufferedState()
 {
@@ -286,18 +290,18 @@ WebMDemuxer::ReadMetadata()
     }
     mBufferedState->NotifyDataArrived(buffer->Elements(), buffer->Length(), 0);
     if (mBufferedState->GetInitEndOffset() < 0) {
       return NS_ERROR_FAILURE;
     }
     MOZ_ASSERT(mBufferedState->GetInitEndOffset() <= resource.Tell());
   }
   mInitData = resource.MediaReadAt(0, mBufferedState->GetInitEndOffset());
-  if (!mInitData ||
-      mInitData->Length() != size_t(mBufferedState->GetInitEndOffset())) {
+  if (!mInitData
+      || mInitData->Length() != size_t(mBufferedState->GetInitEndOffset())) {
     return NS_ERROR_FAILURE;
   }
 
   unsigned int ntracks = 0;
   r = nestegg_track_count(context, &ntracks);
   if (r == -1) {
     return NS_ERROR_FAILURE;
   }
@@ -331,20 +335,20 @@ WebMDemuxer::ReadMetadata()
       unsigned int cropH = params.crop_right + params.crop_left;
       unsigned int cropV = params.crop_bottom + params.crop_top;
       nsIntRect pictureRect(params.crop_left,
                             params.crop_top,
                             params.width - cropH,
                             params.height - cropV);
 
       // If the cropping data appears invalid then use the frame data
-      if (pictureRect.width <= 0 ||
-          pictureRect.height <= 0 ||
-          pictureRect.x < 0 ||
-          pictureRect.y < 0) {
+      if (pictureRect.width <= 0
+          || pictureRect.height <= 0
+          || pictureRect.x < 0
+          || pictureRect.y < 0) {
         pictureRect.x = 0;
         pictureRect.y = 0;
         pictureRect.width = params.width;
         pictureRect.height = params.height;
       }
 
       // Validate the container-reported frame and pictureRect sizes. This
       // ensures that our video frame creation code doesn't overflow.
@@ -378,38 +382,42 @@ WebMDemuxer::ReadMetadata()
           break;
         case NESTEGG_VIDEO_STEREO_RIGHT_LEFT:
           mInfo.mVideo.mStereoMode = StereoMode::RIGHT_LEFT;
           break;
       }
       uint64_t duration = 0;
       r = nestegg_duration(context, &duration);
       if (!r) {
-        mInfo.mVideo.mDuration = media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
+        mInfo.mVideo.mDuration =
+          media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
       }
       mInfo.mVideo.mCrypto = GetTrackCrypto(TrackInfo::kVideoTrack, track);
       if (mInfo.mVideo.mCrypto.mValid) {
-        mCrypto.AddInitData(NS_LITERAL_STRING("webm"), mInfo.mVideo.mCrypto.mKeyId);
+        mCrypto.AddInitData(NS_LITERAL_STRING("webm"),
+                            mInfo.mVideo.mCrypto.mKeyId);
       }
     } else if (type == NESTEGG_TRACK_AUDIO && !mHasAudio) {
       nestegg_audio_params params;
       r = nestegg_track_audio_params(context, track, &params);
       if (r == -1) {
         return NS_ERROR_FAILURE;
       }
 
       mAudioTrack = track;
       mHasAudio = true;
       mAudioCodec = nestegg_track_codec_id(context, track);
       if (mAudioCodec == NESTEGG_CODEC_VORBIS) {
         mInfo.mAudio.mMimeType = "audio/vorbis";
       } else if (mAudioCodec == NESTEGG_CODEC_OPUS) {
         mInfo.mAudio.mMimeType = "audio/opus";
-        OpusDataDecoder::AppendCodecDelay(mInfo.mAudio.mCodecSpecificConfig,
-            media::TimeUnit::FromNanoseconds(params.codec_delay).ToMicroseconds());
+        OpusDataDecoder::AppendCodecDelay(
+          mInfo.mAudio.mCodecSpecificConfig,
+          media::TimeUnit::FromNanoseconds(params.codec_delay)
+            .ToMicroseconds());
       }
       mSeekPreroll = params.seek_preroll;
       mInfo.mAudio.mRate = params.rate;
       mInfo.mAudio.mChannels = params.channels;
 
       unsigned int nheaders = 0;
       r = nestegg_track_codec_data_count(context, track, &nheaders);
       if (r == -1) {
@@ -442,39 +450,41 @@ WebMDemuxer::ReadMetadata()
       }
       else {
         mInfo.mAudio.mCodecSpecificConfig->AppendElements(headers[0],
                                                           headerLens[0]);
       }
       uint64_t duration = 0;
       r = nestegg_duration(context, &duration);
       if (!r) {
-        mInfo.mAudio.mDuration = media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
+        mInfo.mAudio.mDuration =
+          media::TimeUnit::FromNanoseconds(duration).ToMicroseconds();
       }
       mInfo.mAudio.mCrypto = GetTrackCrypto(TrackInfo::kAudioTrack, track);
       if (mInfo.mAudio.mCrypto.mValid) {
-        mCrypto.AddInitData(NS_LITERAL_STRING("webm"), mInfo.mAudio.mCrypto.mKeyId);
+        mCrypto.AddInitData(NS_LITERAL_STRING("webm"),
+                            mInfo.mAudio.mCrypto.mKeyId);
       }
     }
   }
   return NS_OK;
 }
 
 bool
 WebMDemuxer::IsSeekable() const
 {
-  return Context(TrackInfo::kVideoTrack) &&
-         nestegg_has_cues(Context(TrackInfo::kVideoTrack));
+  return Context(TrackInfo::kVideoTrack)
+         && nestegg_has_cues(Context(TrackInfo::kVideoTrack));
 }
 
 bool
 WebMDemuxer::IsSeekableOnlyInBufferedRanges() const
 {
-  return Context(TrackInfo::kVideoTrack) &&
-         !nestegg_has_cues(Context(TrackInfo::kVideoTrack));
+  return Context(TrackInfo::kVideoTrack)
+         && !nestegg_has_cues(Context(TrackInfo::kVideoTrack));
 }
 
 void
 WebMDemuxer::EnsureUpToDateIndex()
 {
   if (!mNeedReIndex || !mInitData) {
     return;
   }
@@ -503,36 +513,39 @@ WebMDemuxer::NotifyDataArrived()
   mNeedReIndex = true;
 }
 
 void
 WebMDemuxer::NotifyDataRemoved()
 {
   mBufferedState->Reset();
   if (mInitData) {
-    mBufferedState->NotifyDataArrived(mInitData->Elements(), mInitData->Length(), 0);
+    mBufferedState->NotifyDataArrived(mInitData->Elements(),
+                                      mInitData->Length(), 0);
   }
   mNeedReIndex = true;
 }
 
 UniquePtr<EncryptionInfo>
 WebMDemuxer::GetCrypto()
 {
   return mCrypto.IsEncrypted() ? MakeUnique<EncryptionInfo>(mCrypto) : nullptr;
 }
 
 CryptoTrack
-WebMDemuxer::GetTrackCrypto(TrackInfo::TrackType aType, size_t aTrackNumber) {
+WebMDemuxer::GetTrackCrypto(TrackInfo::TrackType aType, size_t aTrackNumber)
+{
   const int WEBM_IV_SIZE = 16;
   const unsigned char * contentEncKeyId;
   size_t contentEncKeyIdLength;
   CryptoTrack crypto;
   nestegg* context = Context(aType);
 
-  int r = nestegg_track_content_enc_key_id(context, aTrackNumber, &contentEncKeyId, &contentEncKeyIdLength);
+  int r = nestegg_track_content_enc_key_id(
+    context, aTrackNumber, &contentEncKeyId, &contentEncKeyIdLength);
 
   if (r == -1) {
     WEBM_DEBUG("nestegg_track_content_enc_key_id failed r=%d", r);
     return crypto;
   }
 
   uint32_t i;
   nsTArray<uint8_t> initData;
@@ -546,17 +559,18 @@ WebMDemuxer::GetTrackCrypto(TrackInfo::T
     crypto.mIVSize = WEBM_IV_SIZE;
     crypto.mKeyId = Move(initData);
   }
 
   return crypto;
 }
 
 bool
-WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType, MediaRawDataQueue *aSamples)
+WebMDemuxer::GetNextPacket(TrackInfo::TrackType aType,
+                           MediaRawDataQueue *aSamples)
 {
   if (mIsMediaSource) {
     // To ensure mLastWebMBlockOffset is properly up to date.
     EnsureUpToDateIndex();
   }
 
   RefPtr<NesteggPacketHolder> holder(NextPacket(aType));
 
@@ -580,33 +594,33 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
   int64_t next_tstamp = INT64_MIN;
   if (aType == TrackInfo::kAudioTrack) {
     RefPtr<NesteggPacketHolder> next_holder(NextPacket(aType));
     if (next_holder) {
       next_tstamp = next_holder->Timestamp();
       PushAudioPacket(next_holder);
     } else if (duration >= 0) {
       next_tstamp = tstamp + duration;
-    } else if (!mIsMediaSource ||
-               (mIsMediaSource && mLastAudioFrameTime.isSome())) {
+    } else if (!mIsMediaSource
+               || (mIsMediaSource && mLastAudioFrameTime.isSome())) {
       next_tstamp = tstamp;
       next_tstamp += tstamp - mLastAudioFrameTime.refOr(0);
     } else {
       PushAudioPacket(holder);
     }
     mLastAudioFrameTime = Some(tstamp);
   } else if (aType == TrackInfo::kVideoTrack) {
     RefPtr<NesteggPacketHolder> next_holder(NextPacket(aType));
     if (next_holder) {
       next_tstamp = next_holder->Timestamp();
       PushVideoPacket(next_holder);
     } else if (duration >= 0) {
       next_tstamp = tstamp + duration;
-    } else if (!mIsMediaSource ||
-               (mIsMediaSource && mLastVideoFrameTime.isSome())) {
+    } else if (!mIsMediaSource
+               || (mIsMediaSource && mLastVideoFrameTime.isSome())) {
       next_tstamp = tstamp;
       next_tstamp += tstamp - mLastVideoFrameTime.refOr(0);
     } else {
       PushVideoPacket(holder);
     }
     mLastVideoFrameTime = Some(tstamp);
   }
 
@@ -645,52 +659,63 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
       }
     }
     bool isKeyframe = false;
     if (aType == TrackInfo::kAudioTrack) {
       isKeyframe = true;
     } else if (aType == TrackInfo::kVideoTrack) {
       if (packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED) {
         // Packet is encrypted, can't peek, use packet info
-        isKeyframe = nestegg_packet_has_keyframe(holder->Packet()) == NESTEGG_PACKET_HAS_KEYFRAME_TRUE;
+        isKeyframe = nestegg_packet_has_keyframe(holder->Packet())
+                     == NESTEGG_PACKET_HAS_KEYFRAME_TRUE;
       } else {
         vpx_codec_stream_info_t si;
         PodZero(&si);
         si.sz = sizeof(si);
         switch (mVideoCodec) {
         case NESTEGG_CODEC_VP8:
           vpx_codec_peek_stream_info(vpx_codec_vp8_dx(), data, length, &si);
           break;
         case NESTEGG_CODEC_VP9:
           vpx_codec_peek_stream_info(vpx_codec_vp9_dx(), data, length, &si);
           break;
         }
         isKeyframe = si.is_kf;
         if (isKeyframe) {
           // We only look for resolution changes on keyframes for both VP8 and
           // VP9. Other resolution changes are invalid.
-          if (mLastSeenFrameWidth.isSome() && mLastSeenFrameHeight.isSome() &&
-            (si.w != mLastSeenFrameWidth.value() ||
-              si.h != mLastSeenFrameHeight.value())) {
+          if (mLastSeenFrameWidth.isSome()
+              && mLastSeenFrameHeight.isSome()
+              && (si.w != mLastSeenFrameWidth.value()
+                  || si.h != mLastSeenFrameHeight.value())) {
             mInfo.mVideo.mDisplay = nsIntSize(si.w, si.h);
-            mSharedVideoTrackInfo = new SharedTrackInfo(mInfo.mVideo, ++sStreamSourceID);
+            mSharedVideoTrackInfo =
+              new SharedTrackInfo(mInfo.mVideo, ++sStreamSourceID);
           }
           mLastSeenFrameWidth = Some(si.w);
           mLastSeenFrameHeight = Some(si.h);
         }
       }
     }
 
     WEBM_DEBUG("push sample tstamp: %ld next_tstamp: %ld length: %ld kf: %d",
                tstamp, next_tstamp, length, isKeyframe);
     RefPtr<MediaRawData> sample;
     if (mInfo.mVideo.HasAlpha() && alphaLength != 0) {
       sample = new MediaRawData(data, length, alphaData, alphaLength);
+      if (!sample->Data() || !sample->AlphaData()) {
+        // OOM.
+        return false;
+      }
     } else {
       sample = new MediaRawData(data, length);
+      if (!sample->Data()) {
+        // OOM.
+        return false;
+      }
     }
     sample->mTimecode = tstamp;
     sample->mTime = tstamp;
     sample->mDuration = next_tstamp - tstamp;
     sample->mOffset = holder->Offset();
     sample->mKeyframe = isKeyframe;
     if (discardPadding && i == count - 1) {
       CheckedInt64 discardFrames;
@@ -704,18 +729,18 @@ WebMDemuxer::GetNextPacket(TrackInfo::Tr
         discardFrames = TimeUnitToFrames(
           media::TimeUnit::FromNanoseconds(discardPadding), mInfo.mAudio.mRate);
       }
       if (discardFrames.isValid()) {
         sample->mDiscardPadding = discardFrames.value();
       }
     }
 
-    if (packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED ||
-        packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED) {
+    if (packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED
+        || packetEncryption == NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED) {
       nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
       unsigned char const* iv;
       size_t ivLength;
       nestegg_packet_iv(holder->Packet(), &iv, &ivLength);
       writer->mCrypto.mValid = true;
       writer->mCrypto.mIVSize = ivLength;
       if (ivLength == 0) {
         // Frame is not encrypted
@@ -999,17 +1024,18 @@ WebMTrackDemuxer::GetSamples(int32_t aNu
       continue;
     }
     mNeedKeyframe = false;
     samples->mSamples.AppendElement(sample);
     aNumSamples--;
   }
 
   if (samples->mSamples.IsEmpty()) {
-    return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM, __func__);
+    return SamplesPromise::CreateAndReject(NS_ERROR_DOM_MEDIA_END_OF_STREAM,
+                                           __func__);
   } else {
     UpdateSamples(samples->mSamples);
     return SamplesPromise::CreateAndResolve(samples, __func__);
   }
 }
 
 void
 WebMTrackDemuxer::SetNextKeyFrameTime()
@@ -1043,32 +1069,34 @@ WebMTrackDemuxer::SetNextKeyFrameTime()
     if (sample->mKeyframe) {
       frameTime = sample->mTime;
       foundKeyframe = true;
     }
     int64_t sampleTimecode = sample->mTimecode;
     skipSamplesQueue.Push(sample.forget());
     if (!startTime) {
       startTime.emplace(sampleTimecode);
-    } else if (!foundKeyframe &&
-               sampleTimecode > startTime.ref() + MAX_LOOK_AHEAD) {
+    } else if (!foundKeyframe
+               && sampleTimecode > startTime.ref() + MAX_LOOK_AHEAD) {
       WEBM_DEBUG("Couldn't find keyframe in a reasonable time, aborting");
       break;
     }
   }
   // We may have demuxed more than intended, so ensure that all frames are kept
   // in the right order.
   mSamples.PushFront(Move(skipSamplesQueue));
 
   if (frameTime != -1) {
     mNextKeyframeTime.emplace(media::TimeUnit::FromMicroseconds(frameTime));
     WEBM_DEBUG("Next Keyframe %f (%u queued %.02fs)",
                mNextKeyframeTime.value().ToSeconds(),
                uint32_t(mSamples.GetSize()),
-               media::TimeUnit::FromMicroseconds(mSamples.Last()->mTimecode - mSamples.First()->mTimecode).ToSeconds());
+               media::TimeUnit::FromMicroseconds(mSamples.Last()->mTimecode
+                                                 - mSamples.First()->mTimecode)
+                 .ToSeconds());
   } else {
     WEBM_DEBUG("Couldn't determine next keyframe time  (%u queued)",
                uint32_t(mSamples.GetSize()));
   }
 }
 
 void
 WebMTrackDemuxer::Reset()
@@ -1091,18 +1119,19 @@ WebMTrackDemuxer::UpdateSamples(nsTArray
   for (const auto& sample : aSamples) {
     if (sample->mCrypto.mValid) {
       nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
       writer->mCrypto.mMode = mInfo->mCrypto.mMode;
       writer->mCrypto.mIVSize = mInfo->mCrypto.mIVSize;
       writer->mCrypto.mKeyId.AppendElements(mInfo->mCrypto.mKeyId);
     }
   }
-  if (mNextKeyframeTime.isNothing() ||
-      aSamples.LastElement()->mTime >= mNextKeyframeTime.value().ToMicroseconds()) {
+  if (mNextKeyframeTime.isNothing()
+      || aSamples.LastElement()->mTime
+         >= mNextKeyframeTime.value().ToMicroseconds()) {
     SetNextKeyFrameTime();
   }
 }
 
 nsresult
 WebMTrackDemuxer::GetNextRandomAccessPoint(media::TimeUnit* aTime)
 {
   if (mNextKeyframeTime.isNothing()) {
@@ -1111,17 +1140,18 @@ WebMTrackDemuxer::GetNextRandomAccessPoi
       media::TimeUnit::FromMicroseconds(std::numeric_limits<int64_t>::max());
   } else {
     *aTime = mNextKeyframeTime.ref();
   }
   return NS_OK;
 }
 
 RefPtr<WebMTrackDemuxer::SkipAccessPointPromise>
-WebMTrackDemuxer::SkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreshold)
+WebMTrackDemuxer::SkipToNextRandomAccessPoint(
+  const media::TimeUnit& aTimeThreshold)
 {
   uint32_t parsed = 0;
   bool found = false;
   RefPtr<MediaRawData> sample;
   int64_t sampleTime;
 
   WEBM_DEBUG("TimeThreshold: %f", aTimeThreshold.ToSeconds());
   while (!found && (sample = NextSample())) {
--- a/dom/media/webm/WebMDemuxer.h
+++ b/dom/media/webm/WebMDemuxer.h
@@ -13,99 +13,112 @@
 
 typedef struct nestegg nestegg;
 
 namespace mozilla {
 
 class WebMBufferedState;
 
 // Queue for holding MediaRawData samples
-class MediaRawDataQueue {
+class MediaRawDataQueue
+{
  public:
-  uint32_t GetSize() {
+  uint32_t GetSize()
+  {
     return mQueue.size();
   }
 
-  void Push(MediaRawData* aItem) {
+  void Push(MediaRawData* aItem)
+  {
     mQueue.push_back(aItem);
   }
 
-  void Push(already_AddRefed<MediaRawData>&& aItem) {
+  void Push(already_AddRefed<MediaRawData>&& aItem)
+  {
     mQueue.push_back(Move(aItem));
   }
 
   void PushFront(MediaRawData* aItem) {
     mQueue.push_front(aItem);
   }
 
-  void PushFront(already_AddRefed<MediaRawData>&& aItem) {
+  void PushFront(already_AddRefed<MediaRawData>&& aItem)
+  {
     mQueue.push_front(Move(aItem));
   }
 
-  void PushFront(MediaRawDataQueue&& aOther) {
+  void PushFront(MediaRawDataQueue&& aOther)
+  {
     while (!aOther.mQueue.empty()) {
       PushFront(aOther.Pop());
     }
   }
 
-  already_AddRefed<MediaRawData> PopFront() {
+  already_AddRefed<MediaRawData> PopFront()
+  {
     RefPtr<MediaRawData> result = mQueue.front().forget();
     mQueue.pop_front();
     return result.forget();
   }
 
-  already_AddRefed<MediaRawData> Pop() {
+  already_AddRefed<MediaRawData> Pop()
+  {
     RefPtr<MediaRawData> result = mQueue.back().forget();
     mQueue.pop_back();
     return result.forget();
   }
 
-  void Reset() {
+  void Reset()
+  {
     while (!mQueue.empty()) {
       mQueue.pop_front();
     }
   }
 
-  MediaRawDataQueue& operator=(const MediaRawDataQueue& aOther) {
+  MediaRawDataQueue& operator=(const MediaRawDataQueue& aOther)
+  {
     mQueue = aOther.mQueue;
     return *this;
   }
 
-  const RefPtr<MediaRawData>& First() const {
+  const RefPtr<MediaRawData>& First() const
+  {
     return mQueue.front();
   }
 
-  const RefPtr<MediaRawData>& Last() const {
+  const RefPtr<MediaRawData>& Last() const
+  {
     return mQueue.back();
   }
 
 private:
   std::deque<RefPtr<MediaRawData>> mQueue;
 };
 
 class WebMTrackDemuxer;
 
 class WebMDemuxer : public MediaDataDemuxer
 {
 public:
   explicit WebMDemuxer(MediaResource* aResource);
   // Indicate if the WebMDemuxer is to be used with MediaSource. In which
   // case the demuxer will stop reads to the last known complete block.
   WebMDemuxer(MediaResource* aResource, bool aIsMediaSource);
-  
+
   RefPtr<InitPromise> Init() override;
 
   bool HasTrackType(TrackInfo::TrackType aType) const override;
 
   uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
 
-  UniquePtr<TrackInfo> GetTrackInfo(TrackInfo::TrackType aType, size_t aTrackNumber) const;
+  UniquePtr<TrackInfo> GetTrackInfo(TrackInfo::TrackType aType,
+                                    size_t aTrackNumber) const;
 
-  already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(TrackInfo::TrackType aType,
-                                                      uint32_t aTrackNumber) override;
+  already_AddRefed<MediaTrackDemuxer>
+  GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
 
   bool IsSeekable() const override;
 
   bool IsSeekableOnlyInBufferedRanges() const override;
 
   UniquePtr<EncryptionInfo> GetCrypto() override;
 
   bool GetOffsetForTime(uint64_t aTime, int64_t* aOffset);
@@ -127,35 +140,39 @@ public:
     return mIsMediaSource;
   }
 
   int64_t LastWebMBlockOffset() const
   {
     return mLastWebMBlockOffset;
   }
 
-  struct NestEggContext {
+  struct NestEggContext
+  {
     NestEggContext(WebMDemuxer* aParent, MediaResource* aResource)
-    : mParent(aParent)
-    , mResource(aResource)
-    , mContext(nullptr) {}
+      : mParent(aParent)
+      , mResource(aResource)
+      , mContext(nullptr)
+    {
+    }
 
     ~NestEggContext();
 
     int Init();
 
     // Public accessor for nestegg callbacks
 
     bool IsMediaSource() const { return mParent->IsMediaSource(); }
     MediaResourceIndex* GetResource() { return &mResource; }
 
     int64_t GetEndDataOffset() const
     {
       return (!mParent->IsMediaSource() || mParent->LastWebMBlockOffset() < 0)
-             ? mResource.GetLength() : mParent->LastWebMBlockOffset();
+             ? mResource.GetLength()
+             : mParent->LastWebMBlockOffset();
     }
 
     WebMDemuxer* mParent;
     MediaResourceIndex mResource;
     nestegg* mContext;
   };
 
 private:
@@ -258,17 +275,18 @@ public:
   RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
 
   RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
 
   void Reset() override;
 
   nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
 
-  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(const media::TimeUnit& aTimeThreshold) override;
+  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
+    const media::TimeUnit& aTimeThreshold) override;
 
   media::TimeIntervals GetBuffered() override;
 
   int64_t GetEvictionOffset(const media::TimeUnit& aTime) override;
 
   void BreakCycles() override;
 
 private:
--- a/dom/svg/SVGAElement.cpp
+++ b/dom/svg/SVGAElement.cpp
@@ -182,34 +182,87 @@ SVGAElement::IsAttributeMapped(const nsI
     sTextContentElementsMap,
     sViewportsMap
   };
 
   return FindAttributeDependence(name, map) ||
     SVGAElementBase::IsAttributeMapped(name);
 }
 
-bool
-SVGAElement::IsFocusableInternal(int32_t *aTabIndex, bool aWithMouse)
+int32_t
+SVGAElement::TabIndexDefault()
+{
+  return 0;
+}
+
+static bool
+IsNodeInEditableRegion(nsINode* aNode)
 {
-  nsCOMPtr<nsIURI> uri;
-  if (IsLink(getter_AddRefs(uri))) {
-    if (aTabIndex) {
-      *aTabIndex = ((sTabFocusModel & eTabFocus_linksMask) == 0 ? -1 : 0);
+  while (aNode) {
+    if (aNode->IsEditable()) {
+      return true;
     }
-    return true;
+    aNode = aNode->GetParent();
   }
-  if (nsSVGElement::IsFocusableInternal(aTabIndex, aWithMouse)) {
+  return false;
+}
+
+bool
+SVGAElement::IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex)
+{
+  if (nsSVGElement::IsSVGFocusable(aIsFocusable, aTabIndex)) {
     return true;
   }
 
-  if (aTabIndex) {
+  // cannot focus links if there is no link handler
+  nsIDocument* doc = GetComposedDoc();
+  if (doc) {
+    nsIPresShell* presShell = doc->GetShell();
+    if (presShell) {
+      nsPresContext* presContext = presShell->GetPresContext();
+      if (presContext && !presContext->GetLinkHandler()) {
+        *aIsFocusable = false;
+        return false;
+      }
+    }
+  }
+
+  // Links that are in an editable region should never be focusable, even if
+  // they are in a contenteditable="false" region.
+  if (IsNodeInEditableRegion(this)) {
+    if (aTabIndex) {
+      *aTabIndex = -1;
+    }
+
+    *aIsFocusable = false;
+
+    return true;
+  }
+
+  if (!HasAttr(kNameSpaceID_None, nsGkAtoms::tabindex)) {
+    // check whether we're actually a link
+    if (!Link::HasURI()) {
+      // Not tabbable or focusable without href (bug 17605), unless
+      // forced to be via presence of nonnegative tabindex attribute
+      if (aTabIndex) {
+        *aTabIndex = -1;
+      }
+
+      *aIsFocusable = false;
+
+      return false;
+    }
+  }
+
+  if (aTabIndex && (sTabFocusModel & eTabFocus_linksMask) == 0) {
     *aTabIndex = -1;
   }
 
+  *aIsFocusable = true;
+
   return false;
 }
 
 bool
 SVGAElement::IsLink(nsIURI** aURI) const
 {
   // To be a clickable XLink for styling and interaction purposes, we require:
   //
--- a/dom/svg/SVGAElement.h
+++ b/dom/svg/SVGAElement.h
@@ -45,17 +45,18 @@ public:
 
   // nsIContent
   virtual nsresult BindToTree(nsIDocument *aDocument, nsIContent *aParent,
                               nsIContent *aBindingParent,
                               bool aCompileEventHandlers) override;
   virtual void UnbindFromTree(bool aDeep = true,
                               bool aNullParent = true) override;
   NS_IMETHOD_(bool) IsAttributeMapped(const nsIAtom* aAttribute) const override;
-  virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;
+  virtual int32_t TabIndexDefault() override;
+  virtual bool IsSVGFocusable(bool* aIsFocusable, int32_t* aTabIndex) override;
   virtual bool IsLink(nsIURI** aURI) const override;
   virtual void GetLinkTarget(nsAString& aTarget) override;
   virtual already_AddRefed<nsIURI> GetHrefURI() const override;
   virtual EventStates IntrinsicState() const override;
   nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                    const nsAString& aValue, bool aNotify)
   {
     return SetAttr(aNameSpaceID, aName, nullptr, aValue, aNotify);
--- a/dom/svg/test/test_tabindex.html
+++ b/dom/svg/test/test_tabindex.html
@@ -11,54 +11,89 @@
 <svg xmlns="http://www.w3.org/2000/svg" overflow="visible">
   <foreignObject id="f" x="0" y="0" width="200" height="60" tabindex="0">
     <body xmlns="http://www.w3.org/1999/xhtml">
       <p>Here is a paragraph that requires word wrap</p>
     </body>
   </foreignObject>
   <rect id="r" x="0" y="70" width="100" height="100" fill="yellow" tabindex="1"/>
   <text id="t" x="0" y="200" tabindex="2">
-        This is SVG text
+    This is SVG text
   </text>
+  <a xlink:href="#" id="l1" tabindex="3">
+    <circle cx="10" cy="230" r="10"/>
+  </a>
+  <a id="l2" tabindex="4">
+    <circle cx="10" cy="260" r="10"/>
+  </a>
 </svg>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 SimpleTest.waitForExplicitFinish();
 
 function main()
 {
   var f = document.getElementById('f');
   var r = document.getElementById('r');
   var t = document.getElementById('t');
+  var l1 = document.getElementById('l1');
+  var l2 = document.getElementById('l2');
+  const isMac = ("nsILocalFileMac" in SpecialPowers.Ci);
 
   try {
     // Step 1: Checking by assigning tabIndex
     is(f.tabIndex, 0, "foreignObject initial tabIndex");
     f.tabIndex = 1;
     is(f.tabIndex, 1, "foreignObject tabIndex is set to 1");
 
     is(r.tabIndex, 1, "rect initial tabIndex");
     r.tabIndex = 2;
     is(r.tabIndex, 2, "rect tabIndex is set to 2");
 
     is(t.tabIndex, 2, "text initial tabIndex");
     t.tabIndex = 3;
     is(t.tabIndex, 3, "text is set to 3");
 
+    is(l1.tabIndex, 3, "link initial tabIndex");
+    l1.tabIndex = 4;
+    is(l1.tabIndex, 4, "link is set to 4");
+
+    is(l2.tabIndex, 4, "non-link initial tabIndex");
+    l2.tabIndex = 5;
+    is(l2.tabIndex, 5, "non-link is set to 4");
+
     // Step 2: Checking by triggering TAB event
     is(document.activeElement.tabIndex, -1, "In the beginning, the active element tabindex is -1");
 
     synthesizeKey("VK_TAB", {});
     is(document.activeElement.tabIndex, 1, "The active element tabindex is 1");
 
     synthesizeKey("VK_TAB", {});
     is(document.activeElement.tabIndex, 2, "The active element tabindex is 2");
 
     synthesizeKey("VK_TAB", {});
     is(document.activeElement.tabIndex, 3, "The active element tabindex is 3");
+
+    synthesizeKey("VK_TAB", {});
+    // On Mac, SVG link elements should not be focused.
+    if (isMac) {
+      is(document.activeElement.tabIndex, 3, "The active element tabindex is 3");
+    } else {
+      is(document.activeElement.tabIndex, 4, "The active element tabindex is 4");
+    }
+
+    synthesizeKey("VK_TAB", {});
+    // On Mac, SVG link elements should not be focused.
+    if (isMac) {
+      // This test has to be run with other tests, otherwise,
+      // document.activeElement.tabIndex will be -1 on Mac.
+      is(document.activeElement.tabIndex, 3, "The active element tabindex is 3");
+    } else {
+      is(document.activeElement.tabIndex, 5, "The active element tabindex is 5");
+    }
   } catch(e) {
     ok(false, "Got unexpected exception" + e);
   }
 
   SimpleTest.finish();
 }
 
 window.addEventListener("load", main);
--- a/gfx/doc/Silk.md
+++ b/gfx/doc/Silk.md
@@ -125,43 +125,43 @@ In practice, this creates very janky scr
 As of this writing, we have not analyzed input events on desktop platforms.
 
 One slight quirk is that input events can start a composite, for example during a scroll and after the **Compositor** is no longer listening to vsync events.
 In these cases, we notify the **Compositor** to observe vsync so that it dispatches touch events.
 If touch events were not dispatched, and since the **Compositor** is not listening to vsync events, the touch events would never be dispatched.
 The **GeckoTouchDispatcher** handles this case by always forcing the **Compositor** to listen to vsync events while touch events are occurring.
 
 ###Widget, Compositor, CompositorVsyncDispatcher, GeckoTouchDispatcher Shutdown Procedure
-When the [nsBaseWidget shuts down](http://hg.mozilla.org/mozilla-central/file/0df249a0e4d3/widget/nsBaseWidget.cpp#l182) - It calls nsBaseWidget::DestroyCompositor on the *Gecko Main Thread*.
+When the [nsBaseWidget shuts down](https://hg.mozilla.org/mozilla-central/file/0df249a0e4d3/widget/nsBaseWidget.cpp#l182) - It calls nsBaseWidget::DestroyCompositor on the *Gecko Main Thread*.
 During nsBaseWidget::DestroyCompositor, it first destroys the CompositorBridgeChild.
-CompositorBridgeChild sends a sync IPC call to CompositorBridgeParent::RecvStop, which calls [CompositorBridgeParent::Destroy](http://hg.mozilla.org/mozilla-central/file/ab0490972e1e/gfx/layers/ipc/CompositorBridgeParent.cpp#l509).
+CompositorBridgeChild sends a sync IPC call to CompositorBridgeParent::RecvStop, which calls [CompositorBridgeParent::Destroy](https://hg.mozilla.org/mozilla-central/file/ab0490972e1e/gfx/layers/ipc/CompositorBridgeParent.cpp#l509).
 During this time, the *main thread* is blocked on the parent process.
 CompositorBridgeParent::RecvStop runs on the *Compositor thread* and cleans up some resources, including setting the **CompositorVsyncScheduler::Observer** to nullptr.
 CompositorBridgeParent::RecvStop also explicitly keeps the CompositorBridgeParent alive and posts another task to run CompositorBridgeParent::DeferredDestroy on the Compositor loop so that all ipdl code can finish executing.
 The **CompositorVsyncScheduler::Observer** also unobserves from vsync and cancels any pending composite tasks.
 Once CompositorBridgeParent::RecvStop finishes, the *main thread* in the parent process continues shutting down the nsBaseWidget.
 
 At the same time, the *Compositor thread* is executing tasks until CompositorBridgeParent::DeferredDestroy runs, which flushes the compositor message loop.
 Now we have two tasks as both the nsBaseWidget releases a reference to the Compositor on the *main thread* during destruction and the CompositorBridgeParent::DeferredDestroy releases a reference to the CompositorBridgeParent on the *Compositor Thread*.
-Finally, the CompositorBridgeParent itself is destroyed on the *main thread* once both references are gone due to explicit [main thread destruction](http://hg.mozilla.org/mozilla-central/file/50b95032152c/gfx/layers/ipc/CompositorBridgeParent.h#l148).
+Finally, the CompositorBridgeParent itself is destroyed on the *main thread* once both references are gone due to explicit [main thread destruction](https://hg.mozilla.org/mozilla-central/file/50b95032152c/gfx/layers/ipc/CompositorBridgeParent.h#l148).
 
 With the **CompositorVsyncScheduler::Observer**, any accesses to the widget after nsBaseWidget::DestroyCompositor executes are invalid.
 Any accesses to the compositor between the time the nsBaseWidget::DestroyCompositor runs and the CompositorVsyncScheduler::Observer's destructor runs aren't safe yet a hardware vsync event could occur between these times.
 Since any tasks posted on the Compositor loop after CompositorBridgeParent::DeferredDestroy is posted are invalid, we make sure that no vsync tasks can be posted once CompositorBridgeParent::RecvStop executes and DeferredDestroy is posted on the Compositor thread.
 When the sync call to CompositorBridgeParent::RecvStop executes, we explicitly set the CompositorVsyncScheduler::Observer to null to prevent vsync notifications from occurring.
 If vsync notifications were allowed to occur, since the **CompositorVsyncScheduler::Observer**'s vsync notification executes on the *hardware vsync thread*, it would post a task to the Compositor loop and may execute after CompositorBridgeParent::DeferredDestroy.
 Thus, we explicitly shut down vsync events in the **CompositorVsyncDispatcher** and **CompositorVsyncScheduler::Observer** during nsBaseWidget::Shutdown to prevent any vsync tasks from executing after CompositorBridgeParent::DeferredDestroy.
 
 The **CompositorVsyncDispatcher** may be destroyed on either the *main thread* or *Compositor Thread*, since both the nsBaseWidget and **CompositorVsyncScheduler::Observer** race to destroy on different threads.
 nsBaseWidget is destroyed on the *main thread* and releases a reference to the **CompositorVsyncDispatcher** during destruction.
-The **CompositorVsyncScheduler::Observer** has a race to be destroyed either during CompositorBridgeParent shutdown or from the **GeckoTouchDispatcher** which is destroyed on the main thread with [ClearOnShutdown](http://hg.mozilla.org/mozilla-central/file/21567e9a6e40/xpcom/base/ClearOnShutdown.h#l15).
+The **CompositorVsyncScheduler::Observer** has a race to be destroyed either during CompositorBridgeParent shutdown or from the **GeckoTouchDispatcher** which is destroyed on the main thread with [ClearOnShutdown](https://hg.mozilla.org/mozilla-central/file/21567e9a6e40/xpcom/base/ClearOnShutdown.h#l15).
 Whichever object, the CompositorBridgeParent or the **GeckoTouchDispatcher** is destroyed last will hold the last reference to the **CompositorVsyncDispatcher**, which destroys the object.
 
 #Refresh Driver
-The Refresh Driver is ticked from a [single active timer](http://hg.mozilla.org/mozilla-central/file/ab0490972e1e/layout/base/nsRefreshDriver.cpp#l11).
+The Refresh Driver is ticked from a [single active timer](https://hg.mozilla.org/mozilla-central/file/ab0490972e1e/layout/base/nsRefreshDriver.cpp#l11).
 The assumption is that there are multiple **RefreshDrivers** connected to a single **RefreshTimer**.
 There are two **RefreshTimers**: an active and an inactive **RefreshTimer**.
 Each Tab has its own **RefreshDriver**, which connects to one of the global **RefreshTimers**.
 The **RefreshTimers** execute on the *Main Thread* and tick their connected **RefreshDrivers**.
 We do not want to break this model of multiple **RefreshDrivers** per a set of two global **RefreshTimers**.
 Each **RefreshDriver** switches between the active and inactive **RefreshTimer**.
 
 Instead, we create a new **RefreshTimer**, the **VsyncRefreshTimer** which ticks based on vsync messages.
--- a/gfx/thebes/gfxGDIFont.cpp
+++ b/gfx/thebes/gfxGDIFont.cpp
@@ -456,18 +456,17 @@ gfxGDIFont::FillLogFont(LOGFONTW& aLogFo
             // avoid GDI synthetic bold which occurs when weight
             // specified is >= font data weight + 200
             weight = mNeedsBold ? 700 : 200;
         }
     } else {
         weight = mNeedsBold ? 700 : fe->Weight();
     }
 
-    fe->FillLogFont(&aLogFont, weight, aSize, 
-                    (mAntialiasOption == kAntialiasSubpixel) ? true : false);
+    fe->FillLogFont(&aLogFont, weight, aSize);
 
     // If GDI synthetic italic is wanted, force the lfItalic field to true
     if (aUseGDIFakeItalic) {
         aLogFont.lfItalic = 1;
     }
 }
 
 uint32_t
--- a/gfx/thebes/gfxGDIFontList.cpp
+++ b/gfx/thebes/gfxGDIFontList.cpp
@@ -32,21 +32,16 @@
 #include "mozilla/WindowsVersion.h"
 
 #include <usp10.h>
 
 using namespace mozilla;
 
 #define ROUND(x) floor((x) + 0.5)
 
-
-#ifndef CLEARTYPE_QUALITY
-#define CLEARTYPE_QUALITY 5
-#endif
-
 #define LOG_FONTLIST(args) MOZ_LOG(gfxPlatform::GetLog(eGfxLog_fontlist), \
                                LogLevel::Debug, args)
 #define LOG_FONTLIST_ENABLED() MOZ_LOG_TEST( \
                                    gfxPlatform::GetLog(eGfxLog_fontlist), \
                                    LogLevel::Debug)
 
 #define LOG_CMAPDATA_ENABLED() MOZ_LOG_TEST( \
                                    gfxPlatform::GetLog(eGfxLog_cmapdata), \
@@ -217,26 +212,17 @@ GDIFontEntry::IsSymbolFont()
     // initialize cmap first
     HasCmapTable();
     return mSymbolFont;  
 }
 
 gfxFont *
 GDIFontEntry::CreateFontInstance(const gfxFontStyle* aFontStyle, bool aNeedsBold)
 {
-    bool isXP = !IsVistaOrLater();
-
-    bool useClearType = isXP && !aFontStyle->systemFont &&
-        (gfxWindowsPlatform::GetPlatform()->UseClearTypeAlways() ||
-         (mIsDataUserFont &&
-          gfxWindowsPlatform::GetPlatform()->UseClearTypeForDownloadableFonts()));
-
-    return new gfxGDIFont(this, aFontStyle, aNeedsBold, 
-                          (useClearType ? gfxFont::kAntialiasSubpixel
-                                        : gfxFont::kAntialiasDefault));
+    return new gfxGDIFont(this, aFontStyle, aNeedsBold);
 }
 
 nsresult
 GDIFontEntry::CopyFontTable(uint32_t aTableTag, nsTArray<uint8_t>& aBuffer)
 {
     if (!IsTrueType()) {
         return NS_ERROR_FAILURE;
     }
@@ -258,18 +244,17 @@ GDIFontEntry::CopyFontTable(uint32_t aTa
             return NS_ERROR_OUT_OF_MEMORY;
         }
     }
     return NS_ERROR_FAILURE;
 }
 
 void
 GDIFontEntry::FillLogFont(LOGFONTW *aLogFont,
-                          uint16_t aWeight, gfxFloat aSize,
-                          bool aUseCleartype)
+                          uint16_t aWeight, gfxFloat aSize)
 {
     memcpy(aLogFont, &mLogFont, sizeof(LOGFONTW));
 
     aLogFont->lfHeight = (LONG)-ROUND(aSize);
 
     if (aLogFont->lfHeight == 0) {
         aLogFont->lfHeight = -1;
     }
@@ -285,18 +270,16 @@ GDIFontEntry::FillLogFont(LOGFONTW *aLog
 
     // for non-local() user fonts, we never want to apply italics here;
     // if the face is described as italic, we should use it as-is,
     // and if it's not, but then the element is styled italic, we'll use
     // a cairo transform to create fake italic (oblique)
     if (mIsDataUserFont) {
         aLogFont->lfItalic = 0;
     }
-
-    aLogFont->lfQuality = (aUseCleartype ? CLEARTYPE_QUALITY : DEFAULT_QUALITY);
 }
 
 #define MISSING_GLYPH 0x1F // glyph index returned for missing characters
                            // on WinXP with .fon fonts, but not Type1 (.pfb)
 
 bool 
 GDIFontEntry::TestCharacterMap(uint32_t aCh)
 {
--- a/gfx/thebes/gfxGDIFontList.h
+++ b/gfx/thebes/gfxGDIFontList.h
@@ -107,18 +107,17 @@ class GDIFontEntry : public gfxFontEntry
 {
 public:
     LPLOGFONTW GetLogFont() { return &mLogFont; }
 
     nsresult ReadCMAP(FontInfoData *aFontInfoData = nullptr);
 
     virtual bool IsSymbolFont();
 
-    void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize,
-                     bool aUseCleartype);
+    void FillLogFont(LOGFONTW *aLogFont, uint16_t aWeight, gfxFloat aSize);
 
     static gfxWindowsFontType DetermineFontType(const NEWTEXTMETRICW& metrics, 
                                                 DWORD fontType)
     {
         gfxWindowsFontType feType;
         if (metrics.ntmFlags & NTM_TYPE1)
             feType = GFX_FONT_TYPE_TYPE1;
         else if (metrics.ntmFlags & NTM_PS_OPENTYPE)
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -140,19 +140,16 @@ public:
             "Video memory used by D2D SourceSurfaces.");
 
         return NS_OK;
     }
 };
 
 NS_IMPL_ISUPPORTS(GfxD2DVramReporter, nsIMemoryReporter)
 
-#define GFX_USE_CLEARTYPE_ALWAYS "gfx.font_rendering.cleartype.always_use_for_content"
-#define GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE "gfx.font_rendering.cleartype.use_for_downloadable_fonts"
-
 #define GFX_CLEARTYPE_PARAMS           "gfx.font_rendering.cleartype_params."
 #define GFX_CLEARTYPE_PARAMS_GAMMA     "gfx.font_rendering.cleartype_params.gamma"
 #define GFX_CLEARTYPE_PARAMS_CONTRAST  "gfx.font_rendering.cleartype_params.enhanced_contrast"
 #define GFX_CLEARTYPE_PARAMS_LEVEL     "gfx.font_rendering.cleartype_params.cleartype_level"
 #define GFX_CLEARTYPE_PARAMS_STRUCTURE "gfx.font_rendering.cleartype_params.pixel_structure"
 #define GFX_CLEARTYPE_PARAMS_MODE      "gfx.font_rendering.cleartype_params.rendering_mode"
 
 class GPUAdapterReporter final : public nsIMemoryReporter
@@ -310,19 +307,16 @@ public:
   }
 };
 
 NS_IMPL_ISUPPORTS(D3DSharedTexturesReporter, nsIMemoryReporter)
 
 gfxWindowsPlatform::gfxWindowsPlatform()
   : mRenderMode(RENDER_GDI)
 {
-  mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
-  mUseClearTypeAlways = UNINITIALIZED_VALUE;
-
   /*
    * Initialize COM
    */
   CoInitialize(nullptr);
 
   RegisterStrongMemoryReporter(new GfxD2DVramReporter());
   RegisterStrongMemoryReporter(new GPUAdapterReporter());
   RegisterStrongMemoryReporter(new D3DSharedTexturesReporter());
@@ -972,36 +966,16 @@ gfxWindowsPlatform::GetPlatformCMSOutput
     if (mem_size > 0)
         fprintf(stderr,
                 "ICM profile read from %s successfully\n",
                 NS_ConvertUTF16toUTF8(str).get());
 #endif // DEBUG_tor
 #endif // _WIN32
 }
 
-bool
-gfxWindowsPlatform::UseClearTypeForDownloadableFonts()
-{
-    if (mUseClearTypeForDownloadableFonts == UNINITIALIZED_VALUE) {
-        mUseClearTypeForDownloadableFonts = Preferences::GetBool(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, true);
-    }
-
-    return mUseClearTypeForDownloadableFonts;
-}
-
-bool
-gfxWindowsPlatform::UseClearTypeAlways()
-{
-    if (mUseClearTypeAlways == UNINITIALIZED_VALUE) {
-        mUseClearTypeAlways = Preferences::GetBool(GFX_USE_CLEARTYPE_ALWAYS, false);
-    }
-
-    return mUseClearTypeAlways;
-}
-
 void
 gfxWindowsPlatform::GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion)
 {
     DWORD versInfoSize, vers[4] = {0};
     // version info not available case
     aVersion.AssignLiteral(u"0.0.0.0");
     versInfoSize = GetFileVersionInfoSizeW(aDLLPath, nullptr);
     AutoTArray<BYTE,512> versionInfo;
@@ -1135,24 +1109,17 @@ gfxWindowsPlatform::GetCleartypeParams(n
 
 void
 gfxWindowsPlatform::FontsPrefsChanged(const char *aPref)
 {
     bool clearTextFontCaches = true;
 
     gfxPlatform::FontsPrefsChanged(aPref);
 
-    if (!aPref) {
-        mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
-        mUseClearTypeAlways = UNINITIALIZED_VALUE;
-    } else if (!strcmp(GFX_DOWNLOADABLE_FONTS_USE_CLEARTYPE, aPref)) {
-        mUseClearTypeForDownloadableFonts = UNINITIALIZED_VALUE;
-    } else if (!strcmp(GFX_USE_CLEARTYPE_ALWAYS, aPref)) {
-        mUseClearTypeAlways = UNINITIALIZED_VALUE;
-    } else if (!strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
+    if (aPref && !strncmp(GFX_CLEARTYPE_PARAMS, aPref, strlen(GFX_CLEARTYPE_PARAMS))) {
         SetupClearTypeParams();
     } else {
         clearTextFontCaches = false;
     }
 
     if (clearTextFontCaches) {
         gfxFontCache *fc = gfxFontCache::GetCache();
         if (fc) {
--- a/gfx/thebes/gfxWindowsPlatform.h
+++ b/gfx/thebes/gfxWindowsPlatform.h
@@ -179,21 +179,16 @@ public:
 
     virtual void CompositorUpdated() override;
 
     bool DidRenderingDeviceReset(DeviceResetReason* aResetReason = nullptr) override;
     void SchedulePaintIfDeviceReset() override;
 
     mozilla::gfx::BackendType GetContentBackendFor(mozilla::layers::LayersBackend aLayers) override;
 
-    // ClearType is not always enabled even when available (e.g. Windows XP)
-    // if either of these prefs are enabled and apply, use ClearType rendering
-    bool UseClearTypeForDownloadableFonts();
-    bool UseClearTypeAlways();
-
     static void GetDLLVersion(char16ptr_t aDLLPath, nsAString& aVersion);
 
     // returns ClearType tuning information for each display
     static void GetCleartypeParams(nsTArray<ClearTypeParameterInfo>& aParams);
 
     virtual void FontsPrefsChanged(const char *aPref) override;
 
     void SetupClearTypeParams();
@@ -242,19 +237,16 @@ protected:
 
     void ImportGPUDeviceData(const mozilla::gfx::GPUDeviceData& aData) override;
     void ImportContentDeviceData(const mozilla::gfx::ContentDeviceData& aData) override;
     void BuildContentDeviceData(mozilla::gfx::ContentDeviceData* aOut) override;
 
 protected:
     RenderMode mRenderMode;
 
-    int8_t mUseClearTypeForDownloadableFonts;
-    int8_t mUseClearTypeAlways;
-
 private:
     void Init();
     void InitAcceleration() override;
 
     void InitializeDevices();
     void InitializeD3D11();
     void InitializeD2D();
     bool InitDWriteSupport();
--- a/js/src/jit/BaselineCacheIRCompiler.cpp
+++ b/js/src/jit/BaselineCacheIRCompiler.cpp
@@ -1274,16 +1274,17 @@ BaselineCacheIRCompiler::init(CacheKind 
 
     switch (kind) {
       case CacheKind::GetProp:
         MOZ_ASSERT(numInputs == 1);
         allocator.initInputLocation(0, R0);
         break;
       case CacheKind::GetElem:
       case CacheKind::SetProp:
+      case CacheKind::In:
         MOZ_ASSERT(numInputs == 2);
         allocator.initInputLocation(0, R0);
         allocator.initInputLocation(1, R1);
         break;
       case CacheKind::SetElem:
         MOZ_ASSERT(numInputs == 3);
         allocator.initInputLocation(0, R0);
         allocator.initInputLocation(1, R1);
@@ -1318,21 +1319,25 @@ jit::AttachBaselineCacheIRStub(JSContext
 
     if (writer.failed())
         return nullptr;
 
     // Just a sanity check: the caller should ensure we don't attach an
     // unlimited number of stubs.
     MOZ_ASSERT(stub->numOptimizedStubs() < MaxOptimizedCacheIRStubs);
 
-    enum class CacheIRStubKind { Monitored, Updated };
+    enum class CacheIRStubKind { Regular, Monitored, Updated };
 
     uint32_t stubDataOffset;
     CacheIRStubKind stubKind;
     switch (kind) {
+      case CacheKind::In:
+        stubDataOffset = sizeof(ICCacheIR_Regular);
+        stubKind = CacheIRStubKind::Regular;
+        break;
       case CacheKind::GetProp:
       case CacheKind::GetElem:
       case CacheKind::GetName:
         stubDataOffset = sizeof(ICCacheIR_Monitored);
         stubKind = CacheIRStubKind::Monitored;
         break;
       case CacheKind::SetProp:
       case CacheKind::SetElem:
@@ -1375,16 +1380,26 @@ jit::AttachBaselineCacheIRStub(JSContext
     MOZ_ASSERT(stubInfo);
     MOZ_ASSERT(stubInfo->stubDataSize() == writer.stubDataSize());
 
     // Ensure we don't attach duplicate stubs. This can happen if a stub failed
     // for some reason and the IR generator doesn't check for exactly the same
     // conditions.
     for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
         switch (stubKind) {
+          case CacheIRStubKind::Regular: {
+            if (!iter->isCacheIR_Regular())
+                continue;
+            auto otherStub = iter->toCacheIR_Regular();
+            if (otherStub->stubInfo() != stubInfo)
+                continue;
+            if (!writer.stubDataEqualsMaybeUpdate(otherStub->stubDataStart()))
+                continue;
+            break;
+          }
           case CacheIRStubKind::Monitored: {
             if (!iter->isCacheIR_Monitored())
                 continue;
             auto otherStub = iter->toCacheIR_Monitored();
             if (otherStub->stubInfo() != stubInfo)
                 continue;
             if (!writer.stubDataEqualsMaybeUpdate(otherStub->stubDataStart()))
                 continue;
@@ -1414,16 +1429,22 @@ jit::AttachBaselineCacheIRStub(JSContext
 
     ICStubSpace* stubSpace = ICStubCompiler::StubSpaceForStub(stubInfo->makesGCCalls(),
                                                               outerScript, engine);
     void* newStubMem = stubSpace->alloc(bytesNeeded);
     if (!newStubMem)
         return nullptr;
 
     switch (stubKind) {
+      case CacheIRStubKind::Regular: {
+        auto newStub = new(newStubMem) ICCacheIR_Regular(code, stubInfo);
+        writer.copyStubData(newStub->stubDataStart());
+        stub->addNewStub(newStub);
+        return newStub;
+      }
       case CacheIRStubKind::Monitored: {
         ICStub* monitorStub =
             stub->toMonitoredFallbackStub()->fallbackMonitorStub()->firstMonitorStub();
         auto newStub = new(newStubMem) ICCacheIR_Monitored(code, monitorStub, stubInfo);
         writer.copyStubData(newStub->stubDataStart());
         stub->addNewStub(newStub);
         return newStub;
       }
@@ -1438,16 +1459,22 @@ jit::AttachBaselineCacheIRStub(JSContext
         return newStub;
       }
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 uint8_t*
+ICCacheIR_Regular::stubDataStart()
+{
+    return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
+}
+
+uint8_t*
 ICCacheIR_Monitored::stubDataStart()
 {
     return reinterpret_cast<uint8_t*>(this) + stubInfo_->stubDataOffset();
 }
 
 uint8_t*
 ICCacheIR_Updated::stubDataStart()
 {
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -732,33 +732,16 @@ ICToNumber_Fallback::Compiler::generateS
 
     return tailCallVM(DoToNumberFallbackInfo, masm);
 }
 
 //
 // GetElem_Fallback
 //
 
-static bool
-IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId idp)
-{
-    if (!key.isString())
-        return false;
-
-    // Convert to interned property name.
-    if (!ValueToId<CanGC>(cx, key, idp))
-        return false;
-
-    uint32_t dummy;
-    if (!JSID_IS_ATOM(idp) || JSID_TO_ATOM(idp)->isIndex(&dummy))
-        return false;
-
-    return true;
-}
-
 bool
 IsPrimitiveArrayTypedObject(JSObject* obj)
 {
     if (!obj->is<TypedObject>())
         return false;
     TypeDescr& descr = obj->as<TypedObject>().typeDescr();
     return descr.is<ArrayTypeDescr>() &&
            descr.as<ArrayTypeDescr>().elementType().is<ScalarTypeDescr>();
@@ -785,24 +768,16 @@ TypedThingRequiresFloatingPoint(JSObject
 {
     Scalar::Type type = TypedThingElementType(obj);
     return type == Scalar::Uint32 ||
            type == Scalar::Float32 ||
            type == Scalar::Float64;
 }
 
 static bool
-IsNativeDenseElementAccess(HandleObject obj, HandleValue key)
-{
-    if (obj->isNative() && key.isInt32() && key.toInt32() >= 0 && !obj->is<TypedArrayObject>())
-        return true;
-    return false;
-}
-
-static bool
 IsNativeOrUnboxedDenseElementAccess(HandleObject obj, HandleValue key)
 {
     if (!obj->isNative() && !obj->is<UnboxedArrayObject>())
         return false;
     if (key.isInt32() && key.toInt32() >= 0 && !obj->is<TypedArrayObject>())
         return true;
     return false;
 }
@@ -1966,156 +1941,55 @@ ICSetElem_TypedArray::Compiler::generate
     return true;
 }
 
 //
 // In_Fallback
 //
 
 static bool
-TryAttachDenseInStub(JSContext* cx, HandleScript outerScript, ICIn_Fallback* stub,
-                     HandleValue key, HandleObject obj, bool* attached)
-{
-    MOZ_ASSERT(!*attached);
-
-    if (!IsNativeDenseElementAccess(obj, key))
-        return true;
-
-    JitSpew(JitSpew_BaselineIC, "  Generating In(Native[Int32] dense) stub");
-    ICIn_Dense::Compiler compiler(cx, obj->as<NativeObject>().lastProperty());
-    ICStub* denseStub = compiler.getStub(compiler.getStubSpace(outerScript));
-    if (!denseStub)
-        return false;
-
-    *attached = true;
-    stub->addNewStub(denseStub);
-    return true;
-}
-
-static bool
-TryAttachNativeInStub(JSContext* cx, HandleScript outerScript, ICIn_Fallback* stub,
-                      HandleValue key, HandleObject obj, bool* attached)
-{
-    MOZ_ASSERT(!*attached);
-
-    RootedId id(cx);
-    if (!IsOptimizableElementPropertyName(cx, key, &id))
-        return true;
-
-    RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
-    Rooted<PropertyResult> prop(cx);
-    RootedObject holder(cx);
-    if (!LookupPropertyPure(cx, obj, id, holder.address(), prop.address()))
-        return true;
-
-    if (prop.isNonNativeProperty()) {
-        MOZ_ASSERT(!IsCacheableProtoChain(obj, holder, false));
-        return true;
-    }
-
-    RootedShape shape(cx, prop.maybeShape());
-    if (IsCacheableGetPropReadSlot(obj, holder, shape)) {
-        ICStub::Kind kind = (obj == holder) ? ICStub::In_Native
-                                            : ICStub::In_NativePrototype;
-        JitSpew(JitSpew_BaselineIC, "  Generating In(Native %s) stub",
-                    (obj == holder) ? "direct" : "prototype");
-        ICInNativeCompiler compiler(cx, kind, obj, holder, name);
-        ICStub* newStub = compiler.getStub(compiler.getStubSpace(outerScript));
-        if (!newStub)
-            return false;
-
-        *attached = true;
-        stub->addNewStub(newStub);
-        return true;
-    }
-
-    return true;
-}
-
-static bool
-TryAttachNativeInDoesNotExistStub(JSContext* cx, HandleScript outerScript,
-                                  ICIn_Fallback* stub, HandleValue key,
-                                  HandleObject obj, bool* attached)
-{
-    MOZ_ASSERT(!*attached);
-
-    RootedId id(cx);
-    if (!IsOptimizableElementPropertyName(cx, key, &id))
-        return true;
-
-    // Check if does-not-exist can be confirmed on property.
-    RootedPropertyName name(cx, JSID_TO_ATOM(id)->asPropertyName());
-    RootedObject lastProto(cx);
-    size_t protoChainDepth = SIZE_MAX;
-    if (!CheckHasNoSuchProperty(cx, obj.get(), id, lastProto.address(), &protoChainDepth))
-        return true;
-    MOZ_ASSERT(protoChainDepth < SIZE_MAX);
-
-    if (protoChainDepth > ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH)
-        return true;
-
-    // Confirmed no-such-property. Add stub.
-    JitSpew(JitSpew_BaselineIC, "  Generating In_NativeDoesNotExist stub");
-    ICInNativeDoesNotExistCompiler compiler(cx, obj, name, protoChainDepth);
-    ICStub* newStub = compiler.getStub(compiler.getStubSpace(outerScript));
-    if (!newStub)
-        return false;
-
-    *attached = true;
-    stub->addNewStub(newStub);
-    return true;
-}
-
-static bool
 DoInFallback(JSContext* cx, BaselineFrame* frame, ICIn_Fallback* stub_,
              HandleValue key, HandleValue objValue, MutableHandleValue res)
 {
     // This fallback stub may trigger debug mode toggling.
     DebugModeOSRVolatileStub<ICIn_Fallback*> stub(frame, stub_);
 
     FallbackICSpew(cx, stub, "In");
 
     if (!objValue.isObject()) {
         ReportValueError(cx, JSMSG_IN_NOT_OBJECT, -1, objValue, nullptr);
         return false;
     }
 
+    bool attached = false;
+
+    if (stub->numOptimizedStubs() >= ICIn_Fallback::MAX_OPTIMIZED_STUBS)
+        attached = true;
+
     RootedObject obj(cx, &objValue.toObject());
+    jsbytecode* pc = stub->icEntry()->pc(frame->script());
+
+    if (!attached && !JitOptions.disableCacheIR) {
+        ICStubEngine engine = ICStubEngine::Baseline;
+        InIRGenerator gen(cx, pc, key, obj);
+        if (gen.tryAttachStub()) {
+            ICStub* newStub = AttachBaselineCacheIRStub(cx, gen.writerRef(), gen.cacheKind(),
+                                                        engine, frame->script(), stub);
+            if (newStub) {
+                JitSpew(JitSpew_BaselineIC, "  Attached CacheIR stub");
+                attached = true;
+            }
+        }
+    }
 
     bool cond = false;
     if (!OperatorIn(cx, key, obj, &cond))
         return false;
     res.setBoolean(cond);
 
-    if (stub.invalid())
-        return true;
-
-    if (stub->numOptimizedStubs() >= ICIn_Fallback::MAX_OPTIMIZED_STUBS)
-        return true;
-
-    if (obj->isNative()) {
-        RootedScript script(cx, frame->script());
-        bool attached = false;
-        if (cond) {
-            if (!TryAttachDenseInStub(cx, script, stub, key, obj, &attached))
-                return false;
-            if (attached)
-                return true;
-            if (!TryAttachNativeInStub(cx, script, stub, key, obj, &attached))
-                return false;
-            if (attached)
-                return true;
-        } else {
-            if (!TryAttachNativeInDoesNotExistStub(cx, script, stub, key, obj, &attached))
-                return false;
-            if (attached)
-                return true;
-        }
-    }
-
     return true;
 }
 
 typedef bool (*DoInFallbackFn)(JSContext*, BaselineFrame*, ICIn_Fallback*, HandleValue,
                                HandleValue, MutableHandleValue);
 static const VMFunction DoInFallbackInfo =
     FunctionInfo<DoInFallbackFn>(DoInFallback, "DoInFallback", TailCall, PopValues(2));
 
@@ -2134,193 +2008,16 @@ ICIn_Fallback::Compiler::generateStubCod
     masm.pushValue(R1);
     masm.pushValue(R0);
     masm.push(ICStubReg);
     pushStubPayload(masm, R0.scratchReg());
 
     return tailCallVM(DoInFallbackInfo, masm);
 }
 
-bool
-ICInNativeCompiler::generateStubCode(MacroAssembler& masm)
-{
-    MOZ_ASSERT(engine_ == Engine::Baseline);
-
-    Label failure, failurePopR0Scratch;
-
-    masm.branchTestString(Assembler::NotEqual, R0, &failure);
-    masm.branchTestObject(Assembler::NotEqual, R1, &failure);
-
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
-    Register scratch = regs.takeAny();
-
-    // Check key identity.
-    Register strExtract = masm.extractString(R0, ExtractTemp0);
-    masm.loadPtr(Address(ICStubReg, ICInNativeStub::offsetOfName()), scratch);
-    masm.branchPtr(Assembler::NotEqual, strExtract, scratch, &failure);
-
-    // Unbox and shape guard object.
-    Register objReg = masm.extractObject(R1, ExtractTemp0);
-    masm.loadPtr(Address(ICStubReg, ICInNativeStub::offsetOfShape()), scratch);
-    masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
-
-    if (kind == ICStub::In_NativePrototype) {
-        // Shape guard holder. Use R0 scrachReg since on x86 there're not enough registers.
-        Register holderReg = R0.scratchReg();
-        masm.push(R0.scratchReg());
-        masm.loadPtr(Address(ICStubReg, ICIn_NativePrototype::offsetOfHolder()),
-                     holderReg);
-        masm.loadPtr(Address(ICStubReg, ICIn_NativePrototype::offsetOfHolderShape()),
-                     scratch);
-        masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failurePopR0Scratch);
-        masm.addToStackPtr(Imm32(sizeof(size_t)));
-    }
-
-    masm.moveValue(BooleanValue(true), R0);
-
-    EmitReturnFromIC(masm);
-
-    // Failure case - jump to next stub
-    masm.bind(&failurePopR0Scratch);
-    masm.pop(R0.scratchReg());
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
-ICStub*
-ICInNativeDoesNotExistCompiler::getStub(ICStubSpace* space)
-{
-    Rooted<ShapeVector> shapes(cx, ShapeVector(cx));
-    if (!shapes.append(obj_->as<NativeObject>().lastProperty()))
-        return nullptr;
-
-    if (!GetProtoShapes(obj_, protoChainDepth_, &shapes))
-        return nullptr;
-
-    JS_STATIC_ASSERT(ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH == 8);
-
-    ICStub* stub = nullptr;
-    switch (protoChainDepth_) {
-      case 0: stub = getStubSpecific<0>(space, shapes); break;
-      case 1: stub = getStubSpecific<1>(space, shapes); break;
-      case 2: stub = getStubSpecific<2>(space, shapes); break;
-      case 3: stub = getStubSpecific<3>(space, shapes); break;
-      case 4: stub = getStubSpecific<4>(space, shapes); break;
-      case 5: stub = getStubSpecific<5>(space, shapes); break;
-      case 6: stub = getStubSpecific<6>(space, shapes); break;
-      case 7: stub = getStubSpecific<7>(space, shapes); break;
-      case 8: stub = getStubSpecific<8>(space, shapes); break;
-      default: MOZ_CRASH("ProtoChainDepth too high.");
-    }
-    if (!stub)
-        return nullptr;
-    return stub;
-}
-
-bool
-ICInNativeDoesNotExistCompiler::generateStubCode(MacroAssembler& masm)
-{
-    MOZ_ASSERT(engine_ == Engine::Baseline);
-
-    Label failure, failurePopR0Scratch;
-
-    masm.branchTestString(Assembler::NotEqual, R0, &failure);
-    masm.branchTestObject(Assembler::NotEqual, R1, &failure);
-
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
-    Register scratch = regs.takeAny();
-
-#ifdef DEBUG
-    // Ensure that protoChainDepth_ matches the protoChainDepth stored on the stub.
-    {
-        Label ok;
-        masm.load16ZeroExtend(Address(ICStubReg, ICStub::offsetOfExtra()), scratch);
-        masm.branch32(Assembler::Equal, scratch, Imm32(protoChainDepth_), &ok);
-        masm.assumeUnreachable("Non-matching proto chain depth on stub.");
-        masm.bind(&ok);
-    }
-#endif // DEBUG
-
-    // Check key identity.
-    Register strExtract = masm.extractString(R0, ExtractTemp0);
-    masm.loadPtr(Address(ICStubReg, ICIn_NativeDoesNotExist::offsetOfName()), scratch);
-    masm.branchPtr(Assembler::NotEqual, strExtract, scratch, &failure);
-
-    // Unbox and guard against old shape.
-    Register objReg = masm.extractObject(R1, ExtractTemp0);
-    masm.loadPtr(Address(ICStubReg, ICIn_NativeDoesNotExist::offsetOfShape(0)),
-                 scratch);
-    masm.branchTestObjShape(Assembler::NotEqual, objReg, scratch, &failure);
-
-    // Check the proto chain.
-    Register protoReg = R0.scratchReg();
-    masm.push(R0.scratchReg());
-    for (size_t i = 0; i < protoChainDepth_; ++i) {
-        masm.loadObjProto(i == 0 ? objReg : protoReg, protoReg);
-        masm.branchTestPtr(Assembler::Zero, protoReg, protoReg, &failurePopR0Scratch);
-        size_t shapeOffset = ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(i + 1);
-        masm.loadPtr(Address(ICStubReg, shapeOffset), scratch);
-        masm.branchTestObjShape(Assembler::NotEqual, protoReg, scratch, &failurePopR0Scratch);
-    }
-    masm.addToStackPtr(Imm32(sizeof(size_t)));
-
-    // Shape and type checks succeeded, ok to proceed.
-    masm.moveValue(BooleanValue(false), R0);
-
-    EmitReturnFromIC(masm);
-
-    masm.bind(&failurePopR0Scratch);
-    masm.pop(R0.scratchReg());
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
-bool
-ICIn_Dense::Compiler::generateStubCode(MacroAssembler& masm)
-{
-    MOZ_ASSERT(engine_ == Engine::Baseline);
-
-    Label failure;
-
-    masm.branchTestInt32(Assembler::NotEqual, R0, &failure);
-    masm.branchTestObject(Assembler::NotEqual, R1, &failure);
-
-    AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
-    Register scratch = regs.takeAny();
-
-    // Unbox and shape guard object.
-    Register obj = masm.extractObject(R1, ExtractTemp0);
-    masm.loadPtr(Address(ICStubReg, ICIn_Dense::offsetOfShape()), scratch);
-    masm.branchTestObjShape(Assembler::NotEqual, obj, scratch, &failure);
-
-    // Load obj->elements.
-    masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
-
-    // Unbox key and bounds check.
-    Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
-    Register key = masm.extractInt32(R0, ExtractTemp0);
-    masm.branch32(Assembler::BelowOrEqual, initLength, key, &failure);
-
-    // Hole check.
-    JS_STATIC_ASSERT(sizeof(Value) == 8);
-    BaseIndex element(scratch, key, TimesEight);
-    masm.branchTestMagic(Assembler::Equal, element, &failure);
-
-    masm.moveValue(BooleanValue(true), R0);
-
-    EmitReturnFromIC(masm);
-
-    // Failure case - jump to next stub
-    masm.bind(&failure);
-    EmitStubGuardFailure(masm);
-    return true;
-}
-
 static bool
 DoGetNameFallback(JSContext* cx, BaselineFrame* frame, ICGetName_Fallback* stub_,
                   HandleObject envChain, MutableHandleValue res)
 {
     SharedStubInfo info(cx, frame, stub_->icEntry());
 
     // This fallback stub may trigger debug mode toggling.
     DebugModeOSRVolatileStub<ICGetName_Fallback*> stub(frame, stub_);
@@ -5610,74 +5307,16 @@ ICSetElem_TypedArray::ICSetElem_TypedArr
   : ICStub(SetElem_TypedArray, stubCode),
     shape_(shape)
 {
     extra_ = uint8_t(type);
     MOZ_ASSERT(extra_ == type);
     extra_ |= (static_cast<uint16_t>(expectOutOfBounds) << 8);
 }
 
-ICInNativeStub::ICInNativeStub(ICStub::Kind kind, JitCode* stubCode, HandleShape shape,
-                               HandlePropertyName name)
-  : ICStub(kind, stubCode),
-    shape_(shape),
-    name_(name)
-{ }
-
-ICIn_NativePrototype::ICIn_NativePrototype(JitCode* stubCode, HandleShape shape,
-                                           HandlePropertyName name, HandleObject holder,
-                                           HandleShape holderShape)
-  : ICInNativeStub(In_NativePrototype, stubCode, shape, name),
-    holder_(holder),
-    holderShape_(holderShape)
-{ }
-
-ICIn_NativeDoesNotExist::ICIn_NativeDoesNotExist(JitCode* stubCode, size_t protoChainDepth,
-                                                 HandlePropertyName name)
-  : ICStub(In_NativeDoesNotExist, stubCode),
-    name_(name)
-{
-    MOZ_ASSERT(protoChainDepth <= MAX_PROTO_CHAIN_DEPTH);
-    extra_ = protoChainDepth;
-}
-
-/* static */ size_t
-ICIn_NativeDoesNotExist::offsetOfShape(size_t idx)
-{
-    MOZ_ASSERT(ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(idx) ==
-               ICIn_NativeDoesNotExistImpl<
-                    ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH>::offsetOfShape(idx));
-    return ICIn_NativeDoesNotExistImpl<0>::offsetOfShape(idx);
-}
-
-template <size_t ProtoChainDepth>
-ICIn_NativeDoesNotExistImpl<ProtoChainDepth>::ICIn_NativeDoesNotExistImpl(
-        JitCode* stubCode, Handle<ShapeVector> shapes, HandlePropertyName name)
-  : ICIn_NativeDoesNotExist(stubCode, ProtoChainDepth, name)
-{
-    MOZ_ASSERT(shapes.length() == NumShapes);
-    for (size_t i = 0; i < NumShapes; i++)
-        shapes_[i].init(shapes[i]);
-}
-
-ICInNativeDoesNotExistCompiler::ICInNativeDoesNotExistCompiler(
-        JSContext* cx, HandleObject obj, HandlePropertyName name, size_t protoChainDepth)
-  : ICStubCompiler(cx, ICStub::In_NativeDoesNotExist, Engine::Baseline),
-    obj_(cx, obj),
-    name_(cx, name),
-    protoChainDepth_(protoChainDepth)
-{
-    MOZ_ASSERT(protoChainDepth_ <= ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH);
-}
-
-ICIn_Dense::ICIn_Dense(JitCode* stubCode, HandleShape shape)
-  : ICStub(In_Dense, stubCode),
-    shape_(shape)
-{ }
-
 
 ICGetIntrinsic_Constant::ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value)
   : ICStub(GetIntrinsic_Constant, stubCode),
     value_(value)
 { }
 
 ICGetIntrinsic_Constant::~ICGetIntrinsic_Constant()
 { }
--- a/js/src/jit/BaselineIC.h
+++ b/js/src/jit/BaselineIC.h
@@ -708,235 +708,16 @@ class ICIn_Fallback : public ICFallbackS
         { }
 
         ICStub* getStub(ICStubSpace* space) {
             return newStub<ICIn_Fallback>(space, getStubCode());
         }
     };
 };
 
-// Base class for In_Native and In_NativePrototype stubs.
-class ICInNativeStub : public ICStub
-{
-    GCPtrShape shape_;
-    GCPtrPropertyName name_;
-
-  protected:
-    ICInNativeStub(ICStub::Kind kind, JitCode* stubCode, HandleShape shape,
-                   HandlePropertyName name);
-
-  public:
-    GCPtrShape& shape() {
-        return shape_;
-    }
-    static size_t offsetOfShape() {
-        return offsetof(ICInNativeStub, shape_);
-    }
-
-    GCPtrPropertyName& name() {
-        return name_;
-    }
-    static size_t offsetOfName() {
-        return offsetof(ICInNativeStub, name_);
-    }
-};
-
-// Stub for confirming an own property on a native object.
-class ICIn_Native : public ICInNativeStub
-{
-    friend class ICStubSpace;
-
-    ICIn_Native(JitCode* stubCode, HandleShape shape, HandlePropertyName name)
-      : ICInNativeStub(In_Native, stubCode, shape, name)
-    {}
-};
-
-// Stub for confirming a property on a native object's prototype. Note that due to
-// the shape teleporting optimization, we only have to guard on the object's shape
-// and the holder's shape.
-class ICIn_NativePrototype : public ICInNativeStub
-{
-    friend class ICStubSpace;
-
-    GCPtrObject holder_;
-    GCPtrShape holderShape_;
-
-    ICIn_NativePrototype(JitCode* stubCode, HandleShape shape, HandlePropertyName name,
-                         HandleObject holder, HandleShape holderShape);
-
-  public:
-    GCPtrObject& holder() {
-        return holder_;
-    }
-    GCPtrShape& holderShape() {
-        return holderShape_;
-    }
-    static size_t offsetOfHolder() {
-        return offsetof(ICIn_NativePrototype, holder_);
-    }
-    static size_t offsetOfHolderShape() {
-        return offsetof(ICIn_NativePrototype, holderShape_);
-    }
-};
-
-// Compiler for In_Native and In_NativePrototype stubs.
-class ICInNativeCompiler : public ICStubCompiler
-{
-    RootedObject obj_;
-    RootedObject holder_;
-    RootedPropertyName name_;
-
-    MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
-
-  public:
-    ICInNativeCompiler(JSContext* cx, ICStub::Kind kind, HandleObject obj, HandleObject holder,
-                       HandlePropertyName name)
-      : ICStubCompiler(cx, kind, Engine::Baseline),
-        obj_(cx, obj),
-        holder_(cx, holder),
-        name_(cx, name)
-    {}
-
-    ICStub* getStub(ICStubSpace* space) {
-        RootedShape shape(cx, obj_->as<NativeObject>().lastProperty());
-        if (kind == ICStub::In_Native) {
-            MOZ_ASSERT(obj_ == holder_);
-            return newStub<ICIn_Native>(space, getStubCode(), shape, name_);
-        }
-
-        MOZ_ASSERT(obj_ != holder_);
-        MOZ_ASSERT(kind == ICStub::In_NativePrototype);
-        RootedShape holderShape(cx, holder_->as<NativeObject>().lastProperty());
-        return newStub<ICIn_NativePrototype>(space, getStubCode(), shape, name_, holder_,
-                                             holderShape);
-    }
-};
-
-template <size_t ProtoChainDepth> class ICIn_NativeDoesNotExistImpl;
-
-class ICIn_NativeDoesNotExist : public ICStub
-{
-    friend class ICStubSpace;
-
-    GCPtrPropertyName name_;
-
-  public:
-    static const size_t MAX_PROTO_CHAIN_DEPTH = 8;
-
-  protected:
-    ICIn_NativeDoesNotExist(JitCode* stubCode, size_t protoChainDepth,
-                            HandlePropertyName name);
-
-  public:
-    size_t protoChainDepth() const {
-        MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH);
-        return extra_;
-    }
-    GCPtrPropertyName& name() {
-        return name_;
-    }
-
-    template <size_t ProtoChainDepth>
-    ICIn_NativeDoesNotExistImpl<ProtoChainDepth>* toImpl() {
-        MOZ_ASSERT(ProtoChainDepth == protoChainDepth());
-        return static_cast<ICIn_NativeDoesNotExistImpl<ProtoChainDepth>*>(this);
-    }
-
-    static size_t offsetOfShape(size_t idx);
-    static size_t offsetOfName() {
-        return offsetof(ICIn_NativeDoesNotExist, name_);
-    }
-};
-
-template <size_t ProtoChainDepth>
-class ICIn_NativeDoesNotExistImpl : public ICIn_NativeDoesNotExist
-{
-    friend class ICStubSpace;
-
-  public:
-    static const size_t MAX_PROTO_CHAIN_DEPTH = 8;
-    static const size_t NumShapes = ProtoChainDepth + 1;
-
-  private:
-    mozilla::Array<GCPtrShape, NumShapes> shapes_;
-
-    ICIn_NativeDoesNotExistImpl(JitCode* stubCode, Handle<ShapeVector> shapes,
-                                HandlePropertyName name);
-
-  public:
-    void traceShapes(JSTracer* trc) {
-        for (size_t i = 0; i < NumShapes; i++)
-            TraceEdge(trc, &shapes_[i], "baseline-innativedoesnotexist-stub-shape");
-    }
-
-    static size_t offsetOfShape(size_t idx) {
-        return offsetof(ICIn_NativeDoesNotExistImpl, shapes_) + (idx * sizeof(GCPtrShape));
-    }
-};
-
-class ICInNativeDoesNotExistCompiler : public ICStubCompiler
-{
-    RootedObject obj_;
-    RootedPropertyName name_;
-    size_t protoChainDepth_;
-
-  protected:
-    virtual int32_t getKey() const {
-        return static_cast<int32_t>(engine_) |
-              (static_cast<int32_t>(kind) << 1) |
-              (static_cast<int32_t>(protoChainDepth_) << 17);
-    }
-
-    MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
-
-  public:
-    ICInNativeDoesNotExistCompiler(JSContext* cx, HandleObject obj, HandlePropertyName name,
-                                   size_t protoChainDepth);
-
-    template <size_t ProtoChainDepth>
-    ICStub* getStubSpecific(ICStubSpace* space, Handle<ShapeVector> shapes) {
-        return newStub<ICIn_NativeDoesNotExistImpl<ProtoChainDepth>>(space, getStubCode(), shapes,
-                                                                     name_);}
-
-    ICStub* getStub(ICStubSpace* space);
-};
-
-class ICIn_Dense : public ICStub
-{
-    friend class ICStubSpace;
-
-    GCPtrShape shape_;
-
-    ICIn_Dense(JitCode* stubCode, HandleShape shape);
-
-  public:
-    GCPtrShape& shape() {
-        return shape_;
-    }
-    static size_t offsetOfShape() {
-        return offsetof(ICIn_Dense, shape_);
-    }
-
-    class Compiler : public ICStubCompiler {
-      RootedShape shape_;
-
-      protected:
-        MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
-
-      public:
-        Compiler(JSContext* cx, Shape* shape)
-          : ICStubCompiler(cx, ICStub::In_Dense, Engine::Baseline),
-            shape_(cx, shape)
-        {}
-
-        ICStub* getStub(ICStubSpace* space) {
-            return newStub<ICIn_Dense>(space, getStubCode(), shape_);
-        }
-    };
-};
 
 // GetName
 //      JSOP_GETNAME
 //      JSOP_GETGNAME
 class ICGetName_Fallback : public ICMonitoredFallbackStub
 {
     friend class ICStubSpace;
 
--- a/js/src/jit/BaselineICList.h
+++ b/js/src/jit/BaselineICList.h
@@ -51,20 +51,16 @@ namespace jit {
     _(GetElem_Fallback)                          \
                                                  \
     _(SetElem_Fallback)                          \
     _(SetElem_DenseOrUnboxedArray)               \
     _(SetElem_DenseOrUnboxedArrayAdd)            \
     _(SetElem_TypedArray)                        \
                                                  \
     _(In_Fallback)                               \
-    _(In_Native)                                 \
-    _(In_NativePrototype)                        \
-    _(In_NativeDoesNotExist)                     \
-    _(In_Dense)                                  \
                                                  \
     _(GetName_Fallback)                          \
                                                  \
     _(BindName_Fallback)                         \
                                                  \
     _(GetIntrinsic_Fallback)                     \
     _(GetIntrinsic_Constant)                     \
                                                  \
--- a/js/src/jit/CacheIR.cpp
+++ b/js/src/jit/CacheIR.cpp
@@ -360,56 +360,65 @@ TestMatchingReceiver(CacheIRWriter& writ
     } else {
         Shape* shape = obj->maybeShape();
         MOZ_ASSERT(shape);
         writer.guardShape(objId, shape);
     }
 }
 
 static void
-EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
-                   Shape* shape, ObjOperandId objId)
+EmitReadSlotGuard(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
+                  Shape* shape, ObjOperandId objId, Maybe<ObjOperandId>* holderId)
 {
     Maybe<ObjOperandId> expandoId;
     TestMatchingReceiver(writer, obj, shape, objId, &expandoId);
 
-    ObjOperandId holderId;
     if (obj != holder) {
         GeneratePrototypeGuards(writer, obj, holder, objId);
 
         if (holder) {
             // Guard on the holder's shape.
-            holderId = writer.loadObject(holder);
-            writer.guardShape(holderId, holder->as<NativeObject>().lastProperty());
+            holderId->emplace(writer.loadObject(holder));
+            writer.guardShape(holderId->ref(), holder->as<NativeObject>().lastProperty());
         } else {
             // The property does not exist. Guard on everything in the prototype
             // chain. This is guaranteed to see only Native objects because of
             // CanAttachNativeGetProp().
             JSObject* proto = obj->taggedProto().toObjectOrNull();
             ObjOperandId lastObjId = objId;
             while (proto) {
                 ObjOperandId protoId = writer.loadProto(lastObjId);
                 writer.guardShape(protoId, proto->as<NativeObject>().lastProperty());
                 proto = proto->staticPrototype();
                 lastObjId = protoId;
             }
         }
     } else if (obj->is<UnboxedPlainObject>()) {
-        holder = obj->as<UnboxedPlainObject>().maybeExpando();
-        holderId = *expandoId;
+        holderId->emplace(*expandoId);
     } else {
-        holderId = objId;
+        holderId->emplace(objId);
     }
+}
+
+static void
+EmitReadSlotResult(CacheIRWriter& writer, JSObject* obj, JSObject* holder,
+                   Shape* shape, ObjOperandId objId)
+{
+    Maybe<ObjOperandId> holderId;
+    EmitReadSlotGuard(writer, obj, holder, shape, objId, &holderId);
+
+    if (obj == holder && obj->is<UnboxedPlainObject>())
+        holder = obj->as<UnboxedPlainObject>().maybeExpando();
 
     // Slot access.
     if (holder) {
-        MOZ_ASSERT(holderId.valid());
-        EmitLoadSlotResult(writer, holderId, &holder->as<NativeObject>(), shape);
+        MOZ_ASSERT(holderId->valid());
+        EmitLoadSlotResult(writer, *holderId, &holder->as<NativeObject>(), shape);
     } else {
-        MOZ_ASSERT(!holderId.valid());
+        MOZ_ASSERT(holderId.isNothing());
         writer.loadUndefinedResult();
     }
 }
 
 static void
 EmitReadSlotReturn(CacheIRWriter& writer, JSObject*, JSObject* holder, Shape* shape)
 {
     // Slot access.
@@ -1558,16 +1567,113 @@ GetNameIRGenerator::tryAttachEnvironment
         size_t dynamicSlotOffset = holder->dynamicSlotIndex(shape->slot()) * sizeof(Value);
         writer.loadEnvironmentDynamicSlotResult(lastObjId, dynamicSlotOffset);
     }
 
     writer.typeMonitorResult();
     return true;
 }
 
+InIRGenerator::InIRGenerator(JSContext* cx, jsbytecode* pc, HandleValue key, HandleObject obj)
+  : IRGenerator(cx, pc, CacheKind::In),
+    key_(key), obj_(obj)
+{ }
+
+bool
+InIRGenerator::tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
+                                HandleObject obj, ObjOperandId objId)
+{
+    if (!obj->isNative())
+        return false;
+    if (!obj->as<NativeObject>().containsDenseElement(index))
+        return false;
+
+    writer.guardShape(objId, obj->as<NativeObject>().lastProperty());
+    writer.loadDenseElementExistsResult(objId, indexId);
+    writer.returnFromIC();
+    return true;
+}
+
+bool
+InIRGenerator::tryAttachNativeIn(HandleId key, ValOperandId keyId,
+                                 HandleObject obj, ObjOperandId objId)
+{
+    PropertyResult prop;
+    JSObject* holder;
+    if (!LookupPropertyPure(cx_, obj, key, &holder, &prop))
+        return false;
+
+    if (prop.isNonNativeProperty())
+        return false;
+
+    if (!IsCacheableGetPropReadSlotForIonOrCacheIR(obj, holder, prop))
+        return false;
+
+    Maybe<ObjOperandId> holderId;
+    emitIdGuard(keyId, key);
+    EmitReadSlotGuard(writer, obj, holder, prop.maybeShape(), objId, &holderId);
+    writer.loadBooleanResult(true);
+    writer.returnFromIC();
+
+    return true;
+}
+
+bool
+InIRGenerator::tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,
+                                             HandleObject obj, ObjOperandId objId)
+{
+    if (!CheckHasNoSuchProperty(cx_, obj, key))
+        return false;
+
+    Maybe<ObjOperandId> holderId;
+    emitIdGuard(keyId, key);
+    EmitReadSlotGuard(writer, obj, nullptr, nullptr, objId, &holderId);
+    writer.loadBooleanResult(false);
+    writer.returnFromIC();
+
+    return true;
+}
+
+bool
+InIRGenerator::tryAttachStub()
+{
+    MOZ_ASSERT(cacheKind_ == CacheKind::In);
+
+    AutoAssertNoPendingException aanpe(cx_);
+
+    ValOperandId keyId(writer.setInputOperandId(0));
+    ValOperandId valId(writer.setInputOperandId(1));
+    ObjOperandId objId = writer.guardIsObject(valId);
+
+    RootedId id(cx_);
+    bool nameOrSymbol;
+    if (!ValueToNameOrSymbolId(cx_, key_, &id, &nameOrSymbol)) {
+        cx_->clearPendingException();
+        return false;
+    }
+
+    if (nameOrSymbol) {
+        if (tryAttachNativeIn(id, keyId, obj_, objId))
+            return true;
+        if (tryAttachNativeInDoesNotExist(id, keyId, obj_, objId))
+            return true;
+        return false;
+    }
+
+    uint32_t index;
+    Int32OperandId indexId;
+    if (maybeGuardInt32Index(key_, keyId, &index, &indexId)) {
+        if (tryAttachDenseIn(index, indexId, obj_, objId))
+            return true;
+        return false;
+    }
+
+    return false;
+}
+
 bool
 IRGenerator::maybeGuardInt32Index(const Value& index, ValOperandId indexId,
                                   uint32_t* int32Index, Int32OperandId* int32IndexId)
 {
     if (index.isNumber()) {
         int32_t indexSigned;
         if (index.isInt32()) {
             indexSigned = index.toInt32();
--- a/js/src/jit/CacheIR.h
+++ b/js/src/jit/CacheIR.h
@@ -131,16 +131,17 @@ class TypedOperandId : public OperandId
 
 enum class CacheKind : uint8_t
 {
     GetProp,
     GetElem,
     GetName,
     SetProp,
     SetElem,
+    In,
 };
 
 #define CACHE_IR_OPS(_)                   \
     _(GuardIsObject)                      \
     _(GuardIsObjectOrNull)                \
     _(GuardIsString)                      \
     _(GuardIsSymbol)                      \
     _(GuardIsInt32Index)                  \
@@ -185,16 +186,17 @@ enum class CacheKind : uint8_t
                                           \
     /* The *Result ops load a value into the cache's result register. */ \
     _(LoadFixedSlotResult)                \
     _(LoadDynamicSlotResult)              \
     _(LoadUnboxedPropertyResult)          \
     _(LoadTypedObjectResult)              \
     _(LoadDenseElementResult)             \
     _(LoadDenseElementHoleResult)         \
+    _(LoadDenseElementExistsResult)       \
     _(LoadUnboxedArrayElementResult)      \
     _(LoadTypedElementResult)             \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectArgResult)       \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadFunctionLengthResult)           \
     _(LoadStringCharResult)               \
@@ -204,16 +206,17 @@ enum class CacheKind : uint8_t
     _(LoadFrameArgumentResult)            \
     _(LoadEnvironmentFixedSlotResult)     \
     _(LoadEnvironmentDynamicSlotResult)   \
     _(CallScriptedGetterResult)           \
     _(CallNativeGetterResult)             \
     _(CallProxyGetResult)                 \
     _(CallProxyGetByValueResult)          \
     _(LoadUndefinedResult)                \
+    _(LoadBooleanResult)                  \
                                           \
     _(TypeMonitorResult)                  \
     _(ReturnFromIC)
 
 enum class CacheOp {
 #define DEFINE_OP(op) op,
     CACHE_IR_OPS(DEFINE_OP)
 #undef DEFINE_OP
@@ -649,16 +652,20 @@ class MOZ_RAII CacheIRWriter : public JS
         writeOperandId(rhs);
     }
     void callSetArrayLength(ObjOperandId obj, bool strict, ValOperandId rhs) {
         writeOpWithOperandId(CacheOp::CallSetArrayLength, obj);
         buffer_.writeByte(uint32_t(strict));
         writeOperandId(rhs);
     }
 
+    void loadBooleanResult(bool val) {
+        writeOp(CacheOp::LoadBooleanResult);
+        buffer_.writeByte(uint32_t(val));
+    }
     void loadUndefinedResult() {
         writeOp(CacheOp::LoadUndefinedResult);
     }
     void loadFixedSlotResult(ObjOperandId obj, size_t offset) {
         writeOpWithOperandId(CacheOp::LoadFixedSlotResult, obj);
         addStubField(offset, StubField::Type::RawWord);
     }
     void loadDynamicSlotResult(ObjOperandId obj, size_t offset) {
@@ -698,16 +705,20 @@ class MOZ_RAII CacheIRWriter : public JS
     void loadDenseElementResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadDenseElementResult, obj);
         writeOperandId(index);
     }
     void loadDenseElementHoleResult(ObjOperandId obj, Int32OperandId index) {
         writeOpWithOperandId(CacheOp::LoadDenseElementHoleResult, obj);
         writeOperandId(index);
     }
+    void loadDenseElementExistsResult(ObjOperandId obj, Int32OperandId index) {
+        writeOpWithOperandId(CacheOp::LoadDenseElementExistsResult, obj);
+        writeOperandId(index);
+    }
     void loadUnboxedArrayElementResult(ObjOperandId obj, Int32OperandId index, JSValueType elementType) {
         writeOpWithOperandId(CacheOp::LoadUnboxedArrayElementResult, obj);
         writeOperandId(index);
         buffer_.writeByte(uint32_t(elementType));
     }
     void loadTypedElementResult(ObjOperandId obj, Int32OperandId index, TypedThingLayout layout,
                                 Scalar::Type elementType) {
         writeOpWithOperandId(CacheOp::LoadTypedElementResult, obj);
@@ -1020,12 +1031,31 @@ class MOZ_RAII SetPropIRGenerator : publ
         return updateStubGroup_;
     }
     jsid updateStubId() const {
         MOZ_ASSERT(needUpdateStub_);
         return updateStubId_;
     }
 };
 
+// InIRGenerator generates CacheIR for a In IC.
+class MOZ_RAII InIRGenerator : public IRGenerator
+{
+    HandleValue key_;
+    HandleObject obj_;
+
+    bool tryAttachDenseIn(uint32_t index, Int32OperandId indexId,
+                          HandleObject obj, ObjOperandId objId);
+    bool tryAttachNativeIn(HandleId key, ValOperandId keyId,
+                           HandleObject obj, ObjOperandId objId);
+    bool tryAttachNativeInDoesNotExist(HandleId key, ValOperandId keyId,
+                                       HandleObject obj, ObjOperandId objId);
+
+  public:
+    InIRGenerator(JSContext* cx, jsbytecode* pc, HandleValue key, HandleObject obj);
+
+    bool tryAttachStub();
+};
+
 } // namespace jit
 } // namespace js
 
 #endif /* jit_CacheIR_h */
--- a/js/src/jit/CacheIRCompiler.cpp
+++ b/js/src/jit/CacheIRCompiler.cpp
@@ -1465,16 +1465,30 @@ CacheIRCompiler::emitLoadUndefinedResult
     AutoOutputRegister output(*this);
     if (output.hasValue())
         masm.moveValue(UndefinedValue(), output.valueReg());
     else
         masm.assumeUnreachable("Should have monitored undefined result");
     return true;
 }
 
+bool
+CacheIRCompiler::emitLoadBooleanResult()
+{
+    AutoOutputRegister output(*this);
+    if (output.hasValue()) {
+        Value val = BooleanValue(reader.readBool());
+        masm.moveValue(val, output.valueReg());
+    }
+    else {
+        MOZ_CRASH("NYI: Typed LoadBooleanResult");
+    }
+    return true;
+}
+
 static void
 EmitStoreResult(MacroAssembler& masm, Register reg, JSValueType type,
                 const AutoOutputRegister& output)
 {
     if (output.hasValue()) {
         masm.tagValue(type, reg, output.valueReg());
         return;
     }
@@ -1744,16 +1758,42 @@ CacheIRCompiler::emitLoadDenseElementHol
     masm.bind(&hole);
     masm.moveValue(UndefinedValue(), output.valueReg());
 
     masm.bind(&done);
     return true;
 }
 
 bool
+CacheIRCompiler::emitLoadDenseElementExistsResult()
+{
+    AutoOutputRegister output(*this);
+    Register obj = allocator.useRegister(masm, reader.objOperandId());
+    Register index = allocator.useRegister(masm, reader.int32OperandId());
+    AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
+
+    FailurePath* failure;
+    if (!addFailurePath(&failure))
+        return false;
+
+    // Load obj->elements.
+    masm.loadPtr(Address(obj, NativeObject::offsetOfElements()), scratch);
+
+    // Bounds check. Unsigned compare sends negative indices to next IC.
+    Address initLength(scratch, ObjectElements::offsetOfInitializedLength());
+    masm.branch32(Assembler::BelowOrEqual, initLength, index, failure->label());
+
+    // Hole check.
+    BaseObjectElementIndex element(scratch, index);
+    masm.branchTestMagic(Assembler::Equal, element, failure->label());
+    masm.moveValue(BooleanValue(true), output.valueReg());
+    return true;
+}
+
+bool
 CacheIRCompiler::emitLoadUnboxedArrayElementResult()
 {
     AutoOutputRegister output(*this);
     Register obj = allocator.useRegister(masm, reader.objOperandId());
     Register index = allocator.useRegister(masm, reader.int32OperandId());
     JSValueType elementType = reader.valueType();
     AutoScratchRegisterMaybeOutput scratch(allocator, masm, output);
 
--- a/js/src/jit/CacheIRCompiler.h
+++ b/js/src/jit/CacheIRCompiler.h
@@ -30,25 +30,27 @@ namespace jit {
     _(GuardNoDetachedTypedObjects)        \
     _(GuardNoDenseElements)               \
     _(GuardAndGetIndexFromString)         \
     _(LoadProto)                          \
     _(LoadEnclosingEnvironment)           \
     _(LoadDOMExpandoValue)                \
     _(LoadDOMExpandoValueIgnoreGeneration)\
     _(LoadUndefinedResult)                \
+    _(LoadBooleanResult)                  \
     _(LoadInt32ArrayLengthResult)         \
     _(LoadUnboxedArrayLengthResult)       \
     _(LoadArgumentsObjectLengthResult)    \
     _(LoadFunctionLengthResult)           \
     _(LoadStringLengthResult)             \
     _(LoadStringCharResult)               \
     _(LoadArgumentsObjectArgResult)       \
     _(LoadDenseElementResult)             \
     _(LoadDenseElementHoleResult)         \
+    _(LoadDenseElementExistsResult)       \
     _(LoadUnboxedArrayElementResult)      \
     _(LoadTypedElementResult)
 
 // Represents a Value on the Baseline frame's expression stack. Slot 0 is the
 // value on top of the stack (the most recently pushed value), slot 1 is the
 // value pushed before that, etc.
 class BaselineFrameSlot
 {
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -254,16 +254,17 @@ CodeGenerator::visitOutOfLineICFallback(
         restoreLiveIgnore(lir, StoreValueTo(getPropIC->output()).clobbered());
 
         masm.jump(ool->rejoin());
         return;
       }
       case CacheKind::GetName:
       case CacheKind::SetProp:
       case CacheKind::SetElem:
+      case CacheKind::In:
         MOZ_CRASH("Baseline-specific for now");
     }
     MOZ_CRASH();
 }
 
 StringObject*
 MNewStringObject::templateObj() const
 {
--- a/js/src/jit/IonIC.cpp
+++ b/js/src/jit/IonIC.cpp
@@ -39,16 +39,17 @@ IonIC::scratchRegisterForEntryJump()
         if (temp != InvalidReg)
             return temp;
         TypedOrValueRegister output = asGetPropertyIC()->output();
         return output.hasValue() ? output.valueReg().scratchReg() : output.typedReg().gpr();
       }
       case CacheKind::GetName:
       case CacheKind::SetProp:
       case CacheKind::SetElem:
+      case CacheKind::In:
         MOZ_CRASH("Baseline-specific for now");
     }
 
     MOZ_CRASH("Invalid kind");
 }
 
 void
 IonIC::reset(Zone* zone)
--- a/js/src/jit/SharedIC.cpp
+++ b/js/src/jit/SharedIC.cpp
@@ -187,16 +187,18 @@ ICStub::NonCacheIRStubMakesGCCalls(Kind 
         return false;
     }
 }
 
 bool
 ICStub::makesGCCalls() const
 {
     switch (kind()) {
+      case CacheIR_Regular:
+        return toCacheIR_Regular()->stubInfo()->makesGCCalls();
       case CacheIR_Monitored:
         return toCacheIR_Monitored()->stubInfo()->makesGCCalls();
       case CacheIR_Updated:
         return toCacheIR_Updated()->stubInfo()->makesGCCalls();
       default:
         return NonCacheIRStubMakesGCCalls(kind());
     }
 }
@@ -307,53 +309,16 @@ ICStub::trace(JSTracer* trc)
         TraceEdge(trc, &updateStub->object(), "baseline-update-singleton");
         break;
       }
       case ICStub::TypeUpdate_ObjectGroup: {
         ICTypeUpdate_ObjectGroup* updateStub = toTypeUpdate_ObjectGroup();
         TraceEdge(trc, &updateStub->group(), "baseline-update-group");
         break;
       }
-      case ICStub::In_Native: {
-        ICIn_Native* inStub = toIn_Native();
-        TraceEdge(trc, &inStub->shape(), "baseline-innative-stub-shape");
-        TraceEdge(trc, &inStub->name(), "baseline-innative-stub-name");
-        break;
-      }
-      case ICStub::In_NativePrototype: {
-        ICIn_NativePrototype* inStub = toIn_NativePrototype();
-        TraceEdge(trc, &inStub->shape(), "baseline-innativeproto-stub-shape");
-        TraceEdge(trc, &inStub->name(), "baseline-innativeproto-stub-name");
-        TraceEdge(trc, &inStub->holder(), "baseline-innativeproto-stub-holder");
-        TraceEdge(trc, &inStub->holderShape(), "baseline-innativeproto-stub-holdershape");
-        break;
-      }
-      case ICStub::In_NativeDoesNotExist: {
-        ICIn_NativeDoesNotExist* inStub = toIn_NativeDoesNotExist();
-        TraceEdge(trc, &inStub->name(), "baseline-innativedoesnotexist-stub-name");
-        JS_STATIC_ASSERT(ICIn_NativeDoesNotExist::MAX_PROTO_CHAIN_DEPTH == 8);
-        switch (inStub->protoChainDepth()) {
-          case 0: inStub->toImpl<0>()->traceShapes(trc); break;
-          case 1: inStub->toImpl<1>()->traceShapes(trc); break;
-          case 2: inStub->toImpl<2>()->traceShapes(trc); break;
-          case 3: inStub->toImpl<3>()->traceShapes(trc); break;
-          case 4: inStub->toImpl<4>()->traceShapes(trc); break;
-          case 5: inStub->toImpl<5>()->traceShapes(trc); break;
-          case 6: inStub->toImpl<6>()->traceShapes(trc); break;
-          case 7: inStub->toImpl<7>()->traceShapes(trc); break;
-          case 8: inStub->toImpl<8>()->traceShapes(trc); break;
-          default: MOZ_CRASH("Invalid proto stub.");
-        }
-        break;
-      }
-      case ICStub::In_Dense: {
-        ICIn_Dense* inStub = toIn_Dense();
-        TraceEdge(trc, &inStub->shape(), "baseline-in-dense-shape");
-        break;
-      }
       case ICStub::GetIntrinsic_Constant: {
         ICGetIntrinsic_Constant* constantStub = toGetIntrinsic_Constant();
         TraceEdge(trc, &constantStub->value(), "baseline-getintrinsic-constant-value");
         break;
       }
       case ICStub::InstanceOf_Function: {
         ICInstanceOf_Function* instanceofStub = toInstanceOf_Function();
         TraceEdge(trc, &instanceofStub->shape(), "baseline-instanceof-fun-shape");
@@ -371,16 +336,19 @@ ICStub::trace(JSTracer* trc)
         TraceNullableEdge(trc, &stub->templateObject(), "baseline-newobject-template");
         break;
       }
       case ICStub::Rest_Fallback: {
         ICRest_Fallback* stub = toRest_Fallback();
         TraceEdge(trc, &stub->templateObject(), "baseline-rest-template");
         break;
       }
+      case ICStub::CacheIR_Regular:
+        TraceCacheIRStub(trc, this, toCacheIR_Regular()->stubInfo());
+        break;
       case ICStub::CacheIR_Monitored:
         TraceCacheIRStub(trc, this, toCacheIR_Monitored()->stubInfo());
         break;
       case ICStub::CacheIR_Updated: {
         ICCacheIR_Updated* stub = toCacheIR_Updated();
         TraceNullableEdge(trc, &stub->updateStubGroup(), "baseline-update-stub-group");
         TraceEdge(trc, &stub->updateStubId(), "baseline-update-stub-id");
         TraceCacheIRStub(trc, this, stub->stubInfo());
@@ -1930,17 +1898,19 @@ StripPreliminaryObjectStubs(JSContext* c
     // Afterwards, the objects (even the preliminary ones) might be changed
     // to reduce the number of fixed slots they have. If we generate stubs for
     // both the old and new number of fixed slots, the stub will look
     // polymorphic to IonBuilder when it is actually monomorphic. To avoid
     // this, strip out any stubs for preliminary objects before attaching a new
     // stub which isn't on a preliminary object.
 
     for (ICStubIterator iter = stub->beginChain(); !iter.atEnd(); iter++) {
-        if (iter->isCacheIR_Monitored() && iter->toCacheIR_Monitored()->hasPreliminaryObject())
+        if (iter->isCacheIR_Regular() && iter->toCacheIR_Regular()->hasPreliminaryObject())
+            iter.unlink(cx);
+        else if (iter->isCacheIR_Monitored() && iter->toCacheIR_Monitored()->hasPreliminaryObject())
             iter.unlink(cx);
         else if (iter->isCacheIR_Updated() && iter->toCacheIR_Updated()->hasPreliminaryObject())
             iter.unlink(cx);
     }
 }
 
 JSObject*
 GetDOMProxyProto(JSObject* obj)
--- a/js/src/jit/SharedIC.h
+++ b/js/src/jit/SharedIC.h
@@ -503,17 +503,17 @@ class ICStub
 #undef DEF_ENUM_KIND
         LIMIT
     };
 
     static bool IsValidKind(Kind k) {
         return (k > INVALID) && (k < LIMIT);
     }
     static bool IsCacheIRKind(Kind k) {
-        return k == CacheIR_Monitored || k == CacheIR_Updated;
+        return k == CacheIR_Regular || k == CacheIR_Monitored || k == CacheIR_Updated;
     }
 
     static const char* KindString(Kind k) {
         switch(k) {
 #define DEF_KIND_STR(kindName) case kindName: return #kindName;
             IC_BASELINE_STUB_KIND_LIST(DEF_KIND_STR)
             IC_SHARED_STUB_KIND_LIST(DEF_KIND_STR)
 #undef DEF_KIND_STR
@@ -828,16 +828,41 @@ class ICFallbackStub : public ICStub
         }
         return count;
     }
 
     void unlinkStub(Zone* zone, ICStub* prev, ICStub* stub);
     void unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind);
 };
 
+// Base class for Trait::Regular CacheIR stubs
+class ICCacheIR_Regular : public ICStub
+{
+    const CacheIRStubInfo* stubInfo_;
+
+  public:
+    ICCacheIR_Regular(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
+      : ICStub(ICStub::CacheIR_Regular, stubCode),
+        stubInfo_(stubInfo)
+    {}
+
+    void notePreliminaryObject() {
+        extra_ = 1;
+    }
+    bool hasPreliminaryObject() const {
+        return extra_;
+    }
+
+    const CacheIRStubInfo* stubInfo() const {
+        return stubInfo_;
+    }
+
+    uint8_t* stubDataStart();
+};
+
 // Monitored stubs are IC stubs that feed a single resulting value out to a
 // type monitor operation.
 class ICMonitoredStub : public ICStub
 {
   protected:
     // Pointer to the start of the type monitoring stub chain.
     ICStub* firstMonitorStub_;
 
--- a/js/src/jit/SharedICList.h
+++ b/js/src/jit/SharedICList.h
@@ -32,16 +32,17 @@ namespace jit {
     _(Compare_Boolean)                           \
     _(Compare_Object)                            \
     _(Compare_ObjectWithUndefined)               \
     _(Compare_Int32WithBoolean)                  \
                                                  \
     _(GetProp_Fallback)                          \
     _(GetProp_Generic)                           \
                                                  \
+    _(CacheIR_Regular)                           \
     _(CacheIR_Monitored)                         \
     _(CacheIR_Updated)                           \
                                                  \
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_SharedICList_h */
--- a/js/src/make-source-package.sh
+++ b/js/src/make-source-package.sh
@@ -179,17 +179,17 @@ INSTALL_EOF
     # copy or create README
     if [ -e ${STAGING}/README ]; then
         cp ${STAGING}/README ${tgtpath}
     else
         cat <<README_EOF >${tgtpath}/README
 This directory contains SpiderMonkey ${MOZJS_MAJOR_VERSION}.
 
 This release is based on a revision of Mozilla ${MOZJS_MAJOR_VERSION}:
-  http://hg.mozilla.org/releases/
+  https://hg.mozilla.org/releases/
 The changes in the patches/ directory were applied.
 
 MDN hosts the latest SpiderMonkey ${MOZJS_MAJOR_VERSION} release notes:
   https://developer.mozilla.org/en-US/docs/SpiderMonkey/${MOZJS_MAJOR_VERSION}
 README_EOF
     fi
 
     # copy LICENSE
--- a/layout/base/AccessibleCaretEventHub.h
+++ b/layout/base/AccessibleCaretEventHub.h
@@ -48,19 +48,19 @@ class WidgetTouchEvent;
 // methods of AccessibleCaretEventHub. See TestAccessibleCaretEventHub.cpp.
 //
 // Besides dealing with real events, AccessibleCaretEventHub could also
 // synthesize fake long-tap events and inject those events to itself on the
 // platform lacks eMouseLongTap. Turn on this preference
 // "layout.accessiblecaret.use_long_tap_injector" for the fake long-tap events.
 //
 // State transition diagram:
-// http://hg.mozilla.org/mozilla-central/raw-file/default/layout/base/doc/AccessibleCaretEventHubStates.png
+// https://hg.mozilla.org/mozilla-central/raw-file/default/layout/base/doc/AccessibleCaretEventHubStates.png
 // Source code of the diagram:
-// http://hg.mozilla.org/mozilla-central/file/default/layout/base/doc/AccessibleCaretEventHubStates.dot
+// https://hg.mozilla.org/mozilla-central/file/default/layout/base/doc/AccessibleCaretEventHubStates.dot
 //
 // Please see the wiki page for more information.
 // https://wiki.mozilla.org/AccessibleCaret
 //
 class AccessibleCaretEventHub : public nsIReflowObserver,
                                 public nsIScrollObserver,
                                 public nsISelectionListener,
                                 public nsSupportsWeakReference
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -8553,22 +8553,23 @@ static nsRect
 UnionBorderBoxes(nsIFrame* aFrame, bool aApplyTransform,
                  bool& aOutValid,
                  const nsSize* aSizeOverride = nullptr,
                  const nsOverflowAreas* aOverflowOverride = nullptr)
 {
   const nsRect bounds(nsPoint(0, 0),
                       aSizeOverride ? *aSizeOverride : aFrame->GetSize());
 
-  // The SVG container frames do not maintain an accurate mRect.
-  // It will make the outline be larger than we expect, we need
-  // to make them narrow to their children's outline.
+  // The SVG container frames besides SVGTextFrame do not maintain
+  // an accurate mRect. It will make the outline be larger than
+  // we expect, we need to make them narrow to their children's outline.
   // aOutValid is set to false if the returned nsRect is not valid
   // and should not be included in the outline rectangle.
-  aOutValid = !aFrame->IsFrameOfType(nsIFrame::eSVGContainer);
+  aOutValid = !aFrame->IsFrameOfType(nsIFrame::eSVGContainer)
+              || aFrame->GetType() == nsGkAtoms::svgTextFrame;
 
   // Start from our border-box, transformed.  See comment below about
   // transform of children.
   nsRect u;
   bool doTransform = aApplyTransform && aFrame->IsTransformed();
   if (doTransform) {
     u = nsDisplayTransform::TransformRect(bounds, aFrame, &bounds);
   } else {
--- a/layout/painting/nsCSSRendering.cpp
+++ b/layout/painting/nsCSSRendering.cpp
@@ -2147,17 +2147,17 @@ SetupImageLayerClip(nsCSSRendering::Imag
   }
 
   if (aClipState.mHasRoundedCorners) {
     Rect bgAreaGfx = NSRectToRect(aClipState.mBGClipArea, aAppUnitsPerPixel);
     bgAreaGfx.Round();
 
     if (bgAreaGfx.IsEmpty()) {
       // I think it's become possible to hit this since
-      // http://hg.mozilla.org/mozilla-central/rev/50e934e4979b landed.
+      // https://hg.mozilla.org/mozilla-central/rev/50e934e4979b landed.
       NS_WARNING("converted background area should not be empty");
       // Make our caller not do anything.
       aClipState.mDirtyRectGfx.SizeTo(gfxSize(0.0, 0.0));
       return;
     }
 
     aAutoSR->EnsureSaved(aCtx);
 
@@ -2188,17 +2188,17 @@ DrawBackgroundColor(nsCSSRendering::Imag
     return;
   }
 
   Rect bgAreaGfx = NSRectToRect(aClipState.mBGClipArea, aAppUnitsPerPixel);
   bgAreaGfx.Round();
 
   if (bgAreaGfx.IsEmpty()) {
     // I think it's become possible to hit this since
-    // http://hg.mozilla.org/mozilla-central/rev/50e934e4979b landed.
+    // https://hg.mozilla.org/mozilla-central/rev/50e934e4979b landed.
     NS_WARNING("converted background area should not be empty");
     // Make our caller not do anything.
     aClipState.mDirtyRectGfx.SizeTo(gfxSize(0.0, 0.0));
     return;
   }
 
   aCtx->Save();
   gfxRect dirty = ThebesRect(bgAreaGfx).Intersect(aClipState.mDirtyRectGfx);
--- a/layout/reftests/svg/outline-ref.html
+++ b/layout/reftests/svg/outline-ref.html
@@ -26,46 +26,51 @@
       <circle id="ggCircle" cx="50" cy="50" r="20" style="fill: green"/>
       <g>
         <rect id="ggRect" x="15" y ="15" width="30" height="10" style="fill: blue"/>
       </g>
     </g>
     <svg x="300" y="250">
       <rect id="innerRect" x="30" y="10" height="50" width="50" style="fill: red"/>
     </svg>
+    <a xlink:href="#" id="link">
+      <text x="300" y="350" font-family="Verdana" font-size="20">
+        link
+      </text>
+    </a>
   </g>
 </svg>
 <script>
 
 function createOutline(boundingRect) {
   // Outline starts from a top-left shift pixel of the bounding rect
   var left = boundingRect.left - 1;
   var top  = boundingRect.top - 1;
   var right = boundingRect.right;
   var bottom = boundingRect.bottom;
   var width = boundingRect.width;
   var height = boundingRect.height;
 
   var lines = document.createElement("div");
-  var styles = 'border: 1px solid;'
+  var styles = 'border: 1px solid black;'
                + 'width: ' + width + 'px;'
                + 'height: ' + height + 'px;'
                + 'position: absolute;'
                + 'top: ' + top + 'px;'
                + 'left: ' + left + 'px;';
 
   lines.setAttribute('style', styles);
   document.body.appendChild(lines);
 }
 
 window.onload = function drawOutline() {
   var elements = ['rect', 'foreignObject', 'circle',
                   'ellipse', 'image', 'line', 'path',
                   'polygon', 'polyline', 'text','gCircle',
-                  'innerRect'];
+                  'innerRect', 'link'];
   elements.forEach(id => {
     var element = document.getElementById(id);
     createOutline(element.getBoundingClientRect());
   });
 
   var ggRect = document.getElementById('ggRect');
   var ggRectbbox = ggRect.getBoundingClientRect();
   createOutline(ggRectbbox);
--- a/layout/reftests/svg/outline.html
+++ b/layout/reftests/svg/outline.html
@@ -6,17 +6,17 @@ text,
 foreignObject,
 circle,
 ellipse,
 image,
 line,
 path,
 polygon,
 polyline {
-  outline: 1px solid;
+  outline: 1px solid black;
 }
 
 </style>
 <body>
 <svg xmlns="http://www.w3.org/2000/svg" overflow="visible">
   <g>
     <rect width="100" height="100" style="fill: yellow"/>
     <text x="0" y="140" font-family="Verdana" font-size="20">
@@ -41,12 +41,17 @@ polyline {
       <circle cx="50" cy="50" r="20" style="fill: green; outline: 0px"/>
       <g>
         <rect x="15" y="15" width="30" height="10" style="fill: blue"/>
       </g>
     </g>
     <svg x="300" y="250">
       <rect x="30" y="10" height="50" width="50" style="fill: red"/>
     </svg>
+    <a xlink:href="#" id="link">
+      <text x="300" y="350" font-family="Verdana" font-size="20">
+        link
+      </text>
+    </a>
   </g>
 </svg>
 </body>
 </html>
\ No newline at end of file
--- a/media/libcubeb/README_MOZILLA
+++ b/media/libcubeb/README_MOZILLA
@@ -1,8 +1,8 @@
 The source from this directory was copied from the cubeb 
 git repository using the update.sh script.  The only changes
 made were those applied by update.sh and the addition of
 Makefile.in build files for the Mozilla build system.
 
 The cubeb git repository is: git://github.com/kinetiknz/cubeb.git
 
-The git commit ID used was d96e35f02dbb9a093e5bfdff4f2948b7a6e9d3f9.
+The git commit ID used was 927877c3204d6b8467b6dc782ca2aa740d240d41.
--- a/media/libcubeb/gtest/common.h
+++ b/media/libcubeb/gtest/common.h
@@ -11,16 +11,19 @@
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
 #endif
 #include <windows.h>
 #else
 #include <unistd.h>
 #endif
 
+#include <cstdarg>
+#include "cubeb/cubeb.h"
+
 template<typename T, size_t N>
 constexpr size_t
 ARRAY_LENGTH(T(&)[N])
 {
   return N;
 }
 
 void delay(unsigned int ms)
@@ -91,9 +94,17 @@ int has_available_input_device(cubeb * c
     fprintf(stderr, "there are input devices, but they are not "
         "available, skipping\n");
     return 0;
   }
 
   return 1;
 }
 
+void print_log(const char * msg, ...)
+{
+  va_list args;
+  va_start(args, msg);
+  vprintf(msg, args);
+  va_end(args);
+}
+
 #endif /* TEST_COMMON */
--- a/media/libcubeb/gtest/test_audio.cpp
+++ b/media/libcubeb/gtest/test_audio.cpp
@@ -12,214 +12,201 @@
 #define _XOPEN_SOURCE 600
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include <string.h>
 #include "cubeb/cubeb.h"
 #include "common.h"
+#include <string>
+
+using namespace std;
 
 #define MAX_NUM_CHANNELS 32
 
 #if !defined(M_PI)
 #define M_PI 3.14159265358979323846
 #endif
 
 #define VOLUME 0.2
 
 float get_frequency(int channel_index)
 {
   return 220.0f * (channel_index+1);
 }
 
+template<typename T> T ConvertSample(double input);
+template<> float ConvertSample(double input) { return input; }
+template<> short ConvertSample(double input) { return short(input * 32767.0f); }
+
 /* store the phase of the generated waveform */
-typedef struct {
+struct synth_state {
+  synth_state(int num_channels_, float sample_rate_)
+    : num_channels(num_channels_),
+    sample_rate(sample_rate_)
+  {
+    for(int i=0;i < MAX_NUM_CHANNELS;++i)
+      phase[i] = 0.0f;
+  }
+
+  template<typename T>
+    void run(T* audiobuffer, long nframes)
+    {
+      for(int c=0;c < num_channels;++c) {
+        float freq = get_frequency(c);
+        float phase_inc = 2.0 * M_PI * freq / sample_rate;
+        for(long n=0;n < nframes;++n) {
+          audiobuffer[n*num_channels+c] = ConvertSample<T>(sin(phase[c]) * VOLUME);
+          phase[c] += phase_inc;
+        }
+      }
+    }
+
+private:
   int num_channels;
   float phase[MAX_NUM_CHANNELS];
   float sample_rate;
-} synth_state;
-
-synth_state* synth_create(int num_channels, float sample_rate)
-{
-  synth_state* synth = (synth_state *) malloc(sizeof(synth_state));
-  if (!synth)
-    return NULL;
-  for(int i=0;i < MAX_NUM_CHANNELS;++i)
-    synth->phase[i] = 0.0f;
-  synth->num_channels = num_channels;
-  synth->sample_rate = sample_rate;
-  return synth;
-}
+};
 
-void synth_destroy(synth_state* synth)
-{
-  free(synth);
-}
-
-void synth_run_float(synth_state* synth, float* audiobuffer, long nframes)
-{
-  for(int c=0;c < synth->num_channels;++c) {
-    float freq = get_frequency(c);
-    float phase_inc = 2.0 * M_PI * freq / synth->sample_rate;
-    for(long n=0;n < nframes;++n) {
-      audiobuffer[n*synth->num_channels+c] = sin(synth->phase[c]) * VOLUME;
-      synth->phase[c] += phase_inc;
-    }
-  }
-}
-
-long data_cb_float(cubeb_stream * /*stream*/, void * user, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
+template<typename T>
+long data_cb(cubeb_stream * /*stream*/, void * user, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
 {
   synth_state *synth = (synth_state *)user;
-  synth_run_float(synth, (float*)outputbuffer, nframes);
+  synth->run((T*)outputbuffer, nframes);
   return nframes;
 }
 
-void synth_run_16bit(synth_state* synth, short* audiobuffer, long nframes)
+struct CubebCleaner
 {
-  for(int c=0;c < synth->num_channels;++c) {
-    float freq = get_frequency(c);
-    float phase_inc = 2.0 * M_PI * freq / synth->sample_rate;
-    for(long n=0;n < nframes;++n) {
-      audiobuffer[n*synth->num_channels+c] = sin(synth->phase[c]) * VOLUME * 32767.0f;
-      synth->phase[c] += phase_inc;
-    }
-  }
-}
+  CubebCleaner(cubeb* ctx_) : ctx(ctx_) {}
+  ~CubebCleaner() { cubeb_destroy(ctx); }
+  cubeb* ctx;
+};
 
-long data_cb_short(cubeb_stream * /*stream*/, void * user, const void * /*inputbuffer*/, void * outputbuffer, long nframes)
+struct CubebStreamCleaner
 {
-  synth_state *synth = (synth_state *)user;
-  synth_run_16bit(synth, (short*)outputbuffer, nframes);
-  return nframes;
-}
+  CubebStreamCleaner(cubeb_stream* ctx_) : ctx(ctx_) {}
+  ~CubebStreamCleaner() { cubeb_stream_destroy(ctx); }
+  cubeb_stream* ctx;
+};
 
 void state_cb_audio(cubeb_stream * /*stream*/, void * /*user*/, cubeb_state /*state*/)
 {
 }
 
 /* Our android backends don't support float, only int16. */
-int supports_float32(const char* backend_id)
+int supports_float32(string backend_id)
 {
-  return (strcmp(backend_id, "opensl") != 0 &&
-          strcmp(backend_id, "audiotrack") != 0);
+  return backend_id != "opensl"
+    && backend_id != "audiotrack";
 }
 
 /* The WASAPI backend only supports float. */
-int supports_int16(const char* backend_id)
+int supports_int16(string backend_id)
 {
-  return strcmp(backend_id, "wasapi") != 0;
+  return backend_id != "wasapi";
 }
 
 /* Some backends don't have code to deal with more than mono or stereo. */
-int supports_channel_count(const char* backend_id, int nchannels)
+int supports_channel_count(string backend_id, int nchannels)
 {
   return nchannels <= 2 ||
-    (strcmp(backend_id, "opensl") != 0 && strcmp(backend_id, "audiotrack") != 0);
+    (backend_id != "opensl" && backend_id != "audiotrack");
 }
 
 int run_test(int num_channels, layout_info layout, int sampling_rate, int is_float)
 {
   int r = CUBEB_OK;
 
   cubeb *ctx = NULL;
-  synth_state* synth = NULL;
-  cubeb_stream *stream = NULL;
-  const char * backend_id = NULL;
 
   r = cubeb_init(&ctx, "Cubeb audio test: channels");
   if (r != CUBEB_OK) {
     fprintf(stderr, "Error initializing cubeb library\n");
-    goto cleanup;
+    return r;
   }
+  CubebCleaner cleanup_cubeb_at_exit(ctx);
 
-  backend_id = cubeb_get_backend_id(ctx);
+  const char * backend_id = cubeb_get_backend_id(ctx);
 
   if ((is_float && !supports_float32(backend_id)) ||
       (!is_float && !supports_int16(backend_id)) ||
       !supports_channel_count(backend_id, num_channels)) {
     /* don't treat this as a test failure. */
-    goto cleanup;
+    return CUBEB_OK;
   }
 
   fprintf(stderr, "Testing %d channel(s), layout: %s, %d Hz, %s (%s)\n", num_channels, layout.name, sampling_rate, is_float ? "float" : "short", cubeb_get_backend_id(ctx));
 
   cubeb_stream_params params;
   params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE;
   params.rate = sampling_rate;
   params.channels = num_channels;
   params.layout = layout.layout;
 
-  synth = synth_create(params.channels, params.rate);
-  if (synth == NULL) {
-    fprintf(stderr, "Out of memory\n");
-    goto cleanup;
+  synth_state synth(params.channels, params.rate);
+
+  cubeb_stream *stream = NULL;
+  r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, &params,
+      4096, is_float ? &data_cb<float> : &data_cb<short>, state_cb_audio, &synth);
+  if (r != CUBEB_OK) {
+    fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
+    return r;
   }
 
-  r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, &params,
-                        4096, is_float ? data_cb_float : data_cb_short, state_cb_audio, synth);
-  if (r != CUBEB_OK) {
-    fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
-    goto cleanup;
-  }
+  CubebStreamCleaner cleanup_stream_at_exit(stream);
 
   cubeb_stream_start(stream);
   delay(200);
   cubeb_stream_stop(stream);
 
-cleanup:
-  cubeb_stream_destroy(stream);
-  cubeb_destroy(ctx);
-  synth_destroy(synth);
-
   return r;
 }
 
 int run_panning_volume_test(int is_float)
 {
   int r = CUBEB_OK;
 
   cubeb *ctx = NULL;
-  synth_state* synth = NULL;
-  cubeb_stream *stream = NULL;
-  const char * backend_id = NULL;
 
   r = cubeb_init(&ctx, "Cubeb audio test");
   if (r != CUBEB_OK) {
     fprintf(stderr, "Error initializing cubeb library\n");
-    goto cleanup;
+    return r;
   }
-  backend_id = cubeb_get_backend_id(ctx);
+
+  CubebCleaner cleanup_cubeb_at_exit(ctx);
+
+  const char * backend_id = cubeb_get_backend_id(ctx);
 
   if ((is_float && !supports_float32(backend_id)) ||
       (!is_float && !supports_int16(backend_id))) {
     /* don't treat this as a test failure. */
-    goto cleanup;
+    return CUBEB_OK;
   }
 
   cubeb_stream_params params;
   params.format = is_float ? CUBEB_SAMPLE_FLOAT32NE : CUBEB_SAMPLE_S16NE;
   params.rate = 44100;
   params.channels = 2;
   params.layout = CUBEB_LAYOUT_STEREO;
 
-  synth = synth_create(params.channels, params.rate);
-  if (synth == NULL) {
-    fprintf(stderr, "Out of memory\n");
-    goto cleanup;
+  synth_state synth(params.channels, params.rate);
+
+  cubeb_stream *stream = NULL;
+  r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, &params,
+      4096, is_float ? &data_cb<float> : &data_cb<short>,
+      state_cb_audio, &synth);
+  if (r != CUBEB_OK) {
+    fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
+    return r;
   }
 
-  r = cubeb_stream_init(ctx, &stream, "test tone", NULL, NULL, NULL, &params,
-                        4096, is_float ? data_cb_float : data_cb_short,
-                        state_cb_audio, synth);
-  if (r != CUBEB_OK) {
-    fprintf(stderr, "Error initializing cubeb stream: %d\n", r);
-    goto cleanup;
-  }
+  CubebStreamCleaner cleanup_stream_at_exit(stream);
 
   fprintf(stderr, "Testing: volume\n");
   for(int i=0;i <= 4; ++i)
   {
     fprintf(stderr, "Volume: %d%%\n", i*25);
 
     cubeb_stream_set_volume(stream, i/4.0f);
     cubeb_stream_start(stream);
@@ -235,21 +222,16 @@ int run_panning_volume_test(int is_float
 
     cubeb_stream_set_panning(stream, i/4.0f);
     cubeb_stream_start(stream);
     delay(400);
     cubeb_stream_stop(stream);
     delay(100);
   }
 
-cleanup:
-  cubeb_stream_destroy(stream);
-  cubeb_destroy(ctx);
-  synth_destroy(synth);
-
   return r;
 }
 
 TEST(cubeb, run_panning_volume_test_short)
 {
   ASSERT_EQ(run_panning_volume_test(0), CUBEB_OK);
 }
 
@@ -270,21 +252,21 @@ TEST(cubeb, run_channel_rate_test)
 
   int freq_values[] = {
     16000,
     24000,
     44100,
     48000,
   };
 
-  for(unsigned int j = 0; j < ARRAY_LENGTH(channel_values); ++j) {
-    for(unsigned int i = 0; i < ARRAY_LENGTH(freq_values); ++i) {
-      ASSERT_TRUE(channel_values[j] < MAX_NUM_CHANNELS);
+  for(auto channels : channel_values) {
+    for(auto freq : freq_values) {
+      ASSERT_TRUE(channels < MAX_NUM_CHANNELS);
       fprintf(stderr, "--------------------------\n");
-      for (unsigned int k = 0 ; k < ARRAY_LENGTH(layout_infos); ++k ) {
-        if (layout_infos[k].channels == channel_values[j]) {
-          ASSERT_EQ(run_test(channel_values[j], layout_infos[k], freq_values[i], 0), CUBEB_OK);
-          ASSERT_EQ(run_test(channel_values[j], layout_infos[k], freq_values[i], 1), CUBEB_OK);
+      for (auto layout : layout_infos) {
+        if (layout.channels == channels) {
+          ASSERT_EQ(run_test(channels, layout, freq, 0), CUBEB_OK);
+          ASSERT_EQ(run_test(channels, layout, freq, 1), CUBEB_OK);
         }
       }
     }
   }
 }
--- a/media/libcubeb/gtest/test_duplex.cpp
+++ b/media/libcubeb/gtest/test_duplex.cpp
@@ -13,57 +13,47 @@
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include "cubeb/cubeb.h"
 #include "common.h"
 
 #define SAMPLE_FREQUENCY 48000
-#if (defined(_WIN32) || defined(__WIN32__))
 #define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE
-#define SILENT_SAMPLE 0.0f
-#else
-#define STREAM_FORMAT CUBEB_SAMPLE_S16LE
-#define SILENT_SAMPLE 0
-#endif
 
 struct user_state_duplex
 {
-  bool seen_noise;
+  bool seen_audio;
 };
 
 long data_cb_duplex(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
 {
   user_state_duplex * u = reinterpret_cast<user_state_duplex*>(user);
-#if (defined(_WIN32) || defined(__WIN32__))
   float *ib = (float *)inputbuffer;
   float *ob = (float *)outputbuffer;
-#else
-  short *ib = (short *)inputbuffer;
-  short *ob = (short *)outputbuffer;
-#endif
-  bool seen_noise = false;
+  bool seen_audio = true;
 
   if (stream == NULL || inputbuffer == NULL || outputbuffer == NULL) {
     return CUBEB_ERROR;
   }
 
   // Loop back: upmix the single input channel to the two output channels,
   // checking if there is noise in the process.
   long output_index = 0;
   for (long i = 0; i < nframes; i++) {
-    if (ib[i] != SILENT_SAMPLE) {
-      seen_noise = true;
+    if (ib[i] <= -1.0 && ib[i] >= 1.0) {
+      seen_audio = false;
+      break;
     }
     ob[output_index] = ob[output_index + 1] = ib[i];
     output_index += 2;
   }
 
-  u->seen_noise |= seen_noise;
+  u->seen_audio |= seen_audio;
 
   return nframes;
 }
 
 void state_cb_duplex(cubeb_stream * stream, void * /*user*/, cubeb_state state)
 {
   if (stream == NULL)
     return;
@@ -131,10 +121,10 @@ TEST(cubeb, duplex)
 
   cubeb_stream_start(stream);
   delay(500);
   cubeb_stream_stop(stream);
 
   cubeb_stream_destroy(stream);
   cubeb_destroy(ctx);
 
-  ASSERT_TRUE(stream_state.seen_noise);
+  ASSERT_TRUE(stream_state.seen_audio);
 }
--- a/media/libcubeb/gtest/test_record.cpp
+++ b/media/libcubeb/gtest/test_record.cpp
@@ -12,48 +12,41 @@
 #endif
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
 #include "cubeb/cubeb.h"
 #include "common.h"
 
 #define SAMPLE_FREQUENCY 48000
-#if (defined(_WIN32) || defined(__WIN32__))
 #define STREAM_FORMAT CUBEB_SAMPLE_FLOAT32LE
-#else
-#define STREAM_FORMAT CUBEB_SAMPLE_S16LE
-#endif
 
 struct user_state_record
 {
-  bool seen_noise;
+  bool seen_audio;
 };
 
 long data_cb_record(cubeb_stream * stream, void * user, const void * inputbuffer, void * outputbuffer, long nframes)
 {
   user_state_record * u = reinterpret_cast<user_state_record*>(user);
-#if STREAM_FORMAT != CUBEB_SAMPLE_FLOAT32LE
-  short *b = (short *)inputbuffer;
-#else
   float *b = (float *)inputbuffer;
-#endif
 
   if (stream == NULL  || inputbuffer == NULL || outputbuffer != NULL) {
     return CUBEB_ERROR;
   }
 
-  bool seen_noise = false;
+  bool seen_audio = true;
   for (long i = 0; i < nframes; i++) {
-    if (b[i] != 0.0) {
-      seen_noise = true;
+    if (b[i] <= -1.0 && b[i] >= 1.0) {
+      seen_audio = false;
+      break;
     }
   }
 
-  u->seen_noise |= seen_noise;
+  u->seen_audio |= seen_audio;
 
   return nframes;
 }
 
 void state_cb_record(cubeb_stream * stream, void * /*user*/, cubeb_state state)
 {
   if (stream == NULL)
     return;
@@ -69,16 +62,19 @@ void state_cb_record(cubeb_stream * stre
     printf("unknown stream state %d\n", state);
   }
 
   return;
 }
 
 TEST(cubeb, record)
 {
+  if (cubeb_set_log_callback(CUBEB_LOG_DISABLED, nullptr /*print_log*/) != CUBEB_OK) {
+    printf("Set log callback failed\n");
+  }
   cubeb *ctx;
   cubeb_stream *stream;
   cubeb_stream_params params;
   int r;
   user_state_record stream_state = { false };
 
   r = cubeb_init(&ctx, "Cubeb record example");
   if (r != CUBEB_OK) {
@@ -106,10 +102,15 @@ TEST(cubeb, record)
 
   cubeb_stream_start(stream);
   delay(500);
   cubeb_stream_stop(stream);
 
   cubeb_stream_destroy(stream);
   cubeb_destroy(ctx);
 
-  ASSERT_TRUE(stream_state.seen_noise);
+#ifdef __linux__
+  // user callback does not arrive in Linux, silence the error
+  printf("Check is disabled in Linux\n");
+#else
+  ASSERT_TRUE(stream_state.seen_audio);
+#endif
 }
--- a/media/libcubeb/gtest/test_resampler.cpp
+++ b/media/libcubeb/gtest/test_resampler.cpp
@@ -3,16 +3,17 @@
  *
  * This program is made available under an ISC-style license.  See the
  * accompanying file LICENSE for details.
  */
 #ifndef NOMINMAX
 #define NOMINMAX
 #endif // NOMINMAX
 #include "gtest/gtest.h"
+#include "common.h"
 #include "cubeb_resampler_internal.h"
 #include <stdio.h>
 #include <algorithm>
 #include <iostream>
 
 /* Windows cmath USE_MATH_DEFINE thing... */
 const float PI = 3.14159265359f;
 
@@ -386,18 +387,21 @@ void test_resampler_duplex(uint32_t inpu
     state.output.push(output_buffer.data(), got * state.output_channels);
   }
 
   dump("input_expected.raw", expected_resampled_input.data(), expected_resampled_input.length());
   dump("output_expected.raw", expected_resampled_output.data(), expected_resampled_output.length());
   dump("input.raw", state.input.data(), state.input.length());
   dump("output.raw", state.output.data(), state.output.length());
 
-  ASSERT_TRUE(array_fuzzy_equal(state.input, expected_resampled_input, epsilon<T>(input_rate/target_rate)));
-  ASSERT_TRUE(array_fuzzy_equal(state.output, expected_resampled_output, epsilon<T>(output_rate/target_rate)));
+ // This is disabled because the latency estimation in the resampler code is
+ // slightly off so we can generate expected vectors.
+ // See https://github.com/kinetiknz/cubeb/issues/93
+ // ASSERT_TRUE(array_fuzzy_equal(state.input, expected_resampled_input, epsilon<T>(input_rate/target_rate)));
+ // ASSERT_TRUE(array_fuzzy_equal(state.output, expected_resampled_output, epsilon<T>(output_rate/target_rate)));
 
   cubeb_resampler_destroy(resampler);
 }
 
 #define array_size(x) (sizeof(x) / sizeof(x[0]))
 
 TEST(cubeb, resampler_one_way)
 {
@@ -411,19 +415,16 @@ TEST(cubeb, resampler_one_way)
           test_resampler_one_way<float>(channels, sample_rates[source_rate],
                                         sample_rates[dest_rate], chunk_duration);
         }
       }
     }
   }
 }
 
-// This is disabled because the latency estimation in the resampler code is
-// slightly off so we can generate expected vectors.
-// See https://github.com/kinetiknz/cubeb/issues/93
 TEST(cubeb, DISABLED_resampler_duplex)
 {
   for (uint32_t input_channels = 1; input_channels <= max_channels; input_channels++) {
     for (uint32_t output_channels = 1; output_channels <= max_channels; output_channels++) {
       for (uint32_t source_rate_input = 0; source_rate_input < array_size(sample_rates); source_rate_input++) {
         for (uint32_t source_rate_output = 0; source_rate_output < array_size(sample_rates); source_rate_output++) {
           for (uint32_t dest_rate = 0; dest_rate < array_size(sample_rates); dest_rate++) {
             for (uint32_t chunk_duration = min_chunks; chunk_duration < max_chunks; chunk_duration+=chunk_increment) {
@@ -531,8 +532,219 @@ TEST(cubeb, resampler_drain)
 
   /* If the above is not an infinite loop, the drain was a success, just mark
    * this test as such. */
   ASSERT_TRUE(true);
 
   cubeb_resampler_destroy(resampler);
 }
 
+// gtest does not support using ASSERT_EQ and friend in a function that returns
+// a value.
+void check_output(const void * input_buffer, void * output_buffer, long frame_count)
+{
+  ASSERT_EQ(input_buffer, nullptr);
+  ASSERT_EQ(frame_count, 256);
+  ASSERT_TRUE(!!output_buffer);
+}
+
+long cb_passthrough_resampler_output(cubeb_stream * /*stm*/, void * /*user_ptr*/,
+                                     const void * input_buffer,
+                                     void * output_buffer, long frame_count)
+{
+  check_output(input_buffer, output_buffer, frame_count);
+  return frame_count;
+}
+
+TEST(cubeb, resampler_passthrough_output_only)
+{
+  // Test that the passthrough resampler works when there is only an output stream.
+  cubeb_stream_params output_params;
+
+  const size_t output_channels = 2;
+  output_params.channels = output_channels;
+  output_params.rate = 44100;
+  output_params.format = CUBEB_SAMPLE_FLOAT32NE;
+  int target_rate = output_params.rate;
+
+  cubeb_resampler * resampler =
+    cubeb_resampler_create((cubeb_stream*)nullptr, nullptr, &output_params,
+                           target_rate, cb_passthrough_resampler_output, nullptr,
+                           CUBEB_RESAMPLER_QUALITY_VOIP);
+
+  float output_buffer[output_channels * 256];
+
+  long got;
+  for (uint32_t i = 0; i < 30; i++) {
+    got = cubeb_resampler_fill(resampler, nullptr, nullptr, output_buffer, 256);
+    ASSERT_EQ(got, 256);
+  }
+}
+
+// gtest does not support using ASSERT_EQ and friend in a function that returns
+// a value.
+void check_input(const void * input_buffer, void * output_buffer, long frame_count)
+{
+  ASSERT_EQ(output_buffer, nullptr);
+  ASSERT_EQ(frame_count, 256);
+  ASSERT_TRUE(!!input_buffer);
+}
+
+long cb_passthrough_resampler_input(cubeb_stream * /*stm*/, void * /*user_ptr*/,
+                                    const void * input_buffer,
+                                    void * output_buffer, long frame_count)
+{
+  check_input(input_buffer, output_buffer, frame_count);
+  return frame_count;
+}
+
+TEST(cubeb, resampler_passthrough_input_only)
+{
+  // Test that the passthrough resampler works when there is only an output stream.
+  cubeb_stream_params input_params;
+
+  const size_t input_channels = 2;
+  input_params.channels = input_channels;
+  input_params.rate = 44100;
+  input_params.format = CUBEB_SAMPLE_FLOAT32NE;
+  int target_rate = input_params.rate;
+
+  cubeb_resampler * resampler =
+    cubeb_resampler_create((cubeb_stream*)nullptr, &input_params, nullptr,
+                           target_rate, cb_passthrough_resampler_input, nullptr,
+                           CUBEB_RESAMPLER_QUALITY_VOIP);
+
+  float input_buffer[input_channels * 256];
+
+  long got;
+  for (uint32_t i = 0; i < 30; i++) {
+    long int frames = 256;
+    got = cubeb_resampler_fill(resampler, input_buffer, &frames, nullptr, 0);
+    ASSERT_EQ(got, 256);
+  }
+}
+
+template<typename T>
+long seq(T* array, int stride, long start, long count)
+{
+  for(int i = 0; i < count; i++) {
+    for (int j = 0; j < stride; j++) {
+      array[i + j] = static_cast<T>(start + i);
+    }
+  }
+  return start + count;
+}
+
+template<typename T>
+void is_seq(T * array, int stride, long count, long expected_start)
+{
+  uint32_t output_index = 0;
+  for (long i = 0; i < count; i++) {
+    for (int j = 0; j < stride; j++) {
+      ASSERT_EQ(array[output_index + j], expected_start + i);
+    }
+    output_index += stride;
+  }
+}
+
+// gtest does not support using ASSERT_EQ and friend in a function that returns
+// a value.
+template<typename T>
+void check_duplex(const T * input_buffer,
+                  T * output_buffer, long frame_count)
+{
+  ASSERT_EQ(frame_count, 256);
+  // Silence scan-build warning.
+  ASSERT_TRUE(!!output_buffer); assert(output_buffer);
+  ASSERT_TRUE(!!input_buffer); assert(input_buffer);
+
+  int output_index = 0;
+  for (int i = 0; i < frame_count; i++) {
+    // output is two channels, input is one channel, we upmix.
+    output_buffer[output_index] = output_buffer[output_index+1] = input_buffer[i];
+    output_index += 2;
+  }
+}
+
+long cb_passthrough_resampler_duplex(cubeb_stream * /*stm*/, void * /*user_ptr*/,
+                                     const void * input_buffer,
+                                     void * output_buffer, long frame_count)
+{
+  check_duplex<float>(static_cast<const float*>(input_buffer), static_cast<float*>(output_buffer), frame_count);
+  return frame_count;
+}
+
+
+TEST(cubeb, resampler_passthrough_duplex_callback_reordering)
+{
+  // Test that when pre-buffering on resampler creation, we can survive an input
+  // callback being delayed.
+
+  cubeb_stream_params input_params;
+  cubeb_stream_params output_params;
+
+  const int input_channels = 1;
+  const int output_channels = 2;
+
+  input_params.channels = input_channels;
+  input_params.rate = 44100;
+  input_params.format = CUBEB_SAMPLE_FLOAT32NE;
+
+  output_params.channels = output_channels;
+  output_params.rate = input_params.rate;
+  output_params.format = CUBEB_SAMPLE_FLOAT32NE;
+
+  int target_rate = input_params.rate;
+
+  cubeb_resampler * resampler =
+    cubeb_resampler_create((cubeb_stream*)nullptr, &input_params, &output_params,
+                           target_rate, cb_passthrough_resampler_duplex, nullptr,
+                           CUBEB_RESAMPLER_QUALITY_VOIP);
+
+  const long BUF_BASE_SIZE = 256;
+  float input_buffer_prebuffer[input_channels * BUF_BASE_SIZE * 2];
+  float input_buffer_glitch[input_channels * BUF_BASE_SIZE * 2];
+  float input_buffer_normal[input_channels * BUF_BASE_SIZE];
+  float output_buffer[output_channels * BUF_BASE_SIZE];
+
+  long seq_idx = 0;
+  long output_seq_idx = 0;
+
+  long prebuffer_frames = ARRAY_LENGTH(input_buffer_prebuffer) / input_params.channels;
+  seq_idx = seq(input_buffer_prebuffer, input_channels, seq_idx,
+                prebuffer_frames);
+
+  long got = cubeb_resampler_fill(resampler, input_buffer_prebuffer, &prebuffer_frames,
+                                  output_buffer, BUF_BASE_SIZE);
+
+  output_seq_idx += BUF_BASE_SIZE;
+
+  ASSERT_EQ(prebuffer_frames, static_cast<long>(ARRAY_LENGTH(input_buffer_prebuffer) / input_params.channels));
+  ASSERT_EQ(got, BUF_BASE_SIZE);
+
+  for (uint32_t i = 0; i < 300; i++) {
+    long int frames = BUF_BASE_SIZE;
+    // Simulate that sometimes, we don't have the input callback on time
+    if (i != 0 && (i % 100) == 0) {
+      long zero = 0;
+      got = cubeb_resampler_fill(resampler, input_buffer_normal /* unused here */,
+                                 &zero, output_buffer, BUF_BASE_SIZE);
+      is_seq(output_buffer, 2, BUF_BASE_SIZE, output_seq_idx);
+      output_seq_idx += BUF_BASE_SIZE;
+    } else if (i != 0 && (i % 100) == 1) {
+      // if this is the case, the on the next iteration, we'll have twice the
+      // amount of input frames
+      seq_idx = seq(input_buffer_glitch, input_channels, seq_idx, BUF_BASE_SIZE * 2);
+      frames = 2 * BUF_BASE_SIZE;
+      got = cubeb_resampler_fill(resampler, input_buffer_glitch, &frames, output_buffer, BUF_BASE_SIZE);
+      is_seq(output_buffer, 2, BUF_BASE_SIZE, output_seq_idx);
+      output_seq_idx += BUF_BASE_SIZE;
+    } else {
+       // normal case
+      seq_idx = seq(input_buffer_normal, input_channels, seq_idx, BUF_BASE_SIZE);
+      long normal_input_frame_count = 256;
+      got = cubeb_resampler_fill(resampler, input_buffer_normal, &normal_input_frame_count, output_buffer, BUF_BASE_SIZE);
+      is_seq(output_buffer, 2, BUF_BASE_SIZE, output_seq_idx);
+      output_seq_idx += BUF_BASE_SIZE;
+    }
+    ASSERT_EQ(got, BUF_BASE_SIZE);
+  }
+}
--- a/media/libcubeb/src/cubeb-internal.h
+++ b/media/libcubeb/src/cubeb-internal.h
@@ -4,16 +4,17 @@
  * This program is made available under an ISC-style license.  See the
  * accompanying file LICENSE for details.
  */
 #if !defined(CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5)
 #define CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5
 
 #include "cubeb/cubeb.h"
 #include "cubeb_log.h"
+#include "cubeb_assert.h"
 #include <stdio.h>
 #include <string.h>
 
 #ifdef __clang__
 #ifndef CLANG_ANALYZER_NORETURN
 #if __has_feature(attribute_analyzer_noreturn)
 #define CLANG_ANALYZER_NORETURN __attribute__((analyzer_noreturn))
 #else
@@ -23,19 +24,16 @@
 #else // __clang__
 #define CLANG_ANALYZER_NORETURN
 #endif
 
 #if defined(__cplusplus)
 extern "C" {
 #endif
 
-/* Crash the caller.  */
-void cubeb_crash() CLANG_ANALYZER_NORETURN;
-
 #if defined(__cplusplus)
 }
 #endif
 
 typedef struct {
   char const * name;
   unsigned int const channels;
   cubeb_channel_layout const layout;
@@ -80,16 +78,9 @@ struct cubeb_ops {
   int (* stream_register_device_changed_callback)(cubeb_stream * stream,
                                                   cubeb_device_changed_callback device_changed_callback);
   int (* register_device_collection_changed)(cubeb * context,
                                              cubeb_device_type devtype,
                                              cubeb_device_collection_changed_callback callback,
                                              void * user_ptr);
 };
 
-#define XASSERT(expr) do {                                                     \
-    if (!(expr)) {                                                             \
-      fprintf(stderr, "%s:%d - fatal error: %s\n", __FILE__, __LINE__, #expr); \
-      cubeb_crash();                                                           \
-    }                                                                          \
-  } while (0)
-
 #endif /* CUBEB_INTERNAL_0eb56756_4e20_4404_a76d_42bf88cd15a5 */
--- a/media/libcubeb/src/cubeb.c
+++ b/media/libcubeb/src/cubeb.c
@@ -103,22 +103,22 @@ validate_latency(int latency)
   }
   return CUBEB_OK;
 }
 
 int
 cubeb_init(cubeb ** context, char const * context_name)
 {
   int (* init[])(cubeb **, char const *) = {
+#if defined(USE_PULSE)
+    pulse_init,
+#endif
 #if defined(USE_JACK)
     jack_init,
 #endif
-#if defined(USE_PULSE)
-    pulse_init,
-#endif
 #if defined(USE_ALSA)
     alsa_init,
 #endif
 #if defined(USE_AUDIOUNIT)
     audiounit_init,
 #endif
 #if defined(USE_WASAPI)
     wasapi_init,
@@ -565,14 +565,8 @@ int cubeb_set_log_callback(cubeb_log_lev
   }
 
   g_log_callback = log_callback;
   g_log_level = log_level;
 
   return CUBEB_OK;
 }
 
-void
-cubeb_crash()
-{
-  abort();
-  *((volatile int *) NULL) = 0;
-}
new file mode 100644
--- /dev/null
+++ b/media/libcubeb/src/cubeb_assert.h
@@ -0,0 +1,17 @@
+/* -*- 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/. */
+
+#ifndef CUBEB_ASSERT
+#define CUBEB_ASSERT
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mozilla/Assertions.h>
+
+/* Forward fatal asserts to MOZ_ASSERT when built inside Gecko. */
+#define XASSERT(expr) MOZ_ASSERT(expr)
+
+#endif
--- a/media/libcubeb/src/cubeb_pulse.c
+++ b/media/libcubeb/src/cubeb_pulse.c
@@ -1235,17 +1235,17 @@ pulse_get_state_from_sink_port(pa_sink_p
 #if PA_CHECK_VERSION(2, 0, 0)
     if (info->available == PA_PORT_AVAILABLE_NO)
       return CUBEB_DEVICE_STATE_UNPLUGGED;
     else /*if (info->available == PA_PORT_AVAILABLE_YES) + UNKNOWN */
 #endif
       return CUBEB_DEVICE_STATE_ENABLED;
   }
 
-  return CUBEB_DEVICE_STATE_DISABLED;
+  return CUBEB_DEVICE_STATE_ENABLED;
 }
 
 static void
 pulse_sink_info_cb(pa_context * context, const pa_sink_info * info,
                    int eol, void * user_data)
 {
   pulse_dev_list_data * list_data = user_data;
   cubeb_device_info * devinfo;
@@ -1265,17 +1265,18 @@ pulse_sink_info_cb(pa_context * context,
   if (prop)
     devinfo->group_id = strdup(prop);
   prop = WRAP(pa_proplist_gets)(info->proplist, "device.vendor.name");
   if (prop)
     devinfo->vendor_name = strdup(prop);
 
   devinfo->type = CUBEB_DEVICE_TYPE_OUTPUT;
   devinfo->state = pulse_get_state_from_sink_port(info->active_port);
-  devinfo->preferred = strcmp(info->name, list_data->default_sink_name) == 0;
+  devinfo->preferred = (strcmp(info->name, list_data->default_sink_name) == 0) ?
+				 CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
 
   devinfo->format = CUBEB_DEVICE_FMT_ALL;
   devinfo->default_format = pulse_format_to_cubeb_format(info->sample_spec.format);
   devinfo->max_channels = info->channel_map.channels;
   devinfo->min_rate = 1;
   devinfo->max_rate = PA_RATE_MAX;
   devinfo->default_rate = info->sample_spec.rate;
 
@@ -1295,17 +1296,17 @@ pulse_get_state_from_source_port(pa_sour
 #if PA_CHECK_VERSION(2, 0, 0)
     if (info->available == PA_PORT_AVAILABLE_NO)
       return CUBEB_DEVICE_STATE_UNPLUGGED;
     else /*if (info->available == PA_PORT_AVAILABLE_YES) + UNKNOWN */
 #endif
       return CUBEB_DEVICE_STATE_ENABLED;
   }
 
-  return CUBEB_DEVICE_STATE_DISABLED;
+  return CUBEB_DEVICE_STATE_ENABLED;
 }
 
 static void
 pulse_source_info_cb(pa_context * context, const pa_source_info * info,
     int eol, void * user_data)
 {
   pulse_dev_list_data * list_data = user_data;
   cubeb_device_info * devinfo;
@@ -1325,17 +1326,18 @@ pulse_source_info_cb(pa_context * contex
   if (prop)
     devinfo->group_id = strdup(prop);
   prop = WRAP(pa_proplist_gets)(info->proplist, "device.vendor.name");
   if (prop)
     devinfo->vendor_name = strdup(prop);
 
   devinfo->type = CUBEB_DEVICE_TYPE_INPUT;
   devinfo->state = pulse_get_state_from_source_port(info->active_port);
-  devinfo->preferred = strcmp(info->name, list_data->default_source_name) == 0;
+  devinfo->preferred = (strcmp(info->name, list_data->default_source_name) == 0) ?
+				   CUBEB_DEVICE_PREF_ALL : CUBEB_DEVICE_PREF_NONE;
 
   devinfo->format = CUBEB_DEVICE_FMT_ALL;
   devinfo->default_format = pulse_format_to_cubeb_format(info->sample_spec.format);
   devinfo->max_channels = info->channel_map.channels;
   devinfo->min_rate = 1;
   devinfo->max_rate = PA_RATE_MAX;
   devinfo->default_rate = info->sample_spec.rate;
 
--- a/media/libcubeb/src/cubeb_resampler.cpp
+++ b/media/libcubeb/src/cubeb_resampler.cpp
@@ -30,39 +30,56 @@ to_speex_quality(cubeb_resampler_quality
   case CUBEB_RESAMPLER_QUALITY_DESKTOP:
     return SPEEX_RESAMPLER_QUALITY_DESKTOP;
   default:
     assert(false);
     return 0XFFFFFFFF;
   }
 }
 
-long noop_resampler::fill(void * input_buffer, long * input_frames_count,
-                          void * output_buffer, long output_frames)
+template<typename T>
+passthrough_resampler<T>::passthrough_resampler(cubeb_stream * s,
+                                                cubeb_data_callback cb,
+                                                void * ptr,
+                                                uint32_t input_channels)
+  : processor(input_channels)
+  , stream(s)
+  , data_callback(cb)
+  , user_ptr(ptr)
+{
+}
+
+template<typename T>
+long passthrough_resampler<T>::fill(void * input_buffer, long * input_frames_count,
+                                    void * output_buffer, long output_frames)
 {
   if (input_buffer) {
     assert(input_frames_count);
   }
   assert((input_buffer && output_buffer &&
-         *input_frames_count >= output_frames) ||
-         (!input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
-         (!output_buffer && output_frames == 0));
+         *input_frames_count + static_cast<int>(samples_to_frames(internal_input_buffer.length())) >= output_frames) ||
+         (output_buffer && !input_buffer && (!input_frames_count || *input_frames_count == 0)) ||
+         (input_buffer && !output_buffer && output_frames == 0));
 
-  if (output_buffer == nullptr) {
-    assert(input_buffer);
-    output_frames = *input_frames_count;
+  if (input_buffer) {
+    if (!output_buffer) {
+      output_frames = *input_frames_count;
+    }
+    internal_input_buffer.push(static_cast<T*>(input_buffer),
+                               frames_to_samples(*input_frames_count));
   }
 
-  if (input_buffer && *input_frames_count != output_frames) {
-    assert(*input_frames_count > output_frames);
-    *input_frames_count = output_frames;
+  long rv = data_callback(stream, user_ptr, internal_input_buffer.data(),
+                          output_buffer, output_frames);
+
+  if (input_buffer) {
+    internal_input_buffer.pop(nullptr, frames_to_samples(output_frames));
   }
 
-  return data_callback(stream, user_ptr,
-                       input_buffer, output_buffer, output_frames);
+  return rv;
 }
 
 template<typename T, typename InputProcessor, typename OutputProcessor>
 cubeb_resampler_speex<T, InputProcessor, OutputProcessor>
   ::cubeb_resampler_speex(InputProcessor * input_processor,
                           OutputProcessor * output_processor,
                           cubeb_stream * s,
                           cubeb_data_callback cb,
--- a/media/libcubeb/src/cubeb_resampler_internal.h
+++ b/media/libcubeb/src/cubeb_resampler_internal.h
@@ -43,41 +43,16 @@ int to_speex_quality(cubeb_resampler_qua
 
 struct cubeb_resampler {
   virtual long fill(void * input_buffer, long * input_frames_count,
                     void * output_buffer, long frames_needed) = 0;
   virtual long latency() = 0;
   virtual ~cubeb_resampler() {}
 };
 
-class noop_resampler : public cubeb_resampler {
-public:
-  noop_resampler(cubeb_stream * s,
-                 cubeb_data_callback cb,
-                 void * ptr)
-    : stream(s)
-    , data_callback(cb)
-    , user_ptr(ptr)
-  {
-  }
-
-  virtual long fill(void * input_buffer, long * input_frames_count,
-                    void * output_buffer, long output_frames);
-
-  virtual long latency()
-  {
-    return 0;
-  }
-
-private:
-  cubeb_stream * const stream;
-  const cubeb_data_callback data_callback;
-  void * const user_ptr;
-};
-
 /** Base class for processors. This is just used to share methods for now. */
 class processor {
 public:
   explicit processor(uint32_t channels)
     : channels(channels)
   {}
 protected:
   size_t frames_to_samples(size_t frames)
@@ -88,16 +63,42 @@ protected:
   {
     assert(!(samples % channels));
     return samples / channels;
   }
   /** The number of channel of the audio buffers to be resampled. */
   const uint32_t channels;
 };
 
+template<typename T>
+class passthrough_resampler : public cubeb_resampler
+                            , public processor {
+public:
+  passthrough_resampler(cubeb_stream * s,
+                        cubeb_data_callback cb,
+                        void * ptr,
+                        uint32_t input_channels);
+
+  virtual long fill(void * input_buffer, long * input_frames_count,
+                    void * output_buffer, long output_frames);
+
+  virtual long latency()
+  {
+    return 0;
+  }
+
+private:
+  cubeb_stream * const stream;
+  const cubeb_data_callback data_callback;
+  void * const user_ptr;
+  /* This allows to buffer some input to account for the fact that we buffer
+   * some inputs. */
+  auto_array<T> internal_input_buffer;
+};
+
 /** Bidirectional resampler, can resample an input and an output stream, or just
  * an input stream or output stream. In this case a delay is inserted in the
  * opposite direction to keep the streams synchronized. */
 template<typename T, typename InputProcessing, typename OutputProcessing>
 class cubeb_resampler_speex : public cubeb_resampler {
 public:
   cubeb_resampler_speex(InputProcessing * input_processor,
                         OutputProcessing * output_processor,
@@ -475,17 +476,19 @@ cubeb_resampler_create_internal(cubeb_st
 
   /* All the streams we have have a sample rate that matches the target
      sample rate, use a no-op resampler, that simply forwards the buffers to the
      callback. */
   if (((input_params && input_params->rate == target_rate) &&
       (output_params && output_params->rate == target_rate)) ||
       (input_params && !output_params && (input_params->rate == target_rate)) ||
       (output_params && !input_params && (output_params->rate == target_rate))) {
-    return new noop_resampler(stream, callback, user_ptr);
+    return new passthrough_resampler<T>(stream, callback,
+                                        user_ptr,
+                                        input_params ? input_params->channels : 0);
   }
 
   /* Determine if we need to resampler one or both directions, and create the
      resamplers. */
   if (output_params && (output_params->rate != target_rate)) {
     output_resampler.reset(
         new cubeb_resampler_speex_one_way<T>(output_params->channels,
                                              target_rate,
--- a/media/libcubeb/src/cubeb_sndio.c
+++ b/media/libcubeb/src/cubeb_sndio.c
@@ -240,17 +240,17 @@ sndio_stream_init(cubeb * context,
   sio_onmove(s->hdl, sndio_onmove, s);
   s->active = 0;
   s->nfr = rpar.round;
   s->bpf = rpar.bps * rpar.pchan;
   s->pchan = rpar.pchan;
   s->data_cb = data_callback;
   s->state_cb = state_callback;
   s->arg = user_ptr;
-  s->mtx = PTHREAD_MUTEX_INITIALIZER;
+  s->mtx = (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
   s->rdpos = s->wrpos = 0;
   if (output_stream_params->format == CUBEB_SAMPLE_FLOAT32LE) {
     s->conv = 1;
     size = rpar.round * rpar.pchan * sizeof(float);
   } else {
     s->conv = 0;
     size = rpar.round * rpar.pchan * rpar.bps;
   }
--- a/media/libcubeb/src/cubeb_wasapi.cpp
+++ b/media/libcubeb/src/cubeb_wasapi.cpp
@@ -742,25 +742,16 @@ refill_callback_duplex(cubeb_stream * st
   }
 
   /* This can only happen when debugging, and having breakpoints set in the
    * callback in a way that it makes the stream underrun. */
   if (output_frames == 0) {
     return true;
   }
 
-  // When WASAPI has not filled the input buffer yet, send silence.
-  double output_duration = double(output_frames) / stm->output_mix_params.rate;
-  double input_duration = double(stm->linear_input_buffer.length() / stm->input_stream_params.channels) / stm->input_mix_params.rate;
-  if (input_duration < output_duration) {
-    size_t padding = size_t(round((output_duration - input_duration) * stm->input_mix_params.rate));
-    LOG("padding silence: out=%f in=%f pad=%u", output_duration, input_duration, padding);
-    stm->linear_input_buffer.push_front_silence(padding * stm->input_stream_params.channels);
-  }
-
   LOGV("Duplex callback: input frames: %Iu, output frames: %Iu",
        stm->linear_input_buffer.length(), output_frames);
 
   refill(stm,
          stm->linear_input_buffer.data(),
          stm->linear_input_buffer.length(),
          output_buffer,
          output_frames);
@@ -1646,16 +1637,24 @@ int setup_wasapi_stream(cubeb_stream * s
                                       stm->input_device.get(),
                                       eCapture,
                                       __uuidof(IAudioCaptureClient),
                                       stm->input_client,
                                       &stm->input_buffer_frame_count,
                                       stm->input_available_event,
                                       stm->capture_client,
                                       &stm->input_mix_params);
+
+    // We initializing an input stream, buffer ahead two buffers worth of silence.
+    // This delays the input side slightly, but allow to not glitch when no input
+    // is available when calling into the resampler to call the callback: the input
+    // refill event will be set shortly after to compensate for this lack of data.
+    stm->linear_input_buffer.push_silence(stm->input_buffer_frame_count *
+                                          stm->input_stream_params.channels * 2);
+
     if (rv != CUBEB_OK) {
       LOG("Failure to open the input side.");
       return rv;
     }
   }
 
   if (has_output(stm)) {
     LOG("(%p) Setup render: device=%p", stm, stm->output_device.get());
--- a/mobile/android/chrome/content/browser.js
+++ b/mobile/android/chrome/content/browser.js
@@ -1254,19 +1254,19 @@ var BrowserApp = {
       this.selectedTab = null;
 
     let tabIndex = this._tabs.indexOf(aTab);
 
     let evt = document.createEvent("UIEvents");
     evt.initUIEvent("TabClose", true, false, window, tabIndex);
     aTab.browser.dispatchEvent(evt);
 
-    if (aShowUndoSnackbar) {
+    let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
+    if (aShowUndoSnackbar && ss.canUndoLastCloseTab) {
       // Get a title for the undo close snackbar. Fall back to the URL if there is no title.
-      let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
       let closedTabData = ss.getClosedTabs(window)[0];
 
       if (closedTabData) {
         let message;
         let title = closedTabData.entries[closedTabData.index - 1].title;
         let isPrivate = PrivateBrowsingUtils.isBrowserPrivate(aTab.browser);
 
         if (isPrivate) {
@@ -4369,17 +4369,17 @@ Tab.prototype = {
     this.shouldShowPluginDoorhanger = true;
     this.clickToPlayPluginsActivated = false;
 
     let documentURI = contentWin.document.documentURIObject.spec;
 
     // If reader mode, get the base domain for the original url.
     let strippedURI = this._stripAboutReaderURL(documentURI);
 
-    // Borrowed from desktop Firefox: http://hg.mozilla.org/mozilla-central/annotate/72835344333f/browser/base/content/urlbarBindings.xml#l236
+    // Borrowed from desktop Firefox: https://hg.mozilla.org/mozilla-central/annotate/72835344333f/browser/base/content/urlbarBindings.xml#l236
     let matchedURL = strippedURI.match(/^((?:[a-z]+:\/\/)?(?:[^\/]+@)?)(.+?)(?::\d+)?(?:\/|$)/);
     let baseDomain = "";
     if (matchedURL) {
       var domain = "";
       [, , domain] = matchedURL;
 
       try {
         baseDomain = Services.eTLD.getBaseDomainFromHost(domain);
--- a/mobile/android/components/SessionStore.idl
+++ b/mobile/android/components/SessionStore.idl
@@ -45,16 +45,21 @@ interface nsISessionStore : nsISupports
 
   /**
    * @param aWindow is the browser window associated with the closed tab.
    * @param aIndex  is the index of the closed tab to be removed (FIFO ordered).
    */
   nsIDOMNode forgetClosedTab(in nsIDOMWindow aWindow, in unsigned long aIndex);
 
   /**
+   * Whether the "Undo close tab" message should be shown or not after a tab has been closed.
+   */
+ readonly attribute boolean canUndoLastCloseTab;
+
+  /**
    * @param aTab is the browser tab to get the value for.
    * @param aKey is the value's name.
    * 
    * @returns A string value or an empty string if none is set.
    */
   AString getTabValue(in jsval aTab, in AString aKey);
 
   /**
--- a/mobile/android/components/SessionStore.js
+++ b/mobile/android/components/SessionStore.js
@@ -622,24 +622,25 @@ SessionStore.prototype = {
     log("onTabRemove() ran for tab " + aWindow.BrowserApp.getTabForBrowser(aBrowser).id +
         ", aNoNotification = " + aNoNotification);
     if (!aNoNotification) {
       this.saveStateDelayed();
     }
   },
 
   onTabClose: function ss_onTabClose(aWindow, aBrowser, aTabIndex) {
-    if (this._maxTabsUndo == 0) {
+    let data = aBrowser.__SS_data || {};
+    if (this._maxTabsUndo == 0 || this._sessionDataIsEmpty(data)) {
+      this._lastClosedTabIndex = -1;
       return;
     }
 
     if (aWindow.BrowserApp.tabs.length > 0) {
       // Bundle this browser's data and extra data and save in the closedTabs
       // window property
-      let data = aBrowser.__SS_data || {};
       data.extData = aBrowser.__SS_extdata || {};
 
       this._windows[aWindow.__SSID].closedTabs.unshift(data);
       let length = this._windows[aWindow.__SSID].closedTabs.length;
       if (length > this._maxTabsUndo) {
         this._windows[aWindow.__SSID].closedTabs.splice(this._maxTabsUndo, length - this._maxTabsUndo);
       }
 
@@ -650,16 +651,27 @@ SessionStore.prototype = {
       }
 
       log("onTabClose() ran for tab " + aWindow.BrowserApp.getTabForBrowser(aBrowser).id);
       let evt = new Event("SSTabCloseProcessed", {"bubbles":true, "cancelable":false});
       aBrowser.dispatchEvent(evt);
     }
   },
 
+  _sessionDataIsEmpty: function ss_sessionDataIsEmpty(aData) {
+    if (!aData || !aData.entries || aData.entries.length == 0) {
+      return true;
+    }
+
+    let entries = aData.entries;
+
+    return (entries.length == 1 &&
+            (entries[0].url == "about:home" || entries[0].url == "about:privatebrowsing"));
+  },
+
   onTabLoad: function ss_onTabLoad(aWindow, aBrowser) {
     // If this browser belongs to a zombie tab or the initial restore hasn't yet finished,
     // skip any session save activity.
     if (aBrowser.__SS_restore || !this._startupRestoreFinished || aBrowser.__SS_restoreReloadPending) {
       return;
     }
 
     // Ignore a transient "about:blank"
@@ -1744,16 +1756,20 @@ SessionStore.prototype = {
     if (aIndex == 0) {
       this._lastClosedTabIndex = -1;
     }
     if (this._notifyClosedTabs) {
       this._sendClosedTabsToJava(aWindow);
     }
   },
 
+  get canUndoLastCloseTab() {
+    return this._lastClosedTabIndex > -1;
+  },
+
   _sendClosedTabsToJava: function ss_sendClosedTabsToJava(aWindow) {
 
     // If the app is shutting down, we don't need to do anything.
     if (this._loadState <= STATE_QUITTING) {
       return;
     }
 
     if (!aWindow.__SSID) {
--- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/domain/PasswordRecord.java
+++ b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/repositories/domain/PasswordRecord.java
@@ -184,17 +184,17 @@ public class PasswordRecord extends Reco
 
   /**
    * A PasswordRecord is considered valid if it abides by the database
    * constraints of the PasswordsProvider (moz_logins).
    *
    * See toolkit/components/passwordmgr/storage-mozStorage.js for the
    * definitions:
    *
-   * http://hg.mozilla.org/mozilla-central/file/00955d61cc94/toolkit/components/passwordmgr/storage-mozStorage.js#l98
+   * https://hg.mozilla.org/mozilla-central/file/00955d61cc94/toolkit/components/passwordmgr/storage-mozStorage.js#l98
    */
     public boolean isValid() {
         if (this.deleted) {
             return true;
         }
 
         return this.hostname != null &&
                this.encryptedUsername != null &&
--- a/mobile/android/tests/browser/robocop/reader_mode_pages/developer.mozilla.org/en/XULRunner/Build_Instructions.html
+++ b/mobile/android/tests/browser/robocop/reader_mode_pages/developer.mozilla.org/en/XULRunner/Build_Instructions.html
@@ -253,17 +253,17 @@ ac_add_options --enable-application=xulr
 <p>For instance XULRunner 1.8.1.3, the corresponding tag is CVS is : FIREFOX_2_0_0_3_RELEASE</p>
 <p>To find out how those Firefox tags and XULRunner version maps, check out the file mozilla/config/milestone.txt .</p>
 <p>You can also check the User Agent string in Firefox Help/About menu to get the mapping from a certain binary Firefox version to the corresponding XULRunner version. For instance, in Firefox 2.0.0.9 you will get :</p>
 <pre class="eval">Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.9) Gecko/20071025 Firefox/2.0.0.9
 </pre>
 <p>Therefore the XULRunner version for this Firefox version is : 1.8.1.9</p>
 <h3 id="Fetching_Sources_from_Mercurial">Fetching Sources from Mercurial</h3>
 <p>As with all other Mozilla products, one would fetch recent sources from Mercurial. For example, to build XULRunner with the top of the tree:</p>
-<pre>hg clone http://hg.mozilla.org/mozilla-central/ src
+<pre>hg clone https://hg.mozilla.org/mozilla-central/ src
 cd src
 echo ". \$topsrcdir/xulrunner/config/mozconfig" &gt; .mozconfig
 make -f client.mk build
 </pre>
 <p><span>Interwiki Language Links</span></p>
 <p></p>
                   </div>
     <section class="page-meta">
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryDecoder.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryDecoder.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryEncoder.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/BinaryEncoder.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/CharEncoding.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/CharEncoding.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Decoder.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Decoder.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/DecoderException.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/DecoderException.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Encoder.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/Encoder.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/EncoderException.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/EncoderException.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringDecoder.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringDecoder.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoder.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoder.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoderComparator.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/StringEncoderComparator.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32InputStream.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32InputStream.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32OutputStream.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base32OutputStream.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64InputStream.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64InputStream.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64OutputStream.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Base64OutputStream.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodec.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodec.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecInputStream.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecInputStream.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecOutputStream.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BaseNCodecOutputStream.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BinaryCodec.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/BinaryCodec.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Hex.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/Hex.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/StringUtils.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/binary/StringUtils.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/DigestUtils.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/digest/DigestUtils.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/AbstractCaverphone.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/AbstractCaverphone.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone1.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone1.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone2.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Caverphone2.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/ColognePhonetic.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/ColognePhonetic.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/DoubleMetaphone.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/DoubleMetaphone.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Metaphone.java
+++ b/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/Metaphone.java
@@ -1,9 +1,9 @@
-// Mozilla has modified this file - see http://hg.mozilla.org/ for details.
+// Mozilla has modified this file - see https://hg.mozilla.org/ for details.
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.
  * The ASF licenses this file to You under the Apache License, Version 2.0
  * (the "License"); you may not use this file except in compliance with
  * the License.  You may obtain a copy of the License at
  * 
--- a/mobile/android/thirdparty/org/mozilla/apache/commons/codec/language/RefinedSoundex.java
+++ b/mobile/android/thirdparty/org/mozi