Bug 1521427 - Display the doorhanger notification for unsupported type update notifications. r=bytesized,flod,zbraniecki
authorRobert Strong <robert.bugzilla@gmail.com>
Tue, 07 May 2019 17:59:21 +0000
changeset 531756 6c0d9bd9f398bcff4da0dc15a49a87d060dff9be
parent 531755 fbdbe72f12e42fc3937c89768f24a50ff709f1c2
child 531757 32a3534e33fd7b59dd6759cc605c78b4663f16d5
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbytesized, flod, zbraniecki
bugs1521427
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1521427 - Display the doorhanger notification for unsupported type update notifications. r=bytesized,flod,zbraniecki The unsupported doorhanger will persist the menu item across application restarts until an update has been found. Differential Revision: https://phabricator.services.mozilla.com/D29927
browser/components/customizableui/content/panelUI.inc.xul
browser/locales/en-US/browser/appMenuNotifications.ftl
browser/locales/en-US/chrome/browser/browser.dtd
browser/themes/shared/customizableui/panelUI.inc.css
browser/themes/shared/notification-icons.inc.css
toolkit/components/telemetry/Histograms.json
toolkit/mozapps/update/UpdateListener.jsm
toolkit/mozapps/update/UpdateService.jsm
toolkit/mozapps/update/tests/browser/browser.ini
toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_unsupported.js
toolkit/mozapps/update/tests/data/shared.js
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -125,16 +125,30 @@
                      buttonhighlight="true"
                      hidden="true">
     <popupnotificationcontent id="update-manual-notification-content" orient="vertical">
       <description id="update-manual-description" data-lazy-l10n-id="appmenu-update-manual-message"></description>
       <label id="update-manual-whats-new" is="text-link"  data-lazy-l10n-id="appmenu-update-whats-new"/>
     </popupnotificationcontent>
   </popupnotification>
 
+  <popupnotification id="appMenu-update-unsupported-notification"
+                     popupid="update-unsupported"
+                     data-lazy-l10n-id="appmenu-update-unsupported"
+                     data-l10n-attrs="buttonlabel, buttonaccesskey, secondarybuttonlabel, secondarybuttonaccesskey"
+                     closebuttonhidden="true"
+                     dropmarkerhidden="true"
+                     checkboxhidden="true"
+                     buttonhighlight="true"
+                     hidden="true">
+    <popupnotificationcontent id="update-unsupported-notification-content" orient="vertical">
+      <description id="update-unsupported-description" data-lazy-l10n-id="appmenu-update-unsupported-message"></description>
+    </popupnotificationcontent>
+  </popupnotification>
+
   <popupnotification id="appMenu-update-restart-notification"
                      popupid="update-restart"
                      data-lazy-l10n-id="appmenu-update-restart"
                      data-l10n-attrs="buttonlabel, buttonaccesskey, secondarybuttonlabel, secondarybuttonaccesskey"
                      closebuttonhidden="true"
                      dropmarkerhidden="true"
                      checkboxhidden="true"
                      buttonhighlight="true"
@@ -212,16 +226,17 @@
                   viewCacheId="appMenu-viewCache">
     <panelview id="appMenu-mainView" class="PanelUI-subView"
                descriptionheightworkaround="true">
       <vbox class="panel-subview-body">
         <vbox id="appMenu-addon-banners"/>
         <toolbarbutton class="panel-banner-item"
                        label-update-available="&updateAvailable.panelUI.label;"
                        label-update-manual="&updateManual.panelUI.label;"
+                       label-update-unsupported="&updateUnsupported.panelUI.label;"
                        label-update-restart="&updateRestart.panelUI.label2;"
                        oncommand="PanelUI._onBannerItemSelected(event)"
                        wrap="true"
                        hidden="true"/>
         <toolbaritem id="appMenu-fxa-container" class="toolbaritem-combined-buttons sync-ui-item">
           <hbox id="appMenu-fxa-status"
                 flex="1"
                 defaultlabel="&fxaSignIn.label;"
--- a/browser/locales/en-US/browser/appMenuNotifications.ftl
+++ b/browser/locales/en-US/browser/appMenuNotifications.ftl
@@ -13,16 +13,23 @@ appmenu-update-manual =
     .label = { -brand-shorter-name } can’t update to the latest version.
     .buttonlabel = Download { -brand-shorter-name }
     .buttonaccesskey = D
     .secondarybuttonlabel = Not Now
     .secondarybuttonaccesskey = N
 appmenu-update-manual-message = Download a fresh copy of { -brand-shorter-name } and we’ll help you to install it.
 appmenu-update-whats-new =
     .value = See what’s new.
+appmenu-update-unsupported =
+    .label = { -brand-shorter-name } is unable to update to the latest version.
+    .buttonlabel = Learn more
+    .buttonaccesskey = L
+    .secondarybuttonlabel = Close
+    .secondarybuttonaccesskey = C
+appmenu-update-unsupported-message = The latest version of { -brand-shorter-name } is not supported on your system.
 appmenu-update-restart =
     .label = Restart to update { -brand-shorter-name }.
     .buttonlabel = Restart and Restore
     .buttonaccesskey = R
     .secondarybuttonlabel = Not Now
     .secondarybuttonaccesskey = N
 appmenu-update-restart-message = After a quick restart, { -brand-shorter-name } will restore all your open tabs and windows that are not in Private Browsing mode.
 appmenu-addon-private-browsing-installed =
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -919,16 +919,17 @@ you can use these alternative items. Oth
 <!ENTITY panicButton.thankyou.msg2                "Safe browsing!">
 <!ENTITY panicButton.thankyou.buttonlabel         "Thanks!">
 
 <!ENTITY emeLearnMoreContextMenu.label            "Learn more about DRM…">
 <!ENTITY emeLearnMoreContextMenu.accesskey        "D">
 
 <!ENTITY updateAvailable.panelUI.label "Download &brandShorterName; update">
 <!ENTITY updateManual.panelUI.label "Download a fresh copy of &brandShorterName;">
+<!ENTITY updateUnsupported.panelUI.label "You cannot perform further updates">
 <!ENTITY updateRestart.panelUI.label2 "Restart to update &brandShorterName;">
 
 <!ENTITY newTabControlled.header.message "Your New Tab has changed.">
 <!ENTITY newTabControlled.keepButton.label "Keep Changes">
 <!ENTITY newTabControlled.keepButton.accesskey "K">
 <!ENTITY newTabControlled.disableButton.label "Disable Extension">
 <!ENTITY newTabControlled.disableButton.accesskey "D">
 
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -63,29 +63,46 @@
 
 #PanelUI-menu-button[badge-status="extension-new-tab"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
 #PanelUI-menu-button[badge-status="download-success"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
   display: none;
 }
 
 #PanelUI-menu-button[badge-status="update-available"] > .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;
+#PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
+#PanelUI-menu-button[badge-status="update-unsupported"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
   border-radius: 50%;
   box-shadow: none;
   /* "!important" is necessary to override the rule in toolbarbutton.css */
   margin: -7px 0 0 !important;
   margin-inline-end: -4px !important;
   min-width: 12px;
   min-height: 12px;
 }
 
-.panel-banner-item[notificationid^=update]::after {
+#PanelUI-menu-button[badge-status="update-available"] > .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;
+}
+
+#PanelUI-menu-button[badge-status="update-unsupported"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
+  background: #FFE900 url(chrome://browser/skin/update-badge.svg) no-repeat center;
+}
+
+.panel-banner-item[notificationid="update-available"]::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;
+  border-radius: 50%;
+}
+
+.panel-banner-item[notificationid="update-unsupported"]::after {
+  background: #FFE900 url(chrome://browser/skin/update-badge.svg) no-repeat center;
   border-radius: 50%;
 }
 
 .panel-banner-item[notificationid^=update] {
   list-style-image: url(chrome://branding/content/icon16.png);
 }
 
 #PanelUI-menu-button[badge-status="addon-alert"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
@@ -935,27 +952,51 @@ panelmultiview[mainViewId="PanelUI-fxa"]
 }
 
 .panel-banner-item:not([disabled]):hover:active {
   background-color: hsl(96,65%,75%);
 }
 
 :root[lwt-popup-brighttext] .panel-banner-item:not([disabled]) {
   background-color: rgba(48,230,11,.1);
-  color: #F9F9FA !important;
+  color: @appmenuWarningColorBrightText@ !important;
 }
 
 :root[lwt-popup-brighttext] .panel-banner-item:not([disabled]):hover {
   background-color: rgba(48,230,11,.15);
 }
 
 :root[lwt-popup-brighttext] .panel-banner-item:not([disabled]):active {
   background-color: rgba(48,230,11,.2);
 }
 
