merge b2g-inbound to m-c to fix merge conflicts a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Thu, 05 Nov 2015 13:38:39 +0100
changeset 306865 61dcc13d0848230382d5c85cdcf6721a05ee37c6
parent 306821 59c648a3f95524cb1ee42f2306c1db2698d35258 (current diff)
parent 306864 8f42cacc508e40cd0195ec8daed1c8ca67a20f12 (diff)
child 306866 de0abcd8bd14296589e39cec28ac40188d862ce6
child 306895 4a7a118260afaa82f1a5eba5057ceb53ef893c8a
child 306896 16d242da0a9ebc8b26ba22feba36b7da2dfa0897
child 306897 d5ed080a35c54f2f5b9da69d81d0fbc89b0d943d
child 306899 413c317b3cfda6baa7cf26a3136bc1e00f7bbd62
child 306900 2d6e6c4ea42eb42d9017bbd1c2d450445831d20e
child 306901 94e653d82fa5808689ce828c488152d49df44e91
child 306907 b74429731511479cfd2ed30ec1ce9acee26bea4d
child 306908 cf5e047adbfd5f57e86f4e0f2f4f42e266ec4472
child 306911 61b098c2a52bf79464a40091bf5004d7ec92fd3b
child 306920 ba112c8e0984d69da1bce66d3579a7bd6e81a1a2
child 306986 ae0916bbb8e9d53a685735f53bc6353eca0eb862
child 307001 1d59f113235a98ca30653d2c935e0cc2e7bc8931
child 307002 b6716e407b0073be96ec6e159e93fb921d37d8bc
child 307009 4318a26c00bb74d242313d323bfd43ea75c05d65
child 307026 64ade6fc5700326f41d8d37f21fc7eb4a554eb9b
child 307043 26868d7e2ba506ce4b90085b661265354d95c4ea
child 307044 b15c05c3066c5988ed76e9224d363c64747aa43e
child 307078 f8899923ea4a00b00d295774f5da0e5a2d94938e
child 307133 a09d9a4253744d1b318663f2eb5af1cbd33b9c94
child 307148 86569fe1e18a14707e0a15e4eb7001177169e598
child 307160 539031ea2a9021ca84044f210cb4b7b0f12a24ae
child 307161 6c12b8396a6937108d6e5591e5a4907fe998bb3c
child 307162 84d3688ec5fca78d83ca89d20ebcb32c63379232
child 307165 9743df55e004bb49012301ed5c714d3d821b965a
child 307280 f573b0c2633ee3f4babe3b73ca5a896b32ee9fae
child 307683 be06acf691b43818a6dae06cf52748cecedc0f70
child 307983 e785f200abaecb18dd6be40035164879d4c40045
child 308082 89d1604ef2fd2d65d9d419375ce2a89941edec13
push id7204
push usercku@mozilla.com
push dateThu, 05 Nov 2015 15:38:26 +0000
reviewersmerge
milestone45.0a1
merge b2g-inbound to m-c to fix merge conflicts a=merge
devtools/client/webide/content/simulator.js
dom/browser-element/BrowserElementParent.js
dom/browser-element/mochitest/mochitest-oop.ini
dom/browser-element/mochitest/mochitest.ini
dom/browser-element/nsIBrowserElementAPI.idl
dom/html/nsBrowserElement.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -688,16 +688,17 @@ pref("layout.css.scroll-snap.enabled", t
 
 // Enable the ProcessPriorityManager, and give processes with no visible
 // documents a 1s grace period before they're eligible to be marked as
 // background. Background processes that are perceivable due to playing
 // media are given a longer grace period to accomodate changing tracks, etc.
 pref("dom.ipc.processPriorityManager.enabled", true);
 pref("dom.ipc.processPriorityManager.backgroundGracePeriodMS", 1000);
 pref("dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS", 5000);
+pref("dom.ipc.processPriorityManager.memoryPressureGracePeriodMS", 3000);
 pref("dom.ipc.processPriorityManager.temporaryPriorityLockMS", 5000);
 
 // Number of different background/foreground levels for background/foreground
 // processes.  We use these different levels to force the low-memory killer to
 // kill processes in a LRU order.
 pref("dom.ipc.processPriorityManager.BACKGROUND.LRUPoolLevels", 5);
 pref("dom.ipc.processPriorityManager.BACKGROUND_PERCEIVABLE.LRUPoolLevels", 4);
 
--- a/b2g/chrome/content/devtools/hud.js
+++ b/b2g/chrome/content/devtools/hud.js
@@ -740,29 +740,31 @@ var eventLoopLagWatcher = {
       fronts.delete(target);
     }
   }
 };
 developerHUD.registerWatcher(eventLoopLagWatcher);
 
 /*
  * The performanceEntriesWatcher determines the delta between the epoch
- * of an app's launch time and the app's performance entry marks.
+ * of an app's launch time and the epoch of the app's performance entry marks.
  * When it receives an "appLaunch" performance entry mark it records the
  * name of the app being launched and the epoch of when the launch ocurred.
  * When it receives subsequent performance entry events for the app being
  * launched, it records the delta of the performance entry opoch compared
  * to the app-launch epoch and emits an "app-start-time-<performance mark name>"
  * event containing the delta.
+ *
+ * Additionally, while recording the "app-start-time" for a performance mark,
+ * USS memory at the time of the performance mark is also recorded.
  */
 var performanceEntriesWatcher = {
   _client: null,
   _fronts: new Map(),
-  _appLaunchName: null,
-  _appLaunchStartTime: null,
+  _appLaunch: new Map(),
   _supported: [
     'contentInteractive',
     'navigationInteractive',
     'navigationLoaded',
     'visuallyLoaded',
     'fullyLoaded',
     'mediaEnumerated',
     'scanEnd'
@@ -795,45 +797,44 @@ var performanceEntriesWatcher = {
       // Only process performance marks.
       if (detail.type !== 'mark') {
         return;
       }
 
       let name = detail.name;
       let epoch = detail.epoch;
 
-      // FIXME There is a potential race condition that can result
-      // in some performance entries being disregarded. See bug 1189942.
-      //
       // If this is an "app launch" mark, record the app that was
       // launched and the epoch of when it was launched.
       if (name.indexOf('appLaunch') !== -1) {
         let CHARS_UNTIL_APP_NAME = 7; // '@app://'
         let startPos = name.indexOf('@app') + CHARS_UNTIL_APP_NAME;
         let endPos = name.indexOf('.');
-        this._appLaunchName = name.slice(startPos, endPos);
-        this._appLaunchStartTime = epoch;
+        let appName = name.slice(startPos, endPos);
+        this._appLaunch.set(appName, epoch);
         return;
       }
 
       // Only process supported performance marks
       if (this._supported.indexOf(name) === -1) {
         return;
       }
 
       let origin = detail.origin;
       origin = origin.slice(0, origin.indexOf('.'));
 
-      // Continue if the performance mark corresponds to the app
-      // for which we have recorded app launch information.
-      if (this._appLaunchName !== origin) {
+      let appLaunchTime = this._appLaunch.get(origin);
+
+      // Sanity check: ensure we have an app launch time for the app
+      // corresponding to this performance mark.
+      if (!appLaunchTime) {
         return;
       }
 
-      let time = epoch - this._appLaunchStartTime;
+      let time = epoch - appLaunchTime;
       let eventName = 'app_startup_time_' + name;
 
       // Events based on performance marks are for telemetry only, they are
       // not displayed in the HUD front end.
       target._logHistogram({name: eventName, value: time});
 
       memoryWatcher.front(target).residentUnique().then(value => {
         // bug 1215277, need 'v2' for app-memory histograms
--- a/b2g/config/aries/config.json
+++ b/b2g/config/aries/config.json
@@ -6,23 +6,25 @@
     "mock_files": [
         ["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"],
         ["/builds/crash-stats-api.token", "/builds/crash-stats-api.token"]
     ],
     "build_targets": ["", "blobfree"],
     "upload_files": [
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{objdir}/dist/b2g-*.tar.gz",
-        "{workdir}/sources.xml"
+        "{workdir}/sources.xml",
+        "{workdir}/out/target/product/aries/fota-*-update-*.mar"
     ],
     "public_upload_files": [
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml",
-        "{objdir}/dist/b2g-update/*.mar"
+        "{objdir}/dist/b2g-update/*.mar",
+        "{workdir}/out/target/product/aries/fota-*-update.mar"
     ],
     "zip_files": [
         ["{workdir}/out/target/product/aries/*.img", "out/target/product/aries/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml",
         "{workdir}/profile.sh",
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,22 +10,22 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <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="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,22 +10,22 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <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="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,22 +14,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <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="gaia.git" path="gaia" remote="mozillaorg" revision="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c72c9278ddc2f442d193474993d36e7f2cfb08c4"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,19 +12,19 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,21 +10,21 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,21 +10,21 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,22 +14,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <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="gaia.git" path="gaia" remote="mozillaorg" revision="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="4ace9aaee0e048dfda11bb787646c59982a3dc80"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c72c9278ddc2f442d193474993d36e7f2cfb08c4"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <project name="platform_hardware_libhardware_moz" path="hardware/libhardware_moz" remote="b2g" revision="fdf3a143dc777e5f9d33a88373af7ea161d3b440"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,22 +10,22 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <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="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "607b9c5db7fdbbafc16a572e7c319baa266a3372", 
+        "git_revision": "c3be747b993f0c70e7b93a709ef691383c88fc01", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "7136753530b8af60e42417fc73356ba17971141b", 
+    "revision": "5718aa1b0322ec35435fcd253eedeb91e3f7872c", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4-kk/config.json
+++ b/b2g/config/nexus-4-kk/config.json
@@ -12,17 +12,18 @@
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml"
     ],
     "public_upload_files": [
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml",
-        "{objdir}/dist/b2g-update/*.mar"
+        "{objdir}/dist/b2g-update/*.mar",
+        "{workdir}/mako.zip"
     ],
     "zip_files": [
         ["{workdir}/out/target/product/mako/*.img", "out/target/product/mako/"],
         ["{workdir}/boot.img", "out/target/product/mako/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml",
--- a/b2g/config/nexus-4-kk/sources.xml
+++ b/b2g/config/nexus-4-kk/sources.xml
@@ -10,22 +10,22 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <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="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -13,19 +13,19 @@
   <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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="956700d9754349b630a34551750ae6353614b6aa"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/b2g/config/nexus-5-l/config.json
+++ b/b2g/config/nexus-5-l/config.json
@@ -12,17 +12,18 @@
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml"
     ],
     "public_upload_files": [
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{objdir}/dist/b2g-*.tar.gz",
         "{workdir}/sources.xml",
-        "{objdir}/dist/b2g-update/*.mar"
+        "{objdir}/dist/b2g-update/*.mar",
+        "{workdir}/hammerhead.zip"
     ],
     "zip_files": [
         ["{workdir}/out/target/product/hammerhead/*.img", "out/target/product/hammerhead/"],
         ["{workdir}/boot.img", "out/target/product/hammerhead/"],
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
         "{workdir}/.config",
         "{workdir}/sources.xml",
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,22 +10,22 @@
   <!--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="607b9c5db7fdbbafc16a572e7c319baa266a3372"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="c3be747b993f0c70e7b93a709ef691383c88fc01"/>
   <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="956700d9754349b630a34551750ae6353614b6aa"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
-  <project name="moztt" path="external/moztt" remote="b2g" revision="27de93fe66c3e80e157d157bd52ca99565351669"/>
+  <project name="moztt" path="external/moztt" remote="b2g" revision="aa5b7b7f6ed207ea1adc4df11d1d8bdaeabadd85"/>
   <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="638ec448619fda80fcb439b1747af62169d05548"/>
   <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"/>
--- a/devtools/client/webide/content/simulator.js
+++ b/devtools/client/webide/content/simulator.js
@@ -39,17 +39,17 @@ var SimulatorEditor = {
     let form = this._form;
     if (!form) {
       // This is the first time we run `init()`, bootstrap some things.
       form = this._form = document.querySelector("#simulator-editor");
       form.addEventListener("change", this.update.bind(this));
       Simulators.on("configure", (e, simulator) => { this.edit(simulator) });
       // Extract the list of device simulation options we'll support.
       let deviceFields = form.querySelectorAll("*[data-device]");
-      this._deviceOptions = [].map.call(deviceFields, field => field.name);
+      this._deviceOptions = Array.map(deviceFields, field => field.name);
     }
 
     // Append a new <option> to a <select> (or <optgroup>) element.
     function opt(select, value, text) {
       let option = document.createElement("option");
       option.value = value;
       option.textContent = text;
       select.appendChild(option);
@@ -167,17 +167,17 @@ var SimulatorEditor = {
       simulator.addon = this._addons[value];
       simulator.options.b2gBinary = null;
     } else {
       // `value` is a custom binary path.
       simulator.options.b2gBinary = value;
       // TODO (Bug 1146531) Indicate that a custom profile is now required.
     }
     // If `form.name` contains the old version, update its last occurrence.
-    if (form.name.value.contains(oldVer) && simulator.version !== oldVer) {
+    if (form.name.value.includes(oldVer) && simulator.version !== oldVer) {
       let regex = new RegExp("(.*)" + oldVer);
       let name = form.name.value.replace(regex, "$1" + simulator.version);
       simulator.options.name = form.name.value = Simulators.uniqueName(name);
     }
   },
 
   updateVersionSelector() {
     this.updateSelector(this._form.version, this.version);
--- a/devtools/client/webide/modules/simulators.js
+++ b/devtools/client/webide/modules/simulators.js
@@ -134,18 +134,26 @@ var Simulators = {
    * Add a new simulator for `addon` if no other simulator uses it.
    */
   addIfUnusedAddon(addon, silently = false) {
     let simulators = this._simulators;
     let matching = simulators.filter(s => s.addon && s.addon.id == addon.id);
     if (matching.length > 0) {
       return promise.resolve();
     }
-    let name = addon.name.replace(" Simulator", "");
-    return this.add(new Simulator({name}, addon), silently);
+    let options = {};
+    options.name = addon.name.replace(" Simulator", "");
+    // Some addons specify a simulator type at the end of their version string,
+    // e.g. "2_5_tv".
+    let type = this.simulatorAddonVersion(addon).split("_")[2];
+    if (type) {
+      // "tv" is shorthand for type "television".
+      options.type = (type === "tv" ? "television" : type);
+    }
+    return this.add(new Simulator(options, addon), silently);
   },
 
   // TODO (Bug 1146521) Maybe find a better way to deal with removed addons?
   removeIfUsingAddon(addon) {
     let simulators = this._simulators;
     let remaining = simulators.filter(s => !s.addon || s.addon.id != addon.id);
     this._simulators = remaining;
     if (remaining.length !== simulators.length) {
@@ -195,20 +203,37 @@ var Simulators = {
     let unique = stripped;
     for (let i = 1; names[unique]; i++) {
       unique = stripped + " (" + i + ")";
     }
     return unique;
   },
 
   /**
+   * Compare an addon's ID against the expected form of a simulator addon ID,
+   * and try to extract its version if there is a match.
+   *
+   * Note: If a simulator addon is recognized, but no version can be extracted
+   * (e.g. custom RegExp pref value), we return "Unknown" to keep the returned
+   * value 'truthy'.
+   */
+  simulatorAddonVersion(addon) {
+    let match = SimulatorRegExp.exec(addon.id);
+    if (!match) {
+      return null;
+    }
+    let version = match[1];
+    return version || "Unknown";
+  },
+
+  /**
    * Detect simulator addons, including "unofficial" ones.
    */
   isSimulatorAddon(addon) {
-    return SimulatorRegExp.exec(addon.id);
+    return !!this.simulatorAddonVersion(addon);
   },
 
   emitUpdated() {
     this.emit("updated");
     this._simulators.sort(LocaleCompare);
     this._save();
   },
 
@@ -245,35 +270,45 @@ AddonManager.addAddonListener(Simulators
 EventEmitter.decorate(Simulators);
 Simulators.on("configure", Simulators.onConfigure.bind(Simulators));
 
 function Simulator(options = {}, addon = null) {
   this.addon = addon;
   this.options = options;
 
   // Fill `this.options` with default values where needed.
-  let defaults = this._defaults;
+  let defaults = this.defaults;
   for (let option in defaults) {
     if (this.options[option] == null) {
       this.options[option] = defaults[option];
     }
   }
 }
 Simulator.prototype = {
 
-  // Default simulation options, based on the Firefox OS Flame.
+  // Default simulation options.
   _defaults: {
-    width: 320,
-    height: 570,
-    pixelRatio: 1.5
+    // Based on the Firefox OS Flame.
+    phone: {
+      width: 320,
+      height: 570,
+      pixelRatio: 1.5
+    },
+    // Based on a 720p HD TV.
+    television: {
+      width: 1280,
+      height: 720,
+      pixelRatio: 1,
+    }
   },
+  _defaultType: "phone",
 
   restoreDefaults() {
+    let defaults = this.defaults;
     let options = this.options;
-    let defaults = this._defaults;
     for (let option in defaults) {
       options[option] = defaults[option];
     }
   },
 
   launch() {
     // Close already opened simulation.
     if (this.process) {
@@ -302,21 +337,30 @@ Simulator.prototype = {
     let process = this.process;
     if (!process) {
       return promise.resolve();
     }
     this.process = null;
     return process.kill();
   },
 
+  get defaults() {
+    let defaults = this._defaults;
+    return defaults[this.type] || defaults[this._defaultType];
+  },
+
   get id() {
     return this.name;
   },
 
   get name() {
     return this.options.name;
   },
 
+  get type() {
+    return this.options.type || this._defaultType;
+  },
+
   get version() {
     return this.options.b2gBinary ? "Custom" : this.addon.name.match(/\d+\.\d+/)[0];
   },
 };
 exports.Simulator = Simulator;
new file mode 100644
index 0000000000000000000000000000000000000000..f1fec6fc7bed209db842d25b93af4e9ebf03090d
GIT binary patch
literal 1087
zc$^FHW@Zs#U|`^2c#)Ls{@~-ILUASr22&OW25tr!hRnR;lEj=Gy`q$~&=5`rX62a{
zVIW*u!Og(P@`9Ox0ZgO@$L7yA5UG70e&^!$Og8pKTU|KsZdrF}N!aRZD=y7bVxE3X
z`o@WUCZ5axe%~qJvB~CP^*hV&k8hk=zrB=IKV!|6tcU(g@0eG`hzHr~|C#1h_B4L^
zy+5+a8)Ce<`*)dI9ukjLxRVv!d^l(J-$Qd6OfE<@UbrGwa+CG@uh6im4ee&DQ{FK$
zG+WPHyy*vH98(9A+=1;vEKhdb>|NDveS?GBOIYO6q=}K<5eM8Z-4a~#mV4@^qR_fm
zVnqub(p8rH)?jhmpq7=E81eltbM8FnaMO~%hZrQhZS(&<ekOM3*D1X}w$+<&vdrG0
z>_16`vr@!O(Af3l8^4J+j8gUg#2Fv{<x+M><57)N(qFYbAA-$a|6$9`OL0DzDljwe
z<jm|VIr_6aQ$0gOSGP`5je6zc*Y?#%EOY18GST%vy5hpZuH~wF%=UNZeV*tq<NBN1
zcX{D-sY8bTyV)+UI9+<&aAKzKxx9-@Qlj2)uxF%fT_yPQJ#(sjwe7>VYwvh9FTGdh
z*6-U|>Gtc6$vZ_3sppoZ=?9KI{hv^GG&wGAlg*<hUwc3AX(=){Rm3)W80_p>zpUP0
zM&ioW5dYt2)jbbbpA#%QC3>5&zv9Eb=W-hoFMY_la_`9Jt9^S6q6BL~S??%!N;^I}
zBBq+<!@hr?y^~Bqgx$f%1s7wR`%JvL7AvyM$$s0p?MMBSjeYMNcH8V}OFm+KyIgKp
zyxP})i~;bpwYf6cZAs9)1y6vyMn(n(9$?x^%Fiz;E-6YZ(90?YC$32czlNw`Ca&6k
zU+*IZ0&VaAioOp#ed&apxD99125#=Ej~2c`)|1k_jBfsF{C~HE)pqCfpEb{FB`-fZ
za#^ps_1SIRPn+6`U*1pa@>}ViEp_=(=93<G&68DkIzR82ZnE%P(aZR~Ynhm2ZLciX
zbZ#pyp1{x7SfEpzaC^bgd29P`<`=x$@HWrNhDRY{=KcEozG|H*g02rOvLEeRQ63R-
zoU0%%m5nd-aU_?HtH=5yrmp-!J*z&SoAL7a?#W-0RxMkZw=8;oW}DF3O)dpzycA<B
zgKjBQo)TLB@#k0fE47!5;+2jq@|#w{sQEE|aeja|Ba<96u6!uL00O{ZW7yINVxi<p
pR!FWy3p8W{F#{jjz!;!4s8PWRi3$u8S=m6kn1FCGkZxlJ@c_;E!JPmA
new file mode 100644
index 0000000000000000000000000000000000000000..0fd70ca9f13a12362ab54df2691c8aeee8b6d0ab
GIT binary patch
literal 1087
zc$^FHW@Zs#U|`^2*j$<Hwj^lYf+s*;BO?O?4}%OtQht6(aY<2PfnHW|Xb2|*^Q41c
zLqNE+f}4Sn<pnbX1DL4o_w_zvAkg;yuju>0)0a-jiQ8~CZQ$mv`e@-BWIZX(%jo8>
z#{YLqSZ#Ms|5@{_R`T+rBbW86Tc6$5{j{mA_~reyF29xT*;1DuWj^U~*F0Hur}OiU
z=_U)$6}^n#yOxPb*7nMBP3N}a;tBkGjRiWj3AYy<owv6CW`4n|4R7<TY<LtRX5O#Q
z@2l3CBIx?iBKy(473C2T$GHmPQrY-IA4hWOxO%KVV(Q8t)U)dIxfw5y@1Fc6Y1Oio
zdCQ{bXSNBg-Q-em#!E5AGU%2<<td@{AAf#zzfyb2C|>E<BEM-BjG7<g7v~4SLyDy+
z+5N%CM}^`{3=F0$3=G`Bkjl&}E=kPE(JM+x0|(TM%@$!Gj22L-!Lj+X4Mb|6hu^ul
zJ(G=n(N-7EyIa;>S`xPU+KNl_l$fU<lfH3cpNZ%4zu$KXcx<wHSpClO`{NsD)^9Im
z)z4USCF`L-(>vx>G2%hC`hTW*l|7ALe(#TL@`f01?*3h-mWRY+74BpOHy_TK{rAwE
z29pa?jTf$nmE2_g{wp+WYD2r(>Xdhk49(Uv7jOE(7{}DXBzIuD5X+NYH+xsLTi@W|
z_7WDkG-+a_cf<j=OSc4<yyc#{sVKDWl~~b2hjf)CzcpAKH>hQ$B}RPz%bYvUIo!15
z?;!>WZ`=HTkDrO%`E^R~k8Snln=G?;DEm)R;j9#K6Et=``NnVJ4Wm^3KXJx~f4P+1
z(RfrNmGoC_&xc_1*MHb@^HQA8r3%c<J2^A^N{;?4&s5J4(bcV!RHI(G__clY5zE|p
zwM=yVkFL0|uxq)h9<%-3d7mfx%eemL_FY~$UFwjb|8BO+D^8alH=LO1doJ(dl9Z@7
z9PAk>TUQDGe9xRJUv2yF?b<tD%}ei<x%K<DR=WMVWAaXsL+ZI@Y5IX<PyZ*>9Ziml
z+hp^o$=BY`ds>RjO%<_?9tJym)-S8~myx)#HN^k-S#{3?*5?GvPKn-T?63H+@44KD
z#7iG?uG~BF`D))DgDAn8P}V!jozjkvj)<vd`LOTbXYV9a5Mg)lalysd<~|dzuEmNh
zbF$xdZu?RHWMkhuhut=N+LDi0-!7Ni6|eU7A7g+wBa<96u6!uL00KZJ!<I%63pH1=
pLUJWqLPItYGrc04s0E}@QZFkc^<o&v$_CQJ1cZx$bQ?2>2LLYx!oC0i
new file mode 100644
index 0000000000000000000000000000000000000000..434ed5e0db8eda2e865237330d91b3648cda3049
GIT binary patch
literal 1087
zc$^FHW@Zs#U|`^2&`nNufAH~9p*Rx*gDDFG12=;VLuOuaNn%cpUQtR~Xb2|*^U|3X
zVJm^Sw1S&~k>v$50|S^y4UWy9Z6H$nJp9hZ?U`)si?+IO-rch9(vq;%*H&Dbr^Gz{
znDmVk`%FBS|NXvGz+;om!|HdI-yh#NvwnLitA56sD_IZyncgw4iV+X8)&DcitL$m~
z@_T<|lQ+b8bNBBuwLByqt8gbPxcP9-?7xTRG?-kFYP@hotmG!^_g|r5QybdNR;RpU
zWN5aYxp>nL#yF-9Cb<LKg;<{Ky4ky`-TDRxx0kTUrAZSby(12|UAiT><SqBqO+}$~
zuf&QLI;5*C`K`g?xIrx|EivNzU*_C-&f%sde-AN8c-!Xxd;Co7&aYE?e{8Ea-(;D+
zL)m|l3TLH=o1n4l$v1uzZy2TO|A{j`{L7{6j>e-JsiePZdp-o4zy8CPo0sBzE>&P=
z-pQHSS90`cd8T@Xh^}s(q#E_g#jowFk67l;t7W3=e{{u#g<Z>4^_cDN&ig#kU&i$}
zx9{@8=~9Ob{dconUU9ngxZ%W1-*b5vm!w3!;b6~5*}6*b=X>T<`D)vTZ`a=OYF>J;
z%&p(IwbJd^9g}y898%9MOVbY=d-^}2?r3sc+$NhxO}_Si-qTWKZmNiF^f1`jvwm5<
zzl_9{ts(xu&#HSKus$bPc1rX%V}Hemeb41KBwqTEbLHNV&sY2Q7(@xygtFdI?v!?X
zbVN)w%ZGjcK6@vbf(W~Vj|(owHusr$buCt8nUnptbK8&lCmZ|TIqbIC)0TY1`gXb8
zu6VVt{}=<{X=`(3vfGlNc?+HZd5w$=3_QTJm6V@fQe0A$SfH0x3{G5=4t@;*VYI|m
z+wbdr#6Y0!{a?}dfu}E>kQ2AzY}&xhUG>qzH^_QYnwQbdUyc9omay9Hoc^=sS*_&d
zM@KH}RkuF7t@~+HTk*^LX<dFR-Ls`GKgxX4<F0wK>Q3k99n(z~o-2A8zjrMYldSEP
z<(kfI#l;i&`5Fs!Y7=fRI67}_|IPe@R~z2uS=sO?M9jQjpWj!lGeyw#p+)wieJjc%
zB93zv#HF(Fg+7kt(sA`zf5g<4Kd5Kb=W{b&9^XCrOVX-kEAy5`&(CZVTD!@m;Eb1I
zjAhU*h00Sx>p%Yd>VBp6l2N?Uu|<B<Di}3C#xKqf@MdI^W5$&aB^W>e7;Fq%8bK_S
rT*(T_m1u#6Y#?UfBO4e4v<5XQSRqk?VInIVNEZ_jE(X$V%pe{B<B7up
new file mode 100644
index 0000000000000000000000000000000000000000..aea5862b0a016a5874ba3af1235b146417a75416
GIT binary patch
literal 1087
zc$^FHW@Zs#U|`^22ue<NfAH~9p*Rx*gDDFG12=;VLuOuaNn%cpUQtR~Xb2|*^Xr)w
zVIW*u!Og(P@`9Ox0ZgO@$L7yA5UG70e&^!$Og8pKTU|KsZdrF}N!aRZD=y7bVxE3X
z`o@WUCZ5axe%~qJvB~CP^*hV&k8hk=zrB=IKV!|6tcU(g@0eG`hzHr~|C#1h_B4L^
zy+5+a8)Ce<`*)dI9ukjLxRVv!d^l(J-$Qd6OfE<@UbrGwa+CG@uh6im4ee&DQ{FK$
zG+WPHyy*vH98(9A+=1;vEKhdb>|NDveS?GBOIYO6q=}K<5eM8Z-4a~#mV4@^qR_fm
zVnqub(p8rH)?jhmpq7=E81eltbM8FnaMO~%hZrQhZS(&<ekOM3*D1X}w$+<&vdrG0
z>_16`vr@!O(Af3l8^4J+j8gUg#2Fv{<x+M><57)N(qFYbAA-$a|6$9`OL0DzDljwe
z<jm|VIr_6aQ$0gOSGP`5je6zc*Y?#%EOY18GST%vy5hpZuH~wF%=UNZeV*tq<NBN1
zcX{D-sY8bTyV)+UI9+<&aAKzKxx9-@Qlj2)uxF%fT_yPQJ#(sjwe7>VYwvh9FTGdh
z*6-U|>Gtc6$vZ_3sppoZ=?9KI{hv^GG&wGAlg*<hUwc3AX(=){Rm3)W80_p>zpUP0
zM&ioW5dYt2)jbbbpA#%QC3>5&zv9Eb=W-hoFMY_la_`9Jt9^S6q6BL~S??%!N;^I}
zBBq+<!@hr?y^~Bqgx$f%1s7wR`%JvL7AvyM$$s0p?MMBSjeYMNcH8V}OFm+KyIgKp
zyxP})i~;bpwYf6cZAs9)1y6vyMn(n(9$?x^%Fiz;E-6YZ(90?YC$32czlMM?TH>nh
z_w_zvAkg;yuju>0)0a-jiQ8~CZQ$mv`e@-BWIZX(%jo8>#{YLqSZ#Ms|5@{_R`T+r
zBbW86Tc6$5{j{mA_~reyF29xT*;1DuWj^U~*F0Hur}OiU=_U)$6}^n#yOxPb*7nMB
zP3N}a;tBkGjRiWj3AYy<owv6CW`4n|4R7<TY<LtRX5O#Q@2l3CBIx?iBKy(473C2T
z$GHmPQrY-IA4hWOxO%KVV(Q8t)U)dIxfw5y@1Fc6Y1OiodCQ{bXSNBg-Q-em#!E5A
zGU%2<<td@{AAf#zzfyb2C|>E<BEM-BjG7<g7v~3fGcw6B<I0B;3?KjuHij*YAQnol
qWQF8Pv_L~P5Hs+R4U7R=gBlgAkf^{gk(CXkiwOu91L-zq5Dx(20>l~s
--- a/devtools/client/webide/test/addons/simulators.json
+++ b/devtools/client/webide/test/addons/simulators.json
@@ -1,4 +1,4 @@
 {
   "stable": ["1.0", "2.0"],
-  "unstable": ["3.0"]
+  "unstable": ["3.0", "3.0_tv"]
 }
--- a/devtools/client/webide/test/chrome.ini
+++ b/devtools/client/webide/test/chrome.ini
@@ -13,16 +13,20 @@ support-files =
   addons/fxos_2_0_simulator-linux.xpi
   addons/fxos_2_0_simulator-linux64.xpi
   addons/fxos_2_0_simulator-win32.xpi
   addons/fxos_2_0_simulator-mac64.xpi
   addons/fxos_3_0_simulator-linux.xpi
   addons/fxos_3_0_simulator-linux64.xpi
   addons/fxos_3_0_simulator-win32.xpi
   addons/fxos_3_0_simulator-mac64.xpi
+  addons/fxos_3_0_tv_simulator-linux.xpi
+  addons/fxos_3_0_tv_simulator-linux64.xpi
+  addons/fxos_3_0_tv_simulator-win32.xpi
+  addons/fxos_3_0_tv_simulator-mac64.xpi
   addons/adbhelper-linux.xpi
   addons/adbhelper-linux64.xpi
   addons/adbhelper-win32.xpi
   addons/adbhelper-mac64.xpi
   addons/fxdt-adapters-linux32.xpi
   addons/fxdt-adapters-linux64.xpi
   addons/fxdt-adapters-win32.xpi
   addons/fxdt-adapters-mac64.xpi
--- a/devtools/client/webide/test/test_simulators.html
+++ b/devtools/client/webide/test/test_simulators.html
@@ -96,23 +96,23 @@
           yield addonStatus(sim20, "installed");
 
           is(findAll(".runtime-panel-item-simulator").length, 2, "Two simulators in runtime panel");
 
           // Dry run a simulator to verify that its parameters look right.
 
           let params = yield runSimulator(0);
 
-          ok(params.path.contains(sim10.addonID) && params.path.contains("b2g-bin"), "Simulator binary path looks right");
+          ok(params.path.includes(sim10.addonID) && params.path.includes("b2g-bin"), "Simulator binary path looks right");
 
           let pid = params.args.indexOf("-profile");
           ok(pid > -1, "Simulator process arguments have --profile");
 
           let profilePath = params.args[pid + 1];
-          ok(profilePath.contains(sim10.addonID) && profilePath.contains("profile"), "Simulator profile path looks right");
+          ok(profilePath.includes(sim10.addonID) && profilePath.includes("profile"), "Simulator profile path looks right");
 
           ok(params.args.indexOf("-dbgport") > -1 || params.args.indexOf("-start-debugger-server") > -1, "Simulator process arguments have a debugger port");
 
           ok(params.args.indexOf("-no-remote") > -1, "Simulator process arguments have --no-remote");
 
           yield nextTick();
 
           // Configure the fake 1.0 simulator.
@@ -229,31 +229,31 @@
           is(params.args[pid + 1], fakeProfile.path, "Simulator process still uses custom profile directory");
 
           yield set(form.version, "custom");
 
           // Test `device`.
 
           let defaults = Simulator.prototype._defaults;
 
-          for (let param in defaults) {
-            is(form[param].value, String(defaults[param]), "Default value for device " + param);
+          for (let param in defaults.phone) {
+            is(form[param].value, String(defaults.phone[param]), "Default phone value for device " + param);
           }
 
           let width = 5000, height = 4000;
           yield set(form.width, width);
           yield set(form.height, height);
 
           is(form.device.value, "custom", "Device selector is custom");
 
           params = yield runSimulator(0);
 
           let sid = params.args.indexOf("-screen");
           ok(sid > -1, "Simulator process arguments have --screen");
-          ok(params.args[sid + 1].contains(width + "x" + height), "Simulator screen resolution looks right");
+          ok(params.args[sid + 1].includes(width + "x" + height), "Simulator screen resolution looks right");
 
           yield set(form.version, sim10.addonID);
 
           // Configure the fake 2.0 simulator.
 
           simulatorList.querySelectorAll(".configure-button")[1].click();
           yield nextTick();
 
@@ -272,54 +272,77 @@
           is(form.name.value, findAll(".runtime-panel-item-simulator")[1].textContent, "Deduplicated simulator name stayed consistent");
 
           yield set(form.version, sim20.addonID);
 
           is(form.name.value, customName + "2.0", "Name deduplication was undone when possible");
 
           // Test `device`.
 
-          for (let param in defaults) {
-            is(form[param].value, String(defaults[param]), "Default value for device " + param);
+          for (let param in defaults.phone) {
+            is(form[param].value, String(defaults.phone[param]), "Default phone value for device " + param);
           }
 
           let devices = yield GetDevices();
           devices = devices[devices.TYPES[0]];
           let device = devices[devices.length - 1];
 
           yield set(form.device, device.name);
 
           is(form.device.value, device.name, "Device selector was changed");
           is(form.width.value, String(device.width), "New device width is correct");
           is(form.height.value, String(device.height), "New device height is correct");
 
           params = yield runSimulator(1);
 
           sid = params.args.indexOf("-screen");
-          ok(params.args[sid + 1].contains(device.width + "x" + device.height), "Simulator screen resolution looks right");
+          ok(params.args[sid + 1].includes(device.width + "x" + device.height), "Simulator screen resolution looks right");
 
           // Restore default simulator options.
 
           doc.querySelector("#reset").click();
           yield nextTick();
 
-          for (let param in defaults) {
-            is(form[param].value, String(defaults[param]), "Default value for device " + param);
+          for (let param in defaults.phone) {
+            is(form[param].value, String(defaults.phone[param]), "Default phone value for device " + param);
+          }
+
+          // Install and configure the fake "Firefox OS 3.0 TV" simulator addon.
+
+          let sim30tv = addons.simulators.filter(a => a.version == "3.0_tv")[0];
+
+          sim30tv.install();
+
+          yield addonStatus(sim30tv, "installed");
+
+          is(findAll(".runtime-panel-item-simulator").length, 3, "Three simulators in runtime panel");
+
+          simulatorList.querySelectorAll(".configure-button")[2].click();
+          yield nextTick();
+
+          for (let param in defaults.television) {
+            is(form[param].value, String(defaults.television[param]), "Default TV value for device " + param);
           }
 
           // Force reload the list of simulators.
 
           Simulators._loadingPromise = null;
           Simulators._simulators = [];
           yield Simulators._load();
           yield nextTick();
 
-          is(findAll(".runtime-panel-item-simulator").length, 2, "Two simulators saved and reloaded " + Simulators._simulators.map(s => s.name).join(','));
+          is(findAll(".runtime-panel-item-simulator").length, 3, "Three simulators saved and reloaded " + Simulators._simulators.map(s => s.name).join(','));
+
+          // Uninstall the 3.0 TV and 2.0 addons, and watch their Simulator objects disappear.
 
-          // Uninstall the 2.0 addon and watch its Simulator object disappear.
+          sim30tv.uninstall();
+
+          yield addonStatus(sim30tv, "uninstalled");
+
+          is(findAll(".runtime-panel-item-simulator").length, 2, "Two simulators left in runtime panel");
 
           sim20.uninstall();
 
           yield addonStatus(sim20, "uninstalled");
 
           is(findAll(".runtime-panel-item-simulator").length, 1, "One simulator left in runtime panel");
 
           // Remove 1.0 simulator.
--- a/dom/icc/IccCallback.cpp
+++ b/dom/icc/IccCallback.cpp
@@ -33,46 +33,53 @@ IccContactToMozContact(JSContext* aCx, G
   // Names
   char16_t** rawStringArray = nullptr;
   uint32_t count = 0;
   nsresult rv = aIccContact->GetNames(&count, &rawStringArray);
   NS_ENSURE_SUCCESS(rv, rv);
   if (count > 0) {
     Sequence<nsString>& nameSeq = properties.mName.Construct().SetValue();
     for (uint32_t i = 0; i < count; i++) {
-      nameSeq.AppendElement(nsDependentString(rawStringArray[i]), fallible);
+      nameSeq.AppendElement(
+        rawStringArray[i] ? nsDependentString(rawStringArray[i])
+                          : EmptyString(),
+        fallible);
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray);
   }
 
   // Numbers
   rawStringArray = nullptr;
   count = 0;
   rv = aIccContact->GetNumbers(&count, &rawStringArray);
   NS_ENSURE_SUCCESS(rv, rv);
   if (count > 0) {
     Sequence<ContactTelField>& numberSeq = properties.mTel.Construct().SetValue();
     for (uint32_t i = 0; i < count; i++) {
       ContactTelField number;
-      number.mValue.Construct() = nsDependentString(rawStringArray[i]);
+      number.mValue.Construct() =
+        rawStringArray[i] ? nsDependentString(rawStringArray[i])
+                          : EmptyString();
       numberSeq.AppendElement(number, fallible);
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray);
   }
 
   // Emails
   rawStringArray = nullptr;
   count = 0;
   rv = aIccContact->GetEmails(&count, &rawStringArray);
   NS_ENSURE_SUCCESS(rv, rv);
   if (count > 0) {
     Sequence<ContactField>& emailSeq = properties.mEmail.Construct().SetValue();
     for (uint32_t i = 0; i < count; i++) {
       ContactField email;
-      email.mValue.Construct() = nsDependentString(rawStringArray[i]);
+      email.mValue.Construct() =
+        rawStringArray[i] ? nsDependentString(rawStringArray[i])
+                          : EmptyString();
       emailSeq.AppendElement(email, fallible);
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray);
   }
 
   ErrorResult er;
   RefPtr<mozContact> contact
     = mozContact::Constructor(aGlobal, aCx, properties, er);
--- a/dom/icc/IccContact.cpp
+++ b/dom/icc/IccContact.cpp
@@ -124,16 +124,21 @@ NS_IMETHODIMP IccContact::Get##_field(ui
     return NS_OK;                                                               \
   }                                                                             \
   char16_t** temp =                                                             \
     static_cast<char16_t**>(moz_xmalloc(sizeof(char16_t*) * (count)));          \
   if (temp == nullptr) {                                                        \
     return NS_ERROR_OUT_OF_MEMORY;                                              \
   }                                                                             \
   for (uint32_t i = 0; i < count; i++) {                                        \
+    if(m##_field[i].IsVoid()) {                                                 \
+      (temp)[i] = nullptr;                                                      \
+      continue;                                                                 \
+    }                                                                           \
+                                                                                \
     (temp)[i] = ToNewUnicode(m##_field[i]);                                     \
     if (!(temp)[i]) {                                                           \
       NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, temp);                           \
       return NS_ERROR_OUT_OF_MEMORY;                                            \
     }                                                                           \
   }                                                                             \
                                                                                 \
   *aCount = count;                                                              \
--- a/dom/icc/gonk/IccService.js
+++ b/dom/icc/gonk/IccService.js
@@ -81,23 +81,18 @@ CdmaIccInfo.prototype = {
 };
 
 function IccContact(aContact) {
   this.id = aContact.contactId || null;
   this._names = [];
   this._numbers = [];
   this._emails = [];
 
-  if (aContact.alphaId) {
-    this._names.push(aContact.alphaId);
-  }
-
-  if (aContact.number) {
-    this._numbers.push(aContact.number);
-  }
+  this._names.push(aContact.alphaId);
+  this._numbers.push(aContact.number);
 
   let anrLen = aContact.anr ? aContact.anr.length : 0;
   for (let i = 0; i < anrLen; i++) {
     this._numbers.push(aContact.anr[i]);
   }
 
   if (aContact.email) {
     this._emails.push(aContact.email);
--- a/dom/icc/ipc/IccIPCUtils.cpp
+++ b/dom/icc/ipc/IccIPCUtils.cpp
@@ -46,41 +46,47 @@ IccIPCUtils::GetIccContactDataFromIccCon
 
   // Names
   char16_t** rawStringArray = nullptr;
   uint32_t count = 0;
   rv = aContact->GetNames(&count, &rawStringArray);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (count > 0) {
     for (uint32_t i = 0; i < count; i++) {
-      aOutData.names().AppendElement(nsDependentString(rawStringArray[i]));
+      aOutData.names().AppendElement(
+        rawStringArray[i] ? nsDependentString(rawStringArray[i])
+                          : NullString());
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray);
   }
 
   // Numbers
   rawStringArray = nullptr;
   count = 0;
   rv = aContact->GetNumbers(&count, &rawStringArray);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (count > 0) {
     for (uint32_t i = 0; i < count; i++) {
-      aOutData.numbers().AppendElement(nsDependentString(rawStringArray[i]));
+      aOutData.numbers().AppendElement(
+        rawStringArray[i] ? nsDependentString(rawStringArray[i])
+                          : NullString());
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray);
   }
 
   // Emails
   rawStringArray = nullptr;
   count = 0;
   rv = aContact->GetEmails(&count, &rawStringArray);
   NS_ENSURE_SUCCESS_VOID(rv);
   if (count > 0) {
     for (uint32_t i = 0; i < count; i++) {
-      aOutData.emails().AppendElement(nsDependentString(rawStringArray[i]));
+      aOutData.emails().AppendElement(
+        rawStringArray[i] ? nsDependentString(rawStringArray[i])
+                          : NullString());
     }
     NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(count, rawStringArray);
   }
 }
 
 } // namespace icc
 } // namespace dom
 } // namespace mozilla
\ No newline at end of file
--- a/dom/icc/tests/marionette/test_icc_contact_add.js
+++ b/dom/icc/tests/marionette/test_icc_contact_add.js
@@ -25,16 +25,24 @@ var TEST_ADD_DATA = [{
     // a contact with anr but without email.
     name: ["add5"],
     tel: [{value: "01234567890123456789"}, {value: "123456"}, {value: "123"}],
   }, {
     // a contact with email and anr.
     name: ["add6"],
     tel: [{value: "01234567890123456789"}, {value: "123456"}, {value: "123"}],
     email:[{value: "test@mozilla.com"}],
+  }, {
+    // a contact without number.
+    name: ["add7"],
+    tel: [{value: ""}],
+  }, {
+    // a contact without name.
+    name: [""],
+    tel: [{value: "0987654321"}],
   }];
 
 function testAddContact(aIcc, aType, aMozContact, aPin2) {
   log("testAddContact: type=" + aType + ", pin2=" + aPin2);
   let contact = new mozContact(aMozContact);
 
   return aIcc.updateContact(aType, contact, aPin2)
     .then((aResult) => {
--- a/dom/icc/tests/marionette/test_icc_contact_update.js
+++ b/dom/icc/tests/marionette/test_icc_contact_update.js
@@ -20,17 +20,17 @@ const TEST_UPDATE_DATA = [{
       // We don't support extension chain now.
       number: "9876543210987654321099887766554433221100"}
   }, {
     id: 3,
     data: {
       name: ["Fire 火"],
       tel: [{value: ""}]},
     expect: {
-      number: null}
+      number: ""}
   }, {
     id: 5,
     data: {
       name: ["Contact001"],
       tel: [{value: "9988776655443322110098765432109876543210"}]},
     expect: {
       number: "9988776655443322110098765432109876543210"}
   }, {
@@ -47,22 +47,18 @@ function testUpdateContact(aIcc, aType, 
       ", mozContact=" + JSON.stringify(aMozContact) +
       ", expect=" + aExpect.number + ", pin2=" + aPin2);
 
   let contact = new mozContact(aMozContact);
   contact.id = aIcc.iccInfo.iccid + aContactId;
 
   return aIcc.updateContact(aType, contact, aPin2)
     .then((aResult) => {
-      if (aExpect.number === null) {
-        is(aResult.tel, null);
-      } else {
-        is(aResult.tel[0].value, aExpect.number);
-        ok(aResult.tel.length == 1);
-      }
+      is(aResult.tel[0].value, aExpect.number);
+      ok(aResult.tel.length == 1);
       // We only support SIM in emulator, so we don't have anr and email field.
       ok(!aResult.email);
       is(contact.id, aIcc.iccInfo.iccid + aContactId);
     }, (aError) => {
       if (aType === "fdn" && aPin2 === undefined) {
         ok(aError.name === "SimPin2",
            "expected error when pin2 is not provided");
       } else {
@@ -96,21 +92,17 @@ function testUpdateContacts(aIcc, aType,
   promise = promise.then(() => aIcc.readContacts(aType))
   .then((aResult) => {
     for (let i = 0; i < TEST_UPDATE_DATA.length; i++) {
       let expectedResult = TEST_UPDATE_DATA[i];
       let contact = aResult[expectedResult.id - 1];
 
       is(contact.name[0], expectedResult.data.name[0]);
       is(contact.id, aIcc.iccInfo.iccid + expectedResult.id);
-      if (expectedResult.expect.number === null) {
-        is(contact.tel, null);
-      } else {
-        is(contact.tel[0].value, expectedResult.expect.number);
-      }
+      is(contact.tel[0].value, expectedResult.expect.number);
     }
     return revertContacts(aIcc, aCacheContacts, aType, aPin2);
   });
 
   return promise;
 }
 
 // Start tests
--- a/dom/ipc/ProcessPriorityManager.cpp
+++ b/dom/ipc/ProcessPriorityManager.cpp
@@ -341,16 +341,17 @@ public:
   void Freeze();
   void Unfreeze();
 
   void ShutDown();
 
 private:
   static uint32_t sBackgroundPerceivableGracePeriodMS;
   static uint32_t sBackgroundGracePeriodMS;
+  static uint32_t sMemoryPressureGracePeriodMS;
 
   void FireTestOnlyObserverNotification(
     const char* aTopic,
     const nsACString& aData = EmptyCString());
 
   void FireTestOnlyObserverNotification(
     const char* aTopic,
     const char* aData = nullptr);
@@ -365,28 +366,30 @@ private:
   bool mFrozen;
 
   /**
    * Used to implement NameWithComma().
    */
   nsAutoCString mNameWithComma;
 
   nsCOMPtr<nsITimer> mResetPriorityTimer;
+  nsCOMPtr<nsITimer> mMemoryPressureTimer;
 };
 
 /* static */ bool ProcessPriorityManagerImpl::sInitialized = false;
 /* static */ bool ProcessPriorityManagerImpl::sPrefsEnabled = false;
 /* static */ bool ProcessPriorityManagerImpl::sRemoteTabsDisabled = true;
 /* static */ bool ProcessPriorityManagerImpl::sTestMode = false;
 /* static */ bool ProcessPriorityManagerImpl::sPrefListenersRegistered = false;
 /* static */ bool ProcessPriorityManagerImpl::sFrozen = false;
 /* static */ StaticRefPtr<ProcessPriorityManagerImpl>
   ProcessPriorityManagerImpl::sSingleton;
 /* static */ uint32_t ParticularProcessPriorityManager::sBackgroundPerceivableGracePeriodMS = 0;
 /* static */ uint32_t ParticularProcessPriorityManager::sBackgroundGracePeriodMS = 0;
+/* static */ uint32_t ParticularProcessPriorityManager::sMemoryPressureGracePeriodMS = 0;
 
 NS_IMPL_ISUPPORTS(ProcessPriorityManagerImpl,
                   nsIObserver,
                   nsISupportsWeakReference);
 
 /* static */ void
 ProcessPriorityManagerImpl::PrefChangedCallback(const char* aPref,
                                                 void* aClosure)
@@ -696,16 +699,18 @@ ParticularProcessPriorityManager::Partic
 
 void
 ParticularProcessPriorityManager::StaticInit()
 {
   Preferences::AddUintVarCache(&sBackgroundPerceivableGracePeriodMS,
                                "dom.ipc.processPriorityManager.backgroundPerceivableGracePeriodMS");
   Preferences::AddUintVarCache(&sBackgroundGracePeriodMS,
                                "dom.ipc.processPriorityManager.backgroundGracePeriodMS");
+  Preferences::AddUintVarCache(&sMemoryPressureGracePeriodMS,
+                               "dom.ipc.processPriorityManager.memoryPressureGracePeriodMS");
 }
 
 void
 ParticularProcessPriorityManager::Init()
 {
   RegisterWakeLockObserver(this);
 
   nsCOMPtr<nsIObserverService> os = services::GetObserverService();
@@ -1009,20 +1014,31 @@ ParticularProcessPriorityManager::Schedu
   LOGP("Scheduling reset timer to fire in %dms.", timeout);
   mResetPriorityTimer = do_CreateInstance("@mozilla.org/timer;1");
   mResetPriorityTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT);
 }
 
 NS_IMETHODIMP
 ParticularProcessPriorityManager::Notify(nsITimer* aTimer)
 {
-  LOGP("Reset priority timer callback; about to ResetPriorityNow.");
-  ResetPriorityNow();
-  mResetPriorityTimer = nullptr;
-  return NS_OK;
+  if (mResetPriorityTimer == aTimer) {
+    LOGP("Reset priority timer callback; about to ResetPriorityNow.");
+    ResetPriorityNow();
+    mResetPriorityTimer = nullptr;
+    return NS_OK;
+  }
+
+  if (mContentParent && mMemoryPressureTimer == aTimer) {
+    Unused << mContentParent->SendFlushMemory(NS_LITERAL_STRING("lowering-priority"));
+    mMemoryPressureTimer = nullptr;
+    return NS_OK;
+  }
+
+  NS_WARNING("Unexpected timer!");
+  return NS_ERROR_INVALID_POINTER;
 }
 
 bool
 ParticularProcessPriorityManager::HasAppType(const char* aAppType)
 {
   const ManagedContainer<PBrowserParent>& browsers =
     mContentParent->ManagedPBrowserParent();
   for (auto iter = browsers.ConstIter(); !iter.Done(); iter.Next()) {
@@ -1137,20 +1153,28 @@ ParticularProcessPriorityManager::SetPri
   mPriority = aPriority;
   hal::SetProcessPriority(Pid(), mPriority);
 
   if (oldPriority != mPriority) {
     ProcessPriorityManagerImpl::GetSingleton()->
       NotifyProcessPriorityChanged(this, oldPriority);
 
     Unused << mContentParent->SendNotifyProcessPriorityChanged(mPriority);
-  }
+
+    if (mMemoryPressureTimer) {
+      mMemoryPressureTimer->Cancel();
+      mMemoryPressureTimer = nullptr;
+    }
 
-  if (aPriority < PROCESS_PRIORITY_FOREGROUND) {
-    Unused << mContentParent->SendFlushMemory(NS_LITERAL_STRING("lowering-priority"));
+    if (aPriority < PROCESS_PRIORITY_FOREGROUND) {
+      mMemoryPressureTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+      mMemoryPressureTimer->InitWithCallback(this,
+                                             sMemoryPressureGracePeriodMS,
+                                             nsITimer::TYPE_ONE_SHOT);
+    }
   }
 
   FireTestOnlyObserverNotification("process-priority-set",
     ProcessPriorityToString(mPriority));
 }
 
 void
 ParticularProcessPriorityManager::Freeze()
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -8684,17 +8684,17 @@ ICCPDUHelperObject.prototype = {
 
   /**
    * Write GSM 8-bit unpacked octets.
    *
    * @param numOctets   Number of total octets to be writen, including trailing
    *                    0xff.
    * @param str         String to be written. Could be null.
    *
-   * @return The string has been written into Buf.
+   * @return The string has been written into Buf. "" if str is null.
    */
   writeStringTo8BitUnpacked: function(numOctets, str) {
     const langTable = PDU_NL_LOCKING_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
     const langShiftTable = PDU_NL_SINGLE_SHIFT_TABLES[PDU_NL_IDENTIFIER_DEFAULT];
 
     let GsmPDUHelper = this.context.GsmPDUHelper;
 
     // If the character is GSM extended alphabet, two octets will be written.
@@ -8724,17 +8724,17 @@ ICCPDUHelperObject.prototype = {
       j++;
     }
 
     // trailing 0xff
     while (j++ < numOctets) {
       GsmPDUHelper.writeHexOctet(0xff);
     }
 
-    return (str) ? str.substring(0, i) : null;
+    return (str) ? str.substring(0, i) : "";
   },
 
   /**
    * Write UCS2 String on UICC.
    * The default choose 0x81 or 0x82 encode, otherwise use 0x80 encode.
    *
    * @see TS 102.221, Annex A.
    * @param numOctets
@@ -9085,17 +9085,17 @@ ICCPDUHelperObject.prototype = {
    *        Alpha Identifier to be written.
    *
    * @return The Alpha Identifier has been written into Buf.
    *
    * Unused octets will be written as 0xff.
    */
   writeAlphaIdentifier: function(numOctets, alphaId) {
     if (numOctets === 0) {
-      return null;
+      return "";
     }
 
     // If alphaId is empty or it's of GSM 8 bit.
     if (!alphaId || this.context.ICCUtilsHelper.isGsm8BitAlphabet(alphaId)) {
       return this.writeStringTo8BitUnpacked(numOctets, alphaId);
     } else {
       return this.writeICCUCS2String(numOctets, alphaId);
     }
@@ -9217,17 +9217,17 @@ ICCPDUHelperObject.prototype = {
         GsmPDUHelper.writeHexOctet(0xff);
       }
       return writtenNumber;
     } else {
       // +1 for numLen
       for (let i = 0; i < ADN_MAX_BCD_NUMBER_BYTES + 1; i++) {
         GsmPDUHelper.writeHexOctet(0xff);
       }
-      return null;
+      return "";
     }
   }
 };
 
 function StkCommandParamsFactoryObject(aContext) {
   this.context = aContext;
 }
 StkCommandParamsFactoryObject.prototype = {
--- a/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
+++ b/dom/system/gonk/tests/test_ril_worker_icc_ICCPDUHelper.js
@@ -362,17 +362,17 @@ add_test(function test_write_alpha_ident
   let context = worker.ContextPool._contexts[0];
   let helper = context.GsmPDUHelper;
   let iccHelper = context.ICCPDUHelper;
   // Length of trailing 0xff.
   let ffLen = 2;
 
   // Removal
   let writenAlphaId = iccHelper.writeAlphaIdentifier(10, null);
-  equal(writenAlphaId, null);
+  equal(writenAlphaId, "");
   equal(iccHelper.readAlphaIdentifier(10), "");
 
   // GSM 8 bit
   let str = "Mozilla";
   writenAlphaId = iccHelper.writeAlphaIdentifier(str.length + ffLen, str);
   equal(writenAlphaId , str);
   equal(iccHelper.readAlphaIdentifier(str.length + ffLen), str);
 
@@ -396,17 +396,17 @@ add_test(function test_write_alpha_ident
   writenAlphaId = iccHelper.writeAlphaIdentifier(4, str);
   helper.writeHexOctet(0xff); // dummy octet.
   equal(writenAlphaId , str.substring(0, 1));
   equal(iccHelper.readAlphaIdentifier(5), str.substring(0, 1));
 
   // Write 0 octet.
   writenAlphaId = iccHelper.writeAlphaIdentifier(0, "1");
   helper.writeHexOctet(0xff); // dummy octet.
-  equal(writenAlphaId, null);
+  equal(writenAlphaId, "");
   equal(iccHelper.readAlphaIdentifier(1), "");
 
   run_next_test();
 });
 
 /**
  * Verify ICCPDUHelper.readAlphaIdDiallingNumber
  */
@@ -485,18 +485,18 @@ add_test(function test_write_alpha_id_di
   equal(writtenContact.alphaId, contactR.alphaId);
   equal(writtenContact.number, contactR.number);
   equal(0xff, contactR.extRecordNumber);
 
   // Write a null contact (Removal).
   writtenContact = helper.writeAlphaIdDiallingNumber(recordSize);
   contactR = helper.readAlphaIdDiallingNumber(recordSize);
   equal(contactR, null);
-  equal(writtenContact.alphaId, null);
-  equal(writtenContact.number, null);
+  equal(writtenContact.alphaId, "");
+  equal(writtenContact.number, "");
 
   // Write a longer alphaId/dialling number
   // Dialling Number : Maximum 20 digits(10 octets).
   // Alpha Identifier: 32(recordSize) - 14 (10 octets for Dialling Number, 1
   //                   octet for TON/NPI, 1 for number length octet, and 2 for
   //                   Ext) = Maximum 18 octets.
   let longContact = {
     alphaId: "AAAAAAAAABBBBBBBBBCCCCCCCCC",
--- a/testing/mozharness/configs/b2g/taskcluster-phone-ota.py
+++ b/testing/mozharness/configs/b2g/taskcluster-phone-ota.py
@@ -33,16 +33,17 @@ config = {
             "post_upload_cmd": "post_upload.py --tinderbox-builds-dir %(branch)s-%(target)s -p b2g -i %(buildid)s --revision %(revision)s --release-to-tinderbox-dated-builds",
             "post_upload_nightly_cmd": "post_upload.py --tinderbox-builds-dir %(branch)s-%(target)s -b %(branch)s-%(target)s -p b2g -i %(buildid)s --revision %(revision)s --release-to-tinderbox-dated-builds --release-to-latest --release-to-dated",
         },
     },
     "env": {
         "GAIA_OPTIMIZE": "1",
         "WGET_OPTS": "-c -q"
     },
+    "update_types": [ "ota", "fota" ],
     "is_automation": True,
     "repo_remote_mappings": {
         'https://android.googlesource.com/': 'https://git.mozilla.org/external/aosp',
         'git://codeaurora.org/': 'https://git.mozilla.org/external/caf',
         'https://git.mozilla.org/b2g': 'https://git.mozilla.org/b2g',
         'git://github.com/mozilla-b2g/': 'https://git.mozilla.org/b2g',
         'git://github.com/mozilla/': 'https://git.mozilla.org/b2g',
         'https://git.mozilla.org/releases': 'https://git.mozilla.org/releases',
--- a/testing/mozharness/configs/b2g/taskcluster-spark-dogfood.py
+++ b/testing/mozharness/configs/b2g/taskcluster-spark-dogfood.py
@@ -2,32 +2,32 @@
 import os.path
 config = {
     "default_vcs": "tc-vcs",
     "default_actions": [
         'checkout-sources',
         'build',
         'build-symbols',
         'make-updates',
-        'prep-upload',
-        'submit-to-balrog'
+        'prep-upload'
     ],
-    "balrog_credentials_file": "balrog_credentials",
     "nightly_build": True,
     "env": {
         "GAIA_OPTIMIZE": "1",
         "B2G_UPDATER": "1",
         "LIGHTSABER": "1",
         "DOGFOOD": "1",
         "B2G_UPDATE_CHANNEL": "dogfood",
         "BOWER_FLAGS": "--allow-root",
         "B2G_PATH": "%(work_dir)s",
         "GAIA_DISTRIBUTION_DIR": "%(work_dir)s/gaia/distros/spark",
-        "WGET_OPTS": "-c -q"
+        "WGET_OPTS": "-c -q",
+        "B2G_FOTA_FULLIMG_PARTS": "/boot:boot.img /system:system.img /recovery:recovery.img"
     },
+    "update_types": [ "ota", "fota", "fota:fullimg" ],
     "is_automation": True,
     "repo_remote_mappings": {
         'https://android.googlesource.com/': 'https://git.mozilla.org/external/aosp',
         'git://codeaurora.org/': 'https://git.mozilla.org/external/caf',
         'https://git.mozilla.org/b2g': 'https://git.mozilla.org/b2g',
         'git://github.com/mozilla-b2g/': 'https://git.mozilla.org/b2g',
         'git://github.com/mozilla/': 'https://git.mozilla.org/b2g',
         'https://git.mozilla.org/releases': 'https://git.mozilla.org/releases',
--- a/testing/mozharness/scripts/b2g_build.py
+++ b/testing/mozharness/scripts/b2g_build.py
@@ -160,24 +160,26 @@ class B2GBuild(LocalesMixin, PurgeMixin,
             all_actions=all_actions,
             default_actions=default_actions,
         )
 
         dirs = self.query_abs_dirs()
         self.objdir = self.config.get("gecko_objdir",
                 os.path.join(dirs['work_dir'], 'objdir-gecko'))
         self.abs_dirs['abs_obj_dir'] = self.objdir
-        if self.config.get("update_type", "ota") == "fota":
-            self.make_updates_cmd = ['./build.sh', 'gecko-update-fota']
-            self.extra_update_attrs = 'isOsUpdate="true"'
-            self.isOSUpdate = True
+
+        # Evaluating the update type to build.
+        # Default is OTA if config do not specifies anything
+        if "update_types" in self.config:
+            self.update_types = self.config["update_types"]
+        elif "update_type" in self.config:
+            self.update_types = [self.config["update_type"]]
         else:
-            self.make_updates_cmd = ['./build.sh', 'gecko-update-full']
-            self.extra_update_attrs = None
-            self.isOSUpdate = False
+            self.update_types = ["ota"]
+
         self.package_urls = {}
 
         # We need to create the virtualenv directly (without using an action) in
         # order to use python modules in PreScriptRun/Action listeners
         self.create_virtualenv()
 
     def query_abs_dirs(self):
         if self.abs_dirs:
@@ -301,41 +303,65 @@ class B2GBuild(LocalesMixin, PurgeMixin,
             devicedir = dotconfig['DEVICE']
         elif 'PRODUCT_NAME' in dotconfig:
             devicedir = dotconfig['PRODUCT_NAME']
         else:
             self.fatal("Couldn't determine device directory")
         output_dir = os.path.join(dirs['work_dir'], 'out', 'target', 'product', devicedir)
         return output_dir
 
+    def query_device_name(self):
+        return os.path.basename(self.query_device_outputdir())
+
     def query_application_ini(self):
         return os.path.join(self.query_device_outputdir(), 'system', 'b2g', 'application.ini')
 
-    def query_marfile_path(self):
-        if self.config.get("update_type", "ota") == "fota":
+    def query_marfile_path(self, update_type):
+        if update_type.startswith("fota"):
             mardir = self.query_device_outputdir()
         else:
             mardir = "%s/dist/b2g-update" % self.objdir
 
+        device_name = self.query_device_name()
+        update_type_files = {
+            'ota':          'b2g-%s-gecko-update.mar'    % device_name,
+            'fota':         'fota-%s-update.mar'         % device_name,
+            'fota:full':    'fota-%s-update-full.mar'    % device_name,
+            'fota:fullimg': 'fota-%s-update-fullimg.mar' % device_name
+        }
+
         mars = []
         for f in os.listdir(mardir):
-            if f.endswith(".mar"):
+            if f.endswith(update_type_files[update_type]):
                 mars.append(f)
 
-        if len(mars) != 1:
+        if len(mars) < 1:
             self.fatal("Found none or too many marfiles in %s, don't know what to do:\n%s" % (mardir, mars), exit_code=1)
 
         return "%s/%s" % (mardir, mars[0])
 
-    def query_complete_mar_url(self):
+    def query_complete_mar_url(self, marfile=None):
+        mar_url = None
         if "complete_mar_url" in self.config:
-            return self.config["complete_mar_url"]
-        if "completeMarUrl" in self.package_urls:
-            return self.package_urls["completeMarUrl"]
-        self.fatal("Couldn't find complete mar url in config or package_urls")
+            mar_url = self.config["complete_mar_url"]
+        elif "completeMarUrl" in self.package_urls:
+            mar_url = self.package_urls["completeMarUrl"]
+        else:
+            self.fatal("Couldn't find complete mar url in config or package_urls")
+
+        # To support OTA and FOTA update payload, we cannot rely on the filename
+        # being computed before we get called since we will determine the filename
+        # ourselves. Let's detect when the URL does not ends with ".mar" and in
+        # this case, we append the MAR file we just collected
+        if not mar_url.endswith(".mar"):
+            if marfile is not None:
+                self.fatal("URL does not contains a MAR file and none found")
+            mar_url = os.path.join(mar_url, os.path.basename(marfile))
+
+        return mar_url
 
     # Actions {{{2
     def clobber(self):
         dirs = self.query_abs_dirs()
         PurgeMixin.clobber(
             self,
             always_clobber_dirs=[
                 dirs['abs_upload_dir'],
@@ -608,46 +634,49 @@ class B2GBuild(LocalesMixin, PurgeMixin,
             self.enable_mock()
             retval = self.run_command(cmd, cwd=dirs['work_dir'], env=env, error_list=B2GMakefileErrorList)
             self.disable_mock()
 
             if retval != 0:
                 self.fatal("failed to upload symbols", exit_code=2)
 
     def make_updates(self):
-        if not self.query_is_nightly():
-            self.info("Not a nightly build. Skipping...")
-            return
+        if not self.update_types:
+            self.fatal("No update types defined. We should have had at least defaulted to OTA ...")
+
         dirs = self.query_abs_dirs()
+
         self.load_gecko_config()
-        cmd = self.make_updates_cmd[:]
+
         env = self.query_build_env()
 
-        self.enable_mock()
-        retval = self.run_command(cmd, cwd=dirs['work_dir'], env=env, error_list=B2GMakefileErrorList)
-        self.disable_mock()
+        for update_type in self.update_types:
+            # Defaulting to OTA
+            make_target = "gecko-update-full"
 
-        if retval != 0:
-            self.fatal("failed to create complete update", exit_code=2)
+            # Building a FOTA with only Gecko/Gaia (+ a few redistribuable)
+            if update_type == "fota":
+                make_target = "gecko-update-fota"
 
-        # Sign the updates
-        self.sign_updates()
+            # Building a FOTA with all system partition files
+            if update_type == "fota:full":
+                make_target = "gecko-update-fota-full"
 
-    def sign_updates(self):
-        if 'MOZ_SIGNING_SERVERS' not in os.environ:
-            self.info("Skipping signing since no MOZ_SIGNING_SERVERS set")
-            return
+            # Building a FOTA with full partitions images
+            if update_type == "fota:fullimg":
+                make_target = "gecko-update-fota-fullimg"
+
+            cmd = ['./build.sh', make_target]
 
-        self.checkout_tools()
-        cmd = self.query_moz_sign_cmd(formats=['b2gmar'])
-        cmd.append(self.query_marfile_path())
+            self.enable_mock()
+            retval = self.run_command(cmd, cwd=dirs['work_dir'], env=env, error_list=B2GMakefileErrorList)
+            self.disable_mock()
 
-        retval = self.run_command(cmd)
-        if retval != 0:
-            self.fatal("failed to sign complete update", exit_code=2)
+            if retval != 0:
+                self.fatal("failed to create update", exit_code=2)
 
     def prep_upload(self):
         if not self.query_do_upload():
             self.info("Uploads disabled for this build. Skipping...")
             return
 
         dirs = self.query_abs_dirs()
 
@@ -717,18 +746,17 @@ class B2GBuild(LocalesMixin, PurgeMixin,
         for base_pattern in upload_patterns + public_upload_patterns:
             pattern = base_pattern.format(objdir=self.objdir, workdir=dirs['work_dir'], srcdir=dirs['gecko_src'])
             for f in glob.glob(pattern):
                 if base_pattern in upload_patterns:
                     files.append(f)
                 if base_pattern in public_upload_patterns:
                     public_files.append(f)
 
-        device_name   = os.path.basename(output_dir)
-        blobfree_dist = device_name + '.blobfree-dist.zip'
+        blobfree_dist = self.query_device_name() + '.blobfree-dist.zip'
         blobfree_zip  = os.path.join(output_dir, blobfree_dist)
 
         if os.path.exists(blobfree_zip):
             public_files.append(blobfree_zip)
 
         for base_f in files + public_files:
             f = base_f
             if f.endswith(".img"):
@@ -1076,42 +1104,44 @@ class B2GBuild(LocalesMixin, PurgeMixin,
             return
 
         if not self.config.get("balrog_servers"):
             self.info("balrog_servers not set; skipping balrog submission.")
             return
 
         self.checkout_tools()
 
-        marfile = self.query_marfile_path()
-        # Need to update the base url to point at FTP, or better yet, read post_upload.py output?
-        mar_url = self.query_complete_mar_url()
+        for update_type in self.update_types:
+            marfile = self.query_marfile_path(update_type)
+            # Need to update the base url to point at FTP, or better yet, read
+            # post_upload.py output?
+            mar_url = self.query_complete_mar_url(marfile)
 
-        # Set other necessary properties for Balrog submission. None need to
-        # be passed back to buildbot, so we won't write them to the properties
-        # files.
-        # Locale is hardcoded to en-US, for silly reasons
-        self.set_buildbot_property("locale", "en-US")
-        self.set_buildbot_property("appVersion", self.query_version())
-        # The Balrog submitter translates this platform into a build target
-        # via https://github.com/mozilla/build-tools/blob/master/lib/python/release/platforms.py#L23
-        if "platform" in self.config:
-            self.set_buildbot_property("platform", self.config["platform"])
-        else:
-            self.set_buildbot_property("platform", self.buildbot_config["properties"]["platform"])
-        # TODO: Is there a better way to get this?
-        self.set_buildbot_property("appName", "B2G")
-        # TODO: don't hardcode
-        self.set_buildbot_property("hashType", "sha512")
-        self.set_buildbot_property("completeMarSize", self.query_filesize(marfile))
-        self.set_buildbot_property("completeMarHash", self.query_sha512sum(marfile))
-        self.set_buildbot_property("completeMarUrl", mar_url)
-        self.set_buildbot_property("isOSUpdate", self.isOSUpdate)
+            # Set other necessary properties for Balrog submission. None need to
+            # be passed back to buildbot, so we won't write them to the properties
+            # files.
+            # Locale is hardcoded to en-US, for silly reasons
+            self.set_buildbot_property("locale", "en-US")
+            self.set_buildbot_property("appVersion", self.query_version())
+            # The Balrog submitter translates this platform into a build target
+            # via https://github.com/mozilla/build-tools/blob/master/lib/python/release/platforms.py#L23
+            if "platform" in self.config:
+                self.set_buildbot_property("platform", self.config["platform"])
+            else:
+                self.set_buildbot_property("platform", self.buildbot_config["properties"]["platform"])
+            # TODO: Is there a better way to get this?
+            self.set_buildbot_property("appName", "B2G")
+            # TODO: don't hardcode
+            self.set_buildbot_property("hashType", "sha512")
+            self.set_buildbot_property("completeMarSize", self.query_filesize(marfile))
+            self.set_buildbot_property("completeMarHash", self.query_sha512sum(marfile))
+            self.set_buildbot_property("completeMarUrl", mar_url)
+            self.set_buildbot_property("isOSUpdate", update_type.startswith("fota"))
 
-        self.submit_balrog_updates(product='b2g')
+            self.submit_balrog_updates(product='b2g')
 
     @PostScriptRun
     def _remove_userconfig(self):
         self.info("Cleanup .userconfig file.")
         dirs = self.query_abs_dirs()
         userconfig_path = os.path.join(dirs["work_dir"], ".userconfig")
         os.remove(userconfig_path)
 
--- a/testing/taskcluster/scripts/phone-builder/build-phone-ota.sh
+++ b/testing/taskcluster/scripts/phone-builder/build-phone-ota.sh
@@ -6,17 +6,16 @@ if [ $TARGET == "aries" -o $TARGET == "s
   # caching objects might be dangerous for some devices (aka aries)
   rm -rf $gecko_objdir
   rm -rf $WORKSPACE/B2G/out
 fi
 
 PLATFORM=${TARGET%%-*}
 
 aws s3 cp s3://b2g-nightly-credentials/balrog_credentials .
-mar_file=b2g-$PLATFORM-gecko-update.mar
 
 # We need different platform names for each variant (user, userdebug and
 # eng). We do not append variant suffix for "user" to keep compability with
 # verions already installed in the phones.
 if [ 0$DOGFOOD -ne 1 -a $VARIANT != "user" ]; then
   PLATFORM=$PLATFORM-$VARIANT
 fi
 
@@ -36,11 +35,11 @@ rm -rf $WORKSPACE/B2G/upload/
   --gaia-languages-file locales/languages_all.json \
   --log-level=debug \
   --target=$TARGET \
   --b2g-config-dir=$TARGET \
   --checkout-revision=$GECKO_HEAD_REV \
   --repo=$WORKSPACE/gecko \
   --platform $PLATFORM \
   --gecko-objdir=$gecko_objdir \
-  --complete-mar-url https://queue.taskcluster.net/v1/task/$TASK_ID/runs/$RUN_ID/artifacts/public/build/$mar_file
+  --complete-mar-url https://queue.taskcluster.net/v1/task/$TASK_ID/runs/$RUN_ID/artifacts/public/build/
 
 . post-build.sh
--- a/testing/taskcluster/scripts/phone-builder/post-build.sh
+++ b/testing/taskcluster/scripts/phone-builder/post-build.sh
@@ -12,22 +12,38 @@ mkdir -p $HOME/artifacts-public
 
 DEVICE=${TARGET%%-*}
 
 mv $WORKSPACE/B2G/upload/sources.xml $HOME/artifacts/sources.xml
 mv $WORKSPACE/B2G/upload/b2g-*.android-arm.tar.gz $HOME/artifacts/b2g-android-arm.tar.gz
 mv $WORKSPACE/B2G/upload/${TARGET}.zip $HOME/artifacts/${TARGET}.zip
 mv $WORKSPACE/B2G/upload/gaia.zip $HOME/artifacts/gaia.zip
 
+# Upload public images as public artifacts on Nexus 4 KK and Nexus 5 L
+if [ "${TARGET}" = "nexus-4-kk" -o "${TARGET}" = "nexus-5-l" ]; then
+  mv $HOME/artifacts/${TARGET}.zip $HOME/artifacts-public/
+fi
+
 if [ -f $WORKSPACE/B2G/upload/b2g-*.crashreporter-symbols.zip ]; then
   mv $WORKSPACE/B2G/upload/b2g-*.crashreporter-symbols.zip $HOME/artifacts/b2g-crashreporter-symbols.zip
 fi
 
 if [ -f $WORKSPACE/B2G/upload-public/*.blobfree-dist.zip ]; then
   mv $WORKSPACE/B2G/upload-public/*.blobfree-dist.zip $HOME/artifacts-public/
 fi
 
-if [ -f $WORKSPACE/B2G/upload-public/$mar_file ]; then
-  mv $WORKSPACE/B2G/upload-public/$mar_file $HOME/artifacts-public/
+# FOTA full and fullimg might contain blobs
+if [ -f $WORKSPACE/B2G/upload/fota-*-update-*.mar ]; then
+  mv $WORKSPACE/B2G/upload/fota-*-update-*.mar $HOME/artifacts/
+fi
+
+# Gecko/Gaia OTA is clean
+if [ -f $WORKSPACE/B2G/upload-public/b2g-*-gecko-update.mar ]; then
+  mv $WORKSPACE/B2G/upload-public/b2g-*-gecko-update.mar $HOME/artifacts-public/
+fi
+
+# Gecko/Gaia FOTA is clean
+if [ -f $WORKSPACE/B2G/upload-public/fota-*-update.mar ]; then
+  mv $WORKSPACE/B2G/upload-public/fota-*-update.mar $HOME/artifacts-public/
 fi
 
 ccache -s
 
--- a/testing/taskcluster/tasks/branches/base_job_flags.yml
+++ b/testing/taskcluster/tasks/branches/base_job_flags.yml
@@ -56,16 +56,17 @@ flags:
     - linux32_gecko  # b2g desktop linux 32 bit
     - linux64_gecko  # b2g desktop linux 64 bit
     - linux64-mulet  # Firefox desktop - b2g gecko linux 64 bit
     - macosx64_gecko # b2g desktop osx 64 bit
     - win32_gecko    # b2g desktop win 32 bit
     - flame-kk       # b2g flame kitkat
     - flame-kk-eng   # b2g flame eng build
     - flame-kk-spark-eng
+    - flame-kk-ota
     - nexus-4
     - nexus-4-eng
     - nexus-4-kk
     - nexus-4-kk-eng
     - nexus-5l
     - nexus-5l-eng
     - dolphin
     - dolphin-eng
--- a/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml
+++ b/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml
@@ -26,14 +26,22 @@ builds:
   aries-ota:
     platforms:
       - b2g
     types:
       opt:
         task: tasks/builds/b2g_aries_spark_ota_opt.yml
       debug:
         task: tasks/builds/b2g_aries_spark_ota_debug.yml
+  flame-kk-ota:
+    platforms:
+      - b2g
+    types:
+      opt:
+        task: tasks/builds/b2g_flame_kk_ota_opt.yml
+      debug:
+        task: tasks/builds/b2g_flame_kk_ota_debug.yml
 
 post-build:
   simulator:
     allowed_build_tasks:
       - tasks/builds/mulet_linux.yml
     task: tasks/post-builds/mulet_simulator.yml
--- a/testing/taskcluster/tasks/builds/b2g_aries_spark_dogfood.yml
+++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_dogfood.yml
@@ -11,17 +11,16 @@ task:
     - 'docker-worker:cache:build-aries-spark-dogfood-objdir-gecko-{{project}}'
   payload:
     cache:
       build-aries-spark-dogfood: /home/worker/workspace
       build-aries-spark-dogfood-objdir-gecko-{{project}}: /home/worker/objdir-gecko
     env:
       VARIANT: userdebug
       DOGFOOD: 1
-      HARDWARE_COMPOSER: 0
       MOZHARNESS_CONFIG: b2g/taskcluster-spark-dogfood.py
   extra:
     treeherderEnv:
       - production
       - staging
     treeherder:
       symbol: B
       groupSymbol: Aries-DogFood
--- a/testing/taskcluster/tasks/builds/b2g_dolphin_512_eng.yml
+++ b/testing/taskcluster/tasks/builds/b2g_dolphin_512_eng.yml
@@ -1,10 +1,13 @@
 $inherits:
   from: 'tasks/builds/b2g_dolphin_base.yml'
+  variables:
+    build_name: 'dolphin-512-eng'
+    build_type: 'opt'
 task:
   scopes:
     - 'docker-worker:cache:build-dolphin-512-eng'
   metadata:
     name: '[TC] B2G Dolphin 512 Eng'
 
   extra:
     treeherder:
--- a/testing/taskcluster/tasks/builds/b2g_dolphin_512_opt.yml
+++ b/testing/taskcluster/tasks/builds/b2g_dolphin_512_opt.yml
@@ -1,10 +1,13 @@
 $inherits:
   from: 'tasks/builds/b2g_dolphin_base.yml'
+  variables:
+    build_name: 'dolphin-512'
+    build_type: 'opt'
 task:
   scopes:
     - 'docker-worker:cache:build-dolphin-512-opt'
   metadata:
     name: '[TC] B2G Dolphin 512 Opt'
 
   extra:
     treeherder:
--- a/testing/taskcluster/tasks/builds/b2g_dolphin_eng.yml
+++ b/testing/taskcluster/tasks/builds/b2g_dolphin_eng.yml
@@ -1,10 +1,13 @@
 $inherits:
   from: 'tasks/builds/b2g_dolphin_base.yml'
+  variables:
+    build_name: 'dolphin-eng'
+    build_type: 'opt'
 task:
   scopes:
     - 'docker-worker:cache:build-dolphin-eng'
   metadata:
     name: '[TC] B2G Dolphin Eng'
 
   extra:
     treeherder:
--- a/testing/taskcluster/tasks/builds/b2g_dolphin_opt.yml
+++ b/testing/taskcluster/tasks/builds/b2g_dolphin_opt.yml
@@ -1,10 +1,13 @@
 $inherits:
   from: 'tasks/builds/b2g_dolphin_base.yml'
+  variables:
+    build_name: 'dolphin'
+    build_type: 'opt'
 task:
   scopes:
     - 'docker-worker:cache:build-dolphin-opt'
   metadata:
     name: '[TC] B2G Dolphin Opt'
 
   extra:
     treeherder: