Backed out 4 changesets (bug 1570792, bug 1593358, bug 1575905) for causing bug 1593402 to near permafail. CLOSED TREE
authorCosmin Sabou <csabou@mozilla.com>
Sat, 23 Nov 2019 01:57:15 +0200
changeset 503473 74f97d22bea2684f9c677f9cb81d092c5535b6f4
parent 503472 af28127350c3414debefb0489beecfc85b6730b1
child 503474 a197adad5b43aa47d6772282c683bec4a2747c60
push id36834
push usernbeleuzu@mozilla.com
push dateSat, 23 Nov 2019 09:47:42 +0000
treeherdermozilla-central@cf114f3b7494 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1570792, 1593358, 1575905, 1593402
milestone72.0a1
backs out43490702945ff3266f57277a1abafd6ca1d700b5
cf2f28971e644574fec25c268044bde692511c08
67f284b0e4c2a65ddcc20d66e2833f9c491c198b
13d8e61774f1802f661fcb603a2053e158acf2d1
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
Backed out 4 changesets (bug 1570792, bug 1593358, bug 1575905) for causing bug 1593402 to near permafail. CLOSED TREE Backed out changeset 43490702945f (bug 1593358) Backed out changeset cf2f28971e64 (bug 1570792) Backed out changeset 67f284b0e4c2 (bug 1575905) Backed out changeset 13d8e61774f1 (bug 1575905)
browser/base/content/test/webextensions/browser_extension_sideloading.js
browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
python/l10n/fluent_migrations/bug_1570792_aboutaddons_extension_toggle.py
toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
toolkit/mozapps/extensions/content/aboutaddons.css
toolkit/mozapps/extensions/content/aboutaddons.html
toolkit/mozapps/extensions/content/aboutaddons.js
toolkit/mozapps/extensions/content/default-theme.svg
toolkit/mozapps/extensions/content/firefox-compact-dark.svg
toolkit/mozapps/extensions/content/firefox-compact-light.svg
toolkit/mozapps/extensions/content/toggle-button.css
toolkit/mozapps/extensions/jar.mn
toolkit/mozapps/extensions/test/browser/browser.ini
toolkit/mozapps/extensions/test/browser/browser_addon_list_reordering.js
toolkit/mozapps/extensions/test/browser/browser_extension_sideloading_permission.js
toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js
toolkit/mozapps/extensions/test/browser/browser_html_detail_view.js
toolkit/mozapps/extensions/test/browser/browser_html_list_view.js
toolkit/mozapps/extensions/test/browser/browser_updateid.js
toolkit/mozapps/extensions/test/browser/head.js
--- a/browser/base/content/test/webextensions/browser_extension_sideloading.js
+++ b/browser/base/content/test/webextensions/browser_extension_sideloading.js
@@ -48,17 +48,17 @@ function getAddonElement(managerWindow, 
   );
 }
 
 function assertDisabledSideloadedAddonElement(managerWindow, addonElement) {
   const doc = addonElement.ownerDocument;
   const enableBtn = addonElement.querySelector('[action="toggle-disabled"]');
   is(
     doc.l10n.getAttributes(enableBtn).id,
-    "enable-addon-button-label",
+    "enable-addon-button",
     "The button has the enable label"
   );
 }
 
 function clickEnableExtension(managerWindow, addonElement) {
   addonElement.querySelector('[action="toggle-disabled"]').click();
 }
 
--- a/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
+++ b/browser/components/enterprisepolicies/tests/browser/browser_policy_extensions.js
@@ -7,17 +7,19 @@ const BASE_URL =
   "http://mochi.test:8888/browser/browser/components/enterprisepolicies/tests/browser";
 
 async function isExtensionLocked(win, addonID) {
   let addonCard = await BrowserTestUtils.waitForCondition(async () => {
     let doc = win.getHtmlBrowser().contentDocument;
     await win.htmlBrowserLoaded;
     return doc.querySelector(`addon-card[addon-id="${addonID}"]`);
   }, `Get addon-card for "${addonID}"`);
-  let disableBtn = addonCard.querySelector('[action="toggle-disabled"]');
+  let disableBtn = addonCard.querySelector(
+    'panel-item[action="toggle-disabled"]'
+  );
   let removeBtn = addonCard.querySelector('panel-item[action="remove"]');
   ok(removeBtn.disabled, "Remove button should be disabled");
   ok(disableBtn.hidden, "Disable button should be hidden");
 }
 
 add_task(async function test_addon_install() {
   let installPromise = wait_for_addon_install();
   await setupPolicyEngineWithJson({
deleted file mode 100644
--- a/python/l10n/fluent_migrations/bug_1570792_aboutaddons_extension_toggle.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# coding=utf8
-
-# Any copyright is dedicated to the Public Domain.
-# http://creativecommons.org/publicdomain/zero/1.0/
-
-from __future__ import absolute_import
-import fluent.syntax.ast as FTL
-from fluent.migrate.helpers import transforms_from
-from fluent.migrate import COPY_PATTERN
-
-TARGET_FILE = "toolkit/toolkit/about/aboutAddons.ftl"
-SOURCE_FILE = TARGET_FILE
-
-
-def migrate(ctx):
-    """Bug 1570792 - Add a toggle to extension cards, part {index}"""
-
-    ctx.add_transforms(
-        TARGET_FILE,
-        SOURCE_FILE,
-        transforms_from(
-"""
-disable-addon-button-label =
-    .aria-label = {COPY_PATTERN(from_path, "disable-addon-button")}
-enable-addon-button-label =
-    .aria-label = {COPY_PATTERN(from_path, "enable-addon-button")}
-""",
-        from_path=SOURCE_FILE),
-    )
--- a/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
+++ b/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
@@ -362,20 +362,16 @@ addon-options-button =
 
 ## Add-on actions
 report-addon-button = Report
 remove-addon-button = Remove
 # The link will always be shown after the other text.
 remove-addon-disabled-button = Can’t Be Removed <a data-l10n-name="link">Why?</a>
 disable-addon-button = Disable
 enable-addon-button = Enable
-disable-addon-button-label =
-    .aria-label = Disable
-enable-addon-button-label =
-    .aria-label = Enable
 preferences-addon-button =
     { PLATFORM() ->
         [windows] Options
        *[other] Preferences
     }
 details-addon-button = Details
 release-notes-addon-button = Release Notes
 permissions-addon-button = Permissions
--- a/toolkit/mozapps/extensions/content/aboutaddons.css
+++ b/toolkit/mozapps/extensions/content/aboutaddons.css
@@ -171,17 +171,16 @@ addon-card[expanded] .addon-card-message
 /* Theme preview image. */
 .card-heading-image {
   /* If the width, height or aspect ratio changes, don't forget to update the
    * getScreenshotUrlForAddon function in aboutaddons.js */
   width: var(--section-width);
   /* Adjust height so that the image preserves the aspect ratio from AMO.
    * For details, see https://bugzilla.mozilla.org/show_bug.cgi?id=1546123 */
   height: calc(var(--section-width) * 92 / 680);
-  object-fit: cover;
 }
 
 .card-heading-icon {
   flex-shrink: 0;
   width: var(--addon-icon-size);
   height: var(--addon-icon-size);
   margin-inline-end: 16px;
   -moz-context-properties: fill;
@@ -190,16 +189,20 @@ addon-card[expanded] .addon-card-message
 
 .card-contents {
   word-break: break-word;
   flex-grow: 1;
   display: flex;
   flex-direction: column;
 }
 
+.card-actions {
+  flex-shrink: 0;
+}
+
 .addon-name-container {
   /* Subtract the top line-height so the text and icon align at the top. */
   margin-top: -3px;
   display: flex;
   align-items: center;
 }
 
 .addon-name {
@@ -235,25 +238,16 @@ addon-card[expanded] .addon-card-message
   background-color: var(--orange-50);
   background-image: url("chrome://mozapps/skin/extensions/recommended.svg");
   background-size: 10px;
   border-radius: 8px;
   fill: #fff;
   -moz-context-properties: fill;
 }
 
-.theme-enable-button {
-  min-width: auto;
-  height: auto;
-  font-size: 13px;
-  min-height: auto;
-  height: 24px;
-  margin: 0;
-}
-
 .addon-description {
   font-size: 14px;
   line-height: 20px;
   color: var(--in-content-deemphasized-text);
   font-weight: 400;
 }
 
 /* Prevent the content from wrapping unless expanded. */
@@ -276,16 +270,22 @@ addon-card:not([expanded]) .addon-descri
 }
 
 .page-options-menu > .more-options-button {
   background-image: url("chrome://mozapps/skin/extensions/utilities.svg");
   width: 32px;
   height: 32px;
 }
 
+.more-options-menu {
+  /* Add some negative margin to account for the button's padding */
+  margin-top: -10px;
+  margin-inline-end: -8px;
+}
+
 /* Recommended add-ons on list views */
 .recommended-heading {
   margin-top: 48px;
 }
 
 /* Discopane extensions to the add-on card */
 
 recommended-addon-card .addon-name {
@@ -432,17 +432,16 @@ addon-details {
 }
 
 .more-options-button {
   min-width: auto;
   min-height: auto;
   width: 24px;
   height: 24px;
   margin: 0;
-  margin-inline-start: 8px;
   -moz-context-properties: fill;
   fill: currentColor;
   background-image: url("chrome://global/skin/icons/more.svg");
   background-repeat: no-repeat;
   background-position: center center;
   /* Get the -badged ::after element in the right spot. */
   padding: 1px;
   display: flex;
--- a/toolkit/mozapps/extensions/content/aboutaddons.html
+++ b/toolkit/mozapps/extensions/content/aboutaddons.html
@@ -9,17 +9,16 @@
     <!-- @CSP the 'onclick' handler for the searchButtonIcon within the file search-textbox.js, using: sha512-kSDNX67wegjpcf8CSj/L6h46a0QUKm2CyijGxC5PhSWVvPU9gdd28QVBBFq9t8N5UGKUFdDcZsjYbGSlYG0y3g== -->
     <meta http-equiv="Content-Security-Policy" content="default-src chrome:; script-src chrome: 'sha512-kSDNX67wegjpcf8CSj/L6h46a0QUKm2CyijGxC5PhSWVvPU9gdd28QVBBFq9t8N5UGKUFdDcZsjYbGSlYG0y3g=='; style-src chrome: 'unsafe-inline'; img-src chrome: file: jar: https: http:; connect-src chrome: data: https: http:; object-src 'none'">
     <link rel="stylesheet" href="chrome://global/content/tabprompts.css">
     <link rel="stylesheet" href="chrome://global/skin/tabprompts.css">
     <link rel="stylesheet" href="chrome://global/skin/textbox.css">
 
     <link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
     <link rel="stylesheet" href="chrome://mozapps/content/extensions/aboutaddons.css">
-    <link rel="stylesheet" href="chrome://mozapps/content/extensions/toggle-button.css">
     <link rel="stylesheet" href="chrome://mozapps/content/extensions/shortcuts.css">
 
     <link rel="localization" href="branding/brand.ftl">
     <link rel="localization" href="toolkit/about/aboutAddons.ftl">
     <link rel="localization" href="toolkit/about/abuseReports.ftl">
 
     <!-- Defer scripts so all the templates are loaded by the time they run. -->
     <script defer src="chrome://mozapps/content/extensions/named-deck.js"></script>
@@ -73,16 +72,17 @@
         <panel-item action="reset-update-states" data-l10n-attrs="accesskey"></panel-item>
         <panel-item-separator></panel-item-separator>
         <panel-item action="manage-shortcuts" data-l10n-id="addon-manage-extensions-shortcuts" data-l10n-attrs="accesskey"></panel-item>
       </panel-list>
     </template>
 
     <template name="addon-options">
       <panel-list>
+        <panel-item action="toggle-disabled"></panel-item>
         <panel-item data-l10n-id="remove-addon-button" action="remove"></panel-item>
         <panel-item data-l10n-id="install-update-button" action="install-update" badged></panel-item>
         <panel-item data-l10n-id="preferences-addon-button" action="preferences"></panel-item>
         <panel-item-separator></panel-item-separator>
         <panel-item data-l10n-id="report-addon-button" action="report"></panel-item>
         <panel-item-separator></panel-item-separator>
         <panel-item data-l10n-id="manage-addon-button" action="expand"></panel-item>
       </panel-list>
@@ -114,29 +114,28 @@
                  hidden>
               </a>
               <a class="addon-badge addon-badge-private-browsing-allowed"
                  is="support-link"
                  support-page="extensions-pb"
                  data-l10n-id="addon-badge-private-browsing-allowed2"
                  hidden>
               </a>
-              <div class="spacer"></div>
-              <button class="theme-enable-button" action="toggle-disabled" hidden></button>
-              <input type="checkbox" class="toggle-button extension-enable-button" action="toggle-disabled" hidden>
-              <button
-                class="more-options-button"
-                action="more-options"
-                data-l10n-id="addon-options-button"
-                aria-haspopup="menu"
-                aria-expanded="false"></button>
             </div>
             <!-- This ends up in the tab order when the ellipsis happens, but it isn't necessary. -->
             <span class="addon-description" tabindex="-1"></span>
           </div>
+          <div class="more-options-menu">
+            <button
+              class="more-options-button ghost-button"
+              action="more-options"
+              data-l10n-id="addon-options-button"
+              aria-haspopup="menu"
+              aria-expanded="false"></button>
+          </div>
         </div>
         <message-bar class="addon-card-message" align="center" hidden>
           <span></span>
           <button action="link"></button>
         </message-bar>
       </div>
     </template>
 
--- a/toolkit/mozapps/extensions/content/aboutaddons.js
+++ b/toolkit/mozapps/extensions/content/aboutaddons.js
@@ -79,31 +79,16 @@ XPCOMUtils.defineLazyPreferenceGetter(
   "LIST_RECOMMENDATIONS_ENABLED",
   "extensions.htmlaboutaddons.recommendations.enabled",
   false
 );
 
 const PLUGIN_ICON_URL = "chrome://global/skin/plugins/pluginGeneric.svg";
 const EXTENSION_ICON_URL =
   "chrome://mozapps/skin/extensions/extensionGeneric.svg";
-const BUILTIN_THEME_PREVIEWS = new Map([
-  [
-    "default-theme@mozilla.org",
-    "chrome://mozapps/content/extensions/default-theme.svg",
-  ],
-  [
-    "firefox-compact-light@mozilla.org",
-    "chrome://mozapps/content/extensions/firefox-compact-light.svg",
-  ],
-  [
-    "firefox-compact-dark@mozilla.org",
-    "chrome://mozapps/content/extensions/firefox-compact-dark.svg",
-  ],
-]);
-
 const PERMISSION_MASKS = {
   "ask-to-activate": AddonManager.PERM_CAN_ASK_TO_ACTIVATE,
   enable: AddonManager.PERM_CAN_ENABLE,
   "always-activate": AddonManager.PERM_CAN_ENABLE,
   disable: AddonManager.PERM_CAN_DISABLE,
   "never-activate": AddonManager.PERM_CAN_DISABLE,
   uninstall: AddonManager.PERM_CAN_UNINSTALL,
   upgrade: AddonManager.PERM_CAN_UPGRADE,
@@ -117,23 +102,16 @@ const PREF_PRIVACY_POLICY_URL = "extensi
 const PREF_RECOMMENDATION_ENABLED = "browser.discovery.enabled";
 const PREF_TELEMETRY_ENABLED = "datareporting.healthreport.uploadEnabled";
 const PRIVATE_BROWSING_PERM_NAME = "internal:privateBrowsingAllowed";
 const PRIVATE_BROWSING_PERMS = {
   permissions: [PRIVATE_BROWSING_PERM_NAME],
   origins: [],
 };
 
-function shouldSkipAnimations() {
-  return (
-    document.body.hasAttribute("skip-animations") ||
-    window.matchMedia("(prefers-reduced-motion: reduce)").matches
-  );
-}
-
 const AddonCardListenerHandler = {
   ADDON_EVENTS: new Set([
     "onDisabled",
     "onEnabled",
     "onInstalled",
     "onPropertyChanged",
     "onUninstalling",
   ]),
@@ -436,20 +414,16 @@ function nl2br(text) {
 /**
  * Select the screeenshot to display above an add-on card.
  *
  * @param {AddonWrapper|DiscoAddonWrapper} addon
  * @returns {string|null}
  *          The URL of the best fitting screenshot, if any.
  */
 function getScreenshotUrlForAddon(addon) {
-  if (BUILTIN_THEME_PREVIEWS.has(addon.id)) {
-    return BUILTIN_THEME_PREVIEWS.get(addon.id);
-  }
-
   let { screenshots } = addon;
   if (!screenshots || !screenshots.length) {
     return null;
   }
 
   // The image size is defined at .card-heading-image in aboutaddons.css, and
   // is based on the aspect ratio for a 680x92 image. Use the image if possible,
   // and otherwise fall back to the first image and hope for the best.
@@ -1641,16 +1615,22 @@ class AddonOptions extends HTMLElement {
             el.appendChild(link);
             document.l10n.setAttributes(el, "remove-addon-disabled-button");
           }
         }
         break;
       case "report":
         el.hidden = !isAbuseReportSupported(addon);
         break;
+      case "toggle-disabled": {
+        let toggleDisabledAction = addon.userDisabled ? "enable" : "disable";
+        document.l10n.setAttributes(el, `${toggleDisabledAction}-addon-button`);
+        el.hidden = !hasPermission(addon, toggleDisabledAction);
+        break;
+      }
       case "install-update":
         el.hidden = !updateInstall;
         break;
       case "expand":
         el.hidden = card.expanded;
         break;
       case "preferences":
         el.hidden =
@@ -2432,27 +2412,29 @@ class AddonCard extends HTMLElement {
   async handleEvent(e) {
     let { addon } = this;
     let action = e.target.getAttribute("action");
 
     if (e.type == "click") {
       switch (action) {
         case "toggle-disabled":
           this.recordActionEvent(addon.userDisabled ? "enable" : "disable");
-          // Keep the checked state the same until the add-on's state changes.
-          e.target.checked = !addon.userDisabled;
           if (addon.userDisabled) {
             if (shouldShowPermissionsPrompt(addon)) {
               await showPermissionsPrompt(addon);
             } else {
               await addon.enable();
             }
           } else {
             await addon.disable();
           }
+          if (e.mozInputSource == MouseEvent.MOZ_SOURCE_KEYBOARD) {
+            // Refocus the open menu button so it's clear where the focus is.
+            this.querySelector('[action="more-options"]').focus();
+          }
           break;
         case "ask-to-activate":
           if (hasPermission(addon, "ask-to-activate")) {
             addon.userDisabled = AddonManager.STATE_ASK_TO_ACTIVATE;
           }
           break;
         case "always-activate":
           this.recordActionEvent("enable");
@@ -2691,69 +2673,50 @@ class AddonCard extends HTMLElement {
    * Update the card's contents based on the previously set add-on. This should
    * be called if there has been a change to the add-on.
    */
   update() {
     let { addon, card } = this;
 
     card.setAttribute("active", addon.isActive);
 
-    // Set the icon or theme preview.
-    let iconEl = card.querySelector(".addon-icon");
+    // Update the icon.
+    let icon;
+    if (addon.type == "plugin") {
+      icon = PLUGIN_ICON_URL;
+    } else {
+      icon =
+        AddonManager.getPreferredIconURL(addon, 32, window) ||
+        EXTENSION_ICON_URL;
+    }
+    card.querySelector(".addon-icon").src = icon;
+
+    // Update the theme preview.
     let preview = card.querySelector(".card-heading-image");
+    preview.hidden = true;
     if (addon.type == "theme") {
-      iconEl.hidden = true;
       let screenshotUrl = getScreenshotUrlForAddon(addon);
       if (screenshotUrl) {
         preview.src = screenshotUrl;
-      }
-      preview.hidden = !screenshotUrl;
-    } else {
-      preview.hidden = true;
-      iconEl.hidden = false;
-      if (addon.type == "plugin") {
-        iconEl.src = PLUGIN_ICON_URL;
-      } else {
-        iconEl.src =
-          AddonManager.getPreferredIconURL(addon, 32, window) ||
-          EXTENSION_ICON_URL;
+        preview.hidden = false;
       }
     }
 
     // Update the name.
     let name = this.addonNameEl;
     if (addon.isActive) {
       name.textContent = addon.name;
       name.removeAttribute("data-l10n-id");
     } else {
       document.l10n.setAttributes(name, "addon-name-disabled", {
         name: addon.name,
       });
     }
     name.title = `${addon.name} ${addon.version}`;
 
-    let toggleDisabledAction = addon.userDisabled ? "enable" : "disable";
-    let canToggleDisabled = hasPermission(addon, toggleDisabledAction);
-    let toggleDisabledButton = card.querySelector('[action="toggle-disabled"]');
-    if (toggleDisabledButton) {
-      toggleDisabledButton.hidden = !canToggleDisabled;
-      if (addon.type === "theme") {
-        document.l10n.setAttributes(
-          toggleDisabledButton,
-          `${toggleDisabledAction}-addon-button`
-        );
-      } else if (addon.type === "extension") {
-        toggleDisabledButton.checked = !addon.userDisabled;
-        document.l10n.setAttributes(
-          toggleDisabledButton,
-          `${toggleDisabledAction}-addon-button-label`
-        );
-      }
-    }
-
     // Set the items in the more options menu.
     this.options.update(this, addon, this.updateInstall);
 
     // Badge the more options button if there's an update.
     let moreOptionsButton = card.querySelector(".more-options-button");
     moreOptionsButton.classList.toggle(
       "more-options-button-badged",
       !!this.updateInstall
@@ -2837,24 +2800,16 @@ class AddonCard extends HTMLElement {
     }
 
     let headingId = ExtensionCommon.makeWidgetId(`${addon.name}-heading`);
     this.setAttribute("aria-labelledby", headingId);
     this.setAttribute("addon-id", addon.id);
 
     this.card = importTemplate("card").firstElementChild;
 
-    // Remove the toggle-disabled button(s) based on type.
-    if (addon.type != "theme") {
-      this.card.querySelector(".theme-enable-button").remove();
-    }
-    if (addon.type != "extension") {
-      this.card.querySelector(".extension-enable-button").remove();
-    }
-
     let nameContainer = this.card.querySelector(".addon-name-container");
     let headingLevel = this.expanded ? "h1" : "h3";
     let nameHeading = document.createElement(headingLevel);
     nameHeading.classList.add("addon-name");
     if (!this.expanded) {
       let name = document.createElement("a");
       name.classList.add("addon-name-link");
       name.href = `addons://detail/${addon.id}`;
@@ -2863,17 +2818,17 @@ class AddonCard extends HTMLElement {
     } else {
       this.addonNameEl = nameHeading;
     }
     nameContainer.prepend(nameHeading);
 
     let panelType = addon.type == "plugin" ? "plugin-options" : "addon-options";
     this.options = document.createElement(panelType);
     this.options.render();
-    this.card.appendChild(this.options);
+    this.card.querySelector(".more-options-menu").appendChild(this.options);
     this.optionsButton = this.card.querySelector(".more-options-button");
 
     // Set the contents.
     this.update();
 
     let doneRenderPromise = Promise.resolve();
     if (this.expanded) {
       if (!this.details) {
@@ -2936,16 +2891,17 @@ class RecommendedAddonCard extends HTMLE
 
     // Save the information so we can install.
     this.discoAddon = addon;
 
     let card = importTemplate("card").firstElementChild;
     let heading = card.querySelector(".addon-name-container");
     heading.textContent = "";
     heading.append(importTemplate("addon-name-container-in-disco-card"));
+    card.querySelector(".more-options-menu").remove();
 
     this.setCardContent(card, addon);
     if (addon.type != "theme") {
       card
         .querySelector(".addon-description")
         .append(importTemplate("addon-description-in-disco-card"));
       this.setCardDescription(card, addon);
     }
@@ -2974,24 +2930,23 @@ class RecommendedAddonCard extends HTMLE
         addon,
         32,
         window
       );
     }
 
     // Set the theme preview.
     let preview = card.querySelector(".card-heading-image");
+    preview.hidden = true;
     if (addon.type == "theme") {
       let screenshotUrl = getScreenshotUrlForAddon(addon);
       if (screenshotUrl) {
         preview.src = screenshotUrl;
         preview.hidden = false;
       }
-    } else {
-      preview.hidden = true;
     }
 
     // Set the name.
     card.querySelector(".disco-addon-name").textContent = addon.name;
 
     // Set the author name and link to AMO.
     if (addon.creator) {
       let authorInfo = card.querySelector(".disco-addon-author");
@@ -3129,18 +3084,16 @@ customElements.define("recommended-addon
  *    }]);
  *    document.body.appendChild(list);
  */
 class AddonList extends HTMLElement {
   constructor() {
     super();
     this.sections = [];
     this.pendingUninstallAddons = new Set();
-    this._addonsToUpdate = new Set();
-    this._userFocusListenersAdded = false;
   }
 
   async connectedCallback() {
     // Register the listener and get the add-ons, these operations should
     // happpen as close to each other as possible.
     this.registerListener();
     // Don't render again if we were rendered prior to being inserted.
     if (!this.children.length) {
@@ -3323,17 +3276,19 @@ class AddonList extends HTMLElement {
 
   addAddon(addon) {
     // Only insert add-ons of the right type.
     if (addon.type != this.type && this.type != "all") {
       this.sendEvent("skip-add", "type-mismatch");
       return;
     }
 
-    let insertSection = this._addonSectionIndex(addon);
+    let insertSection = this.sections.findIndex(({ filterFn }) =>
+      filterFn(addon)
+    );
 
     // Don't add the add-on if it doesn't go in a section.
     if (insertSection == -1) {
       return;
     }
 
     // Create and insert the card.
     let card = document.createElement("addon-card");
@@ -3352,154 +3307,34 @@ class AddonList extends HTMLElement {
       let section = card.parentNode;
       card.remove();
       this.updateSectionIfEmpty(section);
       this.sendEvent("remove", { id: addon.id });
     }
   }
 
   updateAddon(addon) {
-    if (!this.getCard(addon)) {
-      // Try to add the add-on right away.
-      this.addAddon(addon);
-    } else if (this._addonSectionIndex(addon) == -1) {
-      // Try to remove the add-on right away.
-      this._updateAddon(addon);
-    } else if (this.isUserFocused) {
-      // Queue up a change for when the focus is cleared.
-      this.updateLater(addon);
-    } else {
-      // Not currently focused, make the change now.
-      this.withCardAnimation(() => this._updateAddon(addon));
-    }
-  }
-
-  updateLater(addon) {
-    this._addonsToUpdate.add(addon);
-    this._addUserFocusListeners();
-  }
-
-  _addUserFocusListeners() {
-    if (this._userFocusListenersAdded) {
-      return;
-    }
-
-    this._userFocusListenersAdded = true;
-    this.addEventListener("mouseleave", this);
-    this.addEventListener("hidden", this, true);
-    this.addEventListener("focusout", this);
-  }
-
-  _removeUserFocusListeners() {
-    if (!this._userFocusListenersAdded) {
-      return;
-    }
-
-    this.removeEventListener("mouseleave", this);
-    this.removeEventListener("hidden", this, true);
-    this.removeEventListener("focusout", this);
-    this._userFocusListenersAdded = false;
-  }
-
-  get hasMenuOpen() {
-    return !!this.querySelector("panel-list[open]");
-  }
-
-  get isUserFocused() {
-    return this.matches(":hover, :focus-within") || this.hasMenuOpen;
-  }
-
-  update() {
-    if (this._addonsToUpdate.size) {
-      this.withCardAnimation(() => {
-        for (let addon of this._addonsToUpdate) {
-          this._updateAddon(addon);
-        }
-        this._addonsToUpdate = new Set();
-      });
-    }
-  }
-
-  _getChildCoords() {
-    let results = new Map();
-    for (let child of this.querySelectorAll("addon-card")) {
-      results.set(child, child.getBoundingClientRect());
-    }
-    return results;
-  }
-
-  withCardAnimation(changeFn) {
-    if (shouldSkipAnimations()) {
-      changeFn();
-      return;
-    }
-
-    let origChildCoords = this._getChildCoords();
-
-    changeFn();
-
-    let newChildCoords = this._getChildCoords();
-    let cards = this.querySelectorAll("addon-card");
-    let transitionCards = [];
-    for (let card of cards) {
-      let orig = origChildCoords.get(card);
-      let moved = newChildCoords.get(card);
-      let changeY = moved.y - (orig || moved).y;
-      let cardEl = card.firstElementChild;
-
-      if (changeY != 0) {
-        cardEl.style.transform = `translateY(${changeY * -1}px)`;
-        transitionCards.push(card);
-      }
-    }
-    requestAnimationFrame(() => {
-      for (let card of transitionCards) {
-        card.firstElementChild.style.transition = "transform 125ms";
-      }
-
-      requestAnimationFrame(() => {
-        for (let card of transitionCards) {
-          let cardEl = card.firstElementChild;
-          cardEl.style.transform = "";
-          cardEl.addEventListener("transitionend", function handler(e) {
-            if (e.target == cardEl && e.propertyName == "transform") {
-              cardEl.style.transition = "";
-              cardEl.removeEventListener("transitionend", handler);
-            }
-          });
-        }
-      });
-    });
-  }
-
-  _addonSectionIndex(addon) {
-    return this.sections.findIndex(s => s.filterFn(addon));
-  }
-
-  _updateAddon(addon) {
     let card = this.getCard(addon);
     if (card) {
-      let sectionIndex = this._addonSectionIndex(addon);
+      let sectionIndex = this.sections.findIndex(s => s.filterFn(addon));
       if (sectionIndex != -1) {
         // Move the card, if needed. This will allow an animation between
         // page sections and provides clearer events for testing.
         if (card.parentNode.getAttribute("section") != sectionIndex) {
-          let { activeElement } = document;
-          let refocus = card.contains(activeElement);
           let oldSection = card.parentNode;
           this.insertCardInto(card, sectionIndex);
           this.updateSectionIfEmpty(oldSection);
-          if (refocus) {
-            activeElement.focus();
-          }
           this.sendEvent("move", { id: addon.id });
         }
       } else {
         this.removeAddon(addon);
       }
+    } else {
+      // Add the add-on, this will do nothing if it shouldn't be in the list.
+      this.addAddon(addon);
     }
   }
 
   renderSection(addons, index) {
     let section = document.createElement("section");
     section.setAttribute("section", index);
 
     // Render the heading and add-ons if there are any.
@@ -3588,23 +3423,16 @@ class AddonList extends HTMLElement {
     this.addAddon(addon);
   }
 
   onUninstalled(addon) {
     this.pendingUninstallAddons.delete(addon);
     this.removePendingUninstallBar(addon);
     this.removeAddon(addon);
   }
-
-  handleEvent(e) {
-    if (!this.isUserFocused || (e.type == "mouseleave" && !this.hasMenuOpen)) {
-      this._removeUserFocusListeners();
-      this.update();
-    }
-  }
 }
 customElements.define("addon-list", AddonList);
 
 class RecommendedAddonList extends HTMLElement {
   connectedCallback() {
     if (this.isConnected) {
       this.loadCardsIfNeeded();
       this.updateCardsWithAddonManager();
deleted file mode 100644
--- a/toolkit/mozapps/extensions/content/default-theme.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="664" height="90" fill="#0C0C0D">
-  <path fill="#202340" d="M0 0h664v90H0z"/>
-  <path fill="#F9F9FA" d="M28 35.717V.5L156 0v35.217h508V90H0V35.217z"/>
-  <path fill="#0A84FF" d="M28 0h128v5H28z"/>
-  <rect width="76" height="5" x="54" y="18" fill="#3D3D3D" rx="2.5"/>
-  <rect width="76" height="5" x="182" y="18" fill="#F9F9FA" rx="2.5"/>
-  <rect width="533" height="29" x="82.5" y="47.5" fill="#FFF" stroke="#ADADB3" stroke-opacity=".2" rx="4"/>
-  <rect width="430" height="5" x="96" y="61" rx="2.5"/>
-  <circle cx="27" cy="63" r="7"/>
-  <circle cx="55" cy="63" r="7"/>
-  <rect width="18" height="2.667" x="630" y="54" rx="1.333"/>
-  <rect width="18" height="2.667" x="630" y="60.667" rx="1.333"/>
-  <rect width="18" height="2.667" x="630" y="67" rx="1.333"/>
-</svg>
deleted file mode 100644
--- a/toolkit/mozapps/extensions/content/firefox-compact-dark.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="664" height="90" fill="#F9F9FA">
-  <path fill="#0C0C0D" d="M0 0h664v90H0z"/>
-  <path fill="#323234" d="M28 35.217V0l128 .489v35.218l508-.49V90H0V35.217z"/>
-  <path fill="#0A84FF" d="M28 0h128v5H28z"/>
-  <rect width="76" height="5" x="54" y="18" rx="2.5"/>
-  <rect width="76" height="5" x="182" y="18" rx="2.5"/>
-  <rect width="533" height="29" x="82.5" y="47.5" fill="#515153" stroke="#ADADB3" stroke-opacity=".2" rx="4"/>
-  <rect width="430" height="5" x="96" y="61" rx="2.5"/>
-  <circle cx="27" cy="63" r="7"/>
-  <circle cx="55" cy="63" r="7"/>
-  <rect width="18" height="2.667" x="630" y="54" rx="1.333"/>
-  <rect width="18" height="2.667" x="630" y="60.667" rx="1.333"/>
-  <rect width="18" height="2.667" x="630" y="67.333" rx="1.333"/>
-</svg>
deleted file mode 100644
--- a/toolkit/mozapps/extensions/content/firefox-compact-light.svg
+++ /dev/null
@@ -1,17 +0,0 @@
-<!-- This Source Code Form is subject to the terms of the Mozilla Public
-   - 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" width="664" height="90" fill="#0C0C0D">
-  <path fill="#E1E1E5" d="M0 0h664v90H0z"/>
-  <path fill="#F9F9FA" d="M28 35.217V0h128v35.217h508V90H0V35.217z"/>
-  <path fill="#0A84FF" d="M28 0h128v5H28z"/>
-  <rect width="76" height="5" x="54" y="18" fill="#3D3D3D" rx="2.5"/>
-  <rect width="76" height="5" x="182" y="18" fill="#3D3D3D" rx="2.5"/>
-  <rect width="533" height="29" x="82.5" y="47.5" fill="#FFF" stroke="#ADADB3" stroke-opacity=".2" rx="4"/>
-  <rect width="430" height="5" x="96" y="61" rx="2.5"/>
-  <circle cx="27" cy="63" r="7"/>
-  <circle cx="55" cy="63" r="7"/>
-  <rect width="18" height="2.667" x="630" y="54" rx="1.333"/>
-  <rect width="18" height="2.667" x="630" y="60.667" rx="1.333"/>
-  <rect width="18" height="2.667" x="630" y="67.333" rx="1.333"/>
-</svg>
deleted file mode 100644
--- a/toolkit/mozapps/extensions/content/toggle-button.css
+++ /dev/null
@@ -1,72 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * 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/. */
-
-input[type="checkbox"].toggle-button {
-  --button-height: 16px;
-  --button-half-height: 8px;
-  --button-width: 26px;
-  --button-border-width: 1px;
-  /* dot-size = button-height - 2*dot-margin - 2*button-border-width */
-  --dot-size: 10px;
-  --dot-margin: 2px;
-  /* --dot-transform-x = button-width - 2*dot-margin - dot-size - 2*button-border-width */
-  --dot-transform-x: 10px;
-  --border-color: hsla(210,4%,10%,.14);
-}
-
-input[type="checkbox"].toggle-button {
-  -moz-appearance: none;
-  padding: 0;
-  margin: 0;
-  outline: 0;
-  border: var(--button-border-width) solid var(--border-color);
-  height: var(--button-height);
-  width: var(--button-width);
-  border-radius: var(--button-half-height);
-  background: var(--in-content-button-background);
-  box-sizing: border-box;
-}
-input[type="checkbox"].toggle-button:hover {
-  background: var(--in-content-button-background-hover);
-  border-color: var(--border-color);
-}
-input[type="checkbox"].toggle-button:active {
-  background: var(--in-content-button-background-active);
-  border-color: var(--border-color);
-}
-input[type="checkbox"].toggle-button:focus {
-  box-shadow: 0 0 0 1px var(--border-color), 0 0 0 4px rgba(10, 132, 255, 0.3);
-}
-input[type="checkbox"].toggle-button:checked:focus {
-  box-shadow: 0 0 0 1px var(--in-content-border-active), 0 0 0 4px rgba(10, 132, 255, 0.3);
-}
-
-input[type="checkbox"].toggle-button:checked {
-  background: var(--in-content-primary-button-background);
-  border-color: var(--in-content-primary-button-background-hover);
-}
-input[type="checkbox"].toggle-button:checked:hover {
-  background: var(--in-content-primary-button-background-hover);
-  border-color: var(--in-content-primary-button-background-active);
-}
-input[type="checkbox"].toggle-button:checked:active {
-  background: var(--in-content-primary-button-background-active);
-  border-color: var(--in-content-primary-button-background-active);
-}
-
-input[type="checkbox"].toggle-button::before {
-  display: block;
-  content: "";
-  background: #fff;
-  height: var(--dot-size);
-  width: var(--dot-size);
-  margin: var(--dot-margin);
-  border-radius: 50%;
-  outline: 1px solid var(--border-color);
-  -moz-outline-radius: 50%;
-  transition: transform 100ms;
-}
-input[type="checkbox"].toggle-button:checked::before {
-  transform: translateX(var(--dot-transform-x));
-}
--- a/toolkit/mozapps/extensions/jar.mn
+++ b/toolkit/mozapps/extensions/jar.mn
@@ -17,21 +17,17 @@ toolkit.jar:
   content/mozapps/extensions/aboutaddons.js                     (content/aboutaddons.js)
   content/mozapps/extensions/aboutaddonsCommon.js               (content/aboutaddonsCommon.js)
   content/mozapps/extensions/aboutaddons.css                    (content/aboutaddons.css)
   content/mozapps/extensions/abuse-reports.js                   (content/abuse-reports.js)
   content/mozapps/extensions/abuse-report-frame.html            (content/abuse-report-frame.html)
   content/mozapps/extensions/abuse-report-frame.js              (content/abuse-report-frame.js)
   content/mozapps/extensions/abuse-report-panel.css             (content/abuse-report-panel.css)
   content/mozapps/extensions/abuse-report-panel.js              (content/abuse-report-panel.js)
-  content/mozapps/extensions/default-theme.svg                  (content/default-theme.svg)
-  content/mozapps/extensions/firefox-compact-dark.svg           (content/firefox-compact-dark.svg)
-  content/mozapps/extensions/firefox-compact-light.svg          (content/firefox-compact-light.svg)
   content/mozapps/extensions/message-bar.css                    (content/message-bar.css)
   content/mozapps/extensions/message-bar.js                     (content/message-bar.js)
   content/mozapps/extensions/named-deck.js                      (content/named-deck.js)
   content/mozapps/extensions/panel-list.css                     (content/panel-list.css)
   content/mozapps/extensions/panel-item.css                     (content/panel-item.css)
   content/mozapps/extensions/rating-star.css                    (content/rating-star.css)
   content/mozapps/extensions/shortcuts.css                      (content/shortcuts.css)
   content/mozapps/extensions/shortcuts.js                       (content/shortcuts.js)
-  content/mozapps/extensions/toggle-button.css                  (content/toggle-button.css)
 #endif
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -42,17 +42,16 @@ generated-files =
   addons/browser_dragdrop_incompat.xpi
   addons/browser_installssl.xpi
   addons/browser_theme.xpi
   addons/options_signed.xpi
 
 [browser_CTP_plugins.js]
 tags = blocklist
 [browser_about_debugging_link.js]
-[browser_addon_list_reordering.js]
 [browser_bug523784.js]
 skip-if = (!debug && os == 'win') #Bug 1489496
 [browser_bug567137.js]
 [browser_bug572561.js]
 [browser_bug577990.js]
 [browser_bug591465.js]
 skip-if = os == "linux" && !debug # Bug 1395539 - fails on multi-core
 [browser_bug679604.js]
deleted file mode 100644
--- a/toolkit/mozapps/extensions/test/browser/browser_addon_list_reordering.js
+++ /dev/null
@@ -1,189 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
-   http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-const { AddonTestUtils } = ChromeUtils.import(
-  "resource://testing-common/AddonTestUtils.jsm"
-);
-
-AddonTestUtils.initMochitest(this);
-
-function assertInSection(card, sectionName, msg) {
-  let section = card.closest("section");
-  let heading = section.querySelector(".list-section-heading");
-  is(
-    card.ownerDocument.l10n.getAttributes(heading).id,
-    `extension-${sectionName}-heading`,
-    msg
-  );
-}
-
-function waitForAnimationFrame(win) {
-  return new Promise(resolve => win.requestAnimationFrame(resolve));
-}
-
-async function clickEnableToggle(card) {
-  let isDisabled = card.addon.userDisabled;
-  let addonEvent = isDisabled ? "onEnabled" : "onDisabled";
-  let addonStateChanged = AddonTestUtils.promiseAddonEvent(addonEvent);
-  let win = card.ownerGlobal;
-  let button = card.querySelector(".extension-enable-button");
-
-  // Centre the button since "start" could be behind the sticky header.
-  button.scrollIntoView({ block: "center" });
-  EventUtils.synthesizeMouseAtCenter(button, { type: "mousemove" }, win);
-  EventUtils.synthesizeMouseAtCenter(button, {}, win);
-
-  await addonStateChanged;
-  await waitForAnimationFrame(win);
-}
-
-function mouseOver(el) {
-  let win = el.ownerGlobal;
-  el.scrollIntoView({ block: "center" });
-  EventUtils.synthesizeMouseAtCenter(el, { type: "mousemove" }, win);
-  return waitForAnimationFrame(win);
-}
-
-function mouseOutOfList(win) {
-  return mouseOver(win.document.querySelector(".header-name"));
-}
-
-function pressKey(win, key) {
-  EventUtils.synthesizeKey(key, {}, win);
-  return waitForAnimationFrame(win);
-}
-
-function waitForTransitionEnd(...els) {
-  return Promise.all(
-    els.map(el =>
-      BrowserTestUtils.waitForEvent(el, "transitionend", false, e => {
-        let cardEl = el.firstElementChild;
-        return e.target == cardEl && e.propertyName == "transform";
-      })
-    )
-  );
-}
-
-add_task(async function testReordering() {
-  let addonIds = [
-    "one@mochi.test",
-    "two@mochi.test",
-    "three@mochi.test",
-    "four@mochi.test",
-    "five@mochi.test",
-  ];
-  let extensions = addonIds.map(id =>
-    ExtensionTestUtils.loadExtension({
-      manifest: {
-        name: id,
-        applications: { gecko: { id } },
-      },
-      useAddonManager: "temporary",
-    })
-  );
-
-  await Promise.all(extensions.map(ext => ext.startup()));
-
-  let win = await loadInitialView("extension", { withAnimations: true });
-
-  let cardOne = getAddonCard(win, "one@mochi.test");
-  ok(!cardOne.addon.userDisabled, "extension one is enabled");
-  assertInSection(cardOne, "enabled", "cardOne is initially in Enabled");
-
-  await clickEnableToggle(cardOne);
-
-  ok(cardOne.addon.userDisabled, "extension one is now disabled");
-  assertInSection(cardOne, "enabled", "cardOne is still in Enabled");
-
-  let cardThree = getAddonCard(win, "three@mochi.test");
-  ok(!cardThree.addon.userDisabled, "extension three is enabled");
-  assertInSection(cardThree, "enabled", "cardThree is initially in Enabled");
-
-  await clickEnableToggle(cardThree);
-
-  ok(cardThree.addon.userDisabled, "extension three is now disabled");
-  assertInSection(cardThree, "enabled", "cardThree is still in Enabled");
-
-  let transitionsEnded = waitForTransitionEnd(cardOne, cardThree);
-  await mouseOutOfList(win);
-  await transitionsEnded;
-
-  assertInSection(cardOne, "disabled", "cardOne has moved to disabled");
-  assertInSection(cardThree, "disabled", "cardThree has moved to disabled");
-
-  await clickEnableToggle(cardThree);
-  await clickEnableToggle(cardOne);
-
-  assertInSection(cardOne, "disabled", "cardOne is still in disabled");
-  assertInSection(cardThree, "disabled", "cardThree is still in disabled");
-
-  info("Opening a more options menu");
-  let panel = cardThree.querySelector("panel-list");
-  EventUtils.synthesizeMouseAtCenter(
-    cardThree.querySelector('[action="more-options"]'),
-    {},
-    win
-  );
-
-  await BrowserTestUtils.waitForEvent(panel, "shown");
-  await mouseOutOfList(win);
-
-  assertInSection(cardOne, "disabled", "cardOne stays in disabled, menu open");
-  assertInSection(cardThree, "disabled", "cardThree stays in disabled");
-
-  transitionsEnded = waitForTransitionEnd(cardOne, cardThree);
-  EventUtils.synthesizeMouseAtCenter(
-    win.document.querySelector(".header-name"),
-    {},
-    win
-  );
-  await transitionsEnded;
-
-  assertInSection(cardOne, "enabled", "cardOne is now in enabled");
-  assertInSection(cardThree, "enabled", "cardThree is now in enabled");
-
-  let cardOneToggle = cardOne.querySelector(".extension-enable-button");
-  cardOneToggle.scrollIntoView({ block: "center" });
-  cardOneToggle.focus();
-  await pressKey(win, " ");
-  await waitForAnimationFrame(win);
-
-  let cardThreeToggle = cardThree.querySelector(".extension-enable-button");
-  let addonList = win.document.querySelector("addon-list");
-  // Tab down to cardThreeToggle.
-  while (
-    addonList.contains(win.document.activeElement) &&
-    win.document.activeElement !== cardThreeToggle
-  ) {
-    await pressKey(win, "VK_TAB");
-  }
-  await pressKey(win, " ");
-
-  assertInSection(cardOne, "enabled", "cardOne is still in enabled");
-  assertInSection(cardThree, "enabled", "cardThree is still in enabled");
-
-  transitionsEnded = waitForTransitionEnd(cardOne, cardThree);
-  win.document.querySelector('[action="page-options"]').focus();
-  await transitionsEnded;
-  assertInSection(
-    cardOne,
-    "disabled",
-    "cardOne is now in the disabled section"
-  );
-  assertInSection(
-    cardThree,
-    "disabled",
-    "cardThree is now in the disabled section"
-  );
-
-  // Ensure an uninstalled extension is removed right away.
-  // Hover a card in the middle of the list.
-  await mouseOver(getAddonCard(win, "two@mochi.test"));
-  await cardOne.addon.uninstall(true);
-  ok(!cardOne.parentNode, "cardOne has been removed from the document");
-
-  await closeView(win);
-  await Promise.all(extensions.map(ext => ext.unload()));
-});
--- a/toolkit/mozapps/extensions/test/browser/browser_extension_sideloading_permission.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_extension_sideloading_permission.js
@@ -14,29 +14,29 @@ AddonTestUtils.initMochitest(this);
 
 function assertDisabledSideloadedExtensionElement(managerWindow, addonElement) {
   const doc = addonElement.ownerDocument;
   const toggleDisabled = addonElement.querySelector(
     '[action="toggle-disabled"]'
   );
   is(
     doc.l10n.getAttributes(toggleDisabled).id,
-    "enable-addon-button-label",
+    "enable-addon-button",
     "Addon toggle-disabled action has the enable label"
   );
 }
 
 function assertEnabledSideloadedExtensionElement(managerWindow, addonElement) {
   const doc = addonElement.ownerDocument;
   const toggleDisabled = addonElement.querySelector(
     '[action="toggle-disabled"]'
   );
   is(
     doc.l10n.getAttributes(toggleDisabled).id,
-    "enable-addon-button-label",
+    "enable-addon-button",
     "Addon toggle-disabled action has the enable label"
   );
 }
 
 function clickEnableExtension(managerWindow, addonElement) {
   addonElement.querySelector('[action="toggle-disabled"]').click();
 }
 
--- a/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_gmpProvider.js
@@ -10,16 +10,19 @@ const { AppConstants } = ChromeUtils.imp
 );
 var GMPScope = ChromeUtils.import(
   "resource://gre/modules/addons/GMPProvider.jsm",
   null
 );
 
 const TEST_DATE = new Date(2013, 0, 1, 12);
 
+var gManagerWindow;
+var gCategoryUtilities;
+
 var gMockAddons = [];
 
 for (let plugin of GMPScope.GMP_PLUGINS) {
   let mockAddon = Object.freeze({
     id: plugin.id,
     isValid: true,
     isInstalled: false,
     isEME: !!(
@@ -45,30 +48,45 @@ MockGMPInstallManager.prototype = {
 
   installAddon: addon => {
     gInstalledAddonId = addon.id;
     gInstallDeferred.resolve();
     return Promise.resolve();
   },
 };
 
-function openDetailsView(win, id) {
-  let item = getAddonCard(win, id);
+function openDetailsView(aId) {
+  let view = get_current_view(gManagerWindow);
+  Assert.equal(
+    view.id,
+    "html-view",
+    "Should be in the list view to use this function"
+  );
+
+  let item = get_addon_element(gManagerWindow, aId);
   Assert.ok(item, "Should have got add-on element.");
   is_element_visible(item, "Add-on element should be visible.");
 
-  let loaded = waitForViewLoad(win);
-  EventUtils.synthesizeMouseAtCenter(item, {}, item.ownerGlobal);
-  return loaded;
+  item.scrollIntoView();
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, item.ownerGlobal);
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, item.ownerGlobal);
+
+  return new Promise(resolve => {
+    wait_for_view_load(gManagerWindow, resolve);
+  });
 }
 
-add_task(async function initializeState() {
+async function initializeState() {
   gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_LOGGING_DUMP, true);
   gPrefs.setIntPref(GMPScope.GMPPrefs.KEY_LOGGING_LEVEL, 0);
 
+  gManagerWindow = await open_manager();
+
+  gCategoryUtilities = new CategoryUtilities(gManagerWindow);
+
   registerCleanupFunction(async function() {
     for (let addon of gMockAddons) {
       gPrefs.clearUserPref(
         getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id)
       );
       gPrefs.clearUserPref(
         getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id)
       );
@@ -119,75 +137,67 @@ add_task(async function initializeState(
     );
     gPrefs.setBoolPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id),
       true
     );
   }
   await GMPScope.GMPProvider.shutdown();
   GMPScope.GMPProvider.startup();
-});
+}
 
-add_task(async function testNotInstalledDisabled() {
-  let win = await loadInitialView("extension");
-
-  Assert.ok(isCategoryVisible(win, "plugin"), "Plugin tab visible.");
-  await switchView(win, "plugin");
+async function testNotInstalledDisabled() {
+  Assert.ok(gCategoryUtilities.isTypeVisible("plugin"), "Plugin tab visible.");
+  await gCategoryUtilities.openType("plugin");
 
   for (let addon of gMockAddons) {
-    let addonCard = getAddonCard(win, addon.id);
+    let addonCard = get_addon_element(gManagerWindow, addon.id);
     Assert.ok(addonCard, "Got add-on element:" + addon.id);
 
     is(
       addonCard.ownerDocument.l10n.getAttributes(addonCard.addonNameEl).id,
       "addon-name-disabled",
       "The addon name should include a disabled postfix"
     );
 
     let cardMessage = addonCard.querySelector("message-bar.addon-card-message");
     is_element_hidden(cardMessage, "Warning notification is hidden");
   }
-
-  await closeView(win);
-});
+}
 
-add_task(async function testNotInstalledDisabledDetails() {
-  let win = await loadInitialView("plugin");
+async function testNotInstalledDisabledDetails() {
+  for (let addon of gMockAddons) {
+    await openDetailsView(addon.id);
+    let doc = gManagerWindow.document;
 
-  for (let addon of gMockAddons) {
-    await openDetailsView(win, addon.id);
-    let addonCard = getAddonCard(win, addon.id);
+    let addonCard = get_addon_element(gManagerWindow, addon.id);
     ok(addonCard, "Got add-on element: " + addon.id);
 
     is(
-      win.document.l10n.getAttributes(addonCard.addonNameEl).id,
+      doc.l10n.getAttributes(addonCard.addonNameEl).id,
       "addon-name-disabled",
       "The addon name should include a disabled postfix"
     );
 
     let updatesBtn = addonCard.querySelector("[action=update-check]");
     is_element_visible(updatesBtn, "Check for Updates action is visible");
     let cardMessage = addonCard.querySelector("message-bar.addon-card-message");
     is_element_hidden(cardMessage, "Warning notification is hidden");
 
-    await switchView(win, "plugin");
+    await gCategoryUtilities.openType("plugin");
   }
+}
 
-  await closeView(win);
-});
-
-add_task(async function testNotInstalled() {
-  let win = await loadInitialView("plugin");
-
+async function testNotInstalled() {
   for (let addon of gMockAddons) {
     gPrefs.setBoolPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id),
       true
     );
-    let item = getAddonCard(win, addon.id);
+    let item = get_addon_element(gManagerWindow, addon.id);
     Assert.ok(item, "Got add-on element:" + addon.id);
 
     let warningMessageBar = await BrowserTestUtils.waitForCondition(() => {
       return item.querySelector("message-bar.addon-card-message[type=warning]");
     }, "Wait for the addon card message to be updated");
 
     is_element_visible(warningMessageBar, "Warning notification is visible");
 
@@ -199,106 +209,90 @@ add_task(async function testNotInstalled
       "panel-item[action=always-activate]"
     );
     ok(
       alwaysActivate.hasAttribute("checked"),
       "Plugin state should be always-activate"
     );
     pluginOptions.querySelector("panel-list").open = false;
   }
-
-  await closeView(win);
-});
+}
 
-add_task(async function testNotInstalledDetails() {
-  let win = await loadInitialView("plugin");
-
+async function testNotInstalledDetails() {
   for (let addon of gMockAddons) {
-    await openDetailsView(win, addon.id);
+    await openDetailsView(addon.id);
 
-    const addonCard = getAddonCard(win, addon.id);
+    const addonCard = get_addon_element(gManagerWindow, addon.id);
     let el = addonCard.querySelector("[action=update-check]");
     is_element_visible(el, "Check for Updates action is visible");
 
     let warningMessageBar = await BrowserTestUtils.waitForCondition(() => {
       return addonCard.querySelector(
         "message-bar.addon-card-message[type=warning]"
       );
     }, "Wait for the addon card message to be updated");
     is_element_visible(warningMessageBar, "Warning notification is visible");
 
-    await switchView(win, "plugin");
+    await gCategoryUtilities.openType("plugin");
   }
+}
 
-  await closeView(win);
-});
-
-add_task(async function testInstalled() {
-  let win = await loadInitialView("plugin");
-
+async function testInstalled() {
   for (let addon of gMockAddons) {
     gPrefs.setIntPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_LAST_UPDATE, addon.id),
       TEST_DATE.getTime()
     );
     gPrefs.setBoolPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_AUTOUPDATE, addon.id),
       false
     );
     gPrefs.setCharPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id),
       "1.2.3.4"
     );
 
-    let item = getAddonCard(win, addon.id);
+    let item = get_addon_element(gManagerWindow, addon.id);
     Assert.ok(item, "Got add-on element.");
 
     is(item.parentNode.getAttribute("section"), "0", "Should be enabled");
     // Open the options menu (needed to check the disabled buttons).
     const pluginOptions = item.querySelector("plugin-options");
     pluginOptions.querySelector("panel-list").open = true;
     const alwaysActivate = pluginOptions.querySelector(
       "panel-item[action=always-activate]"
     );
     ok(
       alwaysActivate.hasAttribute("checked"),
       "Plugin state should be always-activate"
     );
     pluginOptions.querySelector("panel-list").open = false;
   }
-
-  await closeView(win);
-});
+}
 
-add_task(async function testInstalledDetails() {
-  let win = await loadInitialView("plugin");
-
+async function testInstalledDetails() {
   for (let addon of gMockAddons) {
-    await openDetailsView(win, addon.id);
+    await openDetailsView(addon.id);
 
-    let card = getAddonCard(win, addon.id);
+    let card = get_addon_element(gManagerWindow, addon.id);
     ok(card, "Got add-on element:" + addon.id);
 
     is_element_visible(
       card.querySelector("[action=update-check]"),
       "Find updates link is visible"
     );
 
-    await switchView(win, "plugin");
+    await gCategoryUtilities.openType("plugin");
   }
-
-  await closeView(win);
-});
+}
 
-add_task(async function testInstalledGlobalEmeDisabled() {
-  let win = await loadInitialView("plugin");
+async function testInstalledGlobalEmeDisabled() {
   gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, false);
-
   for (let addon of gMockAddons) {
-    let item = getAddonCard(win, addon.id);
+    let item = get_addon_element(gManagerWindow, addon.id);
     if (addon.isEME) {
       is(item.parentNode.getAttribute("section"), "1", "Should be disabled");
       // Open the options menu (needed to check the disabled buttons).
       const pluginOptions = item.querySelector("plugin-options");
       pluginOptions.querySelector("panel-list").open = true;
       const askActivate = pluginOptions.querySelector(
         "panel-item[action=ask-to-activate]"
       );
@@ -306,122 +300,112 @@ add_task(async function testInstalledGlo
         askActivate.shadowRoot.querySelector("button").disabled,
         "ask-to-activate should be disabled"
       );
       pluginOptions.querySelector("panel-list").open = false;
     } else {
       Assert.ok(item, "Got add-on element.");
     }
   }
+  gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true);
+}
 
-  gPrefs.setBoolPref(GMPScope.GMPPrefs.KEY_EME_ENABLED, true);
-  await closeView(win);
-});
-
-add_task(async function testPreferencesButton() {
+async function testPreferencesButton() {
   let prefValues = [
     { enabled: false, version: "" },
     { enabled: false, version: "1.2.3.4" },
     { enabled: true, version: "" },
     { enabled: true, version: "1.2.3.4" },
   ];
 
   for (let preferences of prefValues) {
-    info(
+    dump(
       "Testing preferences button with pref settings: " +
-        JSON.stringify(preferences)
+        JSON.stringify(preferences) +
+        "\n"
     );
     for (let addon of gMockAddons) {
-      let win = await loadInitialView("plugin");
+      await close_manager(gManagerWindow);
+      gManagerWindow = await open_manager();
+      gCategoryUtilities = new CategoryUtilities(gManagerWindow);
       gPrefs.setCharPref(
         getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VERSION, addon.id),
         preferences.version
       );
       gPrefs.setBoolPref(
         getKey(GMPScope.GMPPrefs.KEY_PLUGIN_ENABLED, addon.id),
         preferences.enabled
       );
 
-      let item = getAddonCard(win, addon.id);
+      await gCategoryUtilities.openType("plugin");
+      let item = get_addon_element(gManagerWindow, addon.id);
 
       // Open the options menu (needed to check the more options action is enabled).
       const pluginOptions = item.querySelector("plugin-options");
       pluginOptions.querySelector("panel-list").open = true;
       const moreOptions = pluginOptions.querySelector(
         "panel-item[action=expand]"
       );
       ok(
         !moreOptions.shadowRoot.querySelector("button").disabled,
         "more options action should be enabled"
       );
       moreOptions.click();
 
-      await waitForViewLoad(win);
-
-      item = getAddonCard(win, addon.id);
-      ok(item, "The right view is loaded");
-
-      await closeView(win);
+      await wait_for_view_load(gManagerWindow);
     }
   }
-});
+}
 
-add_task(async function testUpdateButton() {
+async function testUpdateButton() {
   gPrefs.clearUserPref(GMPScope.GMPPrefs.KEY_UPDATE_LAST_CHECK);
 
   let originalInstallManager = GMPScope.GMPInstallManager;
   Object.defineProperty(GMPScope, "GMPInstallManager", {
     value: MockGMPInstallManager,
     writable: true,
     enumerable: true,
     configurable: true,
   });
 
-  let win = await loadInitialView("plugin");
-
   for (let addon of gMockAddons) {
-    let item = getAddonCard(win, addon.id);
+    await gCategoryUtilities.openType("plugin");
+    let item = get_addon_element(gManagerWindow, addon.id);
 
     gInstalledAddonId = "";
     gInstallDeferred = Promise.defer();
 
-    let loaded = waitForViewLoad(win);
     item.querySelector("[action=expand]").click();
-    await loaded;
-    let detail = getAddonCard(win, addon.id);
+    await wait_for_view_load(gManagerWindow);
+    let detail = get_addon_element(gManagerWindow, addon.id);
     detail.querySelector("[action=update-check]").click();
 
     await gInstallDeferred.promise;
     Assert.equal(gInstalledAddonId, addon.id);
-
-    await switchView(win, "plugin");
   }
   Object.defineProperty(GMPScope, "GMPInstallManager", {
     value: originalInstallManager,
     writable: true,
     enumerable: true,
     configurable: true,
   });
+}
 
-  await closeView(win);
-});
-
-add_task(async function testEmeSupport() {
+async function testEmeSupport() {
   for (let addon of gMockAddons) {
     gPrefs.clearUserPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id)
     );
   }
   await GMPScope.GMPProvider.shutdown();
   GMPScope.GMPProvider.startup();
 
-  let win = await loadInitialView("plugin");
-
   for (let addon of gMockAddons) {
-    let item = getAddonCard(win, addon.id);
+    await gCategoryUtilities.openType("plugin");
+    let item = get_addon_element(gManagerWindow, addon.id);
     if (addon.id == GMPScope.EME_ADOBE_ID) {
       if (AppConstants.isPlatformAndVersionAtLeast("win", "6")) {
         Assert.ok(item, "Adobe EME supported, found add-on element.");
       } else {
         Assert.ok(
           !item,
           "Adobe EME not supported, couldn't find add-on element."
         );
@@ -439,23 +423,44 @@ add_task(async function testEmeSupport()
           "Widevine not supported, couldn't find add-on element."
         );
       }
     } else {
       Assert.ok(item, "Found add-on element.");
     }
   }
 
-  await closeView(win);
-
   for (let addon of gMockAddons) {
     gPrefs.setBoolPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_VISIBLE, addon.id),
       true
     );
     gPrefs.setBoolPref(
       getKey(GMPScope.GMPPrefs.KEY_PLUGIN_FORCE_SUPPORTED, addon.id),
       true
     );
   }
   await GMPScope.GMPProvider.shutdown();
   GMPScope.GMPProvider.startup();
+}
+
+async function testCleanupState() {
+  await SpecialPowers.popPrefEnv();
+  await close_manager(gManagerWindow);
+}
+
+// This function run the sequence of all the gmpProvider tests
+// under the same initializeStateOptions (which will enable or disable
+// the HTML about:addons views).
+add_task(async function test_gmpProvider(initializeStateOptions) {
+  await initializeState();
+  await testNotInstalledDisabled();
+  await testNotInstalledDisabledDetails();
+  await testNotInstalled();
+  await testNotInstalledDetails();
+  await testInstalled();
+  await testInstalledDetails();
+  await testInstalledGlobalEmeDisabled();
+  await testPreferencesButton();
+  await testUpdateButton();
+  await testEmeSupport();
+  await testCleanupState();
 });
--- a/toolkit/mozapps/extensions/test/browser/browser_html_detail_view.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_html_detail_view.js
@@ -288,17 +288,17 @@ add_task(async function testDetailOperat
   let loaded = waitForViewLoad(win);
   EventUtils.synthesizeMouseAtCenter(card, { clickCount: 1 }, win);
   await loaded;
 
   card = getAddonCard(doc, id);
   let panel = card.querySelector("panel-list");
 
   // Check button visibility.
-  let disableButton = card.querySelector('[action="toggle-disabled"]');
+  let disableButton = panel.querySelector('[action="toggle-disabled"]');
   ok(!disableButton.hidden, "The disable button is visible");
 
   let removeButton = panel.querySelector('[action="remove"]');
   ok(!removeButton.hidden, "The remove button is visible");
 
   let separator = panel.querySelector("panel-item-separator:last-of-type");
   ok(separator.hidden, "The separator is hidden");
 
@@ -645,29 +645,30 @@ add_task(async function testMinimalExten
 add_task(async function testDefaultTheme() {
   let win = await loadInitialView("theme");
   let doc = win.document;
 
   // The list card.
   let card = getAddonCard(doc, DEFAULT_THEME_ID);
   ok(!card.hasAttribute("expanded"), "The list card is not expanded");
 
+  // Make sure the preview is hidden.
   let preview = card.querySelector(".card-heading-image");
   ok(preview, "There is a preview");
-  ok(!preview.hidden, "The preview is visible");
-
+  is(preview.hidden, true, "The preview is hidden");
   let loaded = waitForViewLoad(win);
   card.querySelector('[action="expand"]').click();
   await loaded;
 
   card = getAddonCard(doc, DEFAULT_THEME_ID);
 
+  // Make sure the preview is hidden.
   preview = card.querySelector(".card-heading-image");
   ok(preview, "There is a preview");
-  ok(!preview.hidden, "The preview is visible");
+  is(preview.hidden, true, "The preview is hidden");
 
   // Check all the deck buttons are hidden.
   assertDeckHeadingHidden(card.details.tabGroup);
 
   let rows = getDetailRows(card);
 
   // Author.
   let author = rows.shift();
@@ -1141,33 +1142,38 @@ add_task(async function testEmptyMoreOpt
   let moreOptionsButton = card.querySelector(".more-options-button");
   ok(!moreOptionsButton.hidden, "The more options button is visible");
 
   let loaded = waitForViewLoad(win);
   enabledItems[0].click();
   await loaded;
 
   card = getAddonCard(doc, DEFAULT_THEME_ID);
-  let toggleDisabledButton = card.querySelector('[action="toggle-disabled"]');
   enabledItems = card.options.visibleItems;
   is(enabledItems.length, 0, "There are no enabled items");
   moreOptionsButton = card.querySelector(".more-options-button");
   ok(moreOptionsButton.hidden, "The more options button is now hidden");
-  ok(toggleDisabledButton.hidden, "The disable button is hidden");
 
-  // Switch themes, the menu should be hidden, but enable button should appear.
+  // Switch themes, this should show the menu again.
   let darkTheme = await AddonManager.getAddonByID(DARK_THEME_ID);
   let updated = BrowserTestUtils.waitForEvent(card, "update");
   await darkTheme.enable();
   await updated;
 
-  ok(moreOptionsButton.hidden, "The more options button is still hidden");
-  ok(!toggleDisabledButton.hidden, "The enable button is visible");
+  enabledItems = card.options.visibleItems;
+  is(enabledItems.length, 1, "There is one item visible");
+  is(
+    enabledItems[0].getAttribute("action"),
+    "toggle-disabled",
+    "Enable is the item"
+  );
+  ok(!moreOptionsButton.hidden, "The more options button is now visible");
 
   updated = BrowserTestUtils.waitForEvent(card, "update");
-  await toggleDisabledButton.click();
+  await enabledItems[0].click();
   await updated;
 
-  ok(moreOptionsButton.hidden, "The more options button is hidden");
-  ok(toggleDisabledButton.hidden, "The disable button is hidden");
+  enabledItems = card.options.visibleItems;
+  is(enabledItems.length, 0, "There are no items visible");
+  ok(moreOptionsButton.hidden, "The more options button is hidden again");
 
   await closeView(win);
 });
--- a/toolkit/mozapps/extensions/test/browser/browser_html_list_view.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_html_list_view.js
@@ -101,43 +101,38 @@ add_task(async function testExtensionLis
   ok(card, "The card is in the enabled section");
 
   // Check the properties of the card.
   is(card.addonNameEl.textContent, "Test extension", "The name is set");
   let icon = card.querySelector(".addon-icon");
   ok(icon.src.endsWith("/test-icon.png"), "The icon is set");
 
   // Disable the extension.
-  let disableToggle = card.querySelector('[action="toggle-disabled"]');
-  ok(disableToggle.checked, "The disable toggle is checked");
+  let disableButton = card.querySelector('[action="toggle-disabled"]');
   is(
-    doc.l10n.getAttributes(disableToggle).id,
-    "disable-addon-button-label",
-    "The toggle has the disable label"
+    doc.l10n.getAttributes(disableButton).id,
+    "disable-addon-button",
+    "The button has the disable label"
   );
-  ok(disableToggle.getAttribute("aria-label"), "There's an aria-label");
-  ok(!disableToggle.hidden, "The toggle is visible");
 
   let disabled = BrowserTestUtils.waitForEvent(list, "move");
-  disableToggle.click();
+  disableButton.click();
   await disabled;
   is(
     card.parentNode,
     disabledSection,
     "The card is now in the disabled section"
   );
 
   // The disable button is now enable.
-  ok(!disableToggle.checked, "The disable toggle is unchecked");
   is(
-    doc.l10n.getAttributes(disableToggle).id,
-    "enable-addon-button-label",
+    doc.l10n.getAttributes(disableButton).id,
+    "enable-addon-button",
     "The button has the enable label"
   );
-  ok(disableToggle.getAttribute("aria-label"), "There's an aria-label");
 
   // Remove the add-on.
   let removeButton = card.querySelector('[action="remove"]');
   is(
     doc.l10n.getAttributes(removeButton).id,
     "remove-addon-button",
     "The button has the remove label"
   );
@@ -361,21 +356,20 @@ add_task(async function testMouseSupport
   );
   ok(panel.open, "The panel is now open");
 
   await closeView(win);
   await extension.unload();
 });
 
 add_task(async function testKeyboardSupport() {
-  let id = "test@mochi.test";
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
       name: "Test extension",
-      applications: { gecko: { id } },
+      applications: { gecko: { id: "test@mochi.test" } },
     },
     useAddonManager: "temporary",
   });
   await extension.startup();
 
   let win = await loadInitialView("extension");
   let doc = win.document;
 
@@ -396,70 +390,73 @@ add_task(async function testKeyboardSupp
   // Focus the more options menu button.
   let moreOptionsButton = card.querySelector('[action="more-options"]');
   moreOptionsButton.focus();
   isFocused(moreOptionsButton, "The more options button is focused");
 
   // Test opening and closing the menu.
   let moreOptionsMenu = card.querySelector("panel-list");
   let expandButton = moreOptionsMenu.querySelector('[action="expand"]');
-  let removeButton = card.querySelector('[action="remove"]');
+  let toggleDisableButton = card.querySelector('[action="toggle-disabled"]');
   is(moreOptionsMenu.open, false, "The menu is closed");
   let shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
   space();
   await shown;
   is(moreOptionsMenu.open, true, "The menu is open");
-  isFocused(removeButton, "The remove button is now focused");
+  isFocused(toggleDisableButton, "The disable button is now focused");
+  EventUtils.synthesizeKey("Escape", {});
+  is(moreOptionsMenu.open, false, "The menu is closed");
+  isFocused(moreOptionsButton, "The more options button is focused");
+
+  // Test tabbing out of the menu.
+  space();
+  shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
+  is(moreOptionsMenu.open, true, "The menu is open");
+  await shown;
   tab({ shiftKey: true });
   is(moreOptionsMenu.open, true, "The menu stays open");
   isFocused(expandButton, "The focus has looped to the bottom");
   tab();
   is(moreOptionsMenu.open, true, "The menu stays open");
-  isFocused(removeButton, "The focus has looped to the top");
+  isFocused(toggleDisableButton, "The focus has looped to the top");
 
   let hidden = BrowserTestUtils.waitForEvent(moreOptionsMenu, "hidden");
   EventUtils.synthesizeKey("Escape", {});
   await hidden;
   isFocused(moreOptionsButton, "Escape closed the menu");
 
-  // Disable the add-on.
-  let disableButton = card.querySelector('[action="toggle-disabled"]');
-  tab({ shiftKey: true });
-  isFocused(disableButton, "The disable toggle is focused");
-  is(card.parentNode, enabledSection, "The card is in the enabled section");
+  // Open the menu to test contents.
+  shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
   space();
-  // Wait for the add-on state to change.
-  let [disabledAddon] = await AddonTestUtils.promiseAddonEvent("onDisabled");
-  is(disabledAddon.id, id, "The right add-on was disabled");
-  is(
-    card.parentNode,
-    enabledSection,
-    "The card is still in the enabled section"
-  );
-  isFocused(disableButton, "The disable button is still focused");
-  let moved = BrowserTestUtils.waitForEvent(list, "move");
-  // Click outside the list to clear any focus.
-  EventUtils.synthesizeMouseAtCenter(
-    doc.querySelector(".header-name"),
-    {},
-    win
-  );
-  await moved;
+  is(moreOptionsMenu.open, true, "The menu is open");
+  // Wait for the panel to be shown.
+  await shown;
+
+  // Disable the add-on.
+  isFocused(toggleDisableButton, "The disable button is focused");
+  is(card.parentNode, enabledSection, "The card is in the enabled section");
+  let disabled = BrowserTestUtils.waitForEvent(list, "move");
+  space();
+  await disabled;
+  is(moreOptionsMenu.open, false, "The menu is closed");
   is(
     card.parentNode,
     disabledSection,
-    "The card moved when keyboard focus left the list"
+    "The card is now in the disabled section"
   );
 
+  // Open the menu again.
+  shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
+  isFocused(moreOptionsButton, "The more options button is focused");
+  space();
+  await shown;
+
   // Remove the add-on.
-  moreOptionsButton.focus();
-  shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
-  space();
-  is(moreOptionsMenu.open, true, "The menu is open");
-  await shown;
+  tab();
+  let removeButton = card.querySelector('[action="remove"]');
   isFocused(removeButton, "The remove button is focused");
   let removed = BrowserTestUtils.waitForEvent(list, "remove");
   space();
   await removed;
   is(card.parentNode, null, "The card is no longer on the page");
 
   await extension.unload();
   await closeView(win);
@@ -761,19 +758,18 @@ add_task(async function testSideloadRemo
   ]);
 
   let win = await loadInitialView("extension");
   let doc = win.document;
 
   let card = getCardByAddonId(doc, id);
 
   let moreOptionsPanel = card.querySelector("panel-list");
-  let moreOptionsButton = card.querySelector('[action="more-options"]');
   let panelOpened = BrowserTestUtils.waitForEvent(moreOptionsPanel, "shown");
-  EventUtils.synthesizeMouseAtCenter(moreOptionsButton, {}, win);
+  moreOptionsPanel.show();
   await panelOpened;
 
   // Verify the remove button is visible with a SUMO link.
   let removeButton = card.querySelector('[action="remove"]');
   ok(removeButton.disabled, "Remove is disabled");
   ok(!removeButton.hidden, "Remove is visible");
 
   let sumoLink = removeButton.querySelector("a");
@@ -937,53 +933,42 @@ add_task(async function testDisabledDimm
     useAddonManager: "temporary",
   });
   await extension.startup();
 
   let addon = await AddonManager.getAddonByID(id);
 
   let win = await loadInitialView("extension");
   let doc = win.document;
-  let pageHeader = doc.querySelector("addon-page-header");
-
-  // Ensure there's no focus on the list.
-  EventUtils.synthesizeMouseAtCenter(pageHeader, {}, win);
 
   const checkOpacity = (card, expected, msg) => {
     let { opacity } = card.ownerGlobal.getComputedStyle(card.firstElementChild);
     is(opacity, expected, msg);
   };
   const waitForTransition = card =>
     BrowserTestUtils.waitForEvent(
       card.firstElementChild,
       "transitionend",
       e => e.propertyName === "opacity"
     );
 
   let card = getCardByAddonId(doc, id);
   checkOpacity(card, "1", "The opacity is 1 when enabled");
 
   // Disable the add-on, check again.
-  let list = doc.querySelector("addon-list");
-  let moved = BrowserTestUtils.waitForEvent(list, "move");
   await addon.disable();
-  await moved;
-
-  let disabledSection = getSection(doc, "disabled");
-  is(card.parentNode, disabledSection, "The card is in the disabled section");
   checkOpacity(card, "0.6", "The opacity is dimmed when disabled");
 
   // Click on the menu button, this should un-dim the card.
   let transitionEnded = waitForTransition(card);
-  let moreOptionsButton = card.querySelector(".more-options-button");
-  EventUtils.synthesizeMouseAtCenter(moreOptionsButton, {}, win);
+  card.panel.open = true;
   await transitionEnded;
   checkOpacity(card, "1", "The opacity is 1 when the menu is open");
 
   // Close the menu, opacity should return.
   transitionEnded = waitForTransition(card);
-  EventUtils.synthesizeMouseAtCenter(pageHeader, {}, win);
+  card.panel.open = false;
   await transitionEnded;
   checkOpacity(card, "0.6", "The card is dimmed again");
 
   await closeView(win);
   await extension.unload();
 });
--- a/toolkit/mozapps/extensions/test/browser/browser_updateid.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_updateid.js
@@ -11,18 +11,17 @@ var gCategoryUtilities;
 function getName(item) {
   return item.addonNameEl.textContent;
 }
 
 async function getUpdateButton(item) {
   let button = item.querySelector('[action="install-update"]');
   let panel = button.closest("panel-list");
   let shown = BrowserTestUtils.waitForEvent(panel, "shown");
-  let moreOptionsButton = item.querySelector('[action="more-options"]');
-  EventUtils.synthesizeMouseAtCenter(moreOptionsButton, {}, item.ownerGlobal);
+  panel.show();
   await shown;
   return button;
 }
 
 add_task(async function test_updateid() {
   // Close the existing about:addons tab and unrestier the existing MockProvider
   // instance if a previous failed test has not been able to clear them.
   if (gManagerWindow) {
--- a/toolkit/mozapps/extensions/test/browser/head.js
+++ b/toolkit/mozapps/extensions/test/browser/head.js
@@ -1632,48 +1632,41 @@ function assertAboutAddonsTelemetryEvent
       filters.methods
         ? filters.methods.includes(actual)
         : ABOUT_ADDONS_METHODS.has(actual),
     object: "aboutAddons",
   });
 }
 
 /* HTML view helpers */
-async function loadInitialView(type, opts) {
+async function loadInitialView(type) {
   // Force the first page load to be the view we want.
   let viewId = type == "discover" ? "discover/" : `list/${type}`;
   Services.prefs.setCharPref(PREF_UI_LASTCATEGORY, `addons://${viewId}`);
 
   let managerWindow = await open_manager(null);
 
   let browser = managerWindow.document.getElementById("html-view-browser");
   let win = browser.contentWindow;
-  if (!opts || !opts.withAnimations) {
-    win.document.body.setAttribute("skip-animations", "");
-  }
   win.managerWindow = managerWindow;
   return win;
 }
 
 function waitForViewLoad(win) {
   return wait_for_view_load(win.managerWindow, undefined, true);
 }
 
 function closeView(win) {
   return close_manager(win.managerWindow);
 }
 
 function switchView(win, type) {
   return new CategoryUtilities(win.managerWindow).openType(type);
 }
 
-function isCategoryVisible(win, type) {
-  return new CategoryUtilities(win.managerWindow).isTypeVisible(type);
-}
-
 function mockPromptService() {
   let { prompt } = Services;
   let promptService = {
     // The prompt returns 1 for cancelled and 0 for accepted.
     _response: 1,
     QueryInterface: ChromeUtils.generateQI([Ci.nsIPromptService]),
     confirmEx: () => promptService._response,
   };