+.panel-banner-item[notificationid="update-unsupported"] {
+  background-color: @appmenuWarningBackgroundColor@;
+}
+
+.panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover {
+  background-color: @appmenuWarningBackgroundColorHover@;
+}
+
+.panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover:active {
+  background-color: @appmenuWarningBackgroundColorActive@;
+}
+
+:root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]) {
+  background-color: @appmenuWarningBackgroundColorBrightText@;
+}
+
+:root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]):hover {
+  background-color: @appmenuWarningBackgroundColorHoverBrightText@;
+}
+
+:root[lwt-popup-brighttext] .panel-banner-item[notificationid="update-unsupported"]:not([disabled]):active {
+  background-color: @appmenuWarningBackgroundColorActiveBrightText@;
+}
+
 #customization-palette .toolbarbutton-multiline-text,
 #customization-palette .toolbarbutton-text {
   display: none;
 }
 
 .subview-subheader,
 panelview .toolbarbutton-1,
 .subviewbutton,
--- a/browser/themes/shared/notification-icons.inc.css
+++ b/browser/themes/shared/notification-icons.inc.css
@@ -376,8 +376,13 @@ html|*#webRTC-previewVideo {
 
 /* UPDATE */
 .popup-notification-icon[popupid="update-available"],
 .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;
   border-radius: 50%;
 }
