Bug 801742: Pass updater errors and status to Gaia in B2G. r=fabrice
authorMarshall Culpepper <marshall.law@gmail.com>
Tue, 16 Oct 2012 14:15:37 -0500
changeset 110448 e7497bc33b3c2b25b2aa40e29f2973aeff012084
parent 110447 b8b86cd19f38a16518b678a37f9bb15cc0cff63b
child 110449 a2a2ad2cfb501526bf5e0c60f9ce67dfd8c85c32
push id23695
push userryanvm@gmail.com
push dateWed, 17 Oct 2012 18:08:27 +0000
treeherdermozilla-central@a76c1f4c4112 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs801742
milestone19.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 801742: Pass updater errors and status to Gaia in B2G. r=fabrice
b2g/components/UpdatePrompt.js
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -21,33 +21,42 @@ let log =
 const APPLY_PROMPT_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.apply-prompt-timeout");
 const APPLY_IDLE_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.apply-idle-timeout");
 const SELF_DESTRUCT_TIMEOUT =
       Services.prefs.getIntPref("b2g.update.self-destruct-timeout");
 
 const APPLY_IDLE_TIMEOUT_SECONDS = APPLY_IDLE_TIMEOUT / 1000;
-
+const NETWORK_ERROR_OFFLINE = 111;
 
 XPCOMUtils.defineLazyServiceGetter(Services, "aus",
                                    "@mozilla.org/updates/update-service;1",
                                    "nsIApplicationUpdateService");
 
+XPCOMUtils.defineLazyServiceGetter(Services, "um",
+                                   "@mozilla.org/updates/update-manager;1",
+                                   "nsIUpdateManager");
+
 XPCOMUtils.defineLazyServiceGetter(Services, "idle",
                                    "@mozilla.org/widget/idleservice;1",
                                    "nsIIdleService");
 
+XPCOMUtils.defineLazyServiceGetter(Services, "settings",
+                                   "@mozilla.org/settingsService;1",
+                                   "nsISettingsService");
+
 function UpdatePrompt() {
   this.wrappedJSObject = this;
 }
 
 UpdatePrompt.prototype = {
   classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
+                                         Ci.nsIUpdateCheckListener,
                                          Ci.nsIRequestObserver,
                                          Ci.nsIProgressEventSink,
                                          Ci.nsIObserver]),
   _xpcom_factory: XPCOMUtils.generateSingletonFactory(UpdatePrompt),
 
   _update: null,
   _applyPromptTimer: null,
   _waitingForIdle: false,
@@ -83,67 +92,116 @@ UpdatePrompt.prototype = {
     log("Update is ready to apply, registering idle timeout of " +
         APPLY_IDLE_TIMEOUT_SECONDS + " seconds before prompting.");
 
     this._update = aUpdate;
     this.waitForIdle();
   },
 
   showUpdateError: function UP_showUpdateError(aUpdate) {
-    if (aUpdate.state == "failed") {
-      log("Failed to download update, errorCode: " + aUpdate.errorCode);
-    }
+    log("Update error, state: " + aUpdate.state + ", errorCode: " +
+        aUpdate.errorCode);
+
+    this.sendUpdateEvent("update-error", aUpdate);
+    this.setUpdateStatus(aUpdate.statusText);
   },
 
   showUpdateHistory: function UP_showUpdateHistory(aParent) { },
   showUpdateInstalled: function UP_showUpdateInstalled() { },
 
+  // nsIUpdateCheckListener
+
+  onCheckComplete: function UP_onCheckComplete(request, updates, updateCount) {
+    if (Services.um.activeUpdate) {
+      return;
+    }
+
+    if (updateCount == 0) {
+      this.setUpdateStatus("no-updates");
+      return;
+    }
+
+    let update = Services.aus.selectUpdate(updates, updateCount);
+    if (!update) {
+      this.setUpdateStatus("already-latest-version");
+      return;
+    }
+
+    this.setUpdateStatus("check-complete");
+    this.showUpdateAvailable(update);
+  },
+
+  onError: function UP_onError(request, update) {
+    if (update.errorCode == NETWORK_ERROR_OFFLINE) {
+      this.setUpdateStatus("retry-when-online");
+    }
+
+    Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
+    Services.aus.onError(request, update);
+  },
+
+  onProgress: function UP_onProgress(request, position, totalSize) {
+    Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
+    Services.aus.onProgress(request, position, totalSize);
+  },
+
   // Custom functions
 
   waitForIdle: function UP_waitForIdle() {
     if (this._waitingForIdle) {
       return;
     }
 
     this._waitingForIdle = true;
     Services.idle.addIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
     Services.obs.addObserver(this, "quit-application", false);
   },
 
+  setUpdateStatus: function UP_setUpdateStatus(aStatus) {
+    log("Setting gecko.updateStatus: " + aStatus);
+
+    let lock = Services.settings.createLock();
+    lock.set("gecko.updateStatus", aStatus, null);
+  },
+
   showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
     if (!this.sendUpdateEvent("update-prompt-apply", aUpdate)) {
       log("Unable to prompt, forcing restart");
       this.restartProcess();
       return;
     }
 
     // Schedule a fallback timeout in case the UI is unable to respond or show
     // a prompt for some reason.
     this._applyPromptTimer = this.createTimer(APPLY_PROMPT_TIMEOUT);
   },
 
   sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
     let detail = {
       displayVersion: aUpdate.displayVersion,
-      detailsURL: aUpdate.detailsURL
+      detailsURL: aUpdate.detailsURL,
+      statusText: aUpdate.statusText,
+      state: aUpdate.state,
+      errorCode: aUpdate.errorCode,
+      isOSUpdate: aUpdate.isOSUpdate
     };
 
     let patch = aUpdate.selectedPatch;
-    if (!patch) {
+    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.
-      if (aUpdate.patchCount == 0) {
-        log("Warning: no patches available in update");
-        return false;
-      }
       patch = aUpdate.getPatchAt(0);
     }
 
-    detail.size = patch.size;
-    detail.updateType = patch.type;
+    if (patch) {
+      detail.size = patch.size;
+      detail.updateType = patch.type;
+    } else {
+      log("Warning: no patches available in update");
+    }
 
     this._update = aUpdate;
     return this.sendChromeEvent(aType, detail);
   },
 
   sendChromeEvent: function UP_sendChromeEvent(aType, aDetail) {
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     if (!browser) {
@@ -249,19 +307,17 @@ UpdatePrompt.prototype = {
     }
   },
 
   forceUpdateCheck: function UP_forceUpdateCheck() {
     log("Forcing update check");
 
     let checker = Cc["@mozilla.org/updates/update-checker;1"]
                     .createInstance(Ci.nsIUpdateChecker);
-
-    Services.aus.QueryInterface(Ci.nsIUpdateCheckListener);
-    checker.checkForUpdates(Services.aus, true);
+    checker.checkForUpdates(this, true);
   },
 
   handleEvent: function UP_handleEvent(evt) {
     if (evt.type !== "mozContentEvent") {
       return;
     }
 
     let detail = evt.detail;