Bug 798948: Allow force checking of updates in B2G. r=fabrice
authorMarshall Culpepper <marshall.law@gmail.com>
Sat, 13 Oct 2012 13:11:09 -0500
changeset 110303 24d7f3e5be47101fd6f4990de2fdd374e49401ab
parent 110302 a2be97f8e8749539ebc1a0e8c015a65c8a3e59a6
child 110304 3884ab03451ddf5a1e525a533baa1ef7916ba60f
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersfabrice
bugs798948
milestone19.0a1
Bug 798948: Allow force checking of updates in B2G. r=fabrice
b2g/chrome/content/shell.js
b2g/components/UpdatePrompt.js
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -783,16 +783,24 @@ window.addEventListener('ContentStart', 
       let props = aSubject.QueryInterface(Ci.nsIPropertyBag2);
       if (props.hasKey("abnormal") && props.hasKey("dumpID")) {
         shell.reportCrash(props.getProperty("dumpID"));
       }
     },
     "ipc:content-shutdown", false);
 })();
 
+window.addEventListener('ContentStart', function update_onContentStart() {
+  let updatePrompt = Cc["@mozilla.org/updates/update-prompt;1"]
+                       .createInstance(Ci.nsIUpdatePrompt);
+
+  let content = shell.contentBrowser.contentWindow;
+  content.addEventListener("mozContentEvent", updatePrompt.wrappedJSObject);
+});
+
 (function geolocationStatusTracker() {
   let gGeolocationActiveCount = 0;
 
   Services.obs.addObserver(function(aSubject, aTopic, aData) {
     let oldCount = gGeolocationActiveCount;
     if (aData == "starting") {
       gGeolocationActiveCount += 1;
     } else if (aData == "shutdown") {
--- a/b2g/components/UpdatePrompt.js
+++ b/b2g/components/UpdatePrompt.js
@@ -30,39 +30,42 @@ const APPLY_IDLE_TIMEOUT_SECONDS = APPLY
 
 XPCOMUtils.defineLazyServiceGetter(Services, "aus",
                                    "@mozilla.org/updates/update-service;1",
                                    "nsIApplicationUpdateService");
 
 XPCOMUtils.defineLazyServiceGetter(Services, "idle",
                                    "@mozilla.org/widget/idleservice;1",
                                    "nsIIdleService");
-function UpdatePrompt() { }
+
+function UpdatePrompt() {
+  this.wrappedJSObject = this;
+}
 
 UpdatePrompt.prototype = {
   classID: Components.ID("{88b3eb21-d072-4e3b-886d-f89d8c49fe59}"),
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdatePrompt,
                                          Ci.nsIRequestObserver,
                                          Ci.nsIProgressEventSink,
                                          Ci.nsIObserver]),
+  _xpcom_factory: XPCOMUtils.generateSingletonFactory(UpdatePrompt),
 
   _update: null,
   _applyPromptTimer: null,
   _waitingForIdle: false,
 
   // 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) {
-    if (!this.sendUpdateEvent("update-available", aUpdate,
-                             this.handleAvailableResult)) {
+    if (!this.sendUpdateEvent("update-available", aUpdate)) {
 
       log("Unable to prompt for available update, forcing download");
       this.downloadUpdate(aUpdate);
     }
   },
 
   showUpdateDownloaded: function UP_showUpdateDownloaded(aUpdate, aBackground) {
     // The update has been downloaded and staged. We send the update-downloaded
@@ -100,31 +103,29 @@ UpdatePrompt.prototype = {
       return;
     }
 
     this._waitingForIdle = true;
     Services.idle.addIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
     Services.obs.addObserver(this, "quit-application", false);
   },
 
-
   showApplyPrompt: function UP_showApplyPrompt(aUpdate) {
-    if (!this.sendUpdateEvent("update-prompt-apply", aUpdate,
-                             this.handleApplyPromptResult)) {
+    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, aCallback) {
+  sendUpdateEvent: function UP_sendUpdateEvent(aType, aUpdate) {
     let detail = {
       displayVersion: aUpdate.displayVersion,
       detailsURL: aUpdate.detailsURL
     };
 
     let patch = aUpdate.selectedPatch;
     if (!patch) {
       // For now we just check the first patch to get size information if a
@@ -135,57 +136,30 @@ UpdatePrompt.prototype = {
       }
       patch = aUpdate.getPatchAt(0);
     }
 
     detail.size = patch.size;
     detail.updateType = patch.type;
 
     this._update = aUpdate;
-    return this.sendChromeEvent(aType, detail, aCallback);
+    return this.sendChromeEvent(aType, detail);
   },
 
-  sendChromeEvent: function UP_sendChromeEvent(aType, aDetail, aCallback) {
+  sendChromeEvent: function UP_sendChromeEvent(aType, aDetail) {
     let browser = Services.wm.getMostRecentWindow("navigator:browser");
     if (!browser) {
       log("Warning: Couldn't send update event " + aType +
           ": no content browser");
       return false;
     }
 
-    let content = browser.getContentWindow();
-    if (!content) {
-      log("Warning: Couldn't send update event " + aType +
-          ": no content window");
-      return false;
-    }
-
     let detail = aDetail || {};
     detail.type = aType;
 
-    if (!aCallback) {
-      browser.shell.sendChromeEvent(detail);
-      return true;
-    }
-
-    let resultType = aType + "-result";
-    let handleContentEvent = (function(e) {
-      if (!e.detail) {
-        return;
-      }
-
-      let detail = e.detail;
-      if (detail.type == resultType) {
-        aCallback.call(this, detail);
-        content.removeEventListener("mozContentEvent", handleContentEvent);
-        this._update = null;
-      }
-    }).bind(this);
-
-    content.addEventListener("mozContentEvent", handleContentEvent);
     browser.shell.sendChromeEvent(detail);
     return true;
   },
 
   handleAvailableResult: function UP_handleAvailableResult(aDetail) {
     // If the user doesn't choose "download", the updater will implicitly call
     // showUpdateAvailable again after a certain period of time
     switch (aDetail.result) {
@@ -203,16 +177,17 @@ UpdatePrompt.prototype = {
 
     switch (aDetail.result) {
       case "wait":
         // Wait until the user is idle before prompting to apply the update
         this.waitForIdle();
         break;
       case "restart":
         this.finishUpdate();
+        this._update = null;
         break;
     }
   },
 
   downloadUpdate: function UP_downloadUpdate(aUpdate) {
     Services.aus.downloadUpdate(aUpdate, true);
     Services.aus.addDownloadListener(this);
   },
@@ -269,31 +244,67 @@ UpdatePrompt.prototype = {
     try {
       recoveryService.installFotaUpdate(aOsUpdatePath);
     } catch(e) {
       log("Error: Couldn't reboot into recovery to apply FOTA update " +
           aOsUpdatePath);
     }
   },
 
+  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);
+  },
+
+  handleEvent: function UP_handleEvent(evt) {
+    if (evt.type !== "mozContentEvent") {
+      return;
+    }
+
+    let detail = evt.detail;
+    if (!detail) {
+      return;
+    }
+
+    switch (detail.type) {
+      case "force-update-check":
+        this.forceUpdateCheck();
+        break;
+      case "update-available-result":
+        this.handleAvailableResult(detail);
+        this._update = null;
+        break;
+      case "update-prompt-apply-result":
+        this.handleApplyPromptResult(detail);
+        break;
+    }
+  },
+
   // nsIObserver
 
   observe: function UP_observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "idle":
         this._waitingForIdle = false;
         this.showApplyPrompt(this._update);
         // Fall through
       case "quit-application":
         Services.idle.removeIdleObserver(this, APPLY_IDLE_TIMEOUT_SECONDS);
         Services.obs.removeObserver(this, "quit-application");
         break;
     }
   },
 
+  // nsITimerCallback
+
   notify: function UP_notify(aTimer) {
     if (aTimer == this._applyPromptTimer) {
       log("Timed out waiting for result, restarting");
       this._applyPromptTimer = null;
       this.finishUpdate();
     }
   },