+
+.popup-notification-icon[popupid="update-unsupported"] {
+  background: #FFE900 url(chrome://browser/skin/notification-icons/update.svg) no-repeat center;
+  border-radius: 50%;
+}
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -5989,57 +5989,57 @@
   "UPDATE_NOTIFICATION_SHOWN": {
     "record_in_processes": ["main"],
     "alert_emails": ["application-update-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "categorical",
     "bug_numbers": [893505],
     "releaseChannelCollection": "opt-out",
     "description": "Update: the application update doorhanger type that was displayed.",
-    "labels": ["restart", "available", "manual"]
+    "labels": ["restart", "available", "manual", "unsupported"]
   },
   "UPDATE_NOTIFICATION_BADGE_SHOWN": {
     "record_in_processes": ["main"],
     "alert_emails": ["application-update-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "categorical",
     "bug_numbers": [893505, 1365204],
     "releaseChannelCollection": "opt-out",
     "description": "Update: the application update badge type that was displayed.",
-    "labels": ["restart", "available", "manual"]
+    "labels": ["restart", "available", "manual", "unsupported"]
   },
   "UPDATE_NOTIFICATION_DISMISSED": {
     "record_in_processes": ["main"],
     "alert_emails": ["application-update-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "categorical",
     "bug_numbers": [893505],
     "releaseChannelCollection": "opt-out",
     "description": "Update: the dismiss action was executed for this application update doorhanger type.",
-    "labels": ["restart", "available", "manual"]
+    "labels": ["restart", "available", "manual", "unsupported"]
   },
   "UPDATE_NOTIFICATION_MAIN_ACTION_DOORHANGER": {
     "record_in_processes": ["main"],
     "alert_emails": ["application-update-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "categorical",
     "bug_numbers": [893505],
     "releaseChannelCollection": "opt-out",
     "description": "Update: the main update action was initiated for this application update doorhanger type.",
-    "labels": ["restart", "available", "manual"]
+    "labels": ["restart", "available", "manual", "unsupported"]
   },
   "UPDATE_NOTIFICATION_MAIN_ACTION_MENU": {
     "record_in_processes": ["main"],
     "alert_emails": ["application-update-telemetry-alerts@mozilla.com"],
     "expires_in_version": "never",
     "kind": "categorical",
     "bug_numbers": [893505],
     "releaseChannelCollection": "opt-out",
     "description": "Update: the update action was initiated from the PanelUI application update menu item.",
-    "labels": ["restart", "available", "manual"]
+    "labels": ["restart", "available", "manual", "unsupported"]
   },
   "UPDATE_CAN_USE_BITS_EXTERNAL": {
     "record_in_processes": ["main"],
     "alert_emails": ["application-update-telemetry-alerts@mozilla.com", "rstrong@mozilla.com"],
     "expires_in_version": "never",
     "kind": "categorical",
     "labels": [
       "CanUseBits",
--- a/toolkit/mozapps/update/UpdateListener.jsm
+++ b/toolkit/mozapps/update/UpdateListener.jsm
@@ -7,29 +7,38 @@
 var EXPORTED_SYMBOLS = ["UpdateListener"];
 
 const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
 const {clearTimeout, setTimeout} = ChromeUtils.import("resource://gre/modules/Timer.jsm");
 
 ChromeUtils.defineModuleGetter(this, "AppMenuNotifications",
                                "resource://gre/modules/AppMenuNotifications.jsm");
 
+const PREF_APP_UPDATE_UNSUPPORTED_URL = "app.update.unsupported.url";
+
 // Setup the hamburger button badges for updates, if enabled.
 var UpdateListener = {
   timeouts: [],
 
   get enabled() {
     return Services.prefs.getBoolPref("app.update.doorhanger", false);
   },
 
   get badgeWaitTime() {
     return Services.prefs.getIntPref("app.update.badgeWaitTime", 4 * 24 * 3600); // 4 days
   },
 
   init() {
+    // Persist the unsupported notification across sessions. If at some point an
+    // update is found this pref is cleared and the notifcation won't be shown.
+    let url = Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null);
+    if (url) {
+      this.showUpdateNotification("unsupported", true, true,
+                                  win => this.openUnsupportedUpdateUrl(win, url));
+    }
   },
 
   uninit() {
     this.reset();
   },
 
   reset() {
     AppMenuNotifications.removeNotification(/^update-/);
@@ -70,16 +79,20 @@ var UpdateListener = {
     }
   },
 
   openManualUpdateUrl(win) {
     let manualUpdateUrl = Services.urlFormatter.formatURLPref("app.update.url.manual");
     win.openURL(manualUpdateUrl);
   },
 
+  openUnsupportedUpdateUrl(win, detailsURL) {
+    win.openURL(detailsURL);
+  },
+
   showUpdateNotification(type, mainActionDismiss, dismissed, mainAction, beforeShowDoorhanger) {
     let action = {
       callback(win, fromDoorhanger) {
         if (fromDoorhanger) {
           Services.telemetry.getHistogramById("UPDATE_NOTIFICATION_MAIN_ACTION_DOORHANGER").add(type);
         } else {
           Services.telemetry.getHistogramById("UPDATE_NOTIFICATION_MAIN_ACTION_MENU").add(type);
         }
@@ -121,29 +134,43 @@ var UpdateListener = {
   showManualUpdateNotification(update, dismissed) {
     this.showUpdateNotification("manual",
                                 false,
                                 dismissed,
                                 win => this.openManualUpdateUrl(win),
                                 doc => this.replaceReleaseNotes(doc, update, "updateManualWhatsNew"));
   },
 
+  showUnsupportedUpdateNotification(update, dismissed) {
+    if (!update || !update.detailsURL) {
+      Cu.reportError("The update for an unsupported notification must have a " +
+                     "detailsURL attribute.");
+      return;
+    }
+    let url = update.detailsURL;
+    if (url != Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null)) {
+      Services.prefs.setCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, url);
+      this.showUpdateNotification("unsupported", true, dismissed,
+                                  win => this.openUnsupportedUpdateUrl(win, url));
+    }
+  },
+
   handleUpdateError(update, status) {
     switch (status) {
       case "download-attempt-failed":
         this.clearCallbacks();
         this.showUpdateAvailableNotification(update, false);
         break;
       case "download-attempts-exceeded":
         this.clearCallbacks();
         this.showManualUpdateNotification(update, false);
         break;
       case "elevation-attempt-failed":
         this.clearCallbacks();
-        this.showRestartNotification(update, false);
+        this.showRestartNotification(false);
         break;
       case "elevation-attempts-exceeded":
         this.clearCallbacks();
         this.showManualUpdateNotification(update, false);
         break;
       case "check-attempts-exceeded":
       case "unknown":
       case "bad-perms":
@@ -196,32 +223,44 @@ var UpdateListener = {
         // false, then show an update available doorhanger.
         this.clearCallbacks();
         this.showUpdateAvailableNotification(update, false);
         break;
       case "cant-apply":
         this.clearCallbacks();
         this.showManualUpdateNotification(update, false);
         break;
+      case "unsupported":
+        this.clearCallbacks();
+        this.showUnsupportedUpdateNotification(update, false);
+        break;
     }
   },
 
   observe(subject, topic, status) {
     if (!this.enabled) {
       return;
     }
 
     let update = subject && subject.QueryInterface(Ci.nsIUpdate);
 
     switch (topic) {
       case "update-available":
+        if (status != "unsupported") {
+          // An update check has found an update so clear the unsupported pref
+          // in case it is set.
+          Services.prefs.clearUserPref(PREF_APP_UPDATE_UNSUPPORTED_URL);
+        }
         this.handleUpdateAvailable(update, status);
         break;
       case "update-staged":
       case "update-downloaded":
+        // An update check has found an update and downloaded / staged the
+        // update so clear the unsupported pref in case it is set.
+        Services.prefs.clearUserPref(PREF_APP_UPDATE_UNSUPPORTED_URL);
         this.handleUpdateStagedOrDownloaded(update, status);
         break;
       case "update-error":
         this.handleUpdateError(update, status);
         break;
     }
   },
 };
--- a/toolkit/mozapps/update/UpdateService.jsm
+++ b/toolkit/mozapps/update/UpdateService.jsm
@@ -2613,17 +2613,17 @@ UpdateService.prototype = {
           "this system. Notifying observers. topic: update-available, " +
           "status: unsupported");
       if (!Services.prefs.getBoolPref(PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED, false)) {
         LOG("UpdateService:_selectAndInstallUpdate - notifying that the " +
             "update is not supported for this system");
         this._showPrompt(update);
       }
 
-      Services.obs.notifyObservers(null, "update-available", "unsupported");
+      Services.obs.notifyObservers(update, "update-available", "unsupported");
       AUSTLMY.pingCheckCode(this._pingSuffix, AUSTLMY.CHK_UNSUPPORTED);
       return;
     }
 
     if (!getCanApplyUpdates()) {
       LOG("UpdateService:_selectAndInstallUpdate - the user is unable to " +
           "apply updates... prompting. Notifying observers. " +
           "topic: update-available, status: cant-apply");
--- a/toolkit/mozapps/update/tests/browser/browser.ini
+++ b/toolkit/mozapps/update/tests/browser/browser.ini
@@ -56,16 +56,17 @@ reason = Windows only feature.
 skip-if = os != 'win'
 reason = Tests that update config is properly written to file, which is a Windows-only feature
 
 # Doorhanger Application Update Tests
 [browser_doorhanger_bc_check_cantApply.js]
 skip-if = os != 'win'
 reason = test must be able to prevent file deletion.
 [browser_doorhanger_bc_check_malformedXML.js]
+[browser_doorhanger_bc_check_unsupported.js]
 [browser_doorhanger_bc_downloaded.js]
 [browser_doorhanger_bc_downloaded_staged.js]
 [browser_doorhanger_bc_downloadAutoFailures.js]
 [browser_doorhanger_bc_downloadAutoFailures_bgWin.js]
 [browser_doorhanger_bc_downloadOptIn.js]
 [browser_doorhanger_bc_downloadOptIn_bgWin.js]
 [browser_doorhanger_bc_downloadOptIn_staging.js]
 [browser_doorhanger_bc_patch_completeBadSize.js]
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/tests/browser/browser_doorhanger_bc_check_unsupported.js
@@ -0,0 +1,57 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Test for doorhanger background check for updates
+// with an unsupported update.
+add_task(async function doorhanger_bc_check_unsupported() {
+  let updateParams = "&unsupported=1";
+  await runDoorhangerUpdateTest(updateParams, 1, [
+    {
+      notificationId: "update-unsupported",
+      button: "button",
+      pageURLs: {manual: gDetailsURL},
+    },
+    async function doorhanger_unsupported_persist() {
+      is(PanelUI.notificationPanel.state, "closed",
+         "The window's doorhanger is closed.");
+      ok(PanelUI.menuButton.hasAttribute("badge-status"),
+         "The window has a badge.");
+      is(PanelUI.menuButton.getAttribute("badge-status"), "update-unsupported",
+         "The correct badge is showing for the background window");
+
+      // Test persistence of the badge when the client has restarted by
+      // resetting the UpdateListener.
+      UpdateListener.reset();
+      is(PanelUI.notificationPanel.state, "closed",
+         "The window's doorhanger is closed.");
+      ok(!PanelUI.menuButton.hasAttribute("badge-status"),
+         "The window does not have a badge.");
+      UpdateListener.init();
+      is(PanelUI.notificationPanel.state, "closed",
+         "The window's doorhanger is closed.");
+      ok(PanelUI.menuButton.hasAttribute("badge-status"),
+         "The window has a badge.");
+      is(PanelUI.menuButton.getAttribute("badge-status"), "update-unsupported",
+         "The correct badge is showing for the background window.");
+    },
+ ]);
+
+  updateParams = "&invalidCompleteSize=1&promptWaitTime=0";
+  await runDoorhangerUpdateTest(updateParams, 1, [
+    {
+      notificationId: "update-restart",
+      button: "secondaryButton",
+      checkActiveUpdate: {state: STATE_PENDING},
+    },
+    async function doorhanger_unsupported_removed() {
+      // Test that finding an update removes the app.update.unsupported.url
+      // preference.
+      let unsupportedURL =
+        Services.prefs.getCharPref(PREF_APP_UPDATE_UNSUPPORTED_URL, null);
+      ok(!unsupportedURL,
+         "The " + PREF_APP_UPDATE_UNSUPPORTED_URL + " preference was removed.");
+    },
+ ]);
+});
--- a/toolkit/mozapps/update/tests/data/shared.js
+++ b/toolkit/mozapps/update/tests/data/shared.js
@@ -34,16 +34,17 @@ const PREF_APP_UPDATE_LASTUPDATETIME    
 const PREF_APP_UPDATE_LOG                  = "app.update.log";
 const PREF_APP_UPDATE_NOTIFIEDUNSUPPORTED  = "app.update.notifiedUnsupported";
 const PREF_APP_UPDATE_PROMPTWAITTIME       = "app.update.promptWaitTime";
 const PREF_APP_UPDATE_RETRYTIMEOUT         = "app.update.socket.retryTimeout";
 const PREF_APP_UPDATE_SERVICE_ENABLED      = "app.update.service.enabled";
 const PREF_APP_UPDATE_SILENT               = "app.update.silent";
 const PREF_APP_UPDATE_SOCKET_MAXERRORS     = "app.update.socket.maxErrors";
 const PREF_APP_UPDATE_STAGING_ENABLED      = "app.update.staging.enabled";
+const PREF_APP_UPDATE_UNSUPPORTED_URL      = "app.update.unsupported.url";
 const PREF_APP_UPDATE_URL                  = "app.update.url";
 const PREF_APP_UPDATE_URL_DETAILS          = "app.update.url.details";
 const PREF_APP_UPDATE_URL_MANUAL           = "app.update.url.manual";
 
 const PREFBRANCH_APP_PARTNER         = "app.partner.";
 const PREF_DISTRIBUTION_ID           = "distribution.id";
 const PREF_DISTRIBUTION_VERSION      = "distribution.version";