Merge b2ginbound to central, a=merge a=yolo
authorWes Kocher <wkocher@mozilla.com>
Mon, 13 Jul 2015 15:47:28 -0700
changeset 252643 f101a510a21073fee34dfb0128f43b2e3445aba5
parent 252545 61df86ca9b50edb3c1bae520963627272ecde98e (current diff)
parent 252642 5b7a330595b7e82e72fe87daa2a9313401f163d2 (diff)
child 252644 c68d02e758f0f3e00bc82bfd939bd268fb4cc360
push id13987
push userkwierso@gmail.com
push dateMon, 13 Jul 2015 23:03:21 +0000
treeherderfx-team@c68d02e758f0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge, yolo
milestone42.0a1
Merge b2ginbound to central, a=merge a=yolo
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -618,16 +618,19 @@ pref("app.update.socket.retryTimeout", 3
 // Max of 20 consecutive retries (total 10 minutes) before giving up and marking
 // the update download as failed.
 // Note: Offline errors will always retry when the network comes online.
 pref("app.update.socket.maxErrors", 20);
 
 // Enable update logging for now, to diagnose growing pains in the
 // field.
 pref("app.update.log", true);
+
+// SystemUpdate API
+pref("dom.system_update.active", "@mozilla.org/updates/update-prompt;1");
 #else
 // Explicitly disable the shutdown watchdog.  It's enabled by default.
 // When the updater is disabled, we want to know about shutdown hangs.
 pref("shutdown.watchdog.timeoutSecs", -1);
 #endif
 
 // Allow webapps update checking
 pref("webapps.update.enabled", true);
@@ -1106,16 +1109,19 @@ pref("services.mobileid.server.uri", "ht
 // Enable mapped array buffer.
 #ifndef XP_WIN
 pref("dom.mapped_arraybuffer.enabled", true);
 #endif
 
 // BroadcastChannel API
 pref("dom.broadcastChannel.enabled", true);
 
+// SystemUpdate API
+pref("dom.system_update.enabled", true);
+
 // UDPSocket API
 pref("dom.udpsocket.enabled", true);
 
 // Enable TV Manager API
 pref("dom.tv.enabled", true);
 
 // Enable Inputport Manager API
 pref("dom.inputport.enabled", true);
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -13,16 +13,17 @@ Cu.import('resource://gre/modules/Activi
 Cu.import('resource://gre/modules/NotificationDB.jsm');
 Cu.import('resource://gre/modules/Payment.jsm');
 Cu.import("resource://gre/modules/AppsUtils.jsm");
 Cu.import('resource://gre/modules/UserAgentOverrides.jsm');
 Cu.import('resource://gre/modules/Keyboard.jsm');
 Cu.import('resource://gre/modules/ErrorPage.jsm');
 Cu.import('resource://gre/modules/AlertsHelper.jsm');
 Cu.import('resource://gre/modules/RequestSyncService.jsm');
+Cu.import('resource://gre/modules/SystemUpdateService.jsm');
 #ifdef MOZ_WIDGET_GONK
 Cu.import('resource://gre/modules/NetworkStatsService.jsm');
 Cu.import('resource://gre/modules/ResourceStatsService.jsm');
 #endif
 
 // Identity
 Cu.import('resource://gre/modules/SignInToWebsite.jsm');
 SignInToWebsiteController.init();
--- a/b2g/components/B2GComponents.manifest
+++ b/b2g/components/B2GComponents.manifest
@@ -8,16 +8,17 @@ contract @mozilla.org/system-alerts-serv
 # ContentPermissionPrompt.js
 component {8c719f03-afe0-4aac-91ff-6c215895d467} ContentPermissionPrompt.js
 contract @mozilla.org/content-permission/prompt;1 {8c719f03-afe0-4aac-91ff-6c215895d467}
 
 #ifdef MOZ_UPDATER
 # UpdatePrompt.js
 component {88b3eb21-d072-4e3b-886d-f89d8c49fe59} UpdatePrompt.js
 contract @mozilla.org/updates/update-prompt;1 {88b3eb21-d072-4e3b-886d-f89d8c49fe59}
+category system-update-provider MozillaProvider @mozilla.org/updates/update-prompt;1,{88b3eb21-d072-4e3b-886d-f89d8c49fe59}
 #endif
 
 # DirectoryProvider.js
 component {9181eb7c-6f87-11e1-90b1-4f59d80dd2e5} DirectoryProvider.js
 contract @mozilla.org/b2g/directory-provider;1 {9181eb7c-6f87-11e1-90b1-4f59d80dd2e5}
 category xpcom-directory-providers b2g-directory-provider @mozilla.org/b2g/directory-provider;1
 
 # ActivitiesGlue.js
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -79,42 +79,60 @@ UpdateCheckListener.prototype = {
       // see, even if a newer update is available.
       this._updatePrompt.setUpdateStatus("active-update");
       this._updatePrompt.showUpdateAvailable(Services.um.activeUpdate);
       return;
     }
 
     if (updateCount == 0) {
       this._updatePrompt.setUpdateStatus("no-updates");
+
+      if (this._updatePrompt._systemUpdateListener) {
+        this._updatePrompt._systemUpdateListener.onError("no-updates");
+      }
+
       return;
     }
 
     let update = Services.aus.selectUpdate(updates, updateCount);
     if (!update) {
       this._updatePrompt.setUpdateStatus("already-latest-version");
+
+      if (this._updatePrompt._systemUpdateListener) {
+        this._updatePrompt._systemUpdateListener.onError("already-latest-version");
+      }
+
       return;
     }
 
     this._updatePrompt.setUpdateStatus("check-complete");
     this._updatePrompt.showUpdateAvailable(update);
   },
 
   onError: function UCL_onError(request, update) {
     // nsIUpdate uses a signed integer for errorCode while any platform errors
     // require all 32 bits.
     let errorCode = update.errorCode >>> 0;
     let isNSError = (errorCode >>> 31) == 1;
+    let errorMsg = "check-error-";
 
     if (errorCode == NETWORK_ERROR_OFFLINE) {
-      this._updatePrompt.setUpdateStatus("retry-when-online");
+      errorMsg = "retry-when-online";
+      this._updatePrompt.setUpdateStatus(errorMsg);
     } else if (isNSError) {
-      this._updatePrompt.setUpdateStatus("check-error-" + errorCode);
+      errorMsg = "check-error-" + errorCode;
+      this._updatePrompt.setUpdateStatus(errorMsg);
     } else if (errorCode > HTTP_ERROR_OFFSET) {
       let httpErrorCode = errorCode - HTTP_ERROR_OFFSET;
-      this._updatePrompt.setUpdateStatus("check-error-http-" + httpErrorCode);
+      errorMsg = "check-error-http-" + httpErrorCode;
+      this._updatePrompt.setUpdateStatus(errorMsg);
+    }
+
+    if (this._updatePrompt._systemUpdateListener) {
+      this._updatePrompt._systemUpdateListener.onError(errorMsg);
     }
 
     Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
     Services.aus.onError(request, update);
   }
 };
 
 function UpdatePrompt() {
@@ -124,23 +142,103 @@ function UpdatePrompt() {
 }
 
 UpdatePrompt.prototype = {
   classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
                                          Ci.nsIUpdateCheckListener,
                                          Ci.nsIRequestObserver,
                                          Ci.nsIProgressEventSink,
-                                         Ci.nsIObserver]),
+                                         Ci.nsIObserver,
+                                         Ci.nsISystemUpdateProvider]),
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(UpdatePrompt),
 
   _update: null,
   _applyPromptTimer: null,
   _waitingForIdle: false,
   _updateCheckListner: null,
