commit d176b2c555c1f0298ab8764bcb6c4fda8dc255ff Author: Kathy Brade brade@pearlcrescent.com Date: Wed Jan 16 15:06:07 2019 -0500
Bug 28885: notify users that update is downloading
Add a "Downloading Tor Browser update" item which appears in the hamburger (app) menu while the update service is downloading a MAR file. Before this change, the browser did not indicate to the user that an update was in progress, which is especially confusing in Tor Browser because downloads often take some time. If the user clicks on the new menu item, the about dialog is opened to allow the user to see download progress.
As part of this fix, the update service was changed to always show update-related messages in the hamburger menu, even if the update was started in the foreground via the about dialog or via the "Check for Tor Browser Update" toolbar menu item. This change is consistent with the Tor Browser goal of making sure users are informed about the update process. --- browser/app/profile/000-tor-browser.js | 1 + .../customizableui/content/panelUI.inc.xul | 1 + .../components/customizableui/content/panelUI.js | 28 ++++++++++++++++++++++ browser/components/nsBrowserGlue.js | 1 + .../themes/shared/customizableui/panelUI.inc.css | 1 + browser/themes/shared/toolbarbutton-icons.inc.css | 1 + toolkit/mozapps/update/UpdateListener.jsm | 23 ++++++++++++++++++ toolkit/mozapps/update/nsUpdateService.js | 28 ++++++++++++++++++++++ 8 files changed, 84 insertions(+)
diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js index 11027f4c9a3a..9f1e727ce724 100644 --- a/browser/app/profile/000-tor-browser.js +++ b/browser/app/profile/000-tor-browser.js @@ -20,6 +20,7 @@ pref("startup.homepage_override_url", "https://blog.torproject.org/category/tags // Try to nag a bit more about updates: Pop up a restart dialog an hour after the initial dialog pref("app.update.promptWaitTime", 3600); pref("app.update.badge", true); +pref("app.update.notifyDuringDownload", true); pref("extensions.hotfix.id", ""); // Bug 16837: Disable hotfix updates as they may cause compat issues
#ifdef XP_WIN diff --git a/browser/components/customizableui/content/panelUI.inc.xul b/browser/components/customizableui/content/panelUI.inc.xul index 5891556a6e5f..ee4f8351d02b 100644 --- a/browser/components/customizableui/content/panelUI.inc.xul +++ b/browser/components/customizableui/content/panelUI.inc.xul @@ -172,6 +172,7 @@ <vbox id="appMenu-addon-banners"/> <toolbarbutton class="panel-banner-item" label-update-available="&updateAvailable.panelUI.label;" + label-update-downloading="Downloading update" label-update-manual="&updateManual.panelUI.label;" label-update-restart="&updateRestart.panelUI.label2;" oncommand="PanelUI._onBannerItemSelected(event)" diff --git a/browser/components/customizableui/content/panelUI.js b/browser/components/customizableui/content/panelUI.js index 5233be130be2..a4018bb2e6c2 100644 --- a/browser/components/customizableui/content/panelUI.js +++ b/browser/components/customizableui/content/panelUI.js @@ -46,6 +46,7 @@ const PanelUI = {
init() { this._initElements(); + this._initUpdaterStrings();
this.menuButton.addEventListener("mousedown", this); this.menuButton.addEventListener("keypress", this); @@ -53,6 +54,7 @@ const PanelUI = {
Services.obs.addObserver(this, "fullscreen-nav-toolbox"); Services.obs.addObserver(this, "appMenu-notifications"); + Services.obs.addObserver(this, "show-update-progress");
XPCOMUtils.defineLazyPreferenceGetter(this, "autoHideToolbarInFullScreen", "browser.fullscreen.autohide", false, (pref, previousValue, newValue) => { @@ -120,6 +122,28 @@ const PanelUI = { } },
+ _initUpdaterStrings() { + // If Torbutton is installed and enabled, replace the "Downloading update" + // string with one from torbutton.properties (to facilitate localization). + try { + let brands = Services.strings.createBundle( + "chrome://branding/locale/brand.properties"); + let stringArgs = [brands.GetStringFromName("brandShortName")]; + let torbuttonBundle = Services.strings.createBundle( + "chrome://torbutton/locale/torbutton.properties"); + let label = torbuttonBundle.formatStringFromName( + "updateDownloadingPanelUILabel", stringArgs, 1); + let attrName = "label-update-downloading"; + let elements = document.getElementsByClassName("panel-banner-item"); + for (let i = 0; i < elements.length; ++i) { + let elem = elements.item(i); + if (elem.hasAttribute(attrName)) { + elem.setAttribute(attrName, label); + } + } + } catch (e) {} + }, + _eventListenersAdded: false, _ensureEventListenersAdded() { if (this._eventListenersAdded) @@ -152,6 +176,7 @@ const PanelUI = {
Services.obs.removeObserver(this, "fullscreen-nav-toolbox"); Services.obs.removeObserver(this, "appMenu-notifications"); + Services.obs.removeObserver(this, "show-update-progress");
window.removeEventListener("MozDOMFullscreen:Entered", this); window.removeEventListener("MozDOMFullscreen:Exited", this); @@ -252,6 +277,9 @@ const PanelUI = { this._notifications = AppMenuNotifications.notifications; this._updateNotifications(true); break; + case "show-update-progress": + openAboutDialog(); + break; } },
diff --git a/browser/components/nsBrowserGlue.js b/browser/components/nsBrowserGlue.js index 0ec10a3337d4..e68817fd3c7c 100644 --- a/browser/components/nsBrowserGlue.js +++ b/browser/components/nsBrowserGlue.js @@ -187,6 +187,7 @@ const global = this;
const listeners = { observers: { + "update-downloading": ["UpdateListener"], "update-staged": ["UpdateListener"], "update-downloaded": ["UpdateListener"], "update-available": ["UpdateListener"], diff --git a/browser/themes/shared/customizableui/panelUI.inc.css b/browser/themes/shared/customizableui/panelUI.inc.css index 75946aa5f082..4cb2032a09d1 100644 --- a/browser/themes/shared/customizableui/panelUI.inc.css +++ b/browser/themes/shared/customizableui/panelUI.inc.css @@ -62,6 +62,7 @@ }
#PanelUI-menu-button[badge-status="update-available"] > .toolbarbutton-badge-stack > .toolbarbutton-badge, +#PanelUI-menu-button[badge-status="update-downloading"] > .toolbarbutton-badge-stack > .toolbarbutton-badge, #PanelUI-menu-button[badge-status="update-manual"] > .toolbarbutton-badge-stack > .toolbarbutton-badge, #PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge { background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center; diff --git a/browser/themes/shared/toolbarbutton-icons.inc.css b/browser/themes/shared/toolbarbutton-icons.inc.css index d3a634d5ff51..230ddf951858 100644 --- a/browser/themes/shared/toolbarbutton-icons.inc.css +++ b/browser/themes/shared/toolbarbutton-icons.inc.css @@ -259,6 +259,7 @@ toolbar[brighttext] { }
#PanelUI-menu-button[badge-status="update-available"], +#PanelUI-menu-button[badge-status="update-downloading"], #PanelUI-menu-button[badge-status="update-manual"], #PanelUI-menu-button[badge-status="update-restart"] { list-style-image: url("chrome://browser/skin/menu-badged.svg"); diff --git a/toolkit/mozapps/update/UpdateListener.jsm b/toolkit/mozapps/update/UpdateListener.jsm index a2b228d321ac..8437f4b884d4 100644 --- a/toolkit/mozapps/update/UpdateListener.jsm +++ b/toolkit/mozapps/update/UpdateListener.jsm @@ -127,6 +127,15 @@ var UpdateListener = { doc => this.replaceReleaseNotes(doc, update, "updateManualWhatsNew")); },
+ showUpdateDownloadingNotification() { + this.showUpdateNotification("downloading", true, true, () => { + // The user clicked on the "Downloading update" app menu item. + // Code in browser/components/customizableui/content/panelUI.js + // receives the following notification and opens the about dialog. + Services.obs.notifyObservers(null, "show-update-progress", null); + }); + }, + handleUpdateError(update, status) { switch (status) { case "download-attempt-failed": @@ -204,6 +213,17 @@ var UpdateListener = { } },
+ handleUpdateDownloading(status) { + switch (status) { + case "downloading": + this.showUpdateDownloadingNotification(); + break; + case "idle": + this.reset(); + break; + } + }, + observe(subject, topic, status) { if (!this.enabled) { return; @@ -215,6 +235,9 @@ var UpdateListener = { case "update-available": this.handleUpdateAvailable(update, status); break; + case "update-downloading": + this.handleUpdateDownloading(status); + break; case "update-staged": case "update-downloaded": this.handleUpdateStagedOrDownloaded(update, status); diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js index b2a4e82cf241..159112805425 100644 --- a/toolkit/mozapps/update/nsUpdateService.js +++ b/toolkit/mozapps/update/nsUpdateService.js @@ -38,6 +38,7 @@ const PREF_APP_UPDATE_ENABLED = "app.update.enabled"; const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; const PREF_APP_UPDATE_LOG = "app.update.log"; const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED = "app.update.notifiedUnsupported"; +const PREF_APP_UPDATE_NOTIFYDURINGDOWNLOAD = "app.update.notifyDuringDownload"; const PREF_APP_UPDATE_POSTUPDATE = "app.update.postupdate"; const PREF_APP_UPDATE_PROMPTWAITTIME = "app.update.promptWaitTime"; const PREF_APP_UPDATE_SERVICE_ENABLED = "app.update.service.enabled"; @@ -3325,6 +3326,8 @@ Downloader.prototype = { if (this._request && this._request instanceof Ci.nsIRequest) { this._request.cancel(cancelError); } + + this._notifyDownloadStatusObservers(); },
/** @@ -3498,6 +3501,13 @@ Downloader.prototype = { return selectedPatch; },
+ _notifyDownloadStatusObservers: function Downloader_notifyDownloadStatusObservers() { + if (Services.prefs.getBoolPref(PREF_APP_UPDATE_NOTIFYDURINGDOWNLOAD, false)) { + let status = this.updateService.isDownloading ? "downloading" : "idle"; + Services.obs.notifyObservers(this._update, "update-downloading", status); + } + }, + /** * Whether or not we are currently downloading something. */ @@ -3552,6 +3562,9 @@ Downloader.prototype = { var um = Cc["@mozilla.org/updates/update-manager;1"]. getService(Ci.nsIUpdateManager); um.saveUpdates(); + + this._notifyDownloadStatusObservers(); + return STATE_DOWNLOADING; },
@@ -3728,9 +3741,16 @@ Downloader.prototype = { } else { state = STATE_PENDING; } +#if defined(TOR_BROWSER_UPDATE) + // In Tor Browser, show update-related messages in the hamburger menu + // even if the update was started in the foreground, e.g., from the + // about box. + shouldShowPrompt = !getCanStageUpdates(); +#else if (this.background) { shouldShowPrompt = !getCanStageUpdates(); } +#endif AUSTLMY.pingDownloadCode(this.isCompleteUpdate, AUSTLMY.DWNLD_SUCCESS);
// Tell the updater.exe we're ready to apply. @@ -3835,6 +3855,7 @@ Downloader.prototype = { }
this._request = null; + this._notifyDownloadStatusObservers();
if (state == STATE_DOWNLOAD_FAILED) { var allFailed = true; @@ -3907,9 +3928,16 @@ Downloader.prototype = { // processor service. LOG("Downloader:onStopRequest - failed to stage update. Exception: " + e); +#if defined(TOR_BROWSER_UPDATE) + // In Tor Browser, show update-related messages in the hamburger menu + // even if the update was started in the foreground, e.g., from the + // about box. + shouldShowPrompt = true; +#else if (this.background) { shouldShowPrompt = true; } +#endif } } }