Merge inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 10 Feb 2015 16:03:15 -0500
changeset 242096 ee093ca706662491d356484bf729ef32d55bc19c
parent 242093 9ac2e8cd4faff33702ff849bea34e54db18c2f0b (current diff)
parent 242095 19cbffb1bf61413cbc185a92da3277f87ca0f409 (diff)
child 242097 3f3a914ea90270557adfa14256657922e7c708f9
child 242099 7152dc5221cb10bc9c44d331778bf52610778a75
child 242112 b4c687e6c60fd086a6c7e6b0f9ad0c224d0e6386
child 242114 4e48201d1e91361b80127e8dc423fb4e31fe5b72
child 242123 b04123c901ac90b12dffe6ca25f8765126cca0cc
child 242127 b6e3ed527a348ad193fc9512068bae1c703eda43
child 242135 f17a80ddf9fd942b4d120602d0f8fbbb290e22ce
child 251377 77eae7ac6dfaa15c9e66733bf9b9780c2f6f8f80
push id634
push usermozilla@noorenberghe.ca
push dateTue, 10 Feb 2015 22:34:30 +0000
reviewersmerge
milestone38.0a1
Merge inbound to m-c. a=merge CLOSED TREE
dom/base/nsFrameLoader.cpp.rej
dom/base/nsGlobalWindow.cpp
dom/browser-element/BrowserElementChildPreload.js
dom/ipc/ContentChild.cpp
dom/plugins/base/nsNPAPIPlugin.cpp
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginModuleChild.cpp
dom/svg/SVGIFrameElement.cpp
dom/svg/SVGIFrameElement.h
dom/webidl/SVGIFrameElement.webidl
ipc/glue/MessageChannel.h
layout/mathml/nsMathMLmphantomFrame.cpp
layout/mathml/nsMathMLmphantomFrame.h
mobile/android/base/locales/en-US/android_strings.dtd
mobile/android/base/strings.xml.in
netwerk/protocol/http/nsHttpTransaction.cpp
netwerk/protocol/websocket/WebSocketChannel.cpp
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -29,17 +29,20 @@ var security = {
     catch (exception) { }
 
     var ui = security._getSecurityUI();
     if (!ui)
       return null;
 
     var isBroken =
       (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_BROKEN);
-    var isInsecure = 
+    var isMixed =
+      (ui.state & (Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_ACTIVE_CONTENT |
+                   Components.interfaces.nsIWebProgressListener.STATE_LOADED_MIXED_DISPLAY_CONTENT));
+    var isInsecure =
       (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IS_INSECURE);
     var isEV =
       (ui.state & Components.interfaces.nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL);
     ui.QueryInterface(nsISSLStatusProvider);
     var status = ui.SSLStatus;
 
     if (!isInsecure && status) {
       status.QueryInterface(nsISSLStatus);
@@ -49,16 +52,17 @@ var security = {
 
       var retval = {
         hostName : hName,
         cAName : issuerName,
         encryptionAlgorithm : undefined,
         encryptionStrength : undefined,
         version: undefined,
         isBroken : isBroken,
+        isMixed : isMixed,
         isEV : isEV,
         cert : cert,
         fullLocation : gWindow.location
       };
 
       var version;
       try {
         retval.encryptionAlgorithm = status.cipherName;
@@ -87,16 +91,17 @@ var security = {
     } else {
       return {
         hostName : hName,
         cAName : "",
         encryptionAlgorithm : "",
         encryptionStrength : 0,
         version: "",
         isBroken : isBroken,
+        isMixed : isMixed,
         isEV : isEV,
         cert : null,
         fullLocation : gWindow.location
       };
     }
   },
 
   // Find the secureBrowserUI object (if present)
@@ -248,17 +253,24 @@ function securityOnLoad() {
 
   /* Set the Technical Detail section messages */
   const pkiBundle = document.getElementById("pkiBundle");
   var hdr;
   var msg1;
   var msg2;
 
   if (info.isBroken) {
-    hdr = pkiBundle.getString("pageInfo_MixedContent");
+    if (info.isMixed) {
+      hdr = pkiBundle.getString("pageInfo_MixedContent");
+    } else {
+      hdr = pkiBundle.getFormattedString("pageInfo_BrokenEncryption",
+                                         [info.encryptionAlgorithm,
+                                          info.encryptionStrength + "",
+                                          info.version]);
+    }
     msg1 = pkiBundle.getString("pageInfo_Privacy_Broken1");
     msg2 = pkiBundle.getString("pageInfo_Privacy_None2");
   }
   else if (info.encryptionStrength > 0) {
     hdr = pkiBundle.getFormattedString("pageInfo_EncryptionWithBitsAndProtocol",
                                        [info.encryptionAlgorithm,
                                         info.encryptionStrength + "",
                                         info.version]);
--- a/browser/devtools/netmonitor/test/browser_net_security-state.js
+++ b/browser/devtools/netmonitor/test/browser_net_security-state.js
@@ -11,16 +11,22 @@
 add_task(function* () {
   const EXPECTED_SECURITY_STATES = {
     "test1.example.com": "security-state-insecure",
     "example.com": "security-state-secure",
     "nocert.example.com": "security-state-broken",
     "rc4.example.com": "security-state-weak",
   };
 
+  yield new promise(resolve => {
+    SpecialPowers.pushPrefEnv({"set": [
+      ["security.tls.insecure_fallback_hosts", "rc4.example.com"]
+    ]}, resolve);
+  });
+
   let [tab, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL);
   let { $, EVENTS, NetMonitorView } = monitor.panelWin;
   let { RequestsMenu } = NetMonitorView;
   RequestsMenu.lazyUpdate = false;
 
   yield performRequests();
 
   for (let item of RequestsMenu.items) {
--- a/browser/devtools/netmonitor/test/browser_net_security-warnings.js
+++ b/browser/devtools/netmonitor/test/browser_net_security-warnings.js
@@ -35,19 +35,22 @@ const TEST_CASES = [
 ];
 
 add_task(function* () {
   let [tab, debuggee, monitor] = yield initNetMonitor(CUSTOM_GET_URL);
   let { $, EVENTS, NetMonitorView } = monitor.panelWin;
   let { RequestsMenu, NetworkDetails } = NetMonitorView;
   RequestsMenu.lazyUpdate = false;
 
-  info("Enabling SSLv3 for the test.");
+  info("Enabling SSLv3 and RC4 for the test.");
   yield new promise(resolve => {
-    SpecialPowers.pushPrefEnv({"set": [["security.tls.version.min", 0]]}, resolve);
+    SpecialPowers.pushPrefEnv({"set": [
+      ["security.tls.version.min", 0],
+      ["security.tls.insecure_fallback_hosts", "rc4.example.com,ssl3rc4.example.com"]
+    ]}, resolve);
   });
 
   let cipher = $("#security-warning-cipher");
   let sslv3 = $("#security-warning-sslv3");
 
   for (let test of TEST_CASES) {
     info("Testing site with " + test.desc);
 
--- a/browser/modules/WindowsPreviewPerTab.jsm
+++ b/browser/modules/WindowsPreviewPerTab.jsm
@@ -93,17 +93,17 @@ function _imageFromURI(doc, uri, private
       let out_img = { value: null };
       imgTools.decodeImageData(inputStream, channel.contentType, out_img);
       callback(out_img.value);
     } catch (e) {
       // We failed, so use the default favicon (only if this wasn't the default
       // favicon).
       let defaultURI = faviconSvc.defaultFavicon;
       if (!defaultURI.equals(uri))
-        _imageFromURI(defaultURI, callback);
+        _imageFromURI(doc, defaultURI, privateMode, callback);
     }
   });
 }
 
 // string? -> imgIContainer
 function getFaviconAsImage(doc, iconurl, privateMode, callback) {
   if (iconurl)
     _imageFromURI(doc, NetUtil.newURI(iconurl), privateMode, callback);
--- a/chrome/nsChromeRegistryContent.cpp
+++ b/chrome/nsChromeRegistryContent.cpp
@@ -17,18 +17,18 @@ nsChromeRegistryContent::nsChromeRegistr
 void
 nsChromeRegistryContent::RegisterRemoteChrome(
     const InfallibleTArray<ChromePackage>& aPackages,
     const InfallibleTArray<ResourceMapping>& aResources,
     const InfallibleTArray<OverrideMapping>& aOverrides,
     const nsACString& aLocale,
     bool aReset)
 {
-  NS_ABORT_IF_FALSE(aReset || mLocale.IsEmpty(),
-                    "RegisterChrome twice?");
+  MOZ_ASSERT(aReset || mLocale.IsEmpty(),
+             "RegisterChrome twice?");
 
   if (aReset) {
     mPackagesHash.Clear();
     mOverrideTable.Clear();
     // XXX Can't clear resources.
   }
 
   for (uint32_t i = aPackages.Length(); i > 0; ) {
--- a/dom/animation/Animation.cpp
+++ b/dom/animation/Animation.cpp
@@ -22,17 +22,17 @@ ComputedTimingFunction::Init(const nsTim
   } else {
     mSteps = aFunction.mSteps;
   }
 }
 
 static inline double
 StepEnd(uint32_t aSteps, double aPortion)
 {
-  NS_ABORT_IF_FALSE(0.0 <= aPortion && aPortion <= 1.0, "out of range");
+  MOZ_ASSERT(0.0 <= aPortion && aPortion <= 1.0, "out of range");
   uint32_t step = uint32_t(aPortion * aSteps); // floor
   return double(step) / double(aSteps);
 }
 
 double
 ComputedTimingFunction::GetValue(double aPortion) const
 {
   switch (mType) {
@@ -42,17 +42,17 @@ ComputedTimingFunction::GetValue(double 
       // There are diagrams in the spec that seem to suggest this check
       // and the bounds point should not be symmetric with StepEnd, but
       // should actually step up at rather than immediately after the
       // fraction points.  However, we rely on rounding negative values
       // up to zero, so we can't do that.  And it's not clear the spec
       // really meant it.
       return 1.0 - StepEnd(mSteps, 1.0 - aPortion);
     default:
-      NS_ABORT_IF_FALSE(false, "bad type");
+      MOZ_ASSERT(false, "bad type");
       // fall through
     case nsTimingFunction::StepEnd:
       return StepEnd(mSteps, aPortion);
   }
 }
 
 // In the Web Animations model, the time fraction can be outside the range
 // [0.0, 1.0] but it shouldn't be Infinity.
--- a/dom/apps/Webapps.js
+++ b/dom/apps/Webapps.js
@@ -826,16 +826,17 @@ WebappsApplicationMgmt.prototype = {
   init: function(aWindow, aHasFullMgmtPrivilege) {
     this._window = aWindow;
 
     this.initDOMRequestHelper(aWindow, ["Webapps:Uninstall:Return:OK",
                                         "Webapps:Uninstall:Broadcast:Return:OK",
                                         "Webapps:Uninstall:Return:KO",
                                         "Webapps:Install:Return:OK",
                                         "Webapps:GetNotInstalled:Return:OK",
+                                        "Webapps:GetIcon:Return",
                                         "Webapps:Import:Return",
                                         "Webapps:ExtractManifest:Return",
                                         "Webapps:SetEnabled:Return"]);
     cpmm.sendAsyncMessage("Webapps:RegisterForMessages",
                           {
                             messages: ["Webapps:Install:Return:OK",
                                        "Webapps:Uninstall:Return:OK",
                                        "Webapps:Uninstall:Broadcast:Return:OK",
@@ -891,16 +892,31 @@ WebappsApplicationMgmt.prototype = {
     DOMApplicationRegistry.getAll((aApps) => {
       Services.DOMRequest.fireSuccessAsync(request,
                                            convertAppsArray(aApps, window));
     });
 
     return request;
   },
 
+  getIcon: function(aApp, aIconID, aEntryPoint) {
+    return this.createPromise(function(aResolve, aReject) {
+      cpmm.sendAsyncMessage("Webapps:GetIcon", {
+        oid: this._id,
+        manifestURL: aApp.manifestURL,
+        iconID: aIconID,
+        entryPoint: aEntryPoint,
+        requestID: this.getPromiseResolverId({
+          resolve: aResolve,
+          reject: aReject
+        })
+      });
+    }.bind(this));
+  },
+
   getNotInstalled: function() {
     let request = this.createRequest();
     let principal = this._window.document.nodePrincipal;
 
     cpmm.sendAsyncMessage("Webapps:GetNotInstalled", {
       oid: this._id,
       requestID: this.getRequestId(request)
     }, null, principal);
@@ -965,17 +981,18 @@ WebappsApplicationMgmt.prototype = {
   set onenabledstatechange(aCallback) {
     this.__DOM_IMPL__.setEventHandler("onenabledstatechange", aCallback);
   },
 
   receiveMessage: function(aMessage) {
     let msg = aMessage.data;
     let req;
 
-    if (["Webapps:Import:Return",
+    if (["Webapps:GetIcon:Return",
+         "Webapps:Import:Return",
          "Webapps:ExtractManifest:Return"]
          .indexOf(aMessage.name) != -1) {
       req = this.takePromiseResolver(msg.requestID);
     } else {
       req = this.getRequest(msg.requestID);
     }
 
     // We want Webapps:Install:Return:OK, Webapps:Uninstall:Broadcast:Return:OK
@@ -1031,17 +1048,28 @@ WebappsApplicationMgmt.prototype = {
       case "Webapps:SetEnabled:Return":
         {
           let app = createContentApplicationObject(this._window, msg);
           let event =
             new this._window.MozApplicationEvent("enabledstatechange", { application : app });
           this.__DOM_IMPL__.dispatchEvent(event);
         }
         break;
+      case "Webapps:GetIcon:Return":
+        if (msg.blob) {
+          req.resolve(Cu.cloneInto(msg.blob, this._window));
+        } else if (msg.error && msg.error == "NETWORK_ERROR"
+                             && !this._window.navigator.onLine) {
+          req.reject(new this._window.DOMError("NETWORK_OFFLINE"));
+        } else {
+          req.reject(new this._window.DOMError(msg.error || ""));
+        }
+        break;
     }
+
     if (aMessage.name !== "Webapps:Uninstall:Broadcast:Return:OK") {
       this.removeRequest(msg.requestID);
     }
   },
 
   classID: Components.ID("{8c1bca96-266f-493a-8d57-ec7a95098c15}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports,
--- a/dom/apps/Webapps.jsm
+++ b/dom/apps/Webapps.jsm
@@ -219,16 +219,17 @@ this.DOMApplicationRegistry = {
                      "Webapps:ApplyDownload",
                      "Webapps:Install:Return:Ack",
                      "Webapps:AddReceipt",
                      "Webapps:RemoveReceipt",
                      "Webapps:ReplaceReceipt",
                      "Webapps:RegisterBEP",
                      "Webapps:Export",
                      "Webapps:Import",
+                     "Webapps:GetIcon",
                      "Webapps:ExtractManifest",
                      "Webapps:SetEnabled",
                      "child-process-shutdown"];
 
     this.frameMessages = ["Webapps:ClearBrowserData"];
 
     this.messages.forEach((function(msgName) {
       ppmm.addMessageListener(msgName, this);
@@ -645,17 +646,17 @@ this.DOMApplicationRegistry = {
   // Implements the core of bug 787439
   // if at first run, go through these steps:
   //   a. load the core apps registry.
   //   b. uninstall any core app from the current registry but not in the
   //      new core apps registry.
   //   c. for all apps in the new core registry, install them if they are not
   //      yet in the current registry, and run installPermissions()
   installSystemApps: function() {
-    return Task.spawn(function() {
+    return Task.spawn(function*() {
       let file;
       try {
         file = FileUtils.getFile("coreAppsDir", ["webapps", "webapps.json"], false);
       } catch(e) { }
 
       if (!file || !file.exists()) {
         return;
       }
@@ -722,17 +723,17 @@ this.DOMApplicationRegistry = {
             this.webapps[id] = {oldId: oldId};
           }
         }
       }
     }.bind(this)).then(null, Cu.reportError);
   },
 
   loadAndUpdateApps: function() {
-    return Task.spawn(function() {
+    return Task.spawn(function*() {
       let runUpdate = AppsUtils.isFirstRun(Services.prefs);
 
       yield this.loadCurrentRegistry();
 
       // Sanity check and roll back previous incomplete app updates.
       for (let id in this.webapps) {
         let oldDir = FileUtils.getDir(DIRECTORY_NAME, ["webapps", id + ".old"], false, true);
         if (oldDir.exists()) {
@@ -755,23 +756,26 @@ this.DOMApplicationRegistry = {
         if (!systemAppFound) {
           runUpdate = true;
         }
       } catch(e) {} // getCharPref will throw on non-b2g platforms. That's ok.
 
       if (runUpdate) {
 
         // Run migration before uninstall of core apps happens.
-        try {
-          let appMigrator = Components.classes["@mozilla.org/app-migrator;1"].createInstance(Components.interfaces.nsIObserver);
-          appMigrator.observe(null, "webapps-before-update-merge", null);
-        } catch(e) {
-          debug("Exception running app migration: ");
-          debug(e.name + " " + e.message);
-          debug("Skipping app migration.");
+        let appMigrator = Components.classes["@mozilla.org/app-migrator;1"];
+        if (appMigrator) {
+          try {
+              appMigrator = appMigrator.createInstance(Components.interfaces.nsIObserver);
+              appMigrator.observe(null, "webapps-before-update-merge", null);
+          } catch(e) {
+            debug("Exception running app migration: ");
+            debug(e.name + " " + e.message);
+            debug("Skipping app migration.");
+          }
         }
 
 #ifdef MOZ_WIDGET_GONK
         yield this.installSystemApps();
 #endif
 
         // At first run, install preloaded apps and set up their permissions.
         for (let id in this.webapps) {
@@ -1420,16 +1424,19 @@ this.DOMApplicationRegistry = {
           this.removeReceipt(msg, mm);
           break;
         case "Webapps:ReplaceReceipt":
           this.replaceReceipt(msg, mm);
           break;
         case "Webapps:RegisterBEP":
           this.registerBrowserElementParentForApp(msg, mm);
           break;
+        case "Webapps:GetIcon":
+          this.getIcon(msg, mm);
+          break;
         case "Webapps:Export":
           this.doExport(msg, mm);
           break;
         case "Webapps:Import":
           this.doImport(msg, mm);
           break;
         case "Webapps:ExtractManifest":
           this.doExtractManifest(msg, mm);
@@ -2352,17 +2359,16 @@ this.DOMApplicationRegistry = {
         extraHeaders.push({ name: "X-MOZ-B2G-DEVICE",
                             value: device || "unknown" });
       }
 #endif
       doRequest.call(this, aResult[0].manifest, extraHeaders);
     });
   },
 
-
   updatePackagedApp: Task.async(function*(aData, aId, aApp, aNewManifest) {
     debug("updatePackagedApp");
 
     // Store the new update manifest.
     let dir = this._getAppDir(aId).path;
     let manFile = OS.Path.join(dir, "staged-update.webapp");
     yield this._writeFile(manFile, JSON.stringify(aNewManifest));
 
@@ -3030,17 +3036,17 @@ this.DOMApplicationRegistry = {
           this.doUninstall.bind(this, aData, aData.mm)
         );
       }
 
       this.updateDataStore(this.webapps[id].localId,  this.webapps[id].origin,
                            this.webapps[id].manifestURL, jsonManifest);
     }
 
-    for each (let prop in ["installState", "downloadAvailable", "downloading",
+    for (let prop of ["installState", "downloadAvailable", "downloading",
                            "downloadSize", "readyToApplyDownload"]) {
       aData.app[prop] = appObject[prop];
     }
 
     let dontNeedNetwork = false;
 
     if ((appObject.kind == this.kHostedAppcache ||
         appObject.kind == this.kTrustedHosted) &&
@@ -3343,17 +3349,16 @@ this.DOMApplicationRegistry = {
     // If the response was 304 we probably won't have anything to hash.
     let hash = null;
     if (!oldPackage) {
       hash = yield this._computeFileHash(zipFile.path);
     }
 
     oldPackage = oldPackage || (hash == aOldApp.packageHash);
 
-
     if (oldPackage) {
       debug("package's etag or hash unchanged; sending 'applied' event");
       // The package's Etag or hash has not changed.
       // We send an "applied" event right away so code awaiting that event
       // can proceed to access the app. We also throw an error to alert
       // the caller that the package wasn't downloaded.
       this._sendAppliedEvent(aOldApp);
       throw "PACKAGE_UNCHANGED";
@@ -4276,16 +4281,84 @@ this.DOMApplicationRegistry = {
 
     this._readManifests(tmp).then((aResult) => {
       for (let i = 0; i < aResult.length; i++)
         aData.apps[i].manifest = aResult[i].manifest;
       aMm.sendAsyncMessage("Webapps:GetNotInstalled:Return:OK", aData);
     });
   },
 
+  getIcon: function(aData, aMm) {
+    function sendError(aError) {
+      debug("getIcon error: " + aError);
+      aData.error = aError;
+      aMm.sendAsyncMessage("Webapps:GetIcon:Return", aData);
+    }
+
+    let app = this.getAppByManifestURL(aData.manifestURL);
+    if (!app) {
+      sendError("NO_APP");
+      return;
+    }
+
+    function loadIcon(aUrl) {
+      let fallbackMimeType = aUrl.indexOf('.') >= 0 ?
+                             "image/" + aUrl.split(".").reverse()[0] : "";
+      // Set up an xhr to download a blob.
+      let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
+                  .createInstance(Ci.nsIXMLHttpRequest);
+      xhr.mozBackgroundRequest = true;
+      xhr.open("GET", aUrl, true);
+      xhr.responseType = "blob";
+      xhr.addEventListener("load", function() {
+        debug("Got http status=" + xhr.status + " for " + aUrl);
+        if (xhr.status == 200) {
+          let blob = xhr.response;
+          // Reusing aData with sendAsyncMessage() leads to an empty blob in
+          // the child.
+          let payload = {
+            "oid": aData.oid,
+            "requestID": aData.requestID,
+            "blob": blob,
+            "type": xhr.getResponseHeader("Content-Type") || fallbackMimeType
+          };
+          aMm.sendAsyncMessage("Webapps:GetIcon:Return", payload);
+        } else if (xhr.status === 0) {
+          sendError("NETWORK_ERROR");
+        } else {
+          sendError("FETCH_ICON_FAILED");
+        }
+      });
+      xhr.addEventListener("error", function() {
+        sendError("FETCH_ICON_FAILED");
+      });
+      xhr.send();
+    }
+
+    // Get the manifest, to find the icon url in the current locale.
+    this.getManifestFor(aData.manifestURL, aData.entryPoint)
+        .then((aManifest) => {
+      if (!aManifest) {
+        sendError("FETCH_ICON_FAILED");
+        return;
+      }
+
+      let manifest = new ManifestHelper(aManifest, app.origin, app.manifestURL);
+      let url = manifest.iconURLForSize(aData.iconID);
+      if (!url) {
+        sendError("NO_ICON");
+        return;
+      }
+      loadIcon(url);
+    }).catch(() => {
+      sendError("FETCH_ICON_FAILED");
+      return;
+    });
+  },
+
   getAll: function(aCallback) {
     debug("getAll");
     let apps = [];
     let tmp = [];
 
     for (let id in this.webapps) {
       let app = AppsUtils.cloneAppObject(this.webapps[id]);
       if (!this._isLaunchable(app))
@@ -4509,25 +4582,29 @@ this.DOMApplicationRegistry = {
 
     // Update customization.
     this.getManifestFor(app.manifestURL).then((aManifest) => {
       app.enabled ? UserCustomizations.register(aManifest, app)
                   : UserCustomizations.unregister(aManifest, app);
     });
   },
 
-  getManifestFor: function(aManifestURL) {
+  getManifestFor: function(aManifestURL, aEntryPoint) {
     let id = this._appIdForManifestURL(aManifestURL);
     let app = this.webapps[id];
     if (!id || (app.installState == "pending" && !app.retryingDownload)) {
       return Promise.resolve(null);
     }
 
     return this._readManifests([{ id: id }]).then((aResult) => {
-      return aResult[0].manifest;
+      if (aEntryPoint) {
+        return aResult[0].manifest.entry_points[aEntryPoint];
+      } else {
+        return aResult[0].manifest;
+      }
     });
   },
 
   getAppByManifestURL: function(aManifestURL) {
     return AppsUtils.getAppByManifestURL(this.webapps, aManifestURL);
   },
 
   _getAppWithManifest: Task.async(function*(aManifestURL) {
--- a/dom/apps/tests/file_manifest.json
+++ b/dom/apps/tests/file_manifest.json
@@ -1,13 +1,19 @@
 {
   "name": "My W3C Web App",
   "short_name": "My App",
-  "icons": [
-    {
-      "src": "/favicon.ico",
-      "sizes": "64x64",
-      "type": "image/png"
+  "icons": {
+    "15": "/tests/dom/apps/tests/icon15.png",
+    "48": "/tests/dom/apps/tests/icon48.png"
+  },
+  "start_url": "/index.html",
+  "display": "standalone",
+  "entry_points": {
+    "ep1": {
+      "name": "This is an entry point",
+      "icons": {
+        "15": "/tests/dom/apps/tests/icon15alternate.png",
+        "48": "/tests/dom/apps/tests/icon48.png"
+      }
     }
-  ],
-  "start_url": "/index.html",
-  "display": "standalone"
-}
\ No newline at end of file
+  }
+}
--- a/dom/apps/tests/file_packaged_app.sjs
+++ b/dom/apps/tests/file_packaged_app.sjs
@@ -12,16 +12,36 @@ Cu.import("resource://gre/modules/NetUti
 
 var gBasePath = "tests/dom/apps/tests/";
 var gMiniManifestTemplate = "file_packaged_app.template.webapp";
 var gAppTemplate = "file_packaged_app.template.html";
 var gAppName = "appname";
 var gDevName = "devname";
 var gDevUrl = "http://dev.url";
 
+var gIconData =
+"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
+"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
+"\x78\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xD6\xD8\xD4\x4F\x58" +
+"\x32\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72" +
+"\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61\x67\x65\x52\x65\x61" +
+"\x64\x79\x71\xC9\x65\x3C\x00\x00\x00\x39\x50\x4C\x54\x45\xB5\x42" + 
+"\x42\xCE\x94\x94\xCE\x84\x84\x9C\x21\x21\xAD\x21\x21\xCE\x73\x73" +
+"\x9C\x10\x10\xBD\x52\x52\xEF\xD6\xD6\xB5\x63\x63\xA5\x10\x10\xB5" +
+"\x00\x00\xE7\xC6\xC6\xE7\xB5\xB5\x9C\x00\x00\x8C\x00\x00\xFF\xFF" +
+"\xFF\x7B\x00\x00\xAD\x00\x00\xEC\xAD\x83\x63\x00\x00\x00\x66\x49" +
+"\x44\x41\x54\x78\xDA\x6C\x89\x0B\x12\xC2\x40\x08\x43\xB3\xDB\x8F" +
+"\x5A\x21\x40\xEF\x7F\x58\xA1\x55\x67\xB6\xD3\xC0\x03\x42\xF0\xDE" +
+"\x87\xC2\x3E\xEA\xCE\xF3\x4B\x0D\x30\x27\xAB\xCF\x03\x9C\xFB\xA3" +
+"\xEB\xBC\x2D\xBA\xD4\x0F\x84\x97\x9E\x49\x67\xE5\x74\x87\x26\x70" +
+"\x21\x0D\x66\xAE\xB6\x26\xB5\x8D\xE5\xE5\xCF\xB4\x9E\x79\x1C\xB9" +
+"\x4C\x2E\xB0\x90\x16\x96\x84\xB6\x68\x2F\x84\x45\xF5\x0F\xC4\xA8" +
+"\xAB\xFF\x08\x30\x00\x16\x91\x0C\xDD\xAB\xF1\x05\x11\x00\x00\x00" +
+"\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
+
 function handleRequest(request, response) {
   var query = getQuery(request);
 
   var packageSize = ("packageSize" in query) ? query.packageSize : 0;
   var appName = ("appName" in query) ? query.appName : gAppName;
   var devName = ("devName" in query) ? query.devName : gDevName;
   var devUrl = ("devUrl" in query) ? query.devUrl : gDevUrl;
   // allowCancel just means deliver the file slowly so we have time to cancel it
@@ -82,16 +102,19 @@ function handleRequest(request, response
         addZipEntry(zipWriter, manifest, "manifest.webapp");
       }
 
       var appTemplate = gBasePath + gAppTemplate;
       var app = makeResource(appTemplate, version, packagePath, packageSize,
                              appName, devName, devUrl);
       addZipEntry(zipWriter, app, "index.html");
 
+      var iconString = gIconData;
+      addZipEntry(zipWriter, iconString, "icon.png");
+
       zipWriter.close();
     }
 
     response.setHeader("Content-Type", "text/html", false);
     response.write("OK");
     return;
   }
 
--- a/dom/apps/tests/file_packaged_app.template.webapp
+++ b/dom/apps/tests/file_packaged_app.template.webapp
@@ -7,15 +7,18 @@
   "permissions": {
      "geolocation": {},
      "audio-capture": {},
      "video-capture": {},
      "test-permission": {"access": "readonly"},
      "downloads": {}
    },
   "launch_path": "tests/dom/apps/tests/file_packaged_app.sjs",
+  "icons": {
+    "15": "icon.png"
+  },
   "developer": {
     "name": "DEVELOPERTOKEN",
     "url": "DEVELOPERURLTOKEN"
   },
   "default_locale": "en-US",
   "role": "ROLETOKEN"
 }
new file mode 100644
index 0000000000000000000000000000000000000000..f752986b7e13a7a2f6eba78c031245d6d5619883
GIT binary patch
literal 281
zc%17D@N?(olHy`uVBq!ia0vp^{2<K13?z9tQY(NIOS+@4BLl;=8&~`zjDUQ}64!{5
z;QX|b^2DN42FH~Aq*MjZ+{E<Mpwz^a%EFVWHb6y|0X`wFTb-QFO__48rDcwy;#x(;
zbH&AT1O)a51--v^ZEJG!QUQUj3=GeY9eciY>l_A#9tMX0|NmDrFsx-@c(b-S8E8nF
zr;B4q#jTu9ZlOaC9L}3>_eUu@yswW~7@EHA@&RV25BJ&+*}XdV*_+ouef4?fIlmXb
z-lMzg3V+M=d7kM{OWM^66nWFuZByIY`}FDgE%Pd6cKYaTm>@Q-Wm|@Ri|beZBP&+_
b=P+Opo5*u_^+#4gpp6Wku6{1-oD!M<-aKpU
new file mode 100644
index 0000000000000000000000000000000000000000..a85552b240fbde0ace475e0727267e611f8bb8ec
GIT binary patch
literal 224
zc%17D@N?(olHy`uVBq!ia0vp^{2<K11SGd?VUh(>%ROBjLo`H_Q>M;6;9!!V6s79%
zFd+0S)5oXl-G83AS6lhGZATlMOG<wF?B^kQ9MVUpbJxV=zrVvag+YsTQzOTTu%dz{
z4c18kn;Uf&?25kLZ*zWsNabVI7T&-w&ktMg$ZEN%!{p>}@%(;!Mo$juMI5cX*Vzpp
zAAY~zK``aB0#}3F?)pzGS5zIYZT`*Q;Kdp-^I^^cs|AxA9yuI4D0x{f-sZeT#wAXM
Y;tX$h%O9_#fKF!cboFyt=akR{0Q6Q@KL7v#
new file mode 100644
index 0000000000000000000000000000000000000000..c4307fc8418436bb6b2fd3a6afc702c2db28aa77
GIT binary patch
literal 4762
zc$@*65@qd)P)<h;3K|Lk000e1NJLTq001xm001xu1^@s6R|5Hm000CeX+uL$Nkc;*
zP;zf(X>4Tx05}naRo`#hR1`jmZ&IWdKOk5~hl<6oRa0BJ8yc;~21%2p?MfD<>DVeH
z<T^KrsT&8|>9(p*dx19w`~g7O0}n_%Aq@s%d)fBDv`JHkDym6Hd+5XuAtvnwRpGmK
zVkc9?T=n|PIo~<wJLg{8L_J?=wVD}Kh?c9aozEndlcyGxo=u9<v(!ri)T`-EEs@L3
z5-!0N_s;9#9f}Cc?UC;OPWB_edW+oAi6T$HZWSGU8TbrQ%+zbPOBBBc`}k?M2Hf);
z@Y6N~0;>X-eVh__(Z?q}P9Z-Dj?gOW6|D%o20XmjW-qs4UjrD(li^iv8@eK9k+ZFm
zVRFymFOPAzG5-%Pn|1W;U4vNroTa&AxDScmEA~{ri9gr1^c?U@uwSpaNnw8l_>cP1
zd;)kMQS_;jeRSUEM_*s96y65j1$)tOrwdK{YIQMt92l|D^(E_=$Rjw{b!QT@q!)ni
zR`|5oW9X5n$Wv+HVc@|^eX5yXnsHX<gx$-tTA9oOBadXir_JPm2Y^4ct-PoO&C)tI
zGolvqOIK@duBk!Vu9{g<3;i;gJ6?~-DQ&xz!jvD&4!U-s8Os(*#?k2}f30SEXA#=i
z1-qUX+K`{!((H5w7<t$~ygD!D1{~X6)KX%$qrgY#L_{M_7A<1csY*MfP@XcB#Jxr~
zJS8&7goVS)VKE|4(h_Xlc{z{c$ApZs7riZ_QKdV_uW-M~u~<J-*#Z0?VzcZp8)p-w
zus7J7><CN2I>8PF3UX~a6)MwxDE0HaPjyrlI!;jX{6Kvuh*8ej?;85ekN$?5uuCiS
zBTvvVG+XTxAO{m@bvM#Jr)z6J><&E22D|vq?Y?Vkbo_DijopiF$2PET#<s%v*srlI
z{B2SKJ79W>mZ8e<cESmGBON_l0n;T7>u=y$(ArYkv7@Ex`GL?QCc!_*KFrd&;n1r7
zqW-CFs9&fT)ZaU5gc&=gBz-D<EBz>aCw(vdOp0__x+47~U6sC(E(JNe@4cTT*n6*E
zVH4eoU1-&7pEV~_PRe`a7v+@vy!^5}8?Y3)UmlaE<h}6h3HHql{T;m+bPBU-O|^S1
z@dOw&4<!bj2G_<^#e}PL7FpY$lcrKO$i~?8Bd2y;oaL5^csibnCrF9!i%-PI;xhub
zp1k;8_$IKX1NHus6EHeD;B72SCCD@4ojP$=Mf3`Eo6yZ&eg@wTqDiZE);7u&SJ|(s
zuPF(9%D6IJ)klXF%`_Fy<tR3HxV^%Qqa?nAB97=m-uu2qcHInZ?ps8M|H3=#R%lzO
z6MgLv^}ib0hVV{&<};#;2lcwW;^(7C<OY#bI<VjS9qCKr-E_Cnc!2j+&nHAXA2%BR
zt~VMxUn2h&(Pi^LSpac(Y#S>R000g#Nkl<ZXx{Bv3vg8Dc|G^FckjMeyOLH<gaAoM
zARa68vIC+RYEjza+M>-k(>h5*rk*jGY3h=s;}LS}gf>m4rQ@{NxQSg49;C!L*x`|w
zT469C%NXh+KmxsxSiN8S-uvu#7YS3_U>R%bwDq06v%B}+{r_{m?|kR`?_S0*4E%52
zn9m9PUnRiM2HY5%rZ9fv2@qUn*RFczwNMVXJ-8j)w?hMN0_W-*FS4y@)f#GRb(5Ph
zOB2r`fo+^&G-w}p-TL|_zG+vrHd|S_YXWJB>@pbC0oCi9*zTfkzLd+cUB2A2Bx^z0
z%HZ<cMFF2^_c{d)tT5R0?nJXO)_Wp%LDon!pGZ0TBL)%CX?p!LB2dqwww%cvhUCt0
zc#Qtedy?Mbug!gM@zTdv`drJh1>Rvz7Xnm@_xS-e^@CrHggmW7hZrCCe0(TA(h-`7
z<tN_OnwskFIwPNm0D)m@w>7fE_Lz`RA{Iw+up*|&Vn@?~dsFJluP=PC#`o3V^;oJh
zST4`WLEy}v+$iFN0^?MlqBmcRB$e>Qg;QrjFXj9Aqp;gXC%VrktBZQ%U3GOP8e`T8
zOgl<#E!ek`uZ!MD!llc+pL5Lr*2F+pX*_zNz`f`}@7(eLZ;csj<?maut<(aim5P;q
z8Bu}3gn^%r=xBdW)q`$Xx!O7szR-02)q=U)Gls4Xj)mk%se4nhv4JGT%-p$VNZ>{!
zgTZI{&T+5JBXS;C`8la!`))3fRqieGiy3Z7jCQMx%yHOJXUF0I3oFM!rQv(x27Wqb
zpnXz@{gR4RdAi}1*yPazJxNv>eL-?^&xeO1qw`#)<FQza(%4WtV-g=r;HIC`D_Hd`
zKOD$&aH7|RM6#5z_`mNg&MuZ5qD>ELER!<8($$rf0v47CnCD|*cW_9MHw`9%-lTyG
z*EPgDWNcm|>X)u3<9%%-9RVkH4n>vAF1s{ov5m&|ZV#%=tP`khWQ&Gl0+T3k8<OVb
zc<;kp!m`7a>G3cIE9m_?bdH58YbYq<A$cr_EE3=kN=T881{Gi=q9gK#0;V^Gn%@(V
zQ)E%DbtQ&{cx?B?c<P8FWlRo4uY_0nYLs1dH0ccb#S92gGL5uVa_{9ywhX`}s#;DQ
z8GmE3TUUEB9d=Enz>^v35{Jwz3)Yq~=$_Cpu5-w6u^0^-=;~D<D>@QAafosXrIk*U
zSK9UAA$cO)AKB-!F#E@%T*xjbBeB+*%jk{-ZbqLvZ1A-$oE%6vl$h$~Y+{+rx^|0<
zeSuxDN}7Z4$5}8$Age;a5dEe<$-?7jkQ~>bw8mj{$H1rxw3LjB<u)v=@q@7m#@K)y
zfA6)PQ)}0{{^`Wq1Men7!{MBbu0&H^wKls1LR+}xxa`yv#>H5L3d8F9JBwhQYqJQF
z!Wxh}!qB1#z%Rlma6)%j({>^!b+DsR7{hcvCet+$%q`DF@ON^dS~zrFiY2eSalUoy
zgL9u5A5FBJJ^yZ>BG}`t4YkUw5~ye_=e0nFGoDJiMXR_>QC#1ZG<ShB*Dfi#f>=ig
zykvt);1dyA{O}wMjfKT-I*|r-cnnNp9BO<Vf$|b8*)j*R!J+$VG?^Ogd#k!C`zLM}
zKk(AAcbaoLDFfBN*0HP3_*4WwWTAjfN@crvYpRfAy}K<4EcX`rBn3K?7>I%QTEP_(
zfeAp94Ok==fjLwg(Ky=Qz6Q1L666F~Y2kV-`U5|BKM)F~Qr7T9<JwBc;ml0CY_&1}
z(e$HZU8n^bx7F&iK;V5B%IzE%W!T(Si|Chi_Hmmn_YeJZ3mv+~vy4LBN+QV&%Tx<2
zIJ*UUQh`G0P}DF|;bF)_=Maw+!%=WQ+yx?ZD)Kp{1|C`&IX5yEdEV~N>GgW}2;+>s
z-FYyZ^jMF&x;lM!2%w(cM+Ju?$Hge{^053CYmw?Q{6U{h@(Zk+Cx4=K4`hUUx(M)P
zssRnUJVpdUP}L!Df*(06z6@*rd<>jd;q-Etn;F55uSqD#^F)Utv7cU>5Pxp-_%44j
zh&Gy(28A+fO9@ohbN+rwvRVa~#&H3GaeWWSTH`C6FR?xsYuGrz!a`4^5DQ(yWY0+?
z2986E4}f=-K=5sbE3X`q&p~~{O(SwxoIim=oYgBAEnrtvEk#mMJ30npFLq7(fB0B6
zq8Bg1(%Ran)z;Q(pOS#N?K0nar!(S`W!7!8IaV>c@?D<yWM%l)i-P207&`|=P?3ly
z5$W%Mp^t)N1#lJ*SeHcAO#=`~UJ?)}%fdIm9Kc*R(AIWIrxw7JmX$G?*|~_tB8TPC
z&K<#Eu*01B?AfzIRaKSx!NxY@)#&?D+QwpjfUgjJUTQqv)MRQiYnT4ql~I;y^#+8L
z$RQGmr8_dqTd2daRK;ZJDs?-DNSUzFaUx(uvACcYt1GNnd*2Ea7UW`VY#irXTQxFX
zZuQDF5R~!pvHsBRKYsL!|8U{L1^N9&@%x4S$(GZ!H8dE6=py%>@B9lhG~}~?^Dmcw
zK{XstzxuP*imt8}Qaukrte_}ogC$#KXnDb~v>RzhgGR;f^602qI*1HM7%Z#8OG~T8
zODb{i7pgIG>NI*oA;Y?Sxz^V5CjV#Kw}LF;-P0}q`B$s&x$o$wy`d4zqB4oJw)T1@
zN&9wtd*_bh$4^*}96gEQLDonren!(X2y}o5WP%m#1d^k^K+@q-w8V~}bWRwVWHMHf
zfncG+S7a!15_yIBD6v@Zz~%?Q7Zu{)j~!Qsdsnh<yPvJz5=B?{`M<5Iy6;<`m_TD=
zBS%GKeoPnA`1trEeSLlPq|15x_wUE`(17a6$lye)lZk0wL{lzk3^g^w4w158C0n&w
z6apWGn;Qnlki5vF%$=j<H!lc8jzcPyqT4$+7B5<YKYC~*dO8C5(gS10y8B(qQ_m=t
z_V)AY#f$yrk3Ra)l^GGJudipxhgtKk(ENVw+O;4}_}AyoovR^IIDPuGYPZ{2r_;%r
z!*C=Qmc6l?z|8%F-)|h_>7BXd7*DFFu1)DM1s<j4hRrTvTkW5qWWh2RY`=EBub;bk
z@rrWd#IM)y+qdtnI}$J@LdUsj;Ez4_nD>b%p7=IJeaE3ghs5K@k0Y5(Dg<0G0hnV<
zgJBppEg7EYZW3bBfK3_k6lo@1*yg!ug66x0q+@Q1qQK>H(LKcytX^{u9f#I>p@SV6
z9%H(?JFf2E|MJ!=SFW_)mcSHvGZ5(xc;?KRM=~-po+>FRDL#4fBzErHsSXSba6X@p
zF(=kE?Iws1zMEutp1(=t)^pRJ1yeqBjVT}V*usSiv3~t}WM^mV-Q7Lt?CfR-2m3KN
zIM96R)T!?^H#h%^@Wnrpz!doOfg?wbEGsH1dO9yJuf~iBO`w@hIy5xIz4X$4G&D4(
zQ|<M-(-WK9tsp-vn-3o|!Rxx7247fMm<GOh@nVB&OmA;*=V&fmzka=sKEL?NE3f<;
zO>vdrX}7h}Db4E#4jg!-yuADc8jPcq8Z@z{swz*iq4c`bcG%Y5f<1fo;*DRPghjN#
z?RH_h-`xuOqX?M5&1=o^NQPLqZXMRFSp!iNwab?;a|9Zc<y22k&%tBIj_srGr>CO+
z-+I7pYoMW_;pD1StL`P~#3{Wt0-x5oBuSKR9fNfH7>`)t&jwC4zk)sg_#8Srdf;+9
z)7MO8^F!cG;O2K(mec2#E?tV6ni}Nf<mjPL2&8S2%OI^#L(L@Jy(E{zH1FU?HLyF?
zfcwcOpM0~jvT_-vH8p3>9MR|VPib1gi+iKk^R!OB9YMuX9*^(LM|p4%&pr2J{H*a1
z;)xhM9?wmAOp~DKrVG>rPh(>9=FPN34;m8_6Z+MwS2>daMZJ$Q@WR1^2lo?{cEYCK
z4*2bAz_d&|dH$Z#($Yu$em|%VG%8@WprDX(IBa<8FB16sA6&(<H9v&gKY*UI-@wKV
zHTeFIf%h()#XtY(d9<`NrwN$yNV^b4J06dd%-q<pVFNa9+-PP>yL9PN8aTOIl4SBK
zZO@I4j-Ht=(pzhCrmIo&Hyl}72~G5k{QUec(QYG0!2J0Oh{!xPFRzgK<?9pp*L}Z0
zPiGi?tsCfEF%C582;_-WkSbn#{Z+iY|7DPd(+*?qD^{$))~#F3fanAmRG92kk)C<y
zop+ukhq)=2>BZwr{=vRoA22iFU9e!mCerEGNu%p>b90cNUucw;78^^KEo3J~+<5Z{
zc`Yr}Hf+)0&*CsS8BaGThr^KuZ#FxMaysg(SFbjr(Wq_~sTp<BdLNzp2}S*7nyYQf
zUG6BCySXPe{jr!FVjGe9N+1v@&dJFoA_dygWhLyq;v$;Rp6+*(ld-f^1dEVvRMXNK
z85u!19M(EJJ2~p)W`QOt1JiP8ruk#jLBE@42Dc?}tN!Stm1Gdyv}x0y=H=x+OavU6
znc0{(Z=P0KTE@AlPk_<W9dz2)W3d>Kn$&xHdrg_JrZx8W_fN~^7c}(Ho!n*C{@k4+
zl9nWW^p%yB{q~|oi?-+H=8~*(QBY8zFI-rLtgLK?oF;uO6|6yyLY=gmGc!OW`r6vs
zOu0<Ei}q=vez(hMW{QMaAM>bB)RL^eN+gQSE=s#WE|VT?Y-}uDpcL^WkvMqx@Zo)=
z`Du4yKC?$mAIOF@C9AIxiHFH@ou+M?o^N(oS`M5csqAfOX*u$7&FHguLUR)c5y_xF
zv6dEL_mlhN5~(<WZ=qG|(OcFovl{hTdqy^$jj8YEUm#Y~lIVEyqs-tp@-gcNiQM`h
ofbl=@6#erj^`8^?|4!h)0J^zP3jf7M-2eap07*qoM6N<$f*<W+VgLXD
--- a/dom/apps/tests/mochitest.ini
+++ b/dom/apps/tests/mochitest.ini
@@ -24,16 +24,19 @@ support-files =
   file_test_widget.js
   langpack/*
   signed_app.sjs
   signed_app_template.webapp
   signed/*
   test_packaged_app_common.js
   marketplace/*
   pkg_install_iframe.html
+  icon15.png
+  icon15alternate.png
+  icon48.png
 
 [test_app_addons.html]
 skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
 [test_app_enabled.html]
 [test_app_update.html]
 skip-if = os == "android" || toolkit == "gonk" # embed-apps doesn't work in mochitest app
 [test_bug_795164.html]
 [test_import_export.html]
--- a/dom/apps/tests/test_packaged_app_install.html
+++ b/dom/apps/tests/test_packaged_app_install.html
@@ -71,16 +71,38 @@ function checkInstalledApp(aMiniManifest
       PackagedTestHelper.finish();
     }
 
     PackagedTestHelper.checkAppState(evt.application, aVersion, aExpectedApp,
                                      aLaunchable, false, aCb);
   };
 }
 
+var gIconData =
+"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
+"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
+"\x78\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xD6\xD8\xD4\x4F\x58" +
+"\x32\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72" +
+"\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61\x67\x65\x52\x65\x61" +
+"\x64\x79\x71\xC9\x65\x3C\x00\x00\x00\x39\x50\x4C\x54\x45\xB5\x42" + 
+"\x42\xCE\x94\x94\xCE\x84\x84\x9C\x21\x21\xAD\x21\x21\xCE\x73\x73" +
+"\x9C\x10\x10\xBD\x52\x52\xEF\xD6\xD6\xB5\x63\x63\xA5\x10\x10\xB5" +
+"\x00\x00\xE7\xC6\xC6\xE7\xB5\xB5\x9C\x00\x00\x8C\x00\x00\xFF\xFF" +
+"\xFF\x7B\x00\x00\xAD\x00\x00\xEC\xAD\x83\x63\x00\x00\x00\x66\x49" +
+"\x44\x41\x54\x78\xDA\x6C\x89\x0B\x12\xC2\x40\x08\x43\xB3\xDB\x8F" +
+"\x5A\x21\x40\xEF\x7F\x58\xA1\x55\x67\xB6\xD3\xC0\x03\x42\xF0\xDE" +
+"\x87\xC2\x3E\xEA\xCE\xF3\x4B\x0D\x30\x27\xAB\xCF\x03\x9C\xFB\xA3" +
+"\xEB\xBC\x2D\xBA\xD4\x0F\x84\x97\x9E\x49\x67\xE5\x74\x87\x26\x70" +
+"\x21\x0D\x66\xAE\xB6\x26\xB5\x8D\xE5\xE5\xCF\xB4\x9E\x79\x1C\xB9" +
+"\x4C\x2E\xB0\x90\x16\x96\x84\xB6\x68\x2F\x84\x45\xF5\x0F\xC4\xA8" +
+"\xAB\xFF\x08\x30\x00\x16\x91\x0C\xDD\xAB\xF1\x05\x11\x00\x00\x00" +
+"\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
+
+var gIconSize = 15;
+
 SimpleTest.waitForExplicitFinish();
 SimpleTest.requestFlakyTimeout("untriaged");
 
 var steps = [
   function() {
     // Set up
     SpecialPowers.setAllAppsLaunchable(true);
     SpecialPowers.addPermission("webapps-manage", true, document);
@@ -190,16 +212,17 @@ var steps = [
   },
   function() {
     PackagedTestHelper.setAppVersion(2, PackagedTestHelper.next);
   },
   function() {
     info("== TEST == Install packaged app");
     var miniManifestURL = PackagedTestHelper.gSJS +
                           "?getManifest=true";
+
     navigator.mozApps.mgmt.oninstall = function(evt) {
       info("Got oninstall event");
       PackagedTestHelper.gApp = evt.application;
       PackagedTestHelper.gApp.ondownloaderror = function() {
         ok(false, "Download error " +
                   PackagedTestHelper.gApp.downloadError.name);
         PackagedTestHelper.finish();
       };
@@ -227,16 +250,35 @@ var steps = [
     request.onsuccess = function() {
       info("Application installed");
     };
   },
   function() {
     PackagedTestHelper.setAppVersion(3, PackagedTestHelper.next, false, true);
   },
   function() {
+    info("== TEST == Get icon");
+    var app = PackagedTestHelper.gApp;
+
+    navigator.mozApps.mgmt.getIcon(app, gIconSize).then((blob) => {
+      var reader = new FileReader();
+
+      reader.onloadend = function() {
+        var success = reader.result == gIconData;
+        ok(success, "== TEST == Icon matches expected icon");
+        PackagedTestHelper.next();
+      }
+
+      reader.readAsBinaryString(blob);
+    }, (err) => {
+      ok(false, "Can't get icon: " + err);
+      PackagedTestHelper.finish();
+    });
+  },
+  function() {
     info("== TEST == Install packaged app with a cancel/resume");
     var miniManifestURL = PackagedTestHelper.gSJS +
                           "?getManifest=true&allowCancel";
     navigator.mozApps.mgmt.oninstall = function(evt) {
       info("Got oninstall event");
       PackagedTestHelper.gApp = evt.application;
 
       PackagedTestHelper.gApp.onprogress = function() {
--- a/dom/apps/tests/test_web_app_install.html
+++ b/dom/apps/tests/test_web_app_install.html
@@ -14,16 +14,53 @@ https://bugzilla.mozilla.org/show_bug.cg
 <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={1075716}">Mozilla Bug {1075716}</a>
 <p id="display"></p>
 <div id="content" style="display: none">
 
 </div>
 <pre id="test">
 <script class="testbody" type="application/javascript;version=1.7">
 
+var gIconData =
+"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
+"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x03\x00\x00\x00\x0C\x08\x65" +
+"\x78\x00\x00\x00\x04\x67\x41\x4D\x41\x00\x00\xD6\xD8\xD4\x4F\x58" +
+"\x32\x00\x00\x00\x19\x74\x45\x58\x74\x53\x6F\x66\x74\x77\x61\x72" +
+"\x65\x00\x41\x64\x6F\x62\x65\x20\x49\x6D\x61\x67\x65\x52\x65\x61" +
+"\x64\x79\x71\xC9\x65\x3C\x00\x00\x00\x39\x50\x4C\x54\x45\xB5\x42" + 
+"\x42\xCE\x94\x94\xCE\x84\x84\x9C\x21\x21\xAD\x21\x21\xCE\x73\x73" +
+"\x9C\x10\x10\xBD\x52\x52\xEF\xD6\xD6\xB5\x63\x63\xA5\x10\x10\xB5" +
+"\x00\x00\xE7\xC6\xC6\xE7\xB5\xB5\x9C\x00\x00\x8C\x00\x00\xFF\xFF" +
+"\xFF\x7B\x00\x00\xAD\x00\x00\xEC\xAD\x83\x63\x00\x00\x00\x66\x49" +
+"\x44\x41\x54\x78\xDA\x6C\x89\x0B\x12\xC2\x40\x08\x43\xB3\xDB\x8F" +
+"\x5A\x21\x40\xEF\x7F\x58\xA1\x55\x67\xB6\xD3\xC0\x03\x42\xF0\xDE" +
+"\x87\xC2\x3E\xEA\xCE\xF3\x4B\x0D\x30\x27\xAB\xCF\x03\x9C\xFB\xA3" +
+"\xEB\xBC\x2D\xBA\xD4\x0F\x84\x97\x9E\x49\x67\xE5\x74\x87\x26\x70" +
+"\x21\x0D\x66\xAE\xB6\x26\xB5\x8D\xE5\xE5\xCF\xB4\x9E\x79\x1C\xB9" +
+"\x4C\x2E\xB0\x90\x16\x96\x84\xB6\x68\x2F\x84\x45\xF5\x0F\xC4\xA8" +
+"\xAB\xFF\x08\x30\x00\x16\x91\x0C\xDD\xAB\xF1\x05\x11\x00\x00\x00" +
+"\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
+
+var gAlternateIconData =
+"\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52" +
+"\x00\x00\x00\x0F\x00\x00\x00\x0F\x08\x02\x00\x00\x00\xB4\xB4\x02" +
+"\x1D\x00\x00\x00\xA7\x49\x44\x41\x54\x28\x15\x63\x64\x95\x9D\xC0" +
+"\x40\x34\x60\x22\x5A\x25\x48\xE1\x50\x55\xCD\x02\xF1\xE5\xAF\x47" +
+"\xF9\xC8\xDE\x7D\x79\xE3\x86\xB8\x86\x06\x44\x64\x6F\x67\x9B\xE7" +
+"\x54\x6E\x08\x1B\xC5\x97\x0B\x7C\x5C\x6F\xEF\xDC\x06\x94\x00\x2A" +
+"\x05\xB2\x81\x08\xC8\x56\x72\x70\x82\x28\x05\x92\x50\xB3\x81\x2C" +
+"\xA0\xBA\x5B\xD7\x8F\x3C\xCF\xBF\x54\x79\xE3\x25\x84\x0D\x51\xF4" +
+"\xE7\xC3\x3B\xB8\x6A\x84\xD9\x2C\x02\x42\x40\xD1\xCF\xBF\x3F\x01" +
+"\x49\x08\x1B\xA2\x08\x85\x0D\xD7\x07\x31\xE3\xC3\xEF\xBF\x40\x11" +
+"\x64\xF3\x20\x0A\x80\x1E\xBB\x7F\xF2\x04\xD4\x25\x40\xD6\xB3\xFB" +
+"\x0F\x80\x4A\x05\x58\x99\xE1\x6C\xA0\x3A\xA0\x93\x80\xE2\x40\xC6" +
+"\xC1\x19\xD3\x1E\x5F\x3C\xCF\x38\x68\xD2\x09\x00\x73\x68\x4B\x47" +
+"\x39\xF8\xEA\x1A\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82";
+
+
 var gGenerator = runTest();
 
 function go() {
   SpecialPowers.pushPermissions(
     [{ "type": "webapps-manage", "allow": 1, "context": document }],
     function() { gGenerator.next() });
 }
 
@@ -40,16 +77,30 @@ function finish() {
 }
 
 function cbError(aEvent) {
   ok(false, "Error callback invoked " +
             aEvent.target.error.name + " " + aEvent.target.error.message);
   finish();
 }
 
+function iconTest(app, iconSize, entryPoint, testFunction) {
+  navigator.mozApps.mgmt.getIcon(app, iconSize, entryPoint).then((blob) => {
+    var reader = new FileReader();
+    reader.onloadend = function() {
+      testFunction(reader.result);
+      continueTest();
+    }
+    reader.readAsBinaryString(blob);
+  }, (err) => {
+    ok(false, "Couldn't get icon.");
+    finish();
+  });
+}
+
 SimpleTest.waitForExplicitFinish();
 
 /**
   * Install a web app from a manifest with application/manifest+json MIME type.
   */
 function runTest() {
   SpecialPowers.setAllAppsLaunchable(true);
 
@@ -72,16 +123,40 @@ function runTest() {
   request.onerror = cbError;
   request.onsuccess = continueTest;
   yield undefined;
 
   var app = request.result;
   ok(app, "App is non-null");
   is(app.manifestURL, manifestURL, "App manifest url is correct.");
 
+  info("Fetching 15x15 icon");
+  iconTest(app, 15, undefined, (iconData) => {
+    is(iconData, gIconData, "Fetches 15x15 icon successfully.")
+  });
+  yield undefined;
+
+  info("Fetching 48x48 icon");
+  iconTest(app, 48, "ep1", (iconData) => {
+    ok(iconData.length == 4762, "Fetches 48x48 icon successfully.")
+  });
+  yield undefined;
+
+  info("Fetching 30x30 icon");
+  iconTest(app, 30, undefined, (iconData) => {
+    is(iconData, gIconData, "Fetches 15x15 icon as best fit for 30x30.")
+  });
+  yield undefined;
+
+  info("Fetching entry-point icon");
+  iconTest(app, 15, "ep1", (iconData) => {
+    is(iconData, gAlternateIconData, "Entry-point Icon fetched successfully.")
+  });
+  yield undefined;
+
   request = navigator.mozApps.mgmt.uninstall(app);
   request.onerror = cbError;
   request.onsuccess = continueTest;
   yield undefined;
   is(request.result, manifestURL, "App uninstalled.");
 
   request = navigator.mozApps.mgmt.getAll();
   request.onerror = cbError;
--- a/dom/archivereader/ArchiveRequest.cpp
+++ b/dom/archivereader/ArchiveRequest.cpp
@@ -37,17 +37,17 @@ protected:
 
 private: //data
   nsRefPtr<ArchiveRequest> mRequest;
 };
 
 NS_IMETHODIMP
 ArchiveRequestEvent::Run()
 {
-  NS_ABORT_IF_FALSE(mRequest, "the request is not longer valid");
+  MOZ_ASSERT(mRequest, "the request is not longer valid");
   mRequest->Run();
   return NS_OK;
 }
 
 // ArchiveRequest
 
 ArchiveRequest::ArchiveRequest(nsPIDOMWindow* aWindow,
                                ArchiveReader* aReader)
--- a/dom/base/Attr.cpp
+++ b/dom/base/Attr.cpp
@@ -43,19 +43,19 @@ namespace dom {
 //----------------------------------------------------------------------
 bool Attr::sInitialized;
 
 Attr::Attr(nsDOMAttributeMap *aAttrMap,
            already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
            const nsAString  &aValue, bool aNsAware)
   : nsIAttribute(aAttrMap, aNodeInfo, aNsAware), mValue(aValue)
 {
-  NS_ABORT_IF_FALSE(mNodeInfo, "We must get a nodeinfo here!");
-  NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
-                    "Wrong nodeType");
+  MOZ_ASSERT(mNodeInfo, "We must get a nodeinfo here!");
+  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ATTRIBUTE_NODE,
+             "Wrong nodeType");
 
   // We don't add a reference to our content. It will tell us
   // to drop our reference when it goes away.
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(Attr)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Attr)
--- a/dom/base/Comment.h
+++ b/dom/base/Comment.h
@@ -14,18 +14,18 @@ namespace mozilla {
 namespace dom {
 
 class Comment MOZ_FINAL : public nsGenericDOMDataNode,
                           public nsIDOMComment
 {
 private:
   void Init()
   {
-    NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
-                      "Bad NodeType in aNodeInfo");
+    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE,
+               "Bad NodeType in aNodeInfo");
   }
 
   virtual ~Comment();
 
 public:
   explicit Comment(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
     : nsGenericDOMDataNode(aNodeInfo)
   {
--- a/dom/base/Crypto.cpp
+++ b/dom/base/Crypto.cpp
@@ -51,17 +51,17 @@ Crypto::WrapObject(JSContext* aCx)
   return CryptoBinding::Wrap(aCx, this);
 }
 
 void
 Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
                         JS::MutableHandle<JSObject*> aRetval,
                         ErrorResult& aRv)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Called on the wrong thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Called on the wrong thread");
 
   JS::Rooted<JSObject*> view(aCx, aArray.Obj());
 
   // Throw if the wrong type of ArrayBufferView is passed in
   // (Part of the Web Crypto API spec)
   switch (JS_GetArrayBufferViewType(view)) {
     case js::Scalar::Int8:
     case js::Scalar::Uint8:
--- a/dom/base/DocumentFragment.h
+++ b/dom/base/DocumentFragment.h
@@ -22,21 +22,20 @@ namespace dom {
 class Element;
 
 class DocumentFragment : public FragmentOrElement,
                          public nsIDOMDocumentFragment
 {
 private:
   void Init()
   {
-    NS_ABORT_IF_FALSE(mNodeInfo->NodeType() ==
-                      nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
-                      mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
-                                        kNameSpaceID_None),
-                      "Bad NodeType in aNodeInfo");
+    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE &&
+               mNodeInfo->Equals(nsGkAtoms::documentFragmentNodeName,
+                                 kNameSpaceID_None),
+               "Bad NodeType in aNodeInfo");
   }
 
 public:
   using FragmentOrElement::GetFirstChild;
   using nsINode::QuerySelector;
   using nsINode::QuerySelectorAll;
   // Make sure bindings can see our superclass' protected GetElementById method.
   using nsINode::GetElementById;
--- a/dom/base/DocumentType.cpp
+++ b/dom/base/DocumentType.cpp
@@ -69,18 +69,18 @@ DocumentType::DocumentType(already_AddRe
                            const nsAString& aPublicId,
                            const nsAString& aSystemId,
                            const nsAString& aInternalSubset) :
   DocumentTypeForward(aNodeInfo),
   mPublicId(aPublicId),
   mSystemId(aSystemId),
   mInternalSubset(aInternalSubset)
 {
-  NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
-                    "Bad NodeType in aNodeInfo");
+  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
+             "Bad NodeType in aNodeInfo");
 }
 
 DocumentType::~DocumentType()
 {
 }
 
 NS_IMPL_ISUPPORTS_INHERITED(DocumentType, nsGenericDOMDataNode, nsIDOMNode,
                             nsIDOMDocumentType)
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -199,19 +199,19 @@ Element::NotifyStateChange(EventStates a
     nsAutoScriptBlocker scriptBlocker;
     doc->ContentStateChanged(this, aStates);
   }
 }
 
 void
 Element::UpdateLinkState(EventStates aState)
 {
-  NS_ABORT_IF_FALSE(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
-                                                    NS_EVENT_STATE_UNVISITED)),
-                    "Unexpected link state bits");
+  MOZ_ASSERT(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
+                                             NS_EVENT_STATE_UNVISITED)),
+             "Unexpected link state bits");
   mState =
     (mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
     aState;
 }
 
 void
 Element::UpdateState(bool aNotify)
 {
--- a/dom/base/Element.h
+++ b/dom/base/Element.h
@@ -147,18 +147,18 @@ class DestinationInsertionPointList;
 class Element : public FragmentOrElement
 {
 public:
 #ifdef MOZILLA_INTERNAL_API
   explicit Element(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo) :
     FragmentOrElement(aNodeInfo),
     mState(NS_EVENT_STATE_MOZ_READONLY)
   {
-    NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
-                      "Bad NodeType in aNodeInfo");
+    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::ELEMENT_NODE,
+               "Bad NodeType in aNodeInfo");
     SetIsElement();
   }
 #endif // MOZILLA_INTERNAL_API
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ELEMENT_IID)
 
   NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) MOZ_OVERRIDE;
 
--- a/dom/base/EventSource.cpp
+++ b/dom/base/EventSource.cpp
@@ -575,19 +575,19 @@ EventSource::AsyncOnChannelRedirect(nsIC
   }
   OnRedirectVerifyCallback(NS_OK);
   return NS_OK;
 }
 
 nsresult
 EventSource::OnRedirectVerifyCallback(nsresult aResult)
 {
-  NS_ABORT_IF_FALSE(mRedirectCallback, "mRedirectCallback not set in callback");
-  NS_ABORT_IF_FALSE(mNewRedirectChannel,
-                    "mNewRedirectChannel not set in callback");
+  MOZ_ASSERT(mRedirectCallback, "mRedirectCallback not set in callback");
+  MOZ_ASSERT(mNewRedirectChannel,
+             "mNewRedirectChannel not set in callback");
 
   NS_ENSURE_SUCCESS(aResult, aResult);
 
   // update our channel
 
   mHttpChannel = do_QueryInterface(mNewRedirectChannel);
   NS_ENSURE_STATE(mHttpChannel);
 
--- a/dom/base/Link.cpp
+++ b/dom/base/Link.cpp
@@ -24,17 +24,17 @@ namespace dom {
 
 Link::Link(Element *aElement)
   : mElement(aElement)
   , mHistory(services::GetHistoryService())
   , mLinkState(eLinkState_NotLink)
   , mNeedsRegistration(false)
   , mRegistered(false)
 {
-  NS_ABORT_IF_FALSE(mElement, "Must have an element");
+  MOZ_ASSERT(mElement, "Must have an element");
 }
 
 Link::~Link()
 {
   UnregisterFromHistory();
 }
 
 bool
@@ -53,19 +53,19 @@ Link::SetLinkState(nsLinkState aState)
                "Setting state to the currently set state!");
 
   // Set our current state as appropriate.
   mLinkState = aState;
 
   // Per IHistory interface documentation, we are no longer registered.
   mRegistered = false;
 
-  NS_ABORT_IF_FALSE(LinkState() == NS_EVENT_STATE_VISITED ||
-                    LinkState() == NS_EVENT_STATE_UNVISITED,
-                    "Unexpected state obtained from LinkState()!");
+  MOZ_ASSERT(LinkState() == NS_EVENT_STATE_VISITED ||
+             LinkState() == NS_EVENT_STATE_UNVISITED,
+             "Unexpected state obtained from LinkState()!");
 
   // Tell the element to update its visited state
   mElement->UpdateState(true);
 }
 
 EventStates
 Link::LinkState() const
 {
--- a/dom/base/NodeInfo.cpp
+++ b/dom/base/NodeInfo.cpp
@@ -43,17 +43,17 @@ NodeInfo::~NodeInfo()
   NS_IF_RELEASE(mInner.mExtraName);
 }
 
 NodeInfo::NodeInfo(nsIAtom *aName, nsIAtom *aPrefix, int32_t aNamespaceID,
                    uint16_t aNodeType, nsIAtom* aExtraName,
                    nsNodeInfoManager *aOwnerManager)
 {
   CheckValidNodeInfo(aNodeType, aName, aNamespaceID, aExtraName);
-  NS_ABORT_IF_FALSE(aOwnerManager, "Invalid aOwnerManager");
+  MOZ_ASSERT(aOwnerManager, "Invalid aOwnerManager");
 
   // Initialize mInner
   NS_ADDREF(mInner.mName = aName);
   NS_IF_ADDREF(mInner.mPrefix = aPrefix);
   mInner.mNamespaceID = aNamespaceID;
   mInner.mNodeType = aNodeType;
   mOwnerManager = aOwnerManager;
   NS_IF_ADDREF(mInner.mExtraName = aExtraName);
@@ -99,18 +99,17 @@ NodeInfo::NodeInfo(nsIAtom *aName, nsIAt
       SetDOMStringToNull(mLocalName);
       break;
     case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
     case nsIDOMNode::DOCUMENT_TYPE_NODE:
       mInner.mExtraName->ToString(mNodeName);
       SetDOMStringToNull(mLocalName);
       break;
     default:
-      NS_ABORT_IF_FALSE(aNodeType == UINT16_MAX,
-                        "Unknown node type");
+      MOZ_ASSERT(aNodeType == UINT16_MAX, "Unknown node type");
   }
 }
 
 
 // nsISupports
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(NodeInfo)
 
--- a/dom/base/NodeInfoInlines.h
+++ b/dom/base/NodeInfoInlines.h
@@ -70,47 +70,47 @@ NodeInfo::QualifiedNameEquals(nsIAtom* a
 
 } // namespace dom
 } // namespace mozilla
 
 inline void
 CheckValidNodeInfo(uint16_t aNodeType, nsIAtom *aName, int32_t aNamespaceID,
                    nsIAtom* aExtraName)
 {
-  NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
-                    aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
-                    aNodeType == nsIDOMNode::TEXT_NODE ||
-                    aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
-                    aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-                    aNodeType == nsIDOMNode::COMMENT_NODE ||
-                    aNodeType == nsIDOMNode::DOCUMENT_NODE ||
-                    aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
-                    aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
-                    aNodeType == UINT16_MAX,
-                    "Invalid nodeType");
-  NS_ABORT_IF_FALSE((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-                     aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
-                    !!aExtraName,
-                    "Supply aExtraName for and only for PIs and doctypes");
-  NS_ABORT_IF_FALSE(aNodeType == nsIDOMNode::ELEMENT_NODE ||
-                    aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
-                    aNodeType == UINT16_MAX ||
-                    aNamespaceID == kNameSpaceID_None,
-                    "Only attributes and elements can be in a namespace");
-  NS_ABORT_IF_FALSE(aName && aName != nsGkAtoms::_empty, "Invalid localName");
-  NS_ABORT_IF_FALSE(((aNodeType == nsIDOMNode::TEXT_NODE) ==
-                     (aName == nsGkAtoms::textTagName)) &&
-                    ((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
-                     (aName == nsGkAtoms::cdataTagName)) &&
-                    ((aNodeType == nsIDOMNode::COMMENT_NODE) ==
-                     (aName == nsGkAtoms::commentTagName)) &&
-                    ((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
-                     (aName == nsGkAtoms::documentNodeName)) &&
-                    ((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
-                     (aName == nsGkAtoms::documentFragmentNodeName)) &&
-                    ((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
-                     (aName == nsGkAtoms::documentTypeNodeName)) &&
-                    ((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
-                     (aName == nsGkAtoms::processingInstructionTagName)),
-                    "Wrong localName for nodeType");
+  MOZ_ASSERT(aNodeType == nsIDOMNode::ELEMENT_NODE ||
+             aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+             aNodeType == nsIDOMNode::TEXT_NODE ||
+             aNodeType == nsIDOMNode::CDATA_SECTION_NODE ||
+             aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+             aNodeType == nsIDOMNode::COMMENT_NODE ||
+             aNodeType == nsIDOMNode::DOCUMENT_NODE ||
+             aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE ||
+             aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE ||
+             aNodeType == UINT16_MAX,
+             "Invalid nodeType");
+  MOZ_ASSERT((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+              aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+             !!aExtraName,
+             "Supply aExtraName for and only for PIs and doctypes");
+  MOZ_ASSERT(aNodeType == nsIDOMNode::ELEMENT_NODE ||
+             aNodeType == nsIDOMNode::ATTRIBUTE_NODE ||
+             aNodeType == UINT16_MAX ||
+             aNamespaceID == kNameSpaceID_None,
+             "Only attributes and elements can be in a namespace");
+  MOZ_ASSERT(aName && aName != nsGkAtoms::_empty, "Invalid localName");
+  MOZ_ASSERT(((aNodeType == nsIDOMNode::TEXT_NODE) ==
+              (aName == nsGkAtoms::textTagName)) &&
+             ((aNodeType == nsIDOMNode::CDATA_SECTION_NODE) ==
+              (aName == nsGkAtoms::cdataTagName)) &&
+             ((aNodeType == nsIDOMNode::COMMENT_NODE) ==
+              (aName == nsGkAtoms::commentTagName)) &&
+             ((aNodeType == nsIDOMNode::DOCUMENT_NODE) ==
+              (aName == nsGkAtoms::documentNodeName)) &&
+             ((aNodeType == nsIDOMNode::DOCUMENT_FRAGMENT_NODE) ==
+              (aName == nsGkAtoms::documentFragmentNodeName)) &&
+             ((aNodeType == nsIDOMNode::DOCUMENT_TYPE_NODE) ==
+              (aName == nsGkAtoms::documentTypeNodeName)) &&
+             ((aNodeType == nsIDOMNode::PROCESSING_INSTRUCTION_NODE) ==
+              (aName == nsGkAtoms::processingInstructionTagName)),
+             "Wrong localName for nodeType");
 }
 
-#endif /* mozilla_dom_NodeInfoInlines_h___ */
\ No newline at end of file
+#endif /* mozilla_dom_NodeInfoInlines_h___ */
--- a/dom/base/TextInputProcessor.cpp
+++ b/dom/base/TextInputProcessor.cpp
@@ -73,47 +73,50 @@ TextInputProcessor::~TextInputProcessor(
       nsRefPtr<TextEventDispatcher> kungFuDeathGrip(mDispatcher);
       nsEventStatus status = nsEventStatus_eIgnore;
       mDispatcher->CommitComposition(status, &EmptyString());
     }
   }
 }
 
 NS_IMETHODIMP
-TextInputProcessor::Init(nsIDOMWindow* aWindow,
-                         nsITextInputProcessorCallback* aCallback,
-                         bool* aSucceeded)
+TextInputProcessor::BeginInputTransaction(
+                      nsIDOMWindow* aWindow,
+                      nsITextInputProcessorCallback* aCallback,
+                      bool* aSucceeded)
 {
   MOZ_RELEASE_ASSERT(aSucceeded, "aSucceeded must not be nullptr");
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   if (NS_WARN_IF(!aCallback)) {
     *aSucceeded = false;
     return NS_ERROR_INVALID_ARG;
   }
-  return InitInternal(aWindow, aCallback, false, *aSucceeded);
+  return BeginInputTransactionInternal(aWindow, aCallback, false, *aSucceeded);
 }
 
 NS_IMETHODIMP
-TextInputProcessor::InitForTests(nsIDOMWindow* aWindow,
-                                 nsITextInputProcessorCallback* aCallback,
-                                 uint8_t aOptionalArgc,
-                                 bool* aSucceeded)
+TextInputProcessor::BeginInputTransactionForTests(
+                      nsIDOMWindow* aWindow,
+                      nsITextInputProcessorCallback* aCallback,
+                      uint8_t aOptionalArgc,
+                      bool* aSucceeded)
 {
   MOZ_RELEASE_ASSERT(aSucceeded, "aSucceeded must not be nullptr");
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
   nsITextInputProcessorCallback* callback =
     aOptionalArgc >= 1 ? aCallback : nullptr;
-  return InitInternal(aWindow, callback, true, *aSucceeded);
+  return BeginInputTransactionInternal(aWindow, callback, true, *aSucceeded);
 }
 
 nsresult
-TextInputProcessor::InitInternal(nsIDOMWindow* aWindow,
-                                 nsITextInputProcessorCallback* aCallback,
-                                 bool aForTests,
-                                 bool& aSucceeded)
+TextInputProcessor::BeginInputTransactionInternal(
+                      nsIDOMWindow* aWindow,
+                      nsITextInputProcessorCallback* aCallback,
+                      bool aForTests,
+                      bool& aSucceeded)
 {
   aSucceeded = false;
   if (NS_WARN_IF(!aWindow)) {
     return NS_ERROR_INVALID_ARG;
   }
   nsCOMPtr<nsPIDOMWindow> pWindow(do_QueryInterface(aWindow));
   if (NS_WARN_IF(!pWindow)) {
     return NS_ERROR_INVALID_ARG;
@@ -159,19 +162,19 @@ TextInputProcessor::InitInternal(nsIDOMW
     return NS_OK;
   }
 
   // This instance has finished preparing to link to the dispatcher.  Therefore,
   // let's forget the old dispatcher and purpose.
   UnlinkFromTextEventDispatcher();
 
   if (aForTests) {
-    rv = dispatcher->InitForTests(this);
+    rv = dispatcher->BeginInputTransactionForTests(this);
   } else {
-    rv = dispatcher->Init(this);
+    rv = dispatcher->BeginInputTransaction(this);
   }
 
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   mDispatcher = dispatcher;
   mCallback = aCallback;
@@ -185,17 +188,17 @@ TextInputProcessor::UnlinkFromTextEventD
 {
   mDispatcher = nullptr;
   mForTests = false;
   if (mCallback) {
     nsCOMPtr<nsITextInputProcessorCallback> callback(mCallback);
     mCallback = nullptr;
 
     nsRefPtr<TextInputProcessorNotification> notification =
-      new TextInputProcessorNotification("notify-detached");
+      new TextInputProcessorNotification("notify-end-input-transaction");
     bool result = false;
     callback->OnNotify(this, notification, &result);
   }
 }
 
 nsresult
 TextInputProcessor::IsValidStateForComposition()
 {
--- a/dom/base/TextInputProcessor.h
+++ b/dom/base/TextInputProcessor.h
@@ -33,20 +33,21 @@ public:
                        const IMENotification& aNotification) MOZ_OVERRIDE;
   NS_IMETHOD_(void)
     OnRemovedFrom(TextEventDispatcher* aTextEventDispatcher) MOZ_OVERRIDE;
 
 protected:
   virtual ~TextInputProcessor();
 
 private:
-  nsresult InitInternal(nsIDOMWindow* aWindow,
-                        nsITextInputProcessorCallback* aCallback,
-                        bool aForTests,
-                        bool& aSucceeded);
+  nsresult BeginInputTransactionInternal(
+             nsIDOMWindow* aWindow,
+             nsITextInputProcessorCallback* aCallback,
+             bool aForTests,
+             bool& aSucceeded);
   nsresult CommitCompositionInternal(const nsAString* aCommitString = nullptr,
                                      bool* aSucceeded = nullptr);
   nsresult CancelCompositionInternal();
   nsresult IsValidStateForComposition();
   void UnlinkFromTextEventDispatcher();
 
   TextEventDispatcher* mDispatcher; // [Weak]
   nsCOMPtr<nsITextInputProcessorCallback> mCallback;
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -1477,17 +1477,17 @@ WebSocketImpl::Init(JSContext* aCx,
   } else {
     *aConnectionFailed = false;
   }
 }
 
 void
 WebSocketImpl::AsyncOpen(ErrorResult& aRv)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
 
   nsCString asciiOrigin;
   aRv = nsContentUtils::GetASCIIOrigin(mPrincipal, asciiOrigin);
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 
   ToLowerCase(asciiOrigin);
@@ -1522,17 +1522,17 @@ public:
 private:
   nsRefPtr<WebSocketImpl> mWebSocketImpl;
 };
 
 nsresult
 WebSocketImpl::InitializeConnection()
 {
   AssertIsOnMainThread();
-  NS_ABORT_IF_FALSE(!mChannel, "mChannel should be null");
+  MOZ_ASSERT(!mChannel, "mChannel should be null");
 
   nsCOMPtr<nsIWebSocketChannel> wsChannel;
   nsAutoCloseWS autoClose(this);
   nsresult rv;
 
   if (mSecure) {
     wsChannel =
       do_CreateInstance("@mozilla.org/network/protocol;1?name=wss", &rv);
--- a/dom/base/nsAttrValue.cpp
+++ b/dom/base/nsAttrValue.cpp
@@ -1027,18 +1027,17 @@ nsAttrValue::Equals(const nsAttrValue& a
     default:
     {
       if (IsSVGType(thisCont->mType)) {
         // Currently this method is never called for nsAttrValue objects that
         // point to SVG data types.
         // If that changes then we probably want to add methods to the
         // corresponding SVG types to compare their base values.
         // As a shortcut, however, we can begin by comparing the pointers.
-        NS_ABORT_IF_FALSE(false, "Comparing nsAttrValues that point to SVG "
-          "data");
+        MOZ_ASSERT(false, "Comparing nsAttrValues that point to SVG data");
         return false;
       }
       NS_NOTREACHED("unknown type stored in MiscContainer");
       return false;
     }
   }
   if (needsStringComparison) {
     if (thisCont->mStringBits == otherCont->mStringBits) {
@@ -1749,17 +1748,17 @@ nsAttrValue::ResetMiscAtomOrString()
     }
     cont->mStringBits = 0;
   }
 }
 
 void
 nsAttrValue::SetSVGType(ValueType aType, const void* aValue,
                         const nsAString* aSerialized) {
-  NS_ABORT_IF_FALSE(IsSVGType(aType), "Not an SVG type");
+  MOZ_ASSERT(IsSVGType(aType), "Not an SVG type");
 
   MiscContainer* cont = EnsureEmptyMiscContainer();
   // All SVG types are just pointers to classes so just setting any of them
   // will do. We'll lose type-safety but the signature of the calling
   // function should ensure we don't get anything unexpected, and once we
   // stick aValue in a union we lose type information anyway.
   cont->mValue.mSVGAngle = static_cast<const nsSVGAngle*>(aValue);
   cont->mType = aType;
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -4272,17 +4272,17 @@ nsContentUtils::ParseFragmentXML(const n
     parser.forget(&sXMLFragmentParser);
     // sXMLFragmentParser now owns the parser
   }
   if (!sXMLFragmentSink) {
     NS_NewXMLFragmentContentSink(&sXMLFragmentSink);
     // sXMLFragmentSink now owns the sink
   }
   nsCOMPtr<nsIContentSink> contentsink = do_QueryInterface(sXMLFragmentSink);
-  NS_ABORT_IF_FALSE(contentsink, "Sink doesn't QI to nsIContentSink!");
+  MOZ_ASSERT(contentsink, "Sink doesn't QI to nsIContentSink!");
   sXMLFragmentParser->SetContentSink(contentsink);
 
   sXMLFragmentSink->SetTargetDocument(aDocument);
   sXMLFragmentSink->SetPreventScriptExecution(aPreventScriptExecution);
 
   nsresult rv =
     sXMLFragmentParser->ParseFragment(aSourceBuffer,
                                       aTagStack);
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -1760,17 +1760,17 @@ GetXPCProto(nsIXPConnect *aXPConnect, JS
   NS_ASSERTION(aNameStruct->mType ==
                  nsGlobalNameStruct::eTypeClassConstructor ||
                aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo,
                "Wrong type!");
 
   nsCOMPtr<nsIClassInfo> ci;
   if (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor) {
     int32_t id = aNameStruct->mDOMClassInfoID;
-    NS_ABORT_IF_FALSE(id >= 0, "Negative DOM classinfo?!?");
+    MOZ_ASSERT(id >= 0, "Negative DOM classinfo?!?");
 
     nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id;
 
     ci = NS_GetDOMClassInfoInstance(ci_id);
   }
   else {
     ci = nsDOMClassInfo::GetClassInfoInstance(aNameStruct->mData);
   }
--- a/dom/base/nsDOMDataChannel.cpp
+++ b/dom/base/nsDOMDataChannel.cpp
@@ -264,17 +264,17 @@ nsDOMDataChannel::Send(const nsAString& 
 {
   NS_ConvertUTF16toUTF8 msgString(aData);
   Send(nullptr, msgString, msgString.Length(), false, aRv);
 }
 
 void
 nsDOMDataChannel::Send(File& aData, ErrorResult& aRv)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
 
   nsCOMPtr<nsIInputStream> msgStream;
   nsresult rv = aData.GetInternalStream(getter_AddRefs(msgStream));
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return;
   }
 
@@ -291,33 +291,33 @@ nsDOMDataChannel::Send(File& aData, Erro
   }
 
   Send(msgStream, EmptyCString(), msgLength, true, aRv);
 }
 
 void
 nsDOMDataChannel::Send(const ArrayBuffer& aData, ErrorResult& aRv)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
 
   aData.ComputeLengthAndData();
 
   static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
 
   uint32_t len = aData.Length();
   char* data = reinterpret_cast<char*>(aData.Data());
 
   nsDependentCSubstring msgString(data, len);
   Send(nullptr, msgString, len, true, aRv);
 }
 
 void
 nsDOMDataChannel::Send(const ArrayBufferView& aData, ErrorResult& aRv)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
 
   aData.ComputeLengthAndData();
 
   static_assert(sizeof(*aData.Data()) == 1, "byte-sized data required");
 
   uint32_t len = aData.Length();
   char* data = reinterpret_cast<char*>(aData.Data());
 
--- a/dom/base/nsDOMTokenList.cpp
+++ b/dom/base/nsDOMTokenList.cpp
@@ -177,17 +177,17 @@ nsDOMTokenList::Add(const nsAString& aTo
   tokens.AppendElement(aToken);
   Add(tokens, aError);
 }
 
 void
 nsDOMTokenList::RemoveInternal(const nsAttrValue* aAttr,
                                const nsTArray<nsString>& aTokens)
 {
-  NS_ABORT_IF_FALSE(aAttr, "Need an attribute");
+  MOZ_ASSERT(aAttr, "Need an attribute");
 
   nsAutoString input;
   aAttr->ToString(input);
 
   nsAString::const_iterator copyStart, tokenStart, iter, end;
   input.BeginReading(iter);
   input.EndReading(end);
   copyStart = iter;
@@ -199,17 +199,17 @@ nsDOMTokenList::RemoveInternal(const nsA
     // skip whitespace.
     while (iter != end && nsContentUtils::IsHTMLWhitespace(*iter)) {
       ++iter;
     }
 
     if (iter == end) {
       // At this point we're sure the last seen token (if any) wasn't to be
       // removed. So the trailing spaces will need to be kept.
-      NS_ABORT_IF_FALSE(!lastTokenRemoved, "How did this happen?");
+      MOZ_ASSERT(!lastTokenRemoved, "How did this happen?");
 
       output.Append(Substring(copyStart, end));
       break;
     }
 
     tokenStart = iter;
     do {
       ++iter;
@@ -222,18 +222,18 @@ nsDOMTokenList::RemoveInternal(const nsA
         ++iter;
       }
       copyStart = iter;
       lastTokenRemoved = true;
 
     } else {
 
       if (lastTokenRemoved && !output.IsEmpty()) {
-        NS_ABORT_IF_FALSE(!nsContentUtils::IsHTMLWhitespace(
-          output.Last()), "Invalid last output token");
+        MOZ_ASSERT(!nsContentUtils::IsHTMLWhitespace(output.Last()),
+                   "Invalid last output token");
         output.Append(char16_t(' '));
       }
       lastTokenRemoved = false;
       output.Append(Substring(copyStart, iter));
       copyStart = iter;
     }
   }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1711,19 +1711,19 @@ nsDOMWindowUtils::GetTranslationNodes(ns
 static TemporaryRef<DataSourceSurface>
 CanvasToDataSourceSurface(nsIDOMHTMLCanvasElement* aCanvas)
 {
   nsCOMPtr<nsINode> node = do_QueryInterface(aCanvas);
   if (!node) {
     return nullptr;
   }
 
-  NS_ABORT_IF_FALSE(node->IsElement(),
-                    "An nsINode that implements nsIDOMHTMLCanvasElement should "
-                    "be an element.");
+  MOZ_ASSERT(node->IsElement(),
+             "An nsINode that implements nsIDOMHTMLCanvasElement should "
+             "be an element.");
   nsLayoutUtils::SurfaceFromElementResult result =
     nsLayoutUtils::SurfaceFromElement(node->AsElement());
   return result.mSourceSurface->GetDataSurface();
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::CompareCanvases(nsIDOMHTMLCanvasElement *aCanvas1,
                                   nsIDOMHTMLCanvasElement *aCanvas2,
@@ -2304,17 +2304,17 @@ nsDOMWindowUtils::GetClassName(JS::Handl
   MOZ_RELEASE_ASSERT(nsContentUtils::IsCallerChrome());
 
   // Our argument must be a non-null object.
   if (aObject.isPrimitive()) {
     return NS_ERROR_XPC_BAD_CONVERT_JS;
   }
 
   *aName = NS_strdup(JS_GetClass(aObject.toObjectOrNull())->name);
-  NS_ABORT_IF_FALSE(*aName, "NS_strdup should be infallible.");
+  MOZ_ASSERT(*aName, "NS_strdup should be infallible.");
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetVisitedDependentComputedStyle(
                     nsIDOMElement *aElement, const nsAString& aPseudoElement,
                     const nsAString& aPropertyName, nsAString& aResult)
 {
@@ -2693,19 +2693,19 @@ nsDOMWindowUtils::ComputeAnimationDistan
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCSSProperty property =
     nsCSSProps::LookupProperty(aProperty, nsCSSProps::eIgnoreEnabledState);
   if (property != eCSSProperty_UNKNOWN && nsCSSProps::IsShorthand(property)) {
     property = eCSSProperty_UNKNOWN;
   }
 
-  NS_ABORT_IF_FALSE(property == eCSSProperty_UNKNOWN ||
-                    !nsCSSProps::IsShorthand(property),
-                    "should not have shorthand");
+  MOZ_ASSERT(property == eCSSProperty_UNKNOWN ||
+             !nsCSSProps::IsShorthand(property),
+             "should not have shorthand");
 
   StyleAnimationValue v1, v2;
   if (property == eCSSProperty_UNKNOWN ||
       !ComputeAnimationValue(property, content->AsElement(), aValue1, v1) ||
       !ComputeAnimationValue(property, content->AsElement(), aValue2, v2)) {
     return NS_ERROR_ILLEGAL_VALUE;
   }
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1051,18 +1051,18 @@ nsExternalResourceMap::ShowViewers()
 {
   mMap.EnumerateRead(ExternalResourceShower, nullptr);
 }
 
 void
 TransferZoomLevels(nsIDocument* aFromDoc,
                    nsIDocument* aToDoc)
 {
-  NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
-                    "transferring zoom levels from/to null doc");
+  MOZ_ASSERT(aFromDoc && aToDoc,
+             "transferring zoom levels from/to null doc");
 
   nsIPresShell* fromShell = aFromDoc->GetShell();
   if (!fromShell)
     return;
 
   nsPresContext* fromCtxt = fromShell->GetPresContext();
   if (!fromCtxt)
     return;
@@ -1078,18 +1078,18 @@ TransferZoomLevels(nsIDocument* aFromDoc
   toCtxt->SetFullZoom(fromCtxt->GetFullZoom());
   toCtxt->SetBaseMinFontSize(fromCtxt->BaseMinFontSize());
   toCtxt->SetTextZoom(fromCtxt->TextZoom());
 }
 
 void
 TransferShowingState(nsIDocument* aFromDoc, nsIDocument* aToDoc)
 {
-  NS_ABORT_IF_FALSE(aFromDoc && aToDoc,
-                    "transferring showing state from/to null doc");
+  MOZ_ASSERT(aFromDoc && aToDoc,
+             "transferring showing state from/to null doc");
 
   if (aFromDoc->IsShowing()) {
     aToDoc->OnPageShow(true, nullptr);
   }
 }
 
 nsresult
 nsExternalResourceMap::AddExternalResource(nsIURI* aURI,
@@ -1619,18 +1619,18 @@ ClearAllBoxObjects(nsIContent* aKey, nsP
   if (aBoxObject) {
     aBoxObject->Clear();
   }
   return PL_DHASH_NEXT;
 }
 
 nsIDocument::~nsIDocument()
 {
-  NS_ABORT_IF_FALSE(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
-                    "must not have media query lists left");
+  MOZ_ASSERT(PR_CLIST_IS_EMPTY(&mDOMMediaQueryLists),
+             "must not have media query lists left");
 
   if (mNodeInfoManager) {
     mNodeInfoManager->DropDocumentReference();
   }
 }
 
 
 nsDocument::~nsDocument()
@@ -2206,18 +2206,18 @@ nsDocument::Init()
 
   mNodeInfoManager = new nsNodeInfoManager();
   nsresult rv = mNodeInfoManager->Init(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // mNodeInfo keeps NodeInfoManager alive!
   mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
   NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
-  NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
-                    "Bad NodeType in aNodeInfo");
+  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
+             "Bad NodeType in aNodeInfo");
 
   NS_ASSERTION(OwnerDoc() == this, "Our nodeinfo is busted!");
 
   // If after creation the owner js global is not set for a document
   // we use the default compartment for this document, instead of creating
   // wrapper in some random compartment when the document is exposed to js
   // via some events.
   nsCOMPtr<nsIGlobalObject> global = xpc::NativeGlobal(xpc::PrivilegedJunkScope());
@@ -4667,21 +4667,21 @@ nsDocument::SetScriptGlobalObject(nsIScr
 #ifdef DEBUG
   {
     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aScriptGlobalObject));
 
     NS_ASSERTION(!win || win->IsInnerWindow(),
                  "Script global object must be an inner window!");
   }
 #endif
-  NS_ABORT_IF_FALSE(aScriptGlobalObject || !mAnimationController ||
-                    mAnimationController->IsPausedByType(
-                        nsSMILTimeContainer::PAUSE_PAGEHIDE |
-                        nsSMILTimeContainer::PAUSE_BEGIN),
-                    "Clearing window pointer while animations are unpaused");
+  MOZ_ASSERT(aScriptGlobalObject || !mAnimationController ||
+             mAnimationController->IsPausedByType(
+               nsSMILTimeContainer::PAUSE_PAGEHIDE |
+               nsSMILTimeContainer::PAUSE_BEGIN),
+             "Clearing window pointer while animations are unpaused");
 
   if (mScriptGlobalObject && !aScriptGlobalObject) {
     // We're detaching from the window.  We need to grab a pointer to
     // our layout history state now.
     mLayoutHistoryState = GetLayoutHistoryState();
 
     if (mPresShell && !EventHandlingSuppressed()) {
       RevokeAnimationFrameNotifications();
@@ -10401,18 +10401,18 @@ nsDocument::AddImage(imgIRequest* aImage
 nsresult
 nsDocument::RemoveImage(imgIRequest* aImage, uint32_t aFlags)
 {
   NS_ENSURE_ARG_POINTER(aImage);
 
   // Get the old count. It should exist and be > 0.
   uint32_t count = 0;
   DebugOnly<bool> found = mImageTracker.Get(aImage, &count);
-  NS_ABORT_IF_FALSE(found, "Removing image that wasn't in the tracker!");
-  NS_ABORT_IF_FALSE(count > 0, "Entry in the cache tracker with count 0!");
+  MOZ_ASSERT(found, "Removing image that wasn't in the tracker!");
+  MOZ_ASSERT(count > 0, "Entry in the cache tracker with count 0!");
 
   // We're removing, so decrement the count.
   count--;
 
   // If the count is now zero, remove from the tracker.
   // Otherwise, set the new value.
   if (count != 0) {
     mImageTracker.Put(aImage, count);
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -85,17 +85,16 @@
 #include "mozilla/dom/Element.h"
 #include "mozilla/jsipc/CrossProcessObjectWrappers.h"
 #include "mozilla/layout/RenderFrameParent.h"
 #include "nsIAppsService.h"
 #include "GeckoProfiler.h"
 
 #include "jsapi.h"
 #include "mozilla/dom/HTMLIFrameElement.h"
-#include "mozilla/dom/SVGIFrameElement.h"
 #include "nsSandboxFlags.h"
 #include "mozilla/layers/CompositorChild.h"
 
 #include "mozilla/dom/StructuredCloneUtils.h"
 
 #ifdef MOZ_XUL
 #include "nsXULPopupManager.h"
 #endif
@@ -206,18 +205,17 @@ nsFrameLoader::Create(Element* aOwner, b
 
 NS_IMETHODIMP
 nsFrameLoader::LoadFrame()
 {
   NS_ENSURE_TRUE(mOwnerContent, NS_ERROR_NOT_INITIALIZED);
 
   nsAutoString src;
 
-  bool isSrcdoc = (mOwnerContent->IsHTML(nsGkAtoms::iframe) ||
-                   mOwnerContent->IsSVG(nsGkAtoms::iframe)) &&
+  bool isSrcdoc = mOwnerContent->IsHTML(nsGkAtoms::iframe) &&
                   mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::srcdoc);
   if (isSrcdoc) {
     src.AssignLiteral("about:srcdoc");
   }
   else {
     GetURL(src);
 
     src.Trim(" \t\n\r");
@@ -410,18 +408,17 @@ nsFrameLoader::ReallyStartLoadingInterna
   // We'll use our principal, not that of the document loaded inside us.  This
   // is very important; needed to prevent XSS attacks on documents loaded in
   // subframes!
   loadInfo->SetOwner(mOwnerContent->NodePrincipal());
 
   nsCOMPtr<nsIURI> referrer;
   
   nsAutoString srcdoc;
-  bool isSrcdoc = (mOwnerContent->IsHTML(nsGkAtoms::iframe) ||
-                   mOwnerContent->IsSVG(nsGkAtoms::iframe)) &&
+  bool isSrcdoc = mOwnerContent->IsHTML(nsGkAtoms::iframe) &&
                   mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc,
                                          srcdoc);
 
   if (isSrcdoc) {
     nsAutoString referrerStr;
     mOwnerContent->OwnerDoc()->GetReferrer(referrerStr);
     rv = NS_NewURI(getter_AddRefs(referrer), referrerStr);
 
@@ -1652,40 +1649,34 @@ nsFrameLoader::MaybeCreateDocShell()
   if (mIsPrerendered) {
     nsresult rv = mDocShell->SetIsPrerendered(true);
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   // Apply sandbox flags even if our owner is not an iframe, as this copies
   // flags from our owning content's owning document.
   uint32_t sandboxFlags = 0;
-  if (!mOwnerContent->IsSVG(nsGkAtoms::iframe)) {
-    HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
-    if (iframe) {
-      sandboxFlags = iframe->GetSandboxFlags();
-    }
-  } else {
-    SVGIFrameElement* iframe = static_cast<SVGIFrameElement*>(mOwnerContent);
+  HTMLIFrameElement* iframe = HTMLIFrameElement::FromContent(mOwnerContent);
+  if (iframe) {
     sandboxFlags = iframe->GetSandboxFlags();
   }
   ApplySandboxFlags(sandboxFlags);
 
   if (!mNetworkCreated) {
     if (mDocShell) {
       mDocShell->SetCreatedDynamically(true);
     }
   }
 
   // Get the frame name and tell the docshell about it.
   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
   nsAutoString frameName;
 
   int32_t namespaceID = mOwnerContent->GetNameSpaceID();
-  if ((namespaceID == kNameSpaceID_XHTML || namespaceID == kNameSpaceID_SVG)
-      && !mOwnerContent->IsInHTMLDocument()) {
+  if (namespaceID == kNameSpaceID_XHTML && !mOwnerContent->IsInHTMLDocument()) {
     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
   } else {
     mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, frameName);
     // XXX if no NAME then use ID, after a transition period this will be
     // changed so that XUL only uses ID too (bug 254284).
     if (frameName.IsEmpty() && namespaceID == kNameSpaceID_XUL) {
       mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::id, frameName);
     }
deleted file mode 100644
--- a/dom/base/nsFrameLoader.cpp.rej
+++ /dev/null
@@ -1,21 +0,0 @@
---- nsFrameLoader.cpp
-+++ nsFrameLoader.cpp
-@@ -48,17 +48,17 @@
- #include "nsIDOMHTMLDocument.h"
- #include "nsIXULWindow.h"
- #include "nsIEditor.h"
- #include "nsIMozBrowserFrame.h"
- #include "nsIPermissionManager.h"
- #include "nsISHistory.h"
- #include "nsNullPrincipal.h"
- #include "nsIScriptError.h"
--
-+#include "nsGlobalWindow.h"
- #include "nsLayoutUtils.h"
- #include "nsView.h"
- 
- #include "nsIURI.h"
- #include "nsIURL.h"
- #include "nsNetUtil.h"
- 
- #include "nsGkAtoms.h"
--- a/dom/base/nsFrameMessageManager.cpp
+++ b/dom/base/nsFrameMessageManager.cpp
@@ -1532,50 +1532,51 @@ nsFrameScriptExecutor::TryCacheLoadAndCo
                                    dataStringBuf, dataStringLength);
   }
 
   JS::SourceBufferHolder srcBuf(dataStringBuf, dataStringLength,
                                 JS::SourceBufferHolder::GiveOwnership);
 
   if (dataStringBuf && dataStringLength > 0) {
     AutoSafeJSContext cx;
-    JS::Rooted<JSObject*> global(cx, mGlobal->GetJSObject());
-    if (global) {
-      JSAutoCompartment ac(cx, global);
-      JS::CompileOptions options(cx);
-      options.setFileAndLine(url.get(), 1);
-      options.setNoScriptRval(true);
-      JS::Rooted<JSScript*> script(cx);
+    // Compile the script in the compilation scope instead of the current global
+    // to avoid keeping the current compartment alive.
+    JS::Rooted<JSObject*> global(cx, xpc::CompilationScope());
+
+    JSAutoCompartment ac(cx, global);
+    JS::CompileOptions options(cx, JSVERSION_LATEST);
+    options.setFileAndLine(url.get(), 1);
+    options.setNoScriptRval(true);
+    JS::Rooted<JSScript*> script(cx);
 
-      if (aRunInGlobalScope) {
-        if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
-          return;
-        }
-      } else {
-        // We can't clone compile-and-go scripts.
-        options.setCompileAndGo(false);
-        if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
-          return;
-        }
+    if (aRunInGlobalScope) {
+      if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
+        return;
       }
+    } else {
+      // We can't clone compile-and-go scripts.
+      options.setCompileAndGo(false);
+      if (!JS::Compile(cx, JS::NullPtr(), options, srcBuf, &script)) {
+        return;
+      }
+    }
 
-      aScriptp.set(script);
+    aScriptp.set(script);
 
-      nsAutoCString scheme;
-      uri->GetScheme(scheme);
-      // We don't cache data: scripts!
-      if (aShouldCache && !scheme.EqualsLiteral("data")) {
-        nsFrameScriptObjectExecutorHolder* holder;
+    nsAutoCString scheme;
+    uri->GetScheme(scheme);
+    // We don't cache data: scripts!
+    if (aShouldCache && !scheme.EqualsLiteral("data")) {
+      nsFrameScriptObjectExecutorHolder* holder;
 
-        // Root the object also for caching.
-        if (script) {
-          holder = new nsFrameScriptObjectExecutorHolder(cx, script, aRunInGlobalScope);
-        }
-        sCachedScripts->Put(aURL, holder);
+      // Root the object also for caching.
+      if (script) {
+        holder = new nsFrameScriptObjectExecutorHolder(cx, script, aRunInGlobalScope);
       }
+      sCachedScripts->Put(aURL, holder);
     }
   }
 }
 
 void
 nsFrameScriptExecutor::TryCacheLoadAndCompileScript(const nsAString& aURL,
                                                     bool aRunInGlobalScope)
 {
--- a/dom/base/nsGenericDOMDataNode.cpp
+++ b/dom/base/nsGenericDOMDataNode.cpp
@@ -37,35 +37,33 @@
 #include "nsWrapperCacheInlines.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
 nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
   : nsIContent(aNodeInfo)
 {
-  NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
-                    mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
-                    mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
-                    mNodeInfo->NodeType() ==
-                      nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-                    mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
-                    "Bad NodeType in aNodeInfo");
+  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
+             "Bad NodeType in aNodeInfo");
 }
 
 nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
   : nsIContent(aNodeInfo)
 {
-  NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
-                    mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
-                    mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
-                    mNodeInfo->NodeType() ==
-                      nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
-                    mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
-                    "Bad NodeType in aNodeInfo");
+  MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
+             mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
+             "Bad NodeType in aNodeInfo");
 }
 
 nsGenericDOMDataNode::~nsGenericDOMDataNode()
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
   if (GetParent()) {
     NS_RELEASE(mParent);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1519,17 +1519,17 @@ nsGlobalWindow::CleanUp()
   if (IsInnerWindow()) {
     DisableGamepadUpdates();
     mHasGamepad = false;
   } else {
     MOZ_ASSERT(!mHasGamepad);
   }
 
   if (mCleanMessageManager) {
-    NS_ABORT_IF_FALSE(mIsChrome, "only chrome should have msg manager cleaned");
+    MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
     nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this);
     if (asChrome->mMessageManager) {
       static_cast<nsFrameMessageManager*>(
         asChrome->mMessageManager.get())->Disconnect();
     }
   }
 
   mArguments = nullptr;
@@ -8114,36 +8114,36 @@ PopulateMessagePortList(MessagePortBase*
 
   array->AppendElement(aKey);
   return PL_DHASH_NEXT;
 }
 
 NS_IMETHODIMP
 PostMessageEvent::Run()
 {
-  NS_ABORT_IF_FALSE(mTargetWindow->IsOuterWindow(),
-                    "should have been passed an outer window!");
-  NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(),
-                    "should have been passed an outer window!");
+  MOZ_ASSERT(mTargetWindow->IsOuterWindow(),
+             "should have been passed an outer window!");
+  MOZ_ASSERT(!mSource || mSource->IsOuterWindow(),
+             "should have been passed an outer window!");
 
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
 
   // If we bailed before this point we're going to leak mMessage, but
   // that's probably better than crashing.
 
   nsRefPtr<nsGlobalWindow> targetWindow;
   if (mTargetWindow->IsClosedOrClosing() ||
       !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
       targetWindow->IsClosedOrClosing())
     return NS_OK;
 
-  NS_ABORT_IF_FALSE(targetWindow->IsInnerWindow(),
-                    "we ordered an inner window!");
+  MOZ_ASSERT(targetWindow->IsInnerWindow(),
+             "we ordered an inner window!");
   JSAutoCompartment ac(cx, targetWindow->GetWrapperPreserveColor());
 
   // Ensure that any origin which might have been provided is the origin of this
   // window's document.  Note that we do this *now* instead of when postMessage
   // is called because the target window might have been navigated to a
   // different location between then and now.  If this check happened when
   // postMessage was called, it would be fairly easy for a malicious webpage to
   // intercept messages intended for another site by carefully timing navigation
@@ -8230,18 +8230,18 @@ nsGlobalWindow::PostMessageMoz(JSContext
   //
   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
   //
 
   // First, get the caller's window
   nsRefPtr<nsGlobalWindow> callerInnerWin = CallerInnerWindow();
   nsIPrincipal* callerPrin;
   if (callerInnerWin) {
-    NS_ABORT_IF_FALSE(callerInnerWin->IsInnerWindow(),
-                      "should have gotten an inner window here");
+    MOZ_ASSERT(callerInnerWin->IsInnerWindow(),
+               "should have gotten an inner window here");
 
     // Compute the caller's origin either from its principal or, in the case the
     // principal doesn't carry a URI (e.g. the system principal), the caller's
     // document.  We must get this now instead of when the event is created and
     // dispatched, because ultimately it is the identity of the calling window
     // *now* that determines who sent the message (and not an identity which might
     // have changed due to intervening navigations).
     callerPrin = callerInnerWin->GetPrincipal();
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -1713,18 +1713,18 @@ protected:
       mGroupMessageManagers(1)
   {
     mIsChrome = true;
     mCleanMessageManager = true;
   }
 
   ~nsGlobalChromeWindow()
   {
-    NS_ABORT_IF_FALSE(mCleanMessageManager,
-                      "chrome windows may always disconnect the msg manager");
+    MOZ_ASSERT(mCleanMessageManager,
+               "chrome windows may always disconnect the msg manager");
 
     mGroupMessageManagers.EnumerateRead(DisconnectGroupMessageManager, nullptr);
     mGroupMessageManagers.Clear();
 
     if (mMessageManager) {
       static_cast<nsFrameMessageManager *>(
         mMessageManager.get())->Disconnect();
     }
--- a/dom/base/nsHostObjectURI.cpp
+++ b/dom/base/nsHostObjectURI.cpp
@@ -89,18 +89,17 @@ nsHostObjectURI::CloneInternal(nsSimpleU
   nsCOMPtr<nsIURI> simpleClone;
   nsresult rv =
     nsSimpleURI::CloneInternal(aRefHandlingMode, getter_AddRefs(simpleClone));
   NS_ENSURE_SUCCESS(rv, rv);
 
 #ifdef DEBUG
   nsRefPtr<nsHostObjectURI> uriCheck;
   rv = simpleClone->QueryInterface(kHOSTOBJECTURICID, getter_AddRefs(uriCheck));
-  NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv) && uriCheck,
-		    "Unexpected!");
+  MOZ_ASSERT(NS_SUCCEEDED(rv) && uriCheck);
 #endif
 
   nsHostObjectURI* u = static_cast<nsHostObjectURI*>(simpleClone.get());
 
   u->mPrincipal = mPrincipal;
 
   simpleClone.forget(aClone);
   return NS_OK;
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -1057,17 +1057,17 @@ nsINode::IsEqualNode(nsINode* aOther)
         docType2->GetInternalSubset(string2);
         if (!string1.Equals(string2)) {
           return false;
         }
 
         break;
       }
       default:
-        NS_ABORT_IF_FALSE(false, "Unknown node type");
+        MOZ_ASSERT(false, "Unknown node type");
     }
 
     nsINode* nextNode = node1->GetFirstChild();
     if (nextNode) {
       node1 = nextNode;
       node2 = node2->GetFirstChild();
     }
     else {
@@ -1352,17 +1352,17 @@ nsINode::Traverse(nsINode *tmp, nsCycleC
         // If we're in a black document, return early.
         if ((currentDoc && currentDoc->IsBlack())) {
           return false;
         }
         // If we're not in anonymous content and we have a black parent,
         // return early.
         nsIContent* parent = tmp->GetParent();
         if (parent && !parent->UnoptimizableCCNode() && parent->IsBlack()) {
-          NS_ABORT_IF_FALSE(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
+          MOZ_ASSERT(parent->IndexOf(tmp) >= 0, "Parent doesn't own us?");
           return false;
         }
       }
     }
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNodeInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
@@ -2579,17 +2579,17 @@ FindMatchingElements(nsINode* aRoot, nsC
       aList.AppendElement(results.ElementAt(i));
     }
   }
 }
 
 struct ElementHolder {
   ElementHolder() : mElement(nullptr) {}
   void AppendElement(Element* aElement) {
-    NS_ABORT_IF_FALSE(!mElement, "Should only get one element");
+    MOZ_ASSERT(!mElement, "Should only get one element");
     mElement = aElement;
   }
   void SetCapacity(uint32_t aCapacity) { MOZ_CRASH("Don't call me!"); }
   uint32_t Length() { return 0; }
   Element* ElementAt(uint32_t aIndex) { return nullptr; }
 
   Element* mElement;
 };
--- a/dom/base/nsImageLoadingContent.cpp
+++ b/dom/base/nsImageLoadingContent.cpp
@@ -131,17 +131,17 @@ nsImageLoadingContent::Notify(imgIReques
 
   if (aType == imgINotificationObserver::UNLOCKED_DRAW) {
     OnUnlockedDraw();
     return NS_OK;
   }
 
   if (aType == imgINotificationObserver::LOAD_COMPLETE) {
     // We should definitely have a request here
-    NS_ABORT_IF_FALSE(aRequest, "no request?");
+    MOZ_ASSERT(aRequest, "no request?");
 
     NS_PRECONDITION(aRequest == mCurrentRequest || aRequest == mPendingRequest,
                     "Unknown request");
   }
 
   {
     nsAutoScriptBlocker scriptBlocker;
 
@@ -222,18 +222,18 @@ nsImageLoadingContent::OnLoadComplete(im
 
   // Our state may change. Watch it.
   AutoStateChanger changer(this, true);
 
   // If the pending request is loaded, switch to it.
   if (aRequest == mPendingRequest) {
     MakePendingRequestCurrent();
   }
-  NS_ABORT_IF_FALSE(aRequest == mCurrentRequest,
-                    "One way or another, we should be current by now");
+  MOZ_ASSERT(aRequest == mCurrentRequest,
+             "One way or another, we should be current by now");
 
   // We just loaded all the data we're going to get. If we're visible and
   // haven't done an initial paint (*), we want to make sure the image starts
   // decoding immediately, for two reasons:
   //
   // 1) This image is sitting idle but might need to be decoded as soon as we
   // start painting, in which case we've wasted time.
   //
@@ -885,19 +885,19 @@ nsImageLoadingContent::LoadImage(nsIURI*
   AutoStateChanger changer(this, aNotify);
 
   // Sanity check.
   //
   // We use the principal of aDocument to avoid having to QI |this| an extra
   // time. It should always be the same as the principal of this node.
 #ifdef DEBUG
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
-  NS_ABORT_IF_FALSE(thisContent &&
-                    thisContent->NodePrincipal() == aDocument->NodePrincipal(),
-                    "Principal mismatch?");
+  MOZ_ASSERT(thisContent &&
+             thisContent->NodePrincipal() == aDocument->NodePrincipal(),
+             "Principal mismatch?");
 #endif
 
   // Are we blocked?
   int16_t cpDecision = nsIContentPolicy::REJECT_REQUEST;
   nsContentPolicyType policyType = PolicyTypeForLoad(aImageLoadType);
 
   nsContentUtils::CanLoadImage(aNewURI,
                                static_cast<nsIImageLoadingContent*>(this),
@@ -1214,17 +1214,17 @@ nsImageLoadingContent::PrepareNextReques
   // Otherwise, make it pending.
   return PreparePendingRequest(aImageLoadType);
 }
 
 void
 nsImageLoadingContent::SetBlockedRequest(nsIURI* aURI, int16_t aContentDecision)
 {
   // Sanity
-  NS_ABORT_IF_FALSE(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
+  MOZ_ASSERT(!NS_CP_ACCEPTED(aContentDecision), "Blocked but not?");
 
   // We do some slightly illogical stuff here to maintain consistency with
   // old behavior that people probably depend on. Even in the case where the
   // new image is blocked, the old one should really be canceled with the
   // reason "image source changed". However, apparently there's some abuse
   // over in nsImageFrame where the displaying of the "broken" icon for the
   // next image depends on the cancel reason of the previous image. ugh.
   ClearPendingRequest(NS_ERROR_IMAGE_BLOCKED, ON_NONVISIBLE_REQUEST_DISCARD);
@@ -1342,18 +1342,18 @@ nsImageLoadingContent::ClearCurrentReque
 {
   if (!mCurrentRequest) {
     // Even if we didn't have a current request, we might have been keeping
     // a URI and flags as a placeholder for a failed load. Clear that now.
     mCurrentURI = nullptr;
     mCurrentRequestFlags = 0;
     return;
   }
-  NS_ABORT_IF_FALSE(!mCurrentURI,
-                    "Shouldn't have both mCurrentRequest and mCurrentURI!");
+  MOZ_ASSERT(!mCurrentURI,
+             "Shouldn't have both mCurrentRequest and mCurrentURI!");
 
   // Deregister this image from the refresh driver so it no longer receives
   // notifications.
   nsLayoutUtils::DeregisterImageRequest(GetFramePresContext(), mCurrentRequest,
                                         &mCurrentRequestRegistered);
 
   // Clean up the request.
   UntrackImage(mCurrentRequest, aNonvisibleAction);
--- a/dom/base/nsPerformance.cpp
+++ b/dom/base/nsPerformance.cpp
@@ -600,28 +600,28 @@ nsPerformance::AddEntry(nsIHttpChannel* 
   }
 }
 
 bool
 nsPerformance::PerformanceEntryComparator::Equals(
     const PerformanceEntry* aElem1,
     const PerformanceEntry* aElem2) const
 {
-  NS_ABORT_IF_FALSE(aElem1 && aElem2,
-      "Trying to compare null performance entries");
+  MOZ_ASSERT(aElem1 && aElem2,
+             "Trying to compare null performance entries");
   return aElem1->StartTime() == aElem2->StartTime();
 }
 
 bool
 nsPerformance::PerformanceEntryComparator::LessThan(
     const PerformanceEntry* aElem1,
     const PerformanceEntry* aElem2) const
 {
-  NS_ABORT_IF_FALSE(aElem1 && aElem2,
-      "Trying to compare null performance entries");
+  MOZ_ASSERT(aElem1 && aElem2,
+             "Trying to compare null performance entries");
   return aElem1->StartTime() < aElem2->StartTime();
 }
 
 void
 nsPerformance::InsertPerformanceEntry(PerformanceEntry* aEntry,
                                       bool aShouldPrint)
 {
   MOZ_ASSERT(aEntry);
--- a/dom/base/nsReferencedElement.cpp
+++ b/dom/base/nsReferencedElement.cpp
@@ -13,17 +13,17 @@
 #include "nsIDOMNode.h"
 #include "nsIDOMElement.h"
 #include "nsCycleCollectionParticipant.h"
 
 void
 nsReferencedElement::Reset(nsIContent* aFromContent, nsIURI* aURI,
                            bool aWatch, bool aReferenceImage)
 {
-  NS_ABORT_IF_FALSE(aFromContent, "Reset() expects non-null content pointer");
+  MOZ_ASSERT(aFromContent, "Reset() expects non-null content pointer");
 
   Unlink();
 
   if (!aURI)
     return;
 
   nsAutoCString refPart;
   aURI->GetRef(refPart);
--- a/dom/base/nsTextNode.h
+++ b/dom/base/nsTextNode.h
@@ -21,18 +21,18 @@ class nsNodeInfoManager;
  * Class used to implement DOM text nodes
  */
 class nsTextNode : public mozilla::dom::Text,
                    public nsIDOMText
 {
 private:
   void Init()
   {
-    NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE,
-                      "Bad NodeType in aNodeInfo");
+    MOZ_ASSERT(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE,
+               "Bad NodeType in aNodeInfo");
   }
 
 public:
   explicit nsTextNode(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
     : mozilla::dom::Text(aNodeInfo)
   {
     Init();
   }
--- a/dom/base/nsTreeSanitizer.cpp
+++ b/dom/base/nsTreeSanitizer.cpp
@@ -1098,18 +1098,18 @@ nsTreeSanitizer::SanitizeStyleSheet(cons
   sheet->SetURIs(aDocument->GetDocumentURI(), nullptr, aBaseURI);
   sheet->SetPrincipal(aDocument->NodePrincipal());
   // Create the CSS parser, and parse the CSS text.
   nsCSSParser parser(nullptr, sheet);
   rv = parser.ParseSheet(aOriginal, aDocument->GetDocumentURI(), aBaseURI,
                          aDocument->NodePrincipal(), 0, false);
   NS_ENSURE_SUCCESS(rv, true);
   // Mark the sheet as complete.
-  NS_ABORT_IF_FALSE(!sheet->IsModified(),
-      "should not get marked modified during parsing");
+  MOZ_ASSERT(!sheet->IsModified(),
+             "should not get marked modified during parsing");
   sheet->SetComplete();
   // Loop through all the rules found in the CSS text
   int32_t ruleCount = sheet->StyleRuleCount();
   for (int32_t i = 0; i < ruleCount; ++i) {
     mozilla::css::Rule* rule = sheet->GetStyleRuleAt(i);
     if (!rule)
       continue;
     switch (rule->GetType()) {
--- a/dom/base/nsXMLHttpRequest.cpp
+++ b/dom/base/nsXMLHttpRequest.cpp
@@ -316,17 +316,17 @@ nsXMLHttpRequest::~nsXMLHttpRequest()
 {
   mState |= XML_HTTP_REQUEST_DELETED;
 
   if (mState & (XML_HTTP_REQUEST_SENT |
                 XML_HTTP_REQUEST_LOADING)) {
     Abort();
   }
 
-  NS_ABORT_IF_FALSE(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
+  MOZ_ASSERT(!(mState & XML_HTTP_REQUEST_SYNCLOOPING), "we rather crash than hang");
   mState &= ~XML_HTTP_REQUEST_SYNCLOOPING;
 
   mResultJSON.setUndefined();
   mResultArrayBuffer = nullptr;
   mozilla::DropJSObjects(this);
 }
 
 void
@@ -1910,17 +1910,17 @@ NS_IMETHODIMP
 nsXMLHttpRequest::OnDataAvailable(nsIRequest *request,
                                   nsISupports *ctxt,
                                   nsIInputStream *inStr,
                                   uint64_t sourceOffset,
                                   uint32_t count)
 {
   NS_ENSURE_ARG_POINTER(inStr);
 
-  NS_ABORT_IF_FALSE(mContext.get() == ctxt,"start context different from OnDataAvailable context");
+  MOZ_ASSERT(mContext.get() == ctxt,"start context different from OnDataAvailable context");
 
   mProgressSinceLastProgressEvent = true;
 
   bool cancelable = false;
   if ((mResponseType == XML_HTTP_RESPONSE_TYPE_BLOB ||
        mResponseType == XML_HTTP_RESPONSE_TYPE_MOZ_BLOB) && !mDOMFile) {
     cancelable = CreateDOMFile(request);
     // The nsIStreamListener contract mandates us
@@ -3231,18 +3231,18 @@ nsXMLHttpRequest::SetTimeout(uint32_t aT
   if (mRequestSentTime) {
     StartTimeoutTimer();
   }
 }
 
 void
 nsXMLHttpRequest::StartTimeoutTimer()
 {
-  NS_ABORT_IF_FALSE(mRequestSentTime,
-                    "StartTimeoutTimer mustn't be called before the request was sent!");
+  MOZ_ASSERT(mRequestSentTime,
+             "StartTimeoutTimer mustn't be called before the request was sent!");
   if (mState & XML_HTTP_REQUEST_DONE) {
     // do nothing!
     return;
   }
 
   if (mTimeoutTimer) {
     mTimeoutTimer->Cancel();
   }
--- a/dom/base/test/chrome/cpows_child.js
+++ b/dom/base/test/chrome/cpows_child.js
@@ -59,21 +59,28 @@ function make_object()
   var throwing = new Proxy({}, new Proxy({}, {
       get: function (trap) { throw trap; }
     }));
 
   let array = [1, 2, 3];
 
   let for_json = { "n": 3, "a": array, "s": "hello", o: { "x": 10 } };
 
+  let proto = { data: 42 };
+  let with_proto = Object.create(proto);
+
+  let with_null_proto = Object.create(null);
+
   return { "data": o,
            "throwing": throwing,
            "document": content.document,
            "array": array,
-           "for_json": for_json
+           "for_json": for_json,
+           "with_proto": with_proto,
+           "with_null_proto": with_null_proto
          };
 }
 
 function make_json()
 {
   return { check: "ok" };
 }
 
--- a/dom/base/test/chrome/cpows_parent.xul
+++ b/dom/base/test/chrome/cpows_parent.xul
@@ -121,16 +121,24 @@
       let str = JSON.stringify(j);
       let j2 = JSON.parse(str);
       ok(j2.n === 3, "JSON integer property");
       ok(j2.a[0] === 1, "JSON array index");
       ok(j2.a[1] === 2, "JSON array index");
       ok(j2.a[2] === 3, "JSON array index");
       ok(j2.s === "hello", "JSON string property");
       ok(j2.o.x === 10, "JSON object property");
+
+      let with_proto = message.objects.with_proto;
+      let proto = Object.getPrototypeOf(with_proto);
+      ok(proto.data == 42, "Object.getPrototypeOf works on CPOW");
+
+      let with_null_proto = message.objects.with_null_proto;
+      proto = Object.getPrototypeOf(with_null_proto);
+      ok(proto === null, "Object.getPrototypeOf works on CPOW (null proto)");
     }
 
     function recvAsyncMessage(message) {
       testCpowMessage(message);
     }
 
     function recvSyncMessage(message) {
       testCpowMessage(message);
--- a/dom/base/test/chrome/window_nsITextInputProcessor.xul
+++ b/dom/base/test/chrome/window_nsITextInputProcessor.xul
@@ -68,19 +68,19 @@ var otherDocument = otherWindow.document
 var inputInChildWindow = otherDocument.getElementById("input");
 
 function createTIP()
 {
   return Components.classes["@mozilla.org/text-input-processor;1"].
            createInstance(Components.interfaces.nsITextInputProcessor);
 }
 
-function runInitMethodTests()
+function runBeginInputTransactionMethodTests()
 {
-  var description = "runInitMethodTest: ";
+  var description = "runBeginInputTransactionMethodTests: ";
   input.value = "";
   input.focus();
 
   var simpleCallback = function (aTIP, aNotification)
   {
     switch (aNotification.type) {
       case "request-to-commit":
         aTIP.commitComposition();
@@ -92,83 +92,83 @@ function runInitMethodTests()
     return true;
   };
 
   var TIP1 = createTIP();
   var TIP2 = createTIP();
   isnot(TIP1, TIP2,
         description + "TIP instances should be different");
 
-  // init() and initForTests() can take ownership if there is no composition.
-  ok(TIP1.init(window, simpleCallback),
-     description + "TIP1.init(window) should succeed because there is no composition");
-  ok(TIP1.initForTests(window),
-     description + "TIP1.initForTests(window) should succeed because there is no composition");
-  ok(TIP2.init(window, simpleCallback),
-     description + "TIP2.init(window) should succeed because there is no composition");
-  ok(TIP2.initForTests(window),
-     description + "TIP2.initForTests(window) should succeed because there is no composition");
+  // beginInputTransaction() and beginInputTransactionForTests() can take ownership if there is no composition.
+  ok(TIP1.beginInputTransaction(window, simpleCallback),
+     description + "TIP1.beginInputTransaction(window) should succeed because there is no composition");
+  ok(TIP1.beginInputTransactionForTests(window),
+     description + "TIP1.beginInputTransactionForTests(window) should succeed because there is no composition");
+  ok(TIP2.beginInputTransaction(window, simpleCallback),
+     description + "TIP2.beginInputTransaction(window) should succeed because there is no composition");
+  ok(TIP2.beginInputTransactionForTests(window),
+     description + "TIP2.beginInputTransactionForTests(window) should succeed because there is no composition");
 
   // Start composition with TIP1, then, other TIPs cannot take ownership during a composition.
-  ok(TIP1.initForTests(window),
-     description + "TIP1.initForTests() should succeed because there is no composition");
+  ok(TIP1.beginInputTransactionForTests(window),
+     description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition");
   var composingStr = "foo";
   TIP1.setPendingCompositionString(composingStr);
   TIP1.appendClauseToPendingComposition(composingStr.length, TIP1.ATTR_RAW_CLAUSE);
   ok(TIP1.flushPendingComposition(),
      description + "TIP1.flushPendingComposition() should return true becuase it should be valid composition");
   is(input.value, composingStr,
      description + "The input element should have composing string");
 
   // Composing nsITextInputProcessor instance shouldn't allow initialize it again.
   try {
-    TIP1.init(window, simpleCallback);
+    TIP1.beginInputTransaction(window, simpleCallback);
     ok(false,
-       "TIP1.init(window) should cause throwing an exception because it's composing with different purpose");
+       "TIP1.beginInputTransaction(window) should cause throwing an exception because it's composing with different purpose");
   } catch (e) {
     ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
-       description + "TIP1.init(window) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing for tests");
+       description + "TIP1.beginInputTransaction(window) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing for tests");
   }
   try {
-    TIP1.initForTests(otherWindow);
+    TIP1.beginInputTransactionForTests(otherWindow);
     ok(false,
-       "TIP1.initForTests(otherWindow) should cause throwing an exception because it's composing on different window");
+       "TIP1.beginInputTransactionForTests(otherWindow) should cause throwing an exception because it's composing on different window");
   } catch (e) {
     ok(e.message.contains("NS_ERROR_ALREADY_INITIALIZED"),
-       description + "TIP1.init(otherWindow) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing on this window");
+       description + "TIP1.beginInputTransaction(otherWindow) should cause throwing an exception including NS_ERROR_ALREADY_INITIALIZED because it's composing on this window");
   }
-  ok(TIP1.initForTests(window),
-     description + "TIP1.initForTests(window) should succeed because TextEventDispatcher was initialized with same purpose");
-  ok(TIP1.initForTests(childWindow),
-     description + "TIP1.initForTests(childWindow) should succeed because TextEventDispatcher was initialized with same purpose and is shared by window and childWindow");
-  ok(!TIP2.init(window, simpleCallback),
-     description + "TIP2.init(window) should not succeed because there is composition synthesized by TIP1");
-  ok(!TIP2.initForTests(window),
-     description + "TIP2.initForTests(window) should not succeed because there is composition synthesized by TIP1");
-  ok(!TIP2.init(childWindow, simpleCallback),
-     description + "TIP2.init(childWindow) should not succeed because there is composition synthesized by TIP1");
-  ok(!TIP2.initForTests(childWindow),
-     description + "TIP2.initForTests(childWindow) should not succeed because there is composition synthesized by TIP1");
-  ok(TIP2.init(otherWindow, simpleCallback),
-     description + "TIP2.init(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
-  ok(TIP2.initForTests(otherWindow),
-     description + "TIP2.initForTests(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
+  ok(TIP1.beginInputTransactionForTests(window),
+     description + "TIP1.beginInputTransactionForTests(window) should succeed because TextEventDispatcher was initialized with same purpose");
+  ok(TIP1.beginInputTransactionForTests(childWindow),
+     description + "TIP1.beginInputTransactionForTests(childWindow) should succeed because TextEventDispatcher was initialized with same purpose and is shared by window and childWindow");
+  ok(!TIP2.beginInputTransaction(window, simpleCallback),
+     description + "TIP2.beginInputTransaction(window) should not succeed because there is composition synthesized by TIP1");
+  ok(!TIP2.beginInputTransactionForTests(window),
+     description + "TIP2.beginInputTransactionForTests(window) should not succeed because there is composition synthesized by TIP1");
+  ok(!TIP2.beginInputTransaction(childWindow, simpleCallback),
+     description + "TIP2.beginInputTransaction(childWindow) should not succeed because there is composition synthesized by TIP1");
+  ok(!TIP2.beginInputTransactionForTests(childWindow),
+     description + "TIP2.beginInputTransactionForTests(childWindow) should not succeed because there is composition synthesized by TIP1");
+  ok(TIP2.beginInputTransaction(otherWindow, simpleCallback),
+     description + "TIP2.beginInputTransaction(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
+  ok(TIP2.beginInputTransactionForTests(otherWindow),
+     description + "TIP2.beginInputTransactionForTests(otherWindow) should succeed because there is composition synthesized by TIP1 but it's in other window");
 
   // Let's confirm that the composing string is NOT committed by above tests.
   ok(TIP1.commitComposition(),
      description + "TIP1.commitString() should succeed because there should be composing string");
   is(input.value, composingStr,
      description + "TIP1.commitString() without specifying commit string should be committed with the last composing string");
 
-  ok(TIP1.init(window, simpleCallback),
-     description + "TIP1.init() should succeed because there is no composition #2");
-  ok(TIP1.initForTests(window),
-     description + "TIP1.initForTests() should succeed because there is no composition #2");
-  ok(TIP2.initForTests(window),
-     description + "TIP2.initForTests() should succeed because the composition was already committed #2");
+  ok(TIP1.beginInputTransaction(window, simpleCallback),
+     description + "TIP1.beginInputTransaction() should succeed because there is no composition #2");
+  ok(TIP1.beginInputTransactionForTests(window),
+     description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition #2");
+  ok(TIP2.beginInputTransactionForTests(window),
+     description + "TIP2.beginInputTransactionForTests() should succeed because the composition was already committed #2");
 
   // Let's check if startComposition() throws an exception after ownership is strolen.
   input.value = "";
   try {
     TIP1.startComposition();
     ok(false,
        description + "TIP1.startComposition() should cause throwing an exception because TIP2 took the ownership");
     TIP1.cancelComposition();
@@ -176,20 +176,20 @@ function runInitMethodTests()
     ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.startComposition() should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not have commit string");
   }
 
   // Let's check if flushPendingComposition() throws an exception after ownership is stolen.
-  ok(TIP1.initForTests(window),
-     description + "TIP1.initForTests() should succeed because there is no composition");
-  ok(TIP2.initForTests(window),
-     description + "TIP2.initForTests() should succeed because there is no composition");
+  ok(TIP1.beginInputTransactionForTests(window),
+     description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition");
+  ok(TIP2.beginInputTransactionForTests(window),
+     description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
   input.value = "";
   try {
     TIP1.setPendingCompositionString(composingStr);
     TIP1.appendClauseToPendingComposition(composingStr.length, TIP1.ATTR_RAW_CLAUSE);
     TIP1.flushPendingComposition()
     ok(false,
        description + "TIP1.flushPendingComposition() should cause throwing an exception because TIP2 took the ownership");
     TIP1.cancelComposition();
@@ -197,71 +197,71 @@ function runInitMethodTests()
     ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.flushPendingComposition() should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not have commit string");
   }
 
   // Let's check if commitComposition("bar") throws an exception after ownership is stolen.
-  ok(TIP1.initForTests(window),
-     description + "TIP1.initForTests() should succeed because there is no composition");
-  ok(TIP2.initForTests(window),
-     description + "TIP2.initForTests() should succeed because there is no composition");
+  ok(TIP1.beginInputTransactionForTests(window),
+     description + "TIP1.beginInputTransactionForTests() should succeed because there is no composition");
+  ok(TIP2.beginInputTransactionForTests(window),
+     description + "TIP2.beginInputTransactionForTests() should succeed because there is no composition");
   input.value = "";
   try {
     TIP1.commitComposition("bar");
     ok(false,
        description + "TIP1.commitComposition(\"bar\") should cause throwing an exception because TIP2 took the ownership");
   } catch (e) {
     ok(e.message.contains("NS_ERROR_NOT_INITIALIZED"),
        description + "TIP1.commitComposition(\"bar\") should cause throwing an exception including NS_ERROR_NOT_INITIALIZED");
   } finally {
     is(input.value, "",
        description + "The input element should not have commit string");
   }
 
-  // aCallback of nsITextInputProcessor.init() must not be omitted.
+  // aCallback of nsITextInputProcessor.beginInputTransaction() must not be omitted.
   try {
-    TIP1.init(window);
+    TIP1.beginInputTransaction(window);
     ok(false,
-       description + "TIP1.init(window) should be failed since aCallback is omitted");
+       description + "TIP1.beginInputTransaction(window) should be failed since aCallback is omitted");
   } catch (e) {
     ok(e.message.contains("Not enough arguments"),
-       description + "TIP1.init(window) should cause throwing an exception including \"Not enough arguments\" since aCallback is omitted");
+       description + "TIP1.beginInputTransaction(window) should cause throwing an exception including \"Not enough arguments\" since aCallback is omitted");
   }
 
-  // aCallback of nsITextInputProcessor.init() must not be undefined.
+  // aCallback of nsITextInputProcessor.beginInputTransaction() must not be undefined.
   try {
-    TIP1.init(window, undefined);
+    TIP1.beginInputTransaction(window, undefined);
     ok(false,
-       description + "TIP1.init(window, undefined) should be failed since aCallback is undefined");
+       description + "TIP1.beginInputTransaction(window, undefined) should be failed since aCallback is undefined");
   } catch (e) {
     ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
-       description + "TIP1.init(window, undefined) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is undefined");
+       description + "TIP1.beginInputTransaction(window, undefined) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is undefined");
   }
 
-  // aCallback of nsITextInputProcessor.init() must not be null.
+  // aCallback of nsITextInputProcessor.beginInputTransaction() must not be null.
   try {
-    TIP1.init(window, null);
+    TIP1.beginInputTransaction(window, null);
     ok(false,
-       description + "TIP1.init(window, null) should be failed since aCallback is null");
+       description + "TIP1.beginInputTransaction(window, null) should be failed since aCallback is null");
   } catch (e) {
     ok(e.message.contains("NS_ERROR_ILLEGAL_VALUE"),
-       description + "TIP1.init(window, null) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is null");
+       description + "TIP1.beginInputTransaction(window, null) should cause throwing an exception including NS_ERROR_ILLEGAL_VALUE since aCallback is null");
   }
 }
 
 function runReleaseTests()
 {
   var description = "runReleaseTests(): ";
 
   var TIP = createTIP();
-  ok(TIP.initForTests(window),
-     description + "TIP.initForTests() should succeed");
+  ok(TIP.beginInputTransactionForTests(window),
+     description + "TIP.beginInputTransactionForTests() should succeed");
 
   input.value = "";
   input.focus();
 
   TIP.setPendingCompositionString("foo");
   TIP.appendClauseToPendingComposition(3, TIP.ATTR_RAW_CLAUSE);
   TIP.setCaretInPendingComposition(3);
   TIP.flushPendingComposition();
@@ -272,27 +272,27 @@ function runReleaseTests()
   TIP = null;
   // Needs to run GC forcibly for testing this.
   SpecialPowers.gc();
 
   is(input.value, "",
      description + "the input should be empty because the composition should be canceled");
 
   TIP = createTIP();
-  ok(TIP.initForTests(window),
-     description + "TIP.initForTests() should succeed #2");
+  ok(TIP.beginInputTransactionForTests(window),
+     description + "TIP.beginInputTransactionForTests() should succeed #2");
 }
 
 function runCompositionTests()
 {
   var description = "runCompositionTests(): ";
 
   var TIP = createTIP();
-  ok(TIP.initForTests(window),
-     description + "TIP.initForTests() should succeed");
+  ok(TIP.beginInputTransactionForTests(window),
+     description + "TIP.beginInputTransactionForTests() should succeed");
 
   var events;
 
   function reset()
   {
     events = [];
   }
 
@@ -525,18 +525,18 @@ function runCompositionTests()
   window.removeEventListener("compositionend", handler, false);
 }
 
 function runErrorTests()
 {
   var description = "runErrorTests(): ";
 
   var TIP = createTIP();
-  ok(TIP.initForTests(window),
-     description + "TIP.initForTests() should succeed");
+  ok(TIP.beginInputTransactionForTests(window),
+     description + "TIP.beginInputTransactionForTests() should succeed");
 
   input.value = "";
   input.focus();
 
   // startComposition() should throw an exception if there is already a composition
   TIP.startComposition();
   try {
     TIP.startComposition();
@@ -669,18 +669,18 @@ function runErrorTests()
   }
 }
 
 function runCommitCompositionTests()
 {
   var description = "runCommitCompositionTests(): ";
 
   var TIP = createTIP();
-  ok(TIP.initForTests(window),
-     description + "TIP.initForTests() should succeed");
+  ok(TIP.beginInputTransactionForTests(window),
+     description + "TIP.beginInputTransactionForTests() should succeed");
 
   input.focus();
 
   // commitComposition() should commit the composition with the last data.
   input.value = "";
   TIP.setPendingCompositionString("foo");
   TIP.appendClauseToPendingComposition(3, TIP.ATTR_RAW_CLAUSE);
   TIP.setCaretInPendingComposition(3);
@@ -810,18 +810,18 @@ function runCommitCompositionTests()
      description + "doCommitWithNullCheck(undefined) should commit the composition with empty string");
 }
 
 function runUnloadTests1(aNextTest)
 {
   var description = "runUnloadTests1(): ";
 
   var TIP1 = createTIP();
-  ok(TIP1.initForTests(childWindow),
-     description + "TIP1.initForTests() should succeed");
+  ok(TIP1.beginInputTransactionForTests(childWindow),
+     description + "TIP1.beginInputTransactionForTests() should succeed");
 
   var oldSrc = iframe.src;
   var parentWindow = window;
 
   iframe.addEventListener("load", function (aEvent) {
     ok(true, description + "dummy page is loaded");
     iframe.removeEventListener("load", arguments.callee, true);
     childWindow = iframe.contentWindow;
@@ -833,18 +833,18 @@ function runUnloadTests1(aNextTest)
       childWindow = iframe.contentWindow;
       textareaInFrame = iframe.contentDocument.getElementById("textarea");
       setTimeout(aNextTest, 0);
     }, true);
 
     // The composition should be committed internally.  So, another TIP should
     // be able to steal the rights to using TextEventDispatcher.
     var TIP2 = createTIP();
-    ok(TIP2.initForTests(parentWindow),
-       description + "TIP2.initForTests() should succeed");
+    ok(TIP2.beginInputTransactionForTests(parentWindow),
+       description + "TIP2.beginInputTransactionForTests() should succeed");
 
     input.focus();
     input.value = "";
 
     TIP2.setPendingCompositionString("foo");
     TIP2.appendClauseToPendingComposition(3, TIP2.ATTR_RAW_CLAUSE);
     TIP2.setCaretInPendingComposition(3);
     TIP2.flushPendingComposition();
@@ -872,18 +872,18 @@ function runUnloadTests1(aNextTest)
   iframe.src = "data:text/html,<body>dummy page</body>";
 }
 
 function runUnloadTests2(aNextTest)
 {
   var description = "runUnloadTests2(): ";
 
   var TIP = createTIP();
-  ok(TIP.initForTests(childWindow),
-     description + "TIP.initForTests() should succeed");
+  ok(TIP.beginInputTransactionForTests(childWindow),
+     description + "TIP.beginInputTransactionForTests() should succeed");
 
   var oldSrc = iframe.src;
   var parentWindow = window;
 
   iframe.addEventListener("load", function (aEvent) {
     ok(true, description + "dummy page is loaded");
     iframe.removeEventListener("load", arguments.callee, true);
     childWindow = iframe.contentWindow;
@@ -962,19 +962,19 @@ function runCallbackTests(aForTests)
     }
     for (var i = aExpectedCount; i < notifications.length; i++) {
       ok(false,
          description + "Unexpected notification: " + notifications[i].type);
     }
   }
 
   if (aForTests) {
-    TIP.initForTests(window, callback);
+    TIP.beginInputTransactionForTests(window, callback);
   } else {
-    TIP.init(window, callback);
+    TIP.beginInputTransaction(window, callback);
   }
 
   notifications = [];
   input.focus();
   is(notifications.length, 1,
      description + "input.focus() should cause a notification");
   is(notifications[0].type, "notify-focus",
      description + "input.focus() should cause \"notify-focus\"");
@@ -998,32 +998,32 @@ function runCallbackTests(aForTests)
      description + "synthesizeMouseAtCenter(input, {}) during composition should cause a notification");
   is(notifications[0].type, "request-to-commit",
      description + "synthesizeMouseAtCenter(input, {}) during composition should cause \"request-to-commit\"");
   dumpUnexpectedNotifications(1);
 
   notifications = [];
   var TIP2 = createTIP();
   if (aForTests) {
-    TIP2.initForTests(window, callback);
+    TIP2.beginInputTransactionForTests(window, callback);
   } else {
-    TIP2.init(window, callback);
+    TIP2.beginInputTransaction(window, callback);
   }
   is(notifications.length, 1,
      description + "Initializing another TIP should cause a notification");
-  is(notifications[0].type, "notify-detached",
+  is(notifications[0].type, "notify-end-input-transaction",
      description + "Initializing another TIP should cause \"notify-detached\"");
   dumpUnexpectedNotifications(1);
 }
 
 function runTests()
 {
   textareaInFrame = iframe.contentDocument.getElementById("textarea");
 
-  runInitMethodTests();
+  runBeginInputTransactionMethodTests();
   runReleaseTests();
   runCompositionTests();
   runErrorTests();
   runCommitCompositionTests();
   runCallbackTests(false);
   runCallbackTests(true);
   runUnloadTests1(function () {
     runUnloadTests2(function () {
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -633,16 +633,18 @@ BrowserElementChild.prototype = {
 
     // If we select something and selection range is visible, we cache current
     // event's target to selectionStateChangedTarget.
     // And dispatch the next SelectionStateChagne event if target is matched, so
     // that the parent side can hide the text dialog.
     // We clear selectionStateChangedTarget if selection carets are invisible.
     if (e.visible && !isCollapsed) {
       this._selectionStateChangedTarget = e.target;
+    } else if (canPaste && isCollapsed) {
+      this._selectionStateChangedTarget = e.target;
     } else {
       this._selectionStateChangedTarget = null;
     }
 
     let zoomFactor = content.screen.width / content.innerWidth;
 
     let detail = {
       rect: {
@@ -1162,16 +1164,17 @@ BrowserElementChild.prototype = {
   },
 
   _recvZoom: function(data) {
     docShell.contentViewer.fullZoom = data.json.zoom;
   },
 
   _recvDoCommand: function(data) {
     if (this._isCommandEnabled(data.json.command)) {
+      this._selectionStateChangedTarget = null;
       docShell.doCommand(COMMAND_MAP[data.json.command]);
     }
   },
 
   _recvSetInputMethodActive: function(data) {
     let msgData = { id: data.json.id };
     if (!this._isContentWindowCreated) {
       if (data.json.args.isActive) {
--- a/dom/events/ContentEventHandler.cpp
+++ b/dom/events/ContentEventHandler.cpp
@@ -246,19 +246,18 @@ static uint32_t CountNewlinesInXPLength(
 {
   NS_ASSERTION(aContent->IsNodeOfType(nsINode::eTEXT),
                "aContent is not a text node!");
   const nsTextFragment* text = aContent->GetText();
   if (!text) {
     return 0;
   }
   // For automated tests, we should abort on debug build.
-  NS_ABORT_IF_FALSE(
-    (aXPLength == UINT32_MAX || aXPLength <= text->GetLength()),
-    "aXPLength is out-of-bounds");
+  MOZ_ASSERT(aXPLength == UINT32_MAX || aXPLength <= text->GetLength(),
+             "aXPLength is out-of-bounds");
   const uint32_t length = std::min(aXPLength, text->GetLength());
   uint32_t newlines = 0;
   for (uint32_t i = 0; i < length; ++i) {
     if (text->CharAt(i) == '\n') {
       ++newlines;
     }
   }
   return newlines;
@@ -278,17 +277,17 @@ static uint32_t CountNewlinesInNativeLen
     (aNativeLength == UINT32_MAX || aNativeLength <= text->GetLength() * 2),
     "aNativeLength is unexpected value");
   const uint32_t xpLength = text->GetLength();
   uint32_t newlines = 0;
   for (uint32_t i = 0, nativeOffset = 0;
        i < xpLength && nativeOffset < aNativeLength;
        ++i, ++nativeOffset) {
     // For automated tests, we should abort on debug build.
-    NS_ABORT_IF_FALSE(i < text->GetLength(), "i is out-of-bounds");
+    MOZ_ASSERT(i < text->GetLength(), "i is out-of-bounds");
     if (text->CharAt(i) == '\n') {
       ++newlines;
       ++nativeOffset;
     }
   }
   return newlines;
 }
 #endif
@@ -938,18 +937,23 @@ ContentEventHandler::OnQueryTextRect(Wid
   // get the starting frame rect
   nsRect rect(nsPoint(0, 0), firstFrame->GetRect().Size());
   rv = ConvertToRootViewRelativeOffset(firstFrame, rect);
   NS_ENSURE_SUCCESS(rv, rv);
   nsRect frameRect = rect;
   nsPoint ptOffset;
   firstFrame->GetPointFromOffset(nodeOffset, &ptOffset);
   // minus 1 to avoid creating an empty rect
-  rect.x += ptOffset.x - 1;
-  rect.width -= ptOffset.x - 1;
+  if (firstFrame->GetWritingMode().IsVertical()) {
+    rect.y += ptOffset.y - 1;
+    rect.height -= ptOffset.y - 1;
+  } else {
+    rect.x += ptOffset.x - 1;
+    rect.width -= ptOffset.x - 1;
+  }
 
   // get the ending frame
   nodeOffset = range->EndOffset();
   node = AdjustTextRectNode(range->GetEndParent(), nodeOffset);
   nsIFrame* lastFrame = nullptr;
   rv = GetFrameForTextRect(node, nodeOffset, range->Collapsed(), &lastFrame);
   NS_ENSURE_SUCCESS(rv, rv);
 
@@ -980,25 +984,30 @@ ContentEventHandler::OnQueryTextRect(Wid
       // not last frame, so just add rect to previous result
       rect.UnionRect(rect, frameRect);
     }
   }
 
   // get the ending frame rect
   lastFrame->GetPointFromOffset(nodeOffset, &ptOffset);
   // minus 1 to avoid creating an empty rect
-  frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1;
+  if (lastFrame->GetWritingMode().IsVertical()) {
+    frameRect.height -= lastFrame->GetRect().height - ptOffset.y - 1;
+  } else {
+    frameRect.width -= lastFrame->GetRect().width - ptOffset.x - 1;
+  }
 
   if (firstFrame == lastFrame) {
     rect.IntersectRect(rect, frameRect);
   } else {
     rect.UnionRect(rect, frameRect);
   }
   aEvent->mReply.mRect = LayoutDevicePixel::FromUntyped(
       rect.ToOutsidePixels(mPresContext->AppUnitsPerDevPixel()));
+  aEvent->mReply.mWritingMode = lastFrame->GetWritingMode();
   aEvent->mSucceeded = true;
   return NS_OK;
 }
 
 nsresult
 ContentEventHandler::OnQueryEditorRect(WidgetQueryContentEvent* aEvent)
 {
   nsresult rv = Init(aEvent);
--- a/dom/html/HTMLImageElement.cpp
+++ b/dom/html/HTMLImageElement.cpp
@@ -396,18 +396,18 @@ HTMLImageElement::BeforeSetAttr(int32_t 
 nsresult
 HTMLImageElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None && mForm &&
       (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
       aValue && !aValue->IsEmptyString()) {
     // add the image to the hashtable as needed
-    NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom,
-      "Expected atom value for name/id");
+    MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
+               "Expected atom value for name/id");
     mForm->AddImageElementToTable(this,
       nsDependentAtomString(aValue->GetAtomValue()));
   }
 
   // Handle src/srcset/crossorigin updates. If aNotify is false, we are coming
   // from the parser or some such place; we'll get bound after all the
   // attributes have been set, so we'll do the image load from BindToTree.
 
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -270,17 +270,17 @@ class HTMLMediaElement::MediaLoadListene
   NS_DECL_NSIOBSERVER
   NS_DECL_NSIINTERFACEREQUESTOR
 
 public:
   explicit MediaLoadListener(HTMLMediaElement* aElement)
     : mElement(aElement),
       mLoadID(aElement->GetCurrentLoadID())
   {
-    NS_ABORT_IF_FALSE(mElement, "Must pass an element to call back");
+    MOZ_ASSERT(mElement, "Must pass an element to call back");
   }
 
 private:
   nsRefPtr<HTMLMediaElement> mElement;
   nsCOMPtr<nsIStreamListener> mNextListener;
   uint32_t mLoadID;
 };
 
@@ -2078,17 +2078,16 @@ HTMLMediaElement::HTMLMediaElement(alrea
     mCORSMode(CORS_NONE),
     mHasAudio(false),
     mHasVideo(false),
     mIsEncrypted(false),
     mDownloadSuspendedByCache(false),
     mAudioChannelFaded(false),
     mPlayingThroughTheAudioChannel(false),
     mDisableVideo(false),
-    mWaitingFor(MediaWaitingFor::None),
     mElementInTreeState(ELEMENT_NOT_INTREE)
 {
 #ifdef PR_LOGGING
   if (!gMediaElementLog) {
     gMediaElementLog = PR_NewLogModule("nsMediaElement");
   }
   if (!gMediaElementEventsLog) {
     gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
@@ -4324,22 +4323,16 @@ HTMLMediaElement::SetMediaKeys(mozilla::
     if (mDecoder) {
       mDecoder->SetCDMProxy(mMediaKeys->GetCDMProxy());
     }
   }
   promise->MaybeResolve(JS::UndefinedHandleValue);
   return promise.forget();
 }
 
-MediaWaitingFor
-HTMLMediaElement::WaitingFor() const
-{
-  return mWaitingFor;
-}
-
 EventHandlerNonNull*
 HTMLMediaElement::GetOnencrypted()
 {
   EventListenerManager *elm = GetExistingListenerManager();
   return elm ? elm->GetEventHandler(nsGkAtoms::onencrypted, EmptyString())
               : nullptr;
 }
 
--- a/dom/html/HTMLMediaElement.h
+++ b/dom/html/HTMLMediaElement.h
@@ -20,23 +20,16 @@
 #include "mozilla/dom/Promise.h"
 #include "mozilla/dom/TextTrackManager.h"
 #include "MediaDecoder.h"
 #ifdef MOZ_EME
 #include "mozilla/dom/MediaKeys.h"
 #endif
 #include "nsGkAtoms.h"
 
-// Something on Linux #defines None, which is an entry in the
-// MediaWaitingFor enum, so undef it here before including the binfing,
-// so that the build doesn't fail...
-#ifdef None
-#undef None
-#endif
-
 // X.h on Linux #defines CurrentTime as 0L, so we have to #undef it here.
 #ifdef CurrentTime
 #undef CurrentTime
 #endif
 
 #include "mozilla/dom/HTMLMediaElementBinding.h"
 
 // Define to output information on decoding and painting framerate
@@ -547,18 +540,16 @@ public:
   // XPCOM MozPreservesPitch() is OK
 
 #ifdef MOZ_EME
   MediaKeys* GetMediaKeys() const;
 
   already_AddRefed<Promise> SetMediaKeys(MediaKeys* mediaKeys,
                                          ErrorResult& aRv);
 
-  MediaWaitingFor WaitingFor() const;
-
   mozilla::dom::EventHandlerNonNull* GetOnencrypted();
   void SetOnencrypted(mozilla::dom::EventHandlerNonNull* listener);
 
   void DispatchEncrypted(const nsTArray<uint8_t>& aInitData,
                          const nsAString& aInitDataType) MOZ_OVERRIDE;
 
 
   bool IsEventAttributeName(nsIAtom* aName) MOZ_OVERRIDE;
@@ -1332,18 +1323,16 @@ protected:
   nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
 
   nsRefPtr<TextTrackManager> mTextTrackManager;
 
   nsRefPtr<AudioTrackList> mAudioTrackList;
 
   nsRefPtr<VideoTrackList> mVideoTrackList;
 
-  MediaWaitingFor mWaitingFor;
-
   enum ElementInTreeState {
     // The MediaElement is not in the DOM tree now.
     ELEMENT_NOT_INTREE,
     // The MediaElement is in the DOM tree now.
     ELEMENT_INTREE,
     // The MediaElement is not in the DOM tree now but had been binded to the
     // tree before.
     ELEMENT_NOT_INTREE_HAD_INTREE
--- a/dom/html/nsGenericHTMLElement.cpp
+++ b/dom/html/nsGenericHTMLElement.cpp
@@ -707,18 +707,18 @@ nsGenericHTMLElement::GetHrefURIForAncho
 }
 
 nsresult
 nsGenericHTMLElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
                                    const nsAttrValue* aValue, bool aNotify)
 {
   if (aNamespaceID == kNameSpaceID_None) {
     if (IsEventAttributeName(aName) && aValue) {
-      NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
-        "Expected string value for script body");
+      MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
+                 "Expected string value for script body");
       nsresult rv = SetEventHandler(aName, aValue->GetStringValue());
       NS_ENSURE_SUCCESS(rv, rv);
     }
     else if (aNotify && aName == nsGkAtoms::spellcheck) {
       SyncEditorsOnSubtree(this);
     }
     else if (aName == nsGkAtoms::dir) {
       Directionality dir = eDir_LTR;
@@ -2147,18 +2147,18 @@ nsresult
 nsGenericHTMLFormElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                        const nsAttrValue* aValue, bool aNotify)
 {
   if (aNameSpaceID == kNameSpaceID_None) {
     // add the control to the hashtable as needed
 
     if (mForm && (aName == nsGkAtoms::name || aName == nsGkAtoms::id) &&
         aValue && !aValue->IsEmptyString()) {
-      NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eAtom,
-        "Expected atom value for name/id");
+      MOZ_ASSERT(aValue->Type() == nsAttrValue::eAtom,
+                 "Expected atom value for name/id");
       mForm->AddElementToTable(this,
         nsDependentAtomString(aValue->GetAtomValue()));
     }
 
     if (mForm && aName == nsGkAtoms::type) {
       nsAutoString tmp;
 
       GetAttr(kNameSpaceID_None, nsGkAtoms::name, tmp);
--- a/dom/html/nsHTMLDocument.cpp
+++ b/dom/html/nsHTMLDocument.cpp
@@ -1894,18 +1894,18 @@ nsHTMLDocument::WriteCommon(JSContext *c
               1, getter_AddRefs(ignored));
 
     // If Open() fails, or if it didn't create a parser (as it won't
     // if the user chose to not discard the current document through
     // onbeforeunload), don't write anything.
     if (NS_FAILED(rv) || !mParser) {
       return rv;
     }
-    NS_ABORT_IF_FALSE(!JS_IsExceptionPending(cx),
-                      "Open() succeeded but JS exception is pending");
+    MOZ_ASSERT(!JS_IsExceptionPending(cx),
+               "Open() succeeded but JS exception is pending");
   }
 
   static NS_NAMED_LITERAL_STRING(new_line, "\n");
 
   // Save the data in cache if the write isn't from within the doc
   if (mWyciwygChannel && !key) {
     if (!aText.IsEmpty()) {
       mWyciwygChannel->WriteToCacheEntry(aText);
@@ -2768,17 +2768,17 @@ nsHTMLDocument::EditingStateChanged()
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIEditor> existingEditor;
   editSession->GetEditorForWindow(window, getter_AddRefs(existingEditor));
   if (existingEditor) {
     // We might already have an editor if it was set up for mail, let's see
     // if this is actually the case.
     nsCOMPtr<nsIHTMLEditor> htmlEditor = do_QueryInterface(existingEditor);
-    NS_ABORT_IF_FALSE(htmlEditor, "If we have an editor, it must be an HTML editor");
+    MOZ_ASSERT(htmlEditor, "If we have an editor, it must be an HTML editor");
     uint32_t flags = 0;
     existingEditor->GetFlags(&flags);
     if (flags & nsIPlaintextEditor::eEditorMailMask) {
       // We already have a mail editor, then we should not attempt to create
       // another one.
       return NS_OK;
     }
   }
--- a/dom/html/nsTextEditorState.cpp
+++ b/dom/html/nsTextEditorState.cpp
@@ -2102,17 +2102,17 @@ nsTextEditorState::UpdatePlaceholderVisi
   if (mBoundFrame && aNotify) {
     mBoundFrame->InvalidateFrame();
   }
 }
 
 void
 nsTextEditorState::HideSelectionIfBlurred()
 {
-  NS_ABORT_IF_FALSE(mSelCon, "Should have a selection controller if we have a frame!");
+  MOZ_ASSERT(mSelCon, "Should have a selection controller if we have a frame!");
   nsCOMPtr<nsIContent> content = do_QueryInterface(mTextCtrlElement);
   if (!nsContentUtils::IsFocusedContent(content)) {
     mSelCon->SetDisplaySelection(nsISelectionController::SELECTION_HIDDEN);
   }
 }
 
 NS_IMPL_ISUPPORTS(nsAnonDivObserver, nsIMutationObserver)
 
--- a/dom/inputmethod/forms.js
+++ b/dom/inputmethod/forms.js
@@ -1238,17 +1238,18 @@ let CompositionManager =  {
 
   _prepareTextInputProcessor: function cm_prepareTextInputProcessor(aWindow)
   {
     if (!this._textInputProcessor) {
       this._textInputProcessor =
         Cc["@mozilla.org/text-input-processor;1"].
           createInstance(Ci.nsITextInputProcessor);
     }
-    return this._textInputProcessor.init(aWindow, this._callback);
+    return this._textInputProcessor.beginInputTransaction(aWindow,
+                                                          this._callback);
   },
 
   setComposition: function cm_setComposition(element, text, cursor, clauses) {
     // Check parameters.
     if (!element) {
       return;
     }
     let len = text.length;
--- a/dom/interfaces/base/nsITextInputProcessor.idl
+++ b/dom/interfaces/base/nsITextInputProcessor.idl
@@ -5,30 +5,31 @@
 
 #include "nsISupports.idl"
 
 interface nsIDOMWindow;
 interface nsITextInputProcessorCallback;
 
 /**
  * An nsITextInputProcessor instance is associated with a top level widget which
- * handles native IME.  It's associated by calling init() or initForTests().
- * While an instance has composition, nobody can steal the rights to make
- * composition on the top level widget.  In other words, if another instance is
- * composing on a top level widget, either init() or initForTests() returns
- * false (i.e., not throws an exception).
+ * handles native IME.  It's associated by calling beginInputTransaction() or
+ * beginInputTransactionForTests().  While an instance has composition, nobody
+ * can steal the rights to make composition on the top level widget.  In other
+ * words, if another instance is composing on a top level widget, either
+ * beginInputTransaction() or beginInputTransactionForTests() returns false
+ * (i.e., not throws an exception).
  *
  * NOTE: See nsITextInputProcessorCallback.idl for examples of |callback| in
  *       following examples,
  *
  * Example #1 JS-IME can start composition like this:
  *
  *   var TIP = Components.classes["@mozilla.org/text-input-processor;1"].
  *               createInstance(Components.interfaces.nsITextInputProcessor);
- *   if (!TIP.init(window, callback)) {
+ *   if (!TIP.beginInputTransaction(window, callback)) {
  *     return; // You failed to get the rights to make composition
  *   }
  *   // Set new composition string first
  *   TIP.setPendingCompositionString("some-words-are-inputted");
  *   // Set clause information.
  *   TIP.appendClauseToPendingComposition(23, TIP.ATTR_RAW_CLAUSE);
  *   // Set caret position, this is optional.
  *   TIP.setCaretInPendingComposition(23);
@@ -79,66 +80,68 @@ interface nsITextInputProcessorCallback;
  *   TIP.appendClauseToPendingComposition(27, TIP.ATTR_RAW_CLAUSE);
  *   TIP.flushPendingComposition();
  *   // This is useful when user doesn't want to commit the composition.
  *   // FYI: This is same as TIP.commitComposition("") for now.
  *   TIP.cancelComposition();
  *
  * Example #6 JS-IME can insert text only with commitComposition():
  *
- *   if (!TIP.init(window, callback)) {
+ *   if (!TIP.beginInputTransaction(window, callback)) {
  *     return; // You failed to get the rights to make composition
  *   }
  *   TIP.commitComposition("Some words");
  *
  * Example #7 JS-IME can start composition explicitly:
  *
- *   if (!TIP.init(window, callback)) {
+ *   if (!TIP.beginInputTransaction(window, callback)) {
  *     return; // You failed to get the rights to make composition
  *   }
  *   // If JS-IME don't want to show composing string in the focused editor,
  *   // JS-IME can dispatch only compositionstart event with this.
  *   if (!TIP.startComposition()) {
  *     // Failed to start composition.
  *     return;
  *   }
  *   // And when user selects a result from UI of JS-IME, commit with it.
  *   TIP.commitComposition("selected-words");
  */
 
-[scriptable, builtinclass, uuid(8c20753c-8339-4e9c-86c5-ae30f1b456c3)]
+[scriptable, builtinclass, uuid(512f1efe-9e0f-48a4-b423-3936ef948f34)]
 interface nsITextInputProcessor : nsISupports
 {
   /**
-   * When you create an instance, you must call init() first except when you
-   * created the instance for automated tests.
+   * When you create an instance, you must call beginInputTransaction() first
+   * except when you created the instance for automated tests.
    *
    * @param aWindow         A DOM window.  The instance will look for a top
    *                        level widget from this.
    * @param aCallback       Callback interface which handles requests to
    *                        IME and notifications to IME.  This must not be
    *                        null.
    * @return                If somebody uses internal text input service for a
    *                        composition, this returns false.  Otherwise, returns
    *                        true.  I.e., only your TIP can create composition
    *                        when this returns true.  If this returns false,
    *                        your TIP should wait next chance.
    */
-  boolean init(in nsIDOMWindow aWindow,
-               in nsITextInputProcessorCallback aCallback);
+  boolean beginInputTransaction(in nsIDOMWindow aWindow,
+                                in nsITextInputProcessorCallback aCallback);
 
   /**
    * When you create an instance for automated test, you must call
-   * initForTest(), first.  See init() for more detail of this.
+   * beginInputTransaction(), first.  See beginInputTransaction() for more
+   * detail of this.
    * Note that aCallback can be null.  If it's null, nsITextInputProcessor
    * implementation will handle them automatically.
    */
   [optional_argc] boolean
-    initForTests(in nsIDOMWindow aWindow,
-                 [optional] in nsITextInputProcessorCallback aCallback);
+    beginInputTransactionForTests(
+      in nsIDOMWindow aWindow,
+      [optional] in nsITextInputProcessorCallback aCallback);
 
   /**
    * startComposition() dispatches compositionstart event explicitly.
    * IME does NOT need to call this typically since compositionstart event
    * is automatically dispatched by sendPendingComposition() if
    * compositionstart event hasn't been dispatched yet.  If this is called
    * when compositionstart has already been dispatched, this throws an
    * exception.
--- a/dom/interfaces/base/nsITextInputProcessorCallback.idl
+++ b/dom/interfaces/base/nsITextInputProcessorCallback.idl
@@ -25,19 +25,21 @@ interface nsITextInputProcessorNotificat
    *   notification.
    *
    * "request-to-cancel" (required to be handled)
    *   This is requested when Gecko believes that active composition should be
    *   canceled.  I.e., composition should be committed with empty string.
    *   nsITextInputProcessorCallback::onNotify() has to handle this
    *   notification.
    *
-   * "notify-detached" (optional)
+   * "notify-end-input-transaction" (optional)
    *   This is notified when the callback is detached from
-   *   nsITextInputProcessor.
+   *   nsITextInputProcessor.  I.e., the TextInputProcessor lost the rights
+   *   to input text and needs to call .beginInputTransaction() before next
+   *   input.
    *
    * "notify-focus" (optional)
    *   This is notified when an editable editor gets focus and Gecko starts
    *   to observe changes in the content. E.g., selection changes.
    *   IME shouldn't change DOM tree, focus nor something when this is notified.
    *
    * "notify-blur" (optional)
    *   This is notified when an editable editor loses focus and Gecko stops
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1959,18 +1959,18 @@ ContentChild::RecvUpdateDictionaryList(I
 bool
 ContentChild::RecvAddPermission(const IPC::Permission& permission)
 {
 #if MOZ_PERMISSIONS
     nsCOMPtr<nsIPermissionManager> permissionManagerIface =
         services::GetPermissionManager();
     nsPermissionManager* permissionManager =
         static_cast<nsPermissionManager*>(permissionManagerIface.get());
-    NS_ABORT_IF_FALSE(permissionManager,
-                     "We have no permissionManager in the Content process !");
+    MOZ_ASSERT(permissionManager,
+               "We have no permissionManager in the Content process !");
 
     nsCOMPtr<nsIURI> uri;
     NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + nsCString(permission.host));
     NS_ENSURE_TRUE(uri, true);
 
     nsIScriptSecurityManager* secMan = nsContentUtils::GetSecurityManager();
     MOZ_ASSERT(secMan);
 
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -2420,22 +2420,22 @@ ContentParent::RecvReadFontList(Infallib
 bool
 ContentParent::RecvReadPermissions(InfallibleTArray<IPC::Permission>* aPermissions)
 {
 #ifdef MOZ_PERMISSIONS
     nsCOMPtr<nsIPermissionManager> permissionManagerIface =
         services::GetPermissionManager();
     nsPermissionManager* permissionManager =
         static_cast<nsPermissionManager*>(permissionManagerIface.get());
-    NS_ABORT_IF_FALSE(permissionManager,
-                 "We have no permissionManager in the Chrome process !");
+    MOZ_ASSERT(permissionManager,
+               "We have no permissionManager in the Chrome process !");
 
     nsCOMPtr<nsISimpleEnumerator> enumerator;
     DebugOnly<nsresult> rv = permissionManager->GetEnumerator(getter_AddRefs(enumerator));
-    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "Could not get enumerator!");
+    MOZ_ASSERT(NS_SUCCEEDED(rv), "Could not get enumerator!");
     while(1) {
         bool hasMore;
         enumerator->HasMoreElements(&hasMore);
         if (!hasMore)
             break;
 
         nsCOMPtr<nsISupports> supp;
         enumerator->GetNext(getter_AddRefs(supp));
@@ -4420,18 +4420,18 @@ ContentParent::RecvRemoveIdleObserver(co
 }
 
 bool
 ContentParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
 {
 #ifndef MOZ_X11
     NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
 #else
-    NS_ABORT_IF_FALSE(0 > mChildXSocketFdDup.get(),
-                      "Already backed up X resources??");
+    MOZ_ASSERT(0 > mChildXSocketFdDup.get(),
+               "Already backed up X resources??");
     mChildXSocketFdDup.forget();
     if (aXSocketFd.IsValid()) {
         mChildXSocketFdDup.reset(aXSocketFd.PlatformHandle());
     }
 #endif
     return true;
 }
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -3174,18 +3174,18 @@ TabChild::InitRenderingState(const Scrol
       // This results in |remoteFrame| being deleted.
       PRenderFrameChild::Send__delete__(remoteFrame);
       return false;
     }
 
     ShadowLayerForwarder* lf =
         mWidget->GetLayerManager(shadowManager, mTextureFactoryIdentifier.mParentBackend)
                ->AsShadowForwarder();
-    NS_ABORT_IF_FALSE(lf && lf->HasShadowManager(),
-                      "PuppetWidget should have shadow manager");
+    MOZ_ASSERT(lf && lf->HasShadowManager(),
+               "PuppetWidget should have shadow manager");
     lf->IdentifyTextureHost(mTextureFactoryIdentifier);
     ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier);
 
     mRemoteFrame = remoteFrame;
     if (aLayersId != 0) {
       if (!sTabChildren) {
         sTabChildren = new TabChildMap;
       }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1922,16 +1922,17 @@ TabParent::HandleQueryContentEvent(Widge
       aEvent.mReply.mRect.SetEmpty();
       for (uint32_t i = baseOffset; i < endOffset; i++) {
         aEvent.mReply.mRect =
           aEvent.mReply.mRect.Union(mIMECompositionRects[i]);
       }
       aEvent.mReply.mOffset = aEvent.mInput.mOffset;
       aEvent.mReply.mRect =
         aEvent.mReply.mRect - LayoutDevicePixel::FromUntyped(GetChildProcessOffset());
+      aEvent.mReply.mWritingMode = mWritingMode;
       aEvent.mSucceeded = true;
     }
     break;
   case NS_QUERY_CARET_RECT:
     {
       if (aEvent.mInput.mOffset != mIMECaretOffset) {
         break;
       }
@@ -2177,29 +2178,29 @@ TabParent::RecvIsParentWindowMainWidgetV
   return NS_SUCCEEDED(rv);
 }
 
 bool
 TabParent::RecvGetDPI(float* aValue)
 {
   TryCacheDPIAndScale();
 
-  NS_ABORT_IF_FALSE(mDPI > 0,
-                    "Must not ask for DPI before OwnerElement is received!");
+  MOZ_ASSERT(mDPI > 0,
+             "Must not ask for DPI before OwnerElement is received!");
   *aValue = mDPI;
   return true;
 }
 
 bool
 TabParent::RecvGetDefaultScale(double* aValue)
 {
   TryCacheDPIAndScale();
 
-  NS_ABORT_IF_FALSE(mDefaultScale.scale > 0,
-                    "Must not ask for scale before OwnerElement is received!");
+  MOZ_ASSERT(mDefaultScale.scale > 0,
+             "Must not ask for scale before OwnerElement is received!");
   *aValue = mDefaultScale.scale;
   return true;
 }
 
 bool
 TabParent::RecvGetWidgetNativeData(WindowsHandle* aValue)
 {
   *aValue = 0;
--- a/dom/json/nsJSON.cpp
+++ b/dom/json/nsJSON.cpp
@@ -531,17 +531,17 @@ nsJSONListener::OnStopRequest(nsIRequest
     rv = ProcessBytes(nullptr, 0);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   JS::Rooted<JS::Value> reviver(mCx, JS::NullValue()), value(mCx);
 
   JS::ConstTwoByteChars chars(reinterpret_cast<const char16_t*>(mBufferedChars.Elements()),
                               mBufferedChars.Length());
-  bool ok = JS_ParseJSONWithReviver(mCx, chars.get(),
+  bool ok = JS_ParseJSONWithReviver(mCx, chars.start().get(),
                                       uint32_t(mBufferedChars.Length()),
                                       reviver, &value);
 
   *mRootVal = value;
   mBufferedChars.TruncateLength(0);
   return ok ? NS_OK : NS_ERROR_FAILURE;
 }
 
@@ -640,17 +640,17 @@ nsJSONListener::ConsumeConverted(const c
   rv = mDecoder->GetMaxLength(aBuffer, srcLen, &unicharLength);
   NS_ENSURE_SUCCESS(rv, rv);
 
   char16_t* endelems = mBufferedChars.AppendElements(unicharLength);
   int32_t preLength = unicharLength;
   rv = mDecoder->Convert(aBuffer, &srcLen, endelems, &unicharLength);
   if (NS_FAILED(rv))
     return rv;
-  NS_ABORT_IF_FALSE(preLength >= unicharLength, "GetMaxLength lied");
+  MOZ_ASSERT(preLength >= unicharLength, "GetMaxLength lied");
   if (preLength > unicharLength)
     mBufferedChars.TruncateLength(mBufferedChars.Length() - (preLength - unicharLength));
   return NS_OK;
 }
 
 nsresult
 nsJSONListener::Consume(const char16_t* aBuffer, uint32_t aByteLength)
 {
--- a/dom/media/AudioStream.cpp
+++ b/dom/media/AudioStream.cpp
@@ -366,17 +366,17 @@ AudioStream::Init(int32_t aNumChannels, 
   mBytesPerFrame = sizeof(AudioDataValue) * mOutChannels;
 
   mAudioClock.Init();
 
   // Size mBuffer for one second of audio.  This value is arbitrary, and was
   // selected based on the observed behaviour of the existing AudioStream
   // implementations.
   uint32_t bufferLimit = FramesToBytes(aRate);
-  NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
+  MOZ_ASSERT(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
   mBuffer.SetCapacity(bufferLimit);
 
   if (aLatencyRequest == LowLatency) {
     // Don't block this thread to initialize a cubeb stream.
     // When this is done, it will start callbacks from Cubeb.  Those will
     // cause us to move from INITIALIZED to RUNNING.  Until then, we
     // can't access any cubeb functions.
     // Use a RefPtr to avoid leaks if Dispatch fails
@@ -627,18 +627,18 @@ AudioStream::Write(const AudioDataValue*
       timeMs = 0;
     }
     struct Inserts insert = { timeMs, aFrames};
     mInserts.AppendElement(insert);
   }
 
   while (bytesToCopy > 0) {
     uint32_t available = std::min(bytesToCopy, mBuffer.Available());
-    NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0,
-        "Must copy complete frames.");
+    MOZ_ASSERT(available % mBytesPerFrame == 0,
+               "Must copy complete frames.");
 
     mBuffer.AppendElements(src, available);
     src += available;
     bytesToCopy -= available;
 
     if (bytesToCopy > 0) {
       // Careful - the CubebInit thread may not have gotten to STARTED yet
       if ((mState == INITIALIZED || mState == STARTED) && mLatencyRequest == LowLatency) {
@@ -673,24 +673,24 @@ AudioStream::Write(const AudioDataValue*
   mWritten += aFrames;
   return NS_OK;
 }
 
 uint32_t
 AudioStream::Available()
 {
   MonitorAutoLock mon(mMonitor);
-  NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
+  MOZ_ASSERT(mBuffer.Length() % mBytesPerFrame == 0, "Buffer invariant violated.");
   return BytesToFrames(mBuffer.Available());
 }
 
 void
 AudioStream::SetVolume(double aVolume)
 {
-  NS_ABORT_IF_FALSE(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
+  MOZ_ASSERT(aVolume >= 0.0 && aVolume <= 1.0, "Invalid volume");
 
   if (cubeb_stream_set_volume(mCubebStream.get(), aVolume * CubebUtils::GetVolumeScale()) != CUBEB_OK) {
     NS_WARNING("Could not change volume on cubeb stream.");
   }
 }
 
 void
 AudioStream::SetMicrophoneActive(bool aActive)
@@ -1030,17 +1030,17 @@ AudioStream::Reset()
     params.format = CUBEB_SAMPLE_FLOAT32NE;
   }
   mBytesPerFrame = sizeof(AudioDataValue) * mOutChannels;
 
   // Size mBuffer for one second of audio.  This value is arbitrary, and was
   // selected based on the observed behaviour of the existing AudioStream
   // implementations.
   uint32_t bufferLimit = FramesToBytes(mInRate);
-  NS_ABORT_IF_FALSE(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
+  MOZ_ASSERT(bufferLimit % mBytesPerFrame == 0, "Must buffer complete frames");
   mBuffer.Reset();
   mBuffer.SetCapacity(bufferLimit);
 
   // Don't block this thread to initialize a cubeb stream.
   // When this is done, it will start callbacks from Cubeb.  Those will
   // cause us to move from INITIALIZED to RUNNING.  Until then, we
   // can't access any cubeb functions.
   // Use a RefPtr to avoid leaks if Dispatch fails
@@ -1049,17 +1049,17 @@ AudioStream::Reset()
 }
 
 long
 AudioStream::DataCallback(void* aBuffer, long aFrames)
 {
   MonitorAutoLock mon(mMonitor);
   MOZ_ASSERT(mState != SHUTDOWN, "No data callback after shutdown");
   uint32_t available = std::min(static_cast<uint32_t>(FramesToBytes(aFrames)), mBuffer.Length());
-  NS_ABORT_IF_FALSE(available % mBytesPerFrame == 0, "Must copy complete frames");
+  MOZ_ASSERT(available % mBytesPerFrame == 0, "Must copy complete frames");
   AudioDataValue* output = reinterpret_cast<AudioDataValue*>(aBuffer);
   uint32_t underrunFrames = 0;
   uint32_t servicedFrames = 0;
   int64_t insertTime;
 
   mShouldDropFrames = false;
 
   // NOTE: wasapi (others?) can call us back *after* stop()/Shutdown() (mState == SHUTDOWN)
@@ -1108,17 +1108,17 @@ AudioStream::DataCallback(void* aBuffer,
         servicedFrames = GetUnprocessedWithSilencePadding(output, aFrames, insertTime);
       } else {
         servicedFrames = GetUnprocessed(output, aFrames, insertTime);
       }
     } else {
       servicedFrames = GetTimeStretched(output, aFrames, insertTime);
     }
 
-    NS_ABORT_IF_FALSE(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
+    MOZ_ASSERT(mBuffer.Length() % mBytesPerFrame == 0, "Must copy complete frames");
 
     // Notify any blocked Write() call that more space is available in mBuffer.
     mon.NotifyAll();
   } else {
     GetBufferInsertTime(insertTime);
   }
 
   underrunFrames = aFrames - servicedFrames;
--- a/dom/media/AudioStream.h
+++ b/dom/media/AudioStream.h
@@ -83,17 +83,17 @@ class CircularByteBuffer
 public:
   CircularByteBuffer()
     : mBuffer(nullptr), mCapacity(0), mStart(0), mCount(0)
   {}
 
   // Set the capacity of the buffer in bytes.  Must be called before any
   // call to append or pop elements.
   void SetCapacity(uint32_t aCapacity) {
-    NS_ABORT_IF_FALSE(!mBuffer, "Buffer allocated.");
+    MOZ_ASSERT(!mBuffer, "Buffer allocated.");
     mCapacity = aCapacity;
     mBuffer = new uint8_t[mCapacity];
   }
 
   uint32_t Length() {
     return mCount;
   }
 
@@ -103,48 +103,48 @@ public:
 
   uint32_t Available() {
     return Capacity() - Length();
   }
 
   // Append aLength bytes from aSrc to the buffer.  Caller must check that
   // sufficient space is available.
   void AppendElements(const uint8_t* aSrc, uint32_t aLength) {
-    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
-    NS_ABORT_IF_FALSE(aLength <= Available(), "Buffer full.");
+    MOZ_ASSERT(mBuffer && mCapacity, "Buffer not initialized.");
+    MOZ_ASSERT(aLength <= Available(), "Buffer full.");
 
     uint32_t end = (mStart + mCount) % mCapacity;
 
     uint32_t toCopy = std::min(mCapacity - end, aLength);
     memcpy(&mBuffer[end], aSrc, toCopy);
     memcpy(&mBuffer[0], aSrc + toCopy, aLength - toCopy);
     mCount += aLength;
   }
 
   // Remove aSize bytes from the buffer.  Caller must check returned size in
   // aSize{1,2} before using the pointer returned in aData{1,2}.  Caller
   // must not specify an aSize larger than Length().
   void PopElements(uint32_t aSize, void** aData1, uint32_t* aSize1,
                    void** aData2, uint32_t* aSize2) {
-    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
-    NS_ABORT_IF_FALSE(aSize <= Length(), "Request too large.");
+    MOZ_ASSERT(mBuffer && mCapacity, "Buffer not initialized.");
+    MOZ_ASSERT(aSize <= Length(), "Request too large.");
 
     *aData1 = &mBuffer[mStart];
     *aSize1 = std::min(mCapacity - mStart, aSize);
     *aData2 = &mBuffer[0];
     *aSize2 = aSize - *aSize1;
     mCount -= *aSize1 + *aSize2;
     mStart += *aSize1 + *aSize2;
     mStart %= mCapacity;
   }
 
   // Throw away all but aSize bytes from the buffer.  Returns new size, which
   // may be less than aSize
   uint32_t ContractTo(uint32_t aSize) {
-    NS_ABORT_IF_FALSE(mBuffer && mCapacity, "Buffer not initialized.");
+    MOZ_ASSERT(mBuffer && mCapacity, "Buffer not initialized.");
     if (aSize >= mCount) {
       return mCount;
     }
     mStart += (mCount - aSize);
     mCount = aSize;
     mStart %= mCapacity;
     return mCount;
   }
--- a/dom/media/FileBlockCache.cpp
+++ b/dom/media/FileBlockCache.cpp
@@ -207,18 +207,19 @@ nsresult FileBlockCache::Run()
     // This also ensures we will insert a new index into mChangeIndexList
     // when this happens.
 
     // Hold a reference to the change, in case another change
     // overwrites the mBlockChanges entry for this block while we drop
     // mDataMonitor to take mFileMonitor.
     int32_t blockIndex = mChangeIndexList.PopFront();
     nsRefPtr<BlockChange> change = mBlockChanges[blockIndex];
-    NS_ABORT_IF_FALSE(change,
-      "Change index list should only contain entries for blocks with changes");
+    MOZ_ASSERT(change,
+               "Change index list should only contain entries for blocks "
+               "with changes");
     {
       MonitorAutoUnlock unlock(mDataMonitor);
       MonitorAutoLock lock(mFileMonitor);
       if (change->IsWrite()) {
         WriteBlockToFile(blockIndex, change->mData.get());
       } else if (change->IsMove()) {
         MoveBlockInFile(change->mSourceBlockIndex, blockIndex);
       }
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -2259,17 +2259,17 @@ MediaCacheStream::Read(char* aBuffer, ui
       }
       if (streamWithPartialBlock) {
         // We can just use the data in mPartialBlockBuffer. In fact we should
         // use it rather than waiting for the block to fill and land in
         // the cache.
         int64_t bytes = std::min<int64_t>(size, streamWithPartialBlock->mChannelOffset - mStreamOffset);
         // Clamp bytes until 64-bit file size issues are fixed.
         bytes = std::min(bytes, int64_t(INT32_MAX));
-        NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= aCount, "Bytes out of range.");
+        MOZ_ASSERT(bytes >= 0 && bytes <= aCount, "Bytes out of range.");
         memcpy(aBuffer,
           reinterpret_cast<char*>(streamWithPartialBlock->mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
         if (mCurrentMode == MODE_METADATA) {
           streamWithPartialBlock->mMetadataInPartialBlockBuffer = true;
         }
         mStreamOffset += bytes;
         count = bytes;
         break;
@@ -2284,17 +2284,17 @@ MediaCacheStream::Read(char* aBuffer, ui
       }
       continue;
     }
 
     gMediaCache->NoteBlockUsage(this, cacheBlock, mCurrentMode, TimeStamp::Now());
 
     int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
     int32_t bytes;
-    NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range.");
+    MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
     nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
     if (NS_FAILED(rv)) {
       if (count == 0)
         return rv;
       // If we did successfully read some data, may as well return it
       break;
     }
     mStreamOffset += bytes;
@@ -2356,26 +2356,26 @@ MediaCacheStream::ReadFromCache(char* aB
     int32_t cacheBlock = streamBlock < mBlocks.Length() ? mBlocks[streamBlock] : -1;
     if (channelBlock == streamBlock && streamOffset < mChannelOffset) {
       // We can just use the data in mPartialBlockBuffer. In fact we should
       // use it rather than waiting for the block to fill and land in
       // the cache.
       // Clamp bytes until 64-bit file size issues are fixed.
       int64_t toCopy = std::min<int64_t>(size, mChannelOffset - streamOffset);
       bytes = std::min(toCopy, int64_t(INT32_MAX));
-      NS_ABORT_IF_FALSE(bytes >= 0 && bytes <= toCopy, "Bytes out of range.");
+      MOZ_ASSERT(bytes >= 0 && bytes <= toCopy, "Bytes out of range.");
       memcpy(aBuffer + count,
         reinterpret_cast<char*>(mPartialBlockBuffer.get()) + offsetInStreamBlock, bytes);
     } else {
       if (cacheBlock < 0) {
         // We expect all blocks to be cached! Fail!
         return NS_ERROR_FAILURE;
       }
       int64_t offset = cacheBlock*BLOCK_SIZE + offsetInStreamBlock;
-      NS_ABORT_IF_FALSE(size >= 0 && size <= INT32_MAX, "Size out of range.");
+      MOZ_ASSERT(size >= 0 && size <= INT32_MAX, "Size out of range.");
       nsresult rv = gMediaCache->ReadCacheFile(offset, aBuffer + count, int32_t(size), &bytes);
       if (NS_FAILED(rv)) {
         return rv;
       }
     }
     streamOffset += bytes;
     count += bytes;
   }
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -345,48 +345,111 @@ MediaDecoder::DecodedStreamGraphListener
 {
   if (event == EVENT_FINISHED) {
     nsCOMPtr<nsIRunnable> event =
       NS_NewRunnableMethod(this, &DecodedStreamGraphListener::DoNotifyFinished);
     aGraph->DispatchToMainThreadAfterStreamStateUpdate(event.forget());
   }
 }
 
+class MediaDecoder::OutputStreamListener : public MediaStreamListener {
+public:
+  OutputStreamListener(MediaDecoder* aDecoder, MediaStream* aStream)
+    : mDecoder(aDecoder), mStream(aStream) {}
+
+  virtual void NotifyEvent(
+      MediaStreamGraph* aGraph,
+      MediaStreamListener::MediaStreamGraphEvent event) MOZ_OVERRIDE {
+    if (event == EVENT_FINISHED) {
+      nsRefPtr<nsIRunnable> r = NS_NewRunnableMethod(
+          this, &OutputStreamListener::DoNotifyFinished);
+      aGraph->DispatchToMainThreadAfterStreamStateUpdate(r.forget());
+    }
+  }
+
+  void Forget() {
+    MOZ_ASSERT(NS_IsMainThread());
+    mDecoder = nullptr;
+  }
+
+private:
+  void DoNotifyFinished() {
+    MOZ_ASSERT(NS_IsMainThread());
+    if (!mDecoder) {
+      return;
+    }
+
+    // Remove the finished stream so it won't block the decoded stream.
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    auto& streams = mDecoder->OutputStreams();
+    // Don't read |mDecoder| in the loop since removing the element will lead
+    // to ~OutputStreamData() which will call Forget() to reset |mDecoder|.
+    for (int32_t i = streams.Length() - 1; i >= 0; --i) {
+      auto& os = streams[i];
+      MediaStream* p = os.mStream.get();
+      if (p == mStream.get()) {
+        if (os.mPort) {
+          os.mPort->Destroy();
+          os.mPort = nullptr;
+        }
+        streams.RemoveElementAt(i);
+        break;
+      }
+    }
+  }
+
+  // Main thread only
+  MediaDecoder* mDecoder;
+  nsRefPtr<MediaStream> mStream;
+};
+
+void
+MediaDecoder::OutputStreamData::Init(MediaDecoder* aDecoder,
+                                     ProcessedMediaStream* aStream)
+{
+  mStream = aStream;
+  mListener = new OutputStreamListener(aDecoder, aStream);
+  aStream->AddListener(mListener);
+}
+
+MediaDecoder::OutputStreamData::~OutputStreamData()
+{
+  mListener->Forget();
+}
+
 void MediaDecoder::DestroyDecodedStream()
 {
   MOZ_ASSERT(NS_IsMainThread());
   GetReentrantMonitor().AssertCurrentThreadIn();
 
   if (GetDecodedStream()) {
     GetStateMachine()->ResyncMediaStreamClock();
   } else {
     // Avoid the redundant blocking to output stream.
     return;
   }
 
   // All streams are having their SourceMediaStream disconnected, so they
   // need to be explicitly blocked again.
   for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
     OutputStreamData& os = mOutputStreams[i];
+    // Explicitly remove all existing ports.
+    // This is not strictly necessary but it's good form.
+    MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
+    os.mPort->Destroy();
+    os.mPort = nullptr;
     // During cycle collection, nsDOMMediaStream can be destroyed and send
     // its Destroy message before this decoder is destroyed. So we have to
     // be careful not to send any messages after the Destroy().
     if (os.mStream->IsDestroyed()) {
       // Probably the DOM MediaStream was GCed. Clean up.
-      MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
-      os.mPort->Destroy();
       mOutputStreams.RemoveElementAt(i);
-      continue;
+    } else {
+      os.mStream->ChangeExplicitBlockerCount(1);
     }
-    os.mStream->ChangeExplicitBlockerCount(1);
-    // Explicitly remove all existing ports. This is not strictly necessary but it's
-    // good form.
-    MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
-    os.mPort->Destroy();
-    os.mPort = nullptr;
   }
 
   mDecodedStream = nullptr;
 }
 
 void MediaDecoder::UpdateStreamBlockingForStateMachinePlaying()
 {
   GetReentrantMonitor().AssertCurrentThreadIn();
@@ -424,22 +487,18 @@ void MediaDecoder::RecreateDecodedStream
   mDecodedStream = new DecodedStreamData(this, aStartTimeUSecs,
     MediaStreamGraph::GetInstance()->CreateSourceStream(nullptr));
 
   // Note that the delay between removing ports in DestroyDecodedStream
   // and adding new ones won't cause a glitch since all graph operations
   // between main-thread stable states take effect atomically.
   for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
     OutputStreamData& os = mOutputStreams[i];
-    if (os.mStream->IsDestroyed()) {
-      // Probably the DOM MediaStream was GCed. Clean up.
-      // No need to destroy the port; all ports have been destroyed here.
-      mOutputStreams.RemoveElementAt(i);
-      continue;
-    }
+    MOZ_ASSERT(!os.mStream->IsDestroyed(),
+        "Should've been removed in DestroyDecodedStream()");
     ConnectDecodedStreamToOutputStream(&os);
   }
   UpdateStreamBlockingForStateMachinePlaying();
 
   mDecodedStream->mHaveBlockedForPlayState = mPlayState != PLAY_STATE_PLAYING;
   if (mDecodedStream->mHaveBlockedForPlayState) {
     mDecodedStream->mStream->ChangeExplicitBlockerCount(1);
   }
@@ -457,17 +516,17 @@ void MediaDecoder::AddOutputStream(Proce
       mDecoderStateMachine->SetAudioCaptured();
     }
     if (!GetDecodedStream()) {
       int64_t t = mDecoderStateMachine ?
                   mDecoderStateMachine->GetCurrentTimeUs() : 0;
       RecreateDecodedStream(t);
     }
     OutputStreamData* os = mOutputStreams.AppendElement();
-    os->Init(aStream, aFinishWhenEnded);
+    os->Init(this, aStream);
     ConnectDecodedStreamToOutputStream(os);
     if (aFinishWhenEnded) {
       // Ensure that aStream finishes the moment mDecodedStream does.
       aStream->SetAutofinish(true);
     }
   }
 
   // This can be called before Load(), in which case our mDecoderStateMachine
@@ -713,17 +772,17 @@ nsresult MediaDecoder::Play()
 }
 
 nsresult MediaDecoder::Seek(double aTime, SeekTarget::Type aSeekType)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
   UpdateDormantState(false /* aDormantTimeout */, true /* aActivity */);
 
-  NS_ABORT_IF_FALSE(aTime >= 0.0, "Cannot seek to a negative value.");
+  MOZ_ASSERT(aTime >= 0.0, "Cannot seek to a negative value.");
 
   int64_t timeUsecs = 0;
   nsresult rv = SecondsToUsecs(aTime, timeUsecs);
   NS_ENSURE_SUCCESS(rv, rv);
 
   mRequestedSeekTarget = SeekTarget(timeUsecs, aSeekType);
   mCurrentTime = aTime;
 
@@ -940,42 +999,16 @@ void MediaDecoder::PlaybackEnded()
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mShuttingDown ||
       mPlayState == PLAY_STATE_SEEKING ||
       mPlayState == PLAY_STATE_LOADING) {
     return;
   }
 
-  {
-    ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
-
-    for (int32_t i = mOutputStreams.Length() - 1; i >= 0; --i) {
-      OutputStreamData& os = mOutputStreams[i];
-      if (os.mStream->IsDestroyed()) {
-        // Probably the DOM MediaStream was GCed. Clean up.
-        MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
-        os.mPort->Destroy();
-        mOutputStreams.RemoveElementAt(i);
-        continue;
-      }
-      if (os.mFinishWhenEnded) {
-        // Shouldn't really be needed since mDecodedStream should already have
-        // finished, but doesn't hurt.
-        os.mStream->Finish();
-        MOZ_ASSERT(os.mPort, "Double-delete of the ports!");
-        os.mPort->Destroy();
-        // Not really needed but it keeps the invariant that a stream not
-        // connected to mDecodedStream is explicity blocked.
-        os.mStream->ChangeExplicitBlockerCount(1);
-        mOutputStreams.RemoveElementAt(i);
-      }
-    }
-  }
-
   PlaybackPositionChanged();
   ChangeState(PLAY_STATE_ENDED);
   InvalidateWithFlags(VideoFrameContainer::INVALIDATE_FORCE);
 
   UpdateReadyStateForData();
   if (mOwner)  {
     mOwner->PlaybackEnded();
   }
@@ -1546,17 +1579,17 @@ void MediaDecoder::SetPreservesPitch(boo
 }
 
 bool MediaDecoder::OnDecodeThread() const {
   NS_WARN_IF_FALSE(mDecoderStateMachine, "mDecoderStateMachine is null");
   return mDecoderStateMachine ? mDecoderStateMachine->OnDecodeThread() : false;
 }
 
 ReentrantMonitor& MediaDecoder::GetReentrantMonitor() {
-  return mReentrantMonitor.GetReentrantMonitor();
+  return mReentrantMonitor;
 }
 
 ImageContainer* MediaDecoder::GetImageContainer()
 {
   return mVideoFrameContainer ? mVideoFrameContainer->GetImageContainer() : nullptr;
 }
 
 void MediaDecoder::InvalidateWithFlags(uint32_t aFlags)
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -341,24 +341,16 @@ public:
   // played measured in seconds.
   virtual double GetCurrentTime();
 
   // Seek to the time position in (seconds) from the start of the video.
   // If aDoFastSeek is true, we'll seek to the sync point/keyframe preceeding
   // the seek target.
   virtual nsresult Seek(double aTime, SeekTarget::Type aSeekType);
 
-  // Enables decoders to supply an enclosing byte range for a seek offset.
-  // E.g. used by ChannelMediaResource to download a whole cluster for
-  // DASH-WebM.
-  virtual nsresult GetByteRangeForSeek(int64_t const aOffset,
-                                       MediaByteRange &aByteRange) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
   // Initialize state machine and schedule it.
   nsresult InitializeStateMachine(MediaDecoder* aCloneDonor);
 
   // Start playback of a video. 'Load' must have previously been
   // called.
   virtual nsresult Play();
 
   // Notify activity of the decoder owner is changed.
@@ -482,27 +474,27 @@ public:
     // Protected by mMutex
     nsRefPtr<MediaStream> mStream;
     // Protected by mMutex
     int64_t mLastOutputTime; // microseconds
     // Protected by mMutex
     bool mStreamFinishedOnMainThread;
   };
 
+  class OutputStreamListener;
+
   struct OutputStreamData {
-    void Init(ProcessedMediaStream* aStream, bool aFinishWhenEnded)
-    {
-      mStream = aStream;
-      mFinishWhenEnded = aFinishWhenEnded;
-    }
+    void Init(MediaDecoder* aDecoder, ProcessedMediaStream* aStream);
+    ~OutputStreamData();
     nsRefPtr<ProcessedMediaStream> mStream;
     // mPort connects mDecodedStream->mStream to our mStream.
     nsRefPtr<MediaInputPort> mPort;
-    bool mFinishWhenEnded;
+    nsRefPtr<OutputStreamListener> mListener;
   };
+
   /**
    * Connects mDecodedStream->mStream to aStream->mStream.
    */
   void ConnectDecodedStreamToOutputStream(OutputStreamData* aStream);
   /**
    * Disconnects mDecodedStream->mStream from all outputs and clears
    * mDecodedStream.
    */
@@ -1077,50 +1069,21 @@ protected:
   // is synchronised on a monitor. The lifetime of this object is
   // after mPlayState is LOADING and before mPlayState is SHUTDOWN. It
   // is safe to access it during this period.
   nsRefPtr<MediaDecoderStateMachine> mDecoderStateMachine;
 
   // Media data resource.
   nsRefPtr<MediaResource> mResource;
 
+private:
   // |ReentrantMonitor| for detecting when the video play state changes. A call
   // to |Wait| on this monitor will block the thread until the next state
-  // change.
-  // Using a wrapper class to restrict direct access to the |ReentrantMonitor|
-  // object. Subclasses may override |MediaDecoder|::|GetReentrantMonitor|
-  // e.g. |DASHRepDecoder|::|GetReentrantMonitor| returns the monitor in the
-  // main |DASHDecoder| object. In this case, directly accessing the
-  // member variable mReentrantMonitor in |DASHRepDecoder| is wrong.
-  // The wrapper |RestrictedAccessMonitor| restricts use to the getter
-  // function rather than the object itself.
-private:
-  class RestrictedAccessMonitor
-  {
-  public:
-    explicit RestrictedAccessMonitor(const char* aName) :
-      mReentrantMonitor(aName)
-    {
-      MOZ_COUNT_CTOR(RestrictedAccessMonitor);
-    }
-    ~RestrictedAccessMonitor()
-    {
-      MOZ_COUNT_DTOR(RestrictedAccessMonitor);
-    }
-
-    // Returns a ref to the reentrant monitor
-    ReentrantMonitor& GetReentrantMonitor() {
-      return mReentrantMonitor;
-    }
-  private:
-    ReentrantMonitor mReentrantMonitor;
-  };
-
-  // The |RestrictedAccessMonitor| member object.
-  RestrictedAccessMonitor mReentrantMonitor;
+  // change.  Explicitly private for force access via GetReentrantMonitor.
+  ReentrantMonitor mReentrantMonitor;
 
 #ifdef MOZ_EME
   nsRefPtr<CDMProxy> mProxy;
 #endif
 
 protected:
   // Data about MediaStreams that are being fed by this decoder.
   nsTArray<OutputStreamData> mOutputStreams;
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -223,18 +223,16 @@ MediaDecoderStateMachine::MediaDecoderSt
   mPlaybackRate(1.0),
   mPreservesPitch(true),
   mAmpleVideoFrames(MIN_VIDEO_QUEUE_SIZE),
   mLowAudioThresholdUsecs(detail::LOW_AUDIO_USECS),
   mAmpleAudioThresholdUsecs(detail::AMPLE_AUDIO_USECS),
   mQuickBufferingLowDataThresholdUsecs(detail::QUICK_BUFFERING_LOW_DATA_USECS),
   mIsAudioPrerolling(false),
   mIsVideoPrerolling(false),
-  mAudioRequestStatus(RequestStatus::Idle),
-  mVideoRequestStatus(RequestStatus::Idle),
   mAudioCaptured(false),
   mPositionChangeQueued(false),
   mAudioCompleted(false),
   mGotDurationFromMetaData(false),
   mDispatchedEventToDecode(false),
   mStopAudioThread(true),
   mQuickBuffering(false),
   mMinimizePreroll(false),
@@ -702,17 +700,17 @@ MediaDecoderStateMachine::IsVideoSeekCom
 }
 
 void
 MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   nsRefPtr<AudioData> audio(aAudioSample);
   MOZ_ASSERT(audio);
-  mAudioRequestStatus = RequestStatus::Idle;
+  mAudioDataRequest.Complete();
   mDecodedAudioEndTime = audio->GetEndTime();
 
   SAMPLE_LOG("OnAudioDecoded [%lld,%lld] disc=%d",
              (audio ? audio->mTime : -1),
              (audio ? audio->GetEndTime() : -1),
              (audio ? audio->mDiscontinuity : 0));
 
   switch (mState) {
@@ -819,39 +817,43 @@ MediaDecoderStateMachine::Push(VideoData
     mDecoder->GetReentrantMonitor().NotifyAll();
   }
 }
 
 void
 MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
                                        MediaDecoderReader::NotDecodedReason aReason)
 {
+  MOZ_ASSERT(OnDecodeThread());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   SAMPLE_LOG("OnNotDecoded (aType=%u, aReason=%u)", aType, aReason);
   bool isAudio = aType == MediaData::AUDIO_DATA;
   MOZ_ASSERT_IF(!isAudio, aType == MediaData::VIDEO_DATA);
 
-  // This callback means that the pending request is dead.
-  RequestStatusRef(aType) = RequestStatus::Idle;
+  if (isAudio) {
+    mAudioDataRequest.Complete();
+  } else {
+    mVideoDataRequest.Complete();
+  }
 
   // If this is a decode error, delegate to the generic error path.
   if (aReason == MediaDecoderReader::DECODE_ERROR) {
     DecodeError();
     return;
   }
 
   // If the decoder is waiting for data, we tell it to call us back when the
   // data arrives.
   if (aReason == MediaDecoderReader::WAITING_FOR_DATA) {
     MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                "Readers that send WAITING_FOR_DATA need to implement WaitForData");
-    RequestStatusRef(aType) = RequestStatus::Waiting;
-    mReader->WaitForData(aType)->Then(DecodeTaskQueue(), __func__, this,
-                                      &MediaDecoderStateMachine::OnWaitForDataResolved,
-                                      &MediaDecoderStateMachine::OnWaitForDataRejected);
+    WaitRequestRef(aType).Begin(mReader->WaitForData(aType)
+                                ->RefableThen(DecodeTaskQueue(), __func__, this,
+                                               &MediaDecoderStateMachine::OnWaitForDataResolved,
+                                               &MediaDecoderStateMachine::OnWaitForDataRejected));
     return;
   }
 
   if (aReason == MediaDecoderReader::CANCELED) {
     DispatchDecodeTasksIfNeeded();
     return;
   }
 
@@ -935,17 +937,17 @@ MediaDecoderStateMachine::MaybeFinishDec
 }
 
 void
 MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
 {
   MOZ_ASSERT(OnDecodeThread());
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
   nsRefPtr<VideoData> video(aVideoSample);
-  mVideoRequestStatus = RequestStatus::Idle;
+  mVideoDataRequest.Complete();
   mDecodedVideoEndTime = video ? video->GetEndTime() : mDecodedVideoEndTime;
 
   SAMPLE_LOG("OnVideoDecoded [%lld,%lld] disc=%d",
              (video ? video->mTime : -1),
              (video ? video->GetEndTime() : -1),
              (video ? video->mDiscontinuity : 0));
 
   switch (mState) {
@@ -1858,19 +1860,19 @@ MediaDecoderStateMachine::DispatchDecode
              (!needToDecodeAudio && !needToDecodeVideo));
 
   bool needIdle = !mDecoder->IsLogicallyPlaying() &&
                   mState != DECODER_STATE_SEEKING &&
                   !needToDecodeAudio &&
                   !needToDecodeVideo &&
                   !IsPlaying();
 
-  SAMPLE_LOG("DispatchDecodeTasksIfNeeded needAudio=%d audioStatus=%d needVideo=%d videoStatus=%d needIdle=%d",
-             needToDecodeAudio, mAudioRequestStatus,
-             needToDecodeVideo, mVideoRequestStatus,
+  SAMPLE_LOG("DispatchDecodeTasksIfNeeded needAudio=%d audioStatus=%s needVideo=%d videoStatus=%s needIdle=%d",
+             needToDecodeAudio, AudioRequestStatus(),
+             needToDecodeVideo, VideoRequestStatus(),
              needIdle);
 
   if (needToDecodeAudio) {
     EnsureAudioDecodeTaskQueued();
   }
   if (needToDecodeVideo) {
     EnsureVideoDecodeTaskQueued();
   }
@@ -1919,38 +1921,39 @@ MediaDecoderStateMachine::DispatchAudioD
 
 nsresult
 MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
 {
   AssertCurrentThreadInMonitor();
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
 
-  SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%d",
-              IsAudioDecoding(), mAudioRequestStatus);
+  SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%s",
+              IsAudioDecoding(), AudioRequestStatus());
 
   if (mState != DECODER_STATE_DECODING &&
       mState != DECODER_STATE_DECODING_FIRSTFRAME &&
       mState != DECODER_STATE_BUFFERING &&
       mState != DECODER_STATE_SEEKING) {
     return NS_OK;
   }
 
-  if (!IsAudioDecoding() || mAudioRequestStatus != RequestStatus::Idle || mWaitingForDecoderSeek) {
+  if (!IsAudioDecoding() || mAudioDataRequest.Exists() ||
+      mAudioWaitRequest.Exists() || mWaitingForDecoderSeek) {
     return NS_OK;
   }
 
   SAMPLE_LOG("Queueing audio task - queued=%i, decoder-queued=%o",
              AudioQueue().GetSize(), mReader->SizeOfAudioQueueInFrames());
 
-  mAudioRequestStatus = RequestStatus::Pending;
-  ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__, &MediaDecoderReader::RequestAudioData)
-    ->Then(DecodeTaskQueue(), __func__, this,
-           &MediaDecoderStateMachine::OnAudioDecoded,
-           &MediaDecoderStateMachine::OnAudioNotDecoded);
+  mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
+                                         __func__, &MediaDecoderReader::RequestAudioData)
+    ->RefableThen(DecodeTaskQueue(), __func__, this,
+                  &MediaDecoderStateMachine::OnAudioDecoded,
+                  &MediaDecoderStateMachine::OnAudioNotDecoded));
 
   return NS_OK;
 }
 
 nsresult
 MediaDecoderStateMachine::DispatchVideoDecodeTaskIfNeeded()
 {
   ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
@@ -1964,52 +1967,52 @@ MediaDecoderStateMachine::DispatchVideoD
   return NS_OK;
 }
 
 nsresult
 MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
 {
   AssertCurrentThreadInMonitor();
 
-  SAMPLE_LOG("EnsureVideoDecodeTaskQueued isDecoding=%d status=%d",
-             IsVideoDecoding(), mVideoRequestStatus);
+  SAMPLE_LOG("EnsureVideoDecodeTaskQueued isDecoding=%d status=%s",
+             IsVideoDecoding(), VideoRequestStatus());
 
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
 
   if (mState != DECODER_STATE_DECODING &&
       mState != DECODER_STATE_DECODING_FIRSTFRAME &&
       mState != DECODER_STATE_BUFFERING &&
       mState != DECODER_STATE_SEEKING) {
     return NS_OK;
   }
 
-  if (!IsVideoDecoding() || mVideoRequestStatus != RequestStatus::Idle || mWaitingForDecoderSeek) {
+  if (!IsVideoDecoding() || mVideoDataRequest.Exists() ||
+      mVideoWaitRequest.Exists() || mWaitingForDecoderSeek) {
     return NS_OK;
   }
 
   bool skipToNextKeyFrame = NeedToSkipToNextKeyframe();
   int64_t currentTime = mState == DECODER_STATE_SEEKING ? 0 : GetMediaTime();
 
   // Time the video decode, so that if it's slow, we can increase our low
   // audio threshold to reduce the chance of an audio underrun while we're
   // waiting for a video decode to complete.
   mVideoDecodeStartTime = TimeStamp::Now();
 
   SAMPLE_LOG("Queueing video task - queued=%i, decoder-queued=%o, skip=%i, time=%lld",
              VideoQueue().GetSize(), mReader->SizeOfVideoQueueInFrames(), skipToNextKeyFrame,
              currentTime);
 
-  mVideoRequestStatus = RequestStatus::Pending;
-  ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
-                 &MediaDecoderReader::RequestVideoData, skipToNextKeyFrame, currentTime)
-    ->Then(DecodeTaskQueue(), __func__, this,
-           &MediaDecoderStateMachine::OnVideoDecoded,
-           &MediaDecoderStateMachine::OnVideoNotDecoded);
-
+  mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(), __func__,
+                                         &MediaDecoderReader::RequestVideoData,
+                                         skipToNextKeyFrame, currentTime)
+    ->RefableThen(DecodeTaskQueue(), __func__, this,
+                  &MediaDecoderStateMachine::OnVideoDecoded,
+                  &MediaDecoderStateMachine::OnVideoNotDecoded));
   return NS_OK;
 }
 
 nsresult
 MediaDecoderStateMachine::StartAudioThread()
 {
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
@@ -2282,31 +2285,32 @@ MediaDecoderStateMachine::DecodeFirstFra
   } else if (mSentFirstFrameLoadedEvent) {
     // We're resuming from dormant state, so we don't need to request
     // the first samples in order to determine the media start time,
     // we have the start time from last time we loaded.
     SetStartTime(mStartTime);
     nsresult res = FinishDecodeFirstFrame();
     NS_ENSURE_SUCCESS(res, res);
   } else {
+    // NB: We're already on the decode thread, but we proxy these anyway so that
+    // we don't need to worry about dropping locks.
     if (HasAudio()) {
-      mAudioRequestStatus = RequestStatus::Pending;
-      ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
-      mReader->RequestAudioData()->Then(DecodeTaskQueue(), __func__, this,
-                                        &MediaDecoderStateMachine::OnAudioDecoded,
-                                        &MediaDecoderStateMachine::OnAudioNotDecoded);
+      mAudioDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
+                                             __func__, &MediaDecoderReader::RequestAudioData)
+        ->RefableThen(DecodeTaskQueue(), __func__, this,
+                      &MediaDecoderStateMachine::OnAudioDecoded,
+                      &MediaDecoderStateMachine::OnAudioNotDecoded));
     }
     if (HasVideo()) {
       mVideoDecodeStartTime = TimeStamp::Now();
-      mVideoRequestStatus = RequestStatus::Pending;
-      ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
-      mReader->RequestVideoData(false, 0)
-             ->Then(DecodeTaskQueue(), __func__, this,
-                    &MediaDecoderStateMachine::OnVideoDecoded,
-                    &MediaDecoderStateMachine::OnVideoNotDecoded);
+      mVideoDataRequest.Begin(ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
+                                             __func__, &MediaDecoderReader::RequestVideoData, false, int64_t(0))
+        ->RefableThen(DecodeTaskQueue(), __func__, this,
+                      &MediaDecoderStateMachine::OnVideoDecoded,
+                      &MediaDecoderStateMachine::OnVideoNotDecoded));
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 MediaDecoderStateMachine::FinishDecodeFirstFrame()
@@ -2753,18 +2757,16 @@ nsresult MediaDecoderStateMachine::RunSt
       StopAudioThread();
       FlushDecoding();
       // Now that those threads are stopped, there's no possibility of
       // mPendingWakeDecoder being needed again. Revoke it.
       mPendingWakeDecoder = nullptr;
       DebugOnly<nsresult> rv = DecodeTaskQueue()->Dispatch(
       NS_NewRunnableMethod(mReader, &MediaDecoderReader::ReleaseMediaResources));
       MOZ_ASSERT(NS_SUCCEEDED(rv));
-      mAudioRequestStatus = RequestStatus::Idle;
-      mVideoRequestStatus = RequestStatus::Idle;
       return NS_OK;
     }
 
     case DECODER_STATE_WAIT_FOR_RESOURCES: {
       return NS_OK;
     }
 
     case DECODER_STATE_DECODING_NONE: {
@@ -2822,22 +2824,22 @@ nsresult MediaDecoderStateMachine::RunSt
                       (mQuickBuffering ? "(quick exit)" : ""));
           ScheduleStateMachine(USECS_PER_S);
           return NS_OK;
         }
       } else if (OutOfDecodedAudio() || OutOfDecodedVideo()) {
         MOZ_ASSERT(mReader->IsWaitForDataSupported(),
                    "Don't yet have a strategy for non-heuristic + non-WaitForData");
         DispatchDecodeTasksIfNeeded();
-        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mAudioRequestStatus != RequestStatus::Idle);
-        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mVideoRequestStatus != RequestStatus::Idle);
+        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedAudio(), mAudioDataRequest.Exists() || mAudioWaitRequest.Exists());
+        MOZ_ASSERT_IF(!mMinimizePreroll && OutOfDecodedVideo(), mVideoDataRequest.Exists() || mVideoWaitRequest.Exists());
         DECODER_LOG("In buffering mode, waiting to be notified: outOfAudio: %d, "
-                    "mAudioStatus: %d, outOfVideo: %d, mVideoStatus: %d",
-                    OutOfDecodedAudio(), mAudioRequestStatus,
-                    OutOfDecodedVideo(), mVideoRequestStatus);
+                    "mAudioStatus: %s, outOfVideo: %d, mVideoStatus: %s",
+                    OutOfDecodedAudio(), AudioRequestStatus(),
+                    OutOfDecodedVideo(), VideoRequestStatus());
         return NS_OK;
       }
 
       DECODER_LOG("Changed state from BUFFERING to DECODING");
       DECODER_LOG("Buffered for %.3lfs", (now - mBufferingStart).ToSeconds());
       StartDecoding();
 
       // Notify to allow blocked decoder thread to continue
@@ -3091,18 +3093,18 @@ void MediaDecoderStateMachine::AdvanceFr
       mDecoder->GetState() == MediaDecoder::PLAY_STATE_PLAYING &&
       mDecoder->IsExpectingMoreData()) {
     bool shouldBuffer;
     if (mReader->UseBufferingHeuristics()) {
       shouldBuffer = HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
                      (JustExitedQuickBuffering() || HasLowUndecodedData());
     } else {
       MOZ_ASSERT(mReader->IsWaitForDataSupported());
-      shouldBuffer = (OutOfDecodedAudio() && mAudioRequestStatus == RequestStatus::Waiting) ||
-                     (OutOfDecodedVideo() && mVideoRequestStatus == RequestStatus::Waiting);
+      shouldBuffer = (OutOfDecodedAudio() && mAudioWaitRequest.Exists()) ||
+                     (OutOfDecodedVideo() && mVideoWaitRequest.Exists());
     }
     if (shouldBuffer) {
       if (currentFrame) {
         VideoQueue().PushFront(currentFrame);
       }
       StartBuffering();
       // Don't go straight back to the state machine loop since that might
       // cause us to start decoding again and we could flip-flop between
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -394,42 +394,37 @@ public:
   // samples in advance of when they're needed for playback.
   void SetMinimizePrerollUntilPlaybackStarts();
 
   void OnAudioDecoded(AudioData* aSample);
   void OnVideoDecoded(VideoData* aSample);
   void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
   void OnAudioNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
   {
-    MOZ_ASSERT(OnDecodeThread());
     OnNotDecoded(MediaData::AUDIO_DATA, aReason);
   }
   void OnVideoNotDecoded(MediaDecoderReader::NotDecodedReason aReason)
   {
-    MOZ_ASSERT(OnDecodeThread());
     OnNotDecoded(MediaData::VIDEO_DATA, aReason);
   }
 
   void OnSeekCompleted(int64_t aTime);
   void OnSeekFailed(nsresult aResult);
 
   void OnWaitForDataResolved(MediaData::Type aType)
   {
     ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
-    if (RequestStatusRef(aType) == RequestStatus::Waiting) {
-      RequestStatusRef(aType) = RequestStatus::Idle;
-      DispatchDecodeTasksIfNeeded();
-    }
+    WaitRequestRef(aType).Complete();
+    DispatchDecodeTasksIfNeeded();
   }
 
   void OnWaitForDataRejected(WaitForDataRejectValue aRejection)
   {
-    if (RequestStatusRef(aRejection.mType) == RequestStatus::Waiting) {
-      RequestStatusRef(aRejection.mType) = RequestStatus::Idle;
-    }
+    ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
+    WaitRequestRef(aRejection.mType).Complete();
   }
 
 private:
   void AcquireMonitorAndInvokeDecodeError();
 
 protected:
   virtual ~MediaDecoderStateMachine();
 
@@ -1014,31 +1009,48 @@ protected:
   // can't keep up with the decode, and cause us to pause playback. So we
   // have a "preroll" stage, where we ignore the results of our "low data"
   // logic during the first few frames of our decode. This occurs during
   // playback. The flags below are true when the corresponding stream is
   // being "prerolled".
   bool mIsAudioPrerolling;
   bool mIsVideoPrerolling;
 
-  enum class RequestStatus {
-    Idle,
-    Pending,
-    Waiting
-  };
+  // Only one of a given pair of ({Audio,Video}DataPromise, WaitForDataPromise)
+  // should exist at any given moment.
+
+  MediaPromiseConsumerHolder<MediaDecoderReader::AudioDataPromise> mAudioDataRequest;
+  MediaPromiseConsumerHolder<MediaDecoderReader::WaitForDataPromise> mAudioWaitRequest;
+  const char* AudioRequestStatus()
+  {
+    if (mAudioDataRequest.Exists()) {
+      MOZ_DIAGNOSTIC_ASSERT(!mAudioWaitRequest.Exists());
+      return "pending";
+    } else if (mAudioWaitRequest.Exists()) {
+      return "waiting";
+    }
+    return "idle";
+  }
 
-  // True when we have dispatched a task to the decode task queue to request
-  // decoded audio/video, and/or we are waiting for the requested sample to be
-  // returned by callback from the Reader.
-  RequestStatus mAudioRequestStatus;
-  RequestStatus mVideoRequestStatus;
+  MediaPromiseConsumerHolder<MediaDecoderReader::WaitForDataPromise> mVideoWaitRequest;
+  MediaPromiseConsumerHolder<MediaDecoderReader::VideoDataPromise> mVideoDataRequest;
+  const char* VideoRequestStatus()
+  {
+    if (mVideoDataRequest.Exists()) {
+      MOZ_DIAGNOSTIC_ASSERT(!mVideoWaitRequest.Exists());
+      return "pending";
+    } else if (mVideoWaitRequest.Exists()) {
+      return "waiting";
+    }
+    return "idle";
+  }
 
-  RequestStatus& RequestStatusRef(MediaData::Type aType)
+  MediaPromiseConsumerHolder<MediaDecoderReader::WaitForDataPromise>& WaitRequestRef(MediaData::Type aType)
   {
-    return aType == MediaData::AUDIO_DATA ? mAudioRequestStatus : mVideoRequestStatus;
+    return aType == MediaData::AUDIO_DATA ? mAudioWaitRequest : mVideoWaitRequest;
   }
 
   // True if we shouldn't play our audio (but still write it to any capturing
   // streams). When this is true, mStopAudioThread is always true and
   // the audio thread will never start again after it has stopped.
   bool mAudioCaptured;
 
   // True if an event to notify about a change in the playback
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -32,37 +32,38 @@ struct TrackInfo {
   nsString mLabel;
   nsString mLanguage;
   bool mEnabled;
 };
 
 // Stores info relevant to presenting media frames.
 class VideoInfo {
 private:
-  VideoInfo(int32_t aWidth, int32_t aHeight, bool aHasVideo)
-    : mDisplay(aWidth, aHeight)
-    , mStereoMode(StereoMode::MONO)
-    , mHasVideo(aHasVideo)
-    , mIsHardwareAccelerated(false)
+  void Init(int32_t aWidth, int32_t aHeight, bool aHasVideo)
   {
+    mDisplay = nsIntSize(aWidth, aHeight);
+    mStereoMode = StereoMode::MONO;
+    mHasVideo = aHasVideo;
+    mIsHardwareAccelerated = false;
+
+    // TODO: TrackInfo should be initialized by its specific codec decoder.
+    // This following call should be removed once we have that implemented.
+    mTrackInfo.Init(NS_LITERAL_STRING("2"), NS_LITERAL_STRING("main"),
+                    EmptyString(), EmptyString(), true);
   }
 
 public:
   VideoInfo()
-    : VideoInfo(0, 0, false)
   {
-    // TODO: TrackInfo should be initialized by its specific codec decoder.
-    // This following call should be removed once we have that implemented.
-    mTrackInfo.Init(NS_LITERAL_STRING("2"), NS_LITERAL_STRING("main"),
-    EmptyString(), EmptyString(), true);
+    Init(0, 0, false);
   }
 
   VideoInfo(int32_t aWidth, int32_t aHeight)
-    : VideoInfo(aWidth, aHeight, true)
   {
+    Init(aWidth, aHeight, true);
   }
 
   // Size in pixels at which the video is rendered. This is after it has
   // been scaled by its aspect ratio.
   nsIntSize mDisplay;
 
   // Indicates the frame layout for single track stereo videos.
   StereoMode mStereoMode;
--- a/dom/media/MediaPromise.h
+++ b/dom/media/MediaPromise.h
@@ -235,18 +235,17 @@ protected:
       PROMISE_LOG("%s Then() call made from %s [Runnable=%p, Promise=%p, ThenValue=%p]",
                   resolved ? "Resolving" : "Rejecting", ThenValueBase::mCallSite,
                   runnable.get(), aPromise, this);
       DebugOnly<nsresult> rv = detail::DispatchMediaPromiseRunnable(mResponseTarget, runnable);
       MOZ_ASSERT(NS_SUCCEEDED(rv));
     }
 
 #ifdef DEBUG
-  // Can't mark MOZ_OVERRIDE due to bug in clang builders we use for osx b2g desktop. :-(
-  virtual void AssertOnDispatchThread()
+  virtual void AssertOnDispatchThread() MOZ_OVERRIDE
   {
     detail::AssertOnThread(mResponseTarget);
   }
 #endif
 
   protected:
     virtual void DoResolve(ResolveValueType aResolveValue) MOZ_OVERRIDE
     {
--- a/dom/media/MediaRecorder.cpp
+++ b/dom/media/MediaRecorder.cpp
@@ -974,17 +974,17 @@ MediaRecorder::Constructor(const GlobalO
                                                      ownerWindow);
   object->SetMimeType(aInitDict.mMimeType);
   return object.forget();
 }
 
 nsresult
 MediaRecorder::CreateAndDispatchBlobEvent(already_AddRefed<nsIDOMBlob>&& aBlob)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
   if (!CheckPrincipal()) {
     // Media is not same-origin, don't allow the data out.
     nsRefPtr<nsIDOMBlob> blob = aBlob;
     return NS_ERROR_DOM_SECURITY_ERR;
   }
   BlobEventInit init;
   init.mBubbles = false;
   init.mCancelable = false;
@@ -998,17 +998,17 @@ MediaRecorder::CreateAndDispatchBlobEven
                            init);
   event->SetTrusted(true);
   return DispatchDOMEvent(nullptr, event, nullptr, nullptr);
 }
 
 void
 MediaRecorder::DispatchSimpleEvent(const nsAString & aStr)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
 
   nsCOMPtr<nsIDOMEvent> event;
   rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
   if (NS_FAILED(rv)) {
@@ -1029,17 +1029,17 @@ MediaRecorder::DispatchSimpleEvent(const
     NS_ERROR("Failed to dispatch the event!!!");
     return;
   }
 }
 
 void
 MediaRecorder::NotifyError(nsresult aRv)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
   nsString errorMsg;
   switch (aRv) {
   case NS_ERROR_DOM_SECURITY_ERR:
     errorMsg = NS_LITERAL_STRING("SecurityError");
@@ -1065,17 +1065,17 @@ MediaRecorder::NotifyError(nsresult aRv)
     NS_ERROR("Failed to dispatch the error event!!!");
     return;
   }
   return;
 }
 
 bool MediaRecorder::CheckPrincipal()
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
   if (!mDOMStream && !mAudioNode) {
     return false;
   }
   if (!GetOwner())
     return false;
   nsCOMPtr<nsIDocument> doc = GetOwner()->GetExtantDoc();
   if (!doc) {
     return false;
--- a/dom/media/fmp4/eme/EMEVideoDecoder.cpp
+++ b/dom/media/fmp4/eme/EMEVideoDecoder.cpp
@@ -30,19 +30,19 @@ EMEVideoDecoder::InitTags(nsTArray<nsCSt
 }
 
 nsCString
 EMEVideoDecoder::GetNodeId()
 {
   return mProxy->GetNodeId();
 }
 
-GMPUniquePtr<GMPVideoEncodedFrame>
+GMPUnique<GMPVideoEncodedFrame>::Ptr
 EMEVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
 {
-  GMPUniquePtr<GMPVideoEncodedFrame> frame = GMPVideoDecoder::CreateFrame(aSample);
+  GMPUnique<GMPVideoEncodedFrame>::Ptr frame = GMPVideoDecoder::CreateFrame(aSample);
   if (frame && aSample->crypto.valid) {
     static_cast<gmp::GMPVideoEncodedFrameImpl*>(frame.get())->InitCrypto(aSample->crypto);
   }
   return frame;
 }
 
 } // namespace mozilla
--- a/dom/media/fmp4/eme/EMEVideoDecoder.h
+++ b/dom/media/fmp4/eme/EMEVideoDecoder.h
@@ -39,16 +39,16 @@ public:
                                                                       aConfig.display_height), aImageContainer))
    , mProxy(aProxy)
   {
   }
 
 private:
   virtual void InitTags(nsTArray<nsCString>& aTags) MOZ_OVERRIDE;
   virtual nsCString GetNodeId() MOZ_OVERRIDE;
-  virtual GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
+  virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
 
   nsRefPtr<CDMProxy> mProxy;
 };
 
 }
 
 #endif // EMEVideoDecoder_h_
--- a/dom/media/fmp4/gmp/GMPVideoDecoder.cpp
+++ b/dom/media/fmp4/gmp/GMPVideoDecoder.cpp
@@ -12,17 +12,17 @@ namespace mozilla {
 
 #if defined(DEBUG)
 static bool IsOnGMPThread();
 #endif
 
 void
 VideoCallbackAdapter::Decoded(GMPVideoi420Frame* aDecodedFrame)
 {
-  GMPUniquePtr<GMPVideoi420Frame> decodedFrame(aDecodedFrame);
+  GMPUnique<GMPVideoi420Frame>::Ptr decodedFrame(aDecodedFrame);
 
   MOZ_ASSERT(IsOnGMPThread());
 
   VideoData::YCbCrBuffer b;
   for (int i = 0; i < kGMPNumOfPlanes; ++i) {
     b.mPlanes[i].mData = decodedFrame->Buffer(GMPPlaneType(i));
     b.mPlanes[i].mStride = decodedFrame->Stride(GMPPlaneType(i));
     if (i == kGMPYPlane) {
@@ -108,27 +108,27 @@ GMPVideoDecoder::InitTags(nsTArray<nsCSt
 }
 
 nsCString
 GMPVideoDecoder::GetNodeId()
 {
   return NS_LITERAL_CSTRING("");
 }
 
-GMPUniquePtr<GMPVideoEncodedFrame>
+GMPUnique<GMPVideoEncodedFrame>::Ptr
 GMPVideoDecoder::CreateFrame(mp4_demuxer::MP4Sample* aSample)
 {
   GMPVideoFrame* ftmp = nullptr;
   GMPErr err = mHost->CreateFrame(kGMPEncodedVideoFrame, &ftmp);
   if (GMP_FAILED(err)) {
     mCallback->Error();
     return nullptr;
   }
 
-  GMPUniquePtr<GMPVideoEncodedFrame> frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
+  GMPUnique<GMPVideoEncodedFrame>::Ptr frame(static_cast<GMPVideoEncodedFrame*>(ftmp));
   err = frame->CreateEmptyFrame(aSample->size);
   if (GMP_FAILED(err)) {
     mCallback->Error();
     return nullptr;
   }
 
   memcpy(frame->Buffer(), aSample->data, frame->Size());
 
@@ -188,17 +188,17 @@ GMPVideoDecoder::Input(mp4_demuxer::MP4S
   nsAutoPtr<mp4_demuxer::MP4Sample> sample(aSample);
   if (!mGMP) {
     mCallback->Error();
     return NS_ERROR_FAILURE;
   }
 
   mAdapter->SetLastStreamOffset(sample->byte_offset);
 
-  GMPUniquePtr<GMPVideoEncodedFrame> frame = CreateFrame(sample);
+  GMPUnique<GMPVideoEncodedFrame>::Ptr frame = CreateFrame(sample);
   nsTArray<uint8_t> info; // No codec specific per-frame info to pass.
   nsresult rv = mGMP->Decode(Move(frame), false, info, 0);
   if (NS_FAILED(rv)) {
     mCallback->Error();
     return rv;
   }
 
   return NS_OK;
--- a/dom/media/fmp4/gmp/GMPVideoDecoder.h
+++ b/dom/media/fmp4/gmp/GMPVideoDecoder.h
@@ -83,17 +83,17 @@ public:
   virtual nsresult Input(mp4_demuxer::MP4Sample* aSample) MOZ_OVERRIDE;
   virtual nsresult Flush() MOZ_OVERRIDE;
   virtual nsresult Drain() MOZ_OVERRIDE;
   virtual nsresult Shutdown() MOZ_OVERRIDE;
 
 protected:
   virtual void InitTags(nsTArray<nsCString>& aTags);
   virtual nsCString GetNodeId();
-  virtual GMPUniquePtr<GMPVideoEncodedFrame> CreateFrame(mp4_demuxer::MP4Sample* aSample);
+  virtual GMPUnique<GMPVideoEncodedFrame>::Ptr CreateFrame(mp4_demuxer::MP4Sample* aSample);
 
 private:
   const mp4_demuxer::VideoDecoderConfig& mConfig;
   MediaDataDecoderCallbackProxy* mCallback;
   nsCOMPtr<mozIGeckoMediaPluginService> mMPS;
   GMPVideoDecoderProxy* mGMP;
   GMPVideoHost* mHost;
   nsAutoPtr<VideoCallbackAdapter> mAdapter;
--- a/dom/media/gmp/GMPProcessChild.cpp
+++ b/dom/media/gmp/GMPProcessChild.cpp
@@ -31,22 +31,22 @@ GMPProcessChild::Init()
   std::string pluginFilename;
   std::string voucherFilename;
 
 #if defined(OS_POSIX)
   // NB: need to be very careful in ensuring that the first arg
   // (after the binary name) here is indeed the plugin module path.
   // Keep in sync with dom/plugins/PluginModuleParent.
   std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
-  NS_ABORT_IF_FALSE(values.size() >= 3, "not enough args");
+  MOZ_ASSERT(values.size() >= 3, "not enough args");
   pluginFilename = values[1];
   voucherFilename = values[2];
 #elif defined(OS_WIN)
   std::vector<std::wstring> values = CommandLine::ForCurrentProcess()->GetLooseValues();
-  NS_ABORT_IF_FALSE(values.size() >= 2, "not enough loose args");
+  MOZ_ASSERT(values.size() >= 2, "not enough loose args");
   pluginFilename = WideToUTF8(values[0]);
   voucherFilename = WideToUTF8(values[1]);
 #else
 #error Not implemented
 #endif
 
   BackgroundHangMonitor::Startup();
 
--- a/dom/media/gmp/GMPUtils.h
+++ b/dom/media/gmp/GMPUtils.h
@@ -13,14 +13,17 @@ namespace mozilla {
 template<typename T>
 struct DestroyPolicy
 {
   void operator()(T* aGMPObject) const {
     aGMPObject->Destroy();
   }
 };
 
+// Ideally, this would be a template alias, but GCC 4.6 doesn't support them.  See bug 1124021.
 template<typename T>
-using GMPUniquePtr = mozilla::UniquePtr<T, DestroyPolicy<T>>;
+struct GMPUnique {
+  typedef mozilla::UniquePtr<T, DestroyPolicy<T>> Ptr;
+};
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/gmp/GMPVideoDecoderParent.cpp
+++ b/dom/media/gmp/GMPVideoDecoderParent.cpp
@@ -104,29 +104,29 @@ GMPVideoDecoderParent::InitDecode(const 
   }
   mIsOpen = true;
 
   // Async IPC, we don't have access to a return value.
   return NS_OK;
 }
 
 nsresult
-GMPVideoDecoderParent::Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
+GMPVideoDecoderParent::Decode(GMPUnique<GMPVideoEncodedFrame>::Ptr aInputFrame,
                               bool aMissingFrames,
                               const nsTArray<uint8_t>& aCodecSpecificInfo,
                               int64_t aRenderTimeMs)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video decoder");
     return NS_ERROR_FAILURE;
   }
 
   MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
 
-  GMPUniquePtr<GMPVideoEncodedFrameImpl> inputFrameImpl(
+  GMPUnique<GMPVideoEncodedFrameImpl>::Ptr inputFrameImpl(
     static_cast<GMPVideoEncodedFrameImpl*>(aInputFrame.release()));
 
   // Very rough kill-switch if the plugin stops processing.  If it's merely
   // hung and continues, we'll come back to life eventually.
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
       (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
     return NS_ERROR_FAILURE;
--- a/dom/media/gmp/GMPVideoDecoderParent.h
+++ b/dom/media/gmp/GMPVideoDecoderParent.h
@@ -33,17 +33,17 @@ public:
   nsresult Shutdown();
 
   // GMPVideoDecoder
   virtual void Close() MOZ_OVERRIDE;
   virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               GMPVideoDecoderCallbackProxy* aCallback,
                               int32_t aCoreCount) MOZ_OVERRIDE;
-  virtual nsresult Decode(GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
+  virtual nsresult Decode(GMPUnique<GMPVideoEncodedFrame>::Ptr aInputFrame,
                           bool aMissingFrames,
                           const nsTArray<uint8_t>& aCodecSpecificInfo,
                           int64_t aRenderTimeMs = -1) MOZ_OVERRIDE;
   virtual nsresult Reset() MOZ_OVERRIDE;
   virtual nsresult Drain() MOZ_OVERRIDE;
   virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
 
   // GMPSharedMemManager
--- a/dom/media/gmp/GMPVideoDecoderProxy.h
+++ b/dom/media/gmp/GMPVideoDecoderProxy.h
@@ -33,17 +33,17 @@ public:
 
 // This interface is not thread-safe and must only be used from GMPThread.
 class GMPVideoDecoderProxy {
 public:
   virtual nsresult InitDecode(const GMPVideoCodec& aCodecSettings,
                               const nsTArray<uint8_t>& aCodecSpecific,
                               GMPVideoDecoderCallbackProxy* aCallback,
                               int32_t aCoreCount) = 0;
-  virtual nsresult Decode(mozilla::GMPUniquePtr<GMPVideoEncodedFrame> aInputFrame,
+  virtual nsresult Decode(mozilla::GMPUnique<GMPVideoEncodedFrame>::Ptr aInputFrame,
                           bool aMissingFrames,
                           const nsTArray<uint8_t>& aCodecSpecificInfo,
                           int64_t aRenderTimeMs = -1) = 0;
   virtual nsresult Reset() = 0;
   virtual nsresult Drain() = 0;
   virtual const uint64_t ParentID() = 0;
 
   // Call to tell GMP/plugin the consumer will no longer use this
--- a/dom/media/gmp/GMPVideoEncoderParent.cpp
+++ b/dom/media/gmp/GMPVideoEncoderParent.cpp
@@ -121,28 +121,28 @@ GMPVideoEncoderParent::InitEncode(const 
   }
   mIsOpen = true;
 
   // Async IPC, we don't have access to a return value.
   return GMPNoErr;
 }
 
 GMPErr
-GMPVideoEncoderParent::Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
+GMPVideoEncoderParent::Encode(GMPUnique<GMPVideoi420Frame>::Ptr aInputFrame,
                               const nsTArray<uint8_t>& aCodecSpecificInfo,
                               const nsTArray<GMPVideoFrameType>& aFrameTypes)
 {
   if (!mIsOpen) {
     NS_WARNING("Trying to use an dead GMP video encoder");
     return GMPGenericErr;
   }
 
   MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
 
-  GMPUniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
+  GMPUnique<GMPVideoi420FrameImpl>::Ptr inputFrameImpl(
     static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release()));
 
   // Very rough kill-switch if the plugin stops processing.  If it's merely
   // hung and continues, we'll come back to life eventually.
   // 3* is because we're using 3 buffers per frame for i420 data for now.
   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
       (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
     return GMPGenericErr;
--- a/dom/media/gmp/GMPVideoEncoderParent.h
+++ b/dom/media/gmp/GMPVideoEncoderParent.h
@@ -34,17 +34,17 @@ public:
 
   // GMPVideoEncoderProxy
   virtual void Close() MOZ_OVERRIDE;
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const nsTArray<uint8_t>& aCodecSpecific,
                             GMPVideoEncoderCallbackProxy* aCallback,
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) MOZ_OVERRIDE;
-  virtual GMPErr Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
+  virtual GMPErr Encode(GMPUnique<GMPVideoi420Frame>::Ptr aInputFrame,
                         const nsTArray<uint8_t>& aCodecSpecificInfo,
                         const nsTArray<GMPVideoFrameType>& aFrameTypes) MOZ_OVERRIDE;
   virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) MOZ_OVERRIDE;
   virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
   virtual GMPErr SetPeriodicKeyFrames(bool aEnable) MOZ_OVERRIDE;
   virtual const uint64_t ParentID() MOZ_OVERRIDE { return reinterpret_cast<uint64_t>(mPlugin.get()); }
 
   // GMPSharedMemManager
--- a/dom/media/gmp/GMPVideoEncoderProxy.h
+++ b/dom/media/gmp/GMPVideoEncoderProxy.h
@@ -35,17 +35,17 @@ public:
 // This interface is not thread-safe and must only be used from GMPThread.
 class GMPVideoEncoderProxy {
 public:
   virtual GMPErr InitEncode(const GMPVideoCodec& aCodecSettings,
                             const nsTArray<uint8_t>& aCodecSpecific,
                             GMPVideoEncoderCallbackProxy* aCallback,
                             int32_t aNumberOfCores,
                             uint32_t aMaxPayloadSize) = 0;
-  virtual GMPErr Encode(mozilla::GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
+  virtual GMPErr Encode(mozilla::GMPUnique<GMPVideoi420Frame>::Ptr aInputFrame,
                         const nsTArray<uint8_t>& aCodecSpecificInfo,
                         const nsTArray<GMPVideoFrameType>& aFrameTypes) = 0;
   virtual GMPErr SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT) = 0;
   virtual GMPErr SetRates(uint32_t aNewBitRate, uint32_t aFrameRate) = 0;
   virtual GMPErr SetPeriodicKeyFrames(bool aEnable) = 0;
   virtual const uint64_t ParentID() = 0;
 
   // Call to tell GMP/plugin the consumer will no longer use this
--- a/dom/media/mediasource/test/mochitest.ini
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -34,10 +34,12 @@ skip-if = (toolkit == 'android' || build
 [test_SeekableAfterEndOfStreamSplit.html]
 [test_SeekableBeforeEndOfStream.html]
 [test_SeekableBeforeEndOfStreamSplit.html]
 [test_SeekTwice_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
 [test_SetModeThrows.html]
 [test_SplitAppendDelay.html]
 [test_SplitAppend.html]
+[test_TimestampOffset_mp4.html]
+skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
 [test_WaitingOnMissingData.html]
  skip-if = android_version == '10' # bug 1115148 - frequent failures on Android 2.3
new file mode 100644
--- /dev/null
+++ b/dom/media/mediasource/test/test_TimestampOffset_mp4.html
@@ -0,0 +1,83 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>MSE: basic functionality</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <script type="text/javascript" src="mediasource.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+SimpleTest.waitForExplicitFinish();
+
+function range(start, end) {
+  var rv = [];
+  for (var i = start; i < end; ++i) {
+    rv.push(i);
+  }
+  return rv;
+}
+
+var eps = 0.01;
+runWithMSE(function(ms, el) {
+
+  once(ms, 'sourceopen').then(function() {
+    ok(true, "Receive a sourceopen event");
+    var audiosb = ms.addSourceBuffer("audio/mp4");
+    var videosb = ms.addSourceBuffer("video/mp4");
+    // We divide the video into 3 chunks:
+    // chunk 0: segments 1-4
+    // chunk 1: segments 5-8
+    // chunk 2: segments 9-13
+    // We then fill the timeline so that it seamlessly plays the chunks in order 0, 2, 1.
+    var vchunks = [ {start: 0, end: 3.2033}, { start: 3.2033, end: 6.4066}, { start: 6.4066, end: 10.01} ];
+    var firstvoffset = vchunks[2].end - vchunks[2].start; // Duration of chunk 2
+    var secondvoffset = -(vchunks[1].end - vchunks[1].start); // -(Duration of chunk 1)
+
+    fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
+    .then(fetchAndLoad.bind(null, videosb, 'bipbop/bipbop_video', range(1, 5), '.m4s'))
+    .then(function() {
+      is(videosb.buffered.length, 1, "No discontinuity");
+      isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "Chunk start");
+      isfuzzy(videosb.buffered.end(0), vchunks[0].end, eps, "Chunk end");
+      videosb.timestampOffset = firstvoffset;
+      return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 9), '.m4s');
+    })
+    .then(function(data) {
+      is(videosb.buffered.length, 2, "One discontinuity");
+      isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "First Chunk start");
+      isfuzzy(videosb.buffered.end(0), vchunks[0].end, eps, "First chunk end");
+      isfuzzy(videosb.buffered.start(1),  vchunks[1].start + firstvoffset, eps, "Second chunk start");
+      isfuzzy(videosb.buffered.end(1), vchunks[1].end + firstvoffset, eps, "Second chunk end");
+      videosb.timestampOffset = secondvoffset;
+      return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(9, 14), '.m4s');
+    })
+    .then(function() {
+      is(videosb.buffered.length, 1, "No discontinuity (end)");
+      isfuzzy(videosb.buffered.start(0), vchunks[0].start, eps, "Chunk start");
+      isfuzzy(videosb.buffered.end(0), vchunks[2].end, eps, "Chunk end");
+      audiosb.timestampOffset = 3;
+    }).then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', ['init'], '.mp4'))
+    .then(fetchAndLoad.bind(null, audiosb, 'bipbop/bipbop_audio', range(1, 12), '.m4s'))
+    .then(function() {
+      is(audiosb.buffered.length, 1, "No audio discontinuity");
+      isfuzzy(audiosb.buffered.start(0), 3, eps, "Audio starts at 3");
+
+      // Trim the rest of the audio.
+      ms.duration = videosb.buffered.end(0);
+      return Promise.all([audiosb.updating ? once(audiosb, 'updateend') : Promise.resolve(),
+                          videosb.updating ? once(videosb, 'updateend') : Promise.resolve()]);
+    }).then(function() {
+      ms.endOfStream();
+      once(el, 'ended').then(SimpleTest.finish.bind(SimpleTest));
+      el.play();
+    });
+  });
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/test/eme.js
+++ b/dom/media/test/eme.js
@@ -68,17 +68,17 @@ function TimeStamp(token) {
              (ms < 10 ? "  " : (ms < 100 ? " " : ""));
   return token ? (time + " " + token) : time;
 }
 
 function Log(token, msg) {
   info(TimeStamp(token) + " " + msg);
 }
 
-function UpdateSessionFunc(test, token, sessionType) {
+function UpdateSessionFunc(test, token, sessionType, resolve, reject) {
   return function(ev) {
     var msgStr = ArrayBufferToString(ev.message);
     var msg = JSON.parse(msgStr);
 
     Log(token, "got message from CDM: " + msgStr);
     is(msg.type, sessionType, TimeStamp(token) + " key session type should match");
     ok(msg.kids, TimeStamp(token) + " message event should contain key ID array");
 
@@ -105,17 +105,21 @@ function UpdateSessionFunc(test, token, 
     var update = JSON.stringify({
       "keys" : outKeys,
       "type" : msg.type
     });
     Log(token, "sending update message to CDM: " + update);
 
     ev.target.update(StringToArrayBuffer(update)).then(function() {
       Log(token, "MediaKeySession update ok!");
-    }, bail(token + " MediaKeySession update failed"));
+      resolve(ev.target);
+    }).catch(function(reason) {
+      bail(token + " MediaKeySession update failed")(reason);
+      reject();
+    });
   }
 }
 
 function MaybeCrossOriginURI(test, uri)
 {
   if (test.crossOrigin) {
     return "http://test2.mochi.test:8888/tests/dom/media/test/allowed.sjs?" + uri;
   } else {
@@ -218,36 +222,62 @@ function SetupEME(test, token, params)
   v.addEventListener("encrypted", function(ev) {
     Log(token, "got encrypted event");
     var options = [
       {
         initDataType: ev.initDataType,
         videoType: test.type,
       }
     ];
-    navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE, options)
-      .then(function(keySystemAccess) {
-        return keySystemAccess.createMediaKeys();
-      }, bail(token + " Failed to request key system access."))
+
+    function chain(promise, onReject) {
+      return promise.then(function(value) {
+        return Promise.resolve(value);
+      }).catch(function(reason) {
+        onReject(reason);
+        return Promise.reject();
+      })
+    }
 
-      .then(function(mediaKeys) {
-        Log(token, "created MediaKeys object ok");
-        mediaKeys.sessions = [];
-        return v.setMediaKeys(mediaKeys);
-      }, bail("failed to create MediaKeys object"))
+    var p = navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE, options);
+    var r = bail(token + " Failed to request key system access.");
+    chain(p, r)
+    .then(function(keySystemAccess) {
+      var p = keySystemAccess.createMediaKeys();
+      var r = bail(token +  " Failed to create MediaKeys object");
+      return chain(p, r);
+    })
+
+    .then(function(mediaKeys) {
+      Log(token, "created MediaKeys object ok");
+      mediaKeys.sessions = [];
+      var p = v.setMediaKeys(mediaKeys);
+      return chain(p, onSetKeysFail);
+    })
 
-      .then(function() {
-        Log(token, "set MediaKeys on <video> element ok");
-        var sessionType = (params && params.sessionType) ? params.sessionType : "temporary";
-        var session = v.mediaKeys.createSession(sessionType);
-        if (params && params.onsessioncreated) {
-          params.onsessioncreated(session);
-        }
-        session.addEventListener("message", UpdateSessionFunc(test, token, sessionType));
-        return session.generateRequest(ev.initDataType, ev.initData);
-      }, onSetKeysFail)
+    .then(function() {
+      Log(token, "set MediaKeys on <video> element ok");
+      var sessionType = (params && params.sessionType) ? params.sessionType : "temporary";
+      var session = v.mediaKeys.createSession(sessionType);
+      if (params && params.onsessioncreated) {
+        params.onsessioncreated(session);
+      }
 
-      .then(function() {
-        Log(token, "generated request");
-      }, bail(token + " Failed to request key system access2."));
+      return new Promise(function (resolve, reject) {
+        session.addEventListener("message", UpdateSessionFunc(test, token, sessionType, resolve, reject));
+        session.generateRequest(ev.initDataType, ev.initData).catch(function(reason) {
+          // Reject the promise if generateRequest() failed. Otherwise it will
+          // be resolve in UpdateSessionFunc().
+          bail(token + ": session.generateRequest failed")(reason);
+          reject();
+        });
+      });
+    })
+
+    .then(function(session) {
+      Log(token, ": session.generateRequest succeeded");
+      if (params && params.onsessionupdated) {
+        params.onsessionupdated(session);
+      }
+    });
   });
   return v;
 }
--- a/dom/media/test/test_eme_persistent_sessions.html
+++ b/dom/media/test/test_eme_persistent_sessions.html
@@ -25,109 +25,127 @@ function UsableKeyIdsMatch(usableKeyIds,
       return false;
     }
   }
   return true;
 }
 
 function AwaitAllKeysUsable(session, keys, token) {
   return new Promise(function(resolve, reject) {
-    function listener(event) {
+    function check() {
       var map = session.keyStatuses;
       var usableKeyIds = [];
       for (var [key, val] of map.entries()) {
         is(val, "usable", token + ": key status should be usable");
         usableKeyIds.push(key);
       }
       if (UsableKeyIdsMatch(usableKeyIds, keys)) {
-        Log(token, "resolving AwaitAllKeysUsable promise");
-        session.removeEventListener("keystatuseschange", listener);
+        session.removeEventListener("keystatuseschange", check);
         resolve();
       }
     }
-    session.addEventListener("keystatuseschange", listener);
+    session.addEventListener("keystatuseschange", check);
+    check(); // in case all keys are already usable
   });
 }
 
 function AwaitAllKeysNotUsable(session, token) {
   return new Promise(function(resolve, reject) {
-    function listener(event) {
+    function check() {
       var map = session.keyStatuses;
       if (map.size == 0) {
-        session.removeEventListener("keystatuseschange", listener);
+        session.removeEventListener("keystatuseschange", check);
         resolve();
       }
     }
-    session.addEventListener("keystatuseschange", listener);
+    session.addEventListener("keystatuseschange", check);
+    check(); // in case all keys are already removed
   });
 }
 
 function startTest(test, token)
 {
   manager.started(token);
 
   var recreatedSession; // will have remove() called on it.
 
   var keySystemAccess;
 
   var v = SetupEME(test, token,
     {
-      onsessioncreated: function(session) {
+      onsessionupdated: function(session) {
         Log(token, "Session created");
         var sessionId;
         initialSession = session;
 
         // Once the session has loaded and has all its keys usable, close
         // all sessions without calling remove() on them.
-        AwaitAllKeysUsable(session, test.keys, token).then(
-          function() {
-            sessionId = session.sessionId;
-            Log(token, "Closing session with id=" + sessionId);
-            session.close();
-          }
-        );
+        AwaitAllKeysUsable(session, test.keys, token)
+        .then(function() {
+          sessionId = session.sessionId;
+          Log(token, "Closing session with id=" + sessionId);
+          return session.close();
+        })
 
         // Once the session is closed, reload the MediaKeys and reload the session
-        session.closed.then(function() {
-          return navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE)
-        }, bail("close promise rejected"))
+        .then(function() {
+          return navigator.requestMediaKeySystemAccess(KEYSYSTEM_TYPE);
+        })
 
         .then(function(requestedKeySystemAccess) {
           keySystemAccess = requestedKeySystemAccess;
           return keySystemAccess.createMediaKeys();
-        }, bail(token + " Failed to request key system access."))
+        })
 
         .then(function(mediaKeys) {
           Log(token, "re-created MediaKeys object ok");
           recreatedSession = mediaKeys.createSession("persistent");
           Log(token, "Created recreatedSession, loading sessionId=" + sessionId);
-          return Promise.all([AwaitAllKeysUsable(recreatedSession, test.keys, token), recreatedSession.load(sessionId)]);
-        }, bail(token + " failed to create mediaKeys"))
+          return recreatedSession.load(sessionId);
+        })
+
+        .then(function(suceeded) {
+          if (suceeded) {
+            return Promise.resolve();
+          } else {
+            return Promise.reject("Fail to load recreatedSession, sessionId=" + sessionId);
+          }
+        })
+
+        .then(function() {
+          return AwaitAllKeysUsable(recreatedSession, test.keys, token);
+        })
 
         .then(function() {
           Log(token, "re-loaded persistent session, all keys still usable");
           return Promise.all([AwaitAllKeysNotUsable(recreatedSession, token), recreatedSession.remove()]);
-        }, bail(token + " failed to get reload session or keys"))
+        })
 
         .then(function() {
           Log(token, "removed session, all keys unusable.");
           // Attempt to recreate the session, the attempt should fail.
           return keySystemAccess.createMediaKeys();
-        }, bail(token + " failed to remove session"))
+        })
 
         .then(function(mediaKeys) {
           Log(token, "re-re-created MediaKeys object ok");
           // Trying to load the removed persistent session should fail.
           return mediaKeys.createSession("persistent").load(sessionId);
-        }, bail(token + " failed to create mediaKeys"))
+        })
 
         .then(function(suceeded) {
           is(suceeded, false, token + " we expect the third session creation to fail, as the session should have been removed.");
           manager.finished(token);
-        }, bail(token + " failure to load session."));
+        })
+
+        .catch(function(reason) {
+          // Catch rejections if any.
+          ok(false, token + " rejected, reason=" + reason);
+          manager.finished(token);
+        });
 
       },
       sessionType: "persistent",
     }
   );
 
   LoadTest(test, v, token);
 }
--- a/dom/media/test/test_eme_playback.html
+++ b/dom/media/test/test_eme_playback.html
@@ -83,17 +83,23 @@ function startTest(test, token)
       for (var kid in session.keyIdsReceived) {
         ok(session.keyIdsReceived[kid], TimeStamp(token) + " key with id " + kid + " was usable as expected");
       }
     }
 
     manager.finished(token);
    });
 
-  LoadTest(test, v, token).then(function(){v.play();}, bail(token + " failed to load"));
+  LoadTest(test, v, token)
+  .then(function() {
+    v.play();
+  }).catch(function() {
+    ok(false, token + " failed to load");
+    manager.finished(token);
+  });
 }
 
 function beginTest() {
   manager.runTests(gEMETests, startTest);
 }
 
 var prefs = [
   [ "media.mediasource.enabled", true ],
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -35,39 +35,39 @@ skip-if = (toolkit == 'gonk' && debug) #
 skip-if = (toolkit == 'gonk' && debug) # debug-only failure
 [test_getUserMedia_basicScreenshare.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' # no screenshare on b2g/android
 [test_getUserMedia_basicWindowshare.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' # no windowshare on b2g/android
 [test_getUserMedia_basicVideoAudio.html]
 skip-if = (toolkit == 'gonk' && debug) # debug-only failure, turned an intermittent (bug 962579) into a permanant orange
 [test_getUserMedia_constraints.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_callbacks.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_gumWithinGum.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_playAudioTwice.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_playVideoAudioTwice.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout # bug 926558, debug-only failure
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout # bug 926558, debug-only failure
 [test_getUserMedia_playVideoTwice.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_stopAudioStream.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_stopAudioStreamWithFollowupAudio.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_stopVideoAudioStream.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout # bug 926558, debug-only failure
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout # bug 926558, debug-only failure
 [test_getUserMedia_stopVideoAudioStreamWithFollowupVideoAudio.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_stopVideoStream.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_stopVideoStreamWithFollowupVideo.html]
-skip-if = toolkit == 'gonk' # Bug 1063290, intermittent timeout
+skip-if = toolkit == 'gonk' || toolkit == 'android' # Bug 1063290, intermittent timeout
 [test_getUserMedia_peerIdentity.html]
 skip-if = toolkit == 'gonk' # b2g(Bug 1021776, too --ing slow on b2g)
 [test_peerConnection_addCandidateInHaveLocalOffer.html]
 skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
 [test_peerConnection_basicAudio.html]
 skip-if = toolkit == 'gonk' # b2g (Bug 1059867)
 [test_peerConnection_basicAudioVideo.html]
 skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g)
--- a/dom/media/wave/WaveReader.cpp
+++ b/dom/media/wave/WaveReader.cpp
@@ -333,18 +333,18 @@ WaveReader::ReadAll(char* aBuf, int64_t 
 }
 
 bool
 WaveReader::LoadRIFFChunk()
 {
   char riffHeader[RIFF_INITIAL_SIZE];
   const char* p = riffHeader;
 
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() == 0,
-                    "LoadRIFFChunk called when resource in invalid state");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() == 0,
+             "LoadRIFFChunk called when resource in invalid state");
 
   if (!ReadAll(riffHeader, sizeof(riffHeader))) {
     return false;
   }
 
   static_assert(sizeof(uint32_t) * 3 <= RIFF_INITIAL_SIZE,
                 "Reads would overflow riffHeader buffer.");
   if (ReadUint32BE(&p) != RIFF_CHUNK_MAGIC) {
@@ -366,18 +366,18 @@ WaveReader::LoadRIFFChunk()
 bool
 WaveReader::LoadFormatChunk(uint32_t aChunkSize)
 {
   uint32_t rate, channels, frameSize, sampleFormat;
   char waveFormat[WAVE_FORMAT_CHUNK_SIZE];
   const char* p = waveFormat;
 
   // RIFF chunks are always word (two byte) aligned.
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
-                    "LoadFormatChunk called with unaligned resource");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0,
+             "LoadFormatChunk called with unaligned resource");
 
   if (!ReadAll(waveFormat, sizeof(waveFormat))) {
     return false;
   }
 
   static_assert(sizeof(uint16_t) +
                 sizeof(uint16_t) +
                 sizeof(uint32_t) +
@@ -428,18 +428,18 @@ WaveReader::LoadFormatChunk(uint32_t aCh
       nsAutoArrayPtr<char> chunkExtension(new char[extra]);
       if (!ReadAll(chunkExtension.get(), extra)) {
         return false;
       }
     }
   }
 
   // RIFF chunks are always word (two byte) aligned.
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
-                    "LoadFormatChunk left resource unaligned");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0,
+             "LoadFormatChunk left resource unaligned");
 
   // Make sure metadata is fairly sane.  The rate check is fairly arbitrary,
   // but the channels check is intentionally limited to mono or stereo
   // when the media is intended for direct playback because that's what the
   // audio backend currently supports.
   unsigned int actualFrameSize = (sampleFormat == 8 ? 1 : 2) * channels;
   if (rate < 100 || rate > 96000 ||
       (((channels < 1 || channels > MAX_CHANNELS) ||
@@ -462,49 +462,49 @@ WaveReader::LoadFormatChunk(uint32_t aCh
   }
   return true;
 }
 
 bool
 WaveReader::FindDataOffset(uint32_t aChunkSize)
 {
   // RIFF chunks are always word (two byte) aligned.
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
-                    "FindDataOffset called with unaligned resource");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0,
+             "FindDataOffset called with unaligned resource");
 
   int64_t offset = mDecoder->GetResource()->Tell();
   if (offset <= 0 || offset > UINT32_MAX) {
     NS_WARNING("PCM data offset out of range");
     return false;
   }
 
   ReentrantMonitorAutoEnter monitor(mDecoder->GetReentrantMonitor());
   mWaveLength = aChunkSize;
   mWavePCMOffset = uint32_t(offset);
   return true;
 }
 
 double
 WaveReader::BytesToTime(int64_t aBytes) const
 {
-  NS_ABORT_IF_FALSE(aBytes >= 0, "Must be >= 0");
+  MOZ_ASSERT(aBytes >= 0, "Must be >= 0");
   return float(aBytes) / mSampleRate / mFrameSize;
 }
 
 int64_t
 WaveReader::TimeToBytes(double aTime) const
 {
-  NS_ABORT_IF_FALSE(aTime >= 0.0f, "Must be >= 0");
+  MOZ_ASSERT(aTime >= 0.0f, "Must be >= 0");
   return RoundDownToFrame(int64_t(aTime * mSampleRate * mFrameSize));
 }
 
 int64_t
 WaveReader::RoundDownToFrame(int64_t aBytes) const
 {
-  NS_ABORT_IF_FALSE(aBytes >= 0, "Must be >= 0");
+  MOZ_ASSERT(aBytes >= 0, "Must be >= 0");
   return aBytes - (aBytes % mFrameSize);
 }
 
 int64_t
 WaveReader::GetDataLength()
 {
   int64_t length = mWaveLength;
   // If the decoder has a valid content length, and it's shorter than the
@@ -522,20 +522,20 @@ int64_t
 WaveReader::GetPosition()
 {
   return mDecoder->GetResource()->Tell();
 }
 
 bool
 WaveReader::GetNextChunk(uint32_t* aChunk, uint32_t* aChunkSize)
 {
-  NS_ABORT_IF_FALSE(aChunk, "Must have aChunk");
-  NS_ABORT_IF_FALSE(aChunkSize, "Must have aChunkSize");
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
-                    "GetNextChunk called with unaligned resource");
+  MOZ_ASSERT(aChunk, "Must have aChunk");
+  MOZ_ASSERT(aChunkSize, "Must have aChunkSize");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0,
+             "GetNextChunk called with unaligned resource");
 
   char chunkHeader[CHUNK_HEADER_SIZE];
   const char* p = chunkHeader;
 
   if (!ReadAll(chunkHeader, sizeof(chunkHeader))) {
     return false;
   }
 
@@ -547,18 +547,18 @@ WaveReader::GetNextChunk(uint32_t* aChun
   return true;
 }
 
 bool
 WaveReader::LoadListChunk(uint32_t aChunkSize,
                           nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags)
 {
   // List chunks are always word (two byte) aligned.
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
-                    "LoadListChunk called with unaligned resource");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0,
+             "LoadListChunk called with unaligned resource");
 
   static const unsigned int MAX_CHUNK_SIZE = 1 << 16;
   static_assert(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char),
                 "MAX_CHUNK_SIZE too large for enumerator.");
 
   if (aChunkSize > MAX_CHUNK_SIZE || aChunkSize < 4) {
     return false;
   }
@@ -623,18 +623,18 @@ WaveReader::LoadListChunk(uint32_t aChun
 
   return true;
 }
 
 bool
 WaveReader::LoadAllChunks(nsAutoPtr<dom::HTMLMediaElement::MetadataTags> &aTags)
 {
   // Chunks are always word (two byte) aligned.
-  NS_ABORT_IF_FALSE(mDecoder->GetResource()->Tell() % 2 == 0,
-                    "LoadAllChunks called with unaligned resource");
+  MOZ_ASSERT(mDecoder->GetResource()->Tell() % 2 == 0,
+             "LoadAllChunks called with unaligned resource");
 
   bool loadFormatChunk = false;
   bool findDataOffset = false;
 
   for (;;) {
     static const unsigned int CHUNK_HEADER_SIZE = 8;
     char chunkHeader[CHUNK_HEADER_SIZE];
     const char* p = chunkHeader;
--- a/dom/plugins/base/nsNPAPIPlugin.cpp
+++ b/dom/plugins/base/nsNPAPIPlugin.cpp
@@ -1503,18 +1503,19 @@ bool
 
   JS::Rooted<JSObject*> obj(cx, nsNPObjWrapper::GetNewOrUsed(npp, cx, npobj));
 
   if (!obj) {
     return false;
   }
 
   obj = JS_ObjectToInnerObject(cx, obj);
-  NS_ABORT_IF_FALSE(obj,
-    "JS_ObjectToInnerObject should never return null with non-null input.");
+  MOZ_ASSERT(obj,
+             "JS_ObjectToInnerObject should never return null with non-null "
+             "input.");
 
   if (result) {
     // Initialize the out param to void
     VOID_TO_NPVARIANT(*result);
   }
 
   if (!script || !script->UTF8Length || !script->UTF8Characters) {
     // Nothing to evaluate.
--- a/dom/plugins/ipc/PluginAsyncSurrogate.cpp
+++ b/dom/plugins/ipc/PluginAsyncSurrogate.cpp
@@ -598,20 +598,25 @@ PluginAsyncSurrogate::GetPropertyHelper(
     return false;
   }
 
   RecursionGuard guard;
   if (guard.IsRecursive()) {
     return false;
   }
 
-  WaitForInit();
+  if (!WaitForInit()) {
+    return false;
+  }
 
   AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject);
   NPObject* realObject = object->GetRealObject();
+  if (!realObject) {
+    return false;
+  }
   if (realObject->_class != PluginScriptableObjectParent::GetClass()) {
     NS_ERROR("Don't know what kind of object this is!");
     return false;
   }
 
   PluginScriptableObjectParent* actor =
     static_cast<ParentNPObject*>(realObject)->parent;
   bool success = actor->GetPropertyHelper(aName, aHasProperty, aHasMethod, aResult);
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2660,18 +2660,18 @@ PluginInstanceChild::DoAsyncSetWindow(co
     if (!mAccumulatedInvalidRect.IsEmpty()) {
         AsyncShowPluginFrame();
     }
 }
 
 bool
 PluginInstanceChild::CreateOptSurface(void)
 {
-    NS_ABORT_IF_FALSE(mSurfaceType != gfxSurfaceType::Max,
-                      "Need a valid surface type here");
+    MOZ_ASSERT(mSurfaceType != gfxSurfaceType::Max,
+               "Need a valid surface type here");
     NS_ASSERTION(!mCurrentSurface, "mCurrentSurfaceActor can get out of sync.");
 
     nsRefPtr<gfxASurface> retsurf;
     // Use an opaque surface unless we're transparent and *don't* have
     // a background to source from.
     gfxImageFormat format =
         (mIsTransparent && !mBackground) ? gfxImageFormat::ARGB32 :
                                            gfxImageFormat::RGB24;
@@ -3090,18 +3090,18 @@ PluginInstanceChild::PaintRectToSurface(
         dt->CopySurface(surface, ToIntRect(aRect), ToIntPoint(aRect.TopLeft()));
     }
 }
 
 void
 PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
                                                   gfxASurface* aSurface)
 {
-    NS_ABORT_IF_FALSE(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA,
-                      "Refusing to pointlessly recover alpha");
+    MOZ_ASSERT(aSurface->GetContentType() == gfxContentType::COLOR_ALPHA,
+               "Refusing to pointlessly recover alpha");
 
     nsIntRect rect(aRect);
     // If |aSurface| can be used to paint and can have alpha values
     // recovered directly to it, do that to save a tmp surface and
     // copy.
     bool useSurfaceSubimageForBlack = false;
     if (gfxSurfaceType::Image == aSurface->GetType()) {
         gfxImageSurface* surfaceAsImage =
@@ -3170,17 +3170,17 @@ PluginInstanceChild::PaintRectWithAlphaE
                                          gfxImageFormat::ARGB32);
     }
 
     // Paint onto black background
     blackImage->SetDeviceOffset(deviceOffset);
     PaintRectToSurface(rect, blackImage, gfxRGBA(0.0, 0.0, 0.0));
 #endif
 
-    NS_ABORT_IF_FALSE(whiteImage && blackImage, "Didn't paint enough!");
+    MOZ_ASSERT(whiteImage && blackImage, "Didn't paint enough!");
 
     // Extract alpha from black and white image and store to black
     // image
     if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
         return;
     }
 
     // If we had to use a temporary black surface, copy the pixels
@@ -3534,17 +3534,17 @@ PluginInstanceChild::InvalidateRect(NPRe
     // before their first SetWindow().
     SendNPN_InvalidateRect(*aInvalidRect);
 }
 
 bool
 PluginInstanceChild::RecvUpdateBackground(const SurfaceDescriptor& aBackground,
                                           const nsIntRect& aRect)
 {
-    NS_ABORT_IF_FALSE(mIsTransparent, "Only transparent plugins use backgrounds");
+    MOZ_ASSERT(mIsTransparent, "Only transparent plugins use backgrounds");
 
     if (!mBackground) {
         // XXX refactor me
         switch (aBackground.type()) {
 #ifdef MOZ_X11
         case SurfaceDescriptor::TSurfaceDescriptorX11: {
             mBackground = aBackground.get_SurfaceDescriptorX11().OpenForeign();
             break;
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -740,17 +740,17 @@ PluginInstanceParent::ContentsScaleFacto
 
 nsresult
 PluginInstanceParent::SetBackgroundUnknown()
 {
     PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this));
 
     if (mBackground) {
         DestroyBackground();
-        NS_ABORT_IF_FALSE(!mBackground, "Background not destroyed");
+        MOZ_ASSERT(!mBackground, "Background not destroyed");
     }
 
     return NS_OK;
 }
 
 nsresult
 PluginInstanceParent::BeginUpdateBackground(const nsIntRect& aRect,
                                             gfxContext** aCtx)
@@ -759,28 +759,28 @@ PluginInstanceParent::BeginUpdateBackgro
         ("[InstanceParent][%p] BeginUpdateBackground for <x=%d,y=%d, w=%d,h=%d>",
          this, aRect.x, aRect.y, aRect.width, aRect.height));
 
     if (!mBackground) {
         // XXX if we failed to create a background surface on one
         // update, there's no guarantee that later updates will be for
         // the entire background area until successful.  We might want
         // to fix that eventually.
-        NS_ABORT_IF_FALSE(aRect.TopLeft() == nsIntPoint(0, 0),
-                          "Expecting rect for whole frame");
+        MOZ_ASSERT(aRect.TopLeft() == nsIntPoint(0, 0),
+                   "Expecting rect for whole frame");
         if (!CreateBackground(aRect.Size())) {
             *aCtx = nullptr;
             return NS_OK;
         }
     }
 
     gfxIntSize sz = mBackground->GetSize();
 #ifdef DEBUG
-    NS_ABORT_IF_FALSE(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect),
-                      "Update outside of background area");
+    MOZ_ASSERT(nsIntRect(0, 0, sz.width, sz.height).Contains(aRect),
+               "Update outside of background area");
 #endif
 
     RefPtr<gfx::DrawTarget> dt = gfxPlatform::GetPlatform()->
       CreateDrawTargetForSurface(mBackground, gfx::IntSize(sz.width, sz.height));
     nsRefPtr<gfxContext> ctx = new gfxContext(dt);
     ctx.forget(aCtx);
 
     return NS_OK;
@@ -816,17 +816,17 @@ PluginAsyncSurrogate*
 PluginInstanceParent::GetAsyncSurrogate()
 {
     return mSurrogate;
 }
 
 bool
 PluginInstanceParent::CreateBackground(const nsIntSize& aSize)
 {
-    NS_ABORT_IF_FALSE(!mBackground, "Already have a background");
+    MOZ_ASSERT(!mBackground, "Already have a background");
 
     // XXX refactor me
 
 #if defined(MOZ_X11)
     Screen* screen = DefaultScreenOfDisplay(DefaultXDisplay());
     Visual* visual = DefaultVisualOfScreen(screen);
     mBackground = gfxXlibSurface::Create(screen, visual,
                                          gfxIntSize(aSize.width, aSize.height));
@@ -861,28 +861,28 @@ PluginInstanceParent::DestroyBackground(
     // If this fails, there's no problem: |bd| will be destroyed along
     // with the old background surface.
     unused << SendPPluginBackgroundDestroyerConstructor(pbd);
 }
 
 mozilla::plugins::SurfaceDescriptor
 PluginInstanceParent::BackgroundDescriptor()
 {
-    NS_ABORT_IF_FALSE(mBackground, "Need a background here");
+    MOZ_ASSERT(mBackground, "Need a background here");
 
     // XXX refactor me
 
 #ifdef MOZ_X11
     gfxXlibSurface* xsurf = static_cast<gfxXlibSurface*>(mBackground.get());
     return SurfaceDescriptorX11(xsurf);
 #endif
 
 #ifdef XP_WIN
-    NS_ABORT_IF_FALSE(gfxSharedImageSurface::IsSharedImage(mBackground),
-                      "Expected shared image surface");
+    MOZ_ASSERT(gfxSharedImageSurface::IsSharedImage(mBackground),
+               "Expected shared image surface");
     gfxSharedImageSurface* shmem =
         static_cast<gfxSharedImageSurface*>(mBackground.get());
     return shmem->GetShmem();
 #endif
 
     // If this is ever used, which it shouldn't be, it will trigger a
     // hard assertion in IPDL-generated code.
     return mozilla::plugins::SurfaceDescriptor();
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -511,20 +511,20 @@ static const gint kBrowserEventPriority 
 static const guint kBrowserEventIntervalMs = 10;
 
 // static
 gboolean
 PluginModuleChild::DetectNestedEventLoop(gpointer data)
 {
     PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
 
-    NS_ABORT_IF_FALSE(0 != pmc->mNestedLoopTimerId,
-                      "callback after descheduling");
-    NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
-                      "not canceled before returning to main event loop!");
+    MOZ_ASSERT(0 != pmc->mNestedLoopTimerId,
+               "callback after descheduling");
+    MOZ_ASSERT(pmc->mTopLoopDepth < g_main_depth(),
+               "not canceled before returning to main event loop!");
 
     PLUGIN_LOG_DEBUG(("Detected nested glib event loop"));
 
     // just detected a nested loop; start a timer that will
     // periodically rpc-call back into the browser and process some
     // events
     pmc->mNestedLoopTimerId =
         g_timeout_add_full(kBrowserEventPriority,
@@ -537,68 +537,68 @@ PluginModuleChild::DetectNestedEventLoop
 }
 
 // static
 gboolean
 PluginModuleChild::ProcessBrowserEvents(gpointer data)
 {
     PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
 
-    NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
-                      "not canceled before returning to main event loop!");
+    MOZ_ASSERT(pmc->mTopLoopDepth < g_main_depth(),
+               "not canceled before returning to main event loop!");
 
     pmc->CallProcessSomeEvents();
 
     return TRUE;
 }
 
 void
 PluginModuleChild::EnteredCxxStack()
 {
-    NS_ABORT_IF_FALSE(0 == mNestedLoopTimerId,
-                      "previous timer not descheduled");
+    MOZ_ASSERT(0 == mNestedLoopTimerId,
+               "previous timer not descheduled");
 
     mNestedLoopTimerId =
         g_timeout_add_full(kNestedLoopDetectorPriority,
                            kNestedLoopDetectorIntervalMs,
                            PluginModuleChild::DetectNestedEventLoop,
                            this,
                            nullptr);
 
 #ifdef DEBUG
     mTopLoopDepth = g_main_depth();
 #endif
 }
 
 void
 PluginModuleChild::ExitedCxxStack()
 {
-    NS_ABORT_IF_FALSE(0 < mNestedLoopTimerId,
-                      "nested loop timeout not scheduled");
+    MOZ_ASSERT(0 < mNestedLoopTimerId,
+               "nested loop timeout not scheduled");
 
     g_source_remove(mNestedLoopTimerId);
     mNestedLoopTimerId = 0;
 }
 #elif defined (MOZ_WIDGET_QT)
 
 void
 PluginModuleChild::EnteredCxxStack()
 {
-    NS_ABORT_IF_FALSE(mNestedLoopTimerObject == nullptr,
-                      "previous timer not descheduled");
+    MOZ_ASSERT(mNestedLoopTimerObject == nullptr,
+               "previous timer not descheduled");
     mNestedLoopTimerObject = new NestedLoopTimer(this);
     QTimer::singleShot(kNestedLoopDetectorIntervalMs,
                        mNestedLoopTimerObject, SLOT(timeOut()));
 }
 
 void
 PluginModuleChild::ExitedCxxStack()
 {
-    NS_ABORT_IF_FALSE(mNestedLoopTimerObject != nullptr,
-                      "nested loop timeout not scheduled");
+    MOZ_ASSERT(mNestedLoopTimerObject != nullptr,
+               "nested loop timeout not scheduled");
     delete mNestedLoopTimerObject;
     mNestedLoopTimerObject = nullptr;
 }
 
 #endif
 
 bool
 PluginModuleChild::RecvSetParentHangTimeout(const uint32_t& aSeconds)
@@ -631,18 +631,18 @@ PluginModuleChild::InitGraphics()
     // GtkPlug is a static class so will leak anyway but this ref makes sure.
     gpointer gtk_plug_class = g_type_class_ref(GTK_TYPE_PLUG);
 
     // The dispose method is a good place to hook into the destruction process
     // because the reference count should be 1 the last time dispose is
     // called.  (Toggle references wouldn't detect if the reference count
     // might be higher.)
     GObjectDisposeFn* dispose = &G_OBJECT_CLASS(gtk_plug_class)->dispose;
-    NS_ABORT_IF_FALSE(*dispose != wrap_gtk_plug_dispose,
-                      "InitGraphics called twice");
+    MOZ_ASSERT(*dispose != wrap_gtk_plug_dispose,
+               "InitGraphics called twice");
     real_gtk_plug_dispose = *dispose;
     *dispose = wrap_gtk_plug_dispose;
 
     // If we ever stop setting GDK_NATIVE_WINDOWS, we'll also need to
     // gtk_widget_add_events GDK_SCROLL_MASK or GDK client-side windows will
     // not tell us about the scroll events that it intercepts.  With native
     // windows, this is called when GDK intercepts the events; if GDK doesn't
     // intercept the events, then the X server will instead send them directly
@@ -1083,17 +1083,17 @@ const NPNetscapeFuncs PluginModuleChild:
     nullptr, // handleevent, unimplemented
     nullptr, // unfocusinstance, unimplemented
     mozilla::plugins::child::_urlredirectresponse
 };
 
 PluginInstanceChild*
 InstCast(NPP aNPP)
 {
-    NS_ABORT_IF_FALSE(!!(aNPP->ndata), "nil instance");
+    MOZ_ASSERT(!!(aNPP->ndata), "nil instance");
     return static_cast<PluginInstanceChild*>(aNPP->ndata);
 }
 
 namespace mozilla {
 namespace plugins {
 namespace child {
 
 NPError
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -1507,18 +1507,18 @@ PluginModuleParent::NPP_SetValue(NPP ins
 }
 
 bool
 PluginModuleParent::RecvBackUpXResources(const FileDescriptor& aXSocketFd)
 {
 #ifndef MOZ_X11
     NS_RUNTIMEABORT("This message only makes sense on X11 platforms");
 #else
-    NS_ABORT_IF_FALSE(0 > mPluginXSocketFdDup.get(),
-                      "Already backed up X resources??");
+    MOZ_ASSERT(0 > mPluginXSocketFdDup.get(),
+               "Already backed up X resources??");
     mPluginXSocketFdDup.forget();
     if (aXSocketFd.IsValid()) {
       mPluginXSocketFdDup.reset(aXSocketFd.PlatformHandle());
     }
 #endif
     return true;
 }
 
@@ -1923,19 +1923,17 @@ bool
 PluginModuleParent::RecvNP_InitializeResult(const NPError& aError)
 {
     if (aError != NPERR_NO_ERROR) {
         OnInitFailure();
         return true;
     }
 
     if (mIsStartingAsync) {
-#if defined(XP_WIN)
         SetPluginFuncs(mNPPIface);
-#endif
         InitAsyncSurrogates();
     }
 
     mNPInitialized = true;
     return true;
 }
 
 bool
--- a/dom/plugins/ipc/PluginProcessChild.cpp
+++ b/dom/plugins/ipc/PluginProcessChild.cpp
@@ -104,24 +104,24 @@ PluginProcessChild::Init()
 
     std::string pluginFilename;
 
 #if defined(OS_POSIX)
     // NB: need to be very careful in ensuring that the first arg
     // (after the binary name) here is indeed the plugin module path.
     // Keep in sync with dom/plugins/PluginModuleParent.
     std::vector<std::string> values = CommandLine::ForCurrentProcess()->argv();
-    NS_ABORT_IF_FALSE(values.size() >= 2, "not enough args");
+    MOZ_ASSERT(values.size() >= 2, "not enough args");
 
     pluginFilename = UnmungePluginDsoPath(values[1]);
 
 #elif defined(OS_WIN)
     std::vector<std::wstring> values =
         CommandLine::ForCurrentProcess()->GetLooseValues();
-    NS_ABORT_IF_FALSE(values.size() >= 1, "not enough loose args");
+    MOZ_ASSERT(values.size() >= 1, "not enough loose args");
 
     if (ShouldProtectPluginCurrentDirectory(values[0].c_str())) {
         SanitizeEnvironmentVariables();
         SetDllDirectory(L"");
     }
 
     pluginFilename = WideToUTF8(values[0]);
 
--- a/dom/smil/SMILIntegerType.cpp
+++ b/dom/smil/SMILIntegerType.cpp
@@ -8,17 +8,17 @@
 #include "nsDebug.h"
 #include <math.h>
 
 namespace mozilla {
 
 void
 SMILIntegerType::Init(nsSMILValue& aValue) const
 {
-  NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
+  MOZ_ASSERT(aValue.IsNull(), "Unexpected value type");
   aValue.mU.mInt = 0;
   aValue.mType = this;
 }
 
 void
 SMILIntegerType::Destroy(nsSMILValue& aValue) const
 {
   NS_PRECONDITION(aValue.mType == this, "Unexpected SMIL value");
--- a/dom/smil/nsSMILAnimationController.cpp
+++ b/dom/smil/nsSMILAnimationController.cpp
@@ -27,17 +27,17 @@ using namespace mozilla::dom;
 nsSMILAnimationController::nsSMILAnimationController(nsIDocument* aDoc)
   : mAvgTimeBetweenSamples(0),
     mResampleNeeded(false),
     mDeferredStartSampling(false),
     mRunningSample(false),
     mRegisteredWithRefreshDriver(false),
     mDocument(aDoc)
 {
-  NS_ABORT_IF_FALSE(aDoc, "need a non-null document");
+  MOZ_ASSERT(aDoc, "need a non-null document");
 
   nsRefreshDriver* refreshDriver = GetRefreshDriver();
   if (refreshDriver) {
     mStartTime = refreshDriver->MostRecentRefresh();
   } else {
     mStartTime = mozilla::TimeStamp::Now();
   }
   mCurrentSampleTime = mStartTime;
@@ -52,19 +52,19 @@ nsSMILAnimationController::~nsSMILAnimat
                " elements when it dies");
   NS_ASSERTION(!mRegisteredWithRefreshDriver,
                "Leaving stale entry in refresh driver's observer list");
 }
 
 void
 nsSMILAnimationController::Disconnect()
 {
-  NS_ABORT_IF_FALSE(mDocument, "disconnecting when we weren't connected...?");
-  NS_ABORT_IF_FALSE(mRefCnt.get() == 1,
-                    "Expecting to disconnect when doc is sole remaining owner");
+  MOZ_ASSERT(mDocument, "disconnecting when we weren't connected...?");
+  MOZ_ASSERT(mRefCnt.get() == 1,
+             "Expecting to disconnect when doc is sole remaining owner");
   NS_ASSERTION(mPauseState & nsSMILTimeContainer::PAUSE_PAGEHIDE,
                "Expecting to be paused for pagehide before disconnect");
 
   StopSampling(GetRefreshDriver());
 
   mDocument = nullptr; // (raw pointer)
 }
 
@@ -165,19 +165,19 @@ void
 nsSMILAnimationController::RegisterAnimationElement(
                                   SVGAnimationElement* aAnimationElement)
 {
   mAnimationElementTable.PutEntry(aAnimationElement);
   if (mDeferredStartSampling) {
     mDeferredStartSampling = false;
     if (mChildContainerTable.Count()) {
       // mAnimationElementTable was empty, but now we've added its 1st element
-      NS_ABORT_IF_FALSE(mAnimationElementTable.Count() == 1,
-                        "we shouldn't have deferred sampling if we already had "
-                        "animations registered");
+      MOZ_ASSERT(mAnimationElementTable.Count() == 1,
+                 "we shouldn't have deferred sampling if we already had "
+                 "animations registered");
       StartSampling(GetRefreshDriver());
       Sample(); // Run the first sample manually
     } // else, don't sample until a time container is registered (via AddChild)
   }
 }
 
 void
 nsSMILAnimationController::UnregisterAnimationElement(
@@ -260,36 +260,34 @@ void
 nsSMILAnimationController::StartSampling(nsRefreshDriver* aRefreshDriver)
 {
   NS_ASSERTION(mPauseState == 0, "Starting sampling but controller is paused");
   NS_ASSERTION(!mDeferredStartSampling,
                "Started sampling but the deferred start flag is still set");
   if (aRefreshDriver) {
     MOZ_ASSERT(!mRegisteredWithRefreshDriver,
                "Redundantly registering with refresh driver");
-    NS_ABORT_IF_FALSE(!GetRefreshDriver() ||
-                      aRefreshDriver == GetRefreshDriver(),
-                      "Starting sampling with wrong refresh driver");
+    MOZ_ASSERT(!GetRefreshDriver() || aRefreshDriver == GetRefreshDriver(),
+               "Starting sampling with wrong refresh driver");
     // We're effectively resuming from a pause so update our current sample time
     // or else it will confuse our "average time between samples" calculations.
     mCurrentSampleTime = mozilla::TimeStamp::Now();
     aRefreshDriver->AddRefreshObserver(this, Flush_Style);
     mRegisteredWithRefreshDriver = true;
   }
 }
 
 void
 nsSMILAnimationController::StopSampling(nsRefreshDriver* aRefreshDriver)
 {
   if (aRefreshDriver && mRegisteredWithRefreshDriver) {
     // NOTE: The document might already have been detached from its PresContext
     // (and RefreshDriver), which would make GetRefreshDriver() return null.
-    NS_ABORT_IF_FALSE(!GetRefreshDriver() ||
-                      aRefreshDriver == GetRefreshDriver(),
-                      "Stopping sampling with wrong refresh driver");
+    MOZ_ASSERT(!GetRefreshDriver() || aRefreshDriver == GetRefreshDriver(),
+               "Stopping sampling with wrong refresh driver");
     aRefreshDriver->RemoveRefreshObserver(this, Flush_Style);
     mRegisteredWithRefreshDriver = false;
   }
 }
 
 void
 nsSMILAnimationController::MaybeStartSampling(nsRefreshDriver* aRefreshDriver)
 {
@@ -477,18 +475,18 @@ nsSMILAnimationController::RewindElement
   mAnimationElementTable.EnumerateEntries(RewindAnimation, nullptr);
   mChildContainerTable.EnumerateEntries(ClearRewindNeeded, nullptr);
 }
 
 /*static*/ PLDHashOperator
 nsSMILAnimationController::RewindNeeded(TimeContainerPtrKey* aKey,
                                         void* aData)
 {
-  NS_ABORT_IF_FALSE(aData,
-      "Null data pointer during time container enumeration");
+  MOZ_ASSERT(aData,
+             "Null data pointer during time container enumeration");
   bool* rewindNeeded = static_cast<bool*>(aData);
 
   nsSMILTimeContainer* container = aKey->GetKey();
   if (container->NeedsRewind()) {
     *rewindNeeded = true;
     return PL_DHASH_STOP;
   }
 
@@ -564,17 +562,17 @@ nsSMILAnimationController::DoMilestoneSa
     //
     // Because we're only performing this clamping at the last moment, the
     // animations will still all get sampled in the correct order and
     // dependencies will be appropriately resolved.
     sampleTime = std::max(nextMilestone.mTime, sampleTime);
 
     for (uint32_t i = 0; i < length; ++i) {
       SVGAnimationElement* elem = params.mElements[i].get();
-      NS_ABORT_IF_FALSE(elem, "nullptr animation element in list");
+      MOZ_ASSERT(elem, "nullptr animation element in list");
       nsSMILTimeContainer* container = elem->GetTimeContainer();
       if (!container)
         // The container may be nullptr if the element has been detached from its
         // parent since registering a milestone.
         continue;
 
       nsSMILTimeValue containerTimeValue =
         container->ParentToContainerTime(sampleTime);
@@ -592,20 +590,20 @@ nsSMILAnimationController::DoMilestoneSa
     }
   }
 }
 
 /*static*/ PLDHashOperator
 nsSMILAnimationController::GetNextMilestone(TimeContainerPtrKey* aKey,
                                             void* aData)
 {
-  NS_ABORT_IF_FALSE(aKey, "Null hash key for time container hash table");
-  NS_ABORT_IF_FALSE(aKey->GetKey(), "Null time container key in hash table");
-  NS_ABORT_IF_FALSE(aData,
-      "Null data pointer during time container enumeration");
+  MOZ_ASSERT(aKey, "Null hash key for time container hash table");
+  MOZ_ASSERT(aKey->GetKey(), "Null time container key in hash table");
+  MOZ_ASSERT(aData,
+             "Null data pointer during time container enumeration");
 
   nsSMILMilestone* nextMilestone = static_cast<nsSMILMilestone*>(aData);
 
   nsSMILTimeContainer* container = aKey->GetKey();
   if (container->IsPausedByType(nsSMILTimeContainer::PAUSE_BEGIN))
     return PL_DHASH_NEXT;
 
   nsSMILMilestone thisMilestone;
@@ -617,20 +615,20 @@ nsSMILAnimationController::GetNextMilest
 
   return PL_DHASH_NEXT;
 }
 
 /*static*/ PLDHashOperator
 nsSMILAnimationController::GetMilestoneElements(TimeContainerPtrKey* aKey,
                                                 void* aData)
 {
-  NS_ABORT_IF_FALSE(aKey, "Null hash key for time container hash table");
-  NS_ABORT_IF_FALSE(aKey->GetKey(), "Null time container key in hash table");
-  NS_ABORT_IF_FALSE(aData,
-      "Null data pointer during time container enumeration");
+  MOZ_ASSERT(aKey, "Null hash key for time container hash table");
+  MOZ_ASSERT(aKey->GetKey(), "Null time container key in hash table");
+  MOZ_ASSERT(aData,
+             "Null data pointer during time container enumeration");
 
   GetMilestoneElementsParams* params =
     static_cast<GetMilestoneElementsParams*>(aData);
 
   nsSMILTimeContainer* container = aKey->GetKey();
   if (container->IsPausedByType(nsSMILTimeContainer::PAUSE_BEGIN))
     return PL_DHASH_NEXT;
 
@@ -697,18 +695,18 @@ nsSMILAnimationController::SampleTimedEl
   // Instead we build up a hashmap of active time containers during the previous
   // step (SampleTimeContainer) and then test here if the container for this
   // timed element is in the list.
   if (!aActiveContainers->GetEntry(timeContainer))
     return;
 
   nsSMILTime containerTime = timeContainer->GetCurrentTime();
 
-  NS_ABORT_IF_FALSE(!timeContainer->IsSeeking(),
-      "Doing a regular sample but the time container is still seeking");
+  MOZ_ASSERT(!timeContainer->IsSeeking(),
+             "Doing a regular sample but the time container is still seeking");
   aElement->TimedElement().SampleAt(containerTime);
 }
 
 /*static*/ void
 nsSMILAnimationController::AddAnimationToCompositorTable(
   SVGAnimationElement* aElement, nsSMILCompositorTable* aCompositorTable)
 {
   // Add a compositor to the hash table if there's not already one there
--- a/dom/smil/nsSMILAnimationFunction.cpp
+++ b/dom/smil/nsSMILAnimationFunction.cpp
@@ -215,20 +215,20 @@ nsSMILAnimationFunction::ComposeResult(c
     return;
 
   // Check that we have the right number of keySplines and keyTimes
   CheckValueListDependentAttrs(values.Length());
   if (mErrorFlags != 0)
     return;
 
   // If this interval is active, we must have a non-negative mSampleTime
-  NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive,
-      "Negative sample time for active animation");
-  NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mLastValue,
-      "Unresolved simple duration for active or frozen animation");
+  MOZ_ASSERT(mSampleTime >= 0 || !mIsActive,
+             "Negative sample time for active animation");
+  MOZ_ASSERT(mSimpleDuration.IsResolved() || mLastValue,
+             "Unresolved simple duration for active or frozen animation");
 
   // If we want to add but don't have a base value then just fail outright.
   // This can happen when we skipped getting the base value because there's an
   // animation function in the sandwich that should replace it but that function
   // failed unexpectedly.
   bool isAdditive = IsAdditive();
   if (isAdditive && aResult.IsNull())
     return;
@@ -298,18 +298,18 @@ nsSMILAnimationFunction::CompareTo(const
     aOther->mAnimationElement->TimedElement();
   if (thisTimedElement.IsTimeDependent(otherTimedElement))
     return 1;
   if (otherTimedElement.IsTimeDependent(thisTimedElement))
     return -1;
 
   // Animations that appear later in the document sort after those earlier in
   // the document
-  NS_ABORT_IF_FALSE(mAnimationElement != aOther->mAnimationElement,
-      "Two animations cannot have the same animation content element!");
+  MOZ_ASSERT(mAnimationElement != aOther->mAnimationElement,
+             "Two animations cannot have the same animation content element!");
 
   return (nsContentUtils::PositionIsBefore(mAnimationElement, aOther->mAnimationElement))
           ? -1 : 1;
 }
 
 bool
 nsSMILAnimationFunction::WillReplace() const
 {
@@ -363,18 +363,18 @@ nsSMILAnimationFunction::InterpolateResu
   // If we have an indefinite simple duration, just set the progress to be
   // 0 which will give us the expected behaviour of the animation being fixed at
   // its starting point.
   double simpleProgress = 0.0;
 
   if (mSimpleDuration.IsDefinite()) {
     nsSMILTime dur = mSimpleDuration.GetMillis();
 
-    NS_ABORT_IF_FALSE(dur >= 0, "Simple duration should not be negative");
-    NS_ABORT_IF_FALSE(mSampleTime >= 0, "Sample time should not be negative");
+    MOZ_ASSERT(dur >= 0, "Simple duration should not be negative");
+    MOZ_ASSERT(mSampleTime >= 0, "Sample time should not be negative");
 
     if (mSampleTime >= dur || mSampleTime < 0) {
       NS_ERROR("Animation sampled outside interval");
       return NS_ERROR_FAILURE;
     }
 
     if (dur > 0) {
       simpleProgress = (double)mSampleTime / dur;
@@ -383,17 +383,17 @@ nsSMILAnimationFunction::InterpolateResu
 
   nsresult rv = NS_OK;
   nsSMILCalcMode calcMode = GetCalcMode();
   if (calcMode != CALC_DISCRETE) {
     // Get the normalised progress between adjacent values
     const nsSMILValue* from = nullptr;
     const nsSMILValue* to = nullptr;
     // Init to -1 to make sure that if we ever forget to set this, the
-    // NS_ABORT_IF_FALSE that tests that intervalProgress is in range will fail.
+    // MOZ_ASSERT that tests that intervalProgress is in range will fail.
     double intervalProgress = -1.f;
     if (IsToAnimation()) {
       from = &aBaseValue;
       to = &aValues[0];
       if (calcMode == CALC_PACED) {
         // Note: key[Times/Splines/Points] are ignored for calcMode="paced"
         intervalProgress = simpleProgress;
       } else {
@@ -416,20 +416,20 @@ nsSMILAnimationFunction::InterpolateResu
       from = &aValues[index];
       to = &aValues[index + 1];
       intervalProgress =
         scaledSimpleProgress * (aValues.Length() - 1) - index;
       intervalProgress = ScaleIntervalProgress(intervalProgress, index);
     }
 
     if (NS_SUCCEEDED(rv)) {
-      NS_ABORT_IF_FALSE(from, "NULL from-value during interpolation");
-      NS_ABORT_IF_FALSE(to, "NULL to-value during interpolation");
-      NS_ABORT_IF_FALSE(0.0f <= intervalProgress && intervalProgress < 1.0f,
-                      "Interval progress should be in the range [0, 1)");
+      MOZ_ASSERT(from, "NULL from-value during interpolation");
+      MOZ_ASSERT(to, "NULL to-value during interpolation");
+      MOZ_ASSERT(0.0f <= intervalProgress && intervalProgress < 1.0f,
+                 "Interval progress should be in the range [0, 1)");
       rv = from->Interpolate(*to, intervalProgress, aResult);
     }
   }
 
   // Discrete-CalcMode case
   // Note: If interpolation failed (isn't supported for this type), the SVG
   // spec says to force discrete mode.
   if (calcMode == CALC_DISCRETE || NS_FAILED(rv)) {
@@ -497,17 +497,17 @@ nsSMILAnimationFunction::ComputePacedPos
                                               double& aIntervalProgress,
                                               const nsSMILValue*& aFrom,
                                               const nsSMILValue*& aTo)
 {
   NS_ASSERTION(0.0f <= aSimpleProgress && aSimpleProgress < 1.0f,
                "aSimpleProgress is out of bounds");
   NS_ASSERTION(GetCalcMode() == CALC_PACED,
                "Calling paced-specific function, but not in paced mode");
-  NS_ABORT_IF_FALSE(aValues.Length() >= 2, "Unexpected number of values");
+  MOZ_ASSERT(aValues.Length() >= 2, "Unexpected number of values");
 
   // Trivial case: If we have just 2 values, then there's only one interval
   // for us to traverse, and our progress across that interval is the exact
   // same as our overall progress.
   if (aValues.Length() == 2) {
     aIntervalProgress = aSimpleProgress;
     aFrom = &aValues[0];
     aTo = &aValues[1];
@@ -543,19 +543,19 @@ nsSMILAnimationFunction::ComputePacedPos
     NS_ASSERTION(remainingDist >= 0, "distance values must be non-negative");
 
     double curIntervalDist;
 
 #ifdef DEBUG
     nsresult rv =
 #endif
       aValues[i].ComputeDistance(aValues[i+1], curIntervalDist);
-    NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv),
-                      "If we got through ComputePacedTotalDistance, we should "
-                      "be able to recompute each sub-distance without errors");
+    MOZ_ASSERT(NS_SUCCEEDED(rv),
+               "If we got through ComputePacedTotalDistance, we should "
+               "be able to recompute each sub-distance without errors");
 
     NS_ASSERTION(curIntervalDist >= 0, "distance values must be non-negative");
     // Clamp distance value at 0, just in case ComputeDistance is evil.
     curIntervalDist = std::max(curIntervalDist, 0.0);
 
     if (remainingDist >= curIntervalDist) {
       remainingDist -= curIntervalDist;
     } else {
@@ -599,17 +599,17 @@ nsSMILAnimationFunction::ComputePacedTot
     double tmpDist;
     nsresult rv = aValues[i].ComputeDistance(aValues[i+1], tmpDist);
     if (NS_FAILED(rv)) {
       return COMPUTE_DISTANCE_ERROR;
     }
 
     // Clamp distance value to 0, just in case we have an evil ComputeDistance
     // implementation somewhere
-    NS_ABORT_IF_FALSE(tmpDist >= 0.0f, "distance values must be non-negative");
+    MOZ_ASSERT(tmpDist >= 0.0f, "distance values must be non-negative");
     tmpDist = std::max(tmpDist, 0.0);
 
     totalDistance += tmpDist;
   }
 
   return totalDistance;
 }
 
@@ -629,19 +629,19 @@ nsSMILAnimationFunction::ScaleSimpleProg
   for (; i < numTimes - 2 && aProgress >= mKeyTimes[i+1]; ++i) { }
 
   if (aCalcMode == CALC_DISCRETE) {
     // discrete calcMode behaviour differs in that each keyTime defines the time
     // from when the corresponding value is set, and therefore the last value
     // needn't be 1. So check if we're in the last 'interval', that is, the
     // space between the final value and 1.0.
     if (aProgress >= mKeyTimes[i+1]) {
-      NS_ABORT_IF_FALSE(i == numTimes - 2,
-          "aProgress is not in range of the current interval, yet the current"
-          " interval is not the last bounded interval either.");
+      MOZ_ASSERT(i == numTimes - 2,
+                 "aProgress is not in range of the current interval, yet the "
+                 "current interval is not the last bounded interval either.");
       ++i;
     }
     return (double)i / numTimes;
   }
 
   double& intervalStart = mKeyTimes[i];
   double& intervalEnd   = mKeyTimes[i+1];
 
@@ -658,18 +658,18 @@ nsSMILAnimationFunction::ScaleIntervalPr
                                                uint32_t aIntervalIndex)
 {
   if (GetCalcMode() != CALC_SPLINE)
     return aProgress;
 
   if (!HasAttr(nsGkAtoms::keySplines))
     return aProgress;
 
-  NS_ABORT_IF_FALSE(aIntervalIndex < mKeySplines.Length(),
-                    "Invalid interval index");
+  MOZ_ASSERT(aIntervalIndex < mKeySplines.Length(),
+             "Invalid interval index");
 
   nsSMILKeySpline const &spline = mKeySplines[aIntervalIndex];
   return spline.GetSplineValue(aProgress);
 }
 
 bool
 nsSMILAnimationFunction::HasAttr(nsIAtom* aAttName) const
 {
--- a/dom/smil/nsSMILAnimationFunction.h
+++ b/dom/smil/nsSMILAnimationFunction.h
@@ -201,20 +201,20 @@ public:
    * after we've reacted to their change to the 'inactive' state, so that we
    * won't needlessly recompose their targets in every sample.
    *
    * This should only be called on an animation function that is inactive and
    * that returns true from HasChanged().
    */
   void ClearHasChanged()
   {
-    NS_ABORT_IF_FALSE(HasChanged(),
-                      "clearing mHasChanged flag, when it's already false");
-    NS_ABORT_IF_FALSE(!IsActiveOrFrozen(),
-                      "clearing mHasChanged flag for active animation");
+    MOZ_ASSERT(HasChanged(),
+               "clearing mHasChanged flag, when it's already false");
+    MOZ_ASSERT(!IsActiveOrFrozen(),
+               "clearing mHasChanged flag for active animation");
     mHasChanged = false;
   }
 
   /**
    * Updates the cached record of our animation target, and returns a boolean
    * that indicates whether the target has changed since the last call to this
    * function. (This lets nsSMILCompositor check whether its animation
    * functions have changed value or target since the last sample.  If none of
--- a/dom/smil/nsSMILCSSProperty.cpp
+++ b/dom/smil/nsSMILCSSProperty.cpp
@@ -17,20 +17,20 @@
 using namespace mozilla::dom;
 
 // Helper function
 static bool
 GetCSSComputedValue(Element* aElem,
                     nsCSSProperty aPropID,
                     nsAString& aResult)
 {
-  NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aPropID),
-                    "Can't look up computed value of shorthand property");
-  NS_ABORT_IF_FALSE(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
-                    "Shouldn't get here for non-animatable properties");
+  MOZ_ASSERT(!nsCSSProps::IsShorthand(aPropID),
+             "Can't look up computed value of shorthand property");
+  MOZ_ASSERT(nsSMILCSSProperty::IsPropertyAnimatable(aPropID),
+             "Shouldn't get here for non-animatable properties");
 
   nsIDocument* doc = aElem->GetCurrentDoc();
   if (!doc) {
     // This can happen if we process certain types of restyles mid-sample
     // and remove anonymous animated content from the document as a result.
     // See bug 534975.
     return false;
   }
@@ -48,19 +48,19 @@ GetCSSComputedValue(Element* aElem,
   return true;
 }
 
 // Class Methods
 nsSMILCSSProperty::nsSMILCSSProperty(nsCSSProperty aPropID,
                                      Element* aElement)
   : mPropID(aPropID), mElement(aElement)
 {
-  NS_ABORT_IF_FALSE(IsPropertyAnimatable(mPropID),
-                    "Creating a nsSMILCSSProperty for a property "
-                    "that's not supported for animation");
+  MOZ_ASSERT(IsPropertyAnimatable(mPropID),
+             "Creating a nsSMILCSSProperty for a property "
+             "that's not supported for animation");
 }
 
 nsSMILValue
 nsSMILCSSProperty::GetBaseValue() const
 {
   // To benefit from Return Value Optimization and avoid copy constructor calls
   // due to our use of return-by-value, we must return the exact same object
   // from ALL return points. This function must only return THIS variable:
--- a/dom/smil/nsSMILCSSValueType.cpp
+++ b/dom/smil/nsSMILCSSValueType.cpp
@@ -40,18 +40,18 @@ GetZeroValueForUnit(StyleAnimationValue:
     sZeroCoord(0, StyleAnimationValue::CoordConstructor);
   static const StyleAnimationValue
     sZeroPercent(0.0f, StyleAnimationValue::PercentConstructor);
   static const StyleAnimationValue
     sZeroFloat(0.0f,  StyleAnimationValue::FloatConstructor);
   static const StyleAnimationValue
     sZeroColor(NS_RGB(0,0,0), StyleAnimationValue::ColorConstructor);
 
-  NS_ABORT_IF_FALSE(aUnit != StyleAnimationValue::eUnit_Null,
-                    "Need non-null unit for a zero value");
+  MOZ_ASSERT(aUnit != StyleAnimationValue::eUnit_Null,
+             "Need non-null unit for a zero value");
   switch (aUnit) {
     case StyleAnimationValue::eUnit_Coord:
       return &sZeroCoord;
     case StyleAnimationValue::eUnit_Percent:
       return &sZeroPercent;
     case StyleAnimationValue::eUnit_Float:
       return &sZeroFloat;
     case StyleAnimationValue::eUnit_Color:
@@ -70,18 +70,18 @@ GetZeroValueForUnit(StyleAnimationValue:
 // may apply a workaround for the special case where a 0 length-value is mixed
 // with a eUnit_Float value.  (See comment below.)
 //
 // Returns true on success, or false.
 static const bool
 FinalizeStyleAnimationValues(const StyleAnimationValue*& aValue1,
                              const StyleAnimationValue*& aValue2)
 {
-  NS_ABORT_IF_FALSE(aValue1 || aValue2,
-                    "expecting at least one non-null value");
+  MOZ_ASSERT(aValue1 || aValue2,
+             "expecting at least one non-null value");
 
   // Are we missing either val? (If so, it's an implied 0 in other val's units)
   if (!aValue1) {
     aValue1 = GetZeroValueForUnit(aValue2->GetUnit());
     return !!aValue1; // Fail if we have no zero value for this unit.
   }
   if (!aValue2) {
     aValue2 = GetZeroValueForUnit(aValue1->GetUnit());
@@ -137,35 +137,35 @@ ExtractValueWrapper(const nsSMILValue& a
   return static_cast<const ValueWrapper*>(aValue.mU.mPtr);
 }
 
 // Class methods
 // -------------
 void
 nsSMILCSSValueType::Init(nsSMILValue& aValue) const
 {
-  NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected SMIL value type");
+  MOZ_ASSERT(aValue.IsNull(), "Unexpected SMIL value type");
 
   aValue.mU.mPtr = nullptr;
   aValue.mType = this;
 }
 
 void
 nsSMILCSSValueType::Destroy(nsSMILValue& aValue) const
 {
-  NS_ABORT_IF_FALSE(aValue.mType == this, "Unexpected SMIL value type");
+  MOZ_ASSERT(aValue.mType == this, "Unexpected SMIL value type");
   delete static_cast<ValueWrapper*>(aValue.mU.mPtr);
   aValue.mType = nsSMILNullType::Singleton();
 }
 
 nsresult
 nsSMILCSSValueType::Assign(nsSMILValue& aDest, const nsSMILValue& aSrc) const
 {
-  NS_ABORT_IF_FALSE(aDest.mType == aSrc.mType, "Incompatible SMIL types");
-  NS_ABORT_IF_FALSE(aDest.mType == this, "Unexpected SMIL value type");
+  MOZ_ASSERT(aDest.mType == aSrc.mType, "Incompatible SMIL types");
+  MOZ_ASSERT(aDest.mType == this, "Unexpected SMIL value type");
   const ValueWrapper* srcWrapper = ExtractValueWrapper(aSrc);
   ValueWrapper* destWrapper = ExtractValueWrapper(aDest);
 
   if (srcWrapper) {
     if (!destWrapper) {
       // barely-initialized dest -- need to alloc & copy
       aDest.mU.mPtr = new ValueWrapper(*srcWrapper);
     } else {
@@ -180,18 +180,18 @@ nsSMILCSSValueType::Assign(nsSMILValue& 
 
   return NS_OK;
 }
 
 bool
 nsSMILCSSValueType::IsEqual(const nsSMILValue& aLeft,
                             const nsSMILValue& aRight) const
 {
-  NS_ABORT_IF_FALSE(aLeft.mType == aRight.mType, "Incompatible SMIL types");
-  NS_ABORT_IF_FALSE(aLeft.mType == this, "Unexpected SMIL value");
+  MOZ_ASSERT(aLeft.mType == aRight.mType, "Incompatible SMIL types");
+  MOZ_ASSERT(aLeft.mType == this, "Unexpected SMIL value");
   const ValueWrapper* leftWrapper = ExtractValueWrapper(aLeft);
   const ValueWrapper* rightWrapper = ExtractValueWrapper(aRight);
 
   if (leftWrapper) {
     if (rightWrapper) {
       // Both non-null
       NS_WARN_IF_FALSE(leftWrapper != rightWrapper,
                        "Two nsSMILValues with matching ValueWrapper ptr");
@@ -208,24 +208,24 @@ nsSMILCSSValueType::IsEqual(const nsSMIL
   // Both null
   return true;
 }
 
 nsresult
 nsSMILCSSValueType::Add(nsSMILValue& aDest, const nsSMILValue& aValueToAdd,
                         uint32_t aCount) const
 {
-  NS_ABORT_IF_FALSE(aValueToAdd.mType == aDest.mType,
-                    "Trying to add invalid types");
-  NS_ABORT_IF_FALSE(aValueToAdd.mType == this, "Unexpected source type");
+  MOZ_ASSERT(aValueToAdd.mType == aDest.mType,
+             "Trying to add invalid types");
+  MOZ_ASSERT(aValueToAdd.mType == this, "Unexpected source type");
 
   ValueWrapper* destWrapper = ExtractValueWrapper(aDest);
   const ValueWrapper* valueToAddWrapper = ExtractValueWrapper(aValueToAdd);
-  NS_ABORT_IF_FALSE(destWrapper || valueToAddWrapper,
-                    "need at least one fully-initialized value");
+  MOZ_ASSERT(destWrapper || valueToAddWrapper,
+             "need at least one fully-initialized value");
 
   nsCSSProperty property = (valueToAddWrapper ? valueToAddWrapper->mPropID :
                             destWrapper->mPropID);
   // Special case: font-size-adjust and stroke-dasharray are explicitly
   // non-additive (even though StyleAnimationValue *could* support adding them)
   if (property == eCSSProperty_font_size_adjust ||
       property == eCSSProperty_stroke_dasharray) {
     return NS_ERROR_FAILURE;
@@ -255,23 +255,23 @@ nsSMILCSSValueType::Add(nsSMILValue& aDe
     NS_OK : NS_ERROR_FAILURE;
 }
 
 nsresult
 nsSMILCSSValueType::ComputeDistance(const nsSMILValue& aFrom,
                                     const nsSMILValue& aTo,
                                     double& aDistance) const
 {
-  NS_ABORT_IF_FALSE(aFrom.mType == aTo.mType,
-                    "Trying to compare different types");
-  NS_ABORT_IF_FALSE(aFrom.mType == this, "Unexpected source type");
+  MOZ_ASSERT(aFrom.mType == aTo.mType,
+             "Trying to compare different types");
+  MOZ_ASSERT(aFrom.mType == this, "Unexpected source type");
 
   const ValueWrapper* fromWrapper = ExtractValueWrapper(aFrom);
   const ValueWrapper* toWrapper = ExtractValueWrapper(aTo);
-  NS_ABORT_IF_FALSE(toWrapper, "expecting non-null endpoint");
+  MOZ_ASSERT(toWrapper, "expecting non-null endpoint");
 
   const StyleAnimationValue* fromCSSValue = fromWrapper ?
     &fromWrapper->mCSSValue : nullptr;
   const StyleAnimationValue* toCSSValue = &toWrapper->mCSSValue;
   if (!FinalizeStyleAnimationValues(fromCSSValue, toCSSValue)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -282,28 +282,28 @@ nsSMILCSSValueType::ComputeDistance(cons
 }
 
 nsresult
 nsSMILCSSValueType::Interpolate(const nsSMILValue& aStartVal,
                                 const nsSMILValue& aEndVal,
                                 double aUnitDistance,
                                 nsSMILValue& aResult) const
 {
-  NS_ABORT_IF_FALSE(aStartVal.mType == aEndVal.mType,
-                    "Trying to interpolate different types");
-  NS_ABORT_IF_FALSE(aStartVal.mType == this,
-                    "Unexpected types for interpolation");
-  NS_ABORT_IF_FALSE(aResult.mType == this, "Unexpected result type");
-  NS_ABORT_IF_FALSE(aUnitDistance >= 0.0 && aUnitDistance <= 1.0,
-                    "unit distance value out of bounds");
-  NS_ABORT_IF_FALSE(!aResult.mU.mPtr, "expecting barely-initialized outparam");
+  MOZ_ASSERT(aStartVal.mType == aEndVal.mType,
+             "Trying to interpolate different types");
+  MOZ_ASSERT(aStartVal.mType == this,
+             "Unexpected types for interpolation");
+  MOZ_ASSERT(aResult.mType == this, "Unexpected result type");
+  MOZ_ASSERT(aUnitDistance >= 0.0 && aUnitDistance <= 1.0,
+             "unit distance value out of bounds");
+  MOZ_ASSERT(!aResult.mU.mPtr, "expecting barely-initialized outparam");
 
   const ValueWrapper* startWrapper = ExtractValueWrapper(aStartVal);
   const ValueWrapper* endWrapper = ExtractValueWrapper(aEndVal);
-  NS_ABORT_IF_FALSE(endWrapper, "expecting non-null endpoint");
+  MOZ_ASSERT(endWrapper, "expecting non-null endpoint");
 
   const StyleAnimationValue* startCSSValue = startWrapper ?
     &startWrapper->mCSSValue : nullptr;
   const StyleAnimationValue* endCSSValue = &endWrapper->mCSSValue;
   if (!FinalizeStyleAnimationValues(startCSSValue, endCSSValue)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -365,34 +365,33 @@ ValueFromStringHelper(nsCSSProperty aPro
     return false;
   }
   if (isNegative) {
     InvertSign(aStyleAnimValue);
   }
 
   if (aPropID == eCSSProperty_font_size) {
     // Divide out text-zoom, since SVG is supposed to ignore it
-    NS_ABORT_IF_FALSE(aStyleAnimValue.GetUnit() ==
-                        StyleAnimationValue::eUnit_Coord,
-                      "'font-size' value with unexpected style unit");
+    MOZ_ASSERT(aStyleAnimValue.GetUnit() == StyleAnimationValue::eUnit_Coord,
+               "'font-size' value with unexpected style unit");
     aStyleAnimValue.SetCoordValue(aStyleAnimValue.GetCoordValue() /
                                   aPresContext->TextZoom());
   }
   return true;
 }
 
 // static
 void
 nsSMILCSSValueType::ValueFromString(nsCSSProperty aPropID,
                                     Element* aTargetElement,
                                     const nsAString& aString,
                                     nsSMILValue& aValue,
                                     bool* aIsContextSensitive)
 {
-  NS_ABORT_IF_FALSE(aValue.IsNull(), "Outparam should be null-typed");
+  MOZ_ASSERT(aValue.IsNull(), "Outparam should be null-typed");
   nsPresContext* presContext = GetPresContextForElement(aTargetElement);
   if (!presContext) {
     NS_WARNING("Not parsing animation value; unable to get PresContext");
     return;
   }
 
   nsIDocument* doc = aTargetElement->GetCurrentDoc();
   if (doc && !nsStyleUtil::CSPAllowsInlineStyle(nullptr,
@@ -410,15 +409,15 @@ nsSMILCSSValueType::ValueFromString(nsCS
   }
 }
 
 // static
 bool
 nsSMILCSSValueType::ValueToString(const nsSMILValue& aValue,
                                   nsAString& aString)
 {
-  NS_ABORT_IF_FALSE(aValue.mType == &nsSMILCSSValueType::sSingleton,
-                    "Unexpected SMIL value type");
+  MOZ_ASSERT(aValue.mType == &nsSMILCSSValueType::sSingleton,
+             "Unexpected SMIL value type");
   const ValueWrapper* wrapper = ExtractValueWrapper(aValue);
   return !wrapper ||
     StyleAnimationValue::UncomputeValue(wrapper->mPropID,
                                         wrapper->mCSSValue, aString);
 }
--- a/dom/smil/nsSMILInstanceTime.cpp
+++ b/dom/smil/nsSMILInstanceTime.cpp
@@ -42,21 +42,21 @@ nsSMILInstanceTime::nsSMILInstanceTime(c
       break;
   }
 
   SetBaseInterval(aBaseInterval);
 }
 
 nsSMILInstanceTime::~nsSMILInstanceTime()
 {
-  NS_ABORT_IF_FALSE(!mBaseInterval,
-      "Destroying instance time without first calling Unlink()");
-  NS_ABORT_IF_FALSE(mFixedEndpointRefCnt == 0,
-      "Destroying instance time that is still used as the fixed endpoint of an "
-      "interval");
+  MOZ_ASSERT(!mBaseInterval,
+             "Destroying instance time without first calling Unlink()");
+  MOZ_ASSERT(mFixedEndpointRefCnt == 0,
+             "Destroying instance time that is still used as the fixed "
+             "endpoint of an interval");
 }
 
 void
 nsSMILInstanceTime::Unlink()
 {
   nsRefPtr<nsSMILInstanceTime> deathGrip(this);
   if (mBaseInterval) {
     mBaseInterval->RemoveDependentTime(*this);
@@ -73,17 +73,17 @@ nsSMILInstanceTime::HandleChangedInterva
 {
   // It's possible a sequence of notifications might cause our base interval to
   // be updated and then deleted. Furthermore, the delete might happen whilst
   // we're still in the queue to be notified of the change. In any case, if we
   // don't have a base interval, just ignore the change.
   if (!mBaseInterval)
     return;
 
-  NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not.");
+  MOZ_ASSERT(mCreator, "Base interval is set but creator is not.");
 
   if (mVisited) {
     // Break the cycle here
     Unlink();
     return;
   }
 
   bool objectChanged = mCreator->DependsOnBegin() ? aBeginObjectChanged :
@@ -95,33 +95,35 @@ nsSMILInstanceTime::HandleChangedInterva
   nsRefPtr<nsSMILInstanceTime> deathGrip(this);
   mCreator->HandleChangedInstanceTime(*GetBaseTime(), aSrcContainer, *this,
                                       objectChanged);
 }
 
 void
 nsSMILInstanceTime::HandleDeletedInterval()
 {
-  NS_ABORT_IF_FALSE(mBaseInterval,
-      "Got call to HandleDeletedInterval on an independent instance time");
-  NS_ABORT_IF_FALSE(mCreator, "Base interval is set but creator is not");
+  MOZ_ASSERT(mBaseInterval,
+             "Got call to HandleDeletedInterval on an independent instance "
+             "time");
+  MOZ_ASSERT(mCreator, "Base interval is set but creator is not");
 
   mBaseInterval = nullptr;
   mFlags &= ~kMayUpdate; // Can't update without a base interval
 
   nsRefPtr<nsSMILInstanceTime> deathGrip(this);
   mCreator->HandleDeletedInstanceTime(*this);
   mCreator = nullptr;
 }
 
 void
 nsSMILInstanceTime::HandleFilteredInterval()
 {
-  NS_ABORT_IF_FALSE(mBaseInterval,
-      "Got call to HandleFilteredInterval on an independent instance time");
+  MOZ_ASSERT(mBaseInterval,
+             "Got call to HandleFilteredInterval on an independent instance "
+             "time");
 
   mBaseInterval = nullptr;
   mFlags &= ~kMayUpdate; // Can't update without a base interval
   mCreator = nullptr;
 }
 
 bool
 nsSMILInstanceTime::ShouldPreserve() const
@@ -133,26 +135,26 @@ void
 nsSMILInstanceTime::UnmarkShouldPreserve()
 {
   mFlags &= ~kWasDynamicEndpoint;
 }
 
 void
 nsSMILInstanceTime::AddRefFixedEndpoint()
 {
-  NS_ABORT_IF_FALSE(mFixedEndpointRefCnt < UINT16_MAX,
-      "Fixed endpoint reference count upper limit reached");
+  MOZ_ASSERT(mFixedEndpointRefCnt < UINT16_MAX,
+             "Fixed endpoint reference count upper limit reached");
   ++mFixedEndpointRefCnt;
   mFlags &= ~kMayUpdate; // Once fixed, always fixed
 }
 
 void
 nsSMILInstanceTime::ReleaseFixedEndpoint()
 {
-  NS_ABORT_IF_FALSE(mFixedEndpointRefCnt > 0, "Duplicate release");
+  MOZ_ASSERT(mFixedEndpointRefCnt > 0, "Duplicate release");
   --mFixedEndpointRefCnt;
   if (mFixedEndpointRefCnt == 0 && IsDynamic()) {
     mFlags |= kWasDynamicEndpoint;
   }
 }
 
 bool
 nsSMILInstanceTime::IsDependentOn(const nsSMILInstanceTime& aOther) const
@@ -174,35 +176,36 @@ nsSMILInstanceTime::IsDependentOn(const 
 
 const nsSMILInstanceTime*
 nsSMILInstanceTime::GetBaseTime() const
 {
   if (!mBaseInterval) {
     return nullptr;
   }
 
-  NS_ABORT_IF_FALSE(mCreator, "Base interval is set but there is no creator.");
+  MOZ_ASSERT(mCreator, "Base interval is set but there is no creator.");
   if (!mCreator) {
     return nullptr;
   }
 
   return mCreator->DependsOnBegin() ? mBaseInterval->Begin() :
                                       mBaseInterval->End();
 }
 
 void
 nsSMILInstanceTime::SetBaseInterval(nsSMILInterval* aBaseInterval)
 {
-  NS_ABORT_IF_FALSE(!mBaseInterval,
-      "Attempting to reassociate an instance time with a different interval.");
+  MOZ_ASSERT(!mBaseInterval,
+             "Attempting to reassociate an instance time with a different "
+             "interval.");
 
   if (aBaseInterval) {
-    NS_ABORT_IF_FALSE(mCreator,
-        "Attempting to create a dependent instance time without reference "
-        "to the creating nsSMILTimeValueSpec object.");
+    MOZ_ASSERT(mCreator,
+               "Attempting to create a dependent instance time without "
+               "reference to the creating nsSMILTimeValueSpec object.");
     if (!mCreator)
       return;
 
     aBaseInterval->AddDependentTime(*this);
   }
 
   mBaseInterval = aBaseInterval;
 }
--- a/dom/smil/nsSMILInstanceTime.h
+++ b/dom/smil/nsSMILInstanceTime.h
@@ -72,18 +72,18 @@ public:
   bool ShouldPreserve() const;
   void   UnmarkShouldPreserve();
 
   void AddRefFixedEndpoint();
   void ReleaseFixedEndpoint();
 
   void DependentUpdate(const nsSMILTimeValue& aNewTime)
   {
-    NS_ABORT_IF_FALSE(!IsFixedTime(),
-        "Updating an instance time that is not expected to be updated");
+    MOZ_ASSERT(!IsFixedTime(),
+               "Updating an instance time that is not expected to be updated");
     mTime = aNewTime;
   }
 
   bool IsDependent() const { return !!mBaseInterval; }
   bool IsDependentOn(const nsSMILInstanceTime& aOther) const;
   const nsSMILInterval* GetBaseInterval() const { return mBaseInterval; }
   const nsSMILInstanceTime* GetBaseTime() const;
 
--- a/dom/smil/nsSMILInterval.cpp
+++ b/dom/smil/nsSMILInterval.cpp
@@ -14,33 +14,33 @@ nsSMILInterval::nsSMILInterval()
 
 nsSMILInterval::nsSMILInterval(const nsSMILInterval& aOther)
 :
   mBegin(aOther.mBegin),
   mEnd(aOther.mEnd),
   mBeginFixed(false),
   mEndFixed(false)
 {
-  NS_ABORT_IF_FALSE(aOther.mDependentTimes.IsEmpty(),
-      "Attempting to copy-construct an interval with dependent times, "
-      "this will lead to instance times being shared between intervals.");
+  MOZ_ASSERT(aOther.mDependentTimes.IsEmpty(),
+             "Attempt to copy-construct an interval with dependent times; this "
+             "will lead to instance times being shared between intervals.");
 
   // For the time being we don't allow intervals with fixed endpoints to be
   // copied since we only ever copy-construct to establish a new current
   // interval. If we ever need to copy historical intervals we may need to move
   // the ReleaseFixedEndpoint calls from Unlink to the dtor.
-  NS_ABORT_IF_FALSE(!aOther.mBeginFixed && !aOther.mEndFixed,
-      "Attempting to copy-construct an interval with fixed endpoints");
+  MOZ_ASSERT(!aOther.mBeginFixed && !aOther.mEndFixed,
+             "Attempt to copy-construct an interval with fixed endpoints");
 }
 
 nsSMILInterval::~nsSMILInterval()
 {
-  NS_ABORT_IF_FALSE(mDependentTimes.IsEmpty(),
-      "Destroying interval without disassociating dependent instance times. "
-      "Unlink was not called");
+  MOZ_ASSERT(mDependentTimes.IsEmpty(),
+             "Destroying interval without disassociating dependent instance "
+             "times. Unlink was not called");
 }
 
 void
 nsSMILInterval::Unlink(bool aFiltered)
 {
   for (int32_t i = mDependentTimes.Length() - 1; i >= 0; --i) {
     if (aFiltered) {
       mDependentTimes[i]->HandleFilteredInterval();
@@ -57,76 +57,76 @@ nsSMILInterval::Unlink(bool aFiltered)
     mEnd->ReleaseFixedEndpoint();
   }
   mEnd = nullptr;
 }
 
 nsSMILInstanceTime*
 nsSMILInterval::Begin()
 {
-  NS_ABORT_IF_FALSE(mBegin && mEnd,
-      "Requesting Begin() on un-initialized interval.");
+  MOZ_ASSERT(mBegin && mEnd,
+             "Requesting Begin() on un-initialized interval.");
   return mBegin;
 }
 
 nsSMILInstanceTime*
 nsSMILInterval::End()
 {
-  NS_ABORT_IF_FALSE(mBegin && mEnd,
-      "Requesting End() on un-initialized interval.");
+  MOZ_ASSERT(mBegin && mEnd,
+             "Requesting End() on un-initialized interval.");
   return mEnd;
 }
 
 void
 nsSMILInterval::SetBegin(nsSMILInstanceTime& aBegin)
 {
-  NS_ABORT_IF_FALSE(aBegin.Time().IsDefinite(),
-      "Attempting to set unresolved or indefinite begin time on interval");
-  NS_ABORT_IF_FALSE(!mBeginFixed,
-      "Attempting to set begin time but the begin point is fixed");
+  MOZ_ASSERT(aBegin.Time().IsDefinite(),
+             "Attempt to set unresolved or indefinite begin time on interval");
+  MOZ_ASSERT(!mBeginFixed,
+             "Attempt to set begin time but the begin point is fixed");
   // Check that we're not making an instance time dependent on itself. Such an
   // arrangement does not make intuitive sense and should be detected when
   // creating or updating intervals.
-  NS_ABORT_IF_FALSE(!mBegin || aBegin.GetBaseTime() != mBegin,
-      "Attempting to make self-dependent instance time");
+  MOZ_ASSERT(!mBegin || aBegin.GetBaseTime() != mBegin,
+             "Attempt to make self-dependent instance time");
 
   mBegin = &aBegin;
 }
 
 void
 nsSMILInterval::SetEnd(nsSMILInstanceTime& aEnd)
 {
-  NS_ABORT_IF_FALSE(!mEndFixed,
-      "Attempting to set end time but the end point is fixed");
+  MOZ_ASSERT(!mEndFixed,
+             "Attempt to set end time but the end point is fixed");
   // As with SetBegin, check we're not making an instance time dependent on
   // itself.
-  NS_ABORT_IF_FALSE(!mEnd || aEnd.GetBaseTime() != mEnd,
-      "Attempting to make self-dependent instance time");
+  MOZ_ASSERT(!mEnd || aEnd.GetBaseTime() != mEnd,
+             "Attempting to make self-dependent instance time");
 
   mEnd = &aEnd;
 }
 
 void
 nsSMILInterval::FixBegin()
 {
-  NS_ABORT_IF_FALSE(mBegin && mEnd,
-      "Fixing begin point on un-initialized interval");
-  NS_ABORT_IF_FALSE(!mBeginFixed, "Duplicate calls to FixBegin()");
+  MOZ_ASSERT(mBegin && mEnd,
+             "Fixing begin point on un-initialized interval");
+  MOZ_ASSERT(!mBeginFixed, "Duplicate calls to FixBegin()");
   mBeginFixed = true;
   mBegin->AddRefFixedEndpoint();
 }
 
 void
 nsSMILInterval::FixEnd()
 {
-  NS_ABORT_IF_FALSE(mBegin && mEnd,
-      "Fixing end point on un-initialized interval");
-  NS_ABORT_IF_FALSE(mBeginFixed,
-      "Fixing the end of an interval without a fixed begin");
-  NS_ABORT_IF_FALSE(!mEndFixed, "Duplicate calls to FixEnd()");
+  MOZ_ASSERT(mBegin && mEnd,
+             "Fixing end point on un-initialized interval");
+  MOZ_ASSERT(mBeginFixed,
+             "Fixing the end of an interval without a fixed begin");
+  MOZ_ASSERT(!mEndFixed, "Duplicate calls to FixEnd()");
   mEndFixed = true;
   mEnd->AddRefFixedEndpoint();
 }
 
 void
 nsSMILInterval::AddDependentTime(nsSMILInstanceTime& aTime)
 {
   nsRefPtr<nsSMILInstanceTime>* inserted =
@@ -138,17 +138,17 @@ nsSMILInterval::AddDependentTime(nsSMILI
 
 void
 nsSMILInterval::RemoveDependentTime(const nsSMILInstanceTime& aTime)
 {
 #ifdef DEBUG
   bool found =
 #endif
     mDependentTimes.RemoveElementSorted(&aTime);
-  NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete.");
+  MOZ_ASSERT(found, "Couldn't find instance time to delete.");
 }
 
 void
 nsSMILInterval::GetDependentTimes(InstanceTimeList& aTimes)
 {
   aTimes = mDependentTimes;
 }
 
--- a/dom/smil/nsSMILInterval.h
+++ b/dom/smil/nsSMILInterval.h
@@ -23,26 +23,26 @@ class nsSMILInterval
 public:
   nsSMILInterval();
   nsSMILInterval(const nsSMILInterval& aOther);
   ~nsSMILInterval();
   void Unlink(bool aFiltered = false);
 
   const nsSMILInstanceTime* Begin() const
   {
-    NS_ABORT_IF_FALSE(mBegin && mEnd,
-        "Requesting Begin() on un-initialized instance time");
+    MOZ_ASSERT(mBegin && mEnd,
+               "Requesting Begin() on un-initialized instance time");
     return mBegin;
   }
   nsSMILInstanceTime* Begin();
 
   const nsSMILInstanceTime* End() const
   {
-    NS_ABORT_IF_FALSE(mBegin && mEnd,
-        "Requesting End() on un-initialized instance time");
+    MOZ_ASSERT(mBegin && mEnd,
+               "Requesting End() on un-initialized instance time");
     return mEnd;
   }
   nsSMILInstanceTime* End();
 
   void SetBegin(nsSMILInstanceTime& aBegin);
   void SetEnd(nsSMILInstanceTime& aEnd);
   void Set(nsSMILInstanceTime& aBegin, nsSMILInstanceTime& aEnd)
   {
--- a/dom/smil/nsSMILParserUtils.cpp
+++ b/dom/smil/nsSMILParserUtils.cpp
@@ -266,26 +266,25 @@ ParseOptionalOffset(RangedPtr<const char
 
   return SkipWhitespace(aIter, aEnd) &&
          ParseOffsetValue(aIter, aEnd, aResult);
 }
 
 bool
 ParseAccessKey(const nsAString& aSpec, nsSMILTimeValueSpecParams& aResult)
 {
-  NS_ABORT_IF_FALSE(StringBeginsWith(aSpec, ACCESSKEY_PREFIX_CC) ||
-      StringBeginsWith(aSpec, ACCESSKEY_PREFIX_LC),
-      "Calling ParseAccessKey on non-accesskey-type spec");
+  MOZ_ASSERT(StringBeginsWith(aSpec, ACCESSKEY_PREFIX_CC) ||
+             StringBeginsWith(aSpec, ACCESSKEY_PREFIX_LC),
+             "Calling ParseAccessKey on non-accesskey-type spec");
 
   nsSMILTimeValueSpecParams result;
   result.mType = nsSMILTimeValueSpecParams::ACCESSKEY;
 
-  NS_ABORT_IF_FALSE(
-      ACCESSKEY_PREFIX_LC.Length() == ACCESSKEY_PREFIX_CC.Length(),
-      "Case variations for accesskey prefix differ in length");
+  MOZ_ASSERT(ACCESSKEY_PREFIX_LC.Length() == ACCESSKEY_PREFIX_CC.Length(),
+             "Case variations for accesskey prefix differ in length");
 
   RangedPtr<const char16_t> iter(SVGContentUtils::GetStartRangedPtr(aSpec));
   RangedPtr<const char16_t> end(SVGContentUtils::GetEndRangedPtr(aSpec));
 
   iter += ACCESSKEY_PREFIX_LC.Length();
 
   // Expecting at least <accesskey> + ')'
   if (end - iter < 2)
@@ -366,17 +365,17 @@ ConvertTokenToAtom(const nsAString& aTok
   nsAutoString token(aToken);
 
   const char16_t* read = token.BeginReading();
   const char16_t* const end = token.EndReading();
   char16_t* write = token.BeginWriting();
   bool escape = false;
 
   while (read != end) {
-    NS_ABORT_IF_FALSE(write <= read, "Writing past where we've read");
+    MOZ_ASSERT(write <= read, "Writing past where we've read");
     if (!escape && *read == '\\') {
       escape = true;
       ++read;
     } else {
       *write++ = *read++;
       escape = false;
     }
   }
--- a/dom/smil/nsSMILTimeContainer.cpp
+++ b/dom/smil/nsSMILTimeContainer.cpp
@@ -249,19 +249,19 @@ nsSMILTimeContainer::PopMilestoneElement
 
   nsSMILTimeValue containerTime = ParentToContainerTime(aMilestone.mTime);
   if (!containerTime.IsDefinite())
     return false;
 
   nsSMILMilestone containerMilestone(containerTime.GetMillis(),
                                      aMilestone.mIsEnd);
 
-  NS_ABORT_IF_FALSE(mMilestoneEntries.Top().mMilestone >= containerMilestone,
-      "Trying to pop off earliest times but we have earlier ones that were "
-      "overlooked");
+  MOZ_ASSERT(mMilestoneEntries.Top().mMilestone >= containerMilestone,
+             "Trying to pop off earliest times but we have earlier ones that "
+             "were overlooked");
 
   bool gotOne = false;
   while (!mMilestoneEntries.IsEmpty() &&
       mMilestoneEntries.Top().mMilestone == containerMilestone)
   {
     aMatchedElements.AppendElement(mMilestoneEntries.Pop().mTimebase);
     gotOne = true;
   }
@@ -286,17 +286,17 @@ nsSMILTimeContainer::Unlink()
   mMilestoneEntries.Clear();
 }
 
 void
 nsSMILTimeContainer::UpdateCurrentTime()
 {
   nsSMILTime now = IsPaused() ? mPauseStart : GetParentTime();
   mCurrentTime = now - mParentOffset;
-  NS_ABORT_IF_FALSE(mCurrentTime >= 0, "Container has negative time");
+  MOZ_ASSERT(mCurrentTime >= 0, "Container has negative time");
 }
 
 void
 nsSMILTimeContainer::NotifyTimeChange()
 {
   // Called when the container time is changed with respect to the document
   // time. When this happens time dependencies in other time containers need to
   // re-resolve their times because begin and end times are stored in container
@@ -308,14 +308,14 @@ nsSMILTimeContainer::NotifyTimeChange()
   // registered. Other timed elements don't matter.
   const MilestoneEntry* p = mMilestoneEntries.Elements();
 #if DEBUG
   uint32_t queueLength = mMilestoneEntries.Length();
 #endif
   while (p < mMilestoneEntries.Elements() + mMilestoneEntries.Length()) {
     mozilla::dom::SVGAnimationElement* elem = p->mTimebase.get();
     elem->TimedElement().HandleContainerTimeChange();
-    NS_ABORT_IF_FALSE(queueLength == mMilestoneEntries.Length(),
-        "Call to HandleContainerTimeChange resulted in a change to the "
-        "queue of milestones");
+    MOZ_ASSERT(queueLength == mMilestoneEntries.Length(),
+               "Call to HandleContainerTimeChange resulted in a change to the "
+               "queue of milestones");
     ++p;
   }
 }
--- a/dom/smil/nsSMILTimeValue.h
+++ b/dom/smil/nsSMILTimeValue.h
@@ -83,18 +83,18 @@ public:
   {
     mState = STATE_UNRESOLVED;
     mMilliseconds = kUnresolvedMillis;
   }
 
   bool IsDefinite() const { return mState == STATE_DEFINITE; }
   nsSMILTime GetMillis() const
   {
-    NS_ABORT_IF_FALSE(mState == STATE_DEFINITE,
-       "GetMillis() called for unresolved or indefinite time");
+    MOZ_ASSERT(mState == STATE_DEFINITE,
+               "GetMillis() called for unresolved or indefinite time");
 
     return mState == STATE_DEFINITE ? mMilliseconds : kUnresolvedMillis;
   }
 
   void SetMillis(nsSMILTime aMillis)
   {
     mState = STATE_DEFINITE;
     mMilliseconds = aMillis;
--- a/dom/smil/nsSMILTimeValueSpec.cpp
+++ b/dom/smil/nsSMILTimeValueSpec.cpp
@@ -87,18 +87,18 @@ nsSMILTimeValueSpec::SetSpec(const nsASt
 }
 
 void
 nsSMILTimeValueSpec::ResolveReferences(nsIContent* aContextNode)
 {
   if (mParams.mType != nsSMILTimeValueSpecParams::SYNCBASE && !IsEventBased())
     return;
 
-  NS_ABORT_IF_FALSE(aContextNode,
-      "null context node for resolving timing references against");
+  MOZ_ASSERT(aContextNode,
+             "null context node for resolving timing references against");
 
   // If we're not bound to the document yet, don't worry, we'll get called again
   // when that happens
   if (!aContextNode->IsInDoc())
     return;
 
   // Hold ref to the old element so that it isn't destroyed in between resetting
   // the referenced element and using the pointer to update the referenced
@@ -108,20 +108,20 @@ nsSMILTimeValueSpec::ResolveReferences(n
   if (mParams.mDependentElemID) {
     mReferencedElement.ResetWithID(aContextNode,
         nsDependentAtomString(mParams.mDependentElemID));
   } else if (mParams.mType == nsSMILTimeValueSpecParams::EVENT) {
     Element* target = mOwner->GetTargetElement();
     mReferencedElement.ResetWithElement(target);
   } else if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
     nsIDocument* doc = aContextNode->GetCurrentDoc();
-    NS_ABORT_IF_FALSE(doc, "We are in the document but current doc is null");
+    MOZ_ASSERT(doc, "We are in the document but current doc is null");
     mReferencedElement.ResetWithElement(doc->GetRootElement());
   } else {
-    NS_ABORT_IF_FALSE(false, "Syncbase or repeat spec without ID");
+    MOZ_ASSERT(false, "Syncbase or repeat spec without ID");
   }
   UpdateReferencedElement(oldReferencedElement, mReferencedElement.get());
 }
 
 bool
 nsSMILTimeValueSpec::IsEventBased() const
 {
   return mParams.mType == nsSMILTimeValueSpecParams::EVENT ||
@@ -292,21 +292,22 @@ nsSMILTimeValueSpec::IsWhitelistedEvent(
   }
 
   return false;
 }
 
 void
 nsSMILTimeValueSpec::RegisterEventListener(Element* aTarget)
 {
-  NS_ABORT_IF_FALSE(IsEventBased(),
-    "Attempting to register event-listener for unexpected nsSMILTimeValueSpec"
-    " type");
-  NS_ABORT_IF_FALSE(mParams.mEventSymbol,
-    "Attempting to register event-listener but there is no event name");
+  MOZ_ASSERT(IsEventBased(),
+             "Attempting to register event-listener for unexpected "
+             "nsSMILTimeValueSpec type");
+  MOZ_ASSERT(mParams.mEventSymbol,
+             "Attempting to register event-listener but there is no event "
+             "name");
 
   if (!aTarget)
     return;
 
   // When script is disabled, only allow registration for whitelisted events.
   if (!aTarget->GetOwnerDocument()->IsScriptEnabled() &&
       !IsWhitelistedEvent()) {
     return;
@@ -338,17 +339,17 @@ nsSMILTimeValueSpec::UnregisterEventList
   elm->RemoveEventListenerByType(mEventListener,
                                  nsDependentAtomString(mParams.mEventSymbol),
                                  AllEventsAtSystemGroupBubble());
 }
 
 EventListenerManager*
 nsSMILTimeValueSpec::GetEventListenerManager(Element* aTarget)
 {
-  NS_ABORT_IF_FALSE(aTarget, "null target; can't get EventListenerManager");
+  MOZ_ASSERT(aTarget, "null target; can't get EventListenerManager");
 
   nsCOMPtr<EventTarget> target;
 
   if (mParams.mType == nsSMILTimeValueSpecParams::ACCESSKEY) {
     nsIDocument* doc = aTarget->GetCurrentDoc();
     if (!doc)
       return nullptr;
     nsPIDOMWindow* win = doc->GetWindow();
@@ -362,20 +363,20 @@ nsSMILTimeValueSpec::GetEventListenerMan
     return nullptr;
 
   return target->GetOrCreateListenerManager();
 }
 
 void
 nsSMILTimeValueSpec::HandleEvent(nsIDOMEvent* aEvent)
 {
-  NS_ABORT_IF_FALSE(mEventListener, "Got event without an event listener");
-  NS_ABORT_IF_FALSE(IsEventBased(),
-                    "Got event for non-event nsSMILTimeValueSpec");
-  NS_ABORT_IF_FALSE(aEvent, "No event supplied");
+  MOZ_ASSERT(mEventListener, "Got event without an event listener");
+  MOZ_ASSERT(IsEventBased(),
+             "Got event for non-event nsSMILTimeValueSpec");
+  MOZ_ASSERT(aEvent, "No event supplied");
 
   // XXX In the long run we should get the time from the event itself which will
   // store the time in global document time which we'll need to convert to our
   // time container
   nsSMILTimeContainer* container = mOwner->GetTimeContainer();
   if (!container)
     return;
 
@@ -504,18 +505,18 @@ nsSMILTimeValueSpec::ConvertBetweenTimeC
   nsSMILTimeValue docTime =
     aSrcContainer->ContainerToParentTime(aSrcTime.GetMillis());
 
   if (docTime.IsIndefinite())
     // This will happen if the source container is paused and we have a future
     // time. Just return the indefinite time.
     return docTime;
 
-  NS_ABORT_IF_FALSE(docTime.IsDefinite(),
-    "ContainerToParentTime gave us an unresolved or indefinite time");
+  MOZ_ASSERT(docTime.IsDefinite(),
+             "ContainerToParentTime gave us an unresolved or indefinite time");
 
   return dstContainer->ParentToContainerTime(docTime.GetMillis());
 }
 
 bool
 nsSMILTimeValueSpec::ApplyOffset(nsSMILTimeValue& aTime) const
 {
   // indefinite + offset = indefinite. Likewise for unresolved times.
--- a/dom/smil/nsSMILTimedElement.cpp
+++ b/dom/smil/nsSMILTimedElement.cpp
@@ -43,35 +43,35 @@ using namespace mozilla::dom;
 //
 // The serial number also means that every instance time has an unambiguous
 // position in the array so we can use RemoveElementSorted and the like.
 bool
 nsSMILTimedElement::InstanceTimeComparator::Equals(
     const nsSMILInstanceTime* aElem1,
     const nsSMILInstanceTime* aElem2) const
 {
-  NS_ABORT_IF_FALSE(aElem1 && aElem2,
-      "Trying to compare null instance time pointers");
-  NS_ABORT_IF_FALSE(aElem1->Serial() && aElem2->Serial(),
-      "Instance times have not been assigned serial numbers");
-  NS_ABORT_IF_FALSE(aElem1 == aElem2 || aElem1->Serial() != aElem2->Serial(),
-      "Serial numbers are not unique");
+  MOZ_ASSERT(aElem1 && aElem2,
+             "Trying to compare null instance time pointers");
+  MOZ_ASSERT(aElem1->Serial() && aElem2->Serial(),
+             "Instance times have not been assigned serial numbers");
+  MOZ_ASSERT(aElem1 == aElem2 || aElem1->Serial() != aElem2->Serial(),
+             "Serial numbers are not unique");
 
   return aElem1->Serial() == aElem2->Serial();
 }
 
 bool
 nsSMILTimedElement::InstanceTimeComparator::LessThan(
     const nsSMILInstanceTime* aElem1,
     const nsSMILInstanceTime* aElem2) const
 {
-  NS_ABORT_IF_FALSE(aElem1 && aElem2,
-      "Trying to compare null instance time pointers");
-  NS_ABORT_IF_FALSE(aElem1->Serial() && aElem2->Serial(),
-      "Instance times have not been assigned serial numbers");
+  MOZ_ASSERT(aElem1 && aElem2,
+             "Trying to compare null instance time pointers");
+  MOZ_ASSERT(aElem1->Serial() && aElem2->Serial(),
+             "Instance times have not been assigned serial numbers");
 
   int8_t cmp = aElem1->Time().CompareTo(aElem2->Time());
   return cmp == 0 ? aElem1->Serial() < aElem2->Serial() : cmp < 0;
 }
 
 //----------------------------------------------------------------------
 // Helper class: AsyncTimeEventRunner
 
@@ -190,19 +190,18 @@ nsSMILTimedElement::RemoveInstanceTimes(
       // instance time that corresponds to the previous interval's end time.
       //
       // Most functors supplied here fulfil this condition by checking if the
       // instance time is marked as "ShouldPreserve" and if so, not deleting it.
       //
       // However, when filtering instance times, we sometimes need to drop even
       // instance times marked as "ShouldPreserve". In that case we take special
       // care not to delete the end instance time of the previous interval.
-      NS_ABORT_IF_FALSE(!GetPreviousInterval() ||
-        item != GetPreviousInterval()->End(),
-        "Removing end instance time of previous interval");
+      MOZ_ASSERT(!GetPreviousInterval() || item != GetPreviousInterval()->End(),
+                 "Removing end instance time of previous interval");
       item->Unlink();
     } else {
       newArray.AppendElement(item);
     }
   }
   aArray.Clear();
   aArray.SwapElements(newArray);
 }
@@ -277,29 +276,29 @@ nsSMILTimedElement::~nsSMILTimedElement(
   // (We shouldn't get any callbacks from this because all our instance times
   // are now disassociated with any intervals)
   ClearIntervals();
 
   // The following assertions are important in their own right (for checking
   // correct behavior) but also because AutoIntervalUpdateBatcher holds pointers
   // to class so if they fail there's the possibility we might have dangling
   // pointers.
-  NS_ABORT_IF_FALSE(!mDeferIntervalUpdates,
-      "Interval updates should no longer be blocked when an nsSMILTimedElement "
-      "disappears");
-  NS_ABORT_IF_FALSE(!mDoDeferredUpdate,
-      "There should no longer be any pending updates when an "
-      "nsSMILTimedElement disappears");
+  MOZ_ASSERT(!mDeferIntervalUpdates,
+             "Interval updates should no longer be blocked when an "
+             "nsSMILTimedElement disappears");
+  MOZ_ASSERT(!mDoDeferredUpdate,
+             "There should no longer be any pending updates when an "
+             "nsSMILTimedElement disappears");
 }
 
 void
 nsSMILTimedElement::SetAnimationElement(SVGAnimationElement* aElement)
 {
-  NS_ABORT_IF_FALSE(aElement, "NULL owner element");
-  NS_ABORT_IF_FALSE(!mAnimationElement, "Re-setting owner");
+  MOZ_ASSERT(aElement, "NULL owner element");
+  MOZ_ASSERT(!mAnimationElement, "Re-setting owner");
   mAnimationElement = aElement;
 }
 
 nsSMILTimeContainer*
 nsSMILTimedElement::GetTimeContainer()
 {
   return mAnimationElement ? mAnimationElement->GetTimeContainer() : nullptr;
 }
@@ -380,28 +379,28 @@ nsSMILTimedElement::GetHyperlinkTime() c
 
 //----------------------------------------------------------------------
 // nsSMILTimedElement
 
 void
 nsSMILTimedElement::AddInstanceTime(nsSMILInstanceTime* aInstanceTime,
                                     bool aIsBegin)
 {
-  NS_ABORT_IF_FALSE(aInstanceTime, "Attempting to add null instance time");
+  MOZ_ASSERT(aInstanceTime, "Attempting to add null instance time");
 
   // Event-sensitivity: If an element is not active (but the parent time
   // container is), then events are only handled for begin specifications.
   if (mElementState != STATE_ACTIVE && !aIsBegin &&
       aInstanceTime->IsDynamic())
   {
     // No need to call Unlink here--dynamic instance times shouldn't be linked
     // to anything that's going to miss them
-    NS_ABORT_IF_FALSE(!aInstanceTime->GetBaseInterval(),
-        "Dynamic instance time has a base interval--we probably need to unlink"
-        " it if we're not going to use it");
+    MOZ_ASSERT(!aInstanceTime->GetBaseInterval(),
+               "Dynamic instance time has a base interval--we probably need "
+               "to unlink it if we're not going to use it");
     return;
   }
 
   aInstanceTime->SetSerial(++mInstanceSerialIndex);
   InstanceTimeList& instanceList = aIsBegin ? mBeginInstances : mEndInstances;
   nsRefPtr<nsSMILInstanceTime>* inserted =
     instanceList.InsertElementSorted(aInstanceTime, InstanceTimeComparator());
   if (!inserted) {
@@ -412,17 +411,17 @@ nsSMILTimedElement::AddInstanceTime(nsSM
   UpdateCurrentInterval();
 }
 
 void
 nsSMILTimedElement::UpdateInstanceTime(nsSMILInstanceTime* aInstanceTime,
                                        nsSMILTimeValue& aUpdatedTime,
                                        bool aIsBegin)
 {
-  NS_ABORT_IF_FALSE(aInstanceTime, "Attempting to update null instance time");
+  MOZ_ASSERT(aInstanceTime, "Attempting to update null instance time");
 
   // The reason we update the time here and not in the nsSMILTimeValueSpec is
   // that it means we *could* re-sort more efficiently by doing a sorted remove
   // and insert but currently this doesn't seem to be necessary given how
   // infrequently we get these change notices.
   aInstanceTime->DependentUpdate(aUpdatedTime);
   InstanceTimeList& instanceList = aIsBegin ? mBeginInstances : mEndInstances;
   instanceList.Sort(InstanceTimeComparator());
@@ -444,29 +443,29 @@ nsSMILTimedElement::UpdateInstanceTime(n
 
   UpdateCurrentInterval(changedCurrentInterval);
 }
 
 void
 nsSMILTimedElement::RemoveInstanceTime(nsSMILInstanceTime* aInstanceTime,
                                        bool aIsBegin)
 {
-  NS_ABORT_IF_FALSE(aInstanceTime, "Attempting to remove null instance time");
+  MOZ_ASSERT(aInstanceTime, "Attempting to remove null instance time");
 
   // If the instance time should be kept (because it is or was the fixed end
   // point of an interval) then just disassociate it from the creator.
   if (aInstanceTime->ShouldPreserve()) {
     aInstanceTime->Unlink();
     return;
   }
 
   InstanceTimeList& instanceList = aIsBegin ? mBeginInstances : mEndInstances;
   mozilla::DebugOnly<bool> found =
     instanceList.RemoveElementSorted(aInstanceTime, InstanceTimeComparator());
-  NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete");
+  MOZ_ASSERT(found, "Couldn't find instance time to delete");
 
   UpdateCurrentInterval();
 }
 
 namespace
 {
   class MOZ_STACK_CLASS RemoveByCreator
   {
@@ -493,17 +492,17 @@ namespace
     const nsSMILTimeValueSpec* mCreator;
   };
 }
 
 void
 nsSMILTimedElement::RemoveInstanceTimesForCreator(
     const nsSMILTimeValueSpec* aCreator, bool aIsBegin)
 {
-  NS_ABORT_IF_FALSE(aCreator, "Creator not set");
+  MOZ_ASSERT(aCreator, "Creator not set");
 
   InstanceTimeList& instances = aIsBegin ? mBeginInstances : mEndInstances;
   RemoveByCreator removeByCreator(aCreator);
   RemoveInstanceTimes(instances, removeByCreator);
 
   UpdateCurrentInterval();
 }
 
@@ -555,20 +554,20 @@ nsSMILTimedElement::SampleEndAt(nsSMILTi
     // our next real milestone is registered.
     RegisterMilestone();
   }
 }
 
 void
 nsSMILTimedElement::DoSampleAt(nsSMILTime aContainerTime, bool aEndOnly)
 {
-  NS_ABORT_IF_FALSE(mAnimationElement,
-      "Got sample before being registered with an animation element");
-  NS_ABORT_IF_FALSE(GetTimeContainer(),
-      "Got sample without being registered with a time container");
+  MOZ_ASSERT(mAnimationElement,
+             "Got sample before being registered with an animation element");
+  MOZ_ASSERT(GetTimeContainer(),
+             "Got sample without being registered with a time container");
 
   // This could probably happen if we later implement externalResourcesRequired
   // (bug 277955) and whilst waiting for those resources (and the animation to
   // start) we transfer a node from another document fragment that has already
   // started. In such a case we might receive milestone samples registered with
   // the already active container.
   if (GetTimeContainer()->IsPausedByType(nsSMILTimeContainer::PAUSE_BEGIN))
     return;
@@ -599,21 +598,22 @@ nsSMILTimedElement::DoSampleAt(nsSMILTim
 
   bool            stateChanged;
   nsSMILTimeValue sampleTime(aContainerTime);
 
   do {
 #ifdef DEBUG
     // Check invariant
     if (mElementState == STATE_STARTUP || mElementState == STATE_POSTACTIVE) {
-      NS_ABORT_IF_FALSE(!mCurrentInterval,
-          "Shouldn't have current interval in startup or postactive states");
+      MOZ_ASSERT(!mCurrentInterval,
+                 "Shouldn't have current interval in startup or postactive "
+                 "states");
     } else {
-      NS_ABORT_IF_FALSE(mCurrentInterval,
-          "Should have current interval in waiting and active states");
+      MOZ_ASSERT(mCurrentInterval,
+                 "Should have current interval in waiting and active states");
     }
 #endif
 
     stateChanged = false;
 
     switch (mElementState)
     {
     case STATE_STARTUP:
@@ -689,18 +689,18 @@ nsSMILTimedElement::DoSampleAt(nsSMILTim
                 mOldIntervals[mOldIntervals.Length() - 1], false, true);
           }
           if (mElementState == STATE_WAITING) {
             NotifyNewInterval();
           }
           FilterHistory();
           stateChanged = true;
         } else {
-          NS_ABORT_IF_FALSE(!didApplyEarlyEnd,
-              "We got an early end, but didn't end");
+          MOZ_ASSERT(!didApplyEarlyEnd,
+                     "We got an early end, but didn't end");
           nsSMILTime beginTime = mCurrentInterval->Begin()->Time().GetMillis();
           NS_ASSERTION(aContainerTime >= beginTime,
                        "Sample time should not precede current interval");
           nsSMILTime activeTime = aContainerTime - beginTime;
 
           // The 'min' attribute can cause the active interval to be longer than
           // the 'repeating interval'.
           // In that extended period we apply the fill mode.
@@ -766,53 +766,53 @@ nsSMILTimedElement::HandleContainerTimeC
 namespace
 {
   bool
   RemoveNonDynamic(nsSMILInstanceTime* aInstanceTime)
   {
     // Generally dynamically-generated instance times (DOM calls, event-based
     // times) are not associated with their creator nsSMILTimeValueSpec since
     // they may outlive them.
-    NS_ABORT_IF_FALSE(!aInstanceTime->IsDynamic() ||
-         !aInstanceTime->GetCreator(),
-        "Dynamic instance time should be unlinked from its creator");
+    MOZ_ASSERT(!aInstanceTime->IsDynamic() || !aInstanceTime->GetCreator(),
+               "Dynamic instance time should be unlinked from its creator");
     return !aInstanceTime->IsDynamic() && !aInstanceTime->ShouldPreserve();
   }
 }
 
 void
 nsSMILTimedElement::Rewind()
 {
-  NS_ABORT_IF_FALSE(mAnimationElement,
-      "Got rewind request before being attached to an animation element");
+  MOZ_ASSERT(mAnimationElement,
+             "Got rewind request before being attached to an animation "
+             "element");
 
   // It's possible to get a rewind request whilst we're already in the middle of
   // a backwards seek. This can happen when we're performing tree surgery and
   // seeking containers at the same time because we can end up requesting
   // a local rewind on an element after binding it to a new container and then
   // performing a rewind on that container as a whole without sampling in
   // between.
   //
   // However, it should currently be impossible to get a rewind in the middle of
   // a forwards seek since forwards seeks are detected and processed within the
   // same (re)sample.
   if (mSeekState == SEEK_NOT_SEEKING) {
     mSeekState = mElementState == STATE_ACTIVE ?
                  SEEK_BACKWARD_FROM_ACTIVE :
                  SEEK_BACKWARD_FROM_INACTIVE;
   }
-  NS_ABORT_IF_FALSE(mSeekState == SEEK_BACKWARD_FROM_INACTIVE ||
-                    mSeekState == SEEK_BACKWARD_FROM_ACTIVE,
-                    "Rewind in the middle of a forwards seek?");
+  MOZ_ASSERT(mSeekState == SEEK_BACKWARD_FROM_INACTIVE ||
+             mSeekState == SEEK_BACKWARD_FROM_ACTIVE,
+             "Rewind in the middle of a forwards seek?");
 
   ClearTimingState(RemoveNonDynamic);
   RebuildTimingState(RemoveNonDynamic);
 
-  NS_ABORT_IF_FALSE(!mCurrentInterval,
-                    "Current interval is set at end of rewind");
+  MOZ_ASSERT(!mCurrentInterval,
+             "Current interval is set at end of rewind");
 }
 
 namespace
 {
   bool
   RemoveAll(nsSMILInstanceTime* aInstanceTime)
   {
     return true;
@@ -967,18 +967,18 @@ nsSMILTimedElement::SetSimpleDuration(co
     if (!nsSMILParserUtils::ParseClockValue(dur, &duration) ||
         duration.GetMillis() == 0L) {
       mSimpleDur.SetIndefinite();
       return NS_ERROR_FAILURE;
     }
   }
   // mSimpleDur should never be unresolved. ParseClockValue will either set
   // duration to resolved or will return false.
-  NS_ABORT_IF_FALSE(duration.IsResolved(),
-    "Setting unresolved simple duration");
+  MOZ_ASSERT(duration.IsResolved(),
+             "Setting unresolved simple duration");
 
   mSimpleDur = duration;
 
   return NS_OK;
 }
 
 void
 nsSMILTimedElement::UnsetSimpleDuration()
@@ -1000,17 +1000,17 @@ nsSMILTimedElement::SetMin(const nsAStri
     duration.SetMillis(0L);
   } else {
     if (!nsSMILParserUtils::ParseClockValue(min, &duration)) {
       mMin.SetMillis(0L);
       return NS_ERROR_FAILURE;
     }
   }
 
-  NS_ABORT_IF_FALSE(duration.GetMillis() >= 0L, "Invalid duration");
+  MOZ_ASSERT(duration.GetMillis() >= 0L, "Invalid duration");
 
   mMin = duration;
 
   return NS_OK;
 }
 
 void
 nsSMILTimedElement::UnsetMin()
@@ -1031,17 +1031,17 @@ nsSMILTimedElement::SetMax(const nsAStri
   if (max.EqualsLiteral("media") || max.EqualsLiteral("indefinite")) {
     duration.SetIndefinite();
   } else {
     if (!nsSMILParserUtils::ParseClockValue(max, &duration) ||
         duration.GetMillis() == 0L) {
       mMax.SetIndefinite();
       return NS_ERROR_FAILURE;
     }
-    NS_ABORT_IF_FALSE(duration.GetMillis() > 0L, "Invalid duration");
+    MOZ_ASSERT(duration.GetMillis() > 0L, "Invalid duration");
   }
 
   mMax = duration;
 
   return NS_OK;
 }
 
 void
@@ -1157,18 +1157,18 @@ nsSMILTimedElement::UnsetFillMode()
   }
 }
 
 void
 nsSMILTimedElement::AddDependent(nsSMILTimeValueSpec& aDependent)
 {
   // There's probably no harm in attempting to register a dependent
   // nsSMILTimeValueSpec twice, but we're not expecting it to happen.
-  NS_ABORT_IF_FALSE(!mTimeDependents.GetEntry(&aDependent),
-      "nsSMILTimeValueSpec is already registered as a dependency");
+  MOZ_ASSERT(!mTimeDependents.GetEntry(&aDependent),
+             "nsSMILTimeValueSpec is already registered as a dependency");
   mTimeDependents.PutEntry(&aDependent);
 
   // Add current interval. We could add historical intervals too but that would
   // cause unpredictable results since some intervals may have been filtered.
   // SMIL doesn't say what to do here so for simplicity and consistency we
   // simply add the current interval if there is one.
   //
   // It's not necessary to call SyncPauseTime since we're dealing with
@@ -1246,47 +1246,47 @@ nsSMILTimedElement::HandleTargetElementC
 }
 
 void
 nsSMILTimedElement::Traverse(nsCycleCollectionTraversalCallback* aCallback)
 {
   uint32_t count = mBeginSpecs.Length();
   for (uint32_t i = 0; i < count; ++i) {
     nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i];
-    NS_ABORT_IF_FALSE(beginSpec,
-        "null nsSMILTimeValueSpec in list of begin specs");
+    MOZ_ASSERT(beginSpec,
+               "null nsSMILTimeValueSpec in list of begin specs");
     beginSpec->Traverse(aCallback);
   }
 
   count = mEndSpecs.Length();
   for (uint32_t j = 0; j < count; ++j) {
     nsSMILTimeValueSpec* endSpec = mEndSpecs[j];
-    NS_ABORT_IF_FALSE(endSpec, "null nsSMILTimeValueSpec in list of end specs");
+    MOZ_ASSERT(endSpec, "null nsSMILTimeValueSpec in list of end specs");
     endSpec->Traverse(aCallback);
   }
 }
 
 void
 nsSMILTimedElement::Unlink()
 {
   AutoIntervalUpdateBatcher updateBatcher(*this);
 
   // Remove dependencies on other elements
   uint32_t count = mBeginSpecs.Length();
   for (uint32_t i = 0; i < count; ++i) {
     nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i];
-    NS_ABORT_IF_FALSE(beginSpec,
-        "null nsSMILTimeValueSpec in list of begin specs");
+    MOZ_ASSERT(beginSpec,
+               "null nsSMILTimeValueSpec in list of begin specs");
     beginSpec->Unlink();
   }
 
   count = mEndSpecs.Length();
   for (uint32_t j = 0; j < count; ++j) {
     nsSMILTimeValueSpec* endSpec = mEndSpecs[j];
-    NS_ABORT_IF_FALSE(endSpec, "null nsSMILTimeValueSpec in list of end specs");
+    MOZ_ASSERT(endSpec, "null nsSMILTimeValueSpec in list of end specs");
     endSpec->Unlink();
   }
 
   ClearIntervals();
 
   // Make sure we don't notify other elements of new intervals
   mTimeDependents.Clear();
 }
@@ -1381,18 +1381,18 @@ nsSMILTimedElement::ClearIntervals()
   }
   mOldIntervals.Clear();
 }
 
 bool
 nsSMILTimedElement::ApplyEarlyEnd(const nsSMILTimeValue& aSampleTime)
 {
   // This should only be called within DoSampleAt as a helper function
-  NS_ABORT_IF_FALSE(mElementState == STATE_ACTIVE,
-      "Unexpected state to try to apply an early end");
+  MOZ_ASSERT(mElementState == STATE_ACTIVE,
+             "Unexpected state to try to apply an early end");
 
   bool updated = false;
 
   // Only apply an early end if we're not already ending.
   if (mCurrentInterval->End()->Time() > aSampleTime) {
     nsSMILInstanceTime* earlyEnd = CheckForEarlyEnd(aSampleTime);
     if (earlyEnd) {
       if (earlyEnd->IsDependent()) {
@@ -1692,18 +1692,18 @@ nsSMILTimedElement::FilterInstanceTimes(
 // http://www.w3.org/TR/2001/REC-smil-animation-20010904/#Timing-BeginEnd-LC-Start
 //
 bool
 nsSMILTimedElement::GetNextInterval(const nsSMILInterval* aPrevInterval,
                                     const nsSMILInterval* aReplacedInterval,
                                     const nsSMILInstanceTime* aFixedBeginTime,
                                     nsSMILInterval& aResult) const
 {
-  NS_ABORT_IF_FALSE(!aFixedBeginTime || aFixedBeginTime->Time().IsDefinite(),
-      "Unresolved or indefinite begin time specified for interval start");
+  MOZ_ASSERT(!aFixedBeginTime || aFixedBeginTime->Time().IsDefinite(),
+             "Unresolved or indefinite begin time given for interval start");
   static const nsSMILTimeValue zeroTime(0L);
 
   if (mRestartMode == RESTART_NEVER && aPrevInterval)
     return false;
 
   // Calc starting point
   nsSMILTimeValue beginAfter;
   bool prevIntervalWasZeroDur = false;
@@ -1741,19 +1741,19 @@ nsSMILTimedElement::GetNextInterval(cons
       // If we're updating the current interval then skip any begin time that is
       // dependent on the current interval's begin time. e.g.
       //   <animate id="a" begin="b.begin; a.begin+2s"...
       // If b's interval disappears whilst 'a' is in the waiting state the begin
       // time at "a.begin+2s" should be skipped since 'a' never begun.
       } while (aReplacedInterval &&
                tempBegin->GetBaseTime() == aReplacedInterval->Begin());
     }
-    NS_ABORT_IF_FALSE(tempBegin && tempBegin->Time().IsDefinite() &&
-        tempBegin->Time() >= beginAfter,
-        "Got a bad begin time while fetching next interval");
+    MOZ_ASSERT(tempBegin && tempBegin->Time().IsDefinite() &&
+               tempBegin->Time() >= beginAfter,
+               "Got a bad begin time while fetching next interval");
 
     // Calculate end time
     {
       int32_t endPos = 0;
       do {
         tempEnd =
           GetNextGreaterOrEqual(mEndInstances, tempBegin->Time(), endPos);
 
@@ -1806,17 +1806,17 @@ nsSMILTimedElement::GetNextInterval(cons
       nsSMILTimeValue intervalEnd = tempEnd
                                   ? tempEnd->Time() : nsSMILTimeValue();
       nsSMILTimeValue activeEnd = CalcActiveEnd(tempBegin->Time(), intervalEnd);
 
       if (!tempEnd || intervalEnd != activeEnd) {
         tempEnd = new nsSMILInstanceTime(activeEnd);
       }
     }
-    NS_ABORT_IF_FALSE(tempEnd, "Failed to get end point for next interval");
+    MOZ_ASSERT(tempEnd, "Failed to get end point for next interval");
 
     // When we choose the interval endpoints, we don't allow coincident
     // zero-duration intervals, so if we arrive here and we have a zero-duration
     // interval starting at the same point as a previous zero-duration interval,
     // then it must be because we've applied constraints to the active duration.
     // In that case, we will potentially run into an infinite loop, so we break
     // it by searching for the next interval that starts AFTER our current
     // zero-duration interval.
@@ -1864,17 +1864,17 @@ nsSMILTimedElement::GetNextGreaterOrEqua
                                           const nsSMILTimeValue& aBase,
                                           int32_t& aPosition) const
 {
   nsSMILInstanceTime* result = nullptr;
   int32_t count = aList.Length();
 
   for (; aPosition < count && !result; ++aPosition) {
     nsSMILInstanceTime* val = aList[aPosition].get();
-    NS_ABORT_IF_FALSE(val, "NULL instance time in list");
+    MOZ_ASSERT(val, "NULL instance time in list");
     if (val->Time() >= aBase) {
       result = val;
     }
   }
 
   return result;
 }
 
@@ -1882,20 +1882,20 @@ nsSMILTimedElement::GetNextGreaterOrEqua
  * @see SMILANIM 3.3.4
  */
 nsSMILTimeValue
 nsSMILTimedElement::CalcActiveEnd(const nsSMILTimeValue& aBegin,
                                   const nsSMILTimeValue& aEnd) const
 {
   nsSMILTimeValue result;
 
-  NS_ABORT_IF_FALSE(mSimpleDur.IsResolved(),
-    "Unresolved simple duration in CalcActiveEnd");
-  NS_ABORT_IF_FALSE(aBegin.IsDefinite(),
-    "Indefinite or unresolved begin time in CalcActiveEnd");
+  MOZ_ASSERT(mSimpleDur.IsResolved(),
+             "Unresolved simple duration in CalcActiveEnd");
+  MOZ_ASSERT(aBegin.IsDefinite(),
+             "Indefinite or unresolved begin time in CalcActiveEnd");
 
   result = GetRepeatDuration();
 
   if (aEnd.IsDefinite()) {
     nsSMILTime activeDur = aEnd.GetMillis() - aBegin.GetMillis();
 
     if (result.IsDefinite()) {
       result.SetMillis(std::min(result.GetMillis(), activeDur));
@@ -1963,19 +1963,19 @@ nsSMILTimedElement::ApplyMinAndMax(const
 }
 
 nsSMILTime
 nsSMILTimedElement::ActiveTimeToSimpleTime(nsSMILTime aActiveTime,
                                            uint32_t& aRepeatIteration)
 {
   nsSMILTime result;
 
-  NS_ABORT_IF_FALSE(mSimpleDur.IsResolved(),
-      "Unresolved simple duration in ActiveTimeToSimpleTime");
-  NS_ABORT_IF_FALSE(aActiveTime >= 0, "Expecting non-negative active time");
+  MOZ_ASSERT(mSimpleDur.IsResolved(),
+             "Unresolved simple duration in ActiveTimeToSimpleTime");
+  MOZ_ASSERT(aActiveTime >= 0, "Expecting non-negative active time");
   // Note that a negative aActiveTime will give us a negative value for
   // aRepeatIteration, which is bad because aRepeatIteration is unsigned
 
   if (mSimpleDur.IsIndefinite() || mSimpleDur.GetMillis() == 0L) {
     aRepeatIteration = 0;
     result = aActiveTime;
   } else {
     result = aActiveTime % mSimpleDur.GetMillis();
@@ -1996,18 +1996,18 @@ nsSMILTimedElement::ActiveTimeToSimpleTi
 // than) the defined end for the current interval. Ending in this manner will
 // also send a changed time notice to all time dependents for the current
 // interval end.'
 //
 nsSMILInstanceTime*
 nsSMILTimedElement::CheckForEarlyEnd(
     const nsSMILTimeValue& aContainerTime) const
 {
-  NS_ABORT_IF_FALSE(mCurrentInterval,
-      "Checking for an early end but the current interval is not set");
+  MOZ_ASSERT(mCurrentInterval,
+             "Checking for an early end but the current interval is not set");
   if (mRestartMode != RESTART_ALWAYS)
     return nullptr;
 
   int32_t position = 0;
   nsSMILInstanceTime* nextBegin =
     GetNextGreater(mBeginInstances, mCurrentInterval->Begin()->Time(),
                    position);
 
@@ -2047,45 +2047,46 @@ nsSMILTimedElement::UpdateCurrentInterva
   // In order to provide consistent behavior in such cases, we detect two
   // deletes in a row and then refuse to create any further intervals. That is,
   // we say the configuration is invalid.
   if (mDeleteCount > 1) {
     // When we update the delete count we also set the state to post active, so
     // if we're not post active here then something other than
     // UpdateCurrentInterval has updated the element state in between and all
     // bets are off.
-    NS_ABORT_IF_FALSE(mElementState == STATE_POSTACTIVE,
-      "Expected to be in post-active state after performing double delete");
+    MOZ_ASSERT(mElementState == STATE_POSTACTIVE,
+               "Expected to be in post-active state after performing double "
+               "delete");
     return;
   }
 
   // Check that we aren't stuck in infinite recursion updating some syncbase
   // dependencies. Generally such situations should be detected in advance and
   // the chain broken in a sensible and predictable manner, so if we're hitting
   // this assertion we need to work out how to detect the case that's causing
   // it. In release builds, just bail out before we overflow the stack.
   AutoRestore<uint8_t> depthRestorer(mUpdateIntervalRecursionDepth);
   if (++mUpdateIntervalRecursionDepth > sMaxUpdateIntervalRecursionDepth) {
-    NS_ABORT_IF_FALSE(false,
-        "Update current interval recursion depth exceeded threshold");
+    MOZ_ASSERT(false,
+               "Update current interval recursion depth exceeded threshold");
     return;
   }
 
   // If the interval is active the begin time is fixed.
   const nsSMILInstanceTime* beginTime = mElementState == STATE_ACTIVE
                                       ? mCurrentInterval->Begin()
                                       : nullptr;
   nsSMILInterval updatedInterval;
   if (GetNextInterval(GetPreviousInterval(), mCurrentInterval,
                       beginTime, updatedInterval)) {
 
     if (mElementState == STATE_POSTACTIVE) {
 
-      NS_ABORT_IF_FALSE(!mCurrentInterval,
-          "In postactive state but the interval has been set");
+      MOZ_ASSERT(!mCurrentInterval,
+                 "In postactive state but the interval has been set");
       mCurrentInterval = new nsSMILInterval(updatedInterval);
       mElementState = STATE_WAITING;
       NotifyNewInterval();
 
     } else {
 
       bool beginChanged = false;
       bool endChanged   = false;
@@ -2147,22 +2148,23 @@ nsSMILTimedElement::SampleFillValue()
 {
   if (mFillMode != FILL_FREEZE || !mClient)
     return;
 
   nsSMILTime activeTime;
 
   if (mElementState == STATE_WAITING || mElementState == STATE_POSTACTIVE) {
     const nsSMILInterval* prevInterval = GetPreviousInterval();
-    NS_ABORT_IF_FALSE(prevInterval,
-        "Attempting to sample fill value but there is no previous interval");
-    NS_ABORT_IF_FALSE(prevInterval->End()->Time().IsDefinite() &&
-        prevInterval->End()->IsFixedTime(),
-        "Attempting to sample fill value but the endpoint of the previous "
-        "interval is not resolved and fixed");
+    MOZ_ASSERT(prevInterval,
+               "Attempting to sample fill value but there is no previous "
+               "interval");
+    MOZ_ASSERT(prevInterval->End()->Time().IsDefinite() &&
+               prevInterval->End()->IsFixedTime(),
+               "Attempting to sample fill value but the endpoint of the "
+               "previous interval is not resolved and fixed");
 
     activeTime = prevInterval->End()->Time().GetMillis() -
                  prevInterval->Begin()->Time().GetMillis();
 
     // If the interval's repeat duration was shorter than its active duration,
     // use the end of the repeat duration to determine the frozen animation's
     // state.
     nsSMILTimeValue repeatDuration = GetRepeatDuration();
@@ -2214,18 +2216,18 @@ nsSMILTimedElement::AddInstanceTimeFromC
 }
 
 void
 nsSMILTimedElement::RegisterMilestone()
 {
   nsSMILTimeContainer* container = GetTimeContainer();
   if (!container)
     return;
-  NS_ABORT_IF_FALSE(mAnimationElement,
-      "Got a time container without an owning animation element");
+  MOZ_ASSERT(mAnimationElement,
+             "Got a time container without an owning animation element");
 
   nsSMILMilestone nextMilestone;
   if (!GetNextMilestone(nextMilestone))
     return;
 
   // This method is called every time we might possibly have updated our
   // current interval, but since nsSMILTimeContainer makes no attempt to filter
   // out redundant milestones we do some rudimentary filtering here. It's not
@@ -2260,18 +2262,18 @@ nsSMILTimedElement::GetNextMilestone(nsS
   case STATE_STARTUP:
     // All elements register for an initial end sample at t=0 where we resolve
     // our initial interval.
     aNextMilestone.mIsEnd = true; // Initial sample should be an end sample
     aNextMilestone.mTime = 0;
     return true;
 
   case STATE_WAITING:
-    NS_ABORT_IF_FALSE(mCurrentInterval,
-        "In waiting state but the current interval has not been set");
+    MOZ_ASSERT(mCurrentInterval,
+               "In waiting state but the current interval has not been set");
     aNextMilestone.mIsEnd = false;
     aNextMilestone.mTime = mCurrentInterval->Begin()->Time().GetMillis();
     return true;
 
   case STATE_ACTIVE:
     {
       // Work out what comes next: the interval end or the next repeat iteration
       nsSMILTimeValue nextRepeat;
@@ -2309,35 +2311,35 @@ nsSMILTimedElement::GetNextMilestone(nsS
     return false;
   }
   MOZ_CRASH("Invalid element state");
 }
 
 void
 nsSMILTimedElement::NotifyNewInterval()
 {
-  NS_ABORT_IF_FALSE(mCurrentInterval,
-      "Attempting to notify dependents of a new interval but the interval "
-      "is not set");
+  MOZ_ASSERT(mCurrentInterval,
+             "Attempting to notify dependents of a new interval but the "
+             "interval is not set");
 
   nsSMILTimeContainer* container = GetTimeContainer();
   if (container) {
     container->SyncPauseTime();
   }
 
   NotifyTimeDependentsParams params = { this, container };
   mTimeDependents.EnumerateEntries(NotifyNewIntervalCallback, &params);
 }
 
 void
 nsSMILTimedElement::NotifyChangedInterval(nsSMILInterval* aInterval,
                                           bool aBeginObjectChanged,
                                           bool aEndObjectChanged)
 {
-  NS_ABORT_IF_FALSE(aInterval, "Null interval for change notification");
+  MOZ_ASSERT(aInterval, "Null interval for change notification");
 
   nsSMILTimeContainer* container = GetTimeContainer();
   if (container) {
     container->SyncPauseTime();
   }
 
   // Copy the instance times list since notifying the instance times can result
   // in a chain reaction whereby our own interval gets deleted along with its
@@ -2427,23 +2429,23 @@ nsSMILTimedElement::AreEndTimesDependent
 
 //----------------------------------------------------------------------
 // Hashtable callback functions
 
 /* static */ PLDHashOperator
 nsSMILTimedElement::NotifyNewIntervalCallback(TimeValueSpecPtrKey* aKey,
                                               void* aData)
 {
-  NS_ABORT_IF_FALSE(aKey, "Null hash key for time container hash table");
-  NS_ABORT_IF_FALSE(aKey->GetKey(),
-                    "null nsSMILTimeValueSpec in set of time dependents");
+  MOZ_ASSERT(aKey, "Null hash key for time container hash table");
+  MOZ_ASSERT(aKey->GetKey(),
+             "null nsSMILTimeValueSpec in set of time dependents");
 
   NotifyTimeDependentsParams* params =
     static_cast<NotifyTimeDependentsParams*>(aData);
-  NS_ABORT_IF_FALSE(params, "null data ptr while enumerating hashtable");
+  MOZ_ASSERT(params, "null data ptr while enumerating hashtable");
   nsSMILInterval* interval = params->mTimedElement->mCurrentInterval;
   // It's possible that in notifying one new time dependent of a new interval
   // that a chain reaction is triggered which results in the original interval
   // disappearing. If that's the case we can skip sending further notifications.
   if (!interval)
     return PL_DHASH_STOP;
 
   nsSMILTimeValueSpec* spec = aKey->GetKey();
--- a/dom/smil/nsSMILValue.cpp
+++ b/dom/smil/nsSMILValue.cpp
@@ -119,26 +119,27 @@ nsSMILValue::Interpolate(const nsSMILVal
 //----------------------------------------------------------------------
 // Helper methods
 
 // Wrappers for nsISMILType::Init & ::Destroy that verify their postconditions
 void
 nsSMILValue::InitAndCheckPostcondition(const nsISMILType* aNewType)
 {
   aNewType->Init(*this);
-  NS_ABORT_IF_FALSE(mType == aNewType,
-                    "Post-condition of Init failed. nsSMILValue is invalid");
+  MOZ_ASSERT(mType == aNewType,
+             "Post-condition of Init failed. nsSMILValue is invalid");
 }
                 
 void
 nsSMILValue::DestroyAndCheckPostcondition()
 {
   mType->Destroy(*this);
-  NS_ABORT_IF_FALSE(IsNull(), "Post-condition of Destroy failed. "
-                    "nsSMILValue not null after destroying");
+  MOZ_ASSERT(IsNull(),
+             "Post-condition of Destroy failed. "
+             "nsSMILValue not null after destroying");
 }
 
 void
 nsSMILValue::DestroyAndReinit(const nsISMILType* aNewType)
 {
   DestroyAndCheckPostcondition();
   InitAndCheckPostcondition(aNewType);
 }
--- a/dom/speakermanager/SpeakerManager.cpp
+++ b/dom/speakermanager/SpeakerManager.cpp
@@ -73,17 +73,17 @@ SpeakerManager::SetForcespeaker(bool aEn
 
   service->ForceSpeaker(aEnable, mVisible);
   mForcespeaker = aEnable;
 }
 
 void
 SpeakerManager::DispatchSimpleEvent(const nsAString& aStr)
 {
-  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
+  MOZ_ASSERT(NS_IsMainThread(), "Not running on main thread");
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
 
   nsCOMPtr<nsIDOMEvent> event;
   rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
   if (NS_FAILED(rv)) {
--- a/dom/storage/DOMStorageIPC.cpp
+++ b/dom/storage/DOMStorageIPC.cpp
@@ -37,25 +37,25 @@ NS_IMETHODIMP_(MozExternalRefCountType) 
     return 0;
   }
   return count;
 }
 
 void
 DOMStorageDBChild::AddIPDLReference()
 {
-  NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references");
+  MOZ_ASSERT(!mIPCOpen, "Attempting to retain multiple IPDL references");
   mIPCOpen = true;
   AddRef();
 }
 
 void
 DOMStorageDBChild::ReleaseIPDLReference()
 {
-  NS_ABORT_IF_FALSE(mIPCOpen, "Attempting to release non-existent IPDL reference");
+  MOZ_ASSERT(mIPCOpen, "Attempting to release non-existent IPDL reference");
   mIPCOpen = false;
   Release();
 }
 
 DOMStorageDBChild::DOMStorageDBChild(DOMLocalStorageManager* aManager)
   : mManager(aManager)
   , mStatus(NS_OK)
   , mIPCOpen(false)
@@ -270,25 +270,25 @@ DOMStorageDBChild::RecvError(const nsres
 // ----------------------------------------------------------------------------
 
 NS_IMPL_ADDREF(DOMStorageDBParent)
 NS_IMPL_RELEASE(DOMStorageDBParent)
 
 void
 DOMStorageDBParent::AddIPDLReference()
 {
-  NS_ABORT_IF_FALSE(!mIPCOpen, "Attempting to retain multiple IPDL references");
+  MOZ_ASSERT(!mIPCOpen, "Attempting to retain multiple IPDL references");
   mIPCOpen = true;
   AddRef();
 }
 
 void
 DOMStorageDBParent::ReleaseIPDLReference()
 {
-  NS_ABORT_IF_FALSE(mIPCOpen, "Attempting to release non-existent IPDL reference");
+  MOZ_ASSERT(mIPCOpen, "Attempting to release non-existent IPDL reference");
   mIPCOpen = false;
   Release();
 }
 
 namespace { // anon
 
 class SendInitialChildDataRunnable : public nsRunnable
 {
--- a/dom/svg/DOMSVGLength.cpp
+++ b/dom/svg/DOMSVGLength.cpp
@@ -102,21 +102,22 @@ DOMSVGLength::DOMSVGLength(DOMSVGLengthL
   , mListIndex(aListIndex)
   , mAttrEnum(aAttrEnum)
   , mIsAnimValItem(aIsAnimValItem)
   , mUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)
   , mValue(0.0f)
   , mVal(nullptr)
 {
   // These shifts are in sync with the members in the header.
-  NS_ABORT_IF_FALSE(aList &&
-                    aAttrEnum < (1 << 4) &&
-                    aListIndex <= MaxListIndex(), "bad arg");
+  MOZ_ASSERT(aList &&
+             aAttrEnum < (1 << 4) &&
+             aListIndex <= MaxListIndex(),
+             "bad arg");
 
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
+  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!");
 }
 
 DOMSVGLength::DOMSVGLength()
   : mList(nullptr)
   , mListIndex(0)
   , mAttrEnum(0)
   , mIsAnimValItem(false)
   , mUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER)
@@ -530,17 +531,17 @@ DOMSVGLength::InsertingIntoList(DOMSVGLe
 {
   NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list");
 
   mList = aList;
   mAttrEnum = aAttrEnum;
   mListIndex = aListIndex;
   mIsAnimValItem = aIsAnimValItem;
 
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGLength!");
+  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGLength!");
 }
 
 void
 DOMSVGLength::RemovingFromList()
 {
   mValue = InternalItem().GetValueInCurrentUnits();
   mUnit  = InternalItem().GetUnit();
   mList = nullptr;
--- a/dom/svg/DOMSVGLengthList.cpp
+++ b/dom/svg/DOMSVGLengthList.cpp
@@ -362,49 +362,49 @@ DOMSVGLengthList::GetItemAt(uint32_t aIn
   }
   nsRefPtr<DOMSVGLength> result = mItems[aIndex];
   return result.forget();
 }
 
 void
 DOMSVGLengthList::MaybeInsertNullInAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   DOMSVGLengthList* animVal = mAList->mAnimVal;
 
   if (!animVal || mAList->IsAnimating()) {
     // No animVal list wrapper, or animVal not a clone of baseVal
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   animVal->mItems.InsertElementAt(aIndex, static_cast<DOMSVGLength*>(nullptr));
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex + 1);
 }
 
 void
 DOMSVGLengthList::MaybeRemoveItemFromAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   // This needs to be a strong reference; otherwise, the RemovingFromList call
   // below might drop the last reference to animVal before we're done with it.
   nsRefPtr<DOMSVGLengthList> animVal = mAList->mAnimVal;
 
   if (!animVal || mAList->IsAnimating()) {
     // No animVal list wrapper, or animVal not a clone of baseVal
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   if (animVal->mItems[aIndex]) {
     animVal->mItems[aIndex]->RemovingFromList();
   }
   animVal->mItems.RemoveElementAt(aIndex);
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex);
 }
--- a/dom/svg/DOMSVGLengthList.h
+++ b/dom/svg/DOMSVGLengthList.h
@@ -76,19 +76,19 @@ public:
     return static_cast<nsIContent*>(Element());
   }
 
   /**
    * This will normally be the same as InternalList().Length(), except if we've
    * hit OOM in which case our length will be zero.
    */
   uint32_t LengthNoFlush() const {
-    NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
-                      mItems.Length() == InternalList().Length(),
-                      "DOM wrapper's list length is out of sync");
+    MOZ_ASSERT(mItems.Length() == 0 ||
+               mItems.Length() == InternalList().Length(),
+               "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
   /// Called to notify us to syncronize our length and detach excess items.
   void InternalListLengthWillChange(uint32_t aNewLength);
 
   /**
    * Returns true if our attribute is animating (in which case our animVal is
@@ -141,18 +141,18 @@ private:
   }
 
   uint8_t Axis() const {
     return mAList->mAxis;
   }
 
   /// Used to determine if this list is the baseVal or animVal list.
   bool IsAnimValList() const {
-    NS_ABORT_IF_FALSE(this == mAList->mBaseVal || this == mAList->mAnimVal,
-                      "Calling IsAnimValList() too early?!");
+    MOZ_ASSERT(this == mAList->mBaseVal || this == mAList->mAnimVal,
+               "Calling IsAnimValList() too early?!");
     return this == mAList->mAnimVal;
   }
 
   /**
    * Get a reference to this object's corresponding internal SVGLengthList.
    *
    * To simplify the code we just have this one method for obtaining both
    * baseVal and animVal internal lists. This means that animVal lists don't
--- a/dom/svg/DOMSVGNumber.cpp
+++ b/dom/svg/DOMSVGNumber.cpp
@@ -88,21 +88,22 @@ DOMSVGNumber::DOMSVGNumber(DOMSVGNumberL
   : mList(aList)
   , mParent(aList)
   , mListIndex(aListIndex)
   , mAttrEnum(aAttrEnum)
   , mIsAnimValItem(aIsAnimValItem)
   , mValue(0.0f)
 {
   // These shifts are in sync with the members in the header.
-  NS_ABORT_IF_FALSE(aList &&
-                    aAttrEnum < (1 << 4) &&
-                    aListIndex <= MaxListIndex(), "bad arg");
+  MOZ_ASSERT(aList &&
+             aAttrEnum < (1 << 4) &&
+             aListIndex <= MaxListIndex(),
+             "bad arg");
 
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
+  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!");
 }
 
 DOMSVGNumber::DOMSVGNumber(nsISupports* aParent)
   : mList(nullptr)
   , mParent(aParent)
   , mListIndex(0)
   , mAttrEnum(0)
   , mIsAnimValItem(false)
@@ -175,17 +176,17 @@ DOMSVGNumber::InsertingIntoList(DOMSVGNu
 {
   NS_ASSERTION(!HasOwner(), "Inserting item that is already in a list");
 
   mList = aList;
   mAttrEnum = aAttrEnum;
   mListIndex = aListIndex;
   mIsAnimValItem = aIsAnimValItem;
 
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGNumber!");
+  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGNumber!");
 }
 
 void
 DOMSVGNumber::RemovingFromList()
 {
   mValue = InternalItem();
   mList = nullptr;
   mIsAnimValItem = false;
--- a/dom/svg/DOMSVGNumberList.cpp
+++ b/dom/svg/DOMSVGNumberList.cpp
@@ -341,49 +341,49 @@ DOMSVGNumberList::GetItemAt(uint32_t aIn
   }
   nsRefPtr<DOMSVGNumber> result = mItems[aIndex];
   return result.forget();
 }
 
 void
 DOMSVGNumberList::MaybeInsertNullInAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   DOMSVGNumberList* animVal = mAList->mAnimVal;
 
   if (!animVal || mAList->IsAnimating()) {
     // No animVal list wrapper, or animVal not a clone of baseVal
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   animVal->mItems.InsertElementAt(aIndex, static_cast<DOMSVGNumber*>(nullptr));
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex + 1);
 }
 
 void
 DOMSVGNumberList::MaybeRemoveItemFromAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   // This needs to be a strong reference; otherwise, the RemovingFromList call
   // below might drop the last reference to animVal before we're done with it.
   nsRefPtr<DOMSVGNumberList> animVal = mAList->mAnimVal;
 
   if (!animVal || mAList->IsAnimating()) {
     // No animVal list wrapper, or animVal not a clone of baseVal
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   if (animVal->mItems[aIndex]) {
     animVal->mItems[aIndex]->RemovingFromList();
   }
   animVal->mItems.RemoveElementAt(aIndex);
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex);
 }
--- a/dom/svg/DOMSVGNumberList.h
+++ b/dom/svg/DOMSVGNumberList.h
@@ -76,19 +76,19 @@ public:
     return static_cast<nsIContent*>(Element());
   }
 
   /**
    * This will normally be the same as InternalList().Length(), except if we've
    * hit OOM in which case our length will be zero.
    */
   uint32_t LengthNoFlush() const {
-    NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
-                      mItems.Length() == InternalList().Length(),
-                      "DOM wrapper's list length is out of sync");
+    MOZ_ASSERT(mItems.Length() == 0 ||
+               mItems.Length() == InternalList().Length(),
+               "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
   /// Called to notify us to syncronize our length and detach excess items.
   void InternalListLengthWillChange(uint32_t aNewLength);
 
   /**
    * Returns true if our attribute is animating (in which case our animVal is
@@ -134,18 +134,18 @@ private:
   }
 
   uint8_t AttrEnum() const {
     return mAList->mAttrEnum;
   }
 
   /// Used to determine if this list is the baseVal or animVal list.
   bool IsAnimValList() const {
-    NS_ABORT_IF_FALSE(this == mAList->mBaseVal || this == mAList->mAnimVal,
-                      "Calling IsAnimValList() too early?!");
+    MOZ_ASSERT(this == mAList->mBaseVal || this == mAList->mAnimVal,
+               "Calling IsAnimValList() too early?!");
     return this == mAList->mAnimVal;
   }
 
   /**
    * Get a reference to this object's corresponding internal SVGNumberList.
    *
    * To simplify the code we just have this one method for obtaining both
    * baseVal and animVal internal lists. This means that animVal lists don't
--- a/dom/svg/DOMSVGPathSeg.cpp
+++ b/dom/svg/DOMSVGPathSeg.cpp
@@ -75,57 +75,56 @@ private:
 DOMSVGPathSeg::DOMSVGPathSeg(DOMSVGPathSegList *aList,
                              uint32_t aListIndex,
                              bool aIsAnimValItem)
   : mList(aList)
   , mListIndex(aListIndex)
   , mIsAnimValItem(aIsAnimValItem)
 {
   // These shifts are in sync with the members in the header.
-  NS_ABORT_IF_FALSE(aList &&
-                    aListIndex <= MaxListIndex(), "bad arg");
+  MOZ_ASSERT(aList && aListIndex <= MaxListIndex(), "bad arg");
 
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
+  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
 }
 
 DOMSVGPathSeg::DOMSVGPathSeg()
   : mList(nullptr)
   , mListIndex(0)
   , mIsAnimValItem(false)
 {
 }
 
 void
 DOMSVGPathSeg::InsertingIntoList(DOMSVGPathSegList *aList,
                                  uint32_t aListIndex,
                                  bool aIsAnimValItem)
 {
-  NS_ABORT_IF_FALSE(!HasOwner(), "Inserting item that is already in a list");
+  MOZ_ASSERT(!HasOwner(), "Inserting item that is already in a list");
 
   mList = aList;
   mListIndex = aListIndex;
   mIsAnimValItem = aIsAnimValItem;
 
-  NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
+  MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPathSeg!");
 }
 
 void
 DOMSVGPathSeg::RemovingFromList()
 {
   uint32_t argCount = SVGPathSegUtils::ArgCountForType(Type());
   // InternalItem() + 1, because the args come after the encoded seg type
   memcpy(PtrToMemberArgs(), InternalItem() + 1, argCount * sizeof(float));
   mList = nullptr;
   mIsAnimValItem = false;
 }
 
 void
 DOMSVGPathSeg::ToSVGPathSegEncodedData(float* aRaw)
 {
-  NS_ABORT_IF_FALSE(aRaw, "null pointer");
+  MOZ_ASSERT(aRaw, "null pointer");
   uint32_t argCount = SVGPathSegUtils::ArgCountForType(Type());
   if (IsInList()) {
     // 1 + argCount, because we're copying the encoded seg type and args
     memcpy(aRaw, InternalItem(), (1 + argCount) * sizeof(float));
   } else {
     aRaw[0] = SVGPathSegUtils::EncodeType(Type());
     // aRaw + 1, because the args go after the encoded seg type
     memcpy(aRaw + 1, PtrToMemberArgs(), argCount * sizeof(float));
--- a/dom/svg/DOMSVGPathSeg.h
+++ b/dom/svg/DOMSVGPathSeg.h
@@ -15,20 +15,20 @@
 
 class nsSVGElement;
 
 #define MOZ_SVG_LIST_INDEX_BIT_COUNT 31
 
 namespace mozilla {
 
 #define CHECK_ARG_COUNT_IN_SYNC(segType)                                      \
-          NS_ABORT_IF_FALSE(ArrayLength(mArgs) ==                             \
-            SVGPathSegUtils::ArgCountForType(uint32_t(segType)) ||            \
-            uint32_t(segType) == PATHSEG_CLOSEPATH,                           \
-            "Arg count/array size out of sync")
+  MOZ_ASSERT(ArrayLength(mArgs) ==                                            \
+               SVGPathSegUtils::ArgCountForType(uint32_t(segType)) ||         \
+             uint32_t(segType) == PATHSEG_CLOSEPATH,                          \
+             "Arg count/array size out of sync")
 
 #define IMPL_SVGPATHSEG_SUBCLASS_COMMON(segName, segType)                     \
   explicit DOMSVGPathSeg##segName(const float *aArgs)                         \
     : DOMSVGPathSeg()                                                         \
   {                                                                           \
     CHECK_ARG_COUNT_IN_SYNC(segType);                                         \
     memcpy(mArgs, aArgs,                                                      \
         SVGPathSegUtils::ArgCountForType(uint32_t(segType)) * sizeof(float)); \
--- a/dom/svg/DOMSVGPathSegList.cpp
+++ b/dom/svg/DOMSVGPathSegList.cpp
@@ -185,19 +185,19 @@ DOMSVGPathSegList::InternalListWillChang
       ItemAt(index) = nullptr;
     }
     // Only after the RemovingFromList() can we touch mInternalDataIndex!
     mItems[index].mInternalDataIndex = dataIndex;
     ++index;
     dataIndex += 1 + SVGPathSegUtils::ArgCountForType(newSegType);
   }
 
-  NS_ABORT_IF_FALSE((index == length && dataIndex <= dataLength) ||
-                    (index <= length && dataIndex == dataLength),
-                    "very bad - list corruption?");
+  MOZ_ASSERT((index == length && dataIndex <= dataLength) ||
+             (index <= length && dataIndex == dataLength),
+             "very bad - list corruption?");
 
   if (index < length) {
     // aNewValue has fewer items than our previous internal counterpart
 
     uint32_t newLength = index;
 
     // Remove excess items from the list:
     for (; index < length; ++index) {
@@ -227,18 +227,18 @@ DOMSVGPathSegList::InternalListWillChang
         Clear(rv);
         MOZ_ASSERT(!rv.Failed());
         return;
       }
       dataIndex += 1 + SVGPathSegUtils::ArgCountForType(SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]));
     }
   }
 
-  NS_ABORT_IF_FALSE(dataIndex == dataLength, "Serious processing error");
-  NS_ABORT_IF_FALSE(index == length, "Serious counting error");
+  MOZ_ASSERT(dataIndex == dataLength, "Serious processing error");
+  MOZ_ASSERT(index == length, "Serious counting error");
 }
 
 bool
 DOMSVGPathSegList::AttrIsAnimating() const
 {
   return InternalAList().IsAnimating();
 }
 
@@ -247,17 +247,17 @@ DOMSVGPathSegList::InternalList() const
 {
   SVGAnimatedPathSegList *alist = mElement->GetAnimPathSegList();
   return mIsAnimValList && alist->IsAnimating() ? *alist->mAnimVal : alist->mBaseVal;
 }
 
 SVGAnimatedPathSegList&
 DOMSVGPathSegList::InternalAList() const
 {
-  NS_ABORT_IF_FALSE(mElement->GetAnimPathSegList(), "Internal error");
+  MOZ_ASSERT(mElement->GetAnimPathSegList(), "Internal error");
   return *mElement->GetAnimPathSegList();
 }
 
 // ----------------------------------------------------------------------------
 // nsIDOMSVGPathSegList implementation:
 
 void
 DOMSVGPathSegList::Clear(ErrorResult& aError)
@@ -513,62 +513,62 @@ DOMSVGPathSegList::GetItemAt(uint32_t aI
 }
 
 void
 DOMSVGPathSegList::
   MaybeInsertNullInAnimValListAt(uint32_t aIndex,
                                  uint32_t aInternalIndex,
                                  uint32_t aArgCountForItem)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   if (AttrIsAnimating()) {
     // animVal not a clone of baseVal
     return;
   }
 
   // The anim val list is in sync with the base val list
   DOMSVGPathSegList *animVal =
     GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
   if (!animVal) {
     // No animVal list wrapper
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   animVal->mItems.InsertElementAt(aIndex, ItemProxy(nullptr, aInternalIndex));
 
   animVal->UpdateListIndicesFromIndex(aIndex + 1, 1 + aArgCountForItem);
 }
 
 void
 DOMSVGPathSegList::
   MaybeRemoveItemFromAnimValListAt(uint32_t aIndex,
                                    int32_t aArgCountForItem)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   if (AttrIsAnimating()) {
     // animVal not a clone of baseVal
     return;
   }
 
   // This needs to be a strong reference; otherwise, the RemovingFromList call
   // below might drop the last reference to animVal before we're done with it.
   nsRefPtr<DOMSVGPathSegList> animVal =
     GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
   if (!animVal) {
     // No animVal list wrapper
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   if (animVal->ItemAt(aIndex)) {
     animVal->ItemAt(aIndex)->RemovingFromList();
   }
   animVal->mItems.RemoveElementAt(aIndex);
 
   animVal->UpdateListIndicesFromIndex(aIndex, -(1 + aArgCountForItem));
 }
--- a/dom/svg/DOMSVGPathSegList.h
+++ b/dom/svg/DOMSVGPathSegList.h
@@ -93,19 +93,19 @@ public:
   static DOMSVGPathSegList*
   GetDOMWrapperIfExists(void *aList);
 
   /**
    * This will normally be the same as InternalList().CountItems(), except if
    * we've hit OOM, in which case our length will be zero.
    */
   uint32_t LengthNoFlush() const {
-    NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
-                      mItems.Length() == InternalList().CountItems(),
-                      "DOM wrapper's list length is out of sync");
+    MOZ_ASSERT(mItems.Length() == 0 ||
+               mItems.Length() == InternalList().CountItems(),
+               "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
   /**
    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
    * must also call it on the animVal wrapper too if necessary!! See other
    * callers!
    *
--- a/dom/svg/DOMSVGPoint.h
+++ b/dom/svg/DOMSVGPoint.h
@@ -52,20 +52,19 @@ public:
               bool aIsAnimValItem)
     : nsISVGPoint()
   {
     mList = aList;
     mListIndex = aListIndex;
     mIsAnimValItem = aIsAnimValItem;
 
     // These shifts are in sync with the members.
-    NS_ABORT_IF_FALSE(aList &&
-                      aListIndex <= MaxListIndex(), "bad arg");
+    MOZ_ASSERT(aList && aListIndex <= MaxListIndex(), "bad arg");
 
-    NS_ABORT_IF_FALSE(IndexIsValid(), "Bad index for DOMSVGPoint!");
+    MOZ_ASSERT(IndexIsValid(), "Bad index for DOMSVGPoint!");
   }
 
   explicit DOMSVGPoint(const DOMSVGPoint *aPt = nullptr)
     : nsISVGPoint()
   {
     if (aPt) {
       mPt = aPt->ToSVGPoint();
     }
--- a/dom/svg/DOMSVGPointList.cpp
+++ b/dom/svg/DOMSVGPointList.cpp
@@ -189,17 +189,17 @@ DOMSVGPointList::InternalList() const
 {
   SVGAnimatedPointList *alist = mElement->GetAnimatedPointList();
   return mIsAnimValList && alist->IsAnimating() ? *alist->mAnimVal : alist->mBaseVal;
 }
 
 SVGAnimatedPointList&
 DOMSVGPointList::InternalAList() const
 {
-  NS_ABORT_IF_FALSE(mElement->GetAnimatedPointList(), "Internal error");
+  MOZ_ASSERT(mElement->GetAnimatedPointList(), "Internal error");
   return *mElement->GetAnimatedPointList();
 }
 
 // ----------------------------------------------------------------------------
 // nsIDOMSVGPointList implementation:
 
 void
 DOMSVGPointList::Clear(ErrorResult& aError)
@@ -409,60 +409,60 @@ DOMSVGPointList::GetItemAt(uint32_t aInd
   }
   nsRefPtr<nsISVGPoint> result = mItems[aIndex];
   return result.forget();
 }
 
 void
 DOMSVGPointList::MaybeInsertNullInAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   if (AttrIsAnimating()) {
     // animVal not a clone of baseVal
     return;
   }
 
   // The anim val list is in sync with the base val list
   DOMSVGPointList *animVal =
     GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
   if (!animVal) {
     // No animVal list wrapper
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   animVal->mItems.InsertElementAt(aIndex, static_cast<nsISVGPoint*>(nullptr));
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex + 1);
 }
 
 void
 DOMSVGPointList::MaybeRemoveItemFromAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   if (AttrIsAnimating()) {
     // animVal not a clone of baseVal
     return;
   }
 
   // This needs to be a strong reference; otherwise, the RemovingFromList call
   // below might drop the last reference to animVal before we're done with it.
   nsRefPtr<DOMSVGPointList> animVal =
     GetDOMWrapperIfExists(InternalAList().GetAnimValKey());
   if (!animVal) {
     // No animVal list wrapper
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   if (animVal->mItems[aIndex]) {
     animVal->mItems[aIndex]->RemovingFromList();
   }
   animVal->mItems.RemoveElementAt(aIndex);
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex);
 }
--- a/dom/svg/DOMSVGPointList.h
+++ b/dom/svg/DOMSVGPointList.h
@@ -95,19 +95,19 @@ public:
   static DOMSVGPointList*
   GetDOMWrapperIfExists(void *aList);
 
   /**
    * This will normally be the same as InternalList().Length(), except if
    * we've hit OOM, in which case our length will be zero.
    */
   uint32_t LengthNoFlush() const {
-    NS_ABORT_IF_FALSE(mItems.Length() == 0 ||
-                      mItems.Length() == InternalList().Length(),
-                      "DOM wrapper's list length is out of sync");
+    MOZ_ASSERT(mItems.Length() == 0 ||
+               mItems.Length() == InternalList().Length(),
+               "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
   /**
    * WATCH OUT! If you add code to call this on a baseVal wrapper, then you
    * must also call it on the animVal wrapper too if necessary!! See other
    * callers!
    *
--- a/dom/svg/DOMSVGTransformList.cpp
+++ b/dom/svg/DOMSVGTransformList.cpp
@@ -388,50 +388,50 @@ DOMSVGTransformList::GetItemAt(uint32_t 
   }
   nsRefPtr<SVGTransform> result = mItems[aIndex];
   return result.forget();
 }
 
 void
 DOMSVGTransformList::MaybeInsertNullInAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   DOMSVGTransformList* animVal = mAList->mAnimVal;
 
   if (!animVal || mAList->IsAnimating()) {
     // No animVal list wrapper, or animVal not a clone of baseVal
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   animVal->mItems.InsertElementAt(aIndex,
                                   static_cast<SVGTransform*>(nullptr));
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex + 1);
 }
 
 void
 DOMSVGTransformList::MaybeRemoveItemFromAnimValListAt(uint32_t aIndex)
 {
-  NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal");
+  MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal");
 
   // This needs to be a strong reference; otherwise, the RemovingFromList call
   // below might drop the last reference to animVal before we're done with it.
   nsRefPtr<DOMSVGTransformList> animVal = mAList->mAnimVal;
 
   if (!animVal || mAList->IsAnimating()) {
     // No animVal list wrapper, or animVal not a clone of baseVal
     return;
   }
 
-  NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(),
-                    "animVal list not in sync!");
+  MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(),
+             "animVal list not in sync!");
 
   if (animVal->mItems[aIndex]) {
     animVal->mItems[aIndex]->RemovingFromList();
   }
   animVal->mItems.RemoveElementAt(aIndex);
 
   UpdateListIndicesFromIndex(animVal->mItems, aIndex);
 }
--- a/dom/svg/DOMSVGTransformList.h
+++ b/dom/svg/DOMSVGTransformList.h
@@ -71,19 +71,18 @@ public:
     return static_cast<nsIContent*>(Element());
   }
 
   /**
    * This will normally be the same as InternalList().Length(), except if we've
    * hit OOM in which case our length will be zero.
    */
   uint32_t LengthNoFlush() const {
-    NS_ABORT_IF_FALSE(mItems.IsEmpty() ||
-      mItems.Length() == InternalList().Length(),
-      "DOM wrapper's list length is out of sync");
+    MOZ_ASSERT(mItems.IsEmpty() || mItems.Length() == InternalList().Length(),
+               "DOM wrapper's list length is out of sync");
     return mItems.Length();
   }
 
   /// Called to notify us to synchronize our length and detach excess items.
   void InternalListLengthWillChange(uint32_t aNewLength);
 
   /**
    * Returns true if our attribute is animating (in which case our animVal is
@@ -130,18 +129,18 @@ public:
 private:
 
   nsSVGElement* Element() const {
     return mAList->mElement;
   }
 
   /// Used to determine if this list is the baseVal or animVal list.
   bool IsAnimValList() const {
-    NS_ABORT_IF_FALSE(this == mAList->mBaseVal || this == mAList->mAnimVal,
-                      "Calling IsAnimValList() too early?!");
+    MOZ_ASSERT(this == mAList->mBaseVal || this == mAList->mAnimVal,
+               "Calling IsAnimValList() too early?!");
     return this == mAList->mAnimVal;
   }
 
   /**
    * Get a reference to this object's corresponding internal SVGTransformList.
    *
    * To simplify the code we just have this one method for obtaining both
    * baseVal and animVal internal lists. This means that animVal lists don't
--- a/dom/svg/SVGAnimationElement.cpp
+++ b/dom/svg/SVGAnimationElement.cpp
@@ -77,19 +77,19 @@ SVGAnimationElement::HasAnimAttr(nsIAtom
 }
 
 Element*
 SVGAnimationElement::GetTargetElementContent()
 {
   if (HasAttr(kNameSpaceID_XLink, nsGkAtoms::href)) {
     return mHrefTarget.get();
   }
-  NS_ABORT_IF_FALSE(!mHrefTarget.get(),
-                    "We shouldn't have an xlink:href target "
-                    "if we don't have an xlink:href attribute");
+  MOZ_ASSERT(!mHrefTarget.get(),
+             "We shouldn't have an xlink:href target "
+             "if we don't have an xlink:href attribute");
 
   // No "xlink:href" attribute --> I should target my parent.
   nsIContent* parent = GetFlattenedTreeParent();
   return parent && parent->IsElement() ? parent->AsElement() : nullptr;
 }
 
 bool
 SVGAnimationElement::GetTargetAttributeName(int32_t *aNamespaceID,
@@ -186,19 +186,18 @@ SVGAnimationElement::GetSimpleDuration(E
 // nsIContent methods
 
 nsresult
 SVGAnimationElement::BindToTree(nsIDocument* aDocument,
                                 nsIContent* aParent,
                                 nsIContent* aBindingParent,
                                 bool aCompileEventHandlers)
 {
-  NS_ABORT_IF_FALSE(!mHrefTarget.get(),
-                    "Shouldn't have href-target yet "
-                    "(or it should've been cleared)");
+  MOZ_ASSERT(!mHrefTarget.get(),
+             "Shouldn't have href-target yet (or it should've been cleared)");
   nsresult rv = SVGAnimationElementBase::BindToTree(aDocument, aParent,
                                                     aBindingParent,
                                                     aCompileEventHandlers);
   NS_ENSURE_SUCCESS(rv,rv);
 
   // XXXdholbert is GetCtx (as a check for SVG parent) still needed here?
   if (!GetCtx()) {
     // No use proceeding. We don't have an SVG parent (yet) so we won't be able
@@ -309,18 +308,18 @@ SVGAnimationElement::AfterSetAttr(int32_
 
   if (aNamespaceID != kNameSpaceID_XLink || aName != nsGkAtoms::href)
     return rv;
 
   if (!aValue) {
     mHrefTarget.Unlink();
     AnimationTargetChanged();
   } else if (IsInDoc()) {
-    NS_ABORT_IF_FALSE(aValue->Type() == nsAttrValue::eString,
-                      "Expected href attribute to be string type");
+    MOZ_ASSERT(aValue->Type() == nsAttrValue::eString,
+               "Expected href attribute to be string type");
     UpdateHrefTarget(this, aValue->GetStringValue());
   } // else: we're not yet in a document -- we'll update the target on
     // next BindToTree call.
 
   return rv;
 }
 
 nsresult
--- a/dom/svg/SVGContentUtils.cpp
+++ b/dom/svg/SVGContentUtils.cpp
@@ -51,18 +51,18 @@ SVGContentUtils::GetOuterSVGElement(nsSV
     return static_cast<SVGSVGElement*>(element);
   }
   return nullptr;
 }
 
 void
 SVGContentUtils::ActivateByHyperlink(nsIContent *aContent)
 {
-  NS_ABORT_IF_FALSE(aContent->IsNodeOfType(nsINode::eANIMATION),
-                    "Expecting an animation element");
+  MOZ_ASSERT(aContent->IsNodeOfType(nsINode::eANIMATION),
+             "Expecting an animation element");
 
   static_cast<SVGAnimationElement*>(aContent)->ActivateByHyperlink();
 }
 
 enum DashState {
   eDashedStroke,
   eContinuousStroke, //< all dashes, no gaps
   eNoStroke          //< all gaps, no dashes
@@ -277,27 +277,27 @@ SVGContentUtils::GetFontSize(Element *aE
   }
 
   return GetFontSize(styleContext);
 }
 
 float
 SVGContentUtils::GetFontSize(nsIFrame *aFrame)
 {
-  NS_ABORT_IF_FALSE(aFrame, "NULL frame in GetFontSize");
+  MOZ_ASSERT(aFrame, "NULL frame in GetFontSize");
   return GetFontSize(aFrame->StyleContext());
 }
 
 float
 SVGContentUtils::GetFontSize(nsStyleContext *aStyleContext)
 {
-  NS_ABORT_IF_FALSE(aStyleContext, "NULL style context in GetFontSize");
+  MOZ_ASSERT(aStyleContext, "NULL style context in GetFontSize");
 
   nsPresContext *presContext = aStyleContext->PresContext();
-  NS_ABORT_IF_FALSE(presContext, "NULL pres context in GetFontSize");
+  MOZ_ASSERT(presContext, "NULL pres context in GetFontSize");
 
   nscoord fontSize = aStyleContext->StyleFont()->mSize;
   return nsPresContext::AppUnitsToFloatCSSPixels(fontSize) / 
          presContext->TextZoom();
 }
 
 float
 SVGContentUtils::GetFontXHeight(Element *aElement)
@@ -315,27 +315,27 @@ SVGContentUtils::GetFontXHeight(Element 
   }
 
   return GetFontXHeight(styleContext);
 }
   
 float
 SVGContentUtils::GetFontXHeight(nsIFrame *aFrame)
 {
-  NS_ABORT_IF_FALSE(aFrame, "NULL frame in GetFontXHeight");
+  MOZ_ASSERT(aFrame, "NULL frame in GetFontXHeight");
   return GetFontXHeight(aFrame->StyleContext());
 }
 
 float
 SVGContentUtils::GetFontXHeight(nsStyleContext *aStyleContext)
 {
-  NS_ABORT_IF_FALSE(aStyleContext, "NULL style context in GetFontXHeight");
+  MOZ_ASSERT(aStyleContext, "NULL style context in GetFontXHeight");
 
   nsPresContext *presContext = aStyleContext->PresContext();
-  NS_ABORT_IF_FALSE(presContext, "NULL pres context in GetFontXHeight");
+  MOZ_ASSERT(presContext, "NULL pres context in GetFontXHeight");
 
   nsRefPtr<nsFontMetrics> fontMetrics;
   nsLayoutUtils::GetFontMetricsForStyleContext(aStyleContext,
                                                getter_AddRefs(fontMetrics));
 
   if (!fontMetrics) {
     // ReportToConsole
     NS_WARNING("no FontMetrics in GetFontXHeight()");
--- a/dom/svg/SVGFEImageElement.cpp
+++ b/dom/svg/SVGFEImageElement.cpp
@@ -329,17 +329,17 @@ NS_IMETHODIMP
 SVGFEImageElement::Notify(imgIRequest* aRequest, int32_t aType, const nsIntRect* aData)
 {
   nsresult rv = nsImageLoadingContent::Notify(aRequest, aType, aData);
 
   if (aType == imgINotificationObserver::SIZE_AVAILABLE) {
     // Request a decode
     nsCOMPtr<imgIContainer> container;
     aRequest->GetImage(getter_AddRefs(container));
-    NS_ABORT_IF_FALSE(container, "who sent the notification then?");
+    MOZ_ASSERT(container, "who sent the notification then?");
     container->StartDecoding();
   }
 
   if (aType == imgINotificationObserver::LOAD_COMPLETE ||
       aType == imgINotificationObserver::FRAME_UPDATE ||
       aType == imgINotificationObserver::SIZE_AVAILABLE) {
     Invalidate();
   }
--- a/dom/svg/SVGForeignObjectElement.cpp
+++ b/dom/svg/SVGForeignObjectElement.cpp
@@ -84,17 +84,17 @@ SVGForeignObjectElement::PrependLocalTra
   // our 'x' and 'y' attributes:
   float x, y;
   const_cast<SVGForeignObjectElement*>(this)->
     GetAnimatedLengthValues(&x, &y, nullptr);
   gfxMatrix toUserSpace = gfxMatrix::Translation(x, y);
   if (aWhich == eChildToUserSpace) {
     return toUserSpace * aMatrix;
   }
-  NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
+  MOZ_ASSERT(aWhich == eAllTransforms, "Unknown TransformTypes");
   return toUserSpace * fromUserSpace;
 }
 
 /* virtual */ bool
 SVGForeignObjectElement::HasValidDimensions() const
 {
   return mLengthAttributes[ATTR_WIDTH].IsExplicitlySet() &&
          mLengthAttributes[ATTR_WIDTH].GetAnimValInSpecifiedUnits() > 0 &&
--- a/dom/svg/SVGFragmentIdentifier.cpp
+++ b/dom/svg/SVGFragmentIdentifier.cpp
@@ -233,18 +233,18 @@ SVGFragmentIdentifier::ProcessSVGViewSpe
 
   return true;
 }
 
 bool
 SVGFragmentIdentifier::ProcessFragmentIdentifier(nsIDocument* aDocument,
                                                  const nsAString& aAnchorName)
 {
-  NS_ABORT_IF_FALSE(aDocument->GetRootElement()->IsSVG(nsGkAtoms::svg),
-                    "expecting an SVG root element");
+  MOZ_ASSERT(aDocument->GetRootElement()->IsSVG(nsGkAtoms::svg),
+             "expecting an SVG root element");
 
   dom::SVGSVGElement* rootElement =
     static_cast<dom::SVGSVGElement*>(aDocument->GetRootElement());
 
   if (!rootElement->mUseCurrentView) {
     SaveOldViewBox(rootElement);
     SaveOldPreserveAspectRatio(rootElement);
     SaveOldZoomAndPan(rootElement);
deleted file mode 100644
--- a/dom/svg/SVGIFrameElement.cpp
+++ /dev/null
@@ -1,343 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "SVGIFrameElement.h"
-
-#include "GeckoProfiler.h"
-#include "mozilla/ArrayUtils.h"
-#include "nsCOMPtr.h"
-#include "nsGkAtoms.h"
-#include "mozilla/dom/SVGDocumentBinding.h"
-#include "mozilla/dom/SVGIFrameElementBinding.h"
-#include "mozilla/dom/SVGMatrix.h"
-#include "mozilla/dom/SVGSVGElement.h"
-#include "mozilla/Preferences.h"
-#include "nsStyleConsts.h"
-
-NS_IMPL_NS_NEW_NAMESPACED_SVG_ELEMENT_CHECK_PARSER(IFrame)
-
-namespace mozilla {
-namespace dom {
-
-JSObject*
-SVGIFrameElement::WrapNode(JSContext *aCx)
-{
-  return SVGIFrameElementBinding::Wrap(aCx, this);
-}
-  
-//--------------------- IFrame ------------------------
-
-nsSVGElement::LengthInfo SVGIFrameElement::sLengthInfo[4] =
-{
-  { &nsGkAtoms::x, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
-  { &nsGkAtoms::y, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y },
-  { &nsGkAtoms::width, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::X },
-  { &nsGkAtoms::height, 0, nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER, SVGContentUtils::Y }
-};
-
-//----------------------------------------------------------------------
-// nsISupports methods
-NS_IMPL_ISUPPORTS_INHERITED(SVGIFrameElement, SVGIFrameElementBase,
-                            nsIFrameLoaderOwner,
-                            nsIDOMNode, nsIDOMElement,
-                            nsIDOMSVGElement)
-//----------------------------------------------------------------------
-// Implementation
-
-SVGIFrameElement::SVGIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
-                                   FromParser aFromParser)
-  : SVGIFrameElementBase(aNodeInfo)
-  , nsElementFrameLoaderOwner(aFromParser)
-{
-}
-
-SVGIFrameElement::~SVGIFrameElement()
-{
-}
-
-//----------------------------------------------------------------------
-// nsSVGElement methods
-
-/* virtual */ gfxMatrix
-SVGIFrameElement::PrependLocalTransformsTo(const gfxMatrix &aMatrix,
-                                           TransformTypes aWhich) const
-{
-  // 'transform' attribute:
-  gfxMatrix fromUserSpace =
-    SVGGraphicsElement::PrependLocalTransformsTo(aMatrix, aWhich);
-  if (aWhich == eUserSpaceToParent) {
-    return fromUserSpace;
-  }
-  // our 'x' and 'y' attributes:
-  float x, y;
-  const_cast<SVGIFrameElement*>(this)->
-    GetAnimatedLengthValues(&x, &y, nullptr);
-  gfxMatrix toUserSpace = gfxMatrix::Translation(x, y);
-  if (aWhich == eChildToUserSpace) {
-    return toUserSpace;
-  }
-  NS_ABORT_IF_FALSE(aWhich == eAllTransforms, "Unknown TransformTypes");
-  return toUserSpace * fromUserSpace;
-}
-  
-  
-//----------------------------------------------------------------------
-// nsIDOMNode methods
-
-nsresult
-SVGIFrameElement::Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const
-{
-  *aResult = nullptr;
-  already_AddRefed<mozilla::dom::NodeInfo> ni = nsRefPtr<mozilla::dom::NodeInfo>(aNodeInfo).forget();
-  SVGIFrameElement *it = new SVGIFrameElement(ni, NOT_FROM_PARSER);
-
-  nsCOMPtr<nsINode> kungFuDeathGrip = it;
-  nsresult rv1 = it->Init();
-  nsresult rv2 = const_cast<SVGIFrameElement*>(this)->CopyInnerTo(it);
-  if (NS_SUCCEEDED(rv1) && NS_SUCCEEDED(rv2)) {
-    kungFuDeathGrip.swap(*aResult);
-  }
-
-  return NS_FAILED(rv1) ? rv1 : rv2;
-}
-
-//----------------------------------------------------------------------
-// nsSVGElement methods
-  
-nsSVGElement::LengthAttributesInfo
-SVGIFrameElement::GetLengthInfo()
-{
-  return LengthAttributesInfo(mLengthAttributes, sLengthInfo,
-                              ArrayLength(sLengthInfo));
-}
-
-SVGAnimatedPreserveAspectRatio *
-SVGIFrameElement::GetPreserveAspectRatio()
-{
-  return &mPreserveAspectRatio;
-}
-
-//----------------------------------------------------------------------
-// nsIDOMSVGIFrameElement methods:
-
-already_AddRefed<SVGAnimatedLength>
-SVGIFrameElement::X()
-{
-  return mLengthAttributes[ATTR_X].ToDOMAnimatedLength(this);
-}
-
-already_AddRefed<SVGAnimatedLength>
-SVGIFrameElement::Y()
-{
-  return mLengthAttributes[ATTR_Y].ToDOMAnimatedLength(this);
-}
-
-already_AddRefed<SVGAnimatedLength>
-SVGIFrameElement::Width()
-{
-  return mLengthAttributes[ATTR_WIDTH].ToDOMAnimatedLength(this);
-}
-
-already_AddRefed<SVGAnimatedLength>
-SVGIFrameElement::Height()
-{
-  return mLengthAttributes[ATTR_HEIGHT].ToDOMAnimatedLength(this);
-}
-
-already_AddRefed<DOMSVGAnimatedPreserveAspectRatio>
-SVGIFrameElement::PreserveAspectRatio()
-{
-  return mPreserveAspectRatio.ToDOMAnimatedPreserveAspectRatio(this);
-}
-
-void
-SVGIFrameElement::GetName(DOMString& name)
-{
-  GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
-}
-
-void
-SVGIFrameElement::GetSrc(DOMString& src)
-{
-  GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
-}
-
-void
-SVGIFrameElement::GetSrcdoc(DOMString& srcdoc)
-{
-  GetAttr(kNameSpaceID_None, nsGkAtoms::srcdoc, srcdoc);
-}
-
-nsDOMSettableTokenList*
-SVGIFrameElement::Sandbox()
-{
-  return GetTokenList(nsGkAtoms::sandbox);
-}
-
-bool
-SVGIFrameElement::ParseAttribute(int32_t aNamespaceID,
-                                 nsIAtom* aAttribute,
-                                 const nsAString& aValue,
-                                 nsAttrValue& aResult)
-{
-  if (aNamespaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::sandbox) {
-      aResult.ParseAtomArray(aValue);
-      return true;
-    }
-  }
-  return SVGIFrameElementBase::ParseAttribute(aNamespaceID, aAttribute,
-                                              aValue, aResult);
-}
-
-nsresult
-SVGIFrameElement::SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                          nsIAtom* aPrefix, const nsAString& aValue,
-                          bool aNotify)
-{
-  nsresult rv = nsSVGElement::SetAttr(aNameSpaceID, aName, aPrefix,
-                                      aValue, aNotify);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aNameSpaceID == kNameSpaceID_None) {
-    if (aName == nsGkAtoms::src &&
-        !HasAttr(kNameSpaceID_None,nsGkAtoms::srcdoc)) {
-      // Don't propagate error here. The attribute was successfully set, that's
-      // what we should reflect.
-      LoadSrc();
-    }
-    if (aName == nsGkAtoms::srcdoc) {
-      // Don't propagate error here. The attribute was successfully set, that's
-      // what we should reflect.
-      LoadSrc();
-    }
-  }
-  return NS_OK;
-}
-
-nsresult
-SVGIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                               const nsAttrValue* aValue,
-                               bool aNotify)
-{
-  if (aNameSpaceID == kNameSpaceID_None) {
-    if (aName == nsGkAtoms::sandbox && mFrameLoader) {
-      // If we have an nsFrameLoader, apply the new sandbox flags.
-      // Since this is called after the setter, the sandbox flags have
-      // alreay been updated.
-      mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
-    }
-  }
-  return nsSVGElement::AfterSetAttr(aNameSpaceID, aName, aValue, aNotify);
-}
-
-nsresult
-SVGIFrameElement::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                            bool aNotify)
-{
-  // Invoke on the superclass.
-  nsresult rv = nsSVGElement::UnsetAttr(aNameSpaceID, aAttribute, aNotify);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aNameSpaceID == kNameSpaceID_None) {
-    if (aAttribute == nsGkAtoms::srcdoc) {
-      // Fall back to the src attribute, if any
-      LoadSrc();
-    }
-  }
-
-  return NS_OK;
-}
-
-uint32_t
-SVGIFrameElement::GetSandboxFlags()
-{
-  const nsAttrValue* sandboxAttr = GetParsedAttr(nsGkAtoms::sandbox);
-  return nsContentUtils::ParseSandboxAttributeToFlags(sandboxAttr);
-}
-
-nsresult
-SVGIFrameElement::BindToTree(nsIDocument* aDocument,
-                             nsIContent* aParent,
-                             nsIContent* aBindingParent,
-                             bool aCompileEventHandlers)
-{
-  nsresult rv = nsSVGElement::BindToTree(aDocument, aParent,
-                                         aBindingParent,
-                                         aCompileEventHandlers);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (aDocument) {
-    NS_ASSERTION(!nsContentUtils::IsSafeToRunScript(),
-                 "Missing a script blocker!");
-
-    PROFILER_LABEL("SVGIFrameElement", "BindToTree",
-      js::ProfileEntry::Category::OTHER);
-
-    // We're in a document now.  Kick off the frame load.
-    LoadSrc();
-
-    if (HasAttr(kNameSpaceID_None, nsGkAtoms::sandbox)) {
-      if (mFrameLoader) {
-        mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
-      }
-    }
-  }
-
-  // We're now in document and scripts may move us, so clear
-  // the mNetworkCreated flag.
-  mNetworkCreated = false;
-  return rv;
-}
-
-void
-SVGIFrameElement::UnbindFromTree(bool aDeep, bool aNullParent)
-{
-  if (mFrameLoader) {
-    // This iframe is being taken out of the document, destroy the
-    // iframe's frame loader (doing that will tear down the window in
-    // this iframe).
-    // XXXbz we really want to only partially destroy the frame
-    // loader... we don't want to tear down the docshell.  Food for
-    // later bug.
-    mFrameLoader->Destroy();
-    mFrameLoader = nullptr;
-  }
-
-  nsSVGElement::UnbindFromTree(aDeep, aNullParent);
-}
-
-void
-SVGIFrameElement::DestroyContent()
-{
-  if (mFrameLoader) {
-    mFrameLoader->Destroy();
-    mFrameLoader = nullptr;
-  }
-
-  nsSVGElement::DestroyContent();
-}
-
-nsresult
-SVGIFrameElement::CopyInnerTo(Element* aDest)
-{
-  nsresult rv = nsSVGElement::CopyInnerTo(aDest);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  nsIDocument* doc = aDest->OwnerDoc();
-  if (doc->IsStaticDocument() && mFrameLoader) {
-    SVGIFrameElement* dest =
-      static_cast<SVGIFrameElement*>(aDest);
-    nsFrameLoader* fl = nsFrameLoader::Create(dest, false);
-    NS_ENSURE_STATE(fl);
-    dest->mFrameLoader = fl;
-    static_cast<nsFrameLoader*>(mFrameLoader.get())->CreateStaticClone(fl);
-  }
-
-  return rv;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/svg/SVGIFrameElement.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "mozilla/dom/DOMString.h"
-#include "mozilla/dom/FromParser.h"
-#include "mozilla/dom/SVGGraphicsElement.h"
-#include "nsContentUtils.h"
-#include "nsDOMSettableTokenList.h"
-#include "nsFrameLoader.h"
-#include "nsElementFrameLoaderOwner.h"
-#include "nsIDOMDocument.h"
-#include "nsIDOMEventListener.h"
-#include "nsIFrameLoader.h"
-#include "nsIWebNavigation.h"
-#include "nsSVGElement.h"
-#include "nsSVGLength2.h"
-#include "SVGAnimatedPreserveAspectRatio.h"
-
-nsresult NS_NewSVGIFrameElement(nsIContent **aResult,
-                                already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
-                                mozilla::dom::FromParser aFromParser);
-
-typedef mozilla::dom::SVGGraphicsElement SVGIFrameElementBase;
-
-class nsIDocument;
-class nsSVGIFrameFrame;
-
-namespace mozilla {
-namespace dom {
-class DOMSVGAnimatedPreserveAspectRatio;
-
-class SVGIFrameElement MOZ_FINAL : public SVGIFrameElementBase,
-                                   public nsElementFrameLoaderOwner
-{
-  friend class ::nsSVGIFrameFrame;
-  friend nsresult (::NS_NewSVGIFrameElement(nsIContent **aResult,
-                                  already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
-                                  mozilla::dom::FromParser aFromParser));
-
-  SVGIFrameElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo,
-                   mozilla::dom::FromParser aFromParser);
-  virtual JSObject* WrapNode(JSContext *aCx) MOZ_OVERRIDE;
-
-  ~SVGIFrameElement();
-
-public:
-  // interface
-  NS_DECL_ISUPPORTS_INHERITED
-
-  // nsSVGElement specializations:
-  virtual gfxMatrix PrependLocalTransformsTo(const gfxMatrix &aMatrix,
-                                             TransformTypes aWhich = eAllTransforms) const MOZ_OVERRIDE;
-
-  // nsIContent
-  virtual bool ParseAttribute(int32_t aNamespaceID,
-                              nsIAtom* aAttribute,
-                              const nsAString& aValue,
-                              nsAttrValue& aResult) MOZ_OVERRIDE;
-  virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent,
-                              nsIContent* aBindingParent,
-                              bool aCompileEventHandlers) MOZ_OVERRIDE;
-  virtual void UnbindFromTree(bool aDeep = true,
-                              bool aNullParent = true) MOZ_OVERRIDE;
-  virtual nsresult SetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                           nsIAtom* aPrefix, const nsAString& aValue,
-                           bool aNotify) MOZ_OVERRIDE;
-  virtual nsresult AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
-                                const nsAttrValue* aValue,
-                                bool aNotify) MOZ_OVERRIDE;
-  virtual nsresult UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttribute,
-                             bool aNotify) MOZ_OVERRIDE;
-
-  virtual void DestroyContent() MOZ_OVERRIDE;
-  nsresult CopyInnerTo(mozilla::dom::Element* aDest);
-  virtual nsresult Clone(mozilla::dom::NodeInfo *aNodeInfo, nsINode **aResult) const MOZ_OVERRIDE;
-
-  // WebIDL
-  already_AddRefed<SVGAnimatedLength> X();
-  already_AddRefed<SVGAnimatedLength> Y();
-  already_AddRefed<SVGAnimatedLength> Width();
-  already_AddRefed<SVGAnimatedLength> Height();
-  already_AddRefed<DOMSVGAnimatedPreserveAspectRatio> PreserveAspectRatio();
-  void GetName(DOMString& name);
-  void GetSrc(DOMString& src);
-  void GetSrcdoc(DOMString& srcdoc);
-  nsDOMSettableTokenList* Sandbox();
-  using nsElementFrameLoaderOwner::GetContentDocument;
-  using nsElementFrameLoaderOwner::GetContentWindow;
-
-  // Parses a sandbox attribute and converts it to the set of flags used internally.
-  // Returns 0 if there isn't the attribute.
-  uint32_t GetSandboxFlags();
-
-private:
-  virtual LengthAttributesInfo GetLengthInfo() MOZ_OVERRIDE;
-  virtual SVGAnimatedPreserveAspectRatio *GetPreserveAspectRatio() MOZ_OVERRIDE;
-  virtual mozilla::dom::Element* ThisFrameElement() MOZ_OVERRIDE
-  {
-    return this;
-  }
-
-  enum { ATTR_X, ATTR_Y, ATTR_WIDTH, ATTR_HEIGHT };
-  nsSVGLength2 mLengthAttributes[4];
-  static LengthInfo sLengthInfo[4];
-
-  SVGAnimatedPreserveAspectRatio mPreserveAspectRatio;
-};
-
-} // namespace dom
-} // namespace mozilla
--- a/dom/svg/SVGIntegerPairSMILType.cpp
+++ b/dom/svg/SVGIntegerPairSMILType.cpp
@@ -8,17 +8,17 @@
 #include "nsMathUtils.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 
 void
 SVGIntegerPairSMILType::Init(nsSMILValue& aValue) const
 {
-  NS_ABORT_IF_FALSE(aValue.IsNull(), "Unexpected value type");
+  MOZ_ASSERT(aValue.IsNull(), "Unexpected value type");
 
   aValue.mU.mIntPair[0] = 0;
   aValue.mU.mIntPair[1] = 0;
   aValue.mType = this;
 }
 
 void
 SVGIntegerPairSMILType::Destroy(nsSMILValue& aValue) const
--- a/dom/svg/SVGLength.cpp
+++ b/dom/svg/SVGLength.cpp
@@ -72,18 +72,18 @@ IsAbsoluteUnit(uint8_t aUnit)
  *
  * Example usage: to find out how many centimeters there are per inch:
  *
  *   GetAbsUnitsPerAbsUnit(nsIDOMSVGLength::SVG_LENGTHTYPE_CM,
  *                         nsIDOMSVGLength::SVG_LENGTHTYPE_IN)
  */
 inline static float GetAbsUnitsPerAbsUnit(uint8_t aUnits, uint8_t aPerUnit)
 {
-  NS_ABORT_IF_FALSE(IsAbsoluteUnit(aUnits), "Not a CSS absolute unit");
-  NS_ABORT_IF_FALSE(IsAbsoluteUnit(aPerUnit), "Not a CSS absolute unit");
+  MOZ_ASSERT(IsAbsoluteUnit(aUnits), "Not a CSS absolute unit");
+  MOZ_ASSERT(IsAbsoluteUnit(aPerUnit), "Not a CSS absolute unit");
 
   float CSSAbsoluteUnitConversionFactors[5][5] = { // columns: cm, mm, in, pt, pc
     // cm per...:
     { 1.0f, 0.1f, 2.54f, 0.035277777777777778f, 0.42333333333333333f },
     // mm per...:
     { 10.0f, 1.0f, 25.4f, 0.35277777777777778f, 4.2333333333333333f },
     // in per...:
     { 0.39370078740157481f, 0.039370078740157481f, 1.0f, 0.013888888888888889f, 0.16666666666666667f },