Merge inbound to m-c. a=merge
authorRyan VanderMeulen <ryanvm@gmail.com>
Tue, 10 Feb 2015 16:03:15 -0500
changeset 255582 ee093ca706662491d356484bf729ef32d55bc19c
parent 255459 9ac2e8cd4faff33702ff849bea34e54db18c2f0b (current diff)
parent 255581 19cbffb1bf61413cbc185a92da3277f87ca0f409 (diff)
child 255583 b04123c901ac90b12dffe6ca25f8765126cca0cc
child 255592 f17a80ddf9fd942b4d120602d0f8fbbb290e22ce
child 255618 7152dc5221cb10bc9c44d331778bf52610778a75
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone38.0a1
first release with
nightly linux32
ee093ca70666 / 38.0a1 / 20150211030228 / files
nightly linux64
ee093ca70666 / 38.0a1 / 20150211030228 / files
nightly mac
ee093ca70666 / 38.0a1 / 20150211030228 / files
nightly win32
ee093ca70666 / 38.0a1 / 20150211030228 / files
nightly win64
ee093ca70666 / 38.0a1 / 20150211030228 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge 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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..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 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..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);