--- 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();
}
},