Bug 1534714 handle checkbox state when appmenu refreshed across windows r=Gijs
authorShane Caraveo <scaraveo@mozilla.com>
Thu, 14 Mar 2019 18:31:07 +0000
changeset 464705 46e6675abc338804c81392b90bf0aac5e5c09cdc
parent 464704 5f22cf5bfe6f0281522103ecf8d23c88dc37b5e6
child 464707 1735fe85436911fca7c7e5837e4cbc94040b8825
child 464708 f16aa91c7d4c0e49193f527feadb2a0b96215d08
push id35718
push usernerli@mozilla.com
push dateSun, 17 Mar 2019 21:37:26 +0000
treeherdermozilla-central@46e6675abc33 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1534714
milestone67.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 1534714 handle checkbox state when appmenu refreshed across windows r=Gijs This adds an onRefresh option for app menus so we can update custom controls in any opened window. In this case, we need to refresh the checkbox state in the addon-installed panel. We test this using the theme install test and verify both windows do not have the checkbox. Differential Revision: https://phabricator.services.mozilla.com/D23224
browser/components/customizableui/content/panelUI.js
browser/modules/ExtensionsUI.jsm
toolkit/mozapps/extensions/test/browser/browser_webapi_theme.js
toolkit/mozapps/extensions/test/browser/head.js
--- a/browser/components/customizableui/content/panelUI.js
+++ b/browser/components/customizableui/content/panelUI.js
@@ -693,17 +693,17 @@ const PanelUI = {
       notifications.filter(n => !n.dismissed && !n.options.badgeOnly);
 
     if (this.panel.state == "showing" || this.panel.state == "open") {
       // If the menu is already showing, then we need to dismiss all notifications
       // since we don't want their doorhangers competing for attention
       doorhangers.forEach(n => {
         n.dismissed = true;
         if (n.options.onDismissed) {
-          n.options.onDismissed();
+          n.options.onDismissed(window);
         }
       });
       this._hidePopup();
       this._clearBadge();
       if (!notifications[0].options.badgeOnly) {
         this._showBannerItem(notifications[0]);
       }
     } else if (doorhangers.length > 0) {
@@ -774,16 +774,19 @@ const PanelUI = {
       "PanelUI._onNotificationButtonEvent(event, 'secondarybuttoncommand');");
 
     if (notification.options.message) {
       let desc = this._formatDescriptionMessage(notification);
       popupnotification.setAttribute("label", desc.start);
       popupnotification.setAttribute("name", desc.name);
       popupnotification.setAttribute("endlabel", desc.end);
     }
+    if (notification.options.onRefresh) {
+      notification.options.onRefresh(window);
+    }
     if (notification.options.popupIconURL) {
       popupnotification.setAttribute("icon", notification.options.popupIconURL);
     }
 
     popupnotification.notification = notification;
     popupnotification.show();
   },
 
--- a/browser/modules/ExtensionsUI.jsm
+++ b/browser/modules/ExtensionsUI.jsm
@@ -437,21 +437,25 @@ var ExtensionsUI = {
     let brandBundle = window.document.getElementById("bundle_brand");
     let appName = brandBundle.getString("brandShortName");
     let bundle = window.gNavigatorBundle;
 
     let message = bundle.getFormattedString("addonPostInstall.message1",
                                             ["<>", appName]);
     return new Promise(resolve => {
       // Show or hide private permission ui based on the pref.
-      let checkbox = window.document.getElementById("addon-incognito-checkbox");
-      checkbox.checked = false;
-      checkbox.hidden = allowPrivateBrowsingByDefault || addon.type !== "extension";
+      function setCheckbox(win) {
+        let checkbox = win.document.getElementById("addon-incognito-checkbox");
+        checkbox.checked = false;
+        checkbox.hidden = allowPrivateBrowsingByDefault || addon.type !== "extension";
+      }
+      setCheckbox(window);
 
-      async function actionResolve() {
+      async function actionResolve(win) {
+        let checkbox = win.document.getElementById("addon-incognito-checkbox");
         if (checkbox.checked) {
           let perms = {permissions: ["internal:privateBrowsingAllowed"], origins: []};
           await ExtensionPermissions.add(addon.id, perms);
           AMTelemetry.recordActionEvent({
             addon,
             object: "doorhanger",
             action: "privateBrowsingAllowed",
             view: "postInstall",
@@ -474,19 +478,20 @@ var ExtensionsUI = {
 
       let icon = addon.isWebExtension ?
                  AddonManager.getPreferredIconURL(addon, 32, window) || DEFAULT_EXTENSION_ICON :
                  "chrome://browser/skin/addons/addon-install-installed.svg";
       let options = {
         name: addon.name,
         message,
         popupIconURL: icon,
-        onDismissed: () => {
+        onRefresh: setCheckbox,
+        onDismissed: (win) => {
           AppMenuNotifications.removeNotification("addon-installed");
-          actionResolve();
+          actionResolve(win);
         },
       };
       AppMenuNotifications.showNotification("addon-installed", action, null, options);
     });
   },
 
   promisePrivateBrowsingNotification(window) {
     return new Promise(resolve => {
--- a/toolkit/mozapps/extensions/test/browser/browser_webapi_theme.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_webapi_theme.js
@@ -16,27 +16,33 @@ add_task(async function test_theme_insta
     function observer(subject, topic, data) {
       updates.push(data);
     }
     Services.obs.addObserver(observer, "lightweight-theme-styling-update");
     registerCleanupFunction(() => {
       Services.obs.removeObserver(observer, "lightweight-theme-styling-update");
     });
 
-    let promptPromise = acceptAppMenuNotificationWhenShown("addon-installed", "theme");
 
+    let prompt1 = waitAppMenuNotificationShown("addon-installed", "theme", false);
     let installPromise = ContentTask.spawn(browser, URL, async (url) => {
       let install = await content.navigator.mozAddonManager.createInstall({url});
       return install.install();
     });
+    await prompt1;
 
-    await promptPromise;
+    // Open a new window and test the app menu panel from there.  This verifies the
+    // incognito checkbox as well as finishing install in this case.
+    let newWin = await BrowserTestUtils.openNewBrowserWindow();
+    await waitAppMenuNotificationShown("addon-installed", "theme", true, newWin);
     await installPromise;
     ok(true, "Theme install completed");
 
+    await BrowserTestUtils.closeWindow(newWin);
+
     Assert.equal(updates.length, 1, "Got a single theme update");
     let parsed = JSON.parse(updates[0]);
     ok(parsed.theme.headerURL.endsWith("/testImage.png"),
        "Theme update has the expected headerURL");
     is(parsed.theme.id, "theme@tests.mozilla.org", "Theme update includes the theme ID");
     is(parsed.theme.version, "1.0", "Theme update includes the theme's version");
 
     let addon = await AddonManager.getAddonByID(parsed.theme.id);
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -1394,44 +1394,58 @@ function promisePopupNotificationShown(n
 
       PopupNotifications.panel.removeEventListener("popupshown", popupshown);
       resolve(PopupNotifications.panel.firstChild);
     }
     PopupNotifications.panel.addEventListener("popupshown", popupshown);
   });
 }
 
-function acceptAppMenuNotificationWhenShown(id, type) {
+function waitAppMenuNotificationShown(id, type, accept = false, win = window) {
   const {AppMenuNotifications} = ChromeUtils.import("resource://gre/modules/AppMenuNotifications.jsm");
   return new Promise(resolve => {
+    let {document, PanelUI} = win;
+
     function popupshown() {
       let notification = AppMenuNotifications.activeNotification;
       if (!notification) { return; }
 
       is(notification.id, id, `${id} notification shown`);
       ok(PanelUI.isNotificationPanelOpen, "notification panel open");
 
       PanelUI.notificationPanel.removeEventListener("popupshown", popupshown);
 
       if (id == "addon-installed" && type) {
         let hidden = type !== "extension" ||
                      Services.prefs.getBoolPref("extensions.allowPrivateBrowsingByDefault", true);
         let checkbox = document.getElementById("addon-incognito-checkbox");
         is(checkbox.hidden, hidden, "checkbox visibility is correct");
       }
-      let popupnotificationID = PanelUI._getPopupId(notification);
-      let popupnotification = document.getElementById(popupnotificationID);
-      popupnotification.button.click();
+      if (accept) {
+        let popupnotificationID = PanelUI._getPopupId(notification);
+        let popupnotification = document.getElementById(popupnotificationID);
+        popupnotification.button.click();
+      }
 
       resolve();
     }
+    // If it's already open just run the test.
+    let notification = AppMenuNotifications.activeNotification;
+    if (notification && PanelUI.isNotificationPanelOpen) {
+      popupshown();
+      return;
+    }
     PanelUI.notificationPanel.addEventListener("popupshown", popupshown);
   });
 }
 
+function acceptAppMenuNotificationWhenShown(id, type) {
+  return waitAppMenuNotificationShown(id, type, true);
+}
+
 function assertTelemetryMatches(events, {filterMethods} = {}) {
   let snapshot = Services.telemetry.snapshotEvents(
     Ci.nsITelemetry.DATASET_RELEASE_CHANNEL_OPTIN, true);
 
   if (events.length == 0) {
     ok(!snapshot.parent || snapshot.parent.length == 0, "There are no telemetry events");
     return;
   }