Bug 1547573 - fix sorting in and add test for themes dropdown in customize mode, r=jaws
authorGijs Kruitbosch <gijskruitbosch@gmail.com>
Thu, 09 May 2019 18:22:53 +0000
changeset 535211 d87eef05591be2cb8b211a2ca26ef41e7b042f99
parent 535210 17c76d081a9a78e20e52dbfe7b89f072e110c471
child 535212 dcf3a023d7d08907c6033a8c61c601a6b06e620a
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjaws
bugs1547573
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 1547573 - fix sorting in and add test for themes dropdown in customize mode, r=jaws Differential Revision: https://phabricator.services.mozilla.com/D30392
browser/components/customizableui/CustomizeMode.jsm
browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -172,17 +172,17 @@ CustomizeMode.prototype = {
       this.enter();
     }
   },
 
   async _updateThemeButtonIcon() {
     let lwthemeButton = this.$("customization-lwtheme-button");
     let lwthemeIcon = lwthemeButton.icon;
     let theme = (await AddonManager.getAddonsByTypes(["theme"])).find(addon => addon.isActive);
-    lwthemeIcon.style.backgroundImage = theme ? "url(" + theme.iconURL + ")" : "";
+    lwthemeIcon.style.backgroundImage = (theme && theme.iconURL) ? "url(" + theme.iconURL + ")" : "";
   },
 
   setTab(aTab) {
     if (gTab == aTab) {
       return;
     }
 
     if (gTab) {
@@ -1336,17 +1336,17 @@ CustomizeMode.prototype = {
     };
 
     let doc = this.window.document;
 
     function buildToolbarButton(aTheme) {
       let tbb = doc.createXULElement("toolbarbutton");
       tbb.theme = aTheme;
       tbb.setAttribute("label", aTheme.name);
-      tbb.setAttribute("image", aTheme.iconURL);
+      tbb.setAttribute("image", aTheme.iconURL || "chrome://mozapps/skin/extensions/themeGeneric.svg");
       if (aTheme.description)
         tbb.setAttribute("tooltiptext", aTheme.description);
       tbb.setAttribute("tabindex", "0");
       tbb.classList.add("customization-lwtheme-menu-theme");
       let isActive = aTheme.isActive;
       tbb.setAttribute("aria-checked", isActive);
       tbb.setAttribute("role", "menuitemradio");
       if (isActive) {
@@ -1359,18 +1359,24 @@ CustomizeMode.prototype = {
     let themes = await AddonManager.getAddonsByTypes(["theme"]);
     let currentTheme = themes.find(theme => theme.isActive);
 
     // Move the current theme (if any) and the light/dark themes to the start:
     let importantThemes = new Set([DEFAULT_THEME_ID, LIGHT_THEME_ID, DARK_THEME_ID]);
     if (currentTheme) {
       importantThemes.add(currentTheme.id);
     }
+    let importantList = [];
+    for (let importantTheme of importantThemes) {
+      importantList.push(...themes.splice(themes.findIndex(theme => theme.id == importantTheme), 1));
+    }
 
-    themes.sort((a, b) => importantThemes.has(a.id) - importantThemes.has(b.id));
+    // Sort the remainder alphabetically:
+    themes.sort((a, b) => a.name.localeCompare(b.name));
+    themes = importantList.concat(themes);
 
     if (themes.length > MAX_THEME_COUNT)
       themes.length = MAX_THEME_COUNT;
 
     let footer = doc.getElementById("customization-lwtheme-menu-footer");
     let panel = footer.parentNode;
     for (let theme of themes) {
       let button = buildToolbarButton(theme);
@@ -1513,16 +1519,20 @@ CustomizeMode.prototype = {
         if (this._canDrawInTitlebar()) {
           this._updateTitlebarCheckbox();
           this._updateDragSpaceCheckbox();
         }
         break;
     }
   },
 
+  async onInstalled(addon) {
+    await this.onEnabled(addon);
+  },
+
   async onEnabled(addon) {
     if (addon.type != "theme") {
       return;
     }
 
     await this._updateThemeButtonIcon();
     if (this._nextThemeChangeUserTriggered) {
       this._onUIChange();
--- a/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
+++ b/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
@@ -2,16 +2,34 @@
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const DEFAULT_THEME_ID = "default-theme@mozilla.org";
 const LIGHT_THEME_ID = "firefox-compact-light@mozilla.org";
 const DARK_THEME_ID = "firefox-compact-dark@mozilla.org";
+const MAX_THEME_COUNT = 6; // Not exposed from CustomizeMode.jsm
+
+async function installTheme(id) {
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      applications: {gecko: {id}},
+      manifest_version: 2,
+      name: "Theme " + id,
+      description: "wow. such theme.",
+      author: "Pixel Pusher",
+      version: "1",
+      theme: {},
+    },
+    useAddonManager: "temporary",
+  });
+  await extension.startup();
+  return extension;
+}
 
 add_task(async function() {
   await startCustomizing();
   // Check restore defaults button is disabled.
   ok(document.getElementById("customization-reset-button").disabled,
      "Reset button should start out disabled");
 
   let themesButton = document.getElementById("customization-lwtheme-button");
@@ -76,16 +94,38 @@ add_task(async function() {
   info("Clicked on themes button a third time");
   await popupShownPromise;
 
   let activeThemes = popup.querySelectorAll("toolbarbutton.customization-lwtheme-menu-theme[active]");
   is(activeThemes.length, 1, "Exactly 1 theme should be selected");
   if (activeThemes.length > 0) {
     is(activeThemes[0].theme.id, LIGHT_THEME_ID, "Light theme should be selected");
   }
+  popup.hidePopup();
+
+  // Install 5 themes:
+  let addons = [];
+  for (let n = 1; n <= 5; n++) {
+    addons.push(await installTheme("my-theme-" + n + "@example.com"));
+  }
+  addons = await Promise.all(addons);
+
+  ok(!themesButtonIcon.style.backgroundImage,
+     `Button should show fallback theme thumbnail - was: "${themesButtonIcon.style.backgroundImage}"`);
+
+  popupShownPromise = popupShown(popup);
+  EventUtils.synthesizeMouseAtCenter(themesButton, {});
+  info("Clicked on themes button a fourth time");
+  await popupShownPromise;
+
+  activeThemes = popup.querySelectorAll("toolbarbutton.customization-lwtheme-menu-theme[active]");
+  is(activeThemes.length, 1, "Exactly 1 theme should be selected");
+  if (activeThemes.length > 0) {
+    is(activeThemes[0].theme.id, "my-theme-5@example.com", "Last installed theme should be selected");
+  }
 
   let firstLWTheme = footer.previousElementSibling;
   let firstLWThemeId = firstLWTheme.theme.id;
   themeChangedPromise = promiseObserverNotified("lightweight-theme-styling-update");
   firstLWTheme.doCommand();
   info("Clicked on first theme");
   await themeChangedPromise;
 
@@ -104,51 +144,53 @@ add_task(async function() {
 
   is(header.nextElementSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
   let themeCount = 0;
   let iterNode = header;
   while (iterNode.nextElementSibling && iterNode.nextElementSibling.theme) {
     themeCount++;
     iterNode = iterNode.nextElementSibling;
   }
-  is(themeCount, 3,
-     "There should be four themes in the 'My Themes' section");
+  is(themeCount, MAX_THEME_COUNT,
+     "There should be the max number of themes in the 'My Themes' section");
 
   let defaultTheme = header.nextElementSibling;
   defaultTheme.doCommand();
   await new Promise(SimpleTest.executeSoon);
 
   // ensure current theme isn't set to "Default"
   popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
-  info("Clicked on themes button a fourth time");
+  info("Clicked on themes button a sixth time");
   await popupShownPromise;
 
   // check that "Restore Defaults" button resets theme
   await gCustomizeMode.reset();
 
   defaultTheme = await AddonManager.getAddonByID(DEFAULT_THEME_ID);
   is(defaultTheme.isActive, true, "Current theme reset to default");
 
   await endCustomizing();
   await startCustomizing();
   popupShownPromise = popupShown(popup);
   EventUtils.synthesizeMouseAtCenter(themesButton, {});
-  info("Clicked on themes button a fifth time");
+  info("Clicked on themes button a seventh time");
   await popupShownPromise;
   header = document.getElementById("customization-lwtheme-menu-header");
   is(header.hidden, false, "Header should never be hidden");
   let themeNode = header.nextElementSibling;
   is(themeNode.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
   is(themeNode.hidden, false, "The default theme should never be hidden");
 
   themeNode = themeNode.nextElementSibling;
   is(themeNode.theme.id, LIGHT_THEME_ID, "The second theme should be the Light theme");
   is(themeNode.hidden, false, "The light theme should never be hidden");
 
   themeNode = themeNode.nextElementSibling;
   is(themeNode.theme.id, DARK_THEME_ID, "The third theme should be the Dark theme");
   is(themeNode.hidden, false, "The dark theme should never be hidden");
+
+  await Promise.all(addons.map(a => a.unload()));
 });
 
 add_task(async function asyncCleanup() {
   await endCustomizing();
 });