diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index f1f5ece43190..c9d763fe3515 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -112,16 +112,15 @@ pref("app.update.url", "https://aus2.mozilla.org/update/3/%PRODUCT%/%VERSION%/%B // Interval: Time between checks for a new version (in seconds) // default=1 day pref("app.update.interval", 86400); -// Interval: Time before prompting the user to download a new version that -// is available (in seconds) default=1 day -pref("app.update.nagTimer.download", 86400); -// Interval: Time before prompting the user to restart to install the latest -// download (in seconds) default=30 minutes -pref("app.update.nagTimer.restart", 1800); +// Interval: Time before prompting the user again to restart to install the +// latest download (in seconds) default=1 day +pref("app.update.nagTimer.restart", 86400); // Interval: When all registered timers should be checked (in milliseconds) // default=10 minutes pref("app.update.timer", 600000); -// Show the Update Checking UI when the user was idle for x seconds +// Give the user x seconds to react before showing the big UI. default=12 hrs +pref("app.update.promptWaitTime", 43200); +// Show the Update Checking/Ready UI when the user was idle for x seconds pref("app.update.idletime", 60); // Whether or not we show a dialog box informing the user that the update was diff --git a/browser/base/content/utilityOverlay.js b/browser/base/content/utilityOverlay.js index 4c1b9eccb5ff..3514b5a7250d 100644 --- a/browser/base/content/utilityOverlay.js +++ b/browser/base/content/utilityOverlay.js @@ -422,7 +422,7 @@ function checkForUpdates() // UI instead and let the user know they have to restart the browser for // the changes to be applied. if (um.activeUpdate && um.activeUpdate.state == "pending") - prompter.showUpdateDownloaded(um.activeUpdate, false); + prompter.showUpdateDownloaded(um.activeUpdate); else prompter.checkForUpdates(); } diff --git a/toolkit/locales/en-US/chrome/mozapps/update/updates.properties b/toolkit/locales/en-US/chrome/mozapps/update/updates.properties index 83e423c56773..8b3dfde6556e 100755 --- a/toolkit/locales/en-US/chrome/mozapps/update/updates.properties +++ b/toolkit/locales/en-US/chrome/mozapps/update/updates.properties @@ -79,3 +79,12 @@ installPending=Install Pending updaterIOErrorTitle=Software Update Failed updaterIOErrorMsg=The update could not be installed. Please make sure there are no other copies of %S running on your computer, and then restart %S to try again. + +updateAvailable_minor.title=%S available +updateAvailable_minor.text=Download & Install… +updateAvailable_major.title=%S available +updateAvailable_major.text=Get the new version… +updateDownloaded_minor.title=%S available +updateDownloaded_minor.text=Apply Downloaded Update… +updateDownloaded_major.title=%S available +updateDownloaded_major.text=Install the new version… diff --git a/toolkit/mozapps/update/content/updates.js b/toolkit/mozapps/update/content/updates.js index 1872e39ea183..18ee74787813 100755 --- a/toolkit/mozapps/update/content/updates.js +++ b/toolkit/mozapps/update/content/updates.js @@ -43,7 +43,6 @@ const nsIIncrementalDownload = Components.interfaces.nsIIncrementalDownload; const XMLNS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; const PREF_UPDATE_MANUAL_URL = "app.update.url.manual"; -const PREF_UPDATE_NAGTIMER_DL = "app.update.nagTimer.download"; const PREF_UPDATE_NAGTIMER_RESTART = "app.update.nagTimer.restart"; const PREF_APP_UPDATE_LOG_BRANCH = "app.update.log."; const PREF_UPDATE_TEST_LOOP = "app.update.test.loop"; @@ -1674,7 +1673,7 @@ var gFinishedPage = { ps.alert(window, gUpdates.strings.getString("restartLaterTitle"), message); - var interval = getPref("getIntPref", PREF_UPDATE_NAGTIMER_RESTART, 1800); + var interval = getPref("getIntPref", PREF_UPDATE_NAGTIMER_RESTART, 86400); gUpdates.registerNagTimer("restart-nag-timer", interval, "showUpdateComplete"); } diff --git a/toolkit/mozapps/update/public/nsIUpdateService.idl b/toolkit/mozapps/update/public/nsIUpdateService.idl index 82a0f2eeace8..6293932eb7a5 100644 --- a/toolkit/mozapps/update/public/nsIUpdateService.idl +++ b/toolkit/mozapps/update/public/nsIUpdateService.idl @@ -439,7 +439,7 @@ interface nsIUpdateManager : nsISupports * An interface describing an object that can show various kinds of Update * notification UI to the user. */ -[scriptable, uuid(13520e54-9a17-11dc-8314-0800200c9a66)] +[scriptable, uuid(6f145728-abc0-11dc-8314-0800200c9a66)] interface nsIUpdatePrompt : nsISupports { /** @@ -450,7 +450,7 @@ interface nsIUpdatePrompt : nsISupports /** * Show a message advising that an update is available for download and - * install. The message will be held back until the user is idle. + * install. * @param update * The update to be downloaded and installed */ @@ -462,10 +462,11 @@ interface nsIUpdatePrompt : nsISupports * update can be installed. * @param update * The update that was downloaded - * @param whenIdle - * Holds the message back until the user is idle + * @param background + * Less obtrusive UI, starting with a non-modal notification alert */ - void showUpdateDownloaded(in nsIUpdate update, in boolean whenIdle); + void showUpdateDownloaded(in nsIUpdate update, + [optional] in boolean background); /** * Shows a message detailing the update which was installed. diff --git a/toolkit/mozapps/update/src/nsUpdateService.js.in b/toolkit/mozapps/update/src/nsUpdateService.js.in index 5f42b575234b..7e995d86afe7 100644 --- a/toolkit/mozapps/update/src/nsUpdateService.js.in +++ b/toolkit/mozapps/update/src/nsUpdateService.js.in @@ -49,6 +49,7 @@ const PREF_APP_UPDATE_SILENT = "app.update.silent"; const PREF_APP_UPDATE_INTERVAL = "app.update.interval"; const PREF_APP_UPDATE_TIMER = "app.update.timer"; const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; +const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime"; const PREF_APP_UPDATE_LOG_BRANCH = "app.update.log."; const PREF_APP_UPDATE_URL = "app.update.url"; const PREF_APP_UPDATE_URL_OVERRIDE = "app.update.url.override"; @@ -2802,23 +2803,36 @@ UpdatePrompt.prototype = { * See nsIUpdateService.idl */ showUpdateAvailable: function(update) { - if (this._enabled) { - this._showUIWhenIdle(null, URI_UPDATE_PROMPT_DIALOG, null, - "Update:Wizard", "updatesavailable", update); - } + if (!this._enabled) + return; + var bundle = this._updateBundle; + var stringsPrefix = "updateAvailable_" + update.type + "."; + var title = bundle.formatStringFromName(stringsPrefix + "title", [update.name], 1); + var text = bundle.GetStringFromName(stringsPrefix + "text"); + var imageUrl = ""; + this._showUnobtrusiveUI(null, URI_UPDATE_PROMPT_DIALOG, null, + "Update:Wizard", "updatesavailable", update, + title, text, imageUrl); }, /** * See nsIUpdateService.idl */ - showUpdateDownloaded: function(update, whenIdle) { - if (this._enabled) { - if (whenIdle) - this._showUIWhenIdle(null, URI_UPDATE_PROMPT_DIALOG, null, - "Update:Wizard", "finishedBackground", update); - else - this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, - "Update:Wizard", "finishedBackground", update); + showUpdateDownloaded: function(update, background) { + if (background) { + if (!this._enabled) + return; + var bundle = this._updateBundle; + var stringsPrefix = "updateDownloaded_" + update.type + "."; + var title = bundle.formatStringFromName(stringsPrefix + "title", [update.name], 1); + var text = bundle.GetStringFromName(stringsPrefix + "text"); + var imageUrl = ""; + this._showUnobtrusiveUI(null, URI_UPDATE_PROMPT_DIALOG, null, + "Update:Wizard", "finishedBackground", update, + title, text, imageUrl); + } else { + this._showUI(null, URI_UPDATE_PROMPT_DIALOG, null, + "Update:Wizard", "finishedBackground", update); } }, @@ -2841,10 +2855,7 @@ UpdatePrompt.prototype = { if (this._enabled) { // In some cases, we want to just show a simple alert dialog: if (update.state == STATE_FAILED && update.errorCode == WRITE_ERROR) { - var sbs = - Components.classes["@mozilla.org/intl/stringbundle;1"]. - getService(Components.interfaces.nsIStringBundleService); - var updateBundle = sbs.createBundle(URI_UPDATES_PROPERTIES); + var updateBundle = this._updateBundle; var title = updateBundle.GetStringFromName("updaterIOErrorTitle"); var text = updateBundle.formatStringFromName("updaterIOErrorMsg", [gApp.name, gApp.name], 2); @@ -2874,8 +2885,84 @@ UpdatePrompt.prototype = { return !getPref("getBoolPref", PREF_APP_UPDATE_SILENT, false); }, + get _updateBundle() { + return Components.classes["@mozilla.org/intl/stringbundle;1"] + .getService(Components.interfaces.nsIStringBundleService) + .createBundle(URI_UPDATES_PROPERTIES); + }, + /** - * Show the Update Checking UI when the user was idle + * Initiate a less obtrusive UI, starting with a non-modal notification alert + * @param parent + * A parent window, can be null + * @param uri + * The URI string of the dialog to show + * @param name + * The Window Name of the dialog to show, in case it is already open + * and can merely be focused + * @param page + * The page of the wizard to be displayed, if one is already open. + * @param update + * An update to pass to the UI in the window arguments. + * Can be null + * @param title + * The title for the notification alert. + * @param text + * The contents of the notification alert. + * @param imageUrl + * A URL identifying the image to put in the notification alert. + */ + _showUnobtrusiveUI: function(parent, uri, features, name, page, update, + title, text, imageUrl) { + var observer = { + updatePrompt: this, + service: null, + timer: null, + notify: function () { + // the user hasn't restarted yet => prompt when idle + this.service.removeObserver(this, "quit-application"); + this.updatePrompt._showUIWhenIdle(parent, uri, features, name, page, update); + }, + observe: function (aSubject, aTopic, aData) { + switch (aTopic) { + case "alertclickcallback": + this.updatePrompt._showUI(parent, uri, features, name, page, update); + // fall thru + case "quit-application": + this.timer.cancel(); + this.service.removeObserver(this, "quit-application"); + break; + } + } + }; + + try { + var notifier = Components.classes["@mozilla.org/alerts-service;1"] + .getService(Components.interfaces.nsIAlertsService); + notifier.showAlertNotification(imageUrl, title, text, true, "", observer); + } + catch (e) { + // Failed to retrieve alerts service, platform unsupported + this._showUIWhenIdle(parent, uri, features, name, page, update); + return; + } + + observer.service = + Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + observer.service.addObserver(observer, "quit-application", false); + + // Give the user x seconds to react before showing the big UI + var promptWaitTime = getPref("getIntPref", PREF_APP_UPDATE_PROMPTWAITTIME, 43200); + observer.timer = + Components.classes["@mozilla.org/timer;1"] + .createInstance(Components.interfaces.nsITimer); + observer.timer.initWithCallback(observer, promptWaitTime * 1000, + observer.timer.TYPE_ONE_SHOT); + }, + + /** + * Show the UI when the user was idle * @param parent * A parent window, can be null * @param uri