Merge m-c to fx-team, a=merge
authorWes Kocher <wkocher@mozilla.com>
Thu, 03 Dec 2015 16:12:01 -0800
changeset 309662 204bb8e3e0c2fa29f7c26c0a9eb62c622a1a919e
parent 309661 43076a707aeb17df93712d073f8066665c09ee3d (current diff)
parent 309643 528fc18a86d3f6e6bec37190522a46853a846665 (diff)
child 309663 a1440a731b1a7b16cb940a4f016b1fb7a726c87a
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team, a=merge
.eslintignore
dom/media/test/test_eme_key_ids_initdata.html
--- a/.eslintignore
+++ b/.eslintignore
@@ -4,17 +4,16 @@
 # Exclude expected objdirs.
 obj*/**
 
 # We ignore all these directories by default, until we get them enabled.
 # If you are enabling a directory, please add directory specific exclusions
 # below.
 accessible/**
 addon-sdk/**
-b2g/**
 build/**
 caps/**
 chrome/**
 config/**
 db/**
 docshell/**
 dom/**
 editor/**
@@ -72,16 +71,21 @@ tools/**
 uriloader/**
 view/**
 webapprt/**
 widget/**
 xpcom/**
 xpfe/**
 xulrunner/**
 
+# b2g exclusions (pref files).
+b2g/app/b2g.js
+b2g/graphene/graphene.js
+b2g/locales/en-US/b2g-l10n.js
+
 # browser/ exclusions
 browser/app/**
 browser/base/content/browser-social.js
 browser/base/content/nsContextMenu.js
 browser/base/content/sanitizeDialog.js
 browser/base/content/test/**
 browser/base/content/newtab/**
 browser/components/customizableui/**
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -1082,16 +1082,19 @@ pref("layout.accessiblecaret.use_long_ta
 
 // Enable sync and mozId with Firefox Accounts.
 pref("services.sync.fxaccounts.enabled", true);
 pref("identity.fxaccounts.enabled", true);
 
 // Mobile Identity API.
 pref("services.mobileid.server.uri", "https://msisdn.services.mozilla.com");
 
+pref("identity.fxaccounts.remote.oauth.uri", "https://oauth.accounts.firefox.com/v1");
+pref("identity.fxaccounts.remote.profile.uri", "https://profile.accounts.firefox.com/v1");
+
 // Enable mapped array buffer.
 #ifndef XP_WIN
 pref("dom.mapped_arraybuffer.enabled", true);
 #endif
 
 // SystemUpdate API
 pref("dom.system_update.enabled", true);
 
--- a/b2g/chrome/content/devtools/debugger.js
+++ b/b2g/chrome/content/devtools/debugger.js
@@ -214,21 +214,21 @@ var RemoteDebugger = {
         } : DebuggerServer.globalActorFactories
       };
       let { RootActor } = devtools.require("devtools/server/actors/root");
       let root = new RootActor(connection, parameters);
       root.applicationType = "operating-system";
       return root;
     };
 
-#ifdef MOZ_WIDGET_GONK
-    DebuggerServer.on("connectionchange", function() {
-      AdbController.updateState();
-    });
-#endif
+    if (isGonk) {
+      DebuggerServer.on("connectionchange", function() {
+        AdbController.updateState();
+      });
+    }
   }
 };
 
 RemoteDebugger.allowConnection =
   RemoteDebugger.allowConnection.bind(RemoteDebugger);
 RemoteDebugger.receiveOOB =
   RemoteDebugger.receiveOOB.bind(RemoteDebugger);
 
@@ -368,19 +368,17 @@ var WiFiRemoteDebugger = {
     try {
       (value == "adb-devtools") ? USBRemoteDebugger.start()
                                 : USBRemoteDebugger.stop();
     } catch(e) {
       dump("Error while initializing USB devtools: " +
            e + "\n" + e.stack + "\n");
     }
 
-#ifdef MOZ_WIDGET_GONK
-    AdbController.setRemoteDebuggerState(value != "disabled");
-#endif
+    isGonk && AdbController.setRemoteDebuggerState(value != "disabled");
   });
 
   SettingsListener.observe("devtools.remote.wifi.enabled", false,
                            function(value) {
     devtoolsWiFi = value;
     Services.prefs.setBoolPref("devtools.debugger.remote-enabled",
                                devtoolsUSB || devtoolsWiFi);
     // Allow remote debugging on non-local interfaces when WiFi debug is enabled
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -17,22 +17,24 @@ var Cr = Components.results;
 // prior to using SettingsListener otherwise there is a race in acquiring the
 // lock and fulfilling it. If we ever move SettingsListener or this file down in
 // the load order of shell.html things will likely break.
 Cu.import('resource://gre/modules/SettingsRequestManager.jsm');
 Cu.import('resource://gre/modules/XPCOMUtils.jsm');
 Cu.import('resource://gre/modules/Services.jsm');
 Cu.import('resource://gre/modules/AppConstants.jsm');
 
-#ifdef MOZ_WIDGET_GONK
-XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
-  Cu.import("resource://gre/modules/systemlibs.js");
-  return libcutils;
-});
-#endif
+const isGonk = AppConstants.platform === 'gonk';
+
+if (isGonk) {
+  XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
+    Cu.import("resource://gre/modules/systemlibs.js");
+    return libcutils;
+  });
+}
 
 XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
                                    "@mozilla.org/uuid-generator;1",
                                    "nsIUUIDGenerator");
 
 XPCOMUtils.defineLazyServiceGetter(this, "gPACGenerator",
                                    "@mozilla.org/pac-generator;1",
                                    "nsIPACGenerator");
@@ -147,39 +149,37 @@ SettingsListener.observe('language.curre
 })();
 
 //=================== DeviceInfo ====================
 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
 Components.utils.import('resource://gre/modules/ctypes.jsm');
 (function DeviceInfoToSettings() {
   // MOZ_B2G_VERSION is set in b2g/confvars.sh, and is output as a #define value
   // from configure.in, defaults to 1.0.0 if this value is not exist.
-#filter attemptSubstitution
-  let os_version = '@MOZ_B2G_VERSION@';
-  let os_name = '@MOZ_B2G_OS_NAME@';
-#unfilter attemptSubstitution
+  let os_version = AppConstants.MOZ_B2G_VERSION;
+  let os_name = AppConstants.MOZ_B2G_OS_NAME;
 
   let appInfo = Cc["@mozilla.org/xre/app-info;1"]
                   .getService(Ci.nsIXULAppInfo);
 
   // Get the hardware info and firmware revision from device properties.
   let hardware_info = null;
   let firmware_revision = null;
   let product_manufacturer = null;
   let product_model = null;
   let product_device = null;
   let build_number = null;
-#ifdef MOZ_WIDGET_GONK
+  if (isGonk) {
     hardware_info = libcutils.property_get('ro.hardware');
     firmware_revision = libcutils.property_get('ro.firmware_revision');
     product_manufacturer = libcutils.property_get('ro.product.manufacturer');
     product_model = libcutils.property_get('ro.product.model');
     product_device = libcutils.property_get('ro.product.device');
     build_number = libcutils.property_get('ro.build.version.incremental');
-#endif
+  }
 
   // Populate deviceinfo settings,
   // copying any existing deviceinfo.os into deviceinfo.previous_os
   let lock = window.navigator.mozSettings.createLock();
   let req = lock.get('deviceinfo.os');
   req.onsuccess = req.onerror = () => {
     let previous_os = req.result && req.result['deviceinfo.os'] || '';
     let software = os_name + ' ' + os_version;
@@ -213,42 +213,41 @@ SettingsListener.observe('devtools.overl
     developerHUD.init();
   } else {
     if (developerHUD) {
       developerHUD.uninit();
     }
   }
 });
 
-#ifdef MOZ_WIDGET_GONK
-
-var LogShake;
-(function() {
-  let scope = {};
-  Cu.import('resource://gre/modules/LogShake.jsm', scope);
-  LogShake = scope.LogShake;
-  LogShake.init();
-})();
+if (isGonk) {
+  var LogShake;
+  (function() {
+    let scope = {};
+    Cu.import('resource://gre/modules/LogShake.jsm', scope);
+    LogShake = scope.LogShake;
+    LogShake.init();
+  })();
 
-SettingsListener.observe('devtools.logshake.enabled', false, value => {
-  if (value) {
-    LogShake.enableDeviceMotionListener();
-  } else {
-    LogShake.disableDeviceMotionListener();
-  }
-});
+  SettingsListener.observe('devtools.logshake.enabled', false, value => {
+    if (value) {
+      LogShake.enableDeviceMotionListener();
+    } else {
+      LogShake.disableDeviceMotionListener();
+    }
+  });
 
-SettingsListener.observe('devtools.logshake.qa_enabled', false, value => {
-  if (value) {
-    LogShake.enableQAMode();
-  } else {
-    LogShake.disableQAMode();
-  }
-});
-#endif
+  SettingsListener.observe('devtools.logshake.qa_enabled', false, value => {
+    if (value) {
+      LogShake.enableQAMode();
+    } else {
+      LogShake.disableQAMode();
+    }
+  });
+}
 
 // =================== Device Storage ====================
 SettingsListener.observe('device.storage.writable.name', 'sdcard', function(value) {
   if (Services.prefs.getPrefType('device.storage.writable.name') != Ci.nsIPrefBranch.PREF_STRING) {
     // We clear the pref because it used to be erroneously written as a bool
     // and we need to clear it before we can change it to have the correct type.
     Services.prefs.clearUserPref('device.storage.writable.name');
   }
@@ -375,25 +374,23 @@ setUpdateTrackingId();
   //3. presence of ro.display.colorfill at the Gonk level
 
   var req = navigator.mozSettings.createLock().get('layers.composer2d.enabled');
   req.onsuccess = function() {
     if (typeof(req.result['layers.composer2d.enabled']) === 'undefined') {
       var enabled = false;
       if (Services.prefs.getPrefType('layers.composer2d.enabled') == Ci.nsIPrefBranch.PREF_BOOL) {
         enabled = Services.prefs.getBoolPref('layers.composer2d.enabled');
-      } else {
-#ifdef MOZ_WIDGET_GONK
+      } else if (isGonk) {
         let androidVersion = libcutils.property_get("ro.build.version.sdk");
         if (androidVersion >= 17 ) {
           enabled = true;
         } else {
           enabled = (libcutils.property_get('ro.display.colorfill') === '1');
         }
-#endif
       }
       navigator.mozSettings.createLock().set({'layers.composer2d.enabled': enabled });
     }
 
     SettingsListener.observe("layers.composer2d.enabled", true, function(value) {
       Services.prefs.setBoolPref("layers.composer2d.enabled", value);
     });
   };
@@ -438,21 +435,17 @@ setUpdateTrackingId();
   let geckoPrefName = 'toolkit.telemetry.enabled';
   SettingsListener.observe(gaiaSettingName, null, function(value) {
     if (value !== null) {
       // Gaia setting has been set; update Gecko pref to that.
       Services.prefs.setBoolPref(geckoPrefName, value);
       return;
     }
     // Gaia setting has not been set; set the gaia setting to default.
-#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
-    let prefValue = true;
-#else
-    let prefValue = false;
-#endif
+    let prefValue = AppConstants.MOZ_TELEMETRY_ON_BY_DEFAULT;
     try {
       prefValue = Services.prefs.getBoolPref(geckoPrefName);
     } catch (e) {
       // Pref not set; use default value.
     }
     let setting = {};
     setting[gaiaSettingName] = prefValue;
     window.navigator.mozSettings.createLock().set(setting);
@@ -566,57 +559,57 @@ SettingsListener.observe("theme.selected
   SettingsListener.observe('browser.proxy.port', 0, function(value) {
     Services.prefs.setIntPref('network.proxy.browsing.port', value);
     setPAC();
   });
 
   setPAC();
 })();
 
-#ifdef MOZ_B2G_RIL
-XPCOMUtils.defineLazyModuleGetter(this, "AppsUtils",
-                                  "resource://gre/modules/AppsUtils.jsm");
-
 // ======================= Dogfooders FOTA ==========================
-SettingsListener.observe('debug.performance_data.dogfooding', false,
-  isDogfooder => {
-    if (!isDogfooder) {
-      dump('AUS:Settings: Not a dogfooder!\n');
-      return;
-    }
+if (AppConstants.MOZ_B2G_RIL) {
+  XPCOMUtils.defineLazyModuleGetter(this, "AppsUtils",
+                                    "resource://gre/modules/AppsUtils.jsm");
 
-    if (!('mozTelephony' in navigator)) {
-      dump('AUS:Settings: There is no mozTelephony!\n');
-      return;
-    }
+  SettingsListener.observe('debug.performance_data.dogfooding', false,
+    isDogfooder => {
+      if (!isDogfooder) {
+        dump('AUS:Settings: Not a dogfooder!\n');
+        return;
+      }
 
-    if (!('mozMobileConnections' in navigator)) {
-      dump('AUS:Settings: There is no mozMobileConnections!\n');
-      return;
-    }
-
-    let conn = navigator.mozMobileConnections[0];
-    conn.addEventListener('radiostatechange', function onradiostatechange() {
-      if (conn.radioState !== 'enabled') {
+      if (!('mozTelephony' in navigator)) {
+        dump('AUS:Settings: There is no mozTelephony!\n');
         return;
       }
 
-      conn.removeEventListener('radiostatechange', onradiostatechange);
-      navigator.mozTelephony.dial('*#06#').then(call => {
-        return call.result.then(res => {
-          if (res.success && res.statusMessage
-              && (res.serviceCode === 'scImei')) {
-            Services.prefs.setCharPref("app.update.imei_hash",
-                                       AppsUtils.computeHash(res.statusMessage, "SHA512"));
-          }
+      if (!('mozMobileConnections' in navigator)) {
+        dump('AUS:Settings: There is no mozMobileConnections!\n');
+        return;
+      }
+
+      let conn = navigator.mozMobileConnections[0];
+      conn.addEventListener('radiostatechange', function onradiostatechange() {
+        if (conn.radioState !== 'enabled') {
+          return;
+        }
+
+        conn.removeEventListener('radiostatechange', onradiostatechange);
+        navigator.mozTelephony.dial('*#06#').then(call => {
+          return call.result.then(res => {
+            if (res.success && res.statusMessage
+                && (res.serviceCode === 'scImei')) {
+              Services.prefs.setCharPref("app.update.imei_hash",
+                                         AppsUtils.computeHash(res.statusMessage, "SHA512"));
+            }
+          });
         });
       });
     });
-  });
-#endif
+}
 
 // =================== Various simple mapping  ======================
 var settingsToObserve = {
   'accessibility.screenreader_quicknav_modes': {
     prefName: 'accessibility.accessfu.quicknav_modes',
     resetToPref: true,
     defaultValue: ''
   },
@@ -658,28 +651,21 @@ var settingsToObserve = {
   'dom.presentation.discovery.enabled': false,
   'dom.presentation.discoverable': false,
   'dom.serviceWorkers.interception.enabled': true,
   'dom.serviceWorkers.testing.enabled': false,
   'gfx.layerscope.enabled': false,
   'layers.draw-borders': false,
   'layers.draw-tile-borders': false,
   'layers.dump': false,
-#ifdef XP_WIN
-  'layers.enable-tiles': false,
-#else
+  'layers.enable-tiles': AppConstants.platform !== "win",
   'layers.enable-tiles': true,
-#endif
   'layers.effect.invert': false,
   'layers.effect.grayscale': false,
   'layers.effect.contrast': '0.0',
-#ifdef MOZ_GRAPHENE
-  // Restart required
-  'layers.async-pan-zoom.enabled': false,
-#endif
   'layout.display-list.dump': false,
   'mms.debugging.enabled': false,
   'network.debugging.enabled': false,
   'privacy.donottrackheader.enabled': false,
   'privacy.trackingprotection.enabled': false,
   'ril.debugging.enabled': false,
   'ril.radio.disabled': false,
   'ril.mms.requestReadReport.enabled': {
@@ -724,16 +710,21 @@ var settingsToObserve = {
   },
   'ui.click_hold_context_menus.delay': {
     resetToPref: true
   },
   'wap.UAProf.tagname': 'x-wap-profile',
   'wap.UAProf.url': ''
 };
 
+if (AppConstants.MOZ_GRAPHENE) {
+  // Restart required
+  settingsToObserve['layers.async-pan-zoom.enabled'] = false;
+}
+
 function settingObserver(setPref, prefName, setting) {
   return value => {
     setPref(prefName, value);
     if (setting.notifyChange) {
       SystemAppProxy._sendCustomEvent('mozPrefChromeEvent', {
         prefName: prefName,
         value: value
       });
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -14,21 +14,23 @@ Cu.import('resource://gre/modules/Notifi
 Cu.import('resource://gre/modules/Payment.jsm');
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
 Cu.import('resource://gre/modules/Keyboard.jsm');
 Cu.import('resource://gre/modules/ErrorPage.jsm');
 Cu.import('resource://gre/modules/AlertsHelper.jsm');
 Cu.import('resource://gre/modules/RequestSyncService.jsm');
 Cu.import('resource://gre/modules/SystemUpdateService.jsm');
-#ifdef MOZ_WIDGET_GONK
-Cu.import('resource://gre/modules/MultiscreenHandler.jsm');
-Cu.import('resource://gre/modules/NetworkStatsService.jsm');
-Cu.import('resource://gre/modules/ResourceStatsService.jsm');
-#endif
+
+if (isGonk) {
+  Cu.import('resource://gre/modules/MultiscreenHandler.jsm');
+  Cu.import('resource://gre/modules/NetworkStatsService.jsm');
+  Cu.import('resource://gre/modules/ResourceStatsService.jsm');
+}
+
 Cu.import('resource://gre/modules/KillSwitchMain.jsm');
 
 // Identity
 Cu.import('resource://gre/modules/SignInToWebsite.jsm');
 SignInToWebsiteController.init();
 
 Cu.import('resource://gre/modules/FxAccountsMgmtService.jsm');
 Cu.import('resource://gre/modules/DownloadsAPI.jsm');
@@ -57,31 +59,31 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    '@mozilla.org/system-message-internal;1',
                                    'nsISystemMessagesInternal');
 
 XPCOMUtils.defineLazyGetter(this, "ppmm", function() {
   return Cc["@mozilla.org/parentprocessmessagemanager;1"]
          .getService(Ci.nsIMessageListenerManager);
 });
 
-#ifdef MOZ_WIDGET_GONK
-XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
-  Cu.import("resource://gre/modules/systemlibs.js");
-  return libcutils;
-});
-#endif
+if (isGonk) {
+  XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
+    Cu.import("resource://gre/modules/systemlibs.js");
+    return libcutils;
+  });
+}
 
 XPCOMUtils.defineLazyServiceGetter(Services, 'captivePortalDetector',
                                   '@mozilla.org/toolkit/captive-detector;1',
                                   'nsICaptivePortalDetector');
 
-#ifdef MOZ_SAFE_BROWSING
-XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
-              "resource://gre/modules/SafeBrowsing.jsm");
-#endif
+if (AppConstants.MOZ_SAFE_BROWSING) {
+  XPCOMUtils.defineLazyModuleGetter(this, "SafeBrowsing",
+                "resource://gre/modules/SafeBrowsing.jsm");
+}
 
 XPCOMUtils.defineLazyModuleGetter(this, "SafeMode",
                                   "resource://gre/modules/SafeMode.jsm");
 
 window.performance.measure('gecko-shell-jsm-loaded', 'gecko-shell-loadstart');
 
 function debug(str) {
   dump(' -*- Shell.js: ' + str + '\n');
@@ -115,35 +117,31 @@ function clearCacheAndReload() {
 }
 
 function restart() {
   let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
                      .getService(Ci.nsIAppStartup);
   appStartup.quit(Ci.nsIAppStartup.eForceQuit | Ci.nsIAppStartup.eRestart);
 }
 
-#ifdef MOZ_CRASHREPORTER
 function debugCrashReport(aStr) {
-  dump('Crash reporter : ' + aStr);
+  AppConstants.MOZ_CRASHREPORTER && dump('Crash reporter : ' + aStr);
 }
-#else
-function debugCrashReport(aStr) {}
-#endif
 
 var shell = {
 
   get CrashSubmit() {
     delete this.CrashSubmit;
-#ifdef MOZ_CRASHREPORTER
-    Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
-    return this.CrashSubmit;
-#else
-    dump('Crash reporter : disabled at build time.');
-    return this.CrashSubmit = null;
-#endif
+    if (AppConstants.MOZ_CRASHREPORTER) {
+      Cu.import("resource://gre/modules/CrashSubmit.jsm", this);
+      return this.CrashSubmit;
+    } else {
+      dump('Crash reporter : disabled at build time.');
+      return this.CrashSubmit = null;
+    }
   },
 
   onlineForCrashReport: function shell_onlineForCrashReport() {
     let wifiManager = navigator.mozWifiManager;
     let onWifi = (wifiManager &&
                   (wifiManager.connection.status == 'connected'));
     return !Services.io.offline && onWifi;
   },
@@ -260,54 +258,52 @@ var shell = {
   },
 
   _started: false,
   hasStarted: function shell_hasStarted() {
     return this._started;
   },
 
   bootstrap: function() {
-#ifdef MOZ_B2GDROID
-    Cc["@mozilla.org/b2g/b2gdroid-setup;1"]
-      .getService(Ci.nsIObserver).observe(window, "shell-startup", null);
-#endif
+    if (AppConstants.MOZ_B2GDROID) {
+      Cc["@mozilla.org/b2g/b2gdroid-setup;1"]
+        .getService(Ci.nsIObserver).observe(window, "shell-startup", null);
+    }
 
     window.performance.mark('gecko-shell-bootstrap');
 
     // Before anything, check if we want to start in safe mode.
     SafeMode.check(window).then(() => {
       let startManifestURL =
         Cc['@mozilla.org/commandlinehandler/general-startup;1?type=b2gbootstrap']
           .getService(Ci.nsISupports).wrappedJSObject.startManifestURL;
 
-#ifdef MOZ_GRAPHENE
       // If --start-manifest hasn't been specified, we re-use the latest specified manifest.
       // If it's the first launch, we will fallback to b2g.default.start_manifest_url
-      if (!startManifestURL) {
+      if (AppConstants.MOZ_GRAPHENE && !startManifestURL) {
         try {
           startManifestURL = Services.prefs.getCharPref("b2g.system_manifest_url");
         } catch(e) {}
       }
-#endif
 
       if (!startManifestURL) {
         try {
           startManifestURL = Services.prefs.getCharPref("b2g.default.start_manifest_url");
         } catch(e) {}
       }
 
       if (startManifestURL) {
         Cu.import('resource://gre/modules/Bootstraper.jsm');
-#ifdef MOZ_GRAPHENE
-        if (Bootstraper.isInstallRequired(startManifestURL)) {
+
+        if (AppConstants.MOZ_GRAPHENE && Bootstraper.isInstallRequired(startManifestURL)) {
           // Installing the app my take some time. We don't want to keep the
           // native window hidden.
           showInstallScreen();
         }
-#endif
+
         Bootstraper.ensureSystemAppInstall(startManifestURL)
                    .then(this.start.bind(this))
                    .catch(Bootstraper.bailout);
       } else {
         this.start();
       }
     });
   },
@@ -329,44 +325,44 @@ var shell = {
       try {
         let dogfoodId = Services.prefs.getCharPref('prerelease.dogfood.id');
         if (dogfoodId != "") {
           cr.annotateCrashReport("Email", dogfoodId);
         }
       }
       catch (e) { }
 
-#ifdef MOZ_WIDGET_GONK
-      // Annotate crash report
-      let annotations = [ [ "Android_Hardware",     "ro.hardware" ],
-                          [ "Android_Device",       "ro.product.device" ],
-                          [ "Android_CPU_ABI2",     "ro.product.cpu.abi2" ],
-                          [ "Android_CPU_ABI",      "ro.product.cpu.abi" ],
-                          [ "Android_Manufacturer", "ro.product.manufacturer" ],
-                          [ "Android_Brand",        "ro.product.brand" ],
-                          [ "Android_Model",        "ro.product.model" ],
-                          [ "Android_Board",        "ro.product.board" ],
-        ];
+      if (isGonk) {
+        // Annotate crash report
+        let annotations = [ [ "Android_Hardware",     "ro.hardware" ],
+                            [ "Android_Device",       "ro.product.device" ],
+                            [ "Android_CPU_ABI2",     "ro.product.cpu.abi2" ],
+                            [ "Android_CPU_ABI",      "ro.product.cpu.abi" ],
+                            [ "Android_Manufacturer", "ro.product.manufacturer" ],
+                            [ "Android_Brand",        "ro.product.brand" ],
+                            [ "Android_Model",        "ro.product.model" ],
+                            [ "Android_Board",        "ro.product.board" ],
+          ];
 
-      annotations.forEach(function (element) {
-          cr.annotateCrashReport(element[0], libcutils.property_get(element[1]));
-        });
+        annotations.forEach(function (element) {
+            cr.annotateCrashReport(element[0], libcutils.property_get(element[1]));
+          });
 
-      let androidVersion = libcutils.property_get("ro.build.version.sdk") +
-                           "(" + libcutils.property_get("ro.build.version.codename") + ")";
-      cr.annotateCrashReport("Android_Version", androidVersion);
+        let androidVersion = libcutils.property_get("ro.build.version.sdk") +
+                             "(" + libcutils.property_get("ro.build.version.codename") + ")";
+        cr.annotateCrashReport("Android_Version", androidVersion);
 
-      SettingsListener.observe("deviceinfo.os", "", function(value) {
-        try {
-          let cr = Cc["@mozilla.org/xre/app-info;1"]
-                     .getService(Ci.nsICrashReporter);
-          cr.annotateCrashReport("B2G_OS_Version", value);
-        } catch(e) { }
-      });
-#endif
+        SettingsListener.observe("deviceinfo.os", "", function(value) {
+          try {
+            let cr = Cc["@mozilla.org/xre/app-info;1"]
+                       .getService(Ci.nsICrashReporter);
+            cr.annotateCrashReport("B2G_OS_Version", value);
+          } catch(e) { }
+        });
+      }
     } catch(e) {
       debugCrashReport('exception: ' + e);
     }
 
     let homeURL = this.homeURL;
     if (!homeURL) {
       let msg = 'Fatal error during startup: No homescreen found: try setting B2G_HOMESCREEN';
       alert(msg);
@@ -380,33 +376,35 @@ var shell = {
     let systemAppFrame =
       document.createElementNS('http://www.w3.org/1999/xhtml', 'html:iframe');
     systemAppFrame.setAttribute('id', 'systemapp');
     systemAppFrame.setAttribute('mozbrowser', 'true');
     systemAppFrame.setAttribute('mozapp', manifestURL);
     systemAppFrame.setAttribute('allowfullscreen', 'true');
     systemAppFrame.setAttribute('src', 'blank.html');
     let container = document.getElementById('container');
-#ifdef MOZ_WIDGET_COCOA
-    // See shell.html
-    let hotfix = document.getElementById('placeholder');
-    if (hotfix) {
-      container.removeChild(hotfix);
+
+    if (AppConstants.platform == 'macosx') {
+      // See shell.html
+      let hotfix = document.getElementById('placeholder');
+      if (hotfix) {
+        container.removeChild(hotfix);
+      }
     }
-#endif
+
     this.contentBrowser = container.appendChild(systemAppFrame);
 
     let webNav = systemAppFrame.contentWindow
                                .QueryInterface(Ci.nsIInterfaceRequestor)
                                .getInterface(Ci.nsIWebNavigation);
     webNav.sessionHistory = Cc["@mozilla.org/browser/shistory;1"].createInstance(Ci.nsISHistory);
 
-#ifdef MOZ_GRAPHENE
-    webNav.QueryInterface(Ci.nsIDocShell).windowDraggingAllowed = true;
-#endif
+    if (AppConstants.MOZ_GRAPHENE) {
+      webNav.QueryInterface(Ci.nsIDocShell).windowDraggingAllowed = true;
+    }
 
     let audioChannels = systemAppFrame.allowedAudioChannels;
     audioChannels && audioChannels.forEach(function(audioChannel) {
       // Set all audio channels as unmuted by default
       // because some audio in System app will be played
       // before AudioChannelService[1] is Gaia is loaded.
       // [1]: https://github.com/mozilla-b2g/gaia/blob/master/apps/system/js/audio_channel_service.js
       audioChannel.setMuted(false);
@@ -446,21 +444,22 @@ var shell = {
 
     window.performance.mark('gecko-shell-system-frame-set');
 
     ppmm.addMessageListener("content-handler", this);
     ppmm.addMessageListener("dial-handler", this);
     ppmm.addMessageListener("sms-handler", this);
     ppmm.addMessageListener("mail-handler", this);
     ppmm.addMessageListener("file-picker", this);
-#ifdef MOZ_SAFE_BROWSING
-    setTimeout(function() {
-      SafeBrowsing.init();
-    }, 5000);
-#endif
+
+    if (AppConstants.MOZ_SAFE_BROWSING) {
+      setTimeout(function() {
+        SafeBrowsing.init();
+      }, 5000);
+    }
   },
 
   stop: function shell_stop() {
     window.removeEventListener('unload', this);
     window.removeEventListener('keydown', this, true);
     window.removeEventListener('keyup', this, true);
     window.removeEventListener('MozApplicationManifest', this);
     window.removeEventListener('sizemodechange', this);
@@ -749,55 +748,50 @@ var shell = {
     this.reportCrash(true);
 
     SystemAppProxy.registerFrame(shell.contentBrowser);
 
     this.sendEvent(window, 'ContentStart');
 
     Services.obs.notifyObservers(null, 'content-start', null);
 
-#ifdef MOZ_WIDGET_GONK
-    Cu.import('resource://gre/modules/OperatorApps.jsm');
-#endif
+    isGonk && Cu.import('resource://gre/modules/OperatorApps.jsm');
 
-#ifdef MOZ_GRAPHENE
-    if (Services.prefs.getBoolPref("b2g.nativeWindowGeometry.fullscreen")) {
+    if (AppConstants.MOZ_GRAPHENE &&
+        Services.prefs.getBoolPref("b2g.nativeWindowGeometry.fullscreen")) {
       window.fullScreen = true;
     }
-#endif
 
     shell.handleCmdLine();
   },
 
   handleCmdLine: function() {
-  // This isn't supported on devices.
-#ifndef ANDROID
-    let b2gcmds = Cc["@mozilla.org/commandlinehandler/general-startup;1?type=b2gcmds"]
-                    .getService(Ci.nsISupports);
-    let args = b2gcmds.wrappedJSObject.cmdLine;
-    try {
-      // Returns null if -url is not present.
-      let url = args.handleFlagWithParam("url", false);
-      if (url) {
-        this.sendChromeEvent({type: "mozbrowseropenwindow", url});
-        args.preventDefault = true;
+    // This isn't supported on devices.
+    if (!isGonk && !AppConstants.MOZ_B2GDROID) {
+      let b2gcmds = Cc["@mozilla.org/commandlinehandler/general-startup;1?type=b2gcmds"]
+                      .getService(Ci.nsISupports);
+      let args = b2gcmds.wrappedJSObject.cmdLine;
+      try {
+        // Returns null if -url is not present.
+        let url = args.handleFlagWithParam("url", false);
+        if (url) {
+          this.sendChromeEvent({type: "mozbrowseropenwindow", url});
+          args.preventDefault = true;
+        }
+      } catch(e) {
+        // Throws if -url is present with no params.
       }
-    } catch(e) {
-      // Throws if -url is present with no params.
     }
-#endif
   },
 
   // This gets called when window.onload fires on the System app content window,
   // which means things in <html> are parsed and statically referenced <script>s
   // and <script defer>s are loaded and run.
   notifyContentWindowLoaded: function shell_notifyContentWindowLoaded() {
-#ifdef MOZ_WIDGET_GONK
-    libcutils.property_set('sys.boot_completed', '1');
-#endif
+    isGonk && libcutils.property_set('sys.boot_completed', '1');
 
     // This will cause Gonk Widget to remove boot animation from the screen
     // and reveals the page.
     Services.obs.notifyObservers(null, "browser-ui-startup-complete", "");
 
     SystemAppProxy.setIsLoaded();
   },
 
@@ -1119,29 +1113,31 @@ window.addEventListener('ContentStart', 
     }
   });
 });
 
 window.addEventListener('ContentStart', function update_onContentStart() {
   Cu.import('resource://gre/modules/WebappsUpdater.jsm');
   WebappsUpdater.handleContentStart(shell);
 
-#ifdef MOZ_UPDATER
+  if (!AppConstants.MOZ_UPDATER) {
+    return;
+  }
+
   let promptCc = Cc["@mozilla.org/updates/update-prompt;1"];
   if (!promptCc) {
     return;
   }
 
   let updatePrompt = promptCc.createInstance(Ci.nsIUpdatePrompt);
   if (!updatePrompt) {
     return;
   }
 
   updatePrompt.wrappedJSObject.handleContentStart(shell);
-#endif
 });
 
 (function geolocationStatusTracker() {
   let gGeolocationActive = false;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldState = gGeolocationActive;
     if (aData == "starting") {
@@ -1308,152 +1304,148 @@ window.addEventListener('ContentStart', 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     shell.sendChromeEvent({
       type: 'volume-state-changed',
       active: (aData == 'Shared')
     });
 }, 'volume-state-changed', false);
 })();
 
-#ifdef MOZ_WIDGET_GONK
-// Devices don't have all the same partition size for /cache where we
-// store the http cache.
-(function setHTTPCacheSize() {
-  let path = Services.prefs.getCharPref("browser.cache.disk.parent_directory");
-  let volumeService = Cc["@mozilla.org/telephony/volume-service;1"]
-                        .getService(Ci.nsIVolumeService);
+if (isGonk) {
+  // Devices don't have all the same partition size for /cache where we
+  // store the http cache.
+  (function setHTTPCacheSize() {
+    let path = Services.prefs.getCharPref("browser.cache.disk.parent_directory");
+    let volumeService = Cc["@mozilla.org/telephony/volume-service;1"]
+                          .getService(Ci.nsIVolumeService);
 
-  let stats = volumeService.createOrGetVolumeByPath(path).getStats();
+    let stats = volumeService.createOrGetVolumeByPath(path).getStats();
 
-  // We must set the size in KB, and keep a bit of free space.
-  let size = Math.floor(stats.totalBytes / 1024) - 1024;
+    // We must set the size in KB, and keep a bit of free space.
+    let size = Math.floor(stats.totalBytes / 1024) - 1024;
 
-  // keep the default value if it is smaller than the physical partition size.
-  let oldSize = Services.prefs.getIntPref("browser.cache.disk.capacity");
-  if (size < oldSize) {
-    Services.prefs.setIntPref("browser.cache.disk.capacity", size);
-  }
-})();
-#endif
+    // keep the default value if it is smaller than the physical partition size.
+    let oldSize = Services.prefs.getIntPref("browser.cache.disk.capacity");
+    if (size < oldSize) {
+      Services.prefs.setIntPref("browser.cache.disk.capacity", size);
+    }
+  })();
 
-#ifdef MOZ_WIDGET_GONK
-try {
-  let gmpService = Cc["@mozilla.org/gecko-media-plugin-service;1"]
-                     .getService(Ci.mozIGeckoMediaPluginChromeService);
-  gmpService.addPluginDirectory("/system/b2g/gmp-clearkey/0.1");
-} catch(e) {
-  dump("Failed to add clearkey path! " + e + "\n");
+  try {
+    let gmpService = Cc["@mozilla.org/gecko-media-plugin-service;1"]
+                       .getService(Ci.mozIGeckoMediaPluginChromeService);
+    gmpService.addPluginDirectory("/system/b2g/gmp-clearkey/0.1");
+  } catch(e) {
+    dump("Failed to add clearkey path! " + e + "\n");
+  }
 }
-#endif
 
 // Calling this observer will cause a shutdown an a profile reset.
 // Use eg. : Services.obs.notifyObservers(null, 'b2g-reset-profile', null);
 Services.obs.addObserver(function resetProfile(subject, topic, data) {
   Services.obs.removeObserver(resetProfile, topic);
 
   // Listening for 'profile-before-change2' which is late in the shutdown
   // sequence, but still has xpcom access.
   Services.obs.addObserver(function clearProfile(subject, topic, data) {
     Services.obs.removeObserver(clearProfile, topic);
-#ifdef MOZ_WIDGET_GONK
-    let json = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
-    json.initWithPath('/system/b2g/webapps/webapps.json');
-    let toRemove = json.exists()
-      // This is a user build, just rm -r /data/local /data/b2g/mozilla
-      ? ['/data/local', '/data/b2g/mozilla']
-      // This is an eng build. We clear the profile and a set of files
-      // under /data/local.
-      : ['/data/b2g/mozilla',
-         '/data/local/permissions.sqlite',
-         '/data/local/storage',
-         '/data/local/OfflineCache'];
+    if (isGonk) {
+      let json = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
+      json.initWithPath('/system/b2g/webapps/webapps.json');
+      let toRemove = json.exists()
+        // This is a user build, just rm -r /data/local /data/b2g/mozilla
+        ? ['/data/local', '/data/b2g/mozilla']
+        // This is an eng build. We clear the profile and a set of files
+        // under /data/local.
+        : ['/data/b2g/mozilla',
+           '/data/local/permissions.sqlite',
+           '/data/local/storage',
+           '/data/local/OfflineCache'];
 
-    toRemove.forEach(function(dir) {
-      try {
-        let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
-        file.initWithPath(dir);
-        file.remove(true);
-      } catch(e) { dump(e); }
-    });
-#else
-    // Desktop builds.
-    let profile = Services.dirsvc.get('ProfD', Ci.nsIFile);
+      toRemove.forEach(function(dir) {
+        try {
+          let file = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
+          file.initWithPath(dir);
+          file.remove(true);
+        } catch(e) { dump(e); }
+      });
+    } else {
+      // Desktop builds.
+      let profile = Services.dirsvc.get('ProfD', Ci.nsIFile);
 
-    // We don't want to remove everything from the profile, since this
-    // would prevent us from starting up.
-    let whitelist = ['defaults', 'extensions', 'settings.json',
-                     'user.js', 'webapps'];
-    let enumerator = profile.directoryEntries;
-    while (enumerator.hasMoreElements()) {
-      let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
-      if (whitelist.indexOf(file.leafName) == -1) {
-        file.remove(true);
+      // We don't want to remove everything from the profile, since this
+      // would prevent us from starting up.
+      let whitelist = ['defaults', 'extensions', 'settings.json',
+                       'user.js', 'webapps'];
+      let enumerator = profile.directoryEntries;
+      while (enumerator.hasMoreElements()) {
+        let file = enumerator.getNext().QueryInterface(Ci.nsIFile);
+        if (whitelist.indexOf(file.leafName) == -1) {
+          file.remove(true);
+        }
       }
     }
-#endif
   },
   'profile-before-change2', false);
 
   let appStartup = Cc['@mozilla.org/toolkit/app-startup;1']
                      .getService(Ci.nsIAppStartup);
   appStartup.quit(Ci.nsIAppStartup.eForceQuit);
 }, 'b2g-reset-profile', false);
 
-#ifdef MOZ_GRAPHENE
+if (AppConstants.MOZ_GRAPHENE) {
+  const restoreWindowGeometry = () => {
+    let screenX = Services.prefs.getIntPref("b2g.nativeWindowGeometry.screenX");
+    let screenY = Services.prefs.getIntPref("b2g.nativeWindowGeometry.screenY");
+    let width = Services.prefs.getIntPref("b2g.nativeWindowGeometry.width");
+    let height = Services.prefs.getIntPref("b2g.nativeWindowGeometry.height");
+
+    if (screenX == -1) {
+      // Center
+      screenX = (screen.width - width) / 2;
+      screenY = (screen.height - height) / 2;
+    }
+
+    moveTo(screenX, screenY);
+    resizeTo(width, height);
+  }
+  restoreWindowGeometry();
 
-const restoreWindowGeometry = () => {
-  let screenX = Services.prefs.getIntPref("b2g.nativeWindowGeometry.screenX");
-  let screenY = Services.prefs.getIntPref("b2g.nativeWindowGeometry.screenY");
-  let width = Services.prefs.getIntPref("b2g.nativeWindowGeometry.width");
-  let height = Services.prefs.getIntPref("b2g.nativeWindowGeometry.height");
+  const saveWindowGeometry = () => {
+    window.removeEventListener("unload", saveWindowGeometry);
+    Services.prefs.setIntPref("b2g.nativeWindowGeometry.screenX", screenX);
+    Services.prefs.setIntPref("b2g.nativeWindowGeometry.screenY", screenY);
+    Services.prefs.setIntPref("b2g.nativeWindowGeometry.width", outerWidth);
+    Services.prefs.setIntPref("b2g.nativeWindowGeometry.height", outerHeight);
+  }
+  window.addEventListener("unload", saveWindowGeometry);
 
-  if (screenX == -1) {
-    // Center
-    screenX = (screen.width - width) / 2;
-    screenY = (screen.height - height) / 2;
+  var baseWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIWebNavigation)
+                         .QueryInterface(Ci.nsIDocShellTreeItem)
+                         .treeOwner
+                         .QueryInterface(Ci.nsIInterfaceRequestor)
+                         .getInterface(Ci.nsIBaseWindow);
+
+  const showNativeWindow = () => baseWindow.visibility = true;
+  const hideNativeWindow = () => baseWindow.visibility = false;
+
+  const showInstallScreen = () => {
+    const grapheneStrings =
+      Services.strings.createBundle('chrome://b2g-l10n/locale/graphene.properties');
+    document.querySelector('#installing > .message').textContent =
+      grapheneStrings.GetStringFromName('installing');
+    showNativeWindow();
   }
 
-  moveTo(screenX, screenY);
-  resizeTo(width, height);
-}
-restoreWindowGeometry();
-
-const saveWindowGeometry = () => {
-  window.removeEventListener("unload", saveWindowGeometry);
-  Services.prefs.setIntPref("b2g.nativeWindowGeometry.screenX", screenX);
-  Services.prefs.setIntPref("b2g.nativeWindowGeometry.screenY", screenY);
-  Services.prefs.setIntPref("b2g.nativeWindowGeometry.width", outerWidth);
-  Services.prefs.setIntPref("b2g.nativeWindowGeometry.height", outerHeight);
-}
-window.addEventListener("unload", saveWindowGeometry);
-
-var baseWindow = window.QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIWebNavigation)
-                       .QueryInterface(Ci.nsIDocShellTreeItem)
-                       .treeOwner
-                       .QueryInterface(Ci.nsIInterfaceRequestor)
-                       .getInterface(Ci.nsIBaseWindow);
+  const hideInstallScreen = () => {
+    document.body.classList.add('content-loaded');
+  }
 
-const showNativeWindow = () => baseWindow.visibility = true;
-const hideNativeWindow = () => baseWindow.visibility = false;
-
-const showInstallScreen = () => {
-  const grapheneStrings =
-    Services.strings.createBundle('chrome://b2g-l10n/locale/graphene.properties');
-  document.querySelector('#installing > .message').textContent =
-    grapheneStrings.GetStringFromName('installing');
-  showNativeWindow();
-}
+  window.addEventListener('ContentStart', () => {
+    shell.contentBrowser.contentWindow.addEventListener('load', () => {
+      hideInstallScreen();
+      showNativeWindow();
+    });
+  });
 
-const hideInstallScreen = () => {
-  document.body.classList.add('content-loaded');
+  hideNativeWindow();
 }
-
-window.addEventListener('ContentStart', () => {
-  shell.contentBrowser.contentWindow.addEventListener('load', () => {
-    hideInstallScreen();
-    showNativeWindow();
-  });
-});
-
-hideNativeWindow();
-
-#endif
--- a/b2g/chrome/jar.mn
+++ b/b2g/chrome/jar.mn
@@ -4,28 +4,28 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 chrome.jar:
 % content branding %content/branding/ contentaccessible=yes
 % content b2g %content/
 
   content/arrow.svg                     (content/arrow.svg)
-* content/settings.js                   (content/settings.js)
+  content/settings.js                   (content/settings.js)
 * content/shell.html                    (content/shell.html)
-* content/shell.js                      (content/shell.js)
+  content/shell.js                      (content/shell.js)
   content/shell_remote.html             (content/shell_remote.html)
   content/shell_remote.js               (content/shell_remote.js)
 * content/shell.css                     (content/shell.css)
   content/blank.html                    (content/blank.html)
   content/blank.css                     (content/blank.css)
 #ifdef MOZ_WIDGET_GONK
   content/devtools/adb.js               (content/devtools/adb.js)
 #endif
-* content/devtools/debugger.js          (content/devtools/debugger.js)
+  content/devtools/debugger.js          (content/devtools/debugger.js)
   content/devtools/hud.js               (content/devtools/hud.js)
 #ifndef MOZ_WIDGET_GONK
   content/desktop.css                   (content/desktop.css)
   content/images/desktop/home-black.png (content/images/desktop/home-black.png)
   content/images/desktop/home-white.png (content/images/desktop/home-white.png)
   content/images/desktop/rotate.png     (content/images/desktop/rotate.png)
   content/desktop.js                    (content/desktop.js)
   content/screen.js                     (content/screen.js)
--- a/b2g/components/DirectoryProvider.js
+++ b/b2g/components/DirectoryProvider.js
@@ -4,16 +4,17 @@
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/AppConstants.jsm");
 
 const XRE_OS_UPDATE_APPLY_TO_DIR = "OSUpdApplyToD"
 const UPDATE_ARCHIVE_DIR = "UpdArchD"
 const LOCAL_DIR = "/data/local";
 const UPDATES_DIR = "updates/0";
 const FOTA_DIR = "updates/fota";
 const COREAPPSDIR_PREF = "b2g.coreappsdir"
 
@@ -52,18 +53,24 @@ function DirectoryProvider() {
 DirectoryProvider.prototype = {
   classID: Components.ID("{9181eb7c-6f87-11e1-90b1-4f59d80dd2e5}"),
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIDirectoryServiceProvider]),
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(DirectoryProvider),
 
   _profD: null,
 
-  getFile: function dp_getFile(prop, persistent) {
-#ifdef MOZ_WIDGET_GONK
+  getFile: function(prop, persistent) {
+    if (AppConstants.platform === "gonk") {
+      return this.getFileOnGonk(prop, persistent);
+    }
+    return this.getFileNotGonk(prop, persistent);
+  },
+
+  getFileOnGonk: function(prop, persistent) {
     let localProps = ["cachePDir", "webappsDir", "PrefD", "indexedDBPDir",
                       "permissionDBPDir", "UpdRootD"];
     if (localProps.indexOf(prop) != -1) {
       let file = Cc["@mozilla.org/file/local;1"]
                    .createInstance(Ci.nsILocalFile)
       file.initWithPath(LOCAL_DIR);
       persistent.value = true;
       return file;
@@ -92,17 +99,20 @@ DirectoryProvider.prototype = {
     }
     if (prop == XRE_OS_UPDATE_APPLY_TO_DIR) {
       // getUpdateDir will set persistent to false since it may toggle between
       // /data/local/ and /mnt/sdcard based on free space and/or availability
       // of the sdcard.
       // before apply, check if free space is 1.1 times of update.mar
       return this.getUpdateDir(persistent, FOTA_DIR, 1.1);
     }
-#else
+    return null;
+  },
+
+  getFileNotGonk: function(prop, persistent) {
     // In desktop builds, coreAppsDir is the same as the profile
     // directory unless otherwise specified. We just need to get the
     // path from the parent, and it is then used to build
     // jar:remoteopenfile:// uris.
     if (prop == "coreAppsDir") {
       let coreAppsDirPref;
       try {
         coreAppsDirPref = Services.prefs.getCharPref(COREAPPSDIR_PREF);
@@ -132,17 +142,16 @@ DirectoryProvider.prototype = {
       if (!this._profD) {
         this._profD = cpmm.sendSyncMessage("getProfD", {})[0];
       }
       let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
       file.initWithPath(this._profD);
       persistent.value = true;
       return file;
     }
-#endif
     return null;
   },
 
   // The VolumeService only exists on the device, and not on desktop
   volumeHasFreeSpace: function dp_volumeHasFreeSpace(volumePath, requiredSpace) {
     if (!volumePath) {
       return false;
     }
--- a/b2g/components/HelperAppDialog.js
+++ b/b2g/components/HelperAppDialog.js
@@ -34,17 +34,17 @@ HelperAppLauncherDialog.prototype = {
   },
 
   promptForSaveToFileAsync: function(aLauncher,
                                      aContext,
                                      aDefaultFile,
                                      aSuggestedFileExt,
                                      aForcePrompt) {
     // Retrieve the user's default download directory.
-    Task.spawn(function() {
+    Task.spawn(function*() {
       let file = null;
       try {
         let defaultFolder = yield Downloads.getPreferredDownloadsDirectory();
         let dir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
         dir.initWithPath(defaultFolder);
         file = this.validateLeafName(dir, aDefaultFile, aSuggestedFileExt);
       } catch(e) { }
       aLauncher.saveDestinationAvailable(file);
--- a/b2g/components/KillSwitchMain.jsm
+++ b/b2g/components/KillSwitchMain.jsm
@@ -5,16 +5,17 @@
 "use strict";
 
 this.EXPORTED_SYMBOLS = [ "KillSwitchMain" ];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/AppConstants.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Promise", "resource://gre/modules/Promise.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "settings",
                    "@mozilla.org/settingsService;1",
                    "nsISettingsService");
 
@@ -22,24 +23,24 @@ XPCOMUtils.defineLazyServiceGetter(this,
                    "@mozilla.org/parentprocessmessagemanager;1",
                    "nsIMessageBroadcaster");
 
 XPCOMUtils.defineLazyGetter(this, "permMgr", function() {
   return Cc["@mozilla.org/permissionmanager;1"]
            .getService(Ci.nsIPermissionManager);
 });
 
-#ifdef MOZ_WIDGET_GONK
-XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
-  Cu.import("resource://gre/modules/systemlibs.js");
-  return libcutils;
-});
-#else
-this.libcutils = null;
-#endif
+if (AppConstants.platform === "gonk") {
+  XPCOMUtils.defineLazyGetter(this, "libcutils", function () {
+    Cu.import("resource://gre/modules/systemlibs.js");
+    return libcutils;
+  });
+} else {
+  this.libcutils = null;
+}
 
 const DEBUG = false;
 
 const kEnableKillSwitch   = "KillSwitch:Enable";
 const kEnableKillSwitchOK = "KillSwitch:Enable:OK";
 const kEnableKillSwitchKO = "KillSwitch:Enable:KO";
 
 const kDisableKillSwitch   = "KillSwitch:Disable";
--- a/b2g/components/RecoveryService.js
+++ b/b2g/components/RecoveryService.js
@@ -4,76 +4,82 @@
  * 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/. */
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/ctypes.jsm");
+Cu.import("resource://gre/modules/AppConstants.jsm");
 
 const RECOVERYSERVICE_CID = Components.ID("{b3caca5d-0bb0-48c6-912b-6be6cbf08832}");
 const RECOVERYSERVICE_CONTRACTID = "@mozilla.org/recovery-service;1";
 
 function log(msg) {
   dump("-*- RecoveryService: " + msg + "\n");
 }
 