+  _systemUpdateListener: null,
+  _availableParameters: {
+    "deviceinfo.last_updated": null,
+    "gecko.updateStatus": null,
+    "app.update.channel": null,
+    "app.update.interval": null,
+    "app.update.url": null,
+  },
+  _pendingUpdateAvailablePackageInfo: null,
+  _isPendingUpdateReady: false,
+
+  // nsISystemUpdateProvider
+  checkForUpdate: function() {
+    this.forceUpdateCheck();
+  },
+
+  startDownload: function() {
+    this.downloadUpdate(this._update);
+  },
+
+  stopDownload: function() {
+    this.handleDownloadCancel();
+  },
+
+  applyUpdate: function() {
+    this.handleApplyPromptResult({result: "restart"});
+  },
+
+  setParameter: function(aName, aValue) {
+    if (!this._availableParameters.hasOwnProperty(aName)) {
+      return false;
+    }
+
+    this._availableParameters[aName] = aValue;
+
+    switch (aName) {
+      case "app.update.channel":
+      case "app.update.url":
+        Services.prefs.setCharPref(aName, aValue);
+        break;
+      case "app.update.interval":
+        Services.prefs.setIntPref(aName, parseInt(aValue, 10));
+        break;
+    }
+
+    return true;
+  },
+
+  getParameter: function(aName) {
+    if (!this._availableParameters.hasOwnProperty(aName)) {
+      return null;
+    }
+
+    return this._availableParameters[aName];
+  },
+
+  setListener: function(aListener) {
+    this._systemUpdateListener = aListener;
+
+    // If an update is available or ready, trigger the event right away at this point.
+    if (this._pendingUpdateAvailablePackageInfo) {
+      this._systemUpdateListener.onUpdateAvailable(this._pendingUpdateAvailablePackageInfo.type,
+                                             this._pendingUpdateAvailablePackageInfo.version,
+                                             this._pendingUpdateAvailablePackageInfo.description,
+                                             this._pendingUpdateAvailablePackageInfo.buildDate,
+                                             this._pendingUpdateAvailablePackageInfo.size);
+      // Set null when the listener is attached.
+      this._pendingUpdateAvailablePackageInfo = null;
+    }
+
+    if (this._isPendingUpdateReady) {
+      this._systemUpdateListener.onUpdateReady();
+      this._isPendingUpdateReady = false;
+    }
+  },
+
+  unsetListener: function(aListener) {
+    this._systemUpdateListener = null;
+  },
 
   get applyPromptTimeout() {
     return Services.prefs.getIntPref(PREF_APPLY_PROMPT_TIMEOUT);
   },
 
   get applyIdleTimeout() {
     return Services.prefs.getIntPref(PREF_APPLY_IDLE_TIMEOUT);
   },
@@ -152,24 +250,61 @@ UpdatePrompt.prototype = {
   // nsIUpdatePrompt
 
   // FIXME/bug 737601: we should have users opt-in to downloading
   // updates when on a billed pipe.  Initially, opt-in for 3g, but
   // that doesn't cover all cases.
   checkForUpdates: function UP_checkForUpdates() { },
 
   showUpdateAvailable: function UP_showUpdateAvailable(aUpdate) {
+    let packageInfo = {};
+    packageInfo.version = aUpdate.displayVersion;
+    packageInfo.description = aUpdate.statusText;
+    packageInfo.buildDate = aUpdate.buildID;
+
+    let patch = aUpdate.selectedPatch;
+    if (!patch && aUpdate.patchCount > 0) {
+      // For now we just check the first patch to get size information if a
+      // patch hasn't been selected yet.
+      patch = aUpdate.getPatchAt(0);
+    }
+
+    if (patch) {
+      packageInfo.size = patch.size;
+      packageInfo.type = patch.type;
+    } else {
+      log("Warning: no patches available in update");
+    }
+
+    this._pendingUpdateAvailablePackageInfo = packageInfo;
+
+    if (this._systemUpdateListener) {
+      this._systemUpdateListener.onUpdateAvailable(packageInfo.type,
+                                             packageInfo.version,
+                                             packageInfo.description,
+                                             packageInfo.buildDate,
+                                             packageInfo.size);
+      // Set null since the event is fired.
+      this._pendingUpdateAvailablePackageInfo = null;
+    }
+
     if (!this.sendUpdateEvent("update-available", aUpdate)) {
 
       log("Unable to prompt for available update, forcing download");
       this.downloadUpdate(aUpdate);
     }
   },
 
   showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) {
+    if (this._systemUpdateListener) {
+      this._systemUpdateListener.onUpdateReady();
+    } else {
+      this._isPendingUpdateReady = true;
+    }
+
     // The update has been downloaded and staged. We send the update-downloaded
     // event right away. After the user has been idle for a while, we send the
     // update-prompt-restart event, increasing the chances that we can apply the
     // update quietly without user intervention.
     this.sendUpdateEvent("update-downloaded", aUpdate);
 
     if (Services.idle.idleTime >= this.applyIdleTimeout) {
       this.showApplyPrompt(aUpdate);
@@ -183,22 +318,28 @@ UpdatePrompt.prototype = {
 
     this._update = aUpdate;
     this.waitForIdle();
   },
 
   showUpdateError: function UP_showUpdateError(aUpdate) {
     log("Update error, state: " + aUpdate.state + ", errorCode: " +
         aUpdate.errorCode);
+    if (this._systemUpdateListener) {
+      this._systemUpdateListener.onError("update-error: " + aUpdate.errorCode + " " + aUpdate.statusText);
+    }
+
     this.sendUpdateEvent("update-error", aUpdate);
     this.setUpdateStatus(aUpdate.statusText);
   },
 
   showUpdateHistory: function UP_showUpdateHistory(aParent) { },
   showUpdateInstalled: function UP_showUpdateInstalled() {
+    this.setParameter("deviceinfo.last_updated", Date.now());
+
     if (useSettings()) {
       let lock = Services.settings.createLock();
       lock.set("deviceinfo.last_updated", Date.now(), null, null);
     }
   },
 
   // Custom functions
 
@@ -208,25 +349,35 @@ UpdatePrompt.prototype = {
     }
 
     this._waitingForIdle = true;
     Services.idle.addIdleObserver(this, this.applyIdleTimeout / 1000);
     Services.obs.addObserver(this, "quit-application", false);
   },
 
   setUpdateStatus: function UP_setUpdateStatus(aStatus) {
+     this.setParameter("gecko.updateStatus", aStatus);
+
      if (useSettings()) {
        log("Setting gecko.updateStatus: " + aStatus);
 
        let lock = Services.settings.createLock();
        lock.set("gecko.updateStatus", aStatus, null);
      }
   },
 
   showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
+    // Notify update package is ready to apply
+    if (this._systemUpdateListener) {
+      this._systemUpdateListener.onUpdateReady();
+    } else {
+      // Set the flag to true and fire the onUpdateReady event when the listener is attached.
+      this._isPendingUpdateReady = true;
+    }
+
     if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
       log("Unable to prompt, forcing restart");
       this.restartProcess();
       return;
     }
 
 #ifdef MOZ_B2G_RIL
     let window = Services.wm.getMostRecentWindow("navigator:browser");
