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 110580 e7497bc33b3c2b25b2aa40e29f2973aeff012084
parent 110579 b8b86cd19f38a16518b678a37f9bb15cc0cff63b
child 110581 a2a2ad2cfb501526bf5e0c60f9ce67dfd8c85c32
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersfabrice
bugs801742
milestone19.0a1
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;