From c60abe439c8ed1a394f5d9474a2aeb545953dec5 Mon Sep 17 00:00:00 2001 From: Kathy Brade Date: Wed, 16 Jan 2019 15:06:07 -0500 Subject: [PATCH] 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 + browser/components/BrowserGlue.jsm | 1 + .../customizableui/content/panelUI.inc.xul | 1 + .../customizableui/content/panelUI.js | 28 +++++++++++++++++++ .../shared/customizableui/panelUI.inc.css | 3 ++ .../themes/shared/notification-icons.inc.css | 1 + .../themes/shared/toolbarbutton-icons.inc.css | 1 + toolkit/mozapps/update/UpdateListener.jsm | 23 +++++++++++++++ toolkit/mozapps/update/UpdateService.jsm | 28 +++++++++++++++++++ 9 files changed, 87 insertions(+) diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js index 47d0e52194ecf..2a5adf07d9745 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); #ifndef XP_MACOSX // Disable staged updates on platforms other than macOS. diff --git a/browser/components/BrowserGlue.jsm b/browser/components/BrowserGlue.jsm index 1e08f4b518882..cc7c6224bdf58 100644 --- a/browser/components/BrowserGlue.jsm +++ b/browser/components/BrowserGlue.jsm @@ -569,6 +569,7 @@ const global = this; const listeners = { observers: { + "update-downloading": ["UpdateListener"], "update-staged": ["UpdateListener"], "update-downloaded": ["UpdateListener"], "update-available": ["UpdateListener"], diff --git a/browser/components/customizableui/content/panelUI.inc.xul b/browser/components/customizableui/content/panelUI.inc.xul index 6d593f89e5aa0..b2c70b9f041dc 100644 --- a/browser/components/customizableui/content/panelUI.inc.xul +++ b/browser/components/customizableui/content/panelUI.inc.xul @@ -231,6 +231,7 @@ .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, #PanelUI-menu-button[badge-status="update-unsupported"] > .toolbarbutton-badge-stack > .toolbarbutton-badge { @@ -80,6 +81,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; @@ -90,6 +92,7 @@ } .panel-banner-item[notificationid="update-available"]::after, +.panel-banner-item[notificationid="update-downloading"]::after, .panel-banner-item[notificationid="update-manual"]::after, .panel-banner-item[notificationid="update-restart"]::after { background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center; diff --git a/browser/themes/shared/notification-icons.inc.css b/browser/themes/shared/notification-icons.inc.css index cf857d9de8157..6d461a89488c4 100644 --- a/browser/themes/shared/notification-icons.inc.css +++ b/browser/themes/shared/notification-icons.inc.css @@ -379,6 +379,7 @@ html|*#webRTC-previewVideo { /* UPDATE */ .popup-notification-icon[popupid="update-available"], +.popup-notification-icon[popupid="update-downloading"], .popup-notification-icon[popupid="update-manual"], .popup-notification-icon[popupid="update-restart"] { background: #74BF43 url(chrome://browser/skin/notification-icons/update.svg) no-repeat center; diff --git a/browser/themes/shared/toolbarbutton-icons.inc.css b/browser/themes/shared/toolbarbutton-icons.inc.css index c42d3c0c78ff1..1c6c03cf26da3 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 a5489b0a4e518..1d1c10ce2b00c 100644 --- a/toolkit/mozapps/update/UpdateListener.jsm +++ b/toolkit/mozapps/update/UpdateListener.jsm @@ -209,6 +209,15 @@ var UpdateListener = { } }, + 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": @@ -291,6 +300,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; @@ -307,6 +327,9 @@ var UpdateListener = { } this.handleUpdateAvailable(update, status); break; + case "update-downloading": + this.handleUpdateDownloading(status); + break; case "update-staged": case "update-downloaded": // An update check has found an update and downloaded / staged the diff --git a/toolkit/mozapps/update/UpdateService.jsm b/toolkit/mozapps/update/UpdateService.jsm index db95e0e91c125..282e1aecc5e85 100644 --- a/toolkit/mozapps/update/UpdateService.jsm +++ b/toolkit/mozapps/update/UpdateService.jsm @@ -66,6 +66,7 @@ const PREF_APP_UPDATE_IDLETIME = "app.update.idletime"; const PREF_APP_UPDATE_LOG = "app.update.log"; const PREF_APP_UPDATE_LOG_FILE = "app.update.log.file"; 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"; @@ -4458,11 +4459,13 @@ Downloader.prototype = { // retrying after a failed cancel is not an error, so we will set the // cancel promise to null in the failure case. this._cancelPromise = null; + this._notifyDownloadStatusObservers(); throw e; } } else if (this._request && this._request instanceof Ci.nsIRequest) { this._request.cancel(cancelError); } + this._notifyDownloadStatusObservers(); }, /** @@ -4677,6 +4680,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. */ @@ -4929,6 +4939,9 @@ Downloader.prototype = { .getService(Ci.nsIUpdateManager) .saveUpdates(); } + + this._notifyDownloadStatusObservers(); + return STATE_DOWNLOADING; }, @@ -5301,9 +5314,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. @@ -5471,6 +5491,7 @@ Downloader.prototype = { } this._request = null; + this._notifyDownloadStatusObservers(); if (state == STATE_DOWNLOAD_FAILED) { var allFailed = true; @@ -5600,9 +5621,16 @@ Downloader.prototype = { 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 } } else { this._patch.setProperty("applyStart", Math.floor(Date.now() / 1000)); -- GitLab