-#ifdef MOZ_WIDGET_GONK
-var librecovery = (function() {
-  let library;
-  try {
-    library = ctypes.open("librecovery.so");
-  } catch (e) {
-    log("Unable to open librecovery.so");
-    throw Cr.NS_ERROR_FAILURE;
-  }
-  // Bug 1163956, modify updatePath from ctyps.char.ptr to ctype.char.array(4096)
-  // align with librecovery.h. 4096 comes from PATH_MAX
-  let FotaUpdateStatus = new ctypes.StructType("FotaUpdateStatus", [
-                                                { result: ctypes.int },
-                                                { updatePath: ctypes.char.array(4096) }
-                                              ]);
+const isGonk = AppConstants.platform === 'gonk';
+
+if (isGonk) {
+  var librecovery = (function() {
+    let library;
+    try {
+      library = ctypes.open("librecovery.so");
+    } catch (e) {
+      log("Unable to open librecovery.so");
+      throw Cr.NS_ERROR_FAILURE;
+    }
+    // Bug 1163956, modify updatePath from ctyps.char.ptr to ctype.char.array(4096)
+    // align with librecovery.h. 4096 comes from PATH_MAX
+    let FotaUpdateStatus = new ctypes.StructType("FotaUpdateStatus", [
+                                                  { result: ctypes.int },
+                                                  { updatePath: ctypes.char.array(4096) }
+                                                ]);
 
-  return {
-    factoryReset:        library.declare("factoryReset",
-                                         ctypes.default_abi,
-                                         ctypes.int),
-    installFotaUpdate:   library.declare("installFotaUpdate",
-                                         ctypes.default_abi,
-                                         ctypes.int,
-                                         ctypes.char.ptr,
-                                         ctypes.int),
+    return {
+      factoryReset:        library.declare("factoryReset",
+                                           ctypes.default_abi,
+                                           ctypes.int),
+      installFotaUpdate:   library.declare("installFotaUpdate",
+                                           ctypes.default_abi,
+                                           ctypes.int,
+                                           ctypes.char.ptr,
+                                           ctypes.int),
 
-    FotaUpdateStatus:    FotaUpdateStatus,
-    getFotaUpdateStatus: library.declare("getFotaUpdateStatus",
-                                         ctypes.default_abi,
-                                         ctypes.int,
-                                         FotaUpdateStatus.ptr)
-  };
-})();
+      FotaUpdateStatus:    FotaUpdateStatus,
+      getFotaUpdateStatus: library.declare("getFotaUpdateStatus",
+                                           ctypes.default_abi,
+                                           ctypes.int,
+                                           FotaUpdateStatus.ptr)
+    };
+  })();
 
-const gFactoryResetFile = "__post_reset_cmd__";
+  const gFactoryResetFile = "__post_reset_cmd__";
 
-#endif
+}
 
 function RecoveryService() {}
 
 RecoveryService.prototype = {
   classID: RECOVERYSERVICE_CID,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIRecoveryService]),
   classInfo: XPCOMUtils.generateCI({
     classID: RECOVERYSERVICE_CID,
     contractID: RECOVERYSERVICE_CONTRACTID,
     interfaces: [Ci.nsIRecoveryService],
     classDescription: "B2G Recovery Service"
   }),
 
   factoryReset: function RS_factoryReset(reason) {
-#ifdef MOZ_WIDGET_GONK
+    if (!isGonk) {
+      Cr.NS_ERROR_FAILURE;
+    }
+
     function doReset() {
       // If this succeeds, then the device reboots and this never returns
       if (librecovery.factoryReset() != 0) {
         log("Error: Factory reset failed. Trying again after clearing cache.");
       }
       let cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"]
                     .getService(Ci.nsICacheStorageService);
       cache.clear();
@@ -114,42 +120,41 @@ RecoveryService.prototype = {
                                         { tmpPath: postResetFile + ".tmp" });
 
       promise.then(doReset, function onError(error) {
         log("Error: " + error);
       });
     } else {
       doReset();
     }
-#endif
-    throw Cr.NS_ERROR_FAILURE;
   },
 
   installFotaUpdate: function RS_installFotaUpdate(updatePath) {
-#ifdef MOZ_WIDGET_GONK
+    if (!isGonk) {
+      throw Cr.NS_ERROR_FAILURE;
+    }
+
     // If this succeeds, then the device reboots and this never returns
     if (librecovery.installFotaUpdate(updatePath, updatePath.length) != 0) {
       log("Error: FOTA install failed. Trying again after clearing cache.");
     }
     var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
     cache.clear();
     if (librecovery.installFotaUpdate(updatePath, updatePath.length) != 0) {
       log("Error: FOTA install failed again");
     }
-#endif
-    throw Cr.NS_ERROR_FAILURE;
   },
 
   getFotaUpdateStatus: function RS_getFotaUpdateStatus() {
     let status =  Ci.nsIRecoveryService.FOTA_UPDATE_UNKNOWN;
-#ifdef MOZ_WIDGET_GONK
-    let cStatus = librecovery.FotaUpdateStatus();
+
+    if (isGonk) {
+      let cStatus = librecovery.FotaUpdateStatus();
 
-    if (librecovery.getFotaUpdateStatus(cStatus.address()) == 0) {
-      status = cStatus.result;
+      if (librecovery.getFotaUpdateStatus(cStatus.address()) == 0) {
+        status = cStatus.result;
+      }
     }
-
-#endif
     return status;
   }
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([RecoveryService]);
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -8,16 +8,17 @@
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 const Cr = Components.results;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/WebappsUpdater.jsm");
+Cu.import("resource://gre/modules/AppConstants.jsm");
 
 const VERBOSE = 1;
 var log =
   VERBOSE ?
   function log_dump(msg) { dump("UpdatePrompt: "+ msg +"\n"); } :
   function log_noop(msg) { };
 
 const PREF_APPLY_PROMPT_TIMEOUT          = "b2g.update.apply-prompt-timeout";
@@ -394,40 +395,40 @@ UpdatePrompt.prototype = {
     }
 
     if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
       log("Unable to prompt, forcing restart");
       this.restartProcess();
       return;
     }
 
-#ifdef MOZ_B2G_RIL
-    let window = Services.wm.getMostRecentWindow("navigator:browser");
-    let pinReq = window.navigator.mozIccManager.getCardLock("pin");
-    pinReq.onsuccess = function(e) {
-      if (e.target.result.enabled) {
-        // The SIM is pin locked. Don't use a fallback timer. This means that
-        // the user has to press Install to apply the update. If we use the
-        // timer, and the timer reboots the phone, then the phone will be
-        // unusable until the SIM is unlocked.
-        log("SIM is pin locked. Not starting fallback timer.");
-      } else {
-        // This means that no pin lock is enabled, so we go ahead and start
-        // the fallback timer.
+    if (AppConstants.MOZ_B2G_RIL) {
+      let window = Services.wm.getMostRecentWindow("navigator:browser");
+      let pinReq = window.navigator.mozIccManager.getCardLock("pin");
+      pinReq.onsuccess = function(e) {
+        if (e.target.result.enabled) {
+          // The SIM is pin locked. Don't use a fallback timer. This means that
+          // the user has to press Install to apply the update. If we use the
+          // timer, and the timer reboots the phone, then the phone will be
+          // unusable until the SIM is unlocked.
+          log("SIM is pin locked. Not starting fallback timer.");
+        } else {
+          // This means that no pin lock is enabled, so we go ahead and start
+          // the fallback timer.
+          this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
+        }
+      }.bind(this);
+      pinReq.onerror = function(e) {
         this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
-      }
-    }.bind(this);
-    pinReq.onerror = function(e) {
+      }.bind(this);
+    } else {
+      // Schedule a fallback timeout in case the UI is unable to respond or show
+      // a prompt for some reason.
       this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
-    }.bind(this);
-#else
-    // Schedule a fallback timeout in case the UI is unable to respond or show
-    // a prompt for some reason.
-    this._applyPromptTimer = this.createTimer(this.applyPromptTimeout);
-#endif
+    }
   },
 
   _copyProperties: ["appVersion", "buildID", "detailsURL", "displayVersion",
                     "errorCode", "isOSUpdate", "platformVersion",
                     "previousAppVersion", "state", "statusText"],
 
   sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
     let detail = {};
@@ -548,26 +549,26 @@ UpdatePrompt.prototype = {
       this.showUpdateError(this._update);
     }
   },
 
   restartProcess: function UP_restartProcess() {
     log("Update downloaded, restarting to apply it");
 
     let callbackAfterSet = function() {
-#ifndef MOZ_WIDGET_GONK
-      let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
-                       .getService(Ci.nsIAppStartup);
-      appStartup.quit(appStartup.eForceQuit | appStartup.eRestart);
-#else
-      // NB: on Gonk, we rely on the system process manager to restart us.
-      let pmService = Cc["@mozilla.org/power/powermanagerservice;1"]
-                      .getService(Ci.nsIPowerManagerService);
-      pmService.restart();
-#endif
+      if (AppConstants.platform !== "gonk") {
+        let appStartup = Cc["@mozilla.org/toolkit/app-startup;1"]
+                         .getService(Ci.nsIAppStartup);
+        appStartup.quit(appStartup.eForceQuit | appStartup.eRestart);
+      } else {
+        // NB: on Gonk, we rely on the system process manager to restart us.
+        let pmService = Cc["@mozilla.org/power/powermanagerservice;1"]
+                        .getService(Ci.nsIPowerManagerService);
+        pmService.restart();
+      }
     }
 
     if (useSettings()) {
       // Save current os version in deviceinfo.previous_os
       let lock = Services.settings.createLock({
         handle: callbackAfterSet,
         handleAbort: function(error) {
           log("Abort callback when trying to set previous_os: " + error);
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -39,49 +39,46 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk
       'SimulatorScreen.js'
     ]
 
 EXTRA_PP_COMPONENTS += [
     'B2GComponents.manifest',
 ]
 
 if CONFIG['MOZ_B2G'] and not CONFIG['MOZ_B2GDROID']:
-    EXTRA_PP_COMPONENTS += [
+    EXTRA_COMPONENTS += [
         'DirectoryProvider.js',
         'RecoveryService.js',
     ]
 
 if CONFIG['MOZ_UPDATER']:
-    EXTRA_PP_COMPONENTS += [
+    EXTRA_COMPONENTS += [
         'UpdatePrompt.js',
     ]
 
 EXTRA_JS_MODULES += [
     'AboutServiceWorkers.jsm',
     'ActivityChannel.jsm',
     'AlertsHelper.jsm',
     'Bootstraper.jsm',
     'ContentRequestHelper.jsm',
     'DebuggerActors.js',
     'ErrorPage.jsm',
     'Frames.jsm',
     'FxAccountsMgmtService.jsm',
+    'KillSwitchMain.jsm',
     'LogCapture.jsm',
     'LogParser.jsm',
     'LogShake.jsm',
     'MultiscreenHandler.jsm',
     'OrientationChangeHandler.jsm',
     'SafeMode.jsm',
     'Screenshot.jsm',
     'SignInToWebsite.jsm',
     'SystemAppProxy.jsm',
     'TelURIParser.jsm',
     'WebappsUpdater.jsm',
 ]
 
-EXTRA_PP_JS_MODULES += [
-    'KillSwitchMain.jsm'
-]
-
 if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk':
     EXTRA_JS_MODULES += [
       'GlobalSimulatorScreen.jsm'
     ]
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,26 +10,26 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,26 +10,26 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gecko and Gaia -->
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <!-- Gonk-specific things and forks -->
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
   <project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was git://github.com/mozilla/-->
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gecko and Gaia -->
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <!-- Gonk-specific things and forks -->
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform_build" path="build" remote="b2g" revision="1b0db93fb6b870b03467aff50d6419771ba0d88c">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
   <project name="android-development" path="development" remote="b2g" revision="2bdf22305b523af644e1891b4ddfd9229336d0ce"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,26 +10,26 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "97266c579c544f5ba57a701f39893cc86d46774a", 
+        "git_revision": "23a94087e701c4bc592f2943e1007e25a9242f97", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "91dde717827095968985b59e5a645b6ac774d015", 
+    "revision": "1a71a5a828091c47b1306ca850d8ac882c7c0c0d", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-kk/sources.xml
@@ -10,26 +10,26 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8d83715f08b7849f16a0dfc88f78d5c3a89c0a54">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -13,20 +13,20 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="660169a3d7e034a892359e39135e8c2785a6ad6f">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,26 +10,26 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="c9d4fe680662ee44a4bdea42ae00366f5df399cf">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="97266c579c544f5ba57a701f39893cc86d46774a"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="23a94087e701c4bc592f2943e1007e25a9242f97"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="fake-qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="939b377d55a2f081d94029a30a75d05e5a20daf3"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="4a962bdab532e18f53e9d2d114c349983262c6b7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ac7e9ae8a24ab4a3f3da801ca53f95f39a32b89f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="5f931350fbc87c3df9db8b0ceb37734b8b471593"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="48d8c7c950745f1b166b42125e6f0d3293d71636"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="5de6856fad82857028f9f059f50680a9bea5b75c"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="2d70fdfc0244a7217df1cfa7df9f4798cbfa3af6"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
--- a/build/autoconf/icu.m4
+++ b/build/autoconf/icu.m4
@@ -15,20 +15,20 @@ MOZ_ARG_WITH_BOOL(system-icu,
 [  --with-system-icu
                           Use system ICU (located with pkgconfig)],
     MOZ_NATIVE_ICU=1)
 
 if test -n "$MOZ_NATIVE_ICU"; then
     PKG_CHECK_MODULES(MOZ_ICU, icu-i18n >= 50.1)
     MOZ_SHARED_ICU=1
 else
-    MOZ_ICU_CFLAGS="-I$_topsrcdir/intl/icu/source/common -I$_topsrcdir/intl/icu/source/i18n"
-    AC_SUBST_LIST(MOZ_ICU_CFLAGS)
+    MOZ_ICU_INCLUDES="/intl/icu/source/common /intl/icu/source/i18n"
 fi
 
+AC_SUBST_LIST(MOZ_ICU_INCLUDES)
 AC_SUBST(MOZ_NATIVE_ICU)
 
 MOZ_ARG_WITH_STRING(intl-api,
 [  --with-intl-api, --with-intl-api=build, --without-intl-api
     Determine the status of the ECMAScript Internationalization API.  The first
     (or lack of any of these) builds and exposes the API.  The second builds it
     but doesn't use ICU or expose the API to script.  The third doesn't build
     ICU at all.],
--- a/config/system-headers
+++ b/config/system-headers
@@ -178,16 +178,17 @@ Appearance.h
 AppFileInfo.h
 AppKit.h
 AppleEvents.h
 Application.h
 app/Message.h
 app/MessageRunner.h
 arpa/inet.h
 arpa/nameser.h
+array
 asm/page.h
 asm/sigcontext.h
 asm/signal.h
 ASRegistry.h
 assert.h
 atk/atk.h
 atlcom.h
 atlconv.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -370,29 +370,21 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
     }
 
     if (callbacks->mDetachedCallback.WasPassed()) {
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
         "mCustomDefinitions->mCallbacks->mDetachedCallback");
       cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value());
     }
   }
-  for (auto iter = tmp->mCandidatesMap.Iter(); !iter.Done(); iter.Next()) {
-    nsTArray<RefPtr<Element>>* elems = iter.UserData();
-    for (size_t i = 0; i < elems->Length(); ++i) {
-      NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCandidatesMap->Element");
-      cb.NoteXPCOMChild(elems->ElementAt(i));
-    }
-  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Registry)
   tmp->mCustomDefinitions.Clear();
-  tmp->mCandidatesMap.Clear();
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Registry)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Registry)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Registry)
@@ -5777,26 +5769,26 @@ nsDocument::RegisterUnresolvedElement(El
     typeName = info->NameAtom();
   }
 
   CustomElementHashKey key(info->NamespaceID(), typeName);
   if (mRegistry->mCustomDefinitions.Get(&key)) {
     return NS_OK;
   }
 
-  nsTArray<RefPtr<Element>>* unresolved;
+  nsTArray<nsWeakPtr>* unresolved;
   mRegistry->mCandidatesMap.Get(&key, &unresolved);
   if (!unresolved) {
-    unresolved = new nsTArray<RefPtr<Element>>();
+    unresolved = new nsTArray<nsWeakPtr>();
     // Ownership of unresolved is taken by mCandidatesMap.
     mRegistry->mCandidatesMap.Put(&key, unresolved);
   }
 
-  RefPtr<Element>* elem = unresolved->AppendElement();
-  *elem = aElement;
+  nsWeakPtr* elem = unresolved->AppendElement();
+  *elem = do_GetWeakReference(aElement);
   aElement->AddStates(NS_EVENT_STATE_UNRESOLVED);
 
   return NS_OK;
 }
 
 void
 nsDocument::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
                                      Element* aCustomElement,
@@ -6170,21 +6162,24 @@ nsDocument::RegisterElement(JSContext* a
                                 typeAtom,
                                 nameAtom,
                                 callbacks,
                                 namespaceID,
                                 0 /* TODO dependent on HTML imports. Bug 877072 */);
   definitions.Put(&key, definition);
 
   // Do element upgrade.
-  nsAutoPtr<nsTArray<RefPtr<Element>>> candidates;
+  nsAutoPtr<nsTArray<nsWeakPtr>> candidates;
   mRegistry->mCandidatesMap.RemoveAndForget(&key, candidates);
   if (candidates) {
     for (size_t i = 0; i < candidates->Length(); ++i) {
-      Element *elem = candidates->ElementAt(i);
+      nsCOMPtr<Element> elem = do_QueryReferent(candidates->ElementAt(i));
+      if (!elem) {
+        continue;
+      }
 
       elem->RemoveStates(NS_EVENT_STATE_UNRESOLVED);
 
       // Make sure that the element name matches the name in the definition.
       // (e.g. a definition for x-button extending button should match
       // <button is="x-button"> but not <x-button>.
       if (elem->NodeInfo()->NameAtom() != nameAtom) {
         //Skip over this element because definition does not apply.
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -422,17 +422,17 @@ public:
 
 protected:
   virtual ~Registry();
 
   typedef nsClassHashtable<mozilla::dom::CustomElementHashKey,
                            mozilla::dom::CustomElementDefinition>
     DefinitionMap;
   typedef nsClassHashtable<mozilla::dom::CustomElementHashKey,
-                           nsTArray<RefPtr<mozilla::dom::Element>>>
+                           nsTArray<nsWeakPtr>>
     CandidateMap;
 
   // Hashtable for custom element definitions in web components.
   // Custom prototypes are stored in the compartment where
   // registerElement was called.
   DefinitionMap mCustomDefinitions;
 
   // The "upgrade candidates map" from the web components spec. Maps from a
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -405,61 +405,27 @@ class CGDOMJSClass(CGThing):
     def __init__(self, descriptor):
         CGThing.__init__(self)
         self.descriptor = descriptor
 
     def declare(self):
         return ""
 
     def define(self):
-        traceHook = 'nullptr'
         callHook = LEGACYCALLER_HOOK_NAME if self.descriptor.operations["LegacyCaller"] else 'nullptr'
         objectMovedHook = OBJECT_MOVED_HOOK_NAME if self.descriptor.wrapperCache else 'nullptr'
         slotCount = INSTANCE_RESERVED_SLOTS + self.descriptor.interface.totalMembersInSlots
         classFlags = "JSCLASS_IS_DOMJSCLASS | "
-        classExtensionAndObjectOps = fill(
-            """
-            {
-              false,   /* isWrappedNative */
-              nullptr, /* weakmapKeyDelegateOp */
-              ${objectMoved} /* objectMovedOp */
-            },
-            JS_NULL_OBJECT_OPS
-            """,
-            objectMoved=objectMovedHook)
         if self.descriptor.isGlobal():
             classFlags += "JSCLASS_DOM_GLOBAL | JSCLASS_GLOBAL_FLAGS_WITH_SLOTS(DOM_GLOBAL_SLOTS)"
             traceHook = "JS_GlobalObjectTraceHook"
             reservedSlots = "JSCLASS_GLOBAL_APPLICATION_SLOTS"
-            if self.descriptor.interface.identifier.name == "Window":
-                classExtensionAndObjectOps = fill(
-                    """
-                    {
-                      false,   /* isWrappedNative */
-                      nullptr, /* weakmapKeyDelegateOp */
-                      ${objectMoved} /* objectMovedOp */
-                    },
-                    {
-                      nullptr, /* lookupProperty */
-                      nullptr, /* defineProperty */
-                      nullptr, /* hasProperty */
-                      nullptr, /* getProperty */
-                      nullptr, /* setProperty */
-                      nullptr, /* getOwnPropertyDescriptor */
-                      nullptr, /* deleteProperty */
-                      nullptr, /* watch */
-                      nullptr, /* unwatch */
-                      nullptr, /* getElements */
-                      nullptr, /* enumerate */
-                      nullptr, /* funToString */
-                    }
-                    """,
-                    objectMoved=objectMovedHook)
         else:
             classFlags += "JSCLASS_HAS_RESERVED_SLOTS(%d)" % slotCount
+            traceHook = 'nullptr'
             reservedSlots = slotCount
         if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
             resolveHook = RESOLVE_HOOK_NAME
             mayResolveHook = MAY_RESOLVE_HOOK_NAME
             enumerateHook = ENUMERATE_HOOK_NAME
         elif self.descriptor.isGlobal():
             resolveHook = "mozilla::dom::ResolveGlobal"
             mayResolveHook = "mozilla::dom::MayResolveGlobal"
@@ -482,17 +448,22 @@ class CGDOMJSClass(CGThing):
                 ${resolve}, /* resolve */
                 ${mayResolve}, /* mayResolve */
                 ${finalize}, /* finalize */
                 ${call}, /* call */
                 nullptr,               /* hasInstance */
                 nullptr,               /* construct */
                 ${trace}, /* trace */
                 JS_NULL_CLASS_SPEC,
-                $*{classExtensionAndObjectOps}
+                {
+                  false,   /* isWrappedNative */
+                  nullptr, /* weakmapKeyDelegateOp */
+                  ${objectMoved} /* objectMovedOp */
+                },
+                JS_NULL_OBJECT_OPS
               },
               $*{descriptor}
             };
             static_assert(${instanceReservedSlots} == DOM_INSTANCE_RESERVED_SLOTS,
                           "Must have the right minimal number of reserved slots.");
             static_assert(${reservedSlots} >= ${slotCount},
                           "Must have enough reserved slots.");
             """,
@@ -500,17 +471,17 @@ class CGDOMJSClass(CGThing):
             flags=classFlags,
             addProperty=ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'nullptr',
             enumerate=enumerateHook,
             resolve=resolveHook,
             mayResolve=mayResolveHook,
             finalize=FINALIZE_HOOK_NAME,
             call=callHook,
             trace=traceHook,
-            classExtensionAndObjectOps=classExtensionAndObjectOps,
+            objectMoved=objectMovedHook,
             descriptor=DOMClass(self.descriptor),
             instanceReservedSlots=INSTANCE_RESERVED_SLOTS,
             reservedSlots=reservedSlots,
             slotCount=slotCount)
 
 
 class CGDOMProxyJSClass(CGThing):
     """
--- a/dom/indexedDB/moz.build
+++ b/dom/indexedDB/moz.build
@@ -102,8 +102,9 @@ LOCAL_INCLUDES += [
     '/dom/workers',
     '/ipc/glue',
     '/xpcom/build',
     '/xpcom/threads',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -2960,16 +2960,25 @@ ContentChild::RecvShutdown()
     nsCOMPtr<nsIObserverService> os = services::GetObserverService();
     if (os) {
         os->NotifyObservers(static_cast<nsIContentChild*>(this),
                             "content-child-shutdown", nullptr);
     }
 
     GetIPCChannel()->SetAbortOnError(false);
 
+#ifdef MOZ_ENABLE_PROFILER_SPS
+    if (profiler_is_active()) {
+        // We're shutting down while we were profiling. Send the
+        // profile up to the parent so that we don't lose this
+        // information.
+        Unused << RecvGatherProfile();
+    }
+#endif
+
     // Ignore errors here. If this fails, the parent will kill us after a
     // timeout.
     Unused << SendFinishShutdown();
     return true;
 }
 
 PBrowserOrId
 ContentChild::GetBrowserOrId(TabChild* aTabChild)
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1564,16 +1564,21 @@ ContentParent::Init()
     DebugOnly<nsresult> rv = profiler->IsActive(&profilerActive);
     MOZ_ASSERT(NS_SUCCEEDED(rv));
 
     if (profilerActive) {
         nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
         rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
         MOZ_ASSERT(NS_SUCCEEDED(rv));
 
+        nsCOMPtr<nsISupports> gatherer;
+        rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+        mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
+
         StartProfiler(currentProfilerParams);
     }
 #endif
 }
 
 void
 ContentParent::ForwardKnownInfo()
 {
@@ -2084,16 +2089,22 @@ ContentParent::ActorDestroy(ActorDestroy
         sNuwaPrefUpdates = nullptr;
     }
 #endif
 
     RecvRemoveGeolocationListener();
 
     mConsoleService = nullptr;
 
+#ifdef MOZ_ENABLE_PROFILER_SPS
+    if (mGatherer && !mProfile.IsEmpty()) {
+        mGatherer->OOPExitProfile(mProfile);
+    }
+#endif
+
     if (obs) {
         RefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
 
         props->SetPropertyAsUint64(NS_LITERAL_STRING("childID"), mChildID);
 
         if (AbnormalShutdown == why) {
             Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
                                   NS_LITERAL_CSTRING("content"), 1);
@@ -3288,28 +3299,30 @@ ContentParent::Observe(nsISupports* aSub
         Unused << SendOnAppThemeChanged();
     }
 #ifdef MOZ_ENABLE_PROFILER_SPS
     else if (!strcmp(aTopic, "profiler-started")) {
         nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
         StartProfiler(params);
     }
     else if (!strcmp(aTopic, "profiler-stopped")) {
+        mGatherer = nullptr;
         Unused << SendStopProfiler();
     }
     else if (!strcmp(aTopic, "profiler-paused")) {
         Unused << SendPauseProfiler(true);
     }
     else if (!strcmp(aTopic, "profiler-resumed")) {
         Unused << SendPauseProfiler(false);
     }
     else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
-        mGatherer = static_cast<ProfileGatherer*>(aSubject);
-        mGatherer->WillGatherOOPProfile();
-        Unused << SendGatherProfile();
+        if (mGatherer) {
+            mGatherer->WillGatherOOPProfile();
+            Unused << SendGatherProfile();
+        }
     }
     else if (!strcmp(aTopic, "profiler-subprocess")) {
         nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
         if (pse) {
             if (!mProfile.IsEmpty()) {
                 pse->AddSubProfile(mProfile.get());
                 mProfile.Truncate();
             }
@@ -5651,17 +5664,16 @@ bool
 ContentParent::RecvProfile(const nsCString& aProfile)
 {
 #ifdef MOZ_ENABLE_PROFILER_SPS
     if (NS_WARN_IF(!mGatherer)) {
         return true;
     }
     mProfile = aProfile;
     mGatherer->GatheredOOPProfile();
-    mGatherer = nullptr;
 #endif
     return true;
 }
 
 bool
 ContentParent::RecvGetGraphicsDeviceInitData(DeviceInitData* aOut)
 {
   gfxPlatform::GetPlatform()->GetDeviceInitData(aOut);
@@ -5742,16 +5754,24 @@ ContentParent::StartProfiler(nsIProfiler
 
     ipcParams.enabled() = true;
     aParams->GetEntries(&ipcParams.entries());
     aParams->GetInterval(&ipcParams.interval());
     ipcParams.features() = aParams->GetFeatures();
     ipcParams.threadFilters() = aParams->GetThreadFilterNames();
 
     Unused << SendStartProfiler(ipcParams);
+
+    nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
+    if (NS_WARN_IF(!profiler)) {
+        return;
+    }
+    nsCOMPtr<nsISupports> gatherer;
+    profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+    mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
 #endif
 }
 
 } // namespace dom
 } // namespace mozilla
 
 NS_IMPL_ISUPPORTS(ParentIdleListener, nsIObserver)
 
--- a/dom/media/AudioStream.h
+++ b/dom/media/AudioStream.h
@@ -83,17 +83,17 @@ public:
     : 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) {
     MOZ_ASSERT(!mBuffer, "Buffer allocated.");
     mCapacity = aCapacity;
-    mBuffer = new uint8_t[mCapacity];
+    mBuffer = MakeUnique<uint8_t[]>(mCapacity);
   }
 
   uint32_t Length() {
     return mCount;
   }
 
   uint32_t Capacity() {
     return mCapacity;
@@ -132,22 +132,22 @@ public:
     mCount -= *aSize1 + *aSize2;
     mStart += *aSize1 + *aSize2;
     mStart %= mCapacity;
   }
 
   size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
   {
     size_t amount = 0;
-    amount += mBuffer.SizeOfExcludingThis(aMallocSizeOf);
+    amount += aMallocSizeOf(mBuffer.get());
     return amount;
   }
 
 private:
-  nsAutoArrayPtr<uint8_t> mBuffer;
+  UniquePtr<uint8_t[]> mBuffer;
   uint32_t mCapacity;
   uint32_t mStart;
   uint32_t mCount;
 };
 
 // Access to a single instance of this class must be synchronized by
 // callers, or made from a single thread.  One exception is that access to
 // GetPosition, GetPositionInFrames, SetVolume, and Get{Rate,Channels},