@@ -576,16 +727,20 @@ UpdatePrompt.prototype = {
       paused: paused
     });
   },
 
   // nsIProgressEventSink
 
   onProgress: function UP_onProgress(aRequest, aContext, aProgress,
                                      aProgressMax) {
+    if (this._systemUpdateListener) {
+      this._systemUpdateListener.onProgress(aProgress, aProgressMax);
+    }
+
     if (aProgress == aProgressMax) {
       // The update.mar validation done by onStopRequest may take
       // a while before the onStopRequest callback is made, so stop
       // the timer now.
       this.stopWatchdogTimer();
     } else {
       this.touchWatchdogTimer();
     }
--- a/b2g/config/aries/sources.xml
+++ b/b2g/config/aries/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <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="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--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="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <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="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="87a2d8ab9248540910e56921654367b78a587095"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="9d0e5057ee5404a31ec1bf76131cb11336a7c3b6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "a7439b6ca88264734171ff5ea0b6a0b8df3f258e", 
+        "git_revision": "a4278e41c08fa619edbd6537b6182d46dc475a4e", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "3073356ae6c82391651cf4d6ca066433c4efd928", 
+    "revision": "37f6eb95a19e04cdf27af3c4c0efe08a167b0fc1", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <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="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="a7439b6ca88264734171ff5ea0b6a0b8df3f258e"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="a4278e41c08fa619edbd6537b6182d46dc475a4e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="46584eaae13051a5d1b3bc3f49f9b38d423a1e86"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="42b31cf3248acf7acd1fd30c7491871c50305fa8"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -685,16 +685,19 @@
 ; InputMethod API
 @RESPATH@/components/MozKeyboard.js
 @RESPATH@/components/InputMethod.manifest
 
 @RESPATH@/components/EngineeringMode.manifest
 @RESPATH@/components/EngineeringModeAPI.js
 @RESPATH@/components/EngineeringModeService.js
 
+@RESPATH@/components/SystemUpdate.manifest
+@RESPATH@/components/SystemUpdateManager.js
+
 #ifdef MOZ_DEBUG
 @RESPATH@/components/TestInterfaceJS.js
 @RESPATH@/components/TestInterfaceJS.manifest
 @RESPATH@/components/TestInterfaceJSMaplike.js
 #endif
 
 @RESPATH@/components/PACGenerator.js
 @RESPATH@/components/PACGenerator.manifest
--- a/dom/apps/PermissionsTable.jsm
+++ b/dom/apps/PermissionsTable.jsm
@@ -543,16 +543,22 @@ this.PermissionsTable =  { geolocation: 
                              privileged: DENY_ACTION,
                              certified: ALLOW_ACTION
                            },
                            "external-app": {
                              app: DENY_ACTION,
                              trusted: DENY_ACTION,
                              privileged: ALLOW_ACTION,
                              certified: ALLOW_ACTION
+                           },
+                           "system-update": {
+                             app: DENY_ACTION,
+                             trusted: DENY_ACTION,
+                             privileged: DENY_ACTION,
+                             certified: ALLOW_ACTION
                            }
                          };
 
 /**
  * Append access modes to the permission name as suffixes.
  *   e.g. permission name 'contacts' with ['read', 'write'] =
  *   ['contacts-read', contacts-write']
  * @param string aPermName
new file mode 100644
--- /dev/null
+++ b/dom/system/SystemUpdate.manifest
@@ -0,0 +1,2 @@
+component {e8530001-ba5b-46ab-a306-7fbeb692d0fe} SystemUpdateManager.js
+contract @mozilla.org/system-update-manager;1 {e8530001-ba5b-46ab-a306-7fbeb692d0fe}
new file mode 100644
--- /dev/null
+++ b/dom/system/SystemUpdateManager.js
@@ -0,0 +1,262 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/DOMRequestHelper.jsm");
+
+let debug = Services.prefs.getBoolPref("dom.system_update.debug")
+              ? (aMsg) => dump("-*- SystemUpdateManager.js : " + aMsg + "\n")
+              : (aMsg) => {};
+
+const SYSTEMUPDATEPROVIDER_CID = Components.ID("{11fbea3d-fd94-459a-b8fb-557fe19e473a}");
+const SYSTEMUPDATEMANAGER_CID = Components.ID("{e8530001-ba5b-46ab-a306-7fbeb692d0fe}");
+const SYSTEMUPDATEMANAGER_CONTRACTID = "@mozilla.org/system-update-manager;1";
+
+XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
+                                   "@mozilla.org/childprocessmessagemanager;1",
+                                   "nsISyncMessageSender");
+
+function SystemUpdateProvider(win, provider) {
+  this.initDOMRequestHelper(win, [
+    {name: "SystemUpdate:OnUpdateAvailable", weakRef: true},
+    {name: "SystemUpdate:OnProgress", weakRef: true},
+    {name: "SystemUpdate:OnUpdateReady", weakRef: true},
+    {name: "SystemUpdate:OnError", weakRef: true},
+  ]);
+  this._provider = Cu.cloneInto(provider, win);
+}
+
+SystemUpdateProvider.prototype = {
+  __proto__: DOMRequestIpcHelper.prototype,
+
+  classID: SYSTEMUPDATEPROVIDER_CID,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
+                                         Ci.nsIObserver]),
+
+  receiveMessage: function(aMsg) {
+    if (!aMsg || !aMsg.json) {
+      return;
+    }
+
+    let json = aMsg.json;
+
+    if (json.uuid !== this._provider.uuid) {
+      return;
+    }
+
+    debug("receive msg: " + aMsg.name);
+    switch (aMsg.name) {
+      case "SystemUpdate:OnUpdateAvailable": {
+        let detail = {
+          detail: {
+            packageInfo: json.packageInfo
+          }
+        };
+        let event = new this._window.CustomEvent("updateavailable",
+                                                  Cu.cloneInto(detail, this._window));
+        this.__DOM_IMPL__.dispatchEvent(event);
+        break;
+      }
+      case "SystemUpdate:OnProgress": {
+        let event = new this._window.ProgressEvent("progress", {lengthComputable: true,
+                                                                loaded: json.loaded,
+                                                                total: json.total});
+        this.__DOM_IMPL__.dispatchEvent(event);
+        break;
+      }
+      case "SystemUpdate:OnUpdateReady": {
+        let event = new this._window.Event("updateready");
+        this.__DOM_IMPL__.dispatchEvent(event);
+        break;
+      }
+      case "SystemUpdate:OnError": {
+        let event = new this._window.ErrorEvent("error", {message: json.message});
+        this.__DOM_IMPL__.dispatchEvent(event);
+        break;
+      }
+    }
+  },
+
+  destroy: function() {
+    this.destroyDOMRequestHelper();
+  },
+
+  get name() {
+    return this._provider.name;
+  },
+
+  get uuid() {
+    return this._provider.uuid;
+  },
+
+  get onupdateavailable() {
+    return this.__DOM_IMPL__.getEventHandler("onupdateavailable");
+  },
+  set onupdateavailable(aHandler) {
+    this.__DOM_IMPL__.setEventHandler("onupdateavailable", aHandler);
+  },
+  get onprogress() {
+    return this.__DOM_IMPL__.getEventHandler("onprogress");
+  },
+  set onprogress(aHandler) {
+    this.__DOM_IMPL__.setEventHandler("onprogress", aHandler);
+  },
+  get onupdateready() {
+    return this.__DOM_IMPL__.getEventHandler("onupdateready");
+  },
+  set onupdateready(aHandler) {
+    this.__DOM_IMPL__.setEventHandler("onupdateready", aHandler);
+  },
+  get onerror() {
+    return this.__DOM_IMPL__.getEventHandler("onerror");
+  },
+  set onerror(aHandler) {
+    this.__DOM_IMPL__.setEventHandler("onerror", aHandler);
+  },
+
+  checkForUpdate: function() {
+    let self = this;
+    cpmm.sendAsyncMessage("SystemUpdate:CheckForUpdate", {
+      uuid: self._provider.uuid
+    });
+  },
+  startDownload: function() {
+    let self = this;
+    cpmm.sendAsyncMessage("SystemUpdate:StartDownload", {
+      uuid: self._provider.uuid
+    });
+  },
+  stopDownload: function() {
+    let self = this;
+    cpmm.sendAsyncMessage("SystemUpdate:StopDownload", {
+      uuid: self._provider.uuid
+    });
+  },
+  applyUpdate: function() {
+    let self = this;
+    cpmm.sendAsyncMessage("SystemUpdate:ApplyUpdate", {
+      uuid: self._provider.uuid
+    });
+  },
+  setParameter: function(aName, aValue) {
+    let self = this;
+    return cpmm.sendSyncMessage("SystemUpdate:SetParameter", {
+      uuid: self._provider.uuid,
+      name: aName,
+      value: aValue
+    })[0];
+  },
+  getParameter: function(aName) {
+    let self = this;
+    return cpmm.sendSyncMessage("SystemUpdate:GetParameter", {
+      uuid: self._provider.uuid,
+      name: aName
+    })[0];
+  },
+};
+
+function SystemUpdateManager() {}
+
+SystemUpdateManager.prototype = {
+  __proto__: DOMRequestIpcHelper.prototype,
+
+  classID: SYSTEMUPDATEMANAGER_CID,
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
+                                         Ci.nsIObserver,
+                                         Ci.nsIDOMGlobalPropertyInitializer]),
+
+  receiveMessage: function(aMsg) {
+    if (!aMsg || !aMsg.json) {
+      return;
+    }
+
+    let json = aMsg.json;
+    let resolver = this.takePromiseResolver(json.requestId);
+
+    if (!resolver) {
+      return;
+    }
+
+    debug("receive msg: " + aMsg.name);
+    switch (aMsg.name) {
+      case "SystemUpdate:GetProviders:Result:OK": {
+        resolver.resolve(Cu.cloneInto(json.providers, this._window));
+        break;
+      }
+      case "SystemUpdate:SetActiveProvider:Result:OK":
+      case "SystemUpdate:GetActiveProvider:Result:OK": {
+        let updateProvider = new SystemUpdateProvider(this._window, json.provider);
+        resolver.resolve(this._window.SystemUpdateProvider._create(this._window,
+                                                                   updateProvider));
+        break;
+      }
+      case "SystemUpdate:GetProviders:Result:Error":
+      case "SystemUpdate:GetActiveProvider:Result:Error":
+      case "SystemUpdate:SetActiveProvider:Result:Error": {
+        resolver.reject(json.error);
+        break;
+      }
+    }
+  },
+
+  init: function(aWindow) {
+    this.initDOMRequestHelper(aWindow, [
+      {name: "SystemUpdate:GetProviders:Result:OK", weakRef: true},
+      {name: "SystemUpdate:GetProviders:Result:Error", weakRef: true},
+      {name: "SystemUpdate:GetActiveProvider:Result:OK", weakRef: true},
+      {name: "SystemUpdate:GetActiveProvider:Result:Error", weakRef: true},
+      {name: "SystemUpdate:SetActiveProvider:Result:OK", weakRef: true},
+      {name: "SystemUpdate:SetActiveProvider:Result:Error", weakRef: true},
+    ]);
+  },
+
+  uninit: function() {
+    let self = this;
+
+    this.forEachPromiseResolver(function(aKey) {
+      self.takePromiseResolver(aKey).reject("SystemUpdateManager got destroyed");
+    });
+  },
+
+  getProviders: function() {
+    return this._sendPromise(function(aResolverId) {
+      cpmm.sendAsyncMessage("SystemUpdate:GetProviders", {
+        requestId: aResolverId,
+      });
+    });
+  },
+
+  getActiveProvider: function() {
+    return this._sendPromise(function(aResolverId) {
+      cpmm.sendAsyncMessage("SystemUpdate:GetActiveProvider", {
+        requestId: aResolverId,
+      });
+    });
+  },
+
+  setActiveProvider: function(aUuid) {
+    return this._sendPromise(function(aResolverId) {
+      cpmm.sendAsyncMessage("SystemUpdate:SetActiveProvider", {
+        requestId: aResolverId,
+        uuid: aUuid
+      });
+    });
+  },
+
+  _sendPromise: function(aCallback) {
+    let self = this;
+    return this.createPromise(function(aResolve, aReject) {
+      let resolverId = self.getPromiseResolverId({resolve: aResolve,
+                                                  reject: aReject});
+      aCallback(resolverId);
+    });
+  }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SystemUpdateManager]);
new file mode 100644
--- /dev/null
+++ b/dom/system/SystemUpdateService.jsm
@@ -0,0 +1,382 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+this.EXPORTED_SYMBOLS = ["SystemUpdateService"];
+
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+Cu.import("resource://gre/modules/Services.jsm");
+
+const CATEGORY_SYSTEM_UPDATE_PROVIDER = "system-update-provider";
+const PROVIDER_ACTIVITY_IDLE = 0;
+const PROVIDER_ACTIVITY_CHECKING = 1;
+const PROVIDER_ACTIVITY_DOWNLOADING = 1 << 1;
+const PROVIDER_ACTIVITY_APPLYING = 1 << 2;
+
+let debug = Services.prefs.getBoolPref("dom.system_update.debug")
+              ? (aMsg) => dump("-*- SystemUpdateService.jsm : " + aMsg + "\n")
+              : (aMsg) => {};
+
+XPCOMUtils.defineLazyServiceGetter(this, "ppmm",
+                                   "@mozilla.org/parentprocessmessagemanager;1",
+                                   "nsIMessageBroadcaster");
+
+function ActiveProvider(aProvider) {
+  this.id = aProvider.id;
+  this._instance = Cc[aProvider.contractId].getService(Ci.nsISystemUpdateProvider);
+  this._instance.setListener(this);
+}
+
+ActiveProvider.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemUpdateListener]),
+
+  _activity: PROVIDER_ACTIVITY_IDLE,
+
+  destroy: function() {
+    if (this._instance) {
+      this._instance.unsetListener();
+      this._instance = null;
+    }
+
+    this.id = null;
+  },
+
+  checkForUpdate: function() {
+    this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_CHECKING,
+                                  this._instance.checkForUpdate);
+  },
+
+  startDownload: function() {
+    this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_DOWNLOADING,
+                                  this._instance.startDownload);
+  },
+
+  stopDownload: function() {
+    this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_DOWNLOADING,
+                                  this._instance.stopDownload);
+  },
+
+  applyUpdate: function() {
+    this._execFuncIfNotInActivity(PROVIDER_ACTIVITY_APPLYING,
+                                  this._instance.applyUpdate);
+  },
+
+  setParameter: function(aName, aValue) {
+    return this._instance.setParameter(aName, aValue);
+  },
+
+  getParameter: function(aName) {
+    return this._instance.getParameter(aName);
+  },
+
+  // nsISystemUpdateListener
+  onUpdateAvailable: function(aType, aVersion, aDescription, aBuildDate, aSize) {
+    this._execFuncIfActiveAndInAction(PROVIDER_ACTIVITY_CHECKING, function() {
+      ppmm.broadcastAsyncMessage("SystemUpdate:OnUpdateAvailable", {
+        uuid: this.id,
+        packageInfo: {
+          type: aType,
+          version: aVersion,
+          description: aDescription,
+          buildDate: aBuildDate,
+          size: aSize,
+        }
+      });
+
+      this._unsetActivity(PROVIDER_ACTIVITY_CHECKING);
+    }.bind(this));
+  },
+
+  onProgress: function(aLoaded, aTotal) {
+    this._execFuncIfActiveAndInAction(PROVIDER_ACTIVITY_DOWNLOADING, function() {
+      ppmm.broadcastAsyncMessage("SystemUpdate:OnProgress", {
+        uuid: this.id,
+        loaded: aLoaded,
+        total: aTotal,
+      });
+    }.bind(this));
+  },
+
+  onUpdateReady: function() {
+    this._execFuncIfActiveAndInAction(PROVIDER_ACTIVITY_DOWNLOADING, function() {
+      ppmm.broadcastAsyncMessage("SystemUpdate:OnUpdateReady", {
+        uuid: this.id,
+      });
+
+      this._unsetActivity(PROVIDER_ACTIVITY_DOWNLOADING);
+    }.bind(this));
+  },
+
+  onError: function(aErrMsg) {
+    if (!SystemUpdateService._isActiveProviderId(this.id)) {
+      return;
+    }
+
+    ppmm.broadcastAsyncMessage("SystemUpdate:OnError", {
+      uuid: this.id,
+      message: aErrMsg,
+    });
+
+    this._activity = PROVIDER_ACTIVITY_IDLE;
+  },
+
+  isIdle: function() {
+    return this._activity === PROVIDER_ACTIVITY_IDLE;
+  },
+
+  _isInActivity: function(aActivity) {
+    return (this._activity & aActivity) !== PROVIDER_ACTIVITY_IDLE;
+  },
+
+  _setActivity: function(aActivity) {
+    this._activity |= aActivity;
+  },
+
+  _unsetActivity: function(aActivity) {
+    this._activity &= ~aActivity;
+  },
+
+  _execFuncIfNotInActivity: function(aActivity, aFunc) {
+    if (!this._isInActivity(aActivity)) {
+      this._setActivity(aActivity);
+      aFunc();
+    }
+  },
+
+  _execFuncIfActiveAndInAction: function(aActivity, aFunc) {
+    if (!SystemUpdateService._isActiveProviderId(this.id)) {
+      return;
+    }
+    if (this._isInActivity(aActivity)) {
+      aFunc();
+    }
+  },
+
+};
+
+this.SystemUpdateService = {
+  _providers: [],
+  _activeProvider: null,
+
+  _updateActiveProvider: function(aProvider) {
+    if (this._activeProvider) {
+      this._activeProvider.destroy();
+    }
+
+    this._activeProvider = new ActiveProvider(aProvider);
+  },
+
+  _isActiveProviderId: function(aId) {
+    return (this._activeProvider && this._activeProvider.id === aId);
+  },
+
+  init: function() {
+    debug("init");
+
+    let messages = ["SystemUpdate:GetProviders",
+                    "SystemUpdate:GetActiveProvider",
+                    "SystemUpdate:SetActiveProvider",
+                    "SystemUpdate:CheckForUpdate",
+                    "SystemUpdate:StartDownload",
+                    "SystemUpdate:StopDownload",
+                    "SystemUpdate:ApplyUpdate",
+                    "SystemUpdate:SetParameter",
+                    "SystemUpdate:GetParameter"];
+    messages.forEach((function(aMsgName) {
+      ppmm.addMessageListener(aMsgName, this);
+    }).bind(this));
+
+    // load available provider list
+    let catMan = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
+    let entries = catMan.enumerateCategory(CATEGORY_SYSTEM_UPDATE_PROVIDER);
+    while (entries.hasMoreElements()) {
+      let name = entries.getNext().QueryInterface(Ci.nsISupportsCString).data;
+      let [contractId, id] = catMan.getCategoryEntry(CATEGORY_SYSTEM_UPDATE_PROVIDER, name).split(",");
+      this._providers.push({
+        id: id,
+        name: name,
+        contractId: contractId
+      });
+    }
+    debug("available providers: " + JSON.stringify(this._providers));
+
+    // setup default active provider
+    let defaultActive;
+    try {
+      defaultActive = Services.prefs.getCharPref("dom.system_update.active");
+    } catch (e) {}
+
+    if (defaultActive) {
+      let defaultProvider = this._providers.find(function(aProvider) {
+        return aProvider.contractId === defaultActive;
+      });
+
+      if (defaultProvider) {
+        this._updateActiveProvider(defaultProvider);
+      }
+    }
+  },
+
+  addProvider: function(aClassId, aContractId, aName) {
+    debug("addProvider");
+
+    //did not allow null or empty string to add.
+    if(!aClassId || !aContractId || !aName) {
+      return;
+    }
+
+    let existedProvider = this._providers.find(function(provider) {
+      return provider.id === aClassId;
+    });
+
+    //skip if adding the existed provider.
+    if (existedProvider) {
+      debug("existing providers: " + JSON.stringify(existedProvider));
+      return;
+    }
+
+    //dynamically add the provider info to list.
+    this._providers.push({
+        id: aClassId,
+        name: aName,
+        contractId: aContractId
+    });
+    debug("available providers: " + JSON.stringify(this._providers));
+  },
+
+  getProviders: function(aData, aMm) {
+    debug("getProviders");
+
+    aData.providers = [];
+    for (let provider of this._providers) {
+      aData.providers.push({
+        name: provider.name,
+        uuid: provider.id
+      });
+    }
+    aMm.sendAsyncMessage("SystemUpdate:GetProviders:Result:OK", aData);
+  },
+
+  getActiveProvider: function(aData, aMm) {
+    debug("getActiveProvider");
+
+    let self = this;
+    let providerInfo = this._providers.find(function(provider) {
+      return self._isActiveProviderId(provider.id);
+    });
+
+    if (!providerInfo) {
+      aData.error = "NotFoundError";
+      aMm.sendAsyncMessage("SystemUpdate:GetActiveProvider:Result:Error", aData);
+      return;
+    }
+
+    aData.provider = {
+      name: providerInfo.name,
+      uuid: providerInfo.id
+    };
+    aMm.sendAsyncMessage("SystemUpdate:GetActiveProvider:Result:OK", aData);
+  },
+
+  setActiveProvider: function(aData, aMm) {
+    debug("setActiveProvider");
+
+    let self = this;
+    let selectedProvider = this._providers.find(function(provider) {
+      return provider.id === aData.uuid;
+    });
+
+    if (!selectedProvider) {
+      aData.error = "DataError";
+      aMm.sendAsyncMessage("SystemUpdate:SetActiveProvider:Result:Error", aData);
+      return;
+    }
+
+    if (!this._isActiveProviderId(selectedProvider.id)) {
+      // not allow changing active provider while there is an ongoing update activity
+      if (this.activeProvider && !this._activeProvider.isIdle()) {
+        aData.error = "DataError";
+        aMm.sendAsyncMessage("SystemUpdate:SetActiveProvider:Result:Error", aData);
+        return;
+      }
+
+      this._updateActiveProvider(selectedProvider);
+      Services.prefs.setCharPref("dom.system_update.active", selectedProvider.contractId);
+    }
+
+    aData.provider = {
+      name: selectedProvider.name,
+      uuid: selectedProvider.id
+    };
+    aMm.sendAsyncMessage("SystemUpdate:SetActiveProvider:Result:OK", aData);
+  },
+
+  receiveMessage: function(aMessage) {
+    if (!aMessage.target.assertPermission("system-update")) {
+      debug("receive message " + aMessage.name +
+            " from a content process with no 'system-update' privileges.");
+      return null;
+    }
+
+    let msg = aMessage.data || {};
+    let mm = aMessage.target;
+
+    switch (aMessage.name) {
+      case "SystemUpdate:GetProviders": {
+        this.getProviders(msg, mm);
+        break;
+      }
+      case "SystemUpdate:GetActiveProvider": {
+        this.getActiveProvider(msg, mm);
+        break;
+      }
+      case "SystemUpdate:SetActiveProvider": {
+        this.setActiveProvider(msg, mm);
+        break;
+      }
+      case "SystemUpdate:CheckForUpdate": {
+        if (this._isActiveProviderId(msg.uuid)) {
+          this._activeProvider.checkForUpdate();
+        }
+        break;
+      }
+      case "SystemUpdate:StartDownload": {
+        if (this._isActiveProviderId(msg.uuid)) {
+          this._activeProvider.startDownload();
+        }
+        break;
+      }
+      case "SystemUpdate:StopDownload": {
+        if (this._isActiveProviderId(msg.uuid)) {
+          this._activeProvider.stopDownload();
+        }
+        break;
+      }
+      case "SystemUpdate:ApplyUpdate": {
+        if (this._isActiveProviderId(msg.uuid)) {
+          this._activeProvider.applyUpdate();
+        }
+        break;
+      }
+      case "SystemUpdate:SetParameter": {
+        if (this._isActiveProviderId(msg.uuid)) {
+          return this._activeProvider.setParameter(msg.name, msg.value);
+        }
+        break;
+      }
+      case "SystemUpdate:GetParameter": {
+        if (this._isActiveProviderId(msg.uuid)) {
+          return this._activeProvider.getParameter(msg.name);
+        }
+        break;
+      }
+    }
+  },
+
+};
+
+SystemUpdateService.init();
--- a/dom/system/moz.build
+++ b/dom/system/moz.build
@@ -14,16 +14,17 @@ elif toolkit == 'cocoa':
     DIRS += ['mac']
 elif toolkit == 'android':
     DIRS += ['android']
 elif toolkit == 'gonk':
     DIRS += ['gonk']
 
 XPIDL_SOURCES += [
     'nsIOSFileConstantsService.idl',
+    'nsISystemUpdateProvider.idl',
 ]
 
 XPIDL_MODULE = 'dom_system'
 
 EXPORTS += [
     'nsDeviceSensors.h',
 ]
 
@@ -34,16 +35,22 @@ EXPORTS.mozilla += [
 UNIFIED_SOURCES += [
     'nsDeviceSensors.cpp',
     'OSFileConstants.cpp',
 ]
 
 EXTRA_COMPONENTS += [
     'NetworkGeolocationProvider.js',
     'NetworkGeolocationProvider.manifest',
+    'SystemUpdate.manifest',
+    'SystemUpdateManager.js',
+]
+
+EXTRA_JS_MODULES += [
+    'SystemUpdateService.jsm',
 ]
 
 FAIL_ON_WARNINGS = True
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
 # We fire the nsDOMDeviceAcceleration
@@ -52,8 +59,9 @@ LOCAL_INCLUDES += [
     '/dom/bindings',
     '/js/xpconnect/loader',
 ]
 
 DEFINES['DLL_PREFIX'] = '"%s"' % CONFIG['DLL_PREFIX']
 DEFINES['DLL_SUFFIX'] = '"%s"' % CONFIG['DLL_SUFFIX']
 
 MOCHITEST_CHROME_MANIFESTS += ['tests/chrome.ini']
+MOCHITEST_MANIFESTS += ['tests/mochitest.ini']
new file mode 100644
--- /dev/null
+++ b/dom/system/nsISystemUpdateProvider.idl
@@ -0,0 +1,73 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(775edbf5-b4a9-400c-b0ad-ea3c3a027097)]
+interface nsISystemUpdateListener : nsISupports
+{
+  /**
+   * callback for notifying an update package is available for download.
+   */
+  void onUpdateAvailable(in DOMString type,
+                         in DOMString version,
+                         in DOMString description,
+                         in unsigned long long buildDate,
+                         in unsigned long long size);
+
+  /**
+   * callback for notifying the download progress.
+   */
+  void onProgress(in unsigned long long loaded, in unsigned long long total);
+
+  /**
+   * callback for notifying an update package is ready to apply.
+   */
+  void onUpdateReady();
+
+  /**
+   * callback for notifying any error while
+   * checking/downloading/applying an update package.
+   */
+  void onError(in DOMString errMsg);
+};
+
+[scriptable, uuid(c9b7c166-b9cf-4396-a6de-39275e1c0a36)]
+interface nsISystemUpdateProvider : nsISupports
+{
+  void checkForUpdate();
+  void startDownload();
+  void stopDownload();
+  void applyUpdate();
+
+  /**
+   * Set the available parameter to the update provider.
+   * The available parameter is implementation-dependent.
+   * e.g. "update-url", "last-update-date", "update-status", "update-interval"
+   *
+   * @param  name      The number of languages.
+   * @param  languages An array of languages.
+   * @return true when setting an available parameter,
+   *         false when setting an unavailable parameter.
+   */
+  bool setParameter(in DOMString name, in DOMString value);
+  /**
+   * Get the available parameter from the update provider.
+   * The available parameter is implementation-dependent.
+   *
+   * @param  name The available parameter.
+   * @return The corresponding value to the name.
+   *         Return null if try to get unavailable parameter.
+   */
+  DOMString getParameter(in DOMString name);
+
+  /**
+   * NOTE TO IMPLEMENTORS:
+   *   Need to consider if it is necessary to fire the pending event when 
+   *   registering the listener.
+   *   (E.g. UpdateAvailable or UpdateReady event.)
+   */
+  void setListener(in nsISystemUpdateListener listener);
+  void unsetListener();
+};
new file mode 100644
--- /dev/null
+++ b/dom/system/tests/mochitest.ini
@@ -0,0 +1,6 @@
+[DEFAULT]
+skip-if = buildapp != 'b2g'
+support-files =
+  preload-SystemUpdateManager-jsm.js
+
+[test_system_update_enabled.html]
new file mode 100644
--- /dev/null
+++ b/dom/system/tests/preload-SystemUpdateManager-jsm.js
@@ -0,0 +1,80 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict';
+
+const {classes: Cc, interfaces: Ci, utils: Cu, manager: Cm} = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+const cid = '{17a84227-28f4-453d-9b80-9ae75a5682e0}';
+const contractId = '@mozilla.org/test-update-provider;1';
+
+function TestUpdateProvider() {}
+TestUpdateProvider.prototype = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsISystemUpdateProvider]),
+
+  checkForUpdate: function() {
+    dump('check for update');
+    this._listener.onUpdateAvailable('test-type', 'test-version', 'test-description', Date.now().valueOf(), 5566);
+  },
+
+  startDownload: function() {
+    dump('test start download');
+    this._listener.onProgress(10, 100);
+  },
+
+  stopDownload: function() {
+    dump('test stop download');
+  },
+
+  applyUpdate: function() {
+    dump('apply update');
+  },
+
+  setParameter: function(name, value) {
+    dump('set parameter');
+    return (name === 'dummy' && value === 'dummy-value');
+  },
+
+  getParameter: function(name) {
+    dump('get parameter');
+    if (name === 'dummy') {
+      return 'dummy-value';
+    }
+  },
+
+  setListener: function(listener) {
+    this._listener = listener;
+  },
+
+  unsetListener: function() {
+    this._listener = null;
+  },
+};
+
+let factory = {
+  createInstance: function(outer, iid) {
+    if (outer) {
+      throw Components.results.NS_ERROR_NO_AGGREGATION;
+    }
+
+    return new TestUpdateProvider().QueryInterface(iid);
+  },
+  lockFactory: function(aLock) {
+    throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
+  },
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory])
+};
+
+Cm.nsIComponentRegistrar.registerFactory(Components.ID(cid), '', contractId, factory);
+
+let cm = Cc['@mozilla.org/categorymanager;1'].getService(Ci.nsICategoryManager);
+cm.addCategoryEntry('system-update-provider', 'DummyProvider',
+                    contractId + ',' + cid, false, true);
+
+Cu.import('resource://gre/modules/SystemUpdateService.jsm');
+this.SystemUpdateService.addProvider('{17a84227-28f4-453d-9b80-9ae75a5682e0}',
+                                     '@mozilla.org/test-update-provider;1',
+                                     'DummyProvider');
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/system/tests/test_system_update_enabled.html
@@ -0,0 +1,175 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1037329
+-->
+<head>
+  <meta charset="utf-8">
+  <title>System Update API Test</title>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1037329">Test System Update API</a>
+<script type="application/javascript;version=1.8">
+
+'use strict';
+
+SimpleTest.waitForExplicitFinish();
+
+function setup() {
+  window.gUrl = SimpleTest.getTestFileURL('preload-SystemUpdateManager-jsm.js');
+  window.gScript = SpecialPowers.loadChromeScript(gUrl);
+  return Promise.resolve();
+}
+
+function testGetProviders() {
+  return new Promise(function(resolve, reject) {
+    navigator.updateManager.getProviders().then(function(providerInfos) {
+      info('num of providers: ' + providerInfos.length);
+      for (let providerInfo of providerInfos) {
+        info('provider info: ' + JSON.stringify(providerInfo));
+      }
+      resolve(providerInfos);
+    });
+  });
+}
+
+function testSetActiveProvider(providerInfos) {
+  return new Promise(function(resolve, reject) {
+    //Find the mock provider for our testing provider instead.
+    //Set the mock provider as active provider.
+    let targetProvider = providerInfos[0];
+    for(let provider of providerInfos) {
+      if(provider.uuid == "{17a84227-28f4-453d-9b80-9ae75a5682e0}") {
+        info('target provider uuid: ' + provider.uuid);
+        targetProvider = provider;
+        break;
+      }
+    }
+    is("{17a84227-28f4-453d-9b80-9ae75a5682e0}", targetProvider.uuid, 'get the dynamically added provider');
+    navigator.updateManager.setActiveProvider(targetProvider.uuid).then(function(activeProvider) {
+      info('active provider info: ' + JSON.stringify(activeProvider.info));
+      is(activeProvider.name, targetProvider.name, 'expected name of active provider');
+      is(activeProvider.uuid, targetProvider.uuid, 'expected uuid of active provider');
+      resolve({name : activeProvider.name, uuid : activeProvider.uuid});
+    });
+  });
+}
+
+function testGetActiveProvider(providerInfo) {
+  info('test GetActiveProvider');
+  return new Promise(function(resolve, reject) {
+    navigator.updateManager.getActiveProvider().then(function(activeProvider) {
+      is(activeProvider.name, providerInfo.name, 'expected name of active provider');
+      is(activeProvider.uuid, providerInfo.uuid, 'expected uuid of active provider');
+      resolve(activeProvider);
+    });
+  });
+}
+
+function testCheckForUpdate(provider) {
+  info('test CheckForUpdate');
+  return new Promise(function(resolve, reject) {
+    provider.addEventListener('updateavailable', function(event) {
+      ok(true, 'receive updateavailable event');
+      info('event: ' + JSON.stringify(event.detail));
+      resolve(provider);
+    });
+    provider.checkForUpdate();
+  });
+}
+
+function testStartDownload(provider) {
+  info('test StartDownload');
+  return new Promise(function(resolve, reject) {
+    provider.addEventListener('progress', function(event) {
+      ok(true, 'receive progress event');
+      is(event.loaded, 10, 'expected loaded');
+      is(event.total, 100, 'expected total');
+      resolve(provider);
+    });
+    provider.startDownload();
+  });
+}
+function testStopDownload(provider) {
+  info('test StopDownload');
+  return new Promise(function(resolve, reject) {
+    provider.stopDownload();
+    resolve(provider);
+  });
+}
+function testApplyUpdate(provider) {
+  info('test ApplyUpdate');
+  return new Promise(function(resolve, reject) {
+    provider.applyUpdate();
+    resolve(provider);
+  });
+}
+function testGetParameter(provider) {
+  info('test GetParameter');
+  return new Promise(function(resolve, reject) {
+    let dummy = provider.getParameter('dummy');
+    is(dummy, 'dummy-value', 'expected parameter');
+    resolve(provider);
+  });
+}
+function testSetParameter(provider) {
+  info('test SetParameter');
+  return new Promise(function(resolve, reject) {
+    provider.setParameter('dummy', 'dummy-value');
+    resolve();
+  });
+}
+function testSetActiveProviderError() {
+  info('test setActiveProvider error');
+  return new Promise(function(resolve, reject) {
+    navigator.updateManager.setActiveProvider('something not exsited').then(function(provider) {
+      ok(false, 'should not success');
+      resolve();
+    }, function(reason) {
+      info('error message: ' + reason);
+      ok(true, 'expected error while setActiveProvider');
+      resolve();
+    });
+  });
+}
+
+
+function runTest() {
+  ok(navigator.updateManager, 'should have navigator.updateManager');
+
+  setup()
+  .then(testGetProviders)
+  .then(testSetActiveProvider)
+  .then(testGetActiveProvider)
+  .then(testCheckForUpdate)
+  .then(testStartDownload)
+  .then(testStopDownload)
+  .then(testApplyUpdate)
+  .then(testGetParameter)
+  .then(testSetParameter)
+  .then(testSetActiveProviderError)
+  .then(function() {
+    info('test finished');
+    gScript.destroy();
+    SimpleTest.finish();
+  });
+}
+
+SpecialPowers.pushPermissions([
+    {type: 'system-update', allow: true, context: document},
+  ], function() {
+    SpecialPowers.pushPrefEnv({
+        'set': [
+          ['dom.system_update.enabled', true],
+          ['dom.system_update.debug', true],
+          ['dom.system_update.active', '@mozilla.org/test-update-provider;1'],
+        ]
+      }, runTest);
+  }
+);
+</script>
+</pre>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/dom/webidl/SystemUpdate.webidl
@@ -0,0 +1,48 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+dictionary SystemUpdateProviderInfo {
+  DOMString name = "";
+  DOMString uuid = "";
+};
+
+dictionary SystemUpdatePackageInfo {
+  DOMString type = "";
+  DOMString version = "";
+  DOMString description = "";
+  DOMTimeStamp buildDate = 0;
+  unsigned long long size = 0;
+};
+
+[JSImplementation="@mozilla.org/system-update-provider;1",
+ CheckPermissions="system-update",
+ Pref="dom.system_update.enabled"]
+interface SystemUpdateProvider : EventTarget {
+  readonly attribute DOMString name;
+  readonly attribute DOMString uuid;
+
+  attribute EventHandler onupdateavailable;
+  attribute EventHandler onprogress;
+  attribute EventHandler onupdateready;
+  attribute EventHandler onerror;
+
+  void checkForUpdate();
+  void startDownload();
+  void stopDownload();
+  void applyUpdate();
+  boolean setParameter(DOMString name, DOMString value);
+  DOMString getParameter(DOMString name);
+};
+
+[NavigatorProperty="updateManager",
+ JSImplementation="@mozilla.org/system-update-manager;1",
+ CheckPermissions="system-update",
+ Pref="dom.system_update.enabled"]
+interface SystemUpdateManager {
+  Promise<sequence<SystemUpdateProviderInfo>> getProviders();
+
+  Promise<SystemUpdateProvider> setActiveProvider(DOMString uuid);
+
+  Promise<SystemUpdateProvider> getActiveProvider();
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -503,16 +503,17 @@ WEBIDL_FILES = [
     'SVGTransformList.webidl',
     'SVGTSpanElement.webidl',
     'SVGUnitTypes.webidl',
     'SVGURIReference.webidl',
     'SVGUseElement.webidl',
     'SVGViewElement.webidl',
     'SVGZoomAndPan.webidl',
     'SVGZoomEvent.webidl',
+    'SystemUpdate.webidl',
     'Telephony.webidl',
     'TelephonyCall.webidl',
     'TelephonyCallGroup.webidl',
     'TelephonyCallId.webidl',
     'Text.webidl',
     'TextDecoder.webidl',
     'TextEncoder.webidl',
     'TextTrack.webidl',
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4799,16 +4799,20 @@ pref("dom.caches.enabled", true);
 // Empirically, this is the value returned by hal::GetTotalSystemMemory()
 // when Flame's memory is limited to 512MiB. If the camera stack determines
 // it is running on a low memory platform, features that can be reliably
 // supported will be disabled. This threshold can be adjusted to suit other
 // platforms; and set to 0 to disable the low-memory check altogether.
 pref("camera.control.low_memory_thresholdMB", 404);
 #endif
 
+// SystemUpdate API
+pref("dom.system_update.enabled", false);
+pref("dom.system_update.debug", false);
+
 // UDPSocket API
 pref("dom.udpsocket.enabled", false);
 
 // MessageChannel enabled by default.
 pref("dom.messageChannel.enabled", true);
 
 // Disable before keyboard events and after keyboard events by default.
 pref("dom.beforeAfterKeyboardEvent.enabled", false);
--- a/testing/docker/phone-builder/VERSION
+++ b/testing/docker/phone-builder/VERSION
@@ -1,1 +1,1 @@
-0.0.17
+0.0.18
--- a/testing/docker/phone-builder/bin/validate_task.py
+++ b/testing/docker/phone-builder/bin/validate_task.py
@@ -31,16 +31,20 @@ def check_task(task):
         print('Task has no base gecko repository', file=sys.stderr)
         return -1
 
     repo = payload['env']['GECKO_BASE_REPOSITORY']
     if not repo_matcher.match(repo):
         print('Invalid base repository', repo, file=sys.stderr)
         return -1
 
+    if "MOZHARNESS_CONFIG" in payload["env"] and \
+            "blobfree" in payload["env"]["MOZHARNESS_CONFIG"]:
+        return 0
+
     locations = task["extra"]["locations"]
     if "img" in locations:
         img = locations["img"]
         if img.startswith("public"):
             print('Cannot upload images to public', file=sys.stderr)
             return -1
 
     return 0
--- a/testing/taskcluster/tasks/branches/base_job_flags.yml
+++ b/testing/taskcluster/tasks/branches/base_job_flags.yml
@@ -13,25 +13,29 @@ flags:
     - emulator-l
     - 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-ota
     - flame-kk       # b2g flame kitkat
+    - flame-kk-blobfree
     - flame-kk-eng   # b2g flame eng build
     - flame-kk-spark-eng
+    - flame-kk-eng-blobfree
     - dolphin
     - dolphin-eng
     - dolphin-512
     - dolphin-512-eng
     - aries
+    - aries-blobfree
     - aries-ota
     - aries-eng
+    - aries-eng-blobfree
     - aries-dogfood
     - android-api-11
     - linux64
 
   tests:
     - cppunit
     - crashtest
     - crashtest-ipc
--- a/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml
+++ b/testing/taskcluster/tasks/branches/mozilla-central/job_flags.yml
@@ -1,30 +1,58 @@
 ---
 # For complete sample of all build and test jobs,
 # see <gecko>/testing/taskcluster/tasks/job_flags.yml
 
 $inherits:
   from: tasks/branches/base_jobs.yml
 
 builds:
+  aries-blobfree:
+    platforms:
+      - b2g
+    types:
+      opt:
+        task: tasks/builds/b2g_aries_spark_opt_blobfree.yml
+      debug:
+        task: tasks/builds/b2g_aries_spark_debug_blobfree.yml
+  aries-dogfood:
+    platforms:
+      - b2g
+    types:
+      opt:
+        task: tasks/builds/b2g_aries_spark_dogfood.yml
+  aries-eng-blobfree:
+    platforms:
+      - b2g
+    types:
+      opt:
+        task: tasks/builds/b2g_aries_spark_eng_blobfree.yml
   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
-  aries-dogfood:
+  flame-kk-blobfree:
     platforms:
       - b2g
     types:
       opt:
-        task: tasks/builds/b2g_aries_spark_dogfood.yml
+        task: tasks/builds/b2g_flame_kk_opt_blobfree.yml
+      debug:
+        task: tasks/builds/b2g_flame_kk_debug_blobfree.yml
+  flame-kk-eng-blobfree:
+    platforms:
+      - b2g
+    types:
+      opt:
+        task: tasks/builds/b2g_flame_kk_eng_blobfree.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
new file mode 100644
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_debug_blobfree.yml
@@ -0,0 +1,40 @@
+$inherits:
+  from: 'tasks/builds/b2g_phone_base.yml'
+  variables:
+    build_name: 'aries-blobfree'
+    build_type: 'debug'
+task:
+  workerType: flame-kk
+  scopes:
+    - 'docker-worker:cache:build-aries-debug-blobfree'
+  metadata:
+    name: 'B2G Aries Debug (blobfree)'
+
+  payload:
+    cache:
+      build-aries-debug-blobfree: /home/worker/workspace
+    env:
+      TARGET: 'aries'
+      DEBUG: 0
+      VARIANT: userdebug
+      GAIA_OPTIMIZE: '1'
+      B2G_SYSTEM_APPS: '1'
+      MOZHARNESS_CONFIG: b2g/taskcluster-spark-blobfree.py
+    command:
+      - >
+        checkout-gecko workspace &&
+        cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+        buildbot_step 'Build' ./build-phone.sh $HOME/workspace
+  extra:
+    treeherderEnv:
+      - staging
+    treeherder:
+      symbol: Bf
+      groupSymbol: Aries
+      groupName: Aries Device Image
+      machine:
+        platform: b2g-device-image
+      collection:
+        debug: true
+    locations:
+      img: 'public/build/aries.zip'
new file mode 100644
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_eng_blobfree.yml
@@ -0,0 +1,38 @@
+$inherits:
+  from: 'tasks/builds/b2g_phone_base.yml'
+  variables:
+    build_name: 'aries-eng-blobfree'
+    build_type: 'opt'
+task:
+  workerType: flame-kk
+  scopes:
+    - 'docker-worker:cache:build-aries-eng-blobfree'
+  metadata:
+    name: 'B2G Aries Eng (blobfree)'
+
+  payload:
+    cache:
+      build-aries-eng-blobfree: /home/worker/workspace
+    env:
+      TARGET: 'aries'
+      DEBUG: 0
+      VARIANT: eng
+      GAIA_OPTIMIZE: '1'
+      B2G_SYSTEM_APPS: '1'
+      MOZHARNESS_CONFIG: b2g/taskcluster-spark-blobfree.py
+    command:
+      - >
+        checkout-gecko workspace &&
+        cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+        buildbot_step 'Build' ./build-phone.sh $HOME/workspace
+  extra:
+    treeherderEnv:
+      - staging
+    treeherder:
+      symbol: Bef
+      groupSymbol: Aries
+      groupName: Aries Device Image
+      machine:
+        platform: b2g-device-image
+    locations:
+      img: 'public/build/aries.zip'
new file mode 100644
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_aries_spark_opt_blobfree.yml
@@ -0,0 +1,38 @@
+$inherits:
+  from: 'tasks/builds/b2g_phone_base.yml'
+  variables:
+    build_name: 'aries-blobfree'
+    build_type: 'opt'
+task:
+  workerType: flame-kk
+  scopes:
+    - 'docker-worker:cache:build-aries-opt-blobfree'
+  metadata:
+    name: 'B2G Aries Opt (blobfree)'
+
+  payload:
+    cache:
+      build-aries-opt-blobfree: /home/worker/workspace
+    env:
+      TARGET: 'aries'
+      DEBUG: 0
+      VARIANT: user
+      GAIA_OPTIMIZE: '1'
+      B2G_SYSTEM_APPS: '1'
+      MOZHARNESS_CONFIG: b2g/taskcluster-spark-blobfree.py
+    command:
+      - >
+        checkout-gecko workspace &&
+        cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+        buildbot_step 'Build' ./build-phone.sh $HOME/workspace
+  extra:
+    treeherderEnv:
+      - staging
+    treeherder:
+      symbol: Bf
+      groupSymbol: Aries
+      groupName: Aries Device Image
+      machine:
+        platform: b2g-device-image
+    locations:
+      img: 'public/build/aries.zip'
new file mode 100644
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_debug_blobfree.yml
@@ -0,0 +1,38 @@
+$inherits:
+  from: 'tasks/builds/b2g_phone_base.yml'
+  variables:
+    build_name: 'flame-kk-blobfree'
+    build_type: 'debug'
+task:
+  workerType: flame-kk
+  scopes:
+    - 'docker-worker:cache:build-flame-kk-debug-blobfree'
+  metadata:
+    name: 'B2G Flame KK Debug (blobfree)'
+
+  payload:
+    cache:
+      build-flame-kk-debug-blobfree: /home/worker/workspace
+    env:
+      TARGET: 'flame-kk'
+      DEBUG: 0
+      VARIANT: userdebug
+      MOZHARNESS_CONFIG: b2g/taskcluster-phone-blobfree.py
+    command:
+      - >
+        checkout-gecko workspace &&
+        cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+        buildbot_step 'Build' ./build-phone.sh $HOME/workspace
+  extra:
+    treeherderEnv:
+      - staging
+    treeherder:
+      symbol: Bf
+      groupSymbol: Flame-KK
+      groupName: Flame KitKat Device Image
+      machine:
+        platform: b2g-device-image
+      collection:
+        debug: true
+    locations:
+      img: 'public/build/flame-kk.zip'
new file mode 100644
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_eng_blobfree.yml
@@ -0,0 +1,38 @@
+$inherits:
+  from: 'tasks/builds/b2g_phone_base.yml'
+  variables:
+    build_name: 'flame-kk-eng-blobfree'
+    build_type: 'opt'
+task:
+  workerType: flame-kk
+  scopes:
+    - 'docker-worker:cache:build-flame-kk-eng-blobfree'
+  metadata:
+    name: 'B2G Flame KK Eng (blobfree)'
+
+  payload:
+    cache:
+      build-flame-kk-eng-blobfree: /home/worker/workspace
+    env:
+      TARGET: 'flame-kk'
+      DEBUG: 0
+      VARIANT: eng
+      GAIA_OPTIMIZE: '1'
+      B2G_SYSTEM_APPS: '1'
+      MOZHARNESS_CONFIG: b2g/taskcluster-phone-blobfree.py
+    command:
+      - >
+        checkout-gecko workspace &&
+        cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+        buildbot_step 'Build' ./build-phone.sh $HOME/workspace
+  extra:
+    treeherderEnv:
+      - staging
+    treeherder:
+      symbol: Bef
+      groupSymbol: Flame-KK
+      groupName: Flame KitKat Device Image
+      machine:
+        platform: b2g-device-image
+    locations:
+      img: 'public/build/flame-kk.zip'
new file mode 100644
--- /dev/null
+++ b/testing/taskcluster/tasks/builds/b2g_flame_kk_opt_blobfree.yml
@@ -0,0 +1,35 @@
+$inherits:
+  from: 'tasks/builds/b2g_phone_base.yml'
+  variables:
+    build_name: 'flame-kk-blobfree'
+    build_type: 'opt'
+task:
+  workerType: flame-kk
+  scopes:
+    - 'docker-worker:cache:build-flame-kk-opt-blobfree'
+  metadata:
+    name: 'B2G Flame KK Opt (blobfree)'
+
+  payload:
+    cache:
+      build-flame-kk-opt-blobfree: /home/worker/workspace
+    env:
+      TARGET: 'flame-kk'
+      DEBUG: 0
+      MOZHARNESS_CONFIG: b2g/taskcluster-phone-blobfree.py
+    command:
+      - >
+        checkout-gecko workspace &&
+        cd ./workspace/gecko/testing/taskcluster/scripts/phone-builder &&
+        buildbot_step 'Build' ./build-phone.sh $HOME/workspace
+  extra:
+    treeherderEnv:
+      - staging
+    treeherder:
+      symbol: Bf
+      groupSymbol: Flame-KK
+      groupName: Flame KitKat Device Image
+      machine:
+        platform: b2g-device-image
+    locations:
+      img: 'public/build/flame-kk.zip'