--- a/dom/media/FileBlockCache.h
+++ b/dom/media/FileBlockCache.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef FILE_BLOCK_CACHE_H_
 #define FILE_BLOCK_CACHE_H_
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Monitor.h"
+#include "mozilla/UniquePtr.h"
 #include "nsTArray.h"
 #include "MediaCache.h"
 #include "nsDeque.h"
 #include "nsThreadUtils.h"
 
 struct PRFileDesc;
 
 namespace mozilla {
@@ -91,26 +92,26 @@ public:
 
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BlockChange)
 
     // This block is waiting in memory to be written.
     // Stores a copy of the block, so we can write it asynchronously.
     explicit BlockChange(const uint8_t* aData)
       : mSourceBlockIndex(-1)
     {
-      mData = new uint8_t[BLOCK_SIZE];
+      mData = MakeUnique<uint8_t[]>(BLOCK_SIZE);
       memcpy(mData.get(), aData, BLOCK_SIZE);
     }
 
     // This block's contents are located in another file
     // block, i.e. this block has been moved.
     explicit BlockChange(int32_t aSourceBlockIndex)
       : mSourceBlockIndex(aSourceBlockIndex) {}
 
-    nsAutoArrayPtr<uint8_t> mData;
+    UniquePtr<uint8_t[]> mData;
     const int32_t mSourceBlockIndex;
 
     bool IsMove() const {
       return mSourceBlockIndex != -1;
     }
     bool IsWrite() const {
       return mSourceBlockIndex == -1 &&
              mData.get() != nullptr;
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -374,31 +374,31 @@ MediaCacheStream::MediaCacheStream(Chann
     mChannelEnded(false),
     mChannelOffset(0),
     mStreamLength(-1),
     mStreamOffset(0),
     mPlaybackBytesPerSecond(10000),
     mPinCount(0),
     mCurrentMode(MODE_PLAYBACK),
     mMetadataInPartialBlockBuffer(false),
-    mPartialBlockBuffer(new int64_t[BLOCK_SIZE/sizeof(int64_t)])
+    mPartialBlockBuffer(MakeUnique<int64_t[]>(BLOCK_SIZE/sizeof(int64_t)))
 {
 }
 
 size_t MediaCacheStream::SizeOfExcludingThis(
                                 MallocSizeOf aMallocSizeOf) const
 {
   // Looks like these are not owned:
   // - mClient
   // - mPrincipal
   size_t size = mBlocks.ShallowSizeOfExcludingThis(aMallocSizeOf);
   size += mReadaheadBlocks.SizeOfExcludingThis(aMallocSizeOf);
   size += mMetadataBlocks.SizeOfExcludingThis(aMallocSizeOf);
   size += mPlayedBlocks.SizeOfExcludingThis(aMallocSizeOf);
-  size += mPartialBlockBuffer.SizeOfExcludingThis(aMallocSizeOf);
+  size += aMallocSizeOf(mPartialBlockBuffer.get());
 
   return size;
 }
 
 size_t MediaCacheStream::BlockList::SizeOfExcludingThis(
                                 MallocSizeOf aMallocSizeOf) const
 {
   return mEntries.ShallowSizeOfExcludingThis(aMallocSizeOf);
@@ -1837,17 +1837,17 @@ MediaCacheStream::FlushPartialBlockInter
                "mStreamOffset [%lld] mChannelOffset[%lld] mStreamLength [%lld] "
                "notifying: [%s]",
                this, blockOffset, mStreamOffset, mChannelOffset, mStreamLength,
                aNotifyAll ? "yes" : "no"));
 
     // Write back the partial block
     memset(reinterpret_cast<char*>(mPartialBlockBuffer.get()) + blockOffset, 0,
            BLOCK_SIZE - blockOffset);
-    gMediaCache->AllocateAndWriteBlock(this, mPartialBlockBuffer,
+    gMediaCache->AllocateAndWriteBlock(this, mPartialBlockBuffer.get(),
         mMetadataInPartialBlockBuffer ? MODE_METADATA : MODE_PLAYBACK);
   }
 
   // |mChannelOffset == 0| means download ends with no bytes received.
   // We should also wake up those readers who are waiting for data
   // that will never come.
   if ((blockOffset > 0 || mChannelOffset == 0) && aNotifyAll) {
     // Wake up readers who may be waiting for this data
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -7,16 +7,17 @@
 #ifndef MediaCache_h_
 #define MediaCache_h_
 
 #include "nsTArray.h"
 #include "nsCOMPtr.h"
 #include "nsHashKeys.h"
 #include "nsTHashtable.h"
 #include "Intervals.h"
+#include "mozilla/UniquePtr.h"
 
 class nsIPrincipal;
 
 namespace mozilla {
 // defined in MediaResource.h
 class ChannelMediaResource;
 typedef media::IntervalSet<int64_t> MediaByteRangeSet;
 class MediaResource;
@@ -505,14 +506,14 @@ private:
 
   // Data received for the block containing mChannelOffset. Data needs
   // to wait here so we can write back a complete block. The first
   // mChannelOffset%BLOCK_SIZE bytes have been filled in with good data,
   // the rest are garbage.
   // Use int64_t so that the data is well-aligned.
   // Heap allocate this buffer since the exact power-of-2 will cause allocation
   // slop when combined with the rest of the object members.
-  nsAutoArrayPtr<int64_t> mPartialBlockBuffer;
+  UniquePtr<int64_t[]> mPartialBlockBuffer;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -7,16 +7,17 @@
 #include "MediaData.h"
 #include "MediaInfo.h"
 #ifdef MOZ_OMX_DECODER
 #include "GrallocImages.h"
 #include "mozilla/layers/TextureClient.h"
 #endif
 #include "VideoUtils.h"
 #include "ImageContainer.h"
+#include "mozilla/UniquePtrExtensions.h"
 
 #ifdef MOZ_WIDGET_GONK
 #include <cutils/properties.h>
 #endif
 #include <stdint.h>
 
 namespace mozilla {
 
@@ -528,30 +529,29 @@ MediaRawData::Clone() const
 bool
 MediaRawData::EnsureCapacity(size_t aSize)
 {
   const size_t sizeNeeded = aSize + RAW_DATA_ALIGNMENT * 2;
 
   if (mData && mCapacity >= sizeNeeded) {
     return true;
   }
-  nsAutoArrayPtr<uint8_t> newBuffer;
-  newBuffer = new (fallible) uint8_t[sizeNeeded];
+  auto newBuffer = MakeUniqueFallible<uint8_t[]>(sizeNeeded);
   if (!newBuffer) {
     return false;
   }
 
   // Find alignment address.
   const uintptr_t alignmask = RAW_DATA_ALIGNMENT;
   uint8_t* newData = reinterpret_cast<uint8_t*>(
     (reinterpret_cast<uintptr_t>(newBuffer.get()) + alignmask) & ~alignmask);
   MOZ_ASSERT(uintptr_t(newData) % (RAW_DATA_ALIGNMENT+1) == 0);
   memcpy(newData, mData, mSize);
 
-  mBuffer = newBuffer.forget();
+  mBuffer = Move(newBuffer);
   mCapacity = sizeNeeded;
   mData = newData;
 
   return true;
 }
 
 MediaRawData::~MediaRawData()
 {
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -420,17 +420,17 @@ private:
   // Ensure that the backend buffer can hold aSize data. Will update mData.
   // Will enforce that the start of allocated data is always 32 bytes
   // aligned and that it has sufficient end padding to allow for 32 bytes block
   // read as required by some data decoders.
   // Returns false if memory couldn't be allocated.
   bool EnsureCapacity(size_t aSize);
   uint8_t* mData;
   size_t mSize;
-  nsAutoArrayPtr<uint8_t> mBuffer;
+  UniquePtr<uint8_t[]> mBuffer;
   uint32_t mCapacity;
   CryptoSample mCryptoInternal;
   MediaRawData(const MediaRawData&); // Not implemented
 };
 
   // MediaByteBuffer is a ref counted infallible TArray.
 class MediaByteBuffer : public nsTArray<uint8_t> {
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaByteBuffer);
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -572,17 +572,17 @@ private:
   // so recompute it. The monitor must be held.
   virtual void UpdatePlaybackRate();
 
   // The actual playback rate computation. The monitor must be held.
   void ComputePlaybackRate();
 
   // Returns true if we can play the entire media through without stopping
   // to buffer, given the current download and playback rates.
-  bool CanPlayThrough();
+  virtual bool CanPlayThrough();
 
   void SetAudioChannel(dom::AudioChannel aChannel) { mAudioChannel = aChannel; }
   dom::AudioChannel GetAudioChannel() { return mAudioChannel; }
 
   /******
    * The following methods must only be called on the main
    * thread.
    ******/
--- a/dom/media/RtspMediaResource.cpp
+++ b/dom/media/RtspMediaResource.cpp
@@ -7,16 +7,17 @@
 #include "mozilla/DebugOnly.h"
 
 #include "RtspMediaResource.h"
 
 #include "MediaDecoder.h"
 #include "mozilla/dom/HTMLMediaElement.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/UniquePtr.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIStreamingProtocolService.h"
 #include "nsServiceManagerUtils.h"
 #ifdef NECKO_PROTOCOL_rtsp
 #include "mozilla/net/RtspChannelChild.h"
 #endif
 using namespace mozilla::net;
 using namespace mozilla::media;
@@ -67,30 +68,30 @@ public:
   , mFrameType(0)
   , mIsStarted(false)
   , mDuringPlayoutDelay(false)
   , mPlayoutDelayMs(kPlayoutDelayMs)
   , mPlayoutDelayTimer(nullptr) {
     MOZ_COUNT_CTOR(RtspTrackBuffer);
     mTrackIdx = aTrackIdx;
     MOZ_ASSERT(mSlotSize < UINT32_MAX / BUFFER_SLOT_NUM);
-    mRingBuffer = new uint8_t[mTotalBufferSize];
+    mRingBuffer = MakeUnique<uint8_t[]>(mTotalBufferSize);
     Reset();
   };
   ~RtspTrackBuffer() {
     MOZ_COUNT_DTOR(RtspTrackBuffer);
     mRingBuffer = nullptr;
   };
 
   size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
     // including this
     size_t size = aMallocSizeOf(this);
 
     // excluding this
-    size += mRingBuffer.SizeOfExcludingThis(aMallocSizeOf);
+    size += aMallocSizeOf(mRingBuffer.get());
 
     return size;
   }
 
   void Start() {
     MonitorAutoLock monitor(mMonitor);
     mIsStarted = true;
     mFrameType = 0;
@@ -174,17 +175,17 @@ private:
   // The value in mBufferSlotData[index].mLength represents:
   // -1(BUFFER_SLOT_INVALID): The index of slot data is invalid, mConsumerIdx
   //                          should go forward.
   // 0(BUFFER_SLOT_EMPTY): The index slot is empty. mConsumerIdx should wait here.
   // positive value: The index slot contains valid data and the value is data size.
   BufferSlotData mBufferSlotData[BUFFER_SLOT_NUM];
 
   // The ring buffer pointer.
-  nsAutoArrayPtr<uint8_t> mRingBuffer;
+  UniquePtr<uint8_t[]> mRingBuffer;
   // Each slot's size.
   uint32_t mSlotSize;
   // Total mRingBuffer's total size.
   uint32_t mTotalBufferSize;
   // A flag that that indicate the incoming data should be dropped or stored.
   // When we are seeking, the incoming data should be dropped.
   // Bit definition in |nsIStreamingProtocolController.h|
   uint32_t mFrameType;
--- a/dom/media/VideoSegment.cpp
+++ b/dom/media/VideoSegment.cpp
@@ -63,17 +63,17 @@ VideoFrame::CreateBlackImage(const gfx::
   const uint8_t lumaBpp = 8;
   const uint8_t chromaBpp = 4;
 
   layers::PlanarYCbCrData data;
   data.mYChannel = frame.rwget();
   data.mYSize = gfx::IntSize(aSize.width, aSize.height);
   data.mYStride = (int32_t) (aSize.width * lumaBpp / 8.0);
   data.mCbCrStride = (int32_t) (aSize.width * chromaBpp / 8.0);
-  data.mCbChannel = frame.rwget() + aSize.height * data.mYStride;
+  data.mCbChannel = frame.get() + aSize.height * data.mYStride;
   data.mCrChannel = data.mCbChannel + aSize.height * data.mCbCrStride / 2;
   data.mCbCrSize = gfx::IntSize(aSize.width / 2, aSize.height / 2);
   data.mPicX = 0;
   data.mPicY = 0;
   data.mPicSize = gfx::IntSize(aSize.width, aSize.height);
   data.mStereoMode = StereoMode::MONO;
 
   // SetData copies data, so we can free data.
--- a/dom/media/android/AndroidMediaResourceServer.cpp
+++ b/dom/media/android/AndroidMediaResourceServer.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 #include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
 #include "mozilla/IntegerPrintfMacros.h"
+#include "mozilla/UniquePtr.h"
 #include "nsThreadUtils.h"
 #include "nsIServiceManager.h"
 #include "nsISocketTransport.h"
 #include "nsIOutputStream.h"
 #include "nsIInputStream.h"
 #include "nsIRandomGenerator.h"
 #include "nsReadLine.h"
 #include "nsNetCID.h"
@@ -258,63 +259,63 @@ ServeResourceEvent::Run() {
   rv = WriteAll(response_line, strlen(response_line));
   if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
 
   // Buffer used for reading from the input stream and writing to
   // the output stream. The buffer size should be big enough for the
   // HTTP response headers sent below. A static_assert ensures
   // this where the buffer is used.
   const int buffer_size = 32768;
-  nsAutoArrayPtr<char> b(new char[buffer_size]);
+  auto b = MakeUnique<char[]>(buffer_size);
 
   // If we know the length of the resource, send a Content-Length header.
   int64_t contentlength = resource->GetLength() - start;
   if (contentlength > 0) {
     static_assert (buffer_size > 1024,
                    "buffer_size must be large enough "
                    "to hold response headers");
-    snprintf(b, buffer_size, "Content-Length: %" PRId64 "\r\n", contentlength);
-    rv = WriteAll(b, strlen(b));
+    snprintf(b.get(), buffer_size, "Content-Length: %" PRId64 "\r\n", contentlength);
+    rv = WriteAll(b.get(), strlen(b.get()));
     if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
   }
 
   // If the request was a byte range request, respond with a Content-Range
   // header which details the extent of the data returned.
   if (start > 0) {
     static_assert (buffer_size > 1024,
                    "buffer_size must be large enough "
                    "to hold response headers");
-    snprintf(b, buffer_size, "Content-Range: "
+    snprintf(b.get(), buffer_size, "Content-Range: "
              "bytes %" PRId64 "-%" PRId64 "/%" PRId64 "\r\n",
              start, resource->GetLength() - 1, resource->GetLength());
-    rv = WriteAll(b, strlen(b));
+    rv = WriteAll(b.get(), strlen(b.get()));
     if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
   }
 
   rv = WriteAll(response_end, strlen(response_end));
   if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
 
   rv = mOutput->Flush();
   if (NS_FAILED(rv)) { Shutdown(); return NS_OK; }
 
   // Read data from media resource
   uint32_t bytesRead = 0; // Number of bytes read/written to streams
-  rv = resource->ReadAt(start, b, buffer_size, &bytesRead);
+  rv = resource->ReadAt(start, b.get(), buffer_size, &bytesRead);
   while (NS_SUCCEEDED(rv) && bytesRead != 0) {
     // Keep track of what we think the starting position for the next read
     // is. This is used in subsequent ReadAt calls to ensure we are reading
     // from the correct offset in the case where another thread is reading
     // from th same MediaResource.
     start += bytesRead;
 
     // Write data obtained from media resource to output stream
-    rv = WriteAll(b, bytesRead);
+    rv = WriteAll(b.get(), bytesRead);
     if (NS_FAILED (rv)) break;
 
-    rv = resource->ReadAt(start, b, 32768, &bytesRead);
+    rv = resource->ReadAt(start, b.get(), 32768, &bytesRead);
   }
 
   Shutdown();
   return NS_OK;
 }
 
 void
 ServeResourceEvent::Shutdown()
--- a/dom/media/eme/MediaKeySession.cpp
+++ b/dom/media/eme/MediaKeySession.cpp
@@ -204,21 +204,22 @@ MediaKeySession::GenerateRequest(const n
   nsAutoCString base64InitData(ToBase64(data));
   PromiseId pid = mKeys->StorePromise(promise);
   mKeys->GetCDMProxy()->CreateSession(Token(),
                                       mSessionType,
                                       pid,
                                       aInitDataType, data);
 
   EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() sent, "
-          "promiseId=%d initData(base64)='%s'",
+          "promiseId=%d initData(base64)='%s' initDataType='%s'",
           this,
           NS_ConvertUTF16toUTF8(mSessionId).get(),
           pid,
-          base64InitData.get());
+          base64InitData.get(),
+          NS_ConvertUTF16toUTF8(aInitDataType).get());
 
   return promise.forget();
 }
 
 already_AddRefed<Promise>
 MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv)
 {
   RefPtr<DetailedPromise> promise(MakePromise(aRv,
--- a/dom/media/eme/MediaKeySystemAccess.cpp
+++ b/dom/media/eme/MediaKeySystemAccess.cpp
@@ -436,19 +436,22 @@ GetSupportedConfig(mozIGeckoMediaPluginS
                    const MediaKeySystemConfiguration& aCandidate,
                    MediaKeySystemConfiguration& aOutConfig)
 {
   MediaKeySystemConfiguration config;
   config.mLabel = aCandidate.mLabel;
   if (aCandidate.mInitDataTypes.WasPassed()) {
     nsTArray<nsString> initDataTypes;
     for (const nsString& candidate : aCandidate.mInitDataTypes.Value()) {
+      // All supported keySystems can handle "cenc" initDataType.
+      // ClearKey also supports "keyids" and "webm" initDataTypes.
       if (candidate.EqualsLiteral("cenc")) {
         initDataTypes.AppendElement(candidate);
-      } else if (candidate.EqualsLiteral("keyids") &&
+      } else if ((candidate.EqualsLiteral("keyids") ||
+                  candidate.EqualsLiteral("webm)")) &&
                  aKeySystem.EqualsLiteral("org.w3.clearkey")) {
         initDataTypes.AppendElement(candidate);
       }
     }
     if (initDataTypes.IsEmpty()) {
       return false;
     }
     config.mInitDataTypes.Construct();
--- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
+++ b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.cpp
@@ -122,17 +122,17 @@ TrackRunBox::fillSampleTable()
   nsTArray<RefPtr<EncodedFrame>> frames;
   FragmentBuffer* frag = mControl->GetFragment(mTrackType);
 
   rv = frag->GetFirstFragment(frames);
   if (NS_FAILED(rv)) {
     return 0;
   }
   uint32_t len = frames.Length();
-  sample_info_table = new tbl[len];
+  sample_info_table = MakeUnique<tbl[]>(len);
   // Create sample table according to 14496-12 8.8.8.2.
   for (uint32_t i = 0; i < len; i++) {
     // Sample size.
     sample_info_table[i].sample_size = 0;
     if (flags.to_ulong() & flags_sample_size_present) {
       sample_info_table[i].sample_size = frames.ElementAt(i)->GetFrameData().Length();
       mAllSampleSize += sample_info_table[i].sample_size;
       table_size += sizeof(uint32_t);
--- a/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h
+++ b/dom/media/encoder/fmp4_muxer/ISOMediaBoxes.h
@@ -6,16 +6,17 @@
 #ifndef ISOMediaBoxes_h_
 #define ISOMediaBoxes_h_
 
 #include <bitset>
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "MuxerOperation.h"
+#include "mozilla/UniquePtr.h"
 
 #define WRITE_FULLBOX(_compositor, _size)       \
   BoxSizeChecker checker(_compositor, _size);   \
   FullBox::Write();
 
 #define FOURCC(a, b, c, d) ( ((a) << 24) | ((b) << 16) | ((c) << 8) | (d) )
 
 namespace mozilla {
@@ -257,17 +258,17 @@ public:
     uint32_t sample_flags;
     uint32_t sample_composition_time_offset;
   } tbl;
 
   uint32_t sample_count;
   // the following are optional fields
   uint32_t data_offset; // data offset exists when audio/video are present in file.
   uint32_t first_sample_flags;
-  nsAutoArrayPtr<tbl> sample_info_table;
+  UniquePtr<tbl[]> sample_info_table;
 
   // MuxerOperation methods
   nsresult Generate(uint32_t* aBoxSize) override;
   nsresult Write() override;
 
   // TrackRunBox methods
   uint32_t GetAllSampleSize() { return mAllSampleSize; }
   nsresult SetDataOffset(uint32_t aOffset);
@@ -399,17 +400,17 @@ public:
 class ChunkOffsetBox : public FullBox {
 public:
   // ISO BMFF members
   typedef struct {
     uint32_t chunk_offset;
   } tbl;
 
   uint32_t entry_count;
-  nsAutoArrayPtr<tbl> sample_tbl;
+  UniquePtr<tbl[]> sample_tbl;
 
   // MuxerOperation methods
   nsresult Generate(uint32_t* aBoxSize) override;
   nsresult Write() override;
 
   // ChunkOffsetBox methods
   ChunkOffsetBox(uint32_t aType, ISOControl* aControl);
   ~ChunkOffsetBox();
@@ -425,17 +426,17 @@ public:
   // ISO BMFF members
   typedef struct {
     uint32_t first_chunk;
     uint32_t sample_per_chunk;
     uint32_t sample_description_index;
   } tbl;
 
   uint32_t entry_count;
-  nsAutoArrayPtr<tbl> sample_tbl;
+  UniquePtr<tbl[]> sample_tbl;
 
   // MuxerOperation methods
   nsresult Generate(uint32_t* aBoxSize) override;
   nsresult Write() override;
 
   // SampleToChunkBox methods
   SampleToChunkBox(uint32_t aType, ISOControl* aControl);
   ~SampleToChunkBox();
@@ -450,17 +451,17 @@ class TimeToSampleBox : public FullBox {
 public:
   // ISO BMFF members
   typedef struct {
     uint32_t sample_count;
     uint32_t sample_delta;
   } tbl;
 
   uint32_t entry_count;
-  nsAutoArrayPtr<tbl> sample_tbl;
+  UniquePtr<tbl[]> sample_tbl;
 
   // MuxerOperation methods
   nsresult Generate(uint32_t* aBoxSize) override;
   nsresult Write() override;
 
   // TimeToSampleBox methods
   TimeToSampleBox(uint32_t aType, ISOControl* aControl);
   ~TimeToSampleBox();
--- a/dom/media/fmp4/MP4Stream.cpp
+++ b/dom/media/fmp4/MP4Stream.cpp
@@ -39,17 +39,17 @@ MP4Stream::BlockingReadIntoCache(int64_t
     if (NS_FAILED(rv)) {
       return false;
     }
   }
 
   MOZ_ASSERT(block.mCount >= bytesRead);
   block.mCount = bytesRead;
 
-  mCache.AppendElement(block);
+  mCache.AppendElement(Move(block));
   return true;
 }
 
 // We surreptitiously reimplement the supposedly-blocking ReadAt as a non-
 // blocking CachedReadAt, and record when it fails. This allows MP4Reader
 // to retry the read as an actual blocking read without holding the lock.
 bool
 MP4Stream::ReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
--- a/dom/media/fmp4/MP4Stream.h
+++ b/dom/media/fmp4/MP4Stream.h
@@ -8,16 +8,17 @@
 #define MP4_STREAM_H_
 
 #include "mp4_demuxer/Stream.h"
 
 #include "MediaResource.h"
 
 #include "mozilla/Maybe.h"
 #include "mozilla/Monitor.h"
+#include "mozilla/UniquePtrExtensions.h"
 
 namespace mozilla {
 
 class Monitor;
 
 class MP4Stream : public mp4_demuxer::Stream {
 public:
   explicit MP4Stream(MediaResource* aResource);
@@ -69,29 +70,38 @@ private:
   uint32_t mPinCount;
 
   struct CacheBlock {
     CacheBlock(int64_t aOffset, size_t aCount)
       : mOffset(aOffset), mCount(aCount), mBuffer(nullptr) {}
     int64_t mOffset;
     size_t mCount;
 
+    CacheBlock(CacheBlock&& aOther)
+      : mOffset(aOther.mOffset)
+      , mCount(aOther.mCount)
+      , mBuffer(Move(aOther.mBuffer))
+    {}
+
     bool Init()
     {
-      mBuffer = new (fallible) char[mCount];
+      mBuffer = MakeUniqueFallible<char[]>(mCount);
       return !!mBuffer;
     }
 
     char* Buffer()
     {
       MOZ_ASSERT(mBuffer.get());
       return mBuffer.get();
     }
 
   private:
-    nsAutoArrayPtr<char> mBuffer;
+    CacheBlock(const CacheBlock&) = delete;
+    CacheBlock& operator=(const CacheBlock&) = delete;
+
+    UniquePtr<char[]> mBuffer;
   };
   nsTArray<CacheBlock> mCache;
 };
 
 } // namespace mozilla
 
 #endif
--- a/dom/media/gmp/GMPLoader.cpp
+++ b/dom/media/gmp/GMPLoader.cpp
@@ -2,16 +2,17 @@
  * vim: sw=4 ts=4 et :
  * 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 "GMPLoader.h"
 #include <stdio.h>
 #include "mozilla/Attributes.h"
+#include "mozilla/UniquePtr.h"
 #include "gmp-entrypoints.h"
 #include "prlink.h"
 #include "prenv.h"
 #include "nsAutoPtr.h"
 
 #include <string>
 
 #ifdef XP_WIN
@@ -242,22 +243,22 @@ GMPLoaderImpl::Load(const char* aUTF8Lib
   // Load the GMP.
   PRLibSpec libSpec;
 #ifdef XP_WIN
   int pathLen = MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, nullptr, 0);
   if (pathLen == 0) {
     return false;
   }
 
-  nsAutoArrayPtr<wchar_t> widePath(new wchar_t[pathLen]);
-  if (MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, widePath, pathLen) == 0) {
+  auto widePath = MakeUnique<wchar_t[]>(pathLen);
+  if (MultiByteToWideChar(CP_UTF8, 0, aUTF8LibPath, -1, widePath.get(), pathLen) == 0) {
     return false;
   }
 
-  libSpec.value.pathname_u = widePath;
+  libSpec.value.pathname_u = widePath.get();
   libSpec.type = PR_LibSpec_PathnameU;
 #else
   libSpec.value.pathname = aUTF8LibPath;
   libSpec.type = PR_LibSpec_Pathname;
 #endif
   mLib = PR_LoadLibraryWithFlags(libSpec, 0);
   if (!mLib) {
     return false;
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -11,16 +11,17 @@
 #include "MediaDecoderStateMachine.h"
 #include "MediaSource.h"
 #include "MediaSourceResource.h"
 #include "MediaSourceUtils.h"
 #include "VideoUtils.h"
 #include "MediaFormatReader.h"
 #include "MediaSourceDemuxer.h"
 #include "SourceBufferList.h"
+#include <algorithm>
 
 extern mozilla::LogModule* GetMediaSourceLog();
 
 #define MSE_DEBUG(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Debug, ("MediaSourceDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 #define MSE_DEBUGV(arg, ...) MOZ_LOG(GetMediaSourceLog(), mozilla::LogLevel::Verbose, ("MediaSourceDecoder(%p)::%s: " arg, this, __func__, ##__VA_ARGS__))
 
 using namespace mozilla::media;
 
@@ -245,12 +246,53 @@ MediaSourceDecoder::GetMozDebugReaderDat
 
 double
 MediaSourceDecoder::GetDuration()
 {
   MOZ_ASSERT(NS_IsMainThread());
   return ExplicitDuration();
 }
 
+MediaDecoderOwner::NextFrameStatus
+MediaSourceDecoder::NextFrameBufferedStatus()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  // Next frame hasn't been decoded yet.
+  // Use the buffered range to consider if we have the next frame available.
+  TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
+  TimeInterval interval(currentPosition,
+                        currentPosition + media::TimeUnit::FromMicroseconds(DEFAULT_NEXT_FRAME_AVAILABLE_BUFFERED),
+                        MediaSourceDemuxer::EOS_FUZZ);
+  return GetBuffered().Contains(interval)
+    ? MediaDecoderOwner::NEXT_FRAME_AVAILABLE
+    : MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
+}
+
+bool
+MediaSourceDecoder::CanPlayThrough()
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  if (IsNaN(mMediaSource->Duration())) {
+    // Don't have any data yet.
+    return false;
+  }
+  TimeUnit duration = TimeUnit::FromSeconds(mMediaSource->Duration());
+  TimeUnit currentPosition = TimeUnit::FromMicroseconds(CurrentPosition());
+  if (duration.IsInfinite()) {
+    // We can't make an informed decision and just assume that it's a live stream
+    return true;
+  } else if (duration <= currentPosition) {
+    return true;
+  }
+  // If we have data up to the mediasource's duration or 30s ahead, we can
+  // assume that we can play without interruption.
+  TimeUnit timeAhead =
+    std::min(duration, currentPosition + TimeUnit::FromSeconds(30));
+  TimeInterval interval(currentPosition,
+                        timeAhead,
+                        MediaSourceDemuxer::EOS_FUZZ);
+  return GetBuffered().Contains(interval);
+}
+
 #undef MSE_DEBUG
 #undef MSE_DEBUGV
 
 } // namespace mozilla
--- a/dom/media/mediasource/MediaSourceDecoder.h
+++ b/dom/media/mediasource/MediaSourceDecoder.h
@@ -72,16 +72,19 @@ public:
   }
 
   // Returns a string describing the state of the MediaSource internal
   // buffered data. Used for debugging purposes.
   void GetMozDebugReaderData(nsAString& aString);
 
   void AddSizeOfResources(ResourceSizes* aSizes) override;
 
+  MediaDecoderOwner::NextFrameStatus NextFrameBufferedStatus() override;
+  bool CanPlayThrough() override;
+
 private:
   void DoSetMediaSourceDuration(double aDuration);
 
   // The owning MediaSource holds a strong reference to this decoder, and
   // calls Attach/DetachMediaSource on this decoder to set and clear
   // mMediaSource.
   dom::MediaSource* mMediaSource;
   RefPtr<MediaSourceDemuxer> mDemuxer;
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -14,29 +14,29 @@
 #include "nsPrintfCString.h"
 
 namespace mozilla {
 
 typedef TrackInfo::TrackType TrackType;
 using media::TimeUnit;
 using media::TimeIntervals;
 
-// Gap allowed between frames. Due to inaccuracies in determining buffer end
-// frames (Bug 1065207). This value is based on the end of frame
-// default value used in Blink, kDefaultBufferDurationInMs.
-#define EOS_FUZZ_US 125000
-
 MediaSourceDemuxer::MediaSourceDemuxer()
   : mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
                              /* aSupportsTailDispatch = */ true))
   , mMonitor("MediaSourceDemuxer")
 {
   MOZ_ASSERT(NS_IsMainThread());
 }
 
+// Due to inaccuracies in determining buffer end
+// frames (Bug 1065207). This value is based on the end of frame
+// default value used in Blink, kDefaultBufferDurationInMs.
+const TimeUnit MediaSourceDemuxer::EOS_FUZZ = media::TimeUnit::FromMicroseconds(125000);
+
 RefPtr<MediaSourceDemuxer::InitPromise>
 MediaSourceDemuxer::Init()
 {
   return InvokeAsync(GetTaskQueue(), this, __func__,
                      &MediaSourceDemuxer::AttemptInit);
 }
 
 RefPtr<MediaSourceDemuxer::InitPromise>
@@ -370,39 +370,40 @@ MediaSourceTrackDemuxer::BreakCycles()
     } );
   mParent->GetTaskQueue()->Dispatch(task.forget());
 }
 
 RefPtr<MediaSourceTrackDemuxer::SeekPromise>
 MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
 {
   TimeIntervals buffered = mManager->Buffered(mType);
-  buffered.SetFuzz(TimeUnit::FromMicroseconds(EOS_FUZZ_US));
+  buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ);
 
   if (!buffered.Contains(aTime)) {
     // We don't have the data to seek to.
     return SeekPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
                                         __func__);
   }
   TimeUnit seekTime =
-    mManager->Seek(mType, aTime, TimeUnit::FromMicroseconds(EOS_FUZZ_US));
+    mManager->Seek(mType, aTime, MediaSourceDemuxer::EOS_FUZZ);
   {
     MonitorAutoLock mon(mMonitor);
     mNextRandomAccessPoint = mManager->GetNextRandomAccessPoint(mType);
   }
   return SeekPromise::CreateAndResolve(seekTime, __func__);
 }
 
 RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
 MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
 {
   bool error;
-  RefPtr<MediaRawData> sample = mManager->GetSample(mType,
-                                                      TimeUnit::FromMicroseconds(EOS_FUZZ_US),
-                                                      error);
+  RefPtr<MediaRawData> sample =
+    mManager->GetSample(mType,
+                        MediaSourceDemuxer::EOS_FUZZ,
+                        error);
   if (!sample) {
     if (error) {
       return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
     }
     return SamplesPromise::CreateAndReject(
       mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
                             DemuxerFailureReason::WAITING_FOR_DATA, __func__);
   }
--- a/dom/media/mediasource/MediaSourceDemuxer.h
+++ b/dom/media/mediasource/MediaSourceDemuxer.h
@@ -50,16 +50,19 @@ public:
   TaskQueue* GetTaskQueue() { return mTaskQueue; }
 
   // Returns a string describing the state of the MediaSource internal
   // buffered data. Used for debugging purposes.
   void GetMozDebugReaderData(nsAString& aString);
 
   void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes);
 
+  // Gap allowed between frames.
+  static const media::TimeUnit EOS_FUZZ;
+
 private:
   ~MediaSourceDemuxer();
   friend class MediaSourceTrackDemuxer;
   // Scan source buffers and update information.
   bool ScanSourceBuffersForContent();
   RefPtr<InitPromise> AttemptInit();
   TrackBuffersManager* GetManager(TrackInfo::TrackType aType);
   TrackInfo* GetTrackInfo(TrackInfo::TrackType);
--- a/dom/media/mediasource/test/mochitest.ini
+++ b/dom/media/mediasource/test/mochitest.ini
@@ -58,16 +58,18 @@ skip-if = ((os == "win" && os_version ==
 [test_MediaSource.html]
 [test_MediaSource_memory_reporting.html]
 [test_MediaSource_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
 [test_MediaSource_disabled.html]
 [test_MultipleInitSegments.html]
 [test_MultipleInitSegments_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
+[test_PlayEvents.html]
+skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
 [test_SeekableAfterEndOfStream.html]
 [test_SeekableAfterEndOfStream_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
 [test_SeekableAfterEndOfStreamSplit.html]
 [test_SeekableAfterEndOfStreamSplit_mp4.html]
 skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
 [test_SeekableBeforeEndOfStream.html]
 [test_SeekableBeforeEndOfStream_mp4.html]
new file mode 100644
--- /dev/null
+++ b/dom/media/mediasource/test/test_PlayEvents.html
@@ -0,0 +1,156 @@
+<!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();
+
+// This test checks that readyState is properly set and the appropriate events are being fired accordingly:
+// 1. Load 1.6s of data and ensure that canplay event is fired.
+// 2. Load data to have a complete buffered range from 0 to duration and ensure that canplaythrough is fired.
+// 3. Seek to an area with no buffered data, and ensure that readyState goes back to HAVE_METADATA
+// 4. Load 1.6s of data at the seek position and ensure that canplay is fired and that readyState is now HAVE_FUTURE_DATA
+// 5. Start playing video and check that once it reaches a position with no data, readyState goes back to HAVE_CURRENT_DATA and waiting event is fired.
+// 6. Add 1.6s of data once video element fired waiting, that canplay is fired once readyState is HAVE_FUTURE_DATA.
+// 7. Finally load data to the end and ensure that canplaythrough is fired and that readyState is now HAVE_ENOUGH_DATA
+
+runWithMSE(function(ms, el) {
+  el.controls = true;
+  once(ms, 'sourceopen').then(function() {
+    ok(true, "Receive a sourceopen event");
+    var videosb = ms.addSourceBuffer("video/mp4");
+    el.addEventListener("error", function(e) {
+      ok(false, "should not fire '" + e + "' event");
+    });
+    is(el.readyState, el.HAVE_NOTHING, "readyState is HAVE_NOTHING");
+    fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
+    .then(once.bind(null, el, 'loadedmetadata'))
+    .then(function() {
+       ok(true, "got loadedmetadata event");
+       var promises = [];
+       promises.push(once(el, 'loadeddata'));
+       promises.push(once(el, 'canplay'));
+       // Load [0, 1.601666). We must ensure that we load over 25 frames as the
+       // windows H264 decoder will not produce a sample until then
+       // (bug 1191138).
+       promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s'));
+       return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got canplay event");
+      // set element duration to 3.203333s. We do so in order to guarantee that
+      // the end of the buffered range will be equal to duration, causing
+      // canplaythrough to be fired later.
+      ms.duration = 3.203333;
+      return once(el, 'durationchange');
+    })
+    .then(function() {
+      ok(true, "got durationchange event");
+      var promises = [];
+      promises.push(once(el, 'canplaythrough'));
+      // Load [0.801666, 3.203333]
+      promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(3, 5), '.m4s'));
+      return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got canplaythrough event");
+     // set element duration to 9.203333s, this value is set to coincide with
+     // data added later (we now have an empty range from 6s to 9.203333s).
+     ms.duration = 9.203333;
+     return once(el, 'durationchange');
+    })
+    .then(function() {
+      ok(true, "got durationchange event");
+      // An arbitrary value, so we are guaranteed to be in a range with no data.
+      el.currentTime = 6;
+      videosb.timestampOffset = 6;
+      ok(el.seeking, "seeking started");
+      return once(el, 'seeking');
+    })
+    .then(function() {
+      ok(true, "got seeking event");
+      is(el.readyState, el.HAVE_METADATA, "readyState is HAVE_METADATA");
+      var promises = [];
+      promises.push(once(el, 'seeked'));
+      promises.push(once(el, 'canplay'));
+      // Load [6+0, 6+1.601666)
+      promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s'));
+      return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got seeked and canplay event");
+      is(el.currentTime, 6, "seeked to 6s");
+      is(el.readyState, el.HAVE_FUTURE_DATA, "readyState is HAVE_FUTURE_DATA");
+      var promises = [];
+      promises.push(once(el, 'canplaythrough'));
+      // Load [6+1.60166, 6+3.203333]
+      promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(3, 5), '.m4s'));
+      return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got canplaythrough event");
+      // set element duration to 19.805s, this value is set to coincide with
+      // data added later (we now have an empty range from 15 to 19.805).
+      ms.duration = 19.805;
+      return once(el, 'durationchange');
+    })
+    .then(function() {
+      ok(true, "got durationchange event");
+      el.currentTime = 15;
+      videosb.timestampOffset = 15;
+      ok(el.seeking, "seeking started");
+      return once(el, 'seeking');
+    })
+    .then(function() {
+      ok(true, "got seeking event");
+      var promises = [];
+      promises.push(once(el, 'seeked'));
+      // Load [15+0, 15+1.601666)
+      promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s'));
+      return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got seeked event");
+      // Load [15+1.60166, 15+3.203333]
+      return fetchAndLoad(videosb, 'bipbop/bipbop_video', range(3, 5), '.m4s');
+    })
+    .then(function() {
+      ok(true, "data loaded");
+      // Playback we play for a little while then stall.
+      var promises = [];
+      promises.push(once(el, 'playing'));
+      promises.push(once(el, 'waiting'));
+      el.play();
+      return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got playing and waiting event");
+      // Playback has stalled, readyState is back to HAVE_CURRENT_DATA.
+      is(el.readyState, el.HAVE_CURRENT_DATA, "readyState is HAVE_CURRENT_DATA");
+      var promises = [];
+      promises.push(once(el, 'playing'));
+      promises.push(once(el, 'canplay'));
+      promises.push(once(el, 'canplaythrough'));
+      // Load [15+3.203333, 15+4.805)
+      // Our final buffered range will now be [0, 3.203333)[6, 9.203333)[15, 19.805)
+      promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(5, 7), '.m4s'));
+      return Promise.all(promises);
+    })
+    .then(function() {
+      ok(true, "got playing, canplay and canplaythrough event");
+      SimpleTest.finish();
+    })
+  });
+});
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/platforms/agnostic/BlankDecoderModule.cpp
+++ b/dom/media/platforms/agnostic/BlankDecoderModule.cpp
@@ -6,16 +6,17 @@
 
 #include "ImageContainer.h"
 #include "MediaDecoderReader.h"
 #include "MediaInfo.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/mozalloc.h" // for operator new, and new (fallible)
 #include "mozilla/RefPtr.h"
 #include "mozilla/TaskQueue.h"
+#include "mozilla/UniquePtr.h"
 #include "nsRect.h"
 #include "PlatformDecoderModule.h"
 #include "TimeUnits.h"
 #include "VideoUtils.h"
 
 namespace mozilla {
 
 // Decoder that uses a passed in object's Create function to create blank
@@ -113,38 +114,38 @@ public:
 
   already_AddRefed<MediaData>
   Create(const media::TimeUnit& aDTS, const media::TimeUnit& aDuration, int64_t aOffsetInStream)
   {
     // Create a fake YUV buffer in a 420 format. That is, an 8bpp Y plane,
     // with a U and V plane that are half the size of the Y plane, i.e 8 bit,
     // 2x2 subsampled. Have the data pointers of each frame point to the
     // first plane, they'll always be zero'd memory anyway.
-    nsAutoArrayPtr<uint8_t> frame(new uint8_t[mFrameWidth * mFrameHeight]);
-    memset(frame, 0, mFrameWidth * mFrameHeight);
+    auto frame = MakeUnique<uint8_t[]>(mFrameWidth * mFrameHeight);
+    memset(frame.get(), 0, mFrameWidth * mFrameHeight);
     VideoData::YCbCrBuffer buffer;
 
     // Y plane.
-    buffer.mPlanes[0].mData = frame;
+    buffer.mPlanes[0].mData = frame.get();
     buffer.mPlanes[0].mStride = mFrameWidth;
     buffer.mPlanes[0].mHeight = mFrameHeight;
     buffer.mPlanes[0].mWidth = mFrameWidth;
     buffer.mPlanes[0].mOffset = 0;
     buffer.mPlanes[0].mSkip = 0;
 
     // Cb plane.
-    buffer.mPlanes[1].mData = frame;
+    buffer.mPlanes[1].mData = frame.get();
     buffer.mPlanes[1].mStride = mFrameWidth / 2;
     buffer.mPlanes[1].mHeight = mFrameHeight / 2;
     buffer.mPlanes[1].mWidth = mFrameWidth / 2;
     buffer.mPlanes[1].mOffset = 0;
     buffer.mPlanes[1].mSkip = 0;
 
     // Cr plane.
-    buffer.mPlanes[2].mData = frame;
+    buffer.mPlanes[2].mData = frame.get();
     buffer.mPlanes[2].mStride = mFrameWidth / 2;
     buffer.mPlanes[2].mHeight = mFrameHeight / 2;
     buffer.mPlanes[2].mWidth = mFrameWidth / 2;
     buffer.mPlanes[2].mOffset = 0;
     buffer.mPlanes[2].mSkip = 0;
 
     return VideoData::Create(mInfo,
                              mImageContainer,
--- a/dom/media/platforms/apple/AppleATDecoder.cpp
+++ b/dom/media/platforms/apple/AppleATDecoder.cpp
@@ -5,16 +5,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "AppleUtils.h"
 #include "MP4Decoder.h"
 #include "mp4_demuxer/Adts.h"
 #include "MediaInfo.h"
 #include "AppleATDecoder.h"
 #include "mozilla/Logging.h"
+#include "mozilla/UniquePtr.h"
 
 extern mozilla::LogModule* GetPDMLog();
 #define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
 #define FourCC2Str(n) ((char[5]){(char)(n >> 24), (char)(n >> 16), (char)(n >> 8), (char)(n), 0})
 
 namespace mozilla {
 
 AppleATDecoder::AppleATDecoder(const AudioInfo& aConfig,
@@ -206,26 +207,25 @@ AppleATDecoder::DecodeSample(MediaRawDat
   nsTArray<AudioDataValue> outputData;
   UInt32 channels = mOutputFormat.mChannelsPerFrame;
   // Pick a multiple of the frame size close to a power of two
   // for efficient allocation.
   const uint32_t MAX_AUDIO_FRAMES = 128;
   const uint32_t maxDecodedSamples = MAX_AUDIO_FRAMES * channels;
 
   // Descriptions for _decompressed_ audio packets. ignored.
-  nsAutoArrayPtr<AudioStreamPacketDescription>
-    packets(new AudioStreamPacketDescription[MAX_AUDIO_FRAMES]);
+  auto packets = MakeUnique<AudioStreamPacketDescription[]>(MAX_AUDIO_FRAMES);
 
   // This API insists on having packets spoon-fed to it from a callback.
   // This structure exists only to pass our state.
   PassthroughUserData userData =
     { channels, (UInt32)aSample->Size(), aSample->Data() };
 
   // Decompressed audio buffer
-  nsAutoArrayPtr<AudioDataValue> decoded(new AudioDataValue[maxDecodedSamples]);
+  auto decoded = MakeUnique<AudioDataValue[]>(maxDecodedSamples);
 
   do {
     AudioBufferList decBuffer;
     decBuffer.mNumberBuffers = 1;
     decBuffer.mBuffers[0].mNumberChannels = channels;
     decBuffer.mBuffers[0].mDataByteSize =
       maxDecodedSamples * sizeof(AudioDataValue);
     decBuffer.mBuffers[0].mData = decoded.get();
@@ -323,37 +323,36 @@ AppleATDecoder::GetInputAudioDescription
   rv = AudioFormatGetPropertyInfo(kAudioFormatProperty_FormatList,
                                   sizeof(formatInfo),
                                   &formatInfo,
                                   &formatListSize);
   if (rv || (formatListSize % sizeof(AudioFormatListItem))) {
     return NS_OK;
   }
   size_t listCount = formatListSize / sizeof(AudioFormatListItem);
-  nsAutoArrayPtr<AudioFormatListItem> formatList(
-    new AudioFormatListItem[listCount]);
+  auto formatList = MakeUnique<AudioFormatListItem[]>(listCount);
 
   rv = AudioFormatGetProperty(kAudioFormatProperty_FormatList,
                               sizeof(formatInfo),
                               &formatInfo,
                               &formatListSize,
-                              formatList);
+                              formatList.get());
   if (rv) {
     return NS_OK;
   }
   LOG("found %u available audio stream(s)",
       formatListSize / sizeof(AudioFormatListItem));
   // Get the index number of the first playable format.
   // This index number will be for the highest quality layer the platform
   // is capable of playing.
   UInt32 itemIndex;
   UInt32 indexSize = sizeof(itemIndex);
   rv = AudioFormatGetProperty(kAudioFormatProperty_FirstPlayableFormatFromList,
                               formatListSize,
-                              formatList,
+                              formatList.get(),
                               &indexSize,
                               &itemIndex);
   if (rv) {
     return NS_OK;
   }
 
   aDesc = formatList[itemIndex].mASBD;
 
@@ -433,19 +432,19 @@ static void
                                                  &size,
                                                  &writeable);
     if (rv) {
       LOG("Couldn't get property info for '%s' (%s)",
           FourCC2Str(aProperty), FourCC2Str(rv));
       decoder->mFileStreamError = true;
       return;
     }
-    nsAutoArrayPtr<uint8_t> data(new uint8_t[size]);
+    auto data = MakeUnique<uint8_t[]>(size);
     rv = AudioFileStreamGetProperty(aStream, aProperty,
-                                    &size, data);
+                                    &size, data.get());
     if (rv) {
       LOG("Couldn't get property '%s' (%s)",
           FourCC2Str(aProperty), FourCC2Str(rv));
       decoder->mFileStreamError = true;
       return;
     }
     decoder->mMagicCookie.AppendElements(data.get(), size);
   }
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
@@ -664,18 +664,17 @@ uint8_t *
 GonkVideoDecoderManager::GetColorConverterBuffer(int32_t aWidth, int32_t aHeight)
 {
   // Allocate a temporary YUV420Planer buffer.
   size_t yuv420p_y_size = aWidth * aHeight;
   size_t yuv420p_u_size = ((aWidth + 1) / 2) * ((aHeight + 1) / 2);
   size_t yuv420p_v_size = yuv420p_u_size;
   size_t yuv420p_size = yuv420p_y_size + yuv420p_u_size + yuv420p_v_size;
   if (mColorConverterBufferSize != yuv420p_size) {
-    mColorConverterBuffer = nullptr; // release the previous buffer first
-    mColorConverterBuffer = new uint8_t[yuv420p_size];
+    mColorConverterBuffer = MakeUnique<uint8_t[]>(yuv420p_size);
     mColorConverterBufferSize = yuv420p_size;
   }
   return mColorConverterBuffer.get();
 }
 
 /* static */
 void
 GonkVideoDecoderManager::RecycleCallback(TextureClient* aClient, void* aClosure)
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.h
@@ -10,16 +10,17 @@
 #include "nsRect.h"
 #include "GonkMediaDataDecoder.h"
 #include "mozilla/RefPtr.h"
 #include "I420ColorConverterHelper.h"
 #include "MediaCodecProxy.h"
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 #include "mozilla/layers/FenceUtils.h"
+#include "mozilla/UniquePtr.h"
 #include <ui/Fence.h>
 
 using namespace android;
 
 namespace android {
 class MediaBuffer;
 struct MOZ_EXPORT AString;
 class GonkNativeWindow;
@@ -107,17 +108,17 @@ private:
   RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator;
 
   MediaInfo mInfo;
   MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
   FrameInfo mFrameInfo;
 
   // color converter
   android::I420ColorConverterHelper mColorConverter;
-  nsAutoArrayPtr<uint8_t> mColorConverterBuffer;
+  UniquePtr<uint8_t[]> mColorConverterBuffer;
   size_t mColorConverterBufferSize;
 
   android::sp<android::GonkNativeWindow> mNativeWindow;
 #if ANDROID_VERSION >= 21
   android::sp<android::IGraphicBufferProducer> mGraphicBufferProducer;
 #endif
 
   enum {
--- a/dom/media/raw/RawReader.cpp
+++ b/dom/media/raw/RawReader.cpp
@@ -5,16 +5,17 @@
 
 #include "MediaDecoderStateMachine.h"
 #include "AbstractMediaDecoder.h"
 #include "RawReader.h"
 #include "RawDecoder.h"
 #include "VideoUtils.h"
 #include "nsISeekableStream.h"
 #include "gfx2DGlue.h"
+#include "mozilla/UniquePtr.h"
 
 using namespace mozilla;
 using namespace mozilla::media;
 
 RawReader::RawReader(AbstractMediaDecoder* aDecoder)
   : MediaDecoderReader(aDecoder),
     mCurrentFrame(0), mFrameSize(0), mResource(aDecoder->GetResource())
 {
@@ -133,52 +134,52 @@ bool RawReader::DecodeVideoFrame(bool &a
   AbstractMediaDecoder::AutoNotifyDecoded a(mDecoder);
 
   if (!mFrameSize)
     return false; // Metadata read failed.  We should refuse to play.
 
   int64_t currentFrameTime = USECS_PER_S * mCurrentFrame / mFrameRate;
   uint32_t length = mFrameSize - sizeof(RawPacketHeader);
 
-  nsAutoArrayPtr<uint8_t> buffer(new uint8_t[length]);
+  auto buffer = MakeUnique<uint8_t[]>(length);
 
   // We're always decoding one frame when called
   while(true) {
     RawPacketHeader header;
 
     // Read in a packet header and validate
     if (!(ReadFromResource(reinterpret_cast<uint8_t*>(&header),
                            sizeof(header))) ||
         !(header.packetID == 0xFF && header.codecID == RAW_ID /* "YUV" */)) {
       return false;
     }
 
-    if (!ReadFromResource(buffer, length)) {
+    if (!ReadFromResource(buffer.get(), length)) {
       return false;
     }
 
     a.mParsed++;
 
     if (currentFrameTime >= aTimeThreshold)
       break;
 
     mCurrentFrame++;
     currentFrameTime += static_cast<double>(USECS_PER_S) / mFrameRate;
   }
 
   VideoData::YCbCrBuffer b;
-  b.mPlanes[0].mData = buffer;
+  b.mPlanes[0].mData = buffer.get();
   b.mPlanes[0].mStride = mMetadata.frameWidth * mMetadata.lumaChannelBpp / 8.0;
   b.mPlanes[0].mHeight = mMetadata.frameHeight;
   b.mPlanes[0].mWidth = mMetadata.frameWidth;
   b.mPlanes[0].mOffset = b.mPlanes[0].mSkip = 0;
 
   uint32_t cbcrStride = mMetadata.frameWidth * mMetadata.chromaChannelBpp / 8.0;
 
-  b.mPlanes[1].mData = buffer + mMetadata.frameHeight * b.mPlanes[0].mStride;
+  b.mPlanes[1].mData = buffer.get() + mMetadata.frameHeight * b.mPlanes[0].mStride;
   b.mPlanes[1].mStride = cbcrStride;
   b.mPlanes[1].mHeight = mMetadata.frameHeight / 2;
   b.mPlanes[1].mWidth = mMetadata.frameWidth / 2;
   b.mPlanes[1].mOffset = b.mPlanes[1].mSkip = 0;
 
   b.mPlanes[2].mData = b.mPlanes[1].mData + mMetadata.frameHeight * cbcrStride / 2;
   b.mPlanes[2].mStride = cbcrStride;
   b.mPlanes[2].mHeight = mMetadata.frameHeight / 2;
--- a/dom/media/systemservices/CamerasChild.cpp
+++ b/dom/media/systemservices/CamerasChild.cpp
@@ -123,27 +123,26 @@ public:
     // We will be returning the resulting pointer (synchronously) to our caller.
     mCamerasChild =
       static_cast<mozilla::camera::CamerasChild*>(existingBackgroundChild->SendPCamerasConstructor());
 
     return NS_OK;
   }
 
   CamerasChild* GetCamerasChild() {
-    MOZ_ASSERT(mCamerasChild);
     return mCamerasChild;
   }
 
 private:
   CamerasChild* mCamerasChild;
 };
 
 static CamerasChild*
-Cameras() {
-  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+GetCamerasChild() {
+  CamerasSingleton::Mutex().AssertCurrentThreadOwns();
   if (!CamerasSingleton::Child()) {
     MOZ_ASSERT(!NS_IsMainThread(), "Should not be on the main Thread");
     MOZ_ASSERT(!CamerasSingleton::Thread());
     LOG(("No sCameras, setting up IPC Thread"));
     nsresult rv = NS_NewNamedThread("Cameras IPC",
                                     getter_AddRefs(CamerasSingleton::Thread()));
     if (NS_FAILED(rv)) {
       LOG(("Error launching IPC Thread"));
@@ -157,17 +156,19 @@ Cameras() {
     // We block until the following happens in the Cameras IPC thread:
     // 1) Creation of PBackground finishes
     // 2) Creation of PCameras finishes by sending a message to the parent
     RefPtr<InitializeIPCThread> runnable = new InitializeIPCThread();
     RefPtr<SyncRunnable> sr = new SyncRunnable(runnable);
     sr->DispatchToThread(CamerasSingleton::Thread());
     CamerasSingleton::Child() = runnable->GetCamerasChild();
   }
-  MOZ_ASSERT(CamerasSingleton::Child());
+  if (!CamerasSingleton::Child()) {
+    LOG(("Failed to set up CamerasChild, are we in shutdown?"));
+  }
   return CamerasSingleton::Child();
 }
 
 bool
 CamerasChild::RecvReplyFailure(void)
 {
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
@@ -185,17 +186,23 @@ CamerasChild::RecvReplySuccess(void)
   mReceivedReply = true;
   mReplySuccess = true;
   monitor.Notify();
   return true;
 }
 
 int NumberOfCapabilities(CaptureEngine aCapEngine, const char* deviceUniqueIdUTF8)
 {
-  return Cameras()->NumberOfCapabilities(aCapEngine, deviceUniqueIdUTF8);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->NumberOfCapabilities(aCapEngine, deviceUniqueIdUTF8);
+  } else {
+    return 0;
+  }
 }
 
 bool
 CamerasChild::RecvReplyNumberOfCapabilities(const int& numdev)
 {
   LOG((__PRETTY_FUNCTION__));
   MonitorAutoLock monitor(mReplyMonitor);
   mReceivedReply = true;
@@ -204,20 +211,18 @@ CamerasChild::RecvReplyNumberOfCapabilit
   monitor.Notify();
   return true;
 }
 
 bool
 CamerasChild::DispatchToParent(nsIRunnable* aRunnable,
                                MonitorAutoLock& aMonitor)
 {
-  {
-    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
-    CamerasSingleton::Thread()->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
-  }
+  CamerasSingleton::Mutex().AssertCurrentThreadOwns();
+  CamerasSingleton::Thread()->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
   // We can't see if the send worked, so we need to be able to bail
   // out on shutdown (when it failed and we won't get a reply).
   if (!mIPCIsAlive) {
     return false;
   }
   // Guard against spurious wakeups.
   mReceivedReply = false;
   // Wait for a reply
@@ -255,17 +260,23 @@ CamerasChild::NumberOfCapabilities(Captu
     return 0;
   }
   LOG(("Capture capability count: %d", mReplyInteger));
   return mReplyInteger;
 }
 
 int NumberOfCaptureDevices(CaptureEngine aCapEngine)
 {
-  return Cameras()->NumberOfCaptureDevices(aCapEngine);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->NumberOfCaptureDevices(aCapEngine);
+  } else {
+    return 0;
+  }
 }
 
 int
 CamerasChild::NumberOfCaptureDevices(CaptureEngine aCapEngine)
 {
   MutexAutoLock requestLock(mRequestMutex);
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
@@ -295,20 +306,26 @@ CamerasChild::RecvReplyNumberOfCaptureDe
   monitor.Notify();
   return true;
 }
 
 int GetCaptureCapability(CaptureEngine aCapEngine, const char* unique_idUTF8,
                          const unsigned int capability_number,
                          webrtc::CaptureCapability& capability)
 {
-  return Cameras()->GetCaptureCapability(aCapEngine,
-                                         unique_idUTF8,
-                                         capability_number,
-                                         capability);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->GetCaptureCapability(aCapEngine,
+                                       unique_idUTF8,
+                                       capability_number,
+                                       capability);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::GetCaptureCapability(CaptureEngine aCapEngine,
                                    const char* unique_idUTF8,
                                    const unsigned int capability_number,
                                    webrtc::CaptureCapability& capability)
 {
@@ -350,22 +367,28 @@ CamerasChild::RecvReplyGetCaptureCapabil
 
 
 int GetCaptureDevice(CaptureEngine aCapEngine,
                      unsigned int list_number, char* device_nameUTF8,
                      const unsigned int device_nameUTF8Length,
                      char* unique_idUTF8,
                      const unsigned int unique_idUTF8Length)
 {
-  return Cameras()->GetCaptureDevice(aCapEngine,
-                                     list_number,
-                                     device_nameUTF8,
-                                     device_nameUTF8Length,
-                                     unique_idUTF8,
-                                     unique_idUTF8Length);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->GetCaptureDevice(aCapEngine,
+                                   list_number,
+                                   device_nameUTF8,
+                                   device_nameUTF8Length,
+                                   unique_idUTF8,
+                                   unique_idUTF8Length);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::GetCaptureDevice(CaptureEngine aCapEngine,
                                unsigned int list_number, char* device_nameUTF8,
                                const unsigned int device_nameUTF8Length,
                                char* unique_idUTF8,
                                const unsigned int unique_idUTF8Length)
@@ -404,20 +427,26 @@ CamerasChild::RecvReplyGetCaptureDevice(
   return true;
 }
 
 int AllocateCaptureDevice(CaptureEngine aCapEngine,
                           const char* unique_idUTF8,
                           const unsigned int unique_idUTF8Length,
                           int& capture_id)
 {
-  return Cameras()->AllocateCaptureDevice(aCapEngine,
-                                          unique_idUTF8,
-                                          unique_idUTF8Length,
-                                          capture_id);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->AllocateCaptureDevice(aCapEngine,
+                                        unique_idUTF8,
+                                        unique_idUTF8Length,
+                                        capture_id);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::AllocateCaptureDevice(CaptureEngine aCapEngine,
                                     const char* unique_idUTF8,
                                     const unsigned int unique_idUTF8Length,
                                     int& capture_id)
 {
@@ -451,17 +480,23 @@ CamerasChild::RecvReplyAllocateCaptureDe
   mReplySuccess = true;
   mReplyInteger = numdev;
   monitor.Notify();
   return true;
 }
 
 int ReleaseCaptureDevice(CaptureEngine aCapEngine, const int capture_id)
 {
-  return Cameras()->ReleaseCaptureDevice(aCapEngine, capture_id);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->ReleaseCaptureDevice(aCapEngine, capture_id);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::ReleaseCaptureDevice(CaptureEngine aCapEngine,
                                    const int capture_id)
 {
   MutexAutoLock requestLock(mRequestMutex);
   LOG((__PRETTY_FUNCTION__));
@@ -504,20 +539,26 @@ CamerasChild::RemoveCallback(const Captu
   }
 }
 
 int StartCapture(CaptureEngine aCapEngine,
                  const int capture_id,
                  webrtc::CaptureCapability& webrtcCaps,
                  webrtc::ExternalRenderer* cb)
 {
-  return Cameras()->StartCapture(aCapEngine,
-                                 capture_id,
-                                 webrtcCaps,
-                                 cb);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->StartCapture(aCapEngine,
+                               capture_id,
+                               webrtcCaps,
+                               cb);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::StartCapture(CaptureEngine aCapEngine,
                            const int capture_id,
                            webrtc::CaptureCapability& webrtcCaps,
                            webrtc::ExternalRenderer* cb)
 {
@@ -542,17 +583,23 @@ CamerasChild::StartCapture(CaptureEngine
   if (!DispatchToParent(runnable, monitor)) {
     return -1;
   }
   return 0;
 }
 
 int StopCapture(CaptureEngine aCapEngine, const int capture_id)
 {
-  return Cameras()->StopCapture(aCapEngine, capture_id);
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  CamerasChild* child = GetCamerasChild();
+  if (child) {
+    return child->StopCapture(aCapEngine, capture_id);
+  } else {
+    return -1;
+  }
 }
 
 int
 CamerasChild::StopCapture(CaptureEngine aCapEngine, const int capture_id)
 {
   MutexAutoLock requestLock(mRequestMutex);
   LOG((__PRETTY_FUNCTION__));
   nsCOMPtr<nsIRunnable> runnable =
@@ -568,26 +615,24 @@ CamerasChild::StopCapture(CaptureEngine 
   }
   RemoveCallback(aCapEngine, capture_id);
   return 0;
 }
 
 void
 Shutdown(void)
 {
-  {
-    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
-    if (!CamerasSingleton::Child()) {
-      // We don't want to cause everything to get fired up if we're
-      // really already shut down.
-      LOG(("Shutdown when already shut down"));
-      return;
-    }
+  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+  if (!CamerasSingleton::Child()) {
+    // We don't want to cause everything to get fired up if we're
+    // really already shut down.
+    LOG(("Shutdown when already shut down"));
+    return;
   }
-  Cameras()->Shutdown();
+  GetCamerasChild()->Shutdown();
 }
 
 class ShutdownRunnable : public nsRunnable {
 public:
   ShutdownRunnable(RefPtr<nsRunnable> aReplyEvent,
                    nsIThread* aReplyThread)
     : mReplyEvent(aReplyEvent), mReplyThread(aReplyThread) {};
 
@@ -610,17 +655,16 @@ void
 CamerasChild::Shutdown()
 {
   {
     MonitorAutoLock monitor(mReplyMonitor);
     mIPCIsAlive = false;
     monitor.NotifyAll();
   }
 
-  OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
   if (CamerasSingleton::Thread()) {
     LOG(("Dispatching actor deletion"));
     // Delete the parent actor.
     RefPtr<nsRunnable> deleteRunnable =
       // CamerasChild (this) will remain alive and is only deleted by the
       // IPC layer when SendAllDone returns.
       media::NewRunnableFrom([this]() -> nsresult {
         Unused << this->SendAllDone();
@@ -703,17 +747,20 @@ CamerasChild::CamerasChild()
 
   MOZ_COUNT_CTOR(CamerasChild);
 }
 
 CamerasChild::~CamerasChild()
 {
   LOG(("~CamerasChild: %p", this));
 
-  Shutdown();
+  {
+    OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
+    Shutdown();
+  }
 
   MOZ_COUNT_DTOR(CamerasChild);
 }
 
 webrtc::ExternalRenderer* CamerasChild::Callback(CaptureEngine aCapEngine,
                                                  int capture_id)
 {
   for (unsigned int i = 0; i < mCallbacks.Length(); i++) {
--- a/dom/media/systemservices/CamerasParent.cpp
+++ b/dom/media/systemservices/CamerasParent.cpp
@@ -181,16 +181,17 @@ CamerasParent::DispatchToVideoCaptureThr
   mVideoCaptureThread->message_loop()->PostTask(FROM_HERE,
                                                 new RunnableTask(event));
   return NS_OK;
 }
 
 void
 CamerasParent::StopVideoCapture()
 {
+  LOG((__PRETTY_FUNCTION__));
   // We are called from the main thread (xpcom-shutdown) or
   // from PBackground (when the Actor shuts down).
   // Shut down the WebRTC stack (on the capture thread)
   RefPtr<CamerasParent> self(this);
   RefPtr<nsRunnable> webrtc_runnable =
     media::NewRunnableFrom([self]() -> nsresult {
       MonitorAutoLock lock(self->mThreadMonitor);
       self->CloseEngines();
@@ -402,16 +403,17 @@ CamerasParent::SetupEngine(CaptureEngine
   }
 
   return true;
 }
 
 void
 CamerasParent::CloseEngines()
 {
+  LOG((__PRETTY_FUNCTION__));
   if (!mWebRTCAlive) {
     return;
   }
   MOZ_ASSERT(mVideoCaptureThread->thread_id() == PlatformThread::CurrentId());
 
   // Stop the callers
   while (mCallbacks.Length()) {
     auto capEngine = mCallbacks[0]->mCapEngine;
@@ -695,20 +697,22 @@ CamerasParent::RecvReleaseCaptureDevice(
 
   RefPtr<CamerasParent> self(this);
   RefPtr<nsRunnable> webrtc_runnable =
     media::NewRunnableFrom([self, aCapEngine, numdev]() -> nsresult {
       int error = self->ReleaseCaptureDevice(aCapEngine, numdev);
       RefPtr<nsIRunnable> ipc_runnable =
         media::NewRunnableFrom([self, error, numdev]() -> nsresult {
           if (self->IsShuttingDown()) {
+            LOG(("In Shutdown, not Releasing"));
             return NS_ERROR_FAILURE;
           }
           if (error) {
             Unused << self->SendReplyFailure();
+            LOG(("Failed to free device nr %d", numdev));
             return NS_ERROR_FAILURE;
           } else {
             Unused << self->SendReplySuccess();
             LOG(("Freed device nr %d", numdev));
             return NS_OK;
           }
         });
       self->mPBackgroundThread->Dispatch(ipc_runnable, NS_DISPATCH_NORMAL);
--- a/dom/media/test/mochitest.ini
+++ b/dom/media/test/mochitest.ini
@@ -614,17 +614,17 @@ skip-if = (toolkit == 'android' && proce
 [test_defaultMuted.html]
 [test_delay_load.html]
 skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
 [test_dormant_playback.html]
 skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'gonk')
 [test_eme_session_callable_value.html]
 [test_eme_canvas_blocked.html]
 skip-if = toolkit == 'android' # bug 1149374
-[test_eme_key_ids_initdata.html]
+[test_eme_initDataTypes.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_non_mse_fails.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_request_notifications.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_persistent_sessions.html]
 skip-if = toolkit == 'android' # bug 1149374
 [test_eme_playback.html]
rename from dom/media/test/test_eme_key_ids_initdata.html
rename to dom/media/test/test_eme_initDataTypes.html
--- a/dom/media/test/test_eme_key_ids_initdata.html
+++ b/dom/media/test/test_eme_initDataTypes.html
@@ -9,92 +9,125 @@
 </head>
 <body>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 var tests = [
   {
     name: "One keyId",
+    initDataType: 'keyids',
     initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}',
     expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"],"type":"temporary"}',
     sessionType: 'temporary',
     expectPass: true,
   },
   {
     name: "Two keyIds",
+    initDataType: 'keyids',
     initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A"]}',
     expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"temporary"}',
     sessionType: 'temporary',
     expectPass: true,
   },
   {
     name: "Two keyIds, temporary session",
+    initDataType: 'keyids',
     initData: '{"type":"temporary", "kids":["LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A"]}',
     expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"temporary"}',
     sessionType: 'temporary',
     expectPass: true,
   },
   {
     name: "Two keyIds, persistent session, type before kids",
+    initDataType: 'keyids',
     initData: '{"type":"persistent", "kids":["LwVHf8JLtPrv2GUXFW2v_A", "0DdtU9od-Bh5L3xbv0Xf_A"]}',
     expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A","0DdtU9od-Bh5L3xbv0Xf_A"],"type":"persistent"}',
     sessionType: 'persistent',
     expectPass: true,
   },
   {
     name: "Invalid keyId",
+    initDataType: 'keyids',
     initData: '{"kids":["0"]}',
     sessionType: 'temporary',
     expectPass: false,
   },
   {
     name: "Empty keyId",
+    initDataType: 'keyids',
     initData: '{"kids":[""]}',
     sessionType: 'temporary',
     expectPass: false,
   },
   {
     name: "SessionType in license doesn't match MediaKeySession's sessionType",
+    initDataType: 'keyids',
     initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"]}',
     sessionType: 'persistent',
     expectPass: false,
   },
   {
     name: "One valid and one invalid kid",
+    initDataType: 'keyids',
     initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A", "invalid"]}',
     expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"],"type":"temporary"}',
     sessionType: 'temporary',
     expectPass: true,
   },
   {
     name: "Invalid initData",
+    initDataType: 'keyids',
     initData: 'invalid initData',
     sessionType: 'temporary',
     expectPass: false,
   },
+  {
+    name: "'webm' initDataType",
+    initDataType: 'webm',
+    initData: 'YAYeAX5Hfod+V9ANHtANHg==',
+    expectedRequest: '{"kids":["YAYeAX5Hfod-V9ANHtANHg"],"type":"temporary"}',
+    sessionType: 'temporary',
+    expectPass: true,
+  },
+  {
+    name: "'webm' initDataType with non 16 byte keyid",
+    initDataType: 'webm',
+    initData: 'YAYeAX5Hfod',
+    sessionType: 'temporary',
+    expectPass: false,
+  },
 ];
 
+function PrepareInitData(initDataType, initData)
+{
+  if (initDataType == "keyids") {
+    return new TextEncoder().encode(initData);
+  } else if (initDataType == "webm") {
+    return StringToArrayBuffer(atob(initData));
+  }
+}
+
 function Test(test) {
   return new Promise(function(resolve, reject) {
     navigator.requestMediaKeySystemAccess('org.w3.clearkey', [{initDataTypes: ['keyids']}]).then(
       (access) => access.createMediaKeys()
       ).then(
         (mediaKeys) => {
           var session = mediaKeys.createSession(test.sessionType);
-          var initData = new TextEncoder().encode(test.initData);
           session.addEventListener("message", function(event) {
             is(event.messageType, "license-request", "'" + test.name + "' MediaKeyMessage type should be license-request.");
             var text = new TextDecoder().decode(event.message);
             is(text, test.expectedRequest, "'" + test.name + "' got expected response.");
             is(text == test.expectedRequest, test.expectPass,
                "'" + test.name + "' expected to " + (test.expectPass ? "pass" : "fail"));
             resolve();
           });
-          return session.generateRequest('keyids', initData);
+          var initData = PrepareInitData(test.initDataType, test.initData);
+          return session.generateRequest(test.initDataType, initData);
         }
       ).catch((x) => {
         ok(!test.expectPass, "'" + test.name + "' expected to fail.");
         resolve();
       });
   });
 }
 
--- a/dom/media/wave/WaveReader.cpp
+++ b/dom/media/wave/WaveReader.cpp
@@ -9,16 +9,17 @@
 #include "MediaDecoderStateMachine.h"
 #include "VideoUtils.h"
 #include "nsISeekableStream.h"
 
 #include <stdint.h>
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Endian.h"
+#include "mozilla/UniquePtr.h"
 #include <algorithm>
 
 using namespace mozilla::media;
 
 namespace mozilla {
 
 // Un-comment to enable logging of seek bisections.
 //#define SEEK_LOGGING
@@ -186,19 +187,19 @@ bool WaveReader::DecodeAudioData()
   static_assert(uint64_t(BLOCK_SIZE) < UINT_MAX /
                 sizeof(AudioDataValue) / MAX_CHANNELS,
                 "bufferSize calculation could overflow.");
   const size_t bufferSize = static_cast<size_t>(frames * mChannels);
   auto sampleBuffer = MakeUnique<AudioDataValue[]>(bufferSize);
 
   static_assert(uint64_t(BLOCK_SIZE) < UINT_MAX / sizeof(char),
                 "BLOCK_SIZE too large for enumerator.");
-  nsAutoArrayPtr<char> dataBuffer(new char[static_cast<size_t>(readSize)]);
+  auto dataBuffer = MakeUnique<char[]>(static_cast<size_t>(readSize));
 
-  if (!ReadAll(dataBuffer, readSize)) {
+  if (!ReadAll(dataBuffer.get(), readSize)) {
     return false;
   }
 
   // convert data to samples
   const char* d = dataBuffer.get();
   AudioDataValue* s = sampleBuffer.get();
   for (int i = 0; i < frames; ++i) {
     for (unsigned int j = 0; j < mChannels; ++j) {
@@ -401,17 +402,17 @@ WaveReader::LoadFormatChunk(uint32_t aCh
       NS_WARNING("Invalid extended format chunk size");
       return false;
     }
     extra += extra % 2;
 
     if (extra > 0) {
       static_assert(UINT16_MAX + (UINT16_MAX % 2) < UINT_MAX / sizeof(char),
                     "chunkExtension array too large for iterator.");
-      nsAutoArrayPtr<char> chunkExtension(new char[extra]);
+      auto chunkExtension = MakeUnique<char[]>(extra);
       if (!ReadAll(chunkExtension.get(), extra)) {
         return false;
       }
     }
   }
 
   // RIFF chunks are always word (two byte) aligned.
   MOZ_ASSERT(mResource.Tell() % 2 == 0,
@@ -523,17 +524,17 @@ WaveReader::LoadListChunk(uint32_t aChun
   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;
   }
 
-  nsAutoArrayPtr<char> chunk(new char[aChunkSize]);
+  auto chunk = MakeUnique<char[]>(aChunkSize);
   if (!ReadAll(chunk.get(), aChunkSize)) {
     return false;
   }
 
   static const uint32_t INFO_LIST_MAGIC = 0x494e464f;
   const char* p = chunk.get();
   if (ReadUint32BE(&p) != INFO_LIST_MAGIC) {
     return false;
@@ -647,17 +648,17 @@ WaveReader::LoadAllChunks(nsAutoPtr<dom:
 
     if (!forward.isValid() || forward.value() < 0) {
       return false;
     }
 
     static const int64_t MAX_CHUNK_SIZE = 1 << 16;
     static_assert(uint64_t(MAX_CHUNK_SIZE) < UINT_MAX / sizeof(char),
                   "MAX_CHUNK_SIZE too large for enumerator.");
-    nsAutoArrayPtr<char> chunk(new char[MAX_CHUNK_SIZE]);
+    auto chunk = MakeUnique<char[]>(MAX_CHUNK_SIZE);
     while (forward.value() > 0) {
       int64_t size = std::min(forward.value(), MAX_CHUNK_SIZE);
       if (!ReadAll(chunk.get(), size)) {
         return false;
       }
       forward -= size;
     }
   }
--- a/dom/media/webaudio/BiquadFilterNode.cpp
+++ b/dom/media/webaudio/BiquadFilterNode.cpp
@@ -7,16 +7,17 @@
 #include "BiquadFilterNode.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "AudioDestinationNode.h"
 #include "PlayingRefChangeHandler.h"
 #include "WebAudioUtils.h"
 #include "blink/Biquad.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/UniquePtr.h"
 #include "AudioParamTimeline.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(BiquadFilterNode, AudioNode,
                                    mFrequency, mDetune, mQ, mGain)
 
@@ -311,17 +312,17 @@ BiquadFilterNode::GetFrequencyResponse(c
   aPhaseResponse.ComputeLengthAndData();
 
   uint32_t length = std::min(std::min(aFrequencyHz.Length(), aMagResponse.Length()),
                              aPhaseResponse.Length());
   if (!length) {
     return;
   }
 
-  nsAutoArrayPtr<float> frequencies(new float[length]);
+  auto frequencies = MakeUnique<float[]>(length);
   float* frequencyHz = aFrequencyHz.Data();
   const double nyquist = Context()->SampleRate() * 0.5;
 
   // Normalize the frequencies
   for (uint32_t i = 0; i < length; ++i) {
     if (frequencyHz[i] >= 0 && frequencyHz[i] <= nyquist) {
         frequencies[i] = static_cast<float>(frequencyHz[i] / nyquist);
     } else {
@@ -333,13 +334,13 @@ BiquadFilterNode::GetFrequencyResponse(c
 
   double freq = mFrequency->GetValueAtTime(currentTime);
   double q = mQ->GetValueAtTime(currentTime);
   double gain = mGain->GetValueAtTime(currentTime);
   double detune = mDetune->GetValueAtTime(currentTime);
 
   WebCore::Biquad biquad;
   SetParamsOnBiquad(biquad, Context()->SampleRate(), mType, freq, q, gain, detune);
-  biquad.getFrequencyResponse(int(length), frequencies, aMagResponse.Data(), aPhaseResponse.Data());
+  biquad.getFrequencyResponse(int(length), frequencies.get(), aMagResponse.Data(), aPhaseResponse.Data());
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/media/webaudio/blink/DynamicsCompressor.cpp
+++ b/dom/media/webaudio/blink/DynamicsCompressor.cpp
@@ -64,18 +64,18 @@ size_t DynamicsCompressor::sizeOfIncludi
 
     amount += m_postFilterPacks.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (size_t i = 0; i < m_postFilterPacks.Length(); i++) {
         if (m_postFilterPacks[i]) {
             amount += m_postFilterPacks[i]->sizeOfIncludingThis(aMallocSizeOf);
         }
     }
 
-    amount += m_sourceChannels.SizeOfExcludingThis(aMallocSizeOf);
-    amount += m_destinationChannels.SizeOfExcludingThis(aMallocSizeOf);
+    amount += aMallocSizeOf(m_sourceChannels.get());
+    amount += aMallocSizeOf(m_destinationChannels.get());
     amount += m_compressor.sizeOfExcludingThis(aMallocSizeOf);
     return amount;
 }
 
 void DynamicsCompressor::setParameterValue(unsigned parameterID, float value)
 {
     MOZ_ASSERT(parameterID < ParamLast);
     if (parameterID < ParamLast)
@@ -303,16 +303,16 @@ void DynamicsCompressor::setNumberOfChan
 
     m_preFilterPacks.Clear();
     m_postFilterPacks.Clear();
     for (unsigned i = 0; i < numberOfChannels; ++i) {
         m_preFilterPacks.AppendElement(new ZeroPoleFilterPack4());
         m_postFilterPacks.AppendElement(new ZeroPoleFilterPack4());
     }
 
-    m_sourceChannels = new const float* [numberOfChannels];
-    m_destinationChannels = new float* [numberOfChannels];
+    m_sourceChannels = mozilla::MakeUnique<const float* []>(numberOfChannels);
+    m_destinationChannels = mozilla::MakeUnique<float* []>(numberOfChannels);
 
     m_compressor.setNumberOfChannels(numberOfChannels);
     m_numberOfChannels = numberOfChannels;
 }
 
 } // namespace WebCore
--- a/dom/media/webaudio/blink/DynamicsCompressor.h
+++ b/dom/media/webaudio/blink/DynamicsCompressor.h
@@ -30,16 +30,17 @@
 #define DynamicsCompressor_h
 
 #include "DynamicsCompressorKernel.h"
 #include "ZeroPole.h"
 
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/UniquePtr.h"
 
 namespace mozilla {
 class AudioBlock;
 } // namespace mozilla
 
 namespace WebCore {
 
 using mozilla::AudioBlock;
@@ -110,18 +111,18 @@ protected:
             return aMallocSizeOf(this);
         }
     } ZeroPoleFilterPack4;
 
     // Per-channel emphasis filters.
     nsTArray<nsAutoPtr<ZeroPoleFilterPack4> > m_preFilterPacks;
     nsTArray<nsAutoPtr<ZeroPoleFilterPack4> > m_postFilterPacks;
 
-    nsAutoArrayPtr<const float*> m_sourceChannels;
-    nsAutoArrayPtr<float*> m_destinationChannels;
+    mozilla::UniquePtr<const float*[]> m_sourceChannels;
+    mozilla::UniquePtr<float*[]> m_destinationChannels;
 
     void setEmphasisStageParameters(unsigned stageIndex, float gain, float normalizedFrequency /* 0 -> 1 */);
     void setEmphasisParameters(float gain, float anchorFreq, float filterStageRatio);
 
     // The core compressor.
     DynamicsCompressorKernel m_compressor;
 };
 
--- a/dom/media/webaudio/blink/DynamicsCompressorKernel.cpp
+++ b/dom/media/webaudio/blink/DynamicsCompressorKernel.cpp
@@ -35,16 +35,17 @@
 #include "mozilla/Constants.h"
 #include "WebAudioUtils.h"
 
 using namespace std;
 
 using namespace mozilla::dom; // for WebAudioUtils
 using mozilla::IsInfinite;
 using mozilla::IsNaN;
+using mozilla::MakeUnique;
 
 namespace WebCore {
 
 
 // Metering hits peaks instantly, but releases this fast (in seconds).
 const float meteringReleaseTimeConstant = 0.325f;
 
 const float uninitializedValue = -1;
@@ -73,43 +74,43 @@ DynamicsCompressorKernel::DynamicsCompre
         static_cast<float>(WebAudioUtils::DiscreteTimeConstantForSampleRate(meteringReleaseTimeConstant, sampleRate));
 }
 
 size_t DynamicsCompressorKernel::sizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
     size_t amount = 0;
     amount += m_preDelayBuffers.ShallowSizeOfExcludingThis(aMallocSizeOf);
     for (size_t i = 0; i < m_preDelayBuffers.Length(); i++) {
-        amount += m_preDelayBuffers[i].SizeOfExcludingThis(aMallocSizeOf);
+        amount += aMallocSizeOf(m_preDelayBuffers[i].get());
     }
 
     return amount;
 }
 
 void DynamicsCompressorKernel::setNumberOfChannels(unsigned numberOfChannels)
 {
     if (m_preDelayBuffers.Length() == numberOfChannels)
         return;
 
     m_preDelayBuffers.Clear();
     for (unsigned i = 0; i < numberOfChannels; ++i)
-        m_preDelayBuffers.AppendElement(new float[MaxPreDelayFrames]);
+      m_preDelayBuffers.AppendElement(MakeUnique<float[]>(MaxPreDelayFrames));
 }
 
 void DynamicsCompressorKernel::setPreDelayTime(float preDelayTime)
 {
     // Re-configure look-ahead section pre-delay if delay time has changed.
     unsigned preDelayFrames = preDelayTime * sampleRate();
     if (preDelayFrames > MaxPreDelayFrames - 1)
         preDelayFrames = MaxPreDelayFrames - 1;
 
     if (m_lastPreDelayFrames != preDelayFrames) {
         m_lastPreDelayFrames = preDelayFrames;
         for (unsigned i = 0; i < m_preDelayBuffers.Length(); ++i)
-            memset(m_preDelayBuffers[i], 0, sizeof(float) * MaxPreDelayFrames);
+	  memset(m_preDelayBuffers[i].get(), 0, sizeof(float) * MaxPreDelayFrames);
 
         m_preDelayReadIndex = 0;
         m_preDelayWriteIndex = preDelayFrames;
     }
 }
 
 // Exponential curve for the knee.
 // It is 1st derivative matched at m_linearThreshold and asymptotically approaches the value m_linearThreshold + 1 / k.
@@ -382,17 +383,17 @@ void DynamicsCompressorKernel::process(f
             float compressorGain = m_compressorGain;
 
             int loopFrames = nDivisionFrames;
             while (loopFrames--) {
                 float compressorInput = 0;
 
                 // Predelay signal, computing compression amount from un-delayed version.
                 for (unsigned i = 0; i < numberOfChannels; ++i) {
-                    float* delayBuffer = m_preDelayBuffers[i];
+                    float* delayBuffer = m_preDelayBuffers[i].get();
                     float undelayedSource = sourceChannels[i][frameIndex];
                     delayBuffer[preDelayWriteIndex] = undelayedSource;
 
                     float absUndelayedSource = undelayedSource > 0 ? undelayedSource : -undelayedSource;
                     if (compressorInput < absUndelayedSource)
                         compressorInput = absUndelayedSource;
                 }
 
@@ -448,17 +449,17 @@ void DynamicsCompressorKernel::process(f
                 float dbRealGain = 20 * log10(postWarpCompressorGain);
                 if (dbRealGain < m_meteringGain)
                     m_meteringGain = dbRealGain;
                 else
                     m_meteringGain += (dbRealGain - m_meteringGain) * m_meteringReleaseK;
 
                 // Apply final gain.
                 for (unsigned i = 0; i < numberOfChannels; ++i) {
-                    float* delayBuffer = m_preDelayBuffers[i];
+                    float* delayBuffer = m_preDelayBuffers[i].get();
                     destinationChannels[i][frameIndex] = delayBuffer[preDelayReadIndex] * totalGain;
                 }
 
                 frameIndex++;
                 preDelayReadIndex = (preDelayReadIndex + 1) & MaxPreDelayFramesMask;
                 preDelayWriteIndex = (preDelayWriteIndex + 1) & MaxPreDelayFramesMask;
             }
 
@@ -474,17 +475,17 @@ void DynamicsCompressorKernel::process(f
 void DynamicsCompressorKernel::reset()
 {
     m_detectorAverage = 0;
     m_compressorGain = 1;
     m_meteringGain = 1;
 
     // Predelay section.
     for (unsigned i = 0; i < m_preDelayBuffers.Length(); ++i)
-        memset(m_preDelayBuffers[i], 0, sizeof(float) * MaxPreDelayFrames);
+        memset(m_preDelayBuffers[i].get(), 0, sizeof(float) * MaxPreDelayFrames);
 
     m_preDelayReadIndex = 0;
     m_preDelayWriteIndex = DefaultPreDelayFrames;
 
     m_maxAttackCompressionDiffDb = -1; // uninitialized state
 }
 
 } // namespace WebCore
--- a/dom/media/webaudio/blink/DynamicsCompressorKernel.h
+++ b/dom/media/webaudio/blink/DynamicsCompressorKernel.h
@@ -27,16 +27,17 @@
  */
 
 #ifndef DynamicsCompressorKernel_h
 #define DynamicsCompressorKernel_h
 
 #include "nsTArray.h"
 #include "nsAutoPtr.h"
 #include "mozilla/MemoryReporting.h"
+#include "mozilla/UniquePtr.h"
 
 namespace WebCore {
 
 class DynamicsCompressorKernel {
 public:
     DynamicsCompressorKernel(float sampleRate, unsigned numberOfChannels);
 
     void setNumberOfChannels(unsigned);
@@ -84,17 +85,17 @@ protected:
 
     // Lookahead section.
     enum { MaxPreDelayFrames = 1024 };
     enum { MaxPreDelayFramesMask = MaxPreDelayFrames - 1 };
     enum { DefaultPreDelayFrames = 256 }; // setPreDelayTime() will override this initial value
     unsigned m_lastPreDelayFrames;
     void setPreDelayTime(float);
 
-    nsTArray<nsAutoArrayPtr<float> > m_preDelayBuffers;
+    nsTArray<mozilla::UniquePtr<float[]>> m_preDelayBuffers;
     int m_preDelayReadIndex;
     int m_preDelayWriteIndex;
 
     float m_maxAttackCompressionDiffDb;
 
     // Static compression curve.
     float kneeCurve(float x, float k);
     float saturate(float x, float k);
--- a/dom/media/webaudio/blink/PeriodicWave.cpp
+++ b/dom/media/webaudio/blink/PeriodicWave.cpp
@@ -24,16 +24,17 @@
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "PeriodicWave.h"
 #include <algorithm>
 #include <cmath>
+#include <limits>
 #include "mozilla/FFTBlock.h"
 
 const unsigned MinPeriodicWaveSize = 4096; // This must be a power of two.
 const unsigned MaxPeriodicWaveSize = 8192; // This must be a power of two.
 const float CentsPerRange = 1200 / 3; // 1/3 Octave.
 
 using namespace mozilla;
 using mozilla::dom::OscillatorType;
@@ -46,17 +47,29 @@ PeriodicWave::create(float sampleRate,
                      const float* imag,
                      size_t numberOfComponents)
 {
     bool isGood = real && imag && numberOfComponents > 0;
     MOZ_ASSERT(isGood);
     if (isGood) {
         RefPtr<PeriodicWave> periodicWave =
             new PeriodicWave(sampleRate, numberOfComponents);
-        periodicWave->createBandLimitedTables(real, imag, numberOfComponents);
+
+        // Limit the number of components used to those for frequencies below the
+        // Nyquist of the fixed length inverse FFT.
+        size_t halfSize = periodicWave->m_periodicWaveSize / 2;
+        numberOfComponents = std::min(numberOfComponents, halfSize);
+        periodicWave->m_numberOfComponents = numberOfComponents;
+        periodicWave->m_realComponents = new AudioFloatArray(numberOfComponents);
+        periodicWave->m_imagComponents = new AudioFloatArray(numberOfComponents);
+        memcpy(periodicWave->m_realComponents->Elements(), real,
+               numberOfComponents * sizeof(float));
+        memcpy(periodicWave->m_imagComponents->Elements(), imag,
+               numberOfComponents * sizeof(float));
+
         return periodicWave.forget();
     }
     return nullptr;
 }
 
 already_AddRefed<PeriodicWave>
 PeriodicWave::createSine(float sampleRate)
 {
@@ -91,27 +104,29 @@ PeriodicWave::createTriangle(float sampl
         new PeriodicWave(sampleRate, MinPeriodicWaveSize);
     periodicWave->generateBasicWaveform(OscillatorType::Triangle);
     return periodicWave.forget();
 }
 
 PeriodicWave::PeriodicWave(float sampleRate, size_t numberOfComponents)
     : m_sampleRate(sampleRate)
     , m_centsPerRange(CentsPerRange)
+    , m_lowestRequestedFundamentalFrequency(std::numeric_limits<float>::max())
 {
     float nyquist = 0.5 * m_sampleRate;
 
     if (numberOfComponents <= MinPeriodicWaveSize) {
         m_periodicWaveSize = MinPeriodicWaveSize;
     } else {
         unsigned npow2 = powf(2.0f, floorf(logf(numberOfComponents - 1.0)/logf(2.0f) + 1.0f));
         m_periodicWaveSize = std::min(MaxPeriodicWaveSize, npow2);
     }
 
     m_numberOfRanges = (unsigned)(3.0f*logf(m_periodicWaveSize)/logf(2.0f));
+    m_bandLimitedTables.SetLength(m_numberOfRanges);
     m_lowestFundamentalFrequency = nyquist / maxNumberOfPartials();
     m_rateScale = m_periodicWaveSize / m_sampleRate;
 }
 
 size_t PeriodicWave::sizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
     size_t amount = aMallocSizeOf(this);
 
@@ -122,20 +137,32 @@ size_t PeriodicWave::sizeOfIncludingThis
         }
     }
 
     return amount;
 }
 
 void PeriodicWave::waveDataForFundamentalFrequency(float fundamentalFrequency, float* &lowerWaveData, float* &higherWaveData, float& tableInterpolationFactor)
 {
+
     // Negative frequencies are allowed, in which case we alias
     // to the positive frequency.
     fundamentalFrequency = fabsf(fundamentalFrequency);
 
+    if (fundamentalFrequency < m_lowestRequestedFundamentalFrequency) {
+        for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
+            m_bandLimitedTables[rangeIndex] = 0;
+        }
+
+        // We need to create the first table to determine the normalization
+        // constant.
+        createBandLimitedTables(fundamentalFrequency, 0);
+        m_lowestRequestedFundamentalFrequency = fundamentalFrequency;
+    }
+
     // Calculate the pitch range.
     float ratio = fundamentalFrequency > 0 ? fundamentalFrequency / m_lowestFundamentalFrequency : 0.5;
     float centsAboveLowestFrequency = logf(ratio)/logf(2.0f) * 1200;
 
     // Add one to round-up to the next range just in time to truncate
     // partials before aliasing occurs.
     float pitchRange = 1 + centsAboveLowestFrequency / m_centsPerRange;
 
@@ -144,16 +171,22 @@ void PeriodicWave::waveDataForFundamenta
 
     // The words "lower" and "higher" refer to the table data having
     // the lower and higher numbers of partials. It's a little confusing
     // since the range index gets larger the more partials we cull out.
     // So the lower table data will have a larger range index.
     unsigned rangeIndex1 = static_cast<unsigned>(pitchRange);
     unsigned rangeIndex2 = rangeIndex1 < m_numberOfRanges - 1 ? rangeIndex1 + 1 : rangeIndex1;
 
+    if (!m_bandLimitedTables[rangeIndex1].get())
+        createBandLimitedTables(fundamentalFrequency, rangeIndex1);
+
+    if (!m_bandLimitedTables[rangeIndex2].get())
+        createBandLimitedTables(fundamentalFrequency, rangeIndex2);
+
     lowerWaveData = m_bandLimitedTables[rangeIndex2]->Elements();
     higherWaveData = m_bandLimitedTables[rangeIndex1]->Elements();
 
     // Ranges from 0 -> 1 to interpolate between lower -> higher.
     tableInterpolationFactor = rangeIndex2 - pitchRange;
 }
 
 unsigned PeriodicWave::maxNumberOfPartials() const
@@ -174,88 +207,87 @@ unsigned PeriodicWave::numberOfPartialsF
 
     return numberOfPartials;
 }
 
 // Convert into time-domain wave buffers.
 // One table is created for each range for non-aliasing playback
 // at different playback rates. Thus, higher ranges have more
 // high-frequency partials culled out.
-void PeriodicWave::createBandLimitedTables(const float* realData, const float* imagData, unsigned numberOfComponents)
+void PeriodicWave::createBandLimitedTables(float fundamentalFrequency,
+                                           unsigned rangeIndex)
 {
-    float normalizationScale = 1;
-
     unsigned fftSize = m_periodicWaveSize;
-    unsigned halfSize = fftSize / 2;
     unsigned i;
 
-    // Limit the number of components used to those for frequencies below the
-    // Nyquist of the fixed length inverse FFT.
-    numberOfComponents = std::min(numberOfComponents, halfSize);
+    const float *realData = m_realComponents->Elements();
+    const float *imagData = m_imagComponents->Elements();
 
-    m_bandLimitedTables.SetCapacity(m_numberOfRanges);
-
-    for (unsigned rangeIndex = 0; rangeIndex < m_numberOfRanges; ++rangeIndex) {
-        // This FFTBlock is used to cull partials (represented by frequency bins).
-        FFTBlock frame(fftSize);
+    // This FFTBlock is used to cull partials (represented by frequency bins).
+    FFTBlock frame(fftSize);
 
-        // Find the starting bin where we should start culling the aliasing
-        // partials for this pitch range.  We need to clear out the highest
-        // frequencies to band-limit the waveform.
-        unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
-        // Also limit to the number of components that are provided.
-        numberOfPartials = std::min(numberOfPartials, numberOfComponents - 1);
+    // Find the starting bin where we should start culling the aliasing
+    // partials for this pitch range.  We need to clear out the highest
+    // frequencies to band-limit the waveform.
+    unsigned numberOfPartials = numberOfPartialsForRange(rangeIndex);
+    // Also limit to the number of components that are provided.
+    numberOfPartials = std::min(numberOfPartials, m_numberOfComponents - 1);
 
-        // Copy from loaded frequency data and generate complex conjugate
-        // because of the way the inverse FFT is defined.
-        // The coefficients of higher partials remain zero, as initialized in
-        // the FFTBlock constructor.
-        for (i = 0; i < numberOfPartials + 1; ++i) {
-            frame.RealData(i) = realData[i];
-            frame.ImagData(i) = -imagData[i];
-        }
+    // Limit number of partials to those below Nyquist frequency
+    float nyquist = 0.5 * m_sampleRate;
+    numberOfPartials = std::min(numberOfPartials,
+                                (unsigned)(nyquist / fundamentalFrequency));
 
-        // Clear any DC-offset.
-        frame.RealData(0) = 0;
-        // Clear value which has no effect.
-        frame.ImagData(0) = 0;
+    // Copy from loaded frequency data and generate complex conjugate
+    // because of the way the inverse FFT is defined.
+    // The coefficients of higher partials remain zero, as initialized in
+    // the FFTBlock constructor.
+    for (i = 0; i < numberOfPartials + 1; ++i) {
+        frame.RealData(i) = realData[i];
+        frame.ImagData(i) = -imagData[i];
+    }
 
-        // Create the band-limited table.
-        AlignedAudioFloatArray* table = new AlignedAudioFloatArray(m_periodicWaveSize);
-        m_bandLimitedTables.AppendElement(table);
-
-        // Apply an inverse FFT to generate the time-domain table data.
-        float* data = m_bandLimitedTables[rangeIndex]->Elements();
-        frame.GetInverseWithoutScaling(data);
+    // Clear any DC-offset.
+    frame.RealData(0) = 0;
+    // Clear value which has no effect.
+    frame.ImagData(0) = 0;
 
-        // For the first range (which has the highest power), calculate
-        // its peak value then compute normalization scale.
-        if (!rangeIndex) {
-            float maxValue;
-            maxValue = AudioBufferPeakValue(data, m_periodicWaveSize);
+    // Create the band-limited table.
+    AlignedAudioFloatArray* table = new AlignedAudioFloatArray(m_periodicWaveSize);
+    m_bandLimitedTables[rangeIndex] = table;
+
+    // Apply an inverse FFT to generate the time-domain table data.
+    float* data = m_bandLimitedTables[rangeIndex]->Elements();
+    frame.GetInverseWithoutScaling(data);
 
-            if (maxValue)
-                normalizationScale = 1.0f / maxValue;
-        }
+    // For the first range (which has the highest power), calculate
+    // its peak value then compute normalization scale.
+    if (!rangeIndex) {
+        float maxValue;
+        maxValue = AudioBufferPeakValue(data, m_periodicWaveSize);
 
-        // Apply normalization scale.
-        AudioBufferInPlaceScale(data, normalizationScale, m_periodicWaveSize);
+        if (maxValue)
+            m_normalizationScale = 1.0f / maxValue;
     }
+
+    // Apply normalization scale.
+    AudioBufferInPlaceScale(data, m_normalizationScale, m_periodicWaveSize);
 }
 
 void PeriodicWave::generateBasicWaveform(OscillatorType shape)
 {
     const float piFloat = float(M_PI);
     unsigned fftSize = periodicWaveSize();
     unsigned halfSize = fftSize / 2;
 
-    AudioFloatArray real(halfSize);
-    AudioFloatArray imag(halfSize);
-    float* realP = real.Elements();
-    float* imagP = imag.Elements();
+    m_numberOfComponents = halfSize;
+    m_realComponents = new AudioFloatArray(halfSize);
+    m_imagComponents = new AudioFloatArray(halfSize);
+    float* realP = m_realComponents->Elements();
+    float* imagP = m_imagComponents->Elements();
 
     // Clear DC and imag value which is ignored.
     realP[0] = 0;
     imagP[0] = 0;
 
     for (unsigned n = 1; n < halfSize; ++n) {
         float omega = 2 * piFloat * n;
         float invOmega = 1 / omega;
@@ -300,13 +332,11 @@ void PeriodicWave::generateBasicWaveform
             a = 0;
             b = 0;
             break;
         }
 
         realP[n] = a;
         imagP[n] = b;
     }
-
-    createBandLimitedTables(realP, imagP, halfSize);
 }
 
 } // namespace WebCore
--- a/dom/media/webaudio/blink/PeriodicWave.h
+++ b/dom/media/webaudio/blink/PeriodicWave.h
@@ -80,32 +80,37 @@ private:
     ~PeriodicWave() {}
 
     void generateBasicWaveform(mozilla::dom::OscillatorType);
 
     float m_sampleRate;
     unsigned m_periodicWaveSize;
     unsigned m_numberOfRanges;
     float m_centsPerRange;
+    unsigned m_numberOfComponents;
+    nsAutoPtr<AudioFloatArray> m_realComponents;
+    nsAutoPtr<AudioFloatArray> m_imagComponents;
 
     // The lowest frequency (in Hertz) where playback will include all of the
     // partials.  Playing back lower than this frequency will gradually lose
     // more high-frequency information.
     // This frequency is quite low (~10Hz @ // 44.1KHz)
     float m_lowestFundamentalFrequency;
 
     float m_rateScale;
 
     unsigned numberOfRanges() const { return m_numberOfRanges; }
 
     // Maximum possible number of partials (before culling).
     unsigned maxNumberOfPartials() const;
 
     unsigned numberOfPartialsForRange(unsigned rangeIndex) const;
 
-    // Creates tables based on numberOfComponents Fourier coefficients.
-    void createBandLimitedTables(const float* real, const float* imag, unsigned numberOfComponents);
+    // Creates table for specified index based on fundamental frequency.
+    void createBandLimitedTables(float fundamentalFrequency, unsigned rangeIndex);
+    float m_lowestRequestedFundamentalFrequency;
+    float m_normalizationScale;
     nsTArray<nsAutoPtr<AlignedAudioFloatArray> > m_bandLimitedTables;
 };
 
 } // namespace WebCore
 
 #endif // PeriodicWave_h
--- a/dom/media/webm/EbmlComposer.cpp
+++ b/dom/media/webm/EbmlComposer.cpp
@@ -16,18 +16,18 @@ static const unsigned long TIME_CODE_SCA
 // The WebM header size without audio CodecPrivateData
 static const int32_t DEFAULT_HEADER_SIZE = 1024;
 
 void EbmlComposer::GenerateHeader()
 {
   // Write the EBML header.
   EbmlGlobal ebml;
   // The WEbM header default size usually smaller than 1k.
-  nsAutoArrayPtr<uint8_t> buffer(new uint8_t[DEFAULT_HEADER_SIZE +
-                                             mCodecPrivateData.Length()]);
+  auto buffer = MakeUnique<uint8_t[]>(DEFAULT_HEADER_SIZE +
+                                             mCodecPrivateData.Length());
   ebml.buf = buffer.get();
   ebml.offset = 0;
   writeHeader(&ebml);
   {
     EbmlLoc segEbmlLoc, ebmlLocseg, ebmlLoc;
     Ebml_StartSubElement(&ebml, &segEbmlLoc, Segment);
     {
       Ebml_StartSubElement(&ebml, &ebmlLocseg, SeekHead);
--- a/dom/media/webrtc/MediaEngineDefault.cpp
+++ b/dom/media/webrtc/MediaEngineDefault.cpp
@@ -1,16 +1,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "MediaEngineDefault.h"
 
 #include "nsCOMPtr.h"
 #include "mozilla/dom/File.h"
+#include "mozilla/UniquePtr.h"
 #include "nsILocalFile.h"
 #include "Layers.h"
 #include "ImageContainer.h"
 #include "ImageTypes.h"
 #include "prmem.h"
 #include "nsContentUtils.h"
 
 #include "nsIFilePicker.h"
@@ -309,17 +310,17 @@ public:
   static const int millisecondsPerSecond = PR_MSEC_PER_SEC;
 
   explicit SineWaveGenerator(uint32_t aSampleRate, uint32_t aFrequency) :
     mTotalLength(aSampleRate / aFrequency),
     mReadLength(0) {
     // If we allow arbitrary frequencies, there's no guarantee we won't get rounded here
     // We could include an error term and adjust for it in generation; not worth the trouble
     //MOZ_ASSERT(mTotalLength * aFrequency == aSampleRate);
-    mAudioBuffer = new int16_t[mTotalLength];
+    mAudioBuffer = MakeUnique<int16_t[]>(mTotalLength);
     for (int i = 0; i < mTotalLength; i++) {
       // Set volume to -20db. It's from 32768.0 * 10^(-20/20) = 3276.8
       mAudioBuffer[i] = (3276.8f * sin(2 * M_PI * i / mTotalLength));
     }
   }
 
   // NOTE: only safely called from a single thread (MSG callback)
   void generate(int16_t* aBuffer, int16_t aLengthInSamples) {
@@ -328,28 +329,28 @@ public:
     while (remaining) {
       int16_t processSamples = 0;
 
       if (mTotalLength - mReadLength >= remaining) {
         processSamples = remaining;
       } else {
         processSamples = mTotalLength - mReadLength;
       }
-      memcpy(aBuffer, mAudioBuffer + mReadLength, processSamples * bytesPerSample);
+      memcpy(aBuffer, &mAudioBuffer[mReadLength], processSamples * bytesPerSample);
       aBuffer += processSamples;
       mReadLength += processSamples;
       remaining -= processSamples;
       if (mReadLength == mTotalLength) {
         mReadLength = 0;
       }
     }
   }
 
 private:
-  nsAutoArrayPtr<int16_t> mAudioBuffer;
+  UniquePtr<int16_t[]> mAudioBuffer;
   int16_t mTotalLength;
   int16_t mReadLength;
 };
 
 /**
  * Default audio source.
  */
 NS_IMPL_ISUPPORTS(MediaEngineDefaultAudioSource, nsITimerCallback)
--- a/dom/media/webspeech/synth/test/nsFakeSynthServices.cpp
+++ b/dom/media/webspeech/synth/test/nsFakeSynthServices.cpp
@@ -147,18 +147,18 @@ FakeDirectAudioSynth::Speak(const nsAStr
     NS_IMETHOD Run() override
     {
       RefPtr<FakeSynthCallback> cb = new FakeSynthCallback(nullptr);
       mTask->Setup(cb, CHANNELS, SAMPLERATE, 2);
 
       // Just an arbitrary multiplier. Pretend that each character is
       // synthesized to 40 frames.
       uint32_t frames_length = 40 * mText.Length();
-      nsAutoArrayPtr<int16_t> frames(new int16_t[frames_length]());
-      mTask->SendAudioNative(frames, frames_length);
+      auto frames = MakeUnique<int16_t[]>(frames_length);
+      mTask->SendAudioNative(frames.get(), frames_length);
 
       mTask->SendAudioNative(nullptr, 0);
 
       return NS_OK;
     }
 
   private:
     nsCOMPtr<nsISpeechTask> mTask;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -622,16 +622,35 @@ PluginModuleChromeParent::OnProcessLaunc
 
 #if defined(XP_MACOSX)
         if (NS_SUCCEEDED(mAsyncInitRv)) {
             mAsyncInitRv = NP_GetEntryPoints(mNPPIface,
                                              &mAsyncInitError);
         }
 #endif
     }
+
+#ifdef MOZ_ENABLE_PROFILER_SPS
+    nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
+    bool profilerActive = false;
+    DebugOnly<nsresult> rv = profiler->IsActive(&profilerActive);
+    MOZ_ASSERT(NS_SUCCEEDED(rv));
+    if (profilerActive) {
+        nsCOMPtr<nsIProfilerStartParams> currentProfilerParams;
+        rv = profiler->GetStartParams(getter_AddRefs(currentProfilerParams));
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+
+        nsCOMPtr<nsISupports> gatherer;
+        rv = profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+        MOZ_ASSERT(NS_SUCCEEDED(rv));
+        mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
+
+        StartProfiler(currentProfilerParams);
+    }
+#endif
 }
 
 bool
 PluginModuleChromeParent::WaitForIPCConnection()
 {
     PluginProcessParent* process = Process();
     MOZ_ASSERT(process);
     process->SetCallRunnableImmediately(true);
@@ -3157,36 +3176,21 @@ NS_IMPL_ISUPPORTS(PluginProfilerObserver
 
 NS_IMETHODIMP
 PluginProfilerObserver::Observe(nsISupports *aSubject,
                                 const char *aTopic,
                                 const char16_t *aData)
 {
     if (!strcmp(aTopic, "profiler-started")) {
         nsCOMPtr<nsIProfilerStartParams> params(do_QueryInterface(aSubject));
-        uint32_t entries;
-        double interval;
-        params->GetEntries(&entries);
-        params->GetInterval(&interval);
-        const nsTArray<nsCString>& features = params->GetFeatures();
-        const nsTArray<nsCString>& threadFilterNames = params->GetThreadFilterNames();
-
-        ProfilerInitParams ipcParams;
-        ipcParams.enabled() = true;
-        ipcParams.entries() = entries;
-        ipcParams.interval() = interval;
-        ipcParams.features() = features;
-        ipcParams.threadFilters() = threadFilterNames;
-
-        Unused << mPmp->SendStartProfiler(ipcParams);
+        mPmp->StartProfiler(params);
     } else if (!strcmp(aTopic, "profiler-stopped")) {
-        Unused << mPmp->SendStopProfiler();
+        mPmp->StopProfiler();
     } else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
-        RefPtr<ProfileGatherer> gatherer = static_cast<ProfileGatherer*>(aSubject);
-        mPmp->GatherAsyncProfile(gatherer);
+        mPmp->GatherAsyncProfile();
     } else if (!strcmp(aTopic, "profiler-subprocess")) {
         nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
         mPmp->GatheredAsyncProfile(pse);
     }
     return NS_OK;
 }
 
 void
@@ -3210,19 +3214,54 @@ PluginModuleChromeParent::ShutdownPlugin
         observerService->RemoveObserver(mProfilerObserver, "profiler-started");
         observerService->RemoveObserver(mProfilerObserver, "profiler-stopped");
         observerService->RemoveObserver(mProfilerObserver, "profiler-subprocess-gather");
         observerService->RemoveObserver(mProfilerObserver, "profiler-subprocess");
     }
 }
 
 void
-PluginModuleChromeParent::GatherAsyncProfile(ProfileGatherer* aGatherer)
+PluginModuleChromeParent::StartProfiler(nsIProfilerStartParams* aParams)
 {
-    mGatherer = aGatherer;
+    if (NS_WARN_IF(!aParams)) {
+        return;
+    }
+
+    ProfilerInitParams ipcParams;
+
+    ipcParams.enabled() = true;
+    aParams->GetEntries(&ipcParams.entries());
+    aParams->GetInterval(&ipcParams.interval());
+    ipcParams.features() = aParams->GetFeatures();
+    ipcParams.threadFilters() = aParams->GetThreadFilterNames();
+
+    Unused << SendStartProfiler(ipcParams);
+
+    nsCOMPtr<nsIProfiler> profiler(do_GetService("@mozilla.org/tools/profiler;1"));
+    if (NS_WARN_IF(!profiler)) {
+        return;
+    }
+    nsCOMPtr<nsISupports> gatherer;
+    profiler->GetProfileGatherer(getter_AddRefs(gatherer));
+    mGatherer = static_cast<ProfileGatherer*>(gatherer.get());
+}
+
+void
+PluginModuleChromeParent::StopProfiler()
+{
+    mGatherer = nullptr;
+    Unused << SendStopProfiler();
+}
+
+void
+PluginModuleChromeParent::GatherAsyncProfile()
+{
+    if (NS_WARN_IF(!mGatherer)) {
+        return;
+    }
     mGatherer->WillGatherOOPProfile();
     Unused << SendGatherProfile();
 }
 
 void
 PluginModuleChromeParent::GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent)
 {
     if (aSaveEvent && !mProfile.IsEmpty()) {
@@ -3237,14 +3276,13 @@ PluginModuleChromeParent::RecvProfile(co
 {
 #ifdef MOZ_ENABLE_PROFILER_SPS
     if (NS_WARN_IF(!mGatherer)) {
         return true;
     }
 
     mProfile = aProfile;
     mGatherer->GatheredOOPProfile();
-    mGatherer = nullptr;
 #endif
     return true;
 }
 
 
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -451,18 +451,20 @@ class PluginModuleChromeParent
     void CachedSettingChanged();
 
     void OnEnteredCall() override;
     void OnExitedCall() override;
     void OnEnteredSyncSend() override;
     void OnExitedSyncSend() override;
 
 #ifdef  MOZ_ENABLE_PROFILER_SPS
-    void GatherAsyncProfile(mozilla::ProfileGatherer* aGatherer);
+    void GatherAsyncProfile();
     void GatheredAsyncProfile(nsIProfileSaveEvent* aSaveEvent);
+    void StartProfiler(nsIProfilerStartParams* aParams);
+    void StopProfiler();
 #endif
 
     virtual bool
     RecvProfile(const nsCString& aProfile) override;
 
 private:
     virtual void
     EnteredCxxStack() override;
--- a/dom/presentation/PresentationSessionInfo.cpp
+++ b/dom/presentation/PresentationSessionInfo.cpp
@@ -33,24 +33,21 @@
 #include "nsINetworkInterface.h"
 #include "nsINetworkManager.h"
 #endif
 
 using namespace mozilla;
 using namespace mozilla::dom;
 using namespace mozilla::services;
 
-inline static PRLogModuleInfo*
-GetPresentationSessionInfoLog()
-{
-  static PRLogModuleInfo* log = PR_NewLogModule("PresentationSessionInfo");
-  return log;
-}
+
+static LazyLogModule gPresentationSessionInfoLog("PresentationSessionInfo");
+
 #undef LOG
-#define LOG(...) MOZ_LOG(GetPresentationSessionInfoLog(), mozilla::LogLevel::Error, (__VA_ARGS__))
+#define LOG(...) MOZ_LOG(gPresentationSessionInfoLog, mozilla::LogLevel::Error, (__VA_ARGS__))
 
 
 /*
  * Implementation of PresentationChannelDescription
  */
 
 namespace mozilla {
 namespace dom {
new file mode 100644
--- /dev/null
+++ b/dom/xslt/crashtests/1205163.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="1205163.xsl"?>
+<result>
+  <Title>Example</Title>
+  <Error>Error</Error>
+</result>
new file mode 100644
--- /dev/null
+++ b/dom/xslt/crashtests/1205163.xsl
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<xsl:stylesheet version="1.0"
+   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:output method="text"/>
+  <xsl:template match="node()|@*">
+    <xsl:copy>
+      <xsl:apply-templates select="node()|@*"/>
+    </xsl:copy>
+  </xsl:template>
+  <xsl:template match="Error"/>
+</xsl:stylesheet>
--- a/dom/xslt/crashtests/crashtests.list
+++ b/dom/xslt/crashtests/crashtests.list
@@ -11,8 +11,9 @@ load 528300.xml
 load 528488.xml
 load 528963.xml
 load 545927.html
 load 601543.html
 load 602115.html
 load 603844.html
 load 667315.xml
 load 1089049.html
+load 1205163.xml
--- a/dom/xslt/xslt/txMozillaTextOutput.cpp
+++ b/dom/xslt/xslt/txMozillaTextOutput.cpp
@@ -76,16 +76,21 @@ txMozillaTextOutput::endDocument(nsresul
     NS_ENSURE_TRUE(mDocument && mTextParent, NS_ERROR_FAILURE);
 
     RefPtr<nsTextNode> text = new nsTextNode(mDocument->NodeInfoManager());
     
     text->SetText(mText, false);
     nsresult rv = mTextParent->AppendChildTo(text, true);
     NS_ENSURE_SUCCESS(rv, rv);
 
+    // This should really be handled by nsIDocument::EndLoad
+    MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
+               nsIDocument::READYSTATE_LOADING, "Bad readyState");
+    mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_INTERACTIVE);
+
     if (NS_SUCCEEDED(aResult)) {
         nsCOMPtr<nsITransformObserver> observer = do_QueryReferent(mObserver);
         if (observer) {
             observer->OnTransformDone(aResult, mDocument);
         }
     }
 
     return NS_OK;
@@ -129,16 +134,20 @@ txMozillaTextOutput::createResultDocumen
      *
      * <transformiix:result> * The text comes here * </transformiix:result>
      */
 
     // Create the document
     nsresult rv = NS_NewXMLDocument(getter_AddRefs(mDocument),
                                     aLoadedAsData);
     NS_ENSURE_SUCCESS(rv, rv);
+    // This should really be handled by nsIDocument::BeginLoad
+    MOZ_ASSERT(mDocument->GetReadyStateEnum() ==
+               nsIDocument::READYSTATE_UNINITIALIZED, "Bad readyState");
+    mDocument->SetReadyStateInternal(nsIDocument::READYSTATE_LOADING);
     nsCOMPtr<nsIDocument> source = do_QueryInterface(aSourceDocument);
     NS_ENSURE_STATE(source);
     bool hasHadScriptObject = false;
     nsIScriptGlobalObject* sgo =
       source->GetScriptHandlingObject(hasHadScriptObject);
     NS_ENSURE_STATE(sgo || !hasHadScriptObject);
     mDocument->SetScriptHandlingObject(sgo);
 
--- a/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
+++ b/gfx/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -204,16 +204,26 @@ void GetUniformBlockInfo(const std::vect
             bool isRowMajorMatrix = (gl::IsMatrixType(field.type) && inRowMajorLayout);
             (*blockInfoOut)[fieldName] =
                 encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix);
         }
     }
 }
 
 template <typename T>
+static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
+{
+    ASSERT(dest != NULL);
+    ASSERT(dirtyFlag != NULL);
+
+    *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
+    *dest      = source;
+}
+
+template <typename T>
 bool TransposeMatrix(T *target,
                      const GLfloat *value,
                      int targetWidth,
                      int targetHeight,
                      int srcWidth,
                      int srcHeight)
 {
     bool dirty = false;
@@ -1907,26 +1917,16 @@ void ProgramD3D::defineUniform(GLenum sh
         if (uniform.isArray())
         {
             encoder->exitAggregateType();
         }
     }
 }
 
 template <typename T>
-static inline void SetIfDirty(T *dest, const T &source, bool *dirtyFlag)
-{
-    ASSERT(dest != NULL);
-    ASSERT(dirtyFlag != NULL);
-
-    *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0);
-    *dest      = source;
-}
-
-template <typename T>
 void ProgramD3D::setUniform(GLint location, GLsizei countIn, const T *v, GLenum targetUniformType)
 {
     const int components        = gl::VariableComponentCount(targetUniformType);
     const GLenum targetBoolType = gl::VariableBoolVectorType(targetUniformType);
 
     D3DUniform *targetUniform = getD3DUniformFromLocation(location);
 
     unsigned int elementCount = targetUniform->elementCount();
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -1914,16 +1914,29 @@ nsEventStatus AsyncPanZoomController::On
 nsEventStatus AsyncPanZoomController::OnPanEnd(const PanGestureInput& aEvent) {
   APZC_LOG("%p got a pan-end in state %d\n", this, mState);
 
   // Call into OnPan in order to process any delta included in this event.
   OnPan(aEvent, true);
 
   mX.EndTouch(aEvent.mTime);
   mY.EndTouch(aEvent.mTime);
+
+  // Drop any velocity on axes where we don't have room to scroll anyways
+  // (in this APZC, or an APZC further in the handoff chain).
+  // This ensures that we don't enlarge the display port unnecessarily.
+  RefPtr<const OverscrollHandoffChain> overscrollHandoffChain =
+    CurrentPanGestureBlock()->GetOverscrollHandoffChain();
+  if (!overscrollHandoffChain->CanScrollInDirection(this, Layer::HORIZONTAL)) {
+    mX.SetVelocity(0);
+  }
+  if (!overscrollHandoffChain->CanScrollInDirection(this, Layer::VERTICAL)) {
+    mY.SetVelocity(0);
+  }
+
   SetState(NOTHING);
   RequestContentRepaint();
 
   return nsEventStatus_eConsumeNoDefault;
 }
 
 nsEventStatus AsyncPanZoomController::OnPanMomentumStart(const PanGestureInput& aEvent) {
   APZC_LOG("%p got a pan-momentumstart in state %d\n", this, mState);
--- a/gfx/layers/apz/src/Axis.cpp
+++ b/gfx/layers/apz/src/Axis.cpp
@@ -71,17 +71,17 @@ void Axis::UpdateWithTouchAtDevicePoint(
     // This could be a duplicate event, or it could be a legitimate event
     // on some platforms that generate events really fast. As a compromise
     // update mPos so we don't run into problems like bug 1042734, even though
     // that means the velocity will be stale. Better than doing a divide-by-zero.
     mPos = aPos;
     return;
   }
 
-  float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos - aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs);
+  float newVelocity = mAxisLocked ? 0.0f : (float)(mPos - aPos + aAdditionalDelta) / (float)(aTimestampMs - mPosTimeMs);
   if (gfxPrefs::APZMaxVelocity() > 0.0f) {
     bool velocityIsNegative = (newVelocity < 0);
     newVelocity = fabs(newVelocity);
 
     float maxVelocity = ToLocalVelocity(gfxPrefs::APZMaxVelocity());
     newVelocity = std::min(newVelocity, maxVelocity);
 
     if (gfxPrefs::APZCurveThreshold() > 0.0f && gfxPrefs::APZCurveThreshold() < gfxPrefs::APZMaxVelocity()) {
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -712,34 +712,16 @@ ClientLayerManager::GetTexturePool(Surfa
                             gfxPrefs::LayersTileMaxPoolSize(),
                             gfxPrefs::LayersTileShrinkPoolTimeout(),
                             mForwarder));
 
   return mTexturePools.LastElement();
 }
 
 void
-ClientLayerManager::ReturnTextureClientDeferred(TextureClient& aClient) {
-  GetTexturePool(aClient.GetFormat(),
-                 aClient.GetFlags())->ReturnTextureClientDeferred(&aClient);
-}
-
-void
-ClientLayerManager::ReturnTextureClient(TextureClient& aClient) {
-  GetTexturePool(aClient.GetFormat(),
-                 aClient.GetFlags())->ReturnTextureClient(&aClient);
-}
-
-void
-ClientLayerManager::ReportClientLost(TextureClient& aClient) {
-  GetTexturePool(aClient.GetFormat(),
-                 aClient.GetFlags())->ReportClientLost();
-}
-
-void
 ClientLayerManager::ClearCachedResources(Layer* aSubtree)
 {
   if (mDestroyed) {
     // ClearCachedResource was already called by ClientLayerManager::Destroy
     return;
   }
   MOZ_ASSERT(!HasShadowManager() || !aSubtree);
   mForwarder->ClearCachedResources();
--- a/gfx/layers/client/ClientLayerManager.h
+++ b/gfx/layers/client/ClientLayerManager.h
@@ -118,21 +118,16 @@ public:
 
   virtual bool IsCompositingCheap() override;
   virtual bool HasShadowManagerInternal() const override { return HasShadowManager(); }
 
   virtual void SetIsFirstPaint() override;
 
   TextureClientPool* GetTexturePool(gfx::SurfaceFormat aFormat, TextureFlags aFlags);
 
-  /// Utility methods for managing texture clients.
-  void ReturnTextureClientDeferred(TextureClient& aClient);
-  void ReturnTextureClient(TextureClient& aClient);
-  void ReportClientLost(TextureClient& aClient);
-
   /**
    * Pass through call to the forwarder for nsPresContext's
    * CollectPluginGeometryUpdates. Passes widget configuration information
    * to the compositor for transmission to the chrome process. This
    * configuration gets set when the window paints.
    */
   void StorePluginWidgetConfigurations(const nsTArray<nsIWidget::Configuration>&
                                        aConfigurations) override;
--- a/gfx/thebes/moz.build
+++ b/gfx/thebes/moz.build
@@ -251,16 +251,17 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'gfxMacPlatformFontList.mm',
     ]
 
 # We prefer to use ICU for normalization functions, but currently it is only
 # available if we're building with the Intl API enabled:
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
     CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
     USE_LIBS += [
         'icu',
     ]
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/intl/build/moz.build
+++ b/intl/build/moz.build
@@ -5,16 +5,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SOURCES += [
     'nsI18nModule.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
 LOCAL_INCLUDES += [
     '../locale',
     '../lwbrk',
     '../strres',
     '../uconv',
     '../unicharutil',
 ]
 
new file mode 100644
--- /dev/null
+++ b/intl/icu-patches/bug-1228227-libc++-gcc_hidden.diff
@@ -0,0 +1,23 @@
+Limit libstdc++ workaround to not upset libc++ with pragma visibility.
+
+diff --git a/intl/icu/source/common/unicode/std_string.h b/intl/icu/source/common/unicode/std_string.h
+--- a/intl/icu/source/common/unicode/std_string.h
++++ b/intl/icu/source/common/unicode/std_string.h
+@@ -22,16 +22,16 @@
+  * \brief C++ API: Central ICU header for including the C++ standard &lt;string&gt;
+  *                 header and for related definitions.
+  */
+ 
+ #include "unicode/utypes.h"
+ 
+ #if U_HAVE_STD_STRING
+ 
+-#if !defined(_MSC_VER)
++#if defined(__GLIBCXX__)
+ namespace std { class type_info; } // WORKAROUND: http://llvm.org/bugs/show_bug.cgi?id=13364
+ #endif
+ #include <string>
+ 
+ #endif  // U_HAVE_STD_STRING
+ 
+ #endif  // __STD_STRING_H__
--- a/intl/icu/source/common/unicode/std_string.h
+++ b/intl/icu/source/common/unicode/std_string.h
@@ -22,16 +22,16 @@
  * \brief C++ API: Central ICU header for including the C++ standard &lt;string&gt;
  *                 header and for related definitions.
  */
 
 #include "unicode/utypes.h"
 
 #if U_HAVE_STD_STRING
 
-#if !defined(_MSC_VER)
+#if defined(__GLIBCXX__)
 namespace std { class type_info; } // WORKAROUND: http://llvm.org/bugs/show_bug.cgi?id=13364
 #endif
 #include <string>
 
 #endif  // U_HAVE_STD_STRING
 
 #endif  // __STD_STRING_H__
--- a/intl/locale/mac/moz.build
+++ b/intl/locale/mac/moz.build
@@ -7,11 +7,12 @@
 UNIFIED_SOURCES += [
     'nsCollationMacUC.cpp',
     'nsDateTimeFormatMac.cpp',
     'nsMacCharset.cpp',
 ]
 
 FINAL_LIBRARY = 'xul'
 CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
 LOCAL_INCLUDES += [
     '..',
 ]
--- a/intl/unicharutil/util/internal/moz.build
+++ b/intl/unicharutil/util/internal/moz.build
@@ -15,10 +15,11 @@ UNIFIED_SOURCES += intl_unicharutil_util
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '..',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
 
 DIST_INSTALL = True
--- a/intl/unicharutil/util/moz.build
+++ b/intl/unicharutil/util/moz.build
@@ -36,11 +36,12 @@ USE_STATIC_LIBS = True
 if CONFIG['_MSC_VER']:
     DEFINES['_USE_ANSI_CPP'] = True
     # Don't include directives about which CRT to use
     CFLAGS += ['-Zl']
     CXXFLAGS += ['-Zl']
 
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
     USE_LIBS += ['icu']
 
 DIST_INSTALL = True
--- a/intl/unicharutil/util/standalone/moz.build
+++ b/intl/unicharutil/util/standalone/moz.build
@@ -8,16 +8,17 @@ if CONFIG['OS_TARGET'] != 'WINNT' and CO
     Library('unicharutil_standalone')
 
 UNIFIED_SOURCES += [
     '../nsUnicodeProperties.cpp',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
     USE_LIBS += ['icu']
 
 for var in ('MOZILLA_INTERNAL_API', 'MOZILLA_XPCOMRT_API', 'MOZILLA_EXTERNAL_LINKAGE',
             'NR_SOCKET_IS_VOID_PTR', 'HAVE_STRDUP'):
     DEFINES[var] = True
 
 if CONFIG['GNU_CXX']:
     CXXFLAGS += ['-Wshadow']
--- a/intl/update-icu.sh
+++ b/intl/update-icu.sh
@@ -53,14 +53,15 @@ rm ${icu_dir}/source/data/unit/*.txt
 svn info $1 | grep -v '^Revision: [[:digit:]]\+$' > ${icu_dir}/SVN-INFO
 
 patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-915735
 patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/suppress-warnings.diff
 patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-1172609-icu-fix.diff
 patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-1172609-timezone-recreateDefault.diff
 patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-1198952-workaround-make-3.82-bug.diff
 patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/icu-release-56-1-flagparser-fix.patch
+patch -d ${icu_dir}/../../ -p1 < ${icu_dir}/../icu-patches/bug-1228227-libc++-gcc_hidden.diff
 
 # NOTE: If you're updating this script for a new ICU version, you have to rerun
 # js/src/tests/ecma_6/String/make-normalize-generateddata-input.py for any
 # normalization changes the new ICU implements.
 
 hg addremove ${icu_dir}
--- a/js/src/asmjs/AsmJSModule.cpp
+++ b/js/src/asmjs/AsmJSModule.cpp
@@ -1794,22 +1794,19 @@ AsmJSModule::setProfilingEnabled(bool en
         Instruction* callerInsn = reinterpret_cast<Instruction*>(caller);
         BOffImm calleeOffset;
         callerInsn->as<InstBLImm>()->extractImm(&calleeOffset);
         void* callee = calleeOffset.getDest(callerInsn);
 #elif defined(JS_CODEGEN_ARM64)
         MOZ_CRASH();
         void* callee = nullptr;
         (void)callerRetAddr;
-#elif defined(JS_CODEGEN_MIPS32)
-        Instruction* instr = (Instruction*)(callerRetAddr - 4 * sizeof(uint32_t));
-        void* callee = (void*)Assembler::ExtractLuiOriValue(instr, instr->next());
-#elif defined(JS_CODEGEN_MIPS64)
-        Instruction* instr = (Instruction*)(callerRetAddr - 6 * sizeof(uint32_t));
-        void* callee = (void*)Assembler::ExtractLoad64Value(instr);
+#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
+        uint8_t* instr = callerRetAddr - Assembler::PatchWrite_NearCallSize();
+        void* callee = (void*)Assembler::ExtractInstructionImmediate(instr);
 #elif defined(JS_CODEGEN_NONE)
         MOZ_CRASH();
         void* callee = nullptr;
 #else
 # error "Missing architecture"
 #endif
 
         const CodeRange* codeRange = lookupCodeRange(callee);
@@ -1824,23 +1821,18 @@ AsmJSModule::setProfilingEnabled(bool en
 
 #if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
         X86Encoding::SetRel32(callerRetAddr, newCallee);
 #elif defined(JS_CODEGEN_ARM)
         new (caller) InstBLImm(BOffImm(newCallee - caller), Assembler::Always);
 #elif defined(JS_CODEGEN_ARM64)
         (void)newCallee;
         MOZ_CRASH();
-#elif defined(JS_CODEGEN_MIPS32)
-        Assembler::WriteLuiOriInstructions(instr, instr->next(),
-                                           ScratchRegister, (uint32_t)newCallee);
-        instr[2] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
-#elif defined(JS_CODEGEN_MIPS64)
-        Assembler::WriteLoad64Instructions(instr, ScratchRegister, (uint64_t)newCallee);
-        instr[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr);
+#elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
+        Assembler::PatchInstructionImmediate(instr, PatchedImmPtr(newCallee));
 #elif defined(JS_CODEGEN_NONE)
         MOZ_CRASH();
 #else
 # error "Missing architecture"
 #endif
     }
 
     // Update all the addresses in the function-pointer tables to point to the
--- a/js/src/builtin/AtomicsObject.cpp
+++ b/js/src/builtin/AtomicsObject.cpp
@@ -134,23 +134,16 @@ CompareExchange(Scalar::Type viewType, i
       }
       case Scalar::Uint8: {
         uint8_t oldval = (uint8_t)oldCandidate;
         uint8_t newval = (uint8_t)newCandidate;
         oldval = jit::AtomicOperations::compareExchangeSeqCst(viewData.cast<uint8_t*>() + offset,
                                                               oldval, newval);
         return oldval;
       }
-      case Scalar::Uint8Clamped: {
-        uint8_t oldval = ClampIntForUint8Array(oldCandidate);
-        uint8_t newval = ClampIntForUint8Array(newCandidate);
-        oldval = jit::AtomicOperations::compareExchangeSeqCst(viewData.cast<uint8_t*>() + offset,
-                                                              oldval, newval);
-        return oldval;
-      }
       case Scalar::Int16: {
         int16_t oldval = (int16_t)oldCandidate;
         int16_t newval = (int16_t)newCandidate;
         oldval = jit::AtomicOperations::compareExchangeSeqCst(viewData.cast<int16_t*>() + offset,
                                                               oldval, newval);
         return oldval;
       }
       case Scalar::Uint16: {
@@ -230,18 +223,17 @@ js::atomics_load(JSContext* cx, unsigned
     if (!GetSharedTypedArray(cx, objv, &view))
         return false;
     uint32_t offset;
     if (!GetTypedArrayIndex(cx, idxv, view, &offset))
         return false;
 
     SharedMem<void*> viewData = view->viewDataShared();
     switch (view->type()) {
-      case Scalar::Uint8:
-      case Scalar::Uint8Clamped: {
+      case Scalar::Uint8: {
         uint8_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<uint8_t*>() + offset);
         r.setInt32(v);
         return true;
       }
       case Scalar::Int8: {
         int8_t v = jit::AtomicOperations::loadSeqCst(viewData.cast<uint8_t*>() + offset);
         r.setInt32(v);
         return true;
@@ -295,21 +287,16 @@ ExchangeOrStore(Scalar::Type viewType, i
         INT_OP(viewData.cast<int8_t*>() + offset, value);
         return value;
       }
       case Scalar::Uint8: {
         uint8_t value = (uint8_t)numberValue;
         INT_OP(viewData.cast<uint8_t*>() + offset, value);
         return value;
       }
-      case Scalar::Uint8Clamped: {
-        uint8_t value = ClampIntForUint8Array(numberValue);
-        INT_OP(viewData.cast<uint8_t*>() + offset, value);
-        return value;
-      }
       case Scalar::Int16: {
         int16_t value = (int16_t)numberValue;
         INT_OP(viewData.cast<int16_t*>() + offset, value);
         return value;
       }
       case Scalar::Uint16: {
         uint16_t value = (uint16_t)numberValue;
         INT_OP(viewData.cast<uint16_t*>() + offset, value);
@@ -401,36 +388,16 @@ AtomicsBinop(JSContext* cx, HandleValue 
         r.setInt32(T::operate(viewData.cast<int8_t*>() + offset, v));
         return true;
       }
       case Scalar::Uint8: {
         uint8_t v = (uint8_t)numberValue;
         r.setInt32(T::operate(viewData.cast<uint8_t*>() + offset, v));
         return true;
       }
-      case Scalar::Uint8Clamped: {
-        // Spec says:
-        //  - clamp the input value
-        //  - perform the operation
-        //  - clamp the result
-        //  - store the result
-        // This requires a CAS loop.
-        int32_t value = ClampIntForUint8Array(numberValue);
-        SharedMem<uint8_t*> loc = viewData.cast<uint8_t*>() + offset;
-        for (;;) {
-            uint8_t old = jit::AtomicOperations::loadSafeWhenRacy(loc);
-            uint8_t result = (uint8_t)ClampIntForUint8Array(T::perform(old, value));
-            uint8_t tmp = jit::AtomicOperations::compareExchangeSeqCst(loc, old, result);
-            if (tmp == old) {
-                r.setInt32(old);
-                break;
-            }
-        }
-        return true;
-      }
       case Scalar::Int16: {
         int16_t v = (int16_t)numberValue;
         r.setInt32(T::operate(viewData.cast<int16_t*>() + offset, v));
         return true;
       }
       case Scalar::Uint16: {
         uint16_t v = (uint16_t)numberValue;
         r.setInt32(T::operate(viewData.cast<uint16_t*>() + offset, v));
--- a/js/src/jit-test/tests/atomics/basic-tests.js
+++ b/js/src/jit-test/tests/atomics/basic-tests.js
@@ -404,16 +404,29 @@ function testIsLockFree() {
     assertEq(Atomics.isLockFree(7), false);
     assertEq(Atomics.isLockFree(8), saved8);
     assertEq(Atomics.isLockFree(9), false);
     assertEq(Atomics.isLockFree(10), false);
     assertEq(Atomics.isLockFree(11), false);
     assertEq(Atomics.isLockFree(12), false);
 }
 
+function testUint8Clamped(sab) {
+    var ta = new Uint8ClampedArray(sab);
+    var thrown = false;
+    try {
+	CLONE(testMethod)(ta, 0);
+    }
+    catch (e) {
+	thrown = true;
+	assertEq(e instanceof TypeError, true);
+    }
+    assertEq(thrown, true);
+}
+
 function isLittleEndian() {
     var xxx = new ArrayBuffer(2);
     var xxa = new Int16Array(xxx);
     var xxb = new Int8Array(xxx);
     xxa[0] = 37;
     var is_little = xxb[0] == 37;
     return is_little;
 }
@@ -435,17 +448,16 @@ function runTests() {
 	assertEq(t2[0], 37);
     else
 	assertEq(t2[0], 37 << 16);
     t1[0] = 0;
 
     // Test that invoking as Atomics.whatever() works, on correct arguments.
     CLONE(testMethod)(new Int8Array(sab), 0, 42, 4095);
     CLONE(testMethod)(new Uint8Array(sab), 0, 42, 4095);
-    CLONE(testMethod)(new Uint8ClampedArray(sab), 0, 42, 4095);
     CLONE(testMethod)(new Int16Array(sab), 0, 42, 2047);
     CLONE(testMethod)(new Uint16Array(sab), 0, 42, 2047);
     CLONE(testMethod)(new Int32Array(sab), 0, 42, 1023);
     CLONE(testMethod)(new Uint32Array(sab), 0, 42, 1023);
 
     // Test that invoking as v = Atomics.whatever; v() works, on correct arguments.
     gAtomics_compareExchange = Atomics.compareExchange;
     gAtomics_exchange = Atomics.exchange;
@@ -455,17 +467,16 @@ function runTests() {
     gAtomics_add = Atomics.add;
     gAtomics_sub = Atomics.sub;
     gAtomics_and = Atomics.and;
     gAtomics_or = Atomics.or;
     gAtomics_xor = Atomics.xor;
 
     CLONE(testFunction)(new Int8Array(sab), 0, 42, 4095);
     CLONE(testFunction)(new Uint8Array(sab), 0, 42, 4095);
-    CLONE(testFunction)(new Uint8ClampedArray(sab), 0, 42, 4095);
     CLONE(testFunction)(new Int16Array(sab), 0, 42, 2047);
     CLONE(testFunction)(new Uint16Array(sab), 0, 42, 2047);
     CLONE(testFunction)(new Int32Array(sab), 0, 42, 1023);
     CLONE(testFunction)(new Uint32Array(sab), 0, 42, 1023);
 
     // Test various range and type conditions
     var v8 = new Int8Array(sab);
     var v32 = new Int32Array(sab);
@@ -492,16 +503,19 @@ function runTests() {
     CLONE(testRangeCAS)(v32);
 
     // Test extreme values
     testInt8Extremes(new Int8Array(sab));
     testUint8Extremes(new Uint8Array(sab));
     testInt16Extremes(new Int16Array(sab));
     testUint32(new Uint32Array(sab));
 
+    // Test that Uint8ClampedArray is not accepted.
+    testUint8Clamped(sab);
+
     // Misc ad-hoc tests
     adHocExchange();
 
     // Misc
     testIsLockFree();
 }
 
 if (this.Atomics && this.SharedArrayBuffer)
--- a/js/src/jit/ExecutableAllocator.h
+++ b/js/src/jit/ExecutableAllocator.h
@@ -403,17 +403,33 @@ class ExecutableAllocator
 #elif defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS32) || defined(JS_SIMULATOR_MIPS64)
     static void cacheFlush(void* code, size_t size)
     {
         js::jit::Simulator::FlushICache(code, size);
     }
 #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
     static void cacheFlush(void* code, size_t size)
     {
-#if defined(__GNUC__)
+#if defined(_MIPS_ARCH_LOONGSON3A)
+        // On Loongson3-CPUs, The cache flushed automatically
+        // by hardware. Just need to execute an instruction hazard.
+        uintptr_t tmp;
+        asm volatile (
+            ".set   push \n"
+            ".set   noreorder \n"
+            "move   %[tmp], $ra \n"
+            "bal    1f \n"
+            "daddiu $ra, 8 \n"
+            "1: \n"
+            "jr.hb  $ra \n"
+            "move   $ra, %[tmp] \n"
+            ".set   pop\n"
+            :[tmp]"=&r"(tmp)
+        );
+#elif defined(__GNUC__)
         intptr_t end = reinterpret_cast<intptr_t>(code) + size;
         __builtin___clear_cache(reinterpret_cast<char*>(code), reinterpret_cast<char*>(end));
 #else
         _flush_cache(reinterpret_cast<char*>(code), size, BCACHE);
 #endif
     }
 #elif defined(JS_CODEGEN_ARM) && (defined(__FreeBSD__) || defined(__NetBSD__))
     static void cacheFlush(void* code, size_t size)
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -2970,17 +2970,17 @@ IonBuilder::atomicsMeetsPreconditions(Ca
       case Scalar::Int32:
         return checkResult == DontCheckAtomicResult || getInlineReturnType() == MIRType_Int32;
       case Scalar::Uint32:
         // Bug 1077305: it would be attractive to allow inlining even
         // if the inline return type is Int32, which it will frequently
         // be.
         return checkResult == DontCheckAtomicResult || getInlineReturnType() == MIRType_Double;
       default:
-        // Excludes floating types and Uint8Clamped
+        // Excludes floating types and Uint8Clamped.
         return false;
     }
 }
 
 void
 IonBuilder::atomicsCheckBounds(CallInfo& callInfo, MInstruction** elements, MDefinition** index)
 {
     // Perform bounds checking and extract the elements vector.
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -13190,18 +13190,17 @@ class MCompareExchangeTypedArrayElement
     static MCompareExchangeTypedArrayElement* New(TempAllocator& alloc, MDefinition* elements,
                                                   MDefinition* index, Scalar::Type arrayType,
                                                   MDefinition* oldval, MDefinition* newval)
     {
         return new(alloc) MCompareExchangeTypedArrayElement(elements, index, arrayType, oldval, newval);
     }
     bool isByteArray() const {
         return (arrayType_ == Scalar::Int8 ||
-                arrayType_ == Scalar::Uint8 ||
-                arrayType_ == Scalar::Uint8Clamped);
+                arrayType_ == Scalar::Uint8);
     }
     MDefinition* elements() {
         return getOperand(0);
     }
     MDefinition* index() {
         return getOperand(1);
     }
     MDefinition* oldval() {
@@ -13245,18 +13244,17 @@ class MAtomicExchangeTypedArrayElement
                                                  MDefinition* index, MDefinition* value,
                                                  Scalar::Type arrayType)
     {
         return new(alloc) MAtomicExchangeTypedArrayElement(elements, index, value, arrayType);
     }
 
     bool isByteArray() const {
         return (arrayType_ == Scalar::Int8 ||
-                arrayType_ == Scalar::Uint8 ||
-                arrayType_ == Scalar::Uint8Clamped);
+                arrayType_ == Scalar::Uint8);
     }
     MDefinition* elements() {
         return getOperand(0);
     }
     MDefinition* index() {
         return getOperand(1);
     }
     MDefinition* value() {
@@ -13297,18 +13295,17 @@ class MAtomicTypedArrayElementBinop
                                               MDefinition* elements, MDefinition* index,
                                               Scalar::Type arrayType, MDefinition* value)
     {
         return new(alloc) MAtomicTypedArrayElementBinop(op, elements, index, arrayType, value);
     }
 
     bool isByteArray() const {
         return (arrayType_ == Scalar::Int8 ||
-                arrayType_ == Scalar::Uint8 ||
-                arrayType_ == Scalar::Uint8Clamped);
+                arrayType_ == Scalar::Uint8);
     }
     AtomicOp operation() const {
         return op_;
     }
     Scalar::Type arrayType() const {
         return arrayType_;
     }
     MDefinition* elements() {
--- a/js/src/jit/arm/CodeGenerator-arm.cpp
+++ b/js/src/jit/arm/CodeGenerator-arm.cpp
@@ -1737,17 +1737,16 @@ template<typename S, typename T>
 void
 CodeGeneratorARM::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType,
                                              const S& value, const T& mem, Register flagTemp,
                                              Register outTemp, AnyRegister output)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
     MOZ_ASSERT_IF(arrayType == Scalar::Uint32, outTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicFetchAdd8SignExtend(value, mem, flagTemp, output.gpr());
             break;
           case AtomicFetchSubOp:
             masm.atomicFetchSub8SignExtend(value, mem, flagTemp, output.gpr());
@@ -1903,17 +1902,16 @@ CodeGeneratorARM::atomicBinopToTypedIntA
 // Binary operation for effect, result discarded.
 template<typename S, typename T>
 void
 CodeGeneratorARM::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                              const T& mem, Register flagTemp)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
       case Scalar::Uint8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicAdd8(value, mem, flagTemp);
             break;
           case AtomicFetchSubOp:
--- a/js/src/jit/arm/MacroAssembler-arm.cpp
+++ b/js/src/jit/arm/MacroAssembler-arm.cpp
@@ -4823,19 +4823,16 @@ MacroAssemblerARMCompat::compareExchange
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, output.gpr());
@@ -4868,19 +4865,16 @@ MacroAssemblerARMCompat::atomicExchangeT
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, output.gpr());
--- a/js/src/jit/arm64/MacroAssembler-arm64.cpp
+++ b/js/src/jit/arm64/MacroAssembler-arm64.cpp
@@ -268,19 +268,16 @@ MacroAssemblerCompat::compareExchangeToT
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, output.gpr());
@@ -313,19 +310,16 @@ MacroAssemblerCompat::atomicExchangeToTy
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, output.gpr());
--- a/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
+++ b/js/src/jit/mips-shared/CodeGenerator-mips-shared.cpp
@@ -2037,17 +2037,16 @@ CodeGeneratorMIPSShared::atomicBinopToTy
                                                     const S& value, const T& mem, Register flagTemp,
                                                     Register outTemp, Register valueTemp,
                                                     Register offsetTemp, Register maskTemp,
                                                     AnyRegister output)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
     MOZ_ASSERT_IF(arrayType == Scalar::Uint32, outTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicFetchAdd8SignExtend(value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output.gpr());
             break;
           case AtomicFetchSubOp:
             masm.atomicFetchSub8SignExtend(value, mem, flagTemp, valueTemp, offsetTemp, maskTemp, output.gpr());
@@ -2208,17 +2207,16 @@ CodeGeneratorMIPSShared::atomicBinopToTy
 template<typename S, typename T>
 void
 CodeGeneratorMIPSShared::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                                     const T& mem, Register flagTemp, Register valueTemp,
                                                     Register offsetTemp, Register maskTemp)
 {
     MOZ_ASSERT(flagTemp != InvalidReg);
 
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
       case Scalar::Uint8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicAdd8(value, mem, flagTemp, valueTemp, offsetTemp, maskTemp);
             break;
           case AtomicFetchSubOp:
--- a/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
+++ b/js/src/jit/mips-shared/MacroAssembler-mips-shared.cpp
@@ -1146,18 +1146,19 @@ MacroAssembler::callWithPatch()
     addLongJump(nextOffset());
     ma_liPatchable(ScratchRegister, ImmWord(0));
     return call(ScratchRegister);
 }
 
 void
 MacroAssembler::patchCall(uint32_t callerOffset, uint32_t calleeOffset)
 {
-    BufferOffset li(callerOffset - 6 * sizeof(uint32_t));
-    Assembler::UpdateLoad64Value(editSrc(li), calleeOffset);
+    BufferOffset li(callerOffset - Assembler::PatchWrite_NearCallSize());
+    Assembler::PatchInstructionImmediate((uint8_t*)editSrc(li),
+                                         PatchedImmPtr((const void*)calleeOffset));
 }
 
 void
 MacroAssembler::call(wasm::SymbolicAddress target)
 {
     movePtr(target, CallReg);
     call(CallReg);
 }
--- a/js/src/jit/mips32/MacroAssembler-mips32.cpp
+++ b/js/src/jit/mips32/MacroAssembler-mips32.cpp
@@ -2432,19 +2432,16 @@ MacroAssemblerMIPSCompat::compareExchang
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
@@ -2481,19 +2478,16 @@ MacroAssemblerMIPSCompat::atomicExchange
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
--- a/js/src/jit/mips64/Assembler-mips64.cpp
+++ b/js/src/jit/mips64/Assembler-mips64.cpp
@@ -269,31 +269,32 @@ Assembler::bind(InstImm* inst, uintptr_t
         addLongJump(BufferOffset(branch));
         Assembler::WriteLoad64Instructions(inst, ScratchRegister, target);
         inst[4] = InstReg(op_special, ScratchRegister, zero, ra, ff_jalr).encode();
         // There is 1 nop after this.
         return;
     }
 
     if (BOffImm16::IsInRange(offset)) {
+#ifdef _MIPS_ARCH_LOONGSON3A
+        // Don't skip trailing nops can imporve performance
+        // on Loongson3 platform.
+        bool skipNops = false;
+#else
+        bool skipNops = (inst[0].encode() != inst_bgezal.encode() &&
+                         inst[0].encode() != inst_beq.encode());
+#endif
+
         inst[0].setBOffImm16(BOffImm16(offset));
         inst[1].makeNop();
 
-        // Don't skip trailing nops can imporve performance
-        // on Loongson3 platform.
-#ifndef _MIPS_ARCH_LOONGSON3A
-        bool conditional = (inst[0].encode() != inst_bgezal.encode() &&
-                            inst[0].encode() != inst_beq.encode());
-
-        // Skip the trailing nops in conditional branches.
-        if (conditional) {
+        if (skipNops) {
             inst[2] = InstImm(op_regimm, zero, rt_bgez, BOffImm16(5 * sizeof(uint32_t))).encode();
             // There are 4 nops after this
         }
-#endif
         return;
     }
 
     if (inst[0].encode() == inst_beq.encode()) {
         // Handle long unconditional jump.
         addLongJump(BufferOffset(branch));
         Assembler::WriteLoad64Instructions(inst, ScratchRegister, target);
         inst[4] = InstReg(op_special, ScratchRegister, zero, zero, ff_jr).encode();
--- a/js/src/jit/mips64/MacroAssembler-mips64.cpp
+++ b/js/src/jit/mips64/MacroAssembler-mips64.cpp
@@ -2535,19 +2535,16 @@ MacroAssemblerMIPS64Compat::compareExcha
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, valueTemp, offsetTemp, maskTemp, output.gpr());
@@ -2584,19 +2581,16 @@ MacroAssemblerMIPS64Compat::atomicExchan
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, valueTemp, offsetTemp, maskTemp, output.gpr());
--- a/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
+++ b/js/src/jit/x86-shared/CodeGenerator-x86-shared.cpp
@@ -3361,17 +3361,16 @@ CodeGeneratorX86Shared::visitAtomicExcha
     }
 }
 
 template<typename S, typename T>
 void
 CodeGeneratorX86Shared::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                                    const T& mem, Register temp1, Register temp2, AnyRegister output)
 {
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicFetchAdd8SignExtend(value, mem, temp1, output.gpr());
             break;
           case AtomicFetchSubOp:
             masm.atomicFetchSub8SignExtend(value, mem, temp1, output.gpr());
@@ -3521,17 +3520,16 @@ CodeGeneratorX86Shared::atomicBinopToTyp
                                                     Register temp1, Register temp2, AnyRegister output);
 
 // Binary operation for effect, result discarded.
 template<typename S, typename T>
 void
 CodeGeneratorX86Shared::atomicBinopToTypedIntArray(AtomicOp op, Scalar::Type arrayType, const S& value,
                                                     const T& mem)
 {
-    // Uint8Clamped is explicitly not supported here
     switch (arrayType) {
       case Scalar::Int8:
       case Scalar::Uint8:
         switch (op) {
           case AtomicFetchAddOp:
             masm.atomicAdd8(value, mem);
             break;
           case AtomicFetchSubOp:
--- a/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
+++ b/js/src/jit/x86-shared/MacroAssembler-x86-shared.cpp
@@ -151,19 +151,16 @@ MacroAssemblerX86Shared::compareExchange
 {
     switch (arrayType) {
       case Scalar::Int8:
         compareExchange8SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint8:
         compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        compareExchange8ZeroExtend(mem, oldval, newval, output.gpr());
-        break;
       case Scalar::Int16:
         compareExchange16SignExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Uint16:
         compareExchange16ZeroExtend(mem, oldval, newval, output.gpr());
         break;
       case Scalar::Int32:
         compareExchange32(mem, oldval, newval, output.gpr());
@@ -196,19 +193,16 @@ MacroAssemblerX86Shared::atomicExchangeT
 {
     switch (arrayType) {
       case Scalar::Int8:
         atomicExchange8SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint8:
         atomicExchange8ZeroExtend(mem, value, output.gpr());
         break;
-      case Scalar::Uint8Clamped:
-        atomicExchange8ZeroExtend(mem, value, output.gpr());
-        break;
       case Scalar::Int16:
         atomicExchange16SignExtend(mem, value, output.gpr());
         break;
       case Scalar::Uint16:
         atomicExchange16ZeroExtend(mem, value, output.gpr());
         break;
       case Scalar::Int32:
         atomicExchange32(mem, value, output.gpr());
--- a/js/src/make-source-package.sh
+++ b/js/src/make-source-package.sh
@@ -8,21 +8,21 @@ set -e
 : ${MAKE:=make}
 : ${MKDIR:=mkdir}
 : ${TAR:=tar}
 : ${SRCDIR:=$(cd $(dirname $0); pwd 2>/dev/null)}
 : ${MOZJS_NAME:=mozjs}
 : ${DIST:=/tmp/mozjs-src-pkg}
 
 if [[ -f "$SRCDIR/../../config/milestone.txt" ]]; then
-    MILESTONE="$(tail -1 $SRCDIR/../../config/milestone.txt)"
-    IFS=. read -a VERSION < <(echo "$MILESTONE")
-    MOZJS_MAJOR_VERSION=${MOZJS_MAJOR_VERSION:-${VERSION[0]}}
-    MOZJS_MINOR_VERSION=${MOZJS_MINOR_VERSION:-${VERSION[1]}}
-    MOZJS_PATCH_VERSION=${MOZJS_PATCH_VERSION:-${VERSION[2]}}
+	MILESTONE="$(tail -1 $SRCDIR/../../config/milestone.txt)"
+	IFS=. read -a VERSION < <(echo "$MILESTONE")
+	MOZJS_MAJOR_VERSION=${MOZJS_MAJOR_VERSION:-${VERSION[0]}}
+	MOZJS_MINOR_VERSION=${MOZJS_MINOR_VERSION:-${VERSION[1]}}
+	MOZJS_PATCH_VERSION=${MOZJS_PATCH_VERSION:-${VERSION[2]}}
 fi
 
 cmd=${1:-build}
 pkg="${MOZJS_NAME}-${MOZJS_MAJOR_VERSION}.${MOZJS_MINOR_VERSION}.${MOZJS_PATCH_VERSION:-${MOZJS_ALPHA:-0}}.tar.bz2"
 pkgpath=${pkg%.tar*}
 tgtpath=${DIST}/${pkgpath}
 taropts="-jcf"
 
@@ -43,97 +43,106 @@ echo ""
 TOPSRCDIR=${SRCDIR}/../..
 
 case $cmd in
 "clean")
 	echo "Cleaning ${pkg} and ${tgtpath} ..."
 	rm -rf ${pkg} ${tgtpath}
 	;;
 "build")
-        echo -n "Press enter to build $pkg> "
-        read
+	echo -n "Press enter to build $pkg> "
+	read
 
-        # Ensure that the configure script is newer than the configure.in script.
-        if [ ${SRCDIR}/configure.in -nt ${SRCDIR}/configure ]; then
-            echo "error: js/src/configure is out of date. Please regenerate before packaging." >&2
-            exit 1
-        fi
+	# Ensure that the configure script is newer than the configure.in script.
+	if [ ${SRCDIR}/configure.in -nt ${SRCDIR}/configure ]; then
+		echo "error: js/src/configure is out of date. Please regenerate before packaging." >&2
+		exit 1
+	fi
 
 	echo "Packaging source tarball ${pkg}..."
 	if [ -d ${tgtpath} ]; then
 		echo "WARNING - dist tree ${tgtpath} already exists!"
 	fi
 	${MKDIR} -p ${tgtpath}/js/src
 
 	# copy the embedded icu
 	${MKDIR} -p ${tgtpath}/intl
-	cp -t ${tgtpath}/intl -dRp ${TOPSRCDIR}/intl/icu
+	cp -pPR ${TOPSRCDIR}/intl/icu ${tgtpath}/intl
 
 	# copy main moz.build and Makefile.in
-	cp -t ${tgtpath} -dRp ${TOPSRCDIR}/Makefile.in ${TOPSRCDIR}/moz.build
+	cp -pPR ${TOPSRCDIR}/Makefile.in ${TOPSRCDIR}/moz.build ${tgtpath}
 
-        # copy nspr.
-        cp -t ${tgtpath} -dRP ${SRCDIR}/../../nsprpub
+	# copy nspr.
+	cp -pPR ${SRCDIR}/../../nsprpub ${tgtpath}
 
 	# copy build and config directory.
-	cp -t ${tgtpath} -dRp ${TOPSRCDIR}/build ${TOPSRCDIR}/config
+	cp -pPR ${TOPSRCDIR}/build ${TOPSRCDIR}/config ${tgtpath}
 
 	# put in js itself
-	cp -t ${tgtpath} -dRp ${TOPSRCDIR}/mfbt
-	cp -t ${tgtpath}/js -dRp ${SRCDIR}/../public
+	cp -pPR ${TOPSRCDIR}/mfbt ${tgtpath}
+	cp -pPR ${SRCDIR}/../public ${tgtpath}/js
 	find ${SRCDIR} -mindepth 1 -maxdepth 1 -not -path ${DIST} -a -not -name ${pkg} \
-		-exec cp -t ${tgtpath}/js/src -dRp {} +
+		-exec cp -pPR {} ${tgtpath}/js/src \;
 
 	# distclean if necessary
 	if [ -e ${tgtpath}/js/src/Makefile ]; then
 		${MAKE} -C ${tgtpath}/js/src distclean
 	fi
 
-	cp -t ${tgtpath} -dRp \
-		${TOPSRCDIR}/python
+	cp -pPR \
+		${TOPSRCDIR}/python \
+		${tgtpath}
 	${MKDIR} -p ${tgtpath}/dom/bindings
-	cp -t ${tgtpath}/dom/bindings -dRp \
-		${TOPSRCDIR}/dom/bindings/mozwebidlcodegen
+	cp -pPR \
+		${TOPSRCDIR}/dom/bindings/mozwebidlcodegen \
+		${tgtpath}/dom/bindings
 	${MKDIR} -p ${tgtpath}/media/webrtc/trunk/tools
-	cp -t ${tgtpath}/media/webrtc/trunk/tools -dRp \
-		${TOPSRCDIR}/media/webrtc/trunk/tools/gyp
+	cp -pPR \
+		${TOPSRCDIR}/media/webrtc/trunk/tools/gyp \
+		${tgtpath}/media/webrtc/trunk/tools
 	${MKDIR} -p ${tgtpath}/testing
-	cp -t ${tgtpath}/testing -dRp \
-		${TOPSRCDIR}/testing/mozbase
+	cp -pPR \
+		${TOPSRCDIR}/testing/mozbase \
+		${tgtpath}/testing
 	${MKDIR} -p ${tgtpath}/modules
-	cp -t ${tgtpath}/modules -dRp \
-		${TOPSRCDIR}/modules/zlib/src
+	cp -pPR \
+		${TOPSRCDIR}/modules/zlib/src \
+		${tgtpath}/modules
 	${MKDIR} -p ${tgtpath}/layout/tools/reftest
-	cp -t ${tgtpath}/layout/tools/reftest -dRp \
-	        ${TOPSRCDIR}/layout/tools/reftest/reftest
+	cp -pPR \
+		${TOPSRCDIR}/layout/tools/reftest/reftest \
+		${tgtpath}/layout/tools/reftest
 	${MKDIR} -p ${tgtpath}/toolkit/mozapps/installer
-	cp -t ${tgtpath}/toolkit/mozapps/installer -dRp \
-	        ${TOPSRCDIR}/toolkit/mozapps/installer/package-name.mk \
-	        ${TOPSRCDIR}/toolkit/mozapps/installer/upload-files.mk
+	cp -pPR \
+		${TOPSRCDIR}/toolkit/mozapps/installer/package-name.mk \
+		${TOPSRCDIR}/toolkit/mozapps/installer/upload-files.mk \
+		${tgtpath}/toolkit/mozapps/installer
 	${MKDIR} -p ${tgtpath}/mozglue
-	cp -t ${tgtpath}/mozglue -dRp \
-	        ${TOPSRCDIR}/mozglue/build \
-	        ${TOPSRCDIR}/mozglue/crt \
-	        ${TOPSRCDIR}/mozglue/misc \
-	        ${TOPSRCDIR}/mozglue/moz.build
-        ${MKDIR} -p ${tgtpath}/memory
-        cp -t ${tgtpath}/memory -dRp \
-                ${TOPSRCDIR}/memory/moz.build \
-                ${TOPSRCDIR}/memory/build \
-                ${TOPSRCDIR}/memory/fallible \
-                ${TOPSRCDIR}/memory/jemalloc \
-                ${TOPSRCDIR}/memory/mozalloc \
-                ${TOPSRCDIR}/memory/mozjemalloc
+	cp -pPR \
+		${TOPSRCDIR}/mozglue/build \
+		${TOPSRCDIR}/mozglue/crt \
+		${TOPSRCDIR}/mozglue/misc \
+		${TOPSRCDIR}/mozglue/moz.build \
+		${tgtpath}/mozglue
+	${MKDIR} -p ${tgtpath}/memory
+	cp -pPR \
+		${TOPSRCDIR}/memory/moz.build \
+		${TOPSRCDIR}/memory/build \
+		${TOPSRCDIR}/memory/fallible \
+		${TOPSRCDIR}/memory/jemalloc \
+		${TOPSRCDIR}/memory/mozalloc \
+		${TOPSRCDIR}/memory/mozjemalloc \
+		${tgtpath}/memory
 
 	# remove *.pyc and *.pyo files if any
 	find ${tgtpath} -type f -name "*.pyc" -o -name "*.pyo" |xargs rm -f
 
 	# copy or create INSTALL
 	if [ -e ${DIST}/INSTALL ]; then
-		cp -t ${tgtpath} ${DIST}/INSTALL
+		cp ${DIST}/INSTALL ${tgtpath}
 	else
 		cat <<INSTALL_EOF >${tgtpath}/INSTALL
 Full build documentation for SpiderMonkey is hosted on MDN:
   https://developer.mozilla.org/en-US/docs/SpiderMonkey/Build_Documentation
 
 Note that the libraries produced by the build system include symbols,
 causing the binaries to be extremely large. It is highly suggested that \`strip\`
 be run over the binaries before deploying them.
@@ -144,17 +153,17 @@ Building with default options may be per
   cd obj
   ../configure
   make # or mozmake on Windows
 INSTALL_EOF
 	fi
 
 	# copy or create README
 	if [ -e ${DIST}/README ]; then
-		cp -t ${tgtpath} ${DIST}/README
+		cp ${DIST}/README ${tgtpath}
 	else
 		cat <<README_EOF >${tgtpath}/README
 This directory contains SpiderMonkey ${MOZJS_MAJOR_VERSION}.
 
 This release is based on a revision of Mozilla ${MOZJS_MAJOR_VERSION}:
   http://hg.mozilla.org/releases/
 The changes in the patches/ directory were applied.
 
@@ -167,19 +176,19 @@ README_EOF
 	if [ -e ${TOPSRCDIR}/b2g/LICENSE ]; then
 		cp ${TOPSRCDIR}/b2g/LICENSE ${tgtpath}/
 	else
 		cp ${TOPSRCDIR}/LICENSE ${tgtpath}/
 	fi
 
 	# copy patches dir, if it currently exists in DIST
 	if [ -d ${DIST}/patches ]; then
-		cp -t ${tgtpath} -dRp ${DIST}/patches
+		cp -pPR ${DIST}/patches ${tgtpath}
 	elif [ -d ${TOPSRCDIR}/patches ]; then
-		cp -t ${tgtpath} -dRp ${TOPSRCDIR}/patches
+		cp -pPR ${TOPSRCDIR}/patches ${tgtpath}
 	fi
 
 	# Roll the tarball
 	${TAR} $taropts ${DIST}/../${pkg} -C ${DIST} ${pkgpath}
 	echo "Wrote $(cd ${DIST}/..; echo $PWD)/${pkg}"
 	;;
 *)
 	echo "Unrecognized command: $cmd"
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -662,16 +662,17 @@ if CONFIG['OS_ARCH'] == 'SunOS':
         'posix4',
         'dl',
         'nsl',
         'socket',
     ]
 
 CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
 CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
 
 if not CONFIG['GNU_CXX']:
     ALLOW_COMPILER_WARNINGS = True
 
 NO_EXPAND_LIBS = True
 
 DIST_INSTALL = True
 
--- a/js/src/tests/js1_8_5/extensions/sharedtypedarray.js
+++ b/js/src/tests/js1_8_5/extensions/sharedtypedarray.js
@@ -186,15 +186,49 @@ function testClone2() {
     var ia2 = deserialize(blob);
     assertEq(ia1.length, ia2.length);
     assertEq(ia1.buffer instanceof SharedArrayBuffer, true);
     assertEq(sharedAddress(ia1.buffer), sharedAddress(ia2.buffer));
     ia1[10] = 37;
     assertEq(ia2[10], 37);
 }
 
+function testApplicable() {
+    var sab = b;
+    var x;
+
+    // Just make sure we can create all the view types on shared memory.
+
+    x = new Int32Array(sab);
+    assertEq(x.length, sab.byteLength / Int32Array.BYTES_PER_ELEMENT);
+    x = new Uint32Array(sab);
+    assertEq(x.length, sab.byteLength / Uint32Array.BYTES_PER_ELEMENT);
+
+    x = new Int16Array(sab);
+    assertEq(x.length, sab.byteLength / Int16Array.BYTES_PER_ELEMENT);
+    x = new Uint16Array(sab);
+    assertEq(x.length, sab.byteLength / Uint16Array.BYTES_PER_ELEMENT);
+
+    x = new Int8Array(sab);
+    assertEq(x.length, sab.byteLength / Int8Array.BYTES_PER_ELEMENT);
+    x = new Uint8Array(sab);
+    assertEq(x.length, sab.byteLength / Uint8Array.BYTES_PER_ELEMENT);
+
+    // Though the atomic operations are illegal on Uint8ClampedArray and the
+    // float arrays, they can still be used to create views on shared memory.
+
+    x = new Uint8ClampedArray(sab);
+    assertEq(x.length, sab.byteLength / Uint8ClampedArray.BYTES_PER_ELEMENT);
+
+    x = new Float32Array(sab);
+    assertEq(x.length, sab.byteLength / Float32Array.BYTES_PER_ELEMENT);
+    x = new Float64Array(sab);
+    assertEq(x.length, sab.byteLength / Float64Array.BYTES_PER_ELEMENT);
+}
+
 testSharedArrayBuffer();
 testSharedTypedArray();
 testSharedTypedArrayMethods();
 testClone1();
 testClone2();
+testApplicable();
 
 reportCompare(0, 0, 'ok');
--- a/layout/forms/moz.build
+++ b/layout/forms/moz.build
@@ -52,8 +52,9 @@ LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/html',
 ]
 
 if CONFIG['ENABLE_INTL_API']:
     # nsNumberControlFrame.cpp requires ICUUtils.h which in turn requires
     # i18n/unum.h
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
--- a/media/gmp-clearkey/0.1/ClearKeySession.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeySession.cpp
@@ -64,16 +64,21 @@ ClearKeySession::Init(uint32_t aCreateSe
   } else if (aInitDataType == "keyids") {
     std::string sessionType;
     ClearKeyUtils::ParseKeyIdsInitData(aInitData, aInitDataSize, mKeyIds, sessionType);
     if (sessionType != ClearKeyUtils::SessionTypeToString(mSessionType)) {
       const char message[] = "Session type specified in keyids init data doesn't match session type.";
       mCallback->RejectPromise(aPromiseId, kGMPAbortError, message, strlen(message));
       return;
     }
+  } else if (aInitDataType == "webm" && aInitDataSize == 16) {
+    // "webm" initData format is simply the raw bytes of the keyId.
+    vector<uint8_t> keyId;
+    keyId.assign(aInitData, aInitData+aInitDataSize);
+    mKeyIds.push_back(keyId);
   }
 
   if (!mKeyIds.size()) {
     const char message[] = "Couldn't parse init data";
     mCallback->RejectPromise(aPromiseId, kGMPAbortError, message, strlen(message));
     return;
   }
 
--- a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
+++ b/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp
@@ -97,20 +97,23 @@ ClearKeySessionManager::CreateSession(ui
                                       uint32_t aInitDataTypeSize,
                                       const uint8_t* aInitData,
                                       uint32_t aInitDataSize,
                                       GMPSessionType aSessionType)
 {
   CK_LOGD("ClearKeySessionManager::CreateSession type:%s", aInitDataType);
 
   string initDataType(aInitDataType, aInitDataType + aInitDataTypeSize);
-  // initDataType must be "cenc" or "keyids".
-  if (initDataType != "cenc" && initDataType != "keyids") {
+  // initDataType must be "cenc", "keyids", or "webm".
+  if (initDataType != "cenc" &&
+      initDataType != "keyids" &&
+      initDataType != "webm") {
+    string message = "'" + initDataType + "' is an initDataType unsupported by ClearKey";
     mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError,
-                             nullptr /* message */, 0 /* messageLen */);
+                             message.c_str(), message.size());
     return;
   }
 
   if (ClearKeyPersistence::DeferCreateSessionIfNotReady(this,
                                                         aCreateSessionToken,
                                                         aPromiseId,
                                                         initDataType,
                                                         aInitData,
--- a/media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.mm
+++ b/media/webrtc/trunk/webrtc/modules/video_capture/mac/qtkit/video_capture_qtkit.mm
@@ -56,18 +56,22 @@ VideoCaptureMacQTKit::~VideoCaptureMacQT
 {
 
     nsAutoreleasePool localPool;
     WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCapture, _id,
                  "~VideoCaptureMacQTKit() called");
     if(_captureDevice)
     {
         [_captureDevice registerOwner:nil];
-        [_captureDevice stopCapture];
-        [_captureDevice release];
+        [_captureDevice performSelectorOnMainThread:@selector(stopCapture)
+                        withObject:nil
+                        waitUntilDone:NO];
+        [_captureDevice performSelectorOnMainThread:@selector(release)
+                        withObject:nil
+                        waitUntilDone:NO];
     }
 
     if(_captureInfo)
     {
         [_captureInfo release];
     }
 }
 
--- a/memory/build/jemalloc_config.cpp
+++ b/memory/build/jemalloc_config.cpp
@@ -6,18 +6,22 @@
 
 #define MOZ_JEMALLOC_IMPL
 
 /* mozmemory_wrap.h needs to be included before MFBT headers */
 #include "mozmemory_wrap.h"
 #include <mozilla/Assertions.h>
 #include "mozilla/Types.h"
 
+#if defined(MOZ_NATIVE_JEMALLOC)
+#include MALLOC_H
+#else
 #define DLLEXPORT
 #include "jemalloc/jemalloc.h"
+#endif
 
 #ifdef XP_WIN
 #include <windows.h>
 #endif
 #ifdef XP_DARWIN
 #include <sys/mman.h>
 #endif
 
--- a/memory/build/mozjemalloc_compat.c
+++ b/memory/build/mozjemalloc_compat.c
@@ -10,26 +10,17 @@
 
 #include "mozmemory_wrap.h"
 #include "jemalloc_types.h"
 #include "mozilla/Types.h"
 
 #include <stdbool.h>
 
 #if defined(MOZ_NATIVE_JEMALLOC)
-
-MOZ_IMPORT_API int
-je_(mallctl)(const char*, void*, size_t*, void*, size_t);
-MOZ_IMPORT_API int
-je_(mallctlnametomib)(const char *name, size_t *mibp, size_t *miblenp);
-MOZ_IMPORT_API int
-je_(mallctlbymib)(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
-MOZ_IMPORT_API int
-je_(nallocx)(size_t size, int flags);
-
+#  include MALLOC_H
 #else
 #  include "jemalloc/jemalloc.h"
 #endif
 
 /*
  *  CTL_* macros are from memory/jemalloc/src/src/stats.c with changes:
  *  - drop `t' argument to avoid redundancy in calculating type size
  *  - require `i' argument for arena number explicitly
--- a/mobile/android/base/Tabs.java
+++ b/mobile/android/base/Tabs.java
@@ -26,16 +26,17 @@ import org.mozilla.gecko.util.GeckoEvent
 import org.mozilla.gecko.util.ThreadUtils;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
 import android.accounts.OnAccountsUpdateListener;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.database.sqlite.SQLiteException;
 import android.graphics.Color;
 import android.net.Uri;
 import android.os.Handler;
 import android.provider.Browser;
 import android.util.Log;
 import android.content.SharedPreferences;
 
 public class Tabs implements GeckoEventListener {
@@ -84,17 +85,21 @@ public class Tabs implements GeckoEventL
         public PersistTabsRunnable(final Context context, Iterable<Tab> tabsInOrder) {
             this.context = context;
             this.db = GeckoProfile.get(context).getDB();
             this.tabs = tabsInOrder;
         }
 
         @Override
         public void run() {
-            db.getTabsAccessor().persistLocalTabs(context.getContentResolver(), tabs);
+            try {
+                db.getTabsAccessor().persistLocalTabs(context.getContentResolver(), tabs);
+            } catch(SQLiteException e) {
+                Log.w(LOGTAG, "Error persisting local tabs", e);
+            }
         }
     };
 
     private Tabs() {
         EventDispatcher.getInstance().registerGeckoThreadListener(this,
             "Tab:Added",
             "Tab:Close",
             "Tab:Select",
--- a/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoProfile.java
+++ b/mobile/android/tests/browser/robocop/src/org/mozilla/gecko/tests/testGeckoProfile.java
@@ -246,16 +246,18 @@ public class testGeckoProfile extends Pi
             mAsserter.is(name, iniName, "Section with name found");
             mAsserter.is(dir.getName(), iniPath, "Section has correct path");
         }
 
         mAsserter.is(found, shouldFind, "Found profile where expected");
     }
 
     // Tries to remove a profile from Gecko profile. Verifies that it's removed from profiles.ini and its directory is deleted.
+    // TODO: Reconsider profile removal. Firefox would not normally remove a
+    // profile. Outstanding tasks may still try to access files in the profile.
     private void removeProfile(GeckoProfile profile, boolean inProfilesIni) {
         findInProfilesIni(profile, inProfilesIni);
         File dir = profile.getDir();
         mAsserter.ok(dir.exists(), "Profile dir exists before removing", dir.toString());
         mAsserter.is(inProfilesIni, GeckoProfile.removeProfile(getActivity(), profile.getName()), "Remove was successful");
         mAsserter.ok(!dir.exists(), "Profile dir was deleted when it was removed", dir.toString());
         findInProfilesIni(profile, false);
     }
--- a/netwerk/base/LoadInfo.cpp
+++ b/netwerk/base/LoadInfo.cpp
@@ -128,16 +128,17 @@ LoadInfo::LoadInfo(nsIPrincipal* aLoadin
                    bool aIsThirdPartyContext,
                    const NeckoOriginAttributes& aOriginAttributes,
                    nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChainIncludingInternalRedirects,
                    nsTArray<nsCOMPtr<nsIPrincipal>>& aRedirectChain)
   : mLoadingPrincipal(aLoadingPrincipal)
   , mTriggeringPrincipal(aTriggeringPrincipal)
   , mSecurityFlags(aSecurityFlags)
   , mInternalContentPolicyType(aContentPolicyType)
+  , mTainting(LoadTainting::Basic)
   , mUpgradeInsecureRequests(aUpgradeInsecureRequests)
   , mUpgradeInsecurePreloads(aUpgradeInsecurePreloads)
   , mInnerWindowID(aInnerWindowID)
   , mOuterWindowID(aOuterWindowID)
   , mParentOuterWindowID(aParentOuterWindowID)
   , mEnforceSecurity(aEnforceSecurity)
   , mInitialSecurityCheckDone(aInitialSecurityCheckDone)
   , mIsThirdPartyContext(aIsThirdPartyContext)
--- a/netwerk/dns/moz.build
+++ b/netwerk/dns/moz.build
@@ -68,13 +68,14 @@ LOCAL_INCLUDES += [
 
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] > '19':
     LOCAL_INCLUDES += ['%' + '%s/bionic/libc/dns/include' % CONFIG['ANDROID_SOURCE']]
 
 if CONFIG['ENABLE_INTL_API']:
     DEFINES['IDNA2008'] = True
     CXXFLAGS += CONFIG['MOZ_ICU_CFLAGS']
     CFLAGS += CONFIG['MOZ_ICU_CFLAGS']
+    LOCAL_INCLUDES += CONFIG['MOZ_ICU_INCLUDES']
     USE_LIBS += ['icu']
 else:
     UNIFIED_SOURCES += [
         'nameprep.c',
     ]
--- a/parser/htmlparser/nsExpatDriver.cpp
+++ b/parser/htmlparser/nsExpatDriver.cpp
@@ -24,16 +24,17 @@
 #include "nsIConsoleService.h"
 #include "nsIScriptError.h"
 #include "nsIContentPolicy.h"
 #include "nsContentPolicyUtils.h"
 #include "nsError.h"
 #include "nsXPCOMCIDInternal.h"
 #include "nsUnicharInputStream.h"
 #include "nsContentUtils.h"
+#include "nsNullPrincipal.h"
 
 #include "mozilla/Logging.h"
 
 using mozilla::LogLevel;
 
 #define kExpatSeparatorChar 0xFFFF
 
 static const char16_t kUTF16[] = { 'U', 'T', 'F', '-', '1', '6', '\0' };
@@ -784,24 +785,31 @@ nsExpatDriver::OpenInputStreamFromExtern
                        nsContentUtils::GetSystemPrincipal(),
                        nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
                        nsIContentPolicy::TYPE_DTD);
   }
   else {
     NS_ASSERTION(mSink == nsCOMPtr<nsIExpatSink>(do_QueryInterface(mOriginalSink)),
                  "In nsExpatDriver::OpenInputStreamFromExternalDTD: "
                  "mOriginalSink not the same object as mSink?");
-    nsCOMPtr<nsIDocument> doc;
+    nsCOMPtr<nsIPrincipal> loadingPrincipal;
     if (mOriginalSink) {
+      nsCOMPtr<nsIDocument> doc;
       doc = do_QueryInterface(mOriginalSink->GetTarget());
+      if (doc) {
+        loadingPrincipal = doc->NodePrincipal();
+      }
     }
-    NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
+    if (!loadingPrincipal) {
+      loadingPrincipal = nsNullPrincipal::Create();
+      NS_ENSURE_TRUE(loadingPrincipal, NS_ERROR_FAILURE);
+    }
     rv = NS_NewChannel(getter_AddRefs(channel),
                        uri,
-                       doc,
+                       loadingPrincipal,
                        nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS |
                        nsILoadInfo::SEC_ALLOW_CHROME,
                        nsIContentPolicy::TYPE_DTD);
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsAutoCString absURL;
   uri->GetSpec(absURL);
--- a/python/compare-locales/mach_commands.py
+++ b/python/compare-locales/mach_commands.py
@@ -9,17 +9,17 @@ from mach.decorators import (
     CommandProvider,
     Command,
 )
 
 from mozbuild.base import (
     MachCommandBase,
 )
 
-import mozpack
+import mozpack.path as mozpath
 
 
 MERGE_HELP = '''Directory to merge to. Will be removed to before running
 the comparison. Default: $(OBJDIR)/($MOZ_BUILD_APP)/locales/merge-$(AB_CD)
 '''.lstrip()
 
 
 @CommandProvider
--- a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp
+++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.cpp
@@ -56,22 +56,22 @@ LogBlocked(const char* aFunctionName, co
     // Skip an extra frame to allow for this function.
     LogBlocked(aFunctionName, base::WideToUTF8(aContext).c_str(),
                /* aFramesToSkip */ 3);
   }
 }
 
 void
 LogBlocked(const char* aFunctionName, const wchar_t* aContext,
-           uint16_t aLength)
+           uint16_t aLengthInBytes)
 {
   if (sLogFunction) {
     // Skip an extra frame to allow for this function.
     LogBlocked(aFunctionName,
-               base::WideToUTF8(std::wstring(aContext, aLength)).c_str(),
+               base::WideToUTF8(std::wstring(aContext, aLengthInBytes / sizeof(wchar_t))).c_str(),
                /* aFramesToSkip */ 3);
   }
 }
 
 void
 LogAllowed(const char* aFunctionName, const char* aContext)
 {
   if (sLogFunction) {
@@ -85,18 +85,18 @@ LogAllowed(const char* aFunctionName, co
 {
   if (sLogFunction) {
     LogAllowed(aFunctionName, base::WideToUTF8(aContext).c_str());
   }
 }
 
 void
 LogAllowed(const char* aFunctionName, const wchar_t* aContext,
-           uint16_t aLength)
+           uint16_t aLengthInBytes)
 {
   if (sLogFunction) {
     LogAllowed(aFunctionName,
-               base::WideToUTF8(std::wstring(aContext, aLength)).c_str());
+               base::WideToUTF8(std::wstring(aContext, aLengthInBytes / sizeof(wchar_t))).c_str());
   }
 }
 
 } // sandboxing
 } // mozilla
--- a/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h
+++ b/security/sandbox/chromium-shim/sandbox/win/sandboxLogging.h
@@ -38,23 +38,23 @@ void ApplyLoggingPolicy(sandbox::TargetP
 // will start from our caller's caller, which should normally be the function
 // that triggered the interception.
 void LogBlocked(const char* aFunctionName, const char* aContext = nullptr,
                 uint32_t aFramesToSkip = 2);
 
 // Convenience functions to convert to char*.
 void LogBlocked(const char* aFunctionName, const wchar_t* aContext);
 void LogBlocked(const char* aFunctionName, const wchar_t* aContext,
-                uint16_t aLength);
+                uint16_t aLengthInBytes);
 
 // Log a "ALLOWED" msg to the browser console and, if DEBUG build, stderr.
 void LogAllowed(const char* aFunctionName, const char* aContext = nullptr);
 
 // Convenience functions to convert to char*.
 void LogAllowed(const char* aFunctionName, const wchar_t* aContext);
 void LogAllowed(const char* aFunctionName, const wchar_t* aContext,
-                uint16_t aLength);
+                uint16_t aLengthInBytes);
 
 
 } // sandboxing
 } // mozilla
 
 #endif // security_sandbox_sandboxLogging_h__
--- a/services/fxaccounts/FxAccountsManager.jsm
+++ b/services/fxaccounts/FxAccountsManager.jsm
@@ -57,17 +57,18 @@ this.FxAccountsManager = {
   // We only expose the email and the verified status so far.
   get _user() {
     if (!this._activeSession || !this._activeSession.email) {
       return null;
     }
 
     return {
       email: this._activeSession.email,
-      verified: this._activeSession.verified
+      verified: this._activeSession.verified,
+      profile: this._activeSession.profile,
     }
   },
 
   _error: function(aError, aDetails) {
     log.error(aError);
     let reason = {
       error: aError
     };
@@ -160,22 +161,32 @@ this.FxAccountsManager = {
             // There is no way to obtain the key fetch token afterwards
             // without login out the user and asking her to log in again.
             // Also, key fetch tokens are designed to be short-lived, so
             // we need to fetch kB as soon as we have the key fetch token.
             if (aFetchKeys) {
               this._fxAccounts.getKeys();
             }
 
-            return Promise.resolve({
-              accountCreated: aMethod === "signUp",
-              user: this._user
+            return this._fxAccounts.getSignedInUserProfile().catch(error => {
+              // Not fetching the profile is sad but the FxA logs will already
+              // have noise.
+              return null;
             });
           }
-        );
+        ).then(profile => {
+          if (profile) {
+            this._activeSession.profile = profile;
+          }
+
+          return Promise.resolve({
+            accountCreated: aMethod === "signUp",
+            user: this._user
+          });
+        });
       },
       reason => { return this._serverError(reason); }
     );
   },
 
   /**
    * Determine whether the incoming error means that the current account
    * has new server-side state via deletion or password change, and if so,
@@ -415,20 +426,33 @@ this.FxAccountsManager = {
           return Promise.resolve(null);
         }
 
         this._activeSession = user;
         // If we get a stored information of a not yet verified account,
         // we kick off verification before returning what we have.
         if (!user.verified) {
           this.verificationStatus(user);
+          // Trying to get the profile for unverified users will fail, so we
+          // don't even try in that case.
+          log.debug("Account ", this._user);
+          return Promise.resolve(this._user);
         }
 
-        log.debug("Account " + JSON.stringify(this._user));
-        return Promise.resolve(this._user);
+        return this._fxAccounts.getSignedInUserProfile().then(profile => {
+          if (profile) {
+            this._activeSession.profile = profile;
+          }
+          log.debug("Account ", this._user);
+          return Promise.resolve(this._user);
+        }).catch(error => {
+          // FxAccounts logs already inform about the error.
+          log.debug("Account ", this._user);
+          return Promise.resolve(this._user);
+        });
       }
     );
   },
 
   queryAccount: function(aEmail) {
     log.debug("queryAccount " + aEmail);
     if (Services.io.offline) {
       return this._error(ERROR_OFFLINE);
@@ -481,16 +505,23 @@ this.FxAccountsManager = {
         let error = this._getError(data);
         if (error) {
           this._error(error, data);
         }
         // If the verification status has changed, update state.
         if (this._activeSession.verified != data.verified) {
           this._activeSession.verified = data.verified;
           this._fxAccounts.setSignedInUser(this._activeSession);
+          this._fxAccounts.getSignedInUserProfile().then(profile => {
+            if (profile) {
+              this._activeSession.profile = profile;
+            }
+          }).catch(error => {
+            // FxAccounts logs already inform about the error.
+          });
         }
         log.debug(JSON.stringify(this._user));
       },
       reason => { this._serverError(reason); }
     );
   },
 
   /*
--- a/services/fxaccounts/tests/xpcshell/test_manager.js
+++ b/services/fxaccounts/tests/xpcshell/test_manager.js
@@ -97,16 +97,17 @@ const kFxAccounts = fxAccounts;
 FxAccountsManager._fxAccounts = {
   _reject: false,
   _getSignedInUserCalled: false,
   _setSignedInUserCalled: false,
 
   _error: 'error',
   _assertion: 'assertion',
   _keys: 'keys',
+  _profile: 'aprofile',
   _signedInUser: null,
 
   _reset: function() {
     this._getSignedInUserCalled = false;
     this._setSignedInUserCalled = false;
     this._reject = false;
   },
 
@@ -135,16 +136,23 @@ FxAccountsManager._fxAccounts = {
   getSignedInUser: function() {
     this._getSignedInUserCalled = true;
     let deferred = Promise.defer();
     this._reject ? deferred.reject(this._error)
                  : deferred.resolve(this._signedInUser);
     return deferred.promise;
   },
 
+  getSignedInUserProfile: function() {
+    let deferred = Promise.defer();
+    this._reject ? deferred.reject(this._error)
+                 : deferred.resolve(this._profile);
+    return deferred.promise;
+  },
+
   getKeys: function() {
     let deferred = Promise.defer();
     this._reject ? deferred.reject(this._error)
                  : deferred.resolve(this._keys);
     return deferred.promise;
   },
 
   resendVerificationEmail: function() {
@@ -631,21 +639,23 @@ add_test(function(test_getAssertion_refr
     error => {
       do_throw("Unexpected error: " + error);
     }
   );
 });
 
 add_test(function(test_getAccount_existing_verified_session) {
   do_print("= getAccount, existing verified session =");
+  FxAccountsManager._activeSession = null;
   FxAccountsManager.getAccount().then(
     result => {
-      do_check_false(FxAccountsManager._fxAccounts._getSignedInUserCalled);
+      do_check_true(FxAccountsManager._fxAccounts._getSignedInUserCalled);
       do_check_eq(result.email, FxAccountsManager._user.email);
       do_check_eq(result.verified, FxAccountsManager._user.verified);
+      do_check_eq(result.profile, "aprofile");
       run_next_test();
     },
     error => {
       do_throw("Unexpected error: " + error);
     }
   );
 });
 
--- a/testing/mozharness/configs/mediatests/buildbot_posix_config.py
+++ b/testing/mozharness/configs/mediatests/buildbot_posix_config.py
@@ -36,20 +36,20 @@ config = {
          "https://blobupload.elasticbeanstalk.com",
     ],
     "blob_uploader_auth_file" : os.path.join(os.getcwd(), "oauth.txt"),
     "download_minidump_stackwalk": True,
     "download_symbols": "ondemand",
 
     "firefox_media_repo": 'https://github.com/mjzffr/firefox-media-tests.git',
     "firefox_media_branch": 'master',
-    "firefox_media_rev": 'b11d6c3d7f6af166be314d2ac6673e78c1edb566',
+    "firefox_media_rev": '49b500b30b80372a6c678ec7d0a2b074844f5e84',
     "firefox_ui_repo": 'https://github.com/mozilla/firefox-ui-tests.git',
     "firefox_ui_branch": 'mozilla-central',
-    "firefox_ui_rev": '6d6d57917f85399e903ac69b7e4297091b2d474c',
+    "firefox_ui_rev": '32be49d74e1d10c6bf087235b1d6753c1b840bc4',
 
     "suite_definitions": {
         "media-tests": {
             "options": [],
         },
         "media-youtube-tests": {
             "options": [
                 "%(test_manifest)s"
--- a/testing/mozharness/configs/mediatests/buildbot_windows_config.py
+++ b/testing/mozharness/configs/mediatests/buildbot_windows_config.py
@@ -47,20 +47,20 @@ config = {
     ],
     "blob_uploader_auth_file" : os.path.join(os.getcwd(), "oauth.txt"),
     "in_tree_config": "config/mozharness/marionette.py",
     "download_minidump_stackwalk": True,
     "download_symbols": "ondemand",
 
     "firefox_media_repo": 'https://github.com/mjzffr/firefox-media-tests.git',
     "firefox_media_branch": 'master',
-    "firefox_media_rev": 'b11d6c3d7f6af166be314d2ac6673e78c1edb566',
+    "firefox_media_rev": '49b500b30b80372a6c678ec7d0a2b074844f5e84',
     "firefox_ui_repo": 'https://github.com/mozilla/firefox-ui-tests.git',
     "firefox_ui_branch": 'mozilla-central',
-    "firefox_ui_rev": '6d6d57917f85399e903ac69b7e4297091b2d474c',
+    "firefox_ui_rev": '32be49d74e1d10c6bf087235b1d6753c1b840bc4',
 
     "suite_definitions": {
         "media-tests": {
             "options": [],
         },
         "media-youtube-tests": {
             "options": [
                 "%(test_manifest)s"
--- a/testing/mozharness/configs/merge_day/b2g_branch_repos.py
+++ b/testing/mozharness/configs/merge_day/b2g_branch_repos.py
@@ -21,16 +21,20 @@ config = {
         "android-sdk",
         "platform_external_wpa_supplicant_8",
         "platform_prebuilts_misc",
         "hardware_qcom_display",
         "device_generic_goldfish",
         "platform_frameworks_av",
         "platform_frameworks_base",
         "android-development",
+        "device-hammerhead",
+        "device_lge_hammerhead-kernel",
+        "platform_bionic",
+        "platform_build",
     ],
     "extra_branch_manifest_repos": [
         "gecko",
         "gaia",
     ],
     "branch_order": [
         "master",
     ],
--- a/testing/mozharness/mozharness/mozilla/testing/testbase.py
+++ b/testing/mozharness/mozharness/mozilla/testing/testbase.py
@@ -26,17 +26,21 @@ from mozharness.mozilla.proxxy import Pr
 from mozharness.mozilla.structuredlog import StructuredOutputParser
 from mozharness.mozilla.taskcluster_helper import TaskClusterArtifactFinderMixin
 from mozharness.mozilla.testing.unittest import DesktopUnittestOutputParser
 from mozharness.mozilla.testing.try_tools import TryToolsMixin, try_config_options
 from mozharness.mozilla.tooltool import TooltoolMixin
 
 from mozharness.lib.python.authentication import get_credentials
 
-INSTALLER_SUFFIXES = ('.tar.bz2', '.zip', '.dmg', '.exe', '.apk', '.tar.gz')
+INSTALLER_SUFFIXES = ('.apk',  # Android
+                      '.tar.bz2', '.tar.gz',  # Linux
+                      '.dmg',  # Mac
+                      '.installer-stub.exe', '.installer.exe', '.exe', '.zip',  # Windows
+                      )
 
 testing_config_options = [
     [["--installer-url"],
      {"action": "store",
      "dest": "installer_url",
      "default": None,
      "help": "URL to the installer to install",
       }],
--- a/toolkit/modules/AppConstants.jsm
+++ b/toolkit/modules/AppConstants.jsm
@@ -89,16 +89,23 @@ this.AppConstants = Object.freeze({
 
   MOZ_TELEMETRY_REPORTING:
 #ifdef MOZ_TELEMETRY_REPORTING
   true,
 #else
   false,
 #endif
 
+  MOZ_TELEMETRY_ON_BY_DEFAULT:
+#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
+  true,
+#else
+  false,
+#endif
+
   MOZ_SERVICES_CLOUDSYNC:
 #ifdef MOZ_SERVICES_CLOUDSYNC
   true,
 #else
   false,
 #endif
 
   MOZ_UPDATER:
@@ -193,30 +200,37 @@ this.AppConstants = Object.freeze({
 
   DEBUG:
 #ifdef DEBUG
   true,
 #else
   false,
 #endif
 
-  MOZ_B2G:
-#ifdef MOZ_B2G
+  MOZ_B2G_RIL:
+#ifdef MOZ_B2G_RIL
   true,
 #else
   false,
 #endif
 
   MOZ_B2GDROID:
 #ifdef MOZ_B2GDROID
   true,
 #else
   false,
 #endif
 
+  MOZ_GRAPHENE:
+#ifdef MOZ_GRAPHENE
+  true,
+#else
+  false,
+#endif
+
   MOZ_PLACES:
 #ifdef MOZ_PLACES
   true,
 #else
   false,
 #endif
 
   MOZ_ANDROID_HISTORY:
@@ -232,16 +246,18 @@ this.AppConstants = Object.freeze({
   MOZ_APP_NAME: "@MOZ_APP_NAME@",
   MOZ_APP_VERSION: "@MOZ_APP_VERSION@",
   MOZ_APP_VERSION_DISPLAY: "@MOZ_APP_VERSION_DISPLAY@",
   MOZ_BUILD_APP: "@MOZ_BUILD_APP@",
   MOZ_UPDATE_CHANNEL: "@MOZ_UPDATE_CHANNEL@",
   INSTALL_LOCALE: "@AB_CD@",
   MOZ_WIDGET_TOOLKIT: "@MOZ_WIDGET_TOOLKIT@",
   ANDROID_PACKAGE_NAME: "@ANDROID_PACKAGE_NAME@",
+  MOZ_B2G_VERSION: @MOZ_B2G_VERSION@,
+  MOZ_B2G_OS_NAME: @MOZ_B2G_OS_NAME@,
 
   MOZ_ANDROID_APZ:
 #ifdef MOZ_ANDROID_APZ
     true,
 #else
     false,
 #endif
   DEBUG_JS_MODULES: "@DEBUG_JS_MODULES@",
--- a/tools/mercurial/hgsetup/wizard.py
+++ b/tools/mercurial/hgsetup/wizard.py
@@ -518,17 +518,20 @@ class MercurialSetupWizard(object):
                 return
             print(name)
             print('=' * len(name))
             print('')
             if not self._prompt_yn(prompt_text):
                 print('')
                 return
         if not path:
-            path = os.path.join(self.vcs_tools_dir, 'hgext', name)
+            # We replace the user's home directory with ~ so the
+            # config file doesn't depend on the path to the home
+            # directory
+            path = os.path.join(self.vcs_tools_dir.replace(os.path.expanduser('~'), '~'), 'hgext', name)
         c.activate_extension(name, path)
         print('Activated %s extension.\n' % name)
 
     def _prompt(self, msg, allow_empty=False):
         print(msg)
 
         while True:
             response = raw_input().decode('utf-8')
--- a/tools/profiler/core/GeckoSampler.cpp
+++ b/tools/profiler/core/GeckoSampler.cpp
@@ -242,16 +242,18 @@ GeckoSampler::GeckoSampler(double aInter
     SetActiveSampler(this);
   }
 
 #ifdef MOZ_TASK_TRACER
   if (mTaskTracer) {
     mozilla::tasktracer::StartLogging();
   }
 #endif
+
+  mGatherer = new mozilla::ProfileGatherer(this);
 }
 
 GeckoSampler::~GeckoSampler()
 {
   if (IsActive())
     Stop();
 
   SetActiveSampler(nullptr);
@@ -274,16 +276,20 @@ GeckoSampler::~GeckoSampler()
         sRegisteredThreads->erase(sRegisteredThreads->begin() + i);
         i--;
       }
     }
   }
 #if defined(XP_WIN)
   delete mIntelPowerGadget;
 #endif
+
+  // Cancel any in-flight async profile gatherering
+  // requests
+  mGatherer->Cancel();
 }
 
 void GeckoSampler::HandleSaveRequest()
 {
   if (!mSaveRequested)
     return;
   mSaveRequested = false;
 
@@ -399,39 +405,41 @@ JSObject* GeckoSampler::ToJSObject(JSCon
   {
     UniquePtr<char[]> buf = ToJSON(aSinceTime);
     NS_ConvertUTF8toUTF16 js_string(nsDependentCString(buf.get()));
     MOZ_ALWAYS_TRUE(JS_ParseJSON(aCx, static_cast<const char16_t*>(js_string.get()),
                                  js_string.Length(), &val));
   }
   return &val.toObject();
 }
+
+void GeckoSampler::GetGatherer(nsISupports** aRetVal)
+{
+  if (!aRetVal || NS_WARN_IF(!mGatherer)) {
+    return;
+  }
+  NS_ADDREF(*aRetVal = mGatherer);
+}
 #endif
 
 UniquePtr<char[]> GeckoSampler::ToJSON(double aSinceTime)
 {
   SpliceableChunkedJSONWriter b;
   StreamJSON(b, aSinceTime);
   return b.WriteFunc()->CopyData();
 }
 
 void GeckoSampler::ToJSObjectAsync(double aSinceTime,
                                   mozilla::dom::Promise* aPromise)
 {
-  if (NS_WARN_IF(mGatherer)) {
+  if (NS_WARN_IF(!mGatherer)) {
     return;
   }
 
-  mGatherer = new mozilla::ProfileGatherer(this, aSinceTime, aPromise);
-  mGatherer->Start();
-}
-
-void GeckoSampler::ProfileGathered()
-{
-  mGatherer = nullptr;
+  mGatherer->Start(aSinceTime, aPromise);
 }
 
 struct SubprocessClosure {
   explicit SubprocessClosure(SpliceableJSONWriter* aWriter)
     : mWriter(aWriter)
   {}
 
   SpliceableJSONWriter* mWriter;
--- a/tools/profiler/core/GeckoSampler.h
+++ b/tools/profiler/core/GeckoSampler.h
@@ -99,16 +99,17 @@ class GeckoSampler: public Sampler {
     }
 
     return mPrimaryThreadProfile;
   }
 
   void ToStreamAsJSON(std::ostream& stream, double aSinceTime = 0);
 #ifndef SPS_STANDALONE
   virtual JSObject *ToJSObject(JSContext *aCx, double aSinceTime = 0);
+  void GetGatherer(nsISupports** aRetVal);
 #endif
   mozilla::UniquePtr<char[]> ToJSON(double aSinceTime = 0);
   virtual void ToJSObjectAsync(double aSinceTime = 0, mozilla::dom::Promise* aPromise = 0);
   void StreamMetaJSCustomObject(SpliceableJSONWriter& aWriter);
   void StreamTaskTracer(SpliceableJSONWriter& aWriter);
   void FlushOnJSShutdown(JSRuntime* aRuntime);
   bool ProfileJS() const { return mProfileJS; }
   bool ProfileJava() const { return mProfileJava; }
@@ -122,18 +123,16 @@ class GeckoSampler: public Sampler {
   bool LayersDump() const { return mLayersDump; }
   bool DisplayListDump() const { return mDisplayListDump; }
   bool ProfileRestyle() const { return mProfileRestyle; }
   const ThreadNameFilterList& ThreadNameFilters() { return mThreadNameFilters; }
   const FeatureList& Features() { return mFeatures; }
 
   void GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration);
 
-  void ProfileGathered();
-
 protected:
   // Called within a signal. This function must be reentrant
   virtual void InplaceTick(TickSample* sample);
 
   // Not implemented on platforms which do not support backtracing
   void doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample);
 
   void StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime);
--- a/tools/profiler/core/platform.cpp
+++ b/tools/profiler/core/platform.cpp
@@ -637,16 +637,36 @@ void mozilla_sampler_get_profiler_start_
 
   const FeatureList& featureList = t->Features();
   MOZ_ALWAYS_TRUE(aFeatures->resize(featureList.length()));
   for (size_t i = 0; i < featureList.length(); ++i) {
     (*aFeatures)[i] = featureList[i].c_str();
   }
 }
 
+void mozilla_sampler_get_gatherer(nsISupports** aRetVal)
+{
+  if (!aRetVal) {
+    return;
+  }
+
+  if (NS_WARN_IF(!profiler_is_active())) {
+    *aRetVal = nullptr;
+    return;
+  }
+
+  GeckoSampler *t = tlsTicker.get();
+  if (NS_WARN_IF(!t)) {
+    *aRetVal = nullptr;
+    return;
+  }
+
+  t->GetGatherer(aRetVal);
+}
+
 #endif
 
 void mozilla_sampler_save_profile_to_file(const char* aFilename)
 {
   GeckoSampler *t = tlsTicker.get();
   if (!t) {
     return;
   }
--- a/tools/profiler/gecko/ProfileGatherer.cpp
+++ b/tools/profiler/gecko/ProfileGatherer.cpp
@@ -7,32 +7,46 @@
 #include "nsIObserverService.h"
 #include "GeckoSampler.h"
 
 using mozilla::dom::AutoJSAPI;
 using mozilla::dom::Promise;
 
 namespace mozilla {
 
-NS_IMPL_ISUPPORTS0(ProfileGatherer)
+/**
+ * When a subprocess exits before we've gathered profiles, we'll
+ * store profiles for those processes until gathering starts. We'll
+ * only store up to MAX_SUBPROCESS_EXIT_PROFILES. The buffer is
+ * circular, so as soon as we receive another exit profile, we'll
+ * bump the oldest one out of the buffer.
+ */
+static const uint32_t MAX_SUBPROCESS_EXIT_PROFILES = 5;
 
-ProfileGatherer::ProfileGatherer(GeckoSampler* aTicker,
-                                 double aSinceTime,
-                                 Promise* aPromise)
-  : mPromise(aPromise)
-  , mTicker(aTicker)
-  , mSinceTime(aSinceTime)
+NS_IMPL_ISUPPORTS(ProfileGatherer, nsIObserver)
+
+ProfileGatherer::ProfileGatherer(GeckoSampler* aTicker)
+  : mTicker(aTicker)
+  , mSinceTime(0)
   , mPendingProfiles(0)
+  , mGathering(false)
 {
 }
 
 void
 ProfileGatherer::GatheredOOPProfile()
 {
   MOZ_ASSERT(NS_IsMainThread());
+  if (!mGathering) {
+    // If we're not actively gathering, then we don't actually
+    // care that we gathered a profile here. This can happen for
+    // processes that exit while profiling.
+    return;
+  }
+
   if (NS_WARN_IF(!mPromise)) {
     // If we're not holding on to a Promise, then someone is
     // calling us erroneously.
     return;
   }
 
   mPendingProfiles--;
 
@@ -45,44 +59,70 @@ ProfileGatherer::GatheredOOPProfile()
 
 void
 ProfileGatherer::WillGatherOOPProfile()
 {
   mPendingProfiles++;
 }
 
 void
-ProfileGatherer::Start()
+ProfileGatherer::Start(double aSinceTime,
+                       Promise* aPromise)
 {
   MOZ_ASSERT(NS_IsMainThread());
+  if (mGathering) {
+    // If we're already gathering, reject the promise - this isn't going
+    // to end well.
+    if (aPromise) {
+      aPromise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
+    }
+    return;
+  }
+
+  mSinceTime = aSinceTime;
+  mPromise = aPromise;
+  mGathering = true;
+  mPendingProfiles = 0;
 
   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   if (os) {
-    nsresult rv = os->NotifyObservers(this, "profiler-subprocess-gather", nullptr);
+    nsresult rv = os->AddObserver(this, "profiler-subprocess", false);
+    NS_WARN_IF(NS_FAILED(rv));
+    rv = os->NotifyObservers(this, "profiler-subprocess-gather", nullptr);
     NS_WARN_IF(NS_FAILED(rv));
   }
 
   if (!mPendingProfiles) {
     Finish();
   }
 }
 
 void
 ProfileGatherer::Finish()
 {
   MOZ_ASSERT(NS_IsMainThread());
+
+  if (!mTicker) {
+    // We somehow got called after we were cancelled! This shouldn't
+    // be possible, but doing a belt-and-suspenders check to be sure.
+    return;
+  }
+
   UniquePtr<char[]> buf = mTicker->ToJSON(mSinceTime);
 
+  nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
+  if (os) {
+    nsresult rv = os->RemoveObserver(this, "profiler-subprocess");
+    NS_WARN_IF(NS_FAILED(rv));
+  }
+
   AutoJSAPI jsapi;
   if (NS_WARN_IF(!jsapi.Init(mPromise->GlobalJSObject()))) {
     // We're really hosed if we can't get a JS context for some reason.
-    // We'll tell the GeckoSampler that we've gathered the profile just
-    // so that it can drop the reference to this ProfileGatherer and maybe
-    // the user can try again.
-    mTicker->ProfileGathered();
+    Reset();
     return;
   }
 
   JSContext* cx = jsapi.cx();
 
   // Now parse the JSON so that we resolve with a JS Object.
   JS::RootedValue val(cx);
   {
@@ -99,12 +139,68 @@ ProfileGatherer::Finish()
         jsapi.ClearException();
         mPromise->MaybeReject(cx, exn);
       }
     } else {
       mPromise->MaybeResolve(val);
     }
   }
 
-  mTicker->ProfileGathered();
+  Reset();
+}
+
+void
+ProfileGatherer::Reset()
+{
+  mSinceTime = 0;
+  mPromise = nullptr;
+  mPendingProfiles = 0;
+  mGathering = false;
+}
+
+void
+ProfileGatherer::Cancel()
+{
+  // The GeckoSampler is going away. If we have a Promise in flight, we
+  // should reject it.
+  if (mPromise) {
+    mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
+  }
+
+  // Clear out the GeckoSampler reference, since it's being destroyed.
+  mTicker = nullptr;
+}
+
+void
+ProfileGatherer::OOPExitProfile(const nsCString& aProfile)
+{
+  if (mExitProfiles.Length() >= MAX_SUBPROCESS_EXIT_PROFILES) {
+    mExitProfiles.RemoveElementAt(0);
+  }
+  mExitProfiles.AppendElement(aProfile);
+
+  // If a process exited while gathering, we need to make
+  // sure we decrement the counter.
+  if (mGathering) {
+    GatheredOOPProfile();
+  }
+}
+
+NS_IMETHODIMP
+ProfileGatherer::Observe(nsISupports* aSubject,
+                         const char* aTopic,
+                         const char16_t *someData)
+{
+  if (!strcmp(aTopic, "profiler-subprocess")) {
+    nsCOMPtr<nsIProfileSaveEvent> pse = do_QueryInterface(aSubject);
+    if (pse) {
+      for (size_t i = 0; i < mExitProfiles.Length(); ++i) {
+        if (!mExitProfiles[i].IsEmpty()) {
+          pse->AddSubProfile(mExitProfiles[i].get());
+        }
+      }
+      mExitProfiles.Clear();
+    }
+  }
+  return NS_OK;
 }
 
 } // namespace mozilla
--- a/tools/profiler/gecko/nsIProfiler.idl
+++ b/tools/profiler/gecko/nsIProfiler.idl
@@ -22,17 +22,17 @@ interface nsIProfilerStartParams : nsISu
 {
   attribute uint32_t entries;
   attribute double interval;
 
   [noscript, notxpcom, nostdcall] StringArrayRef getFeatures();
   [noscript, notxpcom, nostdcall] StringArrayRef getThreadFilterNames();
 };
 
-[scriptable, uuid(b373b360-c997-448a-b60d-4985b70dc810)]
+[scriptable, uuid(ead3f75c-0e0e-4fbb-901c-1e5392ef5b2a)]
 interface nsIProfiler : nsISupports
 {
   boolean CanProfile();
   void StartProfiler(in uint32_t aEntries, in double aInterval,
                       [array, size_is(aFeatureCount)] in string aFeatures,
                       in uint32_t aFeatureCount,
                       [array, size_is(aFilterCount), optional] in string aThreadNameFilters,
                       [optional] in uint32_t aFilterCount);
@@ -61,16 +61,22 @@ interface nsIProfiler : nsISupports
   void GetFeatures(out uint32_t aCount, [retval, array, size_is(aCount)] out string aFeatures);
 
   /**
    * The starting parameters that were sent to the profiler for sampling.
    * If the profiler is not currently sampling, this will return null.
    */
   readonly attribute nsIProfilerStartParams startParams;
 
+  /**
+   * The profileGatherer will be null if the profiler is not currently
+   * active.
+   */
+  readonly attribute nsISupports profileGatherer;
+
   void GetBufferInfo(out uint32_t aCurrentPosition, out uint32_t aTotalSize,
                      out uint32_t aGeneration);
 
   /**
    * Returns the elapsed time, in milliseconds, since the profiler's epoch.
    * The epoch is guaranteed to be constant for the duration of the
    * process, but is otherwise arbitrary.
    */
--- a/tools/profiler/gecko/nsProfiler.cpp
+++ b/tools/profiler/gecko/nsProfiler.cpp
@@ -283,8 +283,26 @@ NS_IMETHODIMP
 nsProfiler::GetBufferInfo(uint32_t *aCurrentPosition, uint32_t *aTotalSize, uint32_t *aGeneration)
 {
   MOZ_ASSERT(aCurrentPosition);
   MOZ_ASSERT(aTotalSize);
   MOZ_ASSERT(aGeneration);
   profiler_get_buffer_info(aCurrentPosition, aTotalSize, aGeneration);
   return NS_OK;
 }
+
+NS_IMETHODIMP
+nsProfiler::GetProfileGatherer(nsISupports** aRetVal)
+{
+  if (!aRetVal) {
+    return NS_ERROR_INVALID_POINTER;
+  }
+
+  // If we're not profiling, there will be no gatherer.
+  if (!profiler_is_active()) {
+    *aRetVal = nullptr;
+  } else {
+    nsCOMPtr<nsISupports> gatherer;
+    profiler_get_gatherer(getter_AddRefs(gatherer));
+    gatherer.forget(aRetVal);
+  }
+  return NS_OK;
+}
\ No newline at end of file
--- a/tools/profiler/public/GeckoProfilerFunc.h
+++ b/tools/profiler/public/GeckoProfilerFunc.h
@@ -9,16 +9,18 @@
 #ifndef SPS_STANDALONE
 #include "js/TypeDecls.h"
 #endif
 #include "js/ProfilingStack.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/Vector.h"
 #include <stdint.h>
 
+class nsISupports;
+
 namespace mozilla {
 class TimeStamp;
 
 namespace dom {
 class Promise;
 } // namespace dom
 
 } // namespace mozilla
@@ -68,16 +70,17 @@ mozilla::UniquePtr<char[]> mozilla_sampl
 #ifndef SPS_STANDALONE
 JSObject *mozilla_sampler_get_profile_data(JSContext* aCx, double aSinceTime);
 void mozilla_sampler_get_profile_data_async(double aSinceTime,
                                             mozilla::dom::Promise* aPromise);
 void mozilla_sampler_get_profiler_start_params(int* aEntrySize,
                                                double* aInterval,
                                                mozilla::Vector<const char*>* aFilters,
                                                mozilla::Vector<const char*>* aFeatures);
+void mozilla_sampler_get_gatherer(nsISupports** aRetVal);
 #endif
 
 // Make this function easily callable from a debugger in a build without
 // debugging information (work around http://llvm.org/bugs/show_bug.cgi?id=22211)
 extern "C" {
   void mozilla_sampler_save_profile_to_file(const char* aFilename);
 }
 
--- a/tools/profiler/public/GeckoProfilerImpl.h
+++ b/tools/profiler/public/GeckoProfilerImpl.h
@@ -174,16 +174,23 @@ void profiler_get_profile_jsobject_async
 static inline
 void profiler_get_start_params(int* aEntrySize,
                                double* aInterval,
                                mozilla::Vector<const char*>* aFilters,
                                mozilla::Vector<const char*>* aFeatures)
 {
   mozilla_sampler_get_profiler_start_params(aEntrySize, aInterval, aFilters, aFeatures);
 }
+
+static inline
+void profiler_get_gatherer(nsISupports** aRetVal)
+{
+  mozilla_sampler_get_gatherer(aRetVal);
+}
+
 #endif
 
 static inline
 void profiler_save_profile_to_file(const char* aFilename)
 {
   return mozilla_sampler_save_profile_to_file(aFilename);
 }
 
--- a/tools/profiler/public/ProfileGatherer.h
+++ b/tools/profiler/public/ProfileGatherer.h
@@ -6,33 +6,37 @@
 #define MOZ_PROFILE_GATHERER_H
 
 #include "mozilla/dom/Promise.h"
 
 class GeckoSampler;
 
 namespace mozilla {
 
-class ProfileGatherer final : public nsISupports
+class ProfileGatherer final : public nsIObserver
 {
 public:
   NS_DECL_ISUPPORTS
+  NS_DECL_NSIOBSERVER
 
-  ProfileGatherer(GeckoSampler* aTicker,
-                  double aSinceTime,
-                  mozilla::dom::Promise* aPromise);
+  explicit ProfileGatherer(GeckoSampler* aTicker);
   void WillGatherOOPProfile();
   void GatheredOOPProfile();
-  void Start();
+  void Start(double aSinceTime, mozilla::dom::Promise* aPromise);
+  void Cancel();
+  void OOPExitProfile(const nsCString& aProfile);
 
 private:
   ~ProfileGatherer() {};
   void Finish();
+  void Reset();
 
+  nsTArray<nsCString> mExitProfiles;
   RefPtr<mozilla::dom::Promise> mPromise;
   GeckoSampler* mTicker;
   double mSinceTime;
   uint32_t mPendingProfiles;
+  bool mGathering;
 };
 
 } // namespace mozilla
 
 #endif
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -843,17 +843,19 @@ GeckoInputDispatcher::unregisterInputCha
 
 nsAppShell::nsAppShell()
     : mNativeCallbackRequest(false)
     , mEnableDraw(false)
     , mHandlers()
     , mPowerKeyChecked(false)
 {
     gAppShell = this;
-    Preferences::SetCString("b2g.safe_mode", "unset");
+    if (XRE_IsParentProcess()) {
+        Preferences::SetCString("b2g.safe_mode", "unset");
+    }
 }
 
 nsAppShell::~nsAppShell()
 {
     // mReaderThread and mEventHub will both be null if InitInputDevices
     // is not called.
     if (mReaderThread.get()) {
         // We separate requestExit() and join() here so we can wake the EventHub's