Backed out 5 changesets (bug 1488730, bug 1490366, bug 1488727) for bc failures in | toolkit/mozapps/extensions/test/browser/browser_details.js and browser/components/enterprisepolicies/tests/browser/browser_policy_disable_flash_plugin.js CLOSED TREE
authorshindli <shindli@mozilla.com>
Sun, 14 Oct 2018 19:23:09 +0300
changeset 489511 45299a26e20a51f8b616a97024f6204d4210ecd1
parent 489510 9cd889824b1ce9a3de0ab7686332b5b9789be6f0
child 489512 202887e7c361b76d8d3c6f5cb261e71042200ad1
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
bugs1488730, 1490366, 1488727
milestone64.0a1
backs out9cd889824b1ce9a3de0ab7686332b5b9789be6f0
4d076c8654717bb23c89be253f7a1118203e4918
0b8bcd97f254e6db8a023deae4d5e2647c87e30c
4486727805723d44387702ce85f25abbeb8937cf
7e0abd16a50b77fb6437f96b80cafe0b83723c27
Backed out 5 changesets (bug 1488730, bug 1490366, bug 1488727) for bc failures in | toolkit/mozapps/extensions/test/browser/browser_details.js and browser/components/enterprisepolicies/tests/browser/browser_policy_disable_flash_plugin.js CLOSED TREE Backed out changeset 9cd889824b1c (bug 1488730) Backed out changeset 4d076c865471 (bug 1488727) Backed out changeset 0b8bcd97f254 (bug 1490366) Backed out changeset 448672780572 (bug 1490366) Backed out changeset 7e0abd16a50b (bug 1490366)
devtools/client/aboutdebugging/aboutdebugging.css
devtools/client/aboutdebugging/components/addons/Target.js
toolkit/content/widgets/richlistbox.xml
toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/extensions.xml
toolkit/mozapps/extensions/content/extensions.xul
toolkit/mozapps/extensions/test/browser/browser.ini
toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
toolkit/mozapps/extensions/test/browser/browser_bug562854.js
toolkit/mozapps/extensions/test/browser/browser_legacy_pre57.js
toolkit/mozapps/extensions/test/browser/browser_list.js
toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js
toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
toolkit/themes/osx/mozapps/extensions/extensions.css
toolkit/themes/shared/extensions/extensions.inc.css
toolkit/themes/shared/in-content/common.inc.css
toolkit/themes/windows/mozapps/extensions/extensions.css
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -245,90 +245,53 @@ button {
 }
 
 #addons-panel h2 {
   font-size: 1.5rem;
   font-weight: bold;
 }
 
 .addon-target-container {
+  background: #fff;
+  box-shadow: 0 0 1px rgba(0, 0, 0, 0.12);
   list-style-type: none;
-  margin: 16px 0;
+  font-size: 13px;
+  margin: 0 0 8px;
+  padding: 4px 16px;
+  transition: box-shadow 150ms;
 }
 
-.target-card-heading {
-  margin: 0;
+.addon-target-container:hover {
+  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.24);
 }
 
-.target-card-heading {
+.addon-target-container .target {
   align-items: center;
   display: flex;
   margin: 0;
-  padding: 0 0 16px;
+  padding: 16px 0;
+}
 
+.addon-target-name {
   font-size: 15px;
   font-weight: 600;
 }
 
-.target-card-heading-icon {
-  height: 24px;
-  width: 24px;
+.addon-target-actions {
+  border-top: 1px solid rgba(0, 0, 0, 0.2);
+}
+
+.addon-target-container .target-icon {
   margin-inline-end: 16px;
 }
 
-.target-card-actions {
-  border-top: 1px solid rgba(0, 0, 0, 0.2);
-  padding-top: 16px;
-}
-
-.target-card-action-link {
-  background: none;
-  border: none;
-  color: #0087ff;
-  font-size: 13px;
-  /* Use some negative top margin to account for the padding and keep the
-   * button vertically centred. */
-  margin: -4px 0 0 12px;
-  min-width: auto;
-  padding: 4px;
-  transition: color 150ms;
-}
-
-.target-card-action-link:first-of-type {
-  /* Other action buttons will have 12px of margin to space between each other,
-   * but for the first button subtract the start padding to align with the border. */
-  margin-inline-start: -4px;
-}
-
-.target-card-action-link:active,
-.target-card-action-link:hover,
-.target-card-action-link:enabled:hover:active {
-  background: none;
-}
-
-.target-card-action-link:disabled {
-  color: #999;
-  opacity: 1;
-}
-
-.target-card-action-link:enabled:focus,
-.target-card-action-link:enabled:hover {
-  background: none;
-  color: #0052cc;
-  cursor: pointer;
-  text-decoration: underline;
-}
-
-.target-card-action-link:enabled:hover:active {
-  color: #003399;
-  text-decoration: none;
-}
-
-.addon-target-icon.target-icon {
-  margin-inline-end: 16px;
+.addon-target-container .name {
+  align-self: center;
+  font-size: 16px;
+  font-weight: 600;
 }
 
 .addon-target-info {
   display: grid;
   grid-template-columns: 128px 1fr;
 }
 
 .addon-target-info-label {
@@ -343,16 +306,57 @@ button {
 .addon-target-info-content {
   margin: 0;
 }
 
 .addon-target-info-more {
   padding-left: 1ch;
 }
 
+.addon-target-button {
+  background: none;
+  border: none;
+  color: #0087ff;
+  font-size: 13px;
+  margin: 12px;
+  min-width: auto;
+  padding: 4px;
+  transition: color 150ms;
+}
+
+.addon-target-button:active,
+.addon-target-button:hover,
+.addon-target-button:enabled:hover:active {
+  background: none;
+}
+
+.addon-target-button:disabled {
+  color: #999;
+  opacity: 1;
+}
+
+.addon-target-button:enabled:focus,
+.addon-target-button:enabled:hover {
+  background: none;
+  color: #0052cc;
+  cursor: pointer;
+  text-decoration: underline;
+}
+
+.addon-target-button:enabled:hover:active {
+  color: #003399;
+  text-decoration: none;
+}
+
+.addon-target-button:first-of-type {
+  /* Subtract the start padding so the button is still a bigger click target but
+   * lines up with the icon. */
+  margin-inline-start: -4px;
+}
+
 .addon-target-messages {
   border-bottom: 1px solid rgba(0, 0, 0, 0.2);
   margin-bottom: 16px;
   padding: 0 0 12px 0;
 }
 
 .addon-target-message {
   list-style-type: none;
--- a/devtools/client/aboutdebugging/components/addons/Target.js
+++ b/devtools/client/aboutdebugging/components/addons/Target.js
@@ -204,49 +204,49 @@ class AddonTarget extends Component {
       throw new Error("Error reloading addon " + target.addonID + ": " + e.message);
     }
   }
 
   render() {
     const { target, debugDisabled } = this.props;
 
     return dom.li(
-      { className: "card addon-target-container", "data-addon-id": target.addonID },
-      dom.div({ className: "target-card-heading target" },
+      { className: "addon-target-container", "data-addon-id": target.addonID },
+      dom.div({ className: "target" },
         dom.img({
-          className: "target-icon addon-target-icon",
+          className: "target-icon",
           role: "presentation",
           src: target.icon
         }),
         dom.span(
           { className: "target-name addon-target-name", title: target.name },
           target.name)
       ),
       showMessages(target),
       dom.dl(
         { className: "addon-target-info" },
         ...filePathForTarget(target),
         ...addonIDforTarget(target),
         ...internalIDForTarget(target),
       ),
-      dom.div({className: "target-card-actions"},
+      dom.div({className: "addon-target-actions"},
         dom.button({
-          className: "target-card-action-link debug-button addon-target-button",
+          className: "debug-button addon-target-button",
           onClick: this.debug,
           disabled: debugDisabled,
         }, Strings.GetStringFromName("debug")),
         target.temporarilyInstalled
           ? dom.button({
-            className: "target-card-action-link reload-button addon-target-button",
+            className: "reload-button addon-target-button",
             onClick: this.reload,
           }, Strings.GetStringFromName("reload"))
           : null,
         target.temporarilyInstalled
           ? dom.button({
-            className: "target-card-action-link uninstall-button addon-target-button",
+            className: "uninstall-button addon-target-button",
             onClick: this.uninstall,
           }, Strings.GetStringFromName("remove"))
           : null,
       ),
     );
   }
 }
 
--- a/toolkit/content/widgets/richlistbox.xml
+++ b/toolkit/content/widgets/richlistbox.xml
@@ -883,20 +883,16 @@
         ]]>
       </handler>
 
       <handler event="focus">
         <![CDATA[
           if (this.getRowCount() > 0) {
             if (this.currentIndex == -1) {
               this.currentIndex = this.getIndexOfFirstVisibleRow();
-              let currentItem = this.getItemAtIndex(this.currentIndex);
-              if (currentItem) {
-                this.selectItem(currentItem);
-              }
             } else {
               this.currentItem._fireEvent("DOMMenuItemActive");
             }
           }
           this._lastKeyTime = 0;
         ]]>
       </handler>
 
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.dtd
@@ -1,14 +1,14 @@
 <!-- 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/. -->
 <!ENTITY addons.windowTitle                   "Add-ons Manager">
 
-<!ENTITY search.placeholder3                  "Search addons.mozilla.org">
+<!ENTITY search.placeholder2                  "Search on addons.mozilla.org">
 <!ENTITY search.buttonlabel                   "Search">
 <!-- LOCALIZATION NOTE (search.commandkey):
      The search command key should match findOnCmd.commandkey from browser.dtd -->
 <!ENTITY search.commandkey                    "f">
 
 <!ENTITY loading.label                        "Loading…">
 <!ENTITY listEmpty.installed.label            "You don’t have any add-ons of this type installed">
 <!ENTITY listEmpty.availableUpdates.label     "No updates found">
--- a/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
+++ b/toolkit/locales/en-US/chrome/mozapps/extensions/extensions.properties
@@ -102,17 +102,8 @@ type.dictionary.name=Dictionaries
 type.service.name=Services
 type.legacy.name=Legacy Extensions
 type.unsupported.name=Unsupported
 
 #LOCALIZATION NOTE(legacyWarning.description) %S is the brandShortName
 legacyWarning.description=Missing something? Some extensions are no longer supported by %S.
 #LOCALIZATION NOTE(legacyThemeWarning.description) %S is the brandShortName
 legacyThemeWarning.description=Missing something? Some themes are no longer supported by %S.
-
-listHeading.extension=Manage your extensions
-listHeading.theme=Manage your themes
-listHeading.plugin=Manage your plugins
-listHeading.locale=Manage your languages
-listHeading.dictionary=Manage your dictionaries
-
-searchLabel.extension=Find more extensions
-searchLabel.theme=Find more themes
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -120,16 +120,24 @@ function initialize(event) {
   let viewCommandSet = document.getElementById("viewCommandSet");
   viewCommandSet.addEventListener("commandupdate", function(event) {
     gViewController.updateCommands();
   });
   viewCommandSet.addEventListener("command", function(event) {
     gViewController.doCommand(event.target.id);
   });
 
+  let detailScreenshot = document.getElementById("detail-screenshot");
+  detailScreenshot.addEventListener("load", function(event) {
+    this.removeAttribute("loading");
+  });
+  detailScreenshot.addEventListener("error", function(event) {
+    this.setAttribute("loading", "error");
+  });
+
   let addonPage = document.getElementById("addons-page");
   addonPage.addEventListener("dragenter", function(event) {
     gDragDrop.onDragOver(event);
   });
   addonPage.addEventListener("dragover", function(event) {
     gDragDrop.onDragOver(event);
   });
   addonPage.addEventListener("drop", function(event) {
@@ -273,28 +281,16 @@ function isDiscoverEnabled() {
 
   if (!XPINSTALL_ENABLED) {
     return false;
   }
 
   return true;
 }
 
-function setSearchLabel(type) {
-  let searchLabel = document.getElementById("search-label");
-  if (type == "extension" || type == "theme") {
-    searchLabel
-      .textContent = gStrings.ext.GetStringFromName(`searchLabel.${type}`);
-    searchLabel.hidden = false;
-  } else {
-    searchLabel.textContent = "";
-    searchLabel.hidden = true;
-  }
-}
-
 /**
  * Obtain the main DOMWindow for the current context.
  */
 function getMainWindow() {
   return window.docShell.rootTreeItem.domWindow;
 }
 
 function getBrowserElement() {
@@ -1472,17 +1468,17 @@ function shouldShowVersionNumber(aAddon)
     return !/@personas\.mozilla\.org$/.test(aAddon.id);
 
   return true;
 }
 
 function createItem(aObj, aIsInstall) {
   let item = document.createXULElement("richlistitem");
 
-  item.setAttribute("class", "addon addon-view card");
+  item.setAttribute("class", "addon addon-view");
   item.setAttribute("name", aObj.name);
   item.setAttribute("type", aObj.type);
 
   if (aIsInstall) {
     item.mInstall = aObj;
 
     if (aObj.state != AddonManager.STATE_INSTALLED) {
       item.setAttribute("status", "installing");
@@ -2387,24 +2383,16 @@ var gListView = {
 
     if (!(aType in AddonManager.addonTypes))
       throw Components.Exception("Attempting to show unknown type " + aType, Cr.NS_ERROR_INVALID_ARG);
 
     this._type = aType;
     this.node.setAttribute("type", aType);
     this.showEmptyNotice(false);
 
-    try {
-      document.getElementById("list-view-heading-name")
-        .textContent = gStrings.ext.GetStringFromName(`listHeading.${aType}`);
-      setSearchLabel(aType);
-    } catch (e) {
-      // In tests we sometimes render this view with a type we don't support, that's fine.
-    }
-
     this._listBox.textContent = "";
 
     if (aType == "plugin") {
       navigator.plugins.refresh(false);
     }
 
     getAddonsAndInstalls(aType, (aAddonsList, aInstallsList) => {
       if (gViewController && aRequest != gViewController.currentViewRequest)
@@ -2593,18 +2581,16 @@ var gDetailView = {
     AddonManager.removeManagerListener(this);
   },
 
   onUpdateModeChanged() {
     this.onPropertyChanged(["applyBackgroundUpdates"]);
   },
 
   _updateView(aAddon, aIsRemote, aScrollToPreferences) {
-    setSearchLabel(aAddon.type);
-
     AddonManager.addManagerListener(this);
     this.clearLoading();
 
     this._addon = aAddon;
     gEventManager.registerAddonListener(this, aAddon.id);
     gEventManager.registerInstallListener(this);
 
     this.node.setAttribute("type", aAddon.type);
@@ -2629,16 +2615,34 @@ var gDetailView = {
     var version = document.getElementById("detail-version");
     if (shouldShowVersionNumber(aAddon)) {
       version.hidden = false;
       version.value = aAddon.version;
     } else {
       version.hidden = true;
     }
 
+    var screenshotbox = document.getElementById("detail-screenshot-box");
+    var screenshot = document.getElementById("detail-screenshot");
+    if (aAddon.screenshots && aAddon.screenshots.length > 0) {
+      if (aAddon.screenshots[0].thumbnailURL) {
+        screenshot.src = aAddon.screenshots[0].thumbnailURL;
+        screenshot.width = aAddon.screenshots[0].thumbnailWidth;
+        screenshot.height = aAddon.screenshots[0].thumbnailHeight;
+      } else {
+        screenshot.src = aAddon.screenshots[0].url;
+        screenshot.width = aAddon.screenshots[0].width;
+        screenshot.height = aAddon.screenshots[0].height;
+      }
+      screenshot.setAttribute("loading", "true");
+      screenshotbox.hidden = false;
+    } else {
+      screenshotbox.hidden = true;
+    }
+
     var desc = document.getElementById("detail-desc");
     desc.textContent = aAddon.description;
 
     var fullDesc = document.getElementById("detail-fulldesc");
     if (aAddon.getFullDescription) {
       fullDesc.textContent = "";
       fullDesc.append(aAddon.getFullDescription(document));
       fullDesc.hidden = false;
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ b/toolkit/mozapps/extensions/content/extensions.xml
@@ -620,33 +620,41 @@
                 <xul:spacer flex="5000"/> <!-- Necessary to make the name crop -->
               </xul:hbox>
             <xul:label anonid="date-updated" class="date-updated"
                        unknown="&addon.unknownDate;"/>
           </xul:hbox>
 
           <xul:hbox class="advancedinfo-container" flex="1">
             <xul:vbox class="description-outer-container" flex="1">
+              <xul:hbox class="description-container">
+                <xul:label anonid="description" class="description" crop="end" flex="1"/>
+                <xul:button anonid="details-btn" class="details button-link"
+                            label="&addon.details.label;"
+                            tooltiptext="&addon.details.tooltip;"
+                            oncommand="document.getBindingParent(this).showInDetailView();"/>
+                <xul:spacer flex="5000"/> <!-- Necessary to make the description crop -->
+              </xul:hbox>
+              <xul:vbox anonid="relnotes-container" class="relnotes-container">
+                <xul:label class="relnotes-header" value="&addon.releaseNotes.label;"/>
+                <xul:label anonid="relnotes-loading" value="&addon.loadingReleaseNotes.label;"/>
+                <xul:label anonid="relnotes-error" hidden="true"
+                           value="&addon.errorLoadingReleaseNotes.label;"/>
+                <xul:vbox anonid="relnotes" class="relnotes"/>
+              </xul:vbox>
               <xul:hbox class="relnotes-toggle-container">
                 <xul:button anonid="relnotes-toggle-btn" class="relnotes-toggle"
                             hidden="true" label="&cmd.showReleaseNotes.label;"
                             tooltiptext="&cmd.showReleaseNotes.tooltip;"
                             showlabel="&cmd.showReleaseNotes.label;"
                             showtooltip="&cmd.showReleaseNotes.tooltip;"
                             hidelabel="&cmd.hideReleaseNotes.label;"
                             hidetooltip="&cmd.hideReleaseNotes.tooltip;"
                             oncommand="document.getBindingParent(this).toggleReleaseNotes();"/>
               </xul:hbox>
-              <xul:vbox anonid="relnotes-container" class="relnotes-container">
-                <xul:label class="relnotes-header" value="&addon.releaseNotes.label;"/>
-                <xul:label anonid="relnotes-loading" value="&addon.loadingReleaseNotes.label;"/>
-                <xul:label anonid="relnotes-error" hidden="true"
-                           value="&addon.errorLoadingReleaseNotes.label;"/>
-                <xul:vbox anonid="relnotes" class="relnotes"/>
-              </xul:vbox>
             </xul:vbox>
           </xul:hbox>
         </xul:vbox>
         <xul:vbox class="status-control-wrapper">
           <xul:hbox class="status-container">
             <xul:hbox anonid="checking-update" hidden="true">
               <xul:image class="spinner"/>
               <xul:label value="&addon.checkingForUpdates.label;"/>
@@ -781,16 +789,20 @@
       </field>
       <field name="_icon">
         document.getAnonymousElementByAttribute(this, "anonid", "icon");
       </field>
       <field name="_dateUpdated">
         document.getAnonymousElementByAttribute(this, "anonid",
                                                 "date-updated");
       </field>
+      <field name="_description">
+        document.getAnonymousElementByAttribute(this, "anonid",
+                                                "description");
+      </field>
       <field name="_stateMenulist">
         document.getAnonymousElementByAttribute(this, "anonid",
                                                 "state-menulist");
       </field>
       <field name="_askToActivateMenuitem">
         document.getAnonymousElementByAttribute(this, "anonid",
                                                 "ask-to-activate-menuitem");
       </field>
@@ -902,16 +914,21 @@
           this.setAttribute("name", aAddon.name);
 
           var iconURL = AddonManager.getPreferredIconURL(aAddon, 32, window);
           if (iconURL)
             this._icon.src = iconURL;
           else
             this._icon.src = "";
 
+          if (this.mAddon.description)
+            this._description.value = this.mAddon.description;
+          else
+            this._description.hidden = true;
+
           let legacyWarning = legacyExtensionsEnabled && !this.mAddon.install &&
             isLegacyExtension(this.mAddon);
           this.setAttribute("legacy", legacyWarning);
           document.getAnonymousElementByAttribute(this, "anonid", "legacy").href = SUPPORT_URL + "webextensions";
 
           if (!("applyBackgroundUpdates" in this.mAddon) ||
               (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DISABLE ||
                (this.mAddon.applyBackgroundUpdates == AddonManager.AUTOUPDATE_DEFAULT &&
@@ -1483,19 +1500,28 @@
         <body><![CDATA[
             this._updateState();
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="click" button="0"><![CDATA[
-        if (!["button", "checkbox"].includes(event.originalTarget.localName) &&
-            !event.originalTarget.classList.contains("text-link")) {
-          this.showInDetailView();
+        switch (event.detail) {
+        case 1:
+          // Prevent double-click where the UI changes on the first click
+          this._lastClickTarget = event.originalTarget;
+          break;
+        case 2:
+          if (event.originalTarget.localName != "button" &&
+              !event.originalTarget.classList.contains("text-link") &&
+              event.originalTarget == this._lastClickTarget) {
+            this.showInDetailView();
+          }
+          break;
         }
       ]]></handler>
     </handlers>
   </binding>
 
 
   <!-- Addon - uninstalled - An uninstalled addon that can be re-installed. -->
   <binding id="addon-uninstalled"
--- a/toolkit/mozapps/extensions/content/extensions.xul
+++ b/toolkit/mozapps/extensions/content/extensions.xul
@@ -210,149 +210,86 @@
           </vbox>
           <browser id="discover-browser" type="content" flex="1"
                    disablehistory="true"/>
         </deck>
 
         <!-- container for views with the search/tools header -->
         <vbox id="headered-views" flex="1">
           <!-- main header -->
-          <hbox id="header">
-            <hbox id="header-inner" align="center">
-              <button id="show-all-extensions" hidden="true"
-                      label="&showAllExtensions.button.label;"
-                      command="cmd_showAllExtensions"/>
-              <spacer flex="1"/>
-              <hbox id="updates-container" align="center">
-                <image class="spinner"/>
-                <label id="updates-noneFound" hidden="true"
-                       value="&updates.noneFound.label;"/>
-                <button id="updates-manualUpdatesFound-btn" class="button-link"
-                        hidden="true" label="&updates.manualUpdatesFound.label;"
-                        command="cmd_goToAvailableUpdates"/>
-                <label id="updates-progress" hidden="true"
-                       value="&updates.updating.label;"/>
-                <label id="updates-installed" hidden="true"
-                       value="&updates.installed.label;"/>
-                <label id="updates-downloaded" hidden="true"
-                       value="&updates.downloaded.label;"/>
-                <button id="updates-restart-btn" class="button-link" hidden="true"
-                        label="&updates.restart.label;"
-                        command="cmd_restartApp"/>
-              </hbox>
-              <button id="show-disabled-unsigned-extensions" hidden="true"
-                      class="warning"
-                      label="&showUnsignedExtensions.button.label;"
-                      command="cmd_showUnsignedExtensions"/>
-              <toolbarbutton id="header-utils-btn" class="header-button" type="menu"
-                             tooltiptext="&toolsMenu.tooltip;">
-                <menupopup id="utils-menu">
-                  <menuitem id="utils-updateNow"
-                            label="&updates.checkForUpdates.label;"
-                            accesskey="&updates.checkForUpdates.accesskey;"
-                            command="cmd_findAllUpdates"/>
-                  <menuitem id="utils-viewUpdates"
-                            label="&updates.viewUpdates.label;"
-                            accesskey="&updates.viewUpdates.accesskey;"
-                            command="cmd_goToRecentUpdates"/>
-                  <menuseparator id="utils-installFromFile-separator"/>
-                  <menuitem id="utils-installFromFile"
-                            label="&installAddonFromFile.label;"
-                            accesskey="&installAddonFromFile.accesskey;"
-                            command="cmd_installFromFile"/>
-                  <menuitem id="utils-debugAddons"
-                            label="&debugAddons.label;"
-                            accesskey="&debugAddons.accesskey;"
-                            command="cmd_debugAddons"/>
-                  <menuseparator/>
-                  <menuitem id="utils-autoUpdateDefault"
-                            label="&updates.updateAddonsAutomatically.label;"
-                            accesskey="&updates.updateAddonsAutomatically.accesskey;"
-                            type="checkbox" autocheck="false"
-                            command="cmd_toggleAutoUpdateDefault"/>
-                  <menuitem id="utils-resetAddonUpdatesToAutomatic"
-                            label="&updates.resetUpdatesToAutomatic.label;"
-                            accesskey="&updates.resetUpdatesToAutomatic.accesskey;"
-                            command="cmd_resetAddonAutoUpdate"/>
-                  <menuitem id="utils-resetAddonUpdatesToManual"
-                            label="&updates.resetUpdatesToManual.label;"
-                            accesskey="&updates.resetUpdatesToManual.accesskey;"
-                            command="cmd_resetAddonAutoUpdate"/>
-                </menupopup>
-              </toolbarbutton>
-              <textbox id="header-search" type="search" searchbutton="true"
-                       searchbuttonlabel="&search.buttonlabel;"
-                       placeholder="&search.placeholder2;" maxlength="100"/>
+          <hbox id="header" align="center">
+            <button id="show-all-extensions" hidden="true"
+                    label="&showAllExtensions.button.label;"
+                    command="cmd_showAllExtensions"/>
+            <spacer flex="1"/>
+            <hbox id="updates-container" align="center">
+              <image class="spinner"/>
+              <label id="updates-noneFound" hidden="true"
+                     value="&updates.noneFound.label;"/>
+              <button id="updates-manualUpdatesFound-btn" class="button-link"
+                      hidden="true" label="&updates.manualUpdatesFound.label;"
+                      command="cmd_goToAvailableUpdates"/>
+              <label id="updates-progress" hidden="true"
+                     value="&updates.updating.label;"/>
+              <label id="updates-installed" hidden="true"
+                     value="&updates.installed.label;"/>
+              <label id="updates-downloaded" hidden="true"
+                     value="&updates.downloaded.label;"/>
+              <button id="updates-restart-btn" class="button-link" hidden="true"
+                      label="&updates.restart.label;"
+                      command="cmd_restartApp"/>
             </hbox>
+            <button id="show-disabled-unsigned-extensions" hidden="true"
+                    class="warning"
+                    label="&showUnsignedExtensions.button.label;"
+                    command="cmd_showUnsignedExtensions"/>
+            <toolbarbutton id="header-utils-btn" class="header-button" type="menu"
+                           tooltiptext="&toolsMenu.tooltip;">
+              <menupopup id="utils-menu">
+                <menuitem id="utils-updateNow"
+                          label="&updates.checkForUpdates.label;"
+                          accesskey="&updates.checkForUpdates.accesskey;"
+                          command="cmd_findAllUpdates"/>
+                <menuitem id="utils-viewUpdates"
+                          label="&updates.viewUpdates.label;"
+                          accesskey="&updates.viewUpdates.accesskey;"
+                          command="cmd_goToRecentUpdates"/>
+                <menuseparator id="utils-installFromFile-separator"/>
+                <menuitem id="utils-installFromFile"
+                          label="&installAddonFromFile.label;"
+                          accesskey="&installAddonFromFile.accesskey;"
+                          command="cmd_installFromFile"/>
+                <menuitem id="utils-debugAddons"
+                          label="&debugAddons.label;"
+                          accesskey="&debugAddons.accesskey;"
+                          command="cmd_debugAddons"/>
+                <menuseparator/>
+                <menuitem id="utils-autoUpdateDefault"
+                          label="&updates.updateAddonsAutomatically.label;"
+                          accesskey="&updates.updateAddonsAutomatically.accesskey;"
+                          type="checkbox" autocheck="false"
+                          command="cmd_toggleAutoUpdateDefault"/>
+                <menuitem id="utils-resetAddonUpdatesToAutomatic"
+                          label="&updates.resetUpdatesToAutomatic.label;"
+                          accesskey="&updates.resetUpdatesToAutomatic.accesskey;"
+                          command="cmd_resetAddonAutoUpdate"/>
+                <menuitem id="utils-resetAddonUpdatesToManual"
+                          label="&updates.resetUpdatesToManual.label;"
+                          accesskey="&updates.resetUpdatesToManual.accesskey;"
+                          command="cmd_resetAddonAutoUpdate"/>
+              </menupopup>
+            </toolbarbutton>
+            <textbox id="header-search" type="search" searchbutton="true"
+                     searchbuttonlabel="&search.buttonlabel;"
+                     placeholder="&search.placeholder2;" maxlength="100"/>
           </hbox>
 
           <deck id="headered-views-content" flex="1" selectedIndex="0">
             <!-- list view -->
             <vbox id="list-view" flex="1" class="view-pane" align="stretch" tabindex="0">
-              <hbox id="list-view-heading">
-                <hbox class="list-view-heading-inner">
-                  <label id="list-view-heading-name" class="header-name" flex="1"/>
-
-                  <hbox id="updates-container" align="center">
-                    <image class="spinner"/>
-                    <label id="updates-noneFound" hidden="true"
-                           value="&updates.noneFound.label;"/>
-                    <button id="updates-manualUpdatesFound-btn" class="button-link"
-                            hidden="true" label="&updates.manualUpdatesFound.label;"
-                            command="cmd_goToAvailableUpdates"/>
-                    <label id="updates-progress" hidden="true"
-                           value="&updates.updating.label;"/>
-                    <label id="updates-installed" hidden="true"
-                           value="&updates.installed.label;"/>
-                    <label id="updates-downloaded" hidden="true"
-                           value="&updates.downloaded.label;"/>
-                    <button id="updates-restart-btn" class="button-link" hidden="true"
-                            label="&updates.restart.label;"
-                            command="cmd_restartApp"/>
-                  </hbox>
-
-                  <toolbarbutton id="header-utils-btn" class="header-button" type="menu"
-                                 tooltiptext="&toolsMenu.tooltip;">
-                    <menupopup id="utils-menu">
-                      <menuitem id="utils-updateNow"
-                                label="&updates.checkForUpdates.label;"
-                                accesskey="&updates.checkForUpdates.accesskey;"
-                                command="cmd_findAllUpdates"/>
-                      <menuitem id="utils-viewUpdates"
-                                label="&updates.viewUpdates.label;"
-                                accesskey="&updates.viewUpdates.accesskey;"
-                                command="cmd_goToRecentUpdates"/>
-                      <menuseparator id="utils-installFromFile-separator"/>
-                      <menuitem id="utils-installFromFile"
-                                label="&installAddonFromFile.label;"
-                                accesskey="&installAddonFromFile.accesskey;"
-                                command="cmd_installFromFile"/>
-                      <menuitem id="utils-debugAddons"
-                                label="&debugAddons.label;"
-                                accesskey="&debugAddons.accesskey;"
-                                command="cmd_debugAddons"/>
-                      <menuseparator/>
-                      <menuitem id="utils-autoUpdateDefault"
-                                label="&updates.updateAddonsAutomatically.label;"
-                                accesskey="&updates.updateAddonsAutomatically.accesskey;"
-                                type="checkbox" autocheck="false"
-                                command="cmd_toggleAutoUpdateDefault"/>
-                      <menuitem id="utils-resetAddonUpdatesToAutomatic"
-                                label="&updates.resetUpdatesToAutomatic.label;"
-                                accesskey="&updates.resetUpdatesToAutomatic.accesskey;"
-                                command="cmd_resetAddonAutoUpdate"/>
-                      <menuitem id="utils-resetAddonUpdatesToManual"
-                                label="&updates.resetUpdatesToManual.label;"
-                                accesskey="&updates.resetUpdatesToManual.accesskey;"
-                                command="cmd_resetAddonAutoUpdate"/>
-                    </menupopup>
-                  </toolbarbutton>
-                </hbox>
-              </hbox>
-
               <!-- info UI for add-ons that have been disabled for being unsigned -->
               <vbox id="disabled-unsigned-addons-info" hidden="true">
                 <label id="disabled-unsigned-addons-heading" value="&disabledUnsigned.heading;"/>
                 <description>
                   &disabledUnsigned.description.start;<label class="text-link plain" id="find-alternative-addons">&disabledUnsigned.description.findAddonsLink;</label>&disabledUnsigned.description.end;
                 </description>
                 <hbox pack="start"><label class="text-link" id="signing-learn-more">&disabledUnsigned.learnMore;</label></hbox>
                 <description id="signing-dev-info">
@@ -488,17 +425,17 @@
                 <button id="update-selected-btn" hidden="true"
                         label="&updates.updateSelected.label;"
                         tooltiptext="&updates.updateSelected.tooltip;"/>
               </hbox>
               <richlistbox id="updates-list" class="list" flex="1"/>
             </vbox>
 
             <!-- detail view -->
-            <scrollbox id="detail-view" class="view-pane addon-view" orient="vertical" tabindex="0"
+            <scrollbox id="detail-view" flex="1" class="view-pane addon-view" orient="vertical" tabindex="0"
                        role="document">
               <!-- global warnings -->
               <hbox class="global-warning-container global-warning">
                 <hbox class="global-warning-safemode" flex="1" align="center"
                       tooltiptext="&warning.safemode.label;">
                   <image class="warning-icon"/>
                   <label class="global-warning-text" flex="1" crop="end"
                          value="&warning.safemode.label;"/>
@@ -520,28 +457,29 @@
                          value="&warning.updatesecurity.label;"/>
                 </hbox>
                 <button class="button-link global-warning-updatesecurity"
                         label="&warning.updatesecurity.enable.label;"
                         tooltiptext="&warning.updatesecurity.enable.tooltip;"
                         command="cmd_enableUpdateSecurity"/>
                 <spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
               </hbox>
-              <hbox class="detail-view-wrapper">
+              <hbox flex="1">
+                <spacer flex="1"/>
                 <!-- "loading" splash screen -->
                 <vbox class="alert-container">
                   <spacer class="alert-spacer-before"/>
                   <hbox class="alert loading">
                     <image/>
                     <label value="&loading.label;"/>
                   </hbox>
                   <spacer class="alert-spacer-after"/>
                 </vbox>
                 <!-- actual detail view -->
-                <vbox class="detail-view-container" contextmenu="addonitem-popup">
+                <vbox class="detail-view-container" flex="3" contextmenu="addonitem-popup">
                   <vbox id="detail-notifications">
                     <hbox id="warning-container" align="center" class="warning">
                       <image class="warning-icon"/>
                       <label id="detail-warning" flex="1"/>
                       <label id="detail-warning-link" class="text-link"/>
                       <spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
                     </hbox>
                     <hbox id="error-container" align="center" class="error">
@@ -558,39 +496,42 @@
                               command="cmd_restartApp"/>
                       <button id="detail-undo-btn" class="button-link"
                               label="&addon.undoAction.label;"
                               tooltipText="&addon.undoAction.tooltip;"
                               command="cmd_cancelOperation"/>
                       <spacer flex="5000"/> <!-- Necessary to allow the message to wrap -->
                     </hbox>
                   </vbox>
-                  <hbox class="card addon-detail" align="start">
+                  <hbox align="start">
+                    <vbox id="detail-icon-container" align="end">
+                      <image id="detail-icon" class="icon"/>
+                    </vbox>
                     <vbox flex="1">
-                      <hbox align="start">
-                        <vbox id="detail-icon-container" align="end">
-                          <image id="detail-icon" class="icon"/>
+                      <vbox id="detail-summary">
+                        <hbox id="detail-name-container" class="name-container"
+                              align="start">
+                          <label id="detail-name" flex="1"/>
+                          <label id="detail-version"/>
+                          <label id="detail-legacy-warning" class="legacy-warning text-link" value="&addon.legacy.label;"/>
+                          <label class="disabled-postfix" value="&addon.disabled.postfix;"/>
+                          <label class="update-postfix" value="&addon.update.postfix;"/>
+                          <spacer flex="5000"/> <!-- Necessary to allow the name to wrap -->
+                        </hbox>
+                        <label id="detail-creator" class="creator"/>
+                      </vbox>
+                      <hbox id="detail-desc-container" align="start">
+                        <vbox id="detail-screenshot-box" pack="center" hidden="true"> <!-- Necessary to work around bug 394738 -->
+                          <image id="detail-screenshot"/>
                         </vbox>
-                        <vbox id="detail-summary">
-                          <hbox id="detail-name-container" class="name-container"
-                                align="start">
-                            <label id="detail-name" flex="1"/>
-                            <label id="detail-version"/>
-                            <label id="detail-legacy-warning" class="legacy-warning text-link" value="&addon.legacy.label;"/>
-                            <label class="disabled-postfix" value="&addon.disabled.postfix;"/>
-                            <label class="update-postfix" value="&addon.update.postfix;"/>
-                            <spacer flex="5000"/> <!-- Necessary to allow the name to wrap -->
-                          </hbox>
-                          <label id="detail-creator" class="creator"/>
+                        <vbox flex="1">
+                          <description id="detail-desc"/>
+                          <description id="detail-fulldesc"/>
                         </vbox>
                       </hbox>
-                      <vbox id="detail-desc-container" align="start" flex="1">
-                        <description id="detail-desc"/>
-                        <description id="detail-fulldesc"/>
-                      </vbox>
                       <vbox id="detail-contributions">
                         <description id="detail-contrib-description">
                           &detail.contributions.description;
                         </description>
                         <hbox align="center">
                           <spacer flex="1"/>
                           <button id="detail-contrib-btn"
                                   label="&cmd.contribute.label;"
--- a/toolkit/mozapps/extensions/test/browser/browser.ini
+++ b/toolkit/mozapps/extensions/test/browser/browser.ini
@@ -26,16 +26,17 @@ support-files =
   !/toolkit/mozapps/extensions/test/xpinstall/unsigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/amosigned.xpi
   !/toolkit/mozapps/extensions/test/xpinstall/amosigned-restart-required.xpi
 
 [browser_CTP_plugins.js]
 tags = blocklist
 [browser_bug523784.js]
 [browser_bug562797.js]
+[browser_bug562854.js]
 [browser_bug562890.js]
 skip-if = os == 'win' && !debug # Disabled on Windows opt/PGO builds due to intermittent failures (bug 1135866)
 [browser_bug562899.js]
 [browser_bug562992.js]
 [browser_bug567127.js]
 [browser_bug567137.js]
 [browser_bug570760.js]
 skip-if = verify
--- a/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_CTP_plugins.js
@@ -103,17 +103,19 @@ add_task(async function() {
     let testPlugin = content.document.getElementById("test");
     ok(testPlugin, "part7: should have a plugin element in the page");
     let objLoadingContent = testPlugin.QueryInterface(Ci.nsIObjectLoadingContent);
     ok(!objLoadingContent.activated, "part7: plugin should not be activated");
   });
 
   BrowserTestUtils.removeTab(pluginTab);
 
-  EventUtils.synthesizeMouseAtCenter(pluginEl, {}, managerWindow);
+  let details = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
+  is_element_visible(details, "part7: details link should be visible");
+  EventUtils.synthesizeMouseAtCenter(details, {}, managerWindow);
   await BrowserTestUtils.waitForEvent(managerWindow.document, "ViewChanged");
 
   is_element_hidden(enableButton, "part8: detail enable button should be hidden");
   is_element_hidden(disableButton, "part8: detail disable button should be hidden");
   is_element_visible(menu, "part8: detail state menu should be visible");
   is(menu.selectedItem, neverActivateItem, "part8: state menu should have 'Never Activate' selected");
 
   menu.selectedItem = alwaysActivateItem;
@@ -154,16 +156,17 @@ add_task(async function() {
     );
   });
 
   pluginEl = get_addon_element(managerWindow, testPluginId);
   pluginEl.parentNode.ensureElementIsVisible(pluginEl);
   menu = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "state-menulist");
   is(menu.disabled, true, "part12: state menu should be disabled");
 
-  EventUtils.synthesizeMouseAtCenter(pluginEl, {}, managerWindow);
+  details = managerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
+  EventUtils.synthesizeMouseAtCenter(details, {}, managerWindow);
   await BrowserTestUtils.waitForEvent(managerWindow.document, "ViewChanged");
 
   menu = managerWindow.document.getElementById("detail-state-menulist");
   is(menu.disabled, true, "part13: detail state menu should be disabled");
 
   managerWindow.close();
 });
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/extensions/test/browser/browser_bug562854.js
@@ -0,0 +1,123 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+/**
+ * Tests that double-click does not go to detail view if the target is a link or button.
+ */
+
+function test() {
+  requestLongerTimeout(2);
+
+  waitForExplicitFinish();
+
+  var gProvider = new MockProvider();
+  gProvider.createAddons([{
+    id: "test1@tests.mozilla.org",
+    name: "Test add-on 1",
+    description: "foo",
+    operationsRequiringRestart: AddonManager.OP_NEEDS_RESTART_NONE,
+  }]);
+
+  run_next_test();
+}
+
+function end_test() {
+  finish();
+}
+
+function is_in_list(aManager, view) {
+  var doc = aManager.document;
+
+  is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
+  is(get_current_view(aManager).id, "list-view", "Should be on the right view");
+}
+
+function is_in_detail(aManager, view) {
+  var doc = aManager.document;
+
+  is(doc.getElementById("categories").selectedItem.value, view, "Should be on the right category");
+  is(get_current_view(aManager).id, "detail-view", "Should be on the right view");
+}
+
+// Check that double-click does something.
+add_test(async function() {
+  let aManager = await open_manager("addons://list/extension");
+  info("Part 1");
+  is_in_list(aManager, "addons://list/extension");
+
+  var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
+  addon.parentNode.ensureElementIsVisible(addon);
+  EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 1 }, aManager);
+  EventUtils.synthesizeMouseAtCenter(addon, { clickCount: 2 }, aManager);
+
+  aManager = await wait_for_view_load(aManager);
+  info("Part 2");
+  is_in_detail(aManager, "addons://list/extension");
+
+  close_manager(aManager, run_next_test);
+});
+
+// Check that double-click does nothing when over the disable button.
+add_test(async function() {
+  let aManager = await open_manager("addons://list/extension");
+  info("Part 1");
+  is_in_list(aManager, "addons://list/extension");
+
+  var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
+  addon.parentNode.ensureElementIsVisible(addon);
+  EventUtils.synthesizeMouseAtCenter(
+    aManager.document.getAnonymousElementByAttribute(addon, "anonid", "disable-btn"),
+    { clickCount: 1 },
+    aManager
+  );
+  // The disable button is replaced by the enable button when clicked on.
+  EventUtils.synthesizeMouseAtCenter(
+    aManager.document.getAnonymousElementByAttribute(addon, "anonid", "enable-btn"),
+    { clickCount: 2 },
+    aManager
+  );
+
+  aManager = await wait_for_view_load(aManager);
+  info("Part 2");
+  is_in_list(aManager, "addons://list/extension");
+
+  close_manager(aManager, run_next_test);
+});
+
+// Check that double-click does nothing when over the undo button.
+add_test(async function() {
+  let aManager = await open_manager("addons://list/extension");
+  info("Part 1");
+  is_in_list(aManager, "addons://list/extension");
+
+  var addon = get_addon_element(aManager, "test1@tests.mozilla.org");
+  addon.parentNode.ensureElementIsVisible(addon);
+  EventUtils.synthesizeMouseAtCenter(
+    aManager.document.getAnonymousElementByAttribute(addon, "anonid", "remove-btn"),
+    { clickCount: 1 },
+    aManager
+  );
+
+  // The undo button is removed when clicked on.
+  // We need to wait for the UI to catch up.
+  setTimeout(async function() {
+    var target = aManager.document.getAnonymousElementByAttribute(addon, "anonid", "undo-btn");
+    var rect = target.getBoundingClientRect();
+    var addonRect = addon.getBoundingClientRect();
+
+    EventUtils.synthesizeMouse(target, rect.width / 2, rect.height / 2, { clickCount: 1 }, aManager);
+    EventUtils.synthesizeMouse(addon,
+      rect.left - addonRect.left + rect.width / 2,
+      rect.top - addonRect.top + rect.height / 2,
+      { clickCount: 2 },
+      aManager
+    );
+
+    aManager = await wait_for_view_load(aManager);
+    info("Part 2");
+    is_in_list(aManager, "addons://list/extension");
+
+    close_manager(aManager, run_next_test);
+  }, 0);
+});
--- a/toolkit/mozapps/extensions/test/browser/browser_legacy_pre57.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_legacy_pre57.js
@@ -58,17 +58,18 @@ add_task(async function() {
     if (isLegacy) {
       is_element_visible(badge, `Legacy badge is visible for ${name}`);
       is(badge.href, INFO_URL, "Legacy badge link is correct");
     } else {
       is_element_hidden(badge, `Legacy badge is hidden for ${name}`);
     }
 
     // Click down to the details page.
-    EventUtils.synthesizeMouseAtCenter(item, {}, mgrWin);
+    let detailsButton = document.getAnonymousElementByAttribute(item, "anonid", "details-btn");
+    EventUtils.synthesizeMouseAtCenter(detailsButton, {}, mgrWin);
     await new Promise(resolve => wait_for_view_load(mgrWin, resolve));
 
     // And check the badge
     let elements = document.getElementsByClassName("legacy-warning");
     is(elements.length, 1, "Found the legacy-warning element");
     badge = elements[0];
 
     if (isLegacy) {
--- a/toolkit/mozapps/extensions/test/browser/browser_list.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_list.js
@@ -380,16 +380,18 @@ add_task(async function() {
   is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed");
 
   let addon = items["Test add-on replacement"];
   addon.parentNode.ensureElementIsVisible(addon);
   let { name, version } = await get_tooltip_info(addon);
   is(get_node(addon, "name").value, "Test add-on replacement", "Name should be correct");
   is(name, "Test add-on replacement", "Tooltip name should be correct");
   is(version, "2.0", "Tooltip version should be correct");
+  is_element_visible(get_node(addon, "description"), "Description should be visible");
+  is(get_node(addon, "description").value, "A test add-on with a new description", "Description should be correct");
   is_element_hidden(get_class_node(addon, "disabled-postfix"), "Disabled postfix should be hidden");
   is_element_hidden(get_class_node(addon, "update-postfix"), "Update postfix should be hidden");
   is(get_node(addon, "date-updated").value, formatDate(gDate), "Update date should be correct");
 
   is_element_hidden(get_node(addon, "preferences-btn"), "Preferences button should be hidden");
   is_element_hidden(get_node(addon, "enable-btn"), "Enable button should be hidden");
   is_element_visible(get_node(addon, "disable-btn"), "Disable button should be visible");
   is_element_visible(get_node(addon, "remove-btn"), "Remove button should be visible");
@@ -417,33 +419,37 @@ add_task(async function() {
   // Ignore the OSX full keyboard access setting
   Services.prefs.setBoolPref("accessibility.tabfocus_applies_to_xul", false);
 
   let items = get_test_items();
   is(Object.keys(items).length, EXPECTED_ADDONS, "Should be the right number of add-ons installed");
 
   let addon = items["Test add-on 6"];
   addon.parentNode.ensureElementIsVisible(addon);
-  addon.parentNode.focus();
+  EventUtils.synthesizeMouseAtCenter(addon, { }, gManagerWindow);
   is(Services.focus.focusedElement, addon.parentNode, "Focus should have moved to the list");
 
   EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
+  is(Services.focus.focusedElement, get_node(addon, "details-btn"), "Focus should have moved to the more button");
+
+  EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
   is(Services.focus.focusedElement, get_node(addon, "disable-btn"), "Focus should have moved to the disable button");
 
   EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
   is(Services.focus.focusedElement, get_node(addon, "remove-btn"), "Focus should have moved to the remove button");
 
   EventUtils.synthesizeKey("VK_TAB", { }, gManagerWindow);
   ok(!is_node_in_list(Services.focus.focusedElement), "Focus should be outside the list");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
   is(Services.focus.focusedElement, get_node(addon, "remove-btn"), "Focus should have moved to the remove button");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
-  is(Services.focus.focusedElement, get_node(addon, "disable-btn"), "Focus should have moved to the disable button");
+  EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
+  is(Services.focus.focusedElement, get_node(addon, "details-btn"), "Focus should have moved to the more button");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
   is(Services.focus.focusedElement, addon.parentNode, "Focus should have moved to the list");
 
   EventUtils.synthesizeKey("VK_TAB", { shiftKey: true }, gManagerWindow);
   ok(!is_node_in_list(Services.focus.focusedElement), "Focus should be outside the list");
 
   try {
--- a/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_plugin_enabled_state_locked.js
@@ -62,17 +62,19 @@ function checkStateMenu(locked) {
   is_element_visible(selectedMenuItem, "State menu's selected item should be visible.");
 }
 
 function checkStateMenuDetail(locked) {
   Assert.equal(Services.prefs.prefIsLocked(getTestPluginPref()), locked,
     "Preference should be " + (locked === true ? "" : "un") + "locked.");
 
   // open details menu
-  EventUtils.synthesizeMouseAtCenter(gPluginElement, {}, gManagerWindow);
+  let details = gManagerWindow.document.getAnonymousElementByAttribute(gPluginElement, "anonid", "details-btn");
+  is_element_visible(details, "Details link should be visible.");
+  EventUtils.synthesizeMouseAtCenter(details, {}, gManagerWindow);
 
   return new Promise(async resolve => {
     await wait_for_view_load(gManagerWindow);
     let menuList = gManagerWindow.document.getElementById("detail-state-menulist");
     is_element_visible(menuList, "Details state menu should be visible.");
     Assert.equal(menuList.disabled, locked,
       "Details state menu enabled state should be correct.");
     resolve();
--- a/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_pluginprefs.js
@@ -34,17 +34,18 @@ add_test(async function() {
   let testPlugin = await AddonManager.getAddonByID(testPluginId);
   let pluginEl = get_addon_element(gManagerWindow, testPluginId);
   is(pluginEl.mAddon.optionsType, AddonManager.OPTIONS_TYPE_INLINE_BROWSER, "Options should be inline type");
   pluginEl.parentNode.ensureElementIsVisible(pluginEl);
 
   let button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "preferences-btn");
   is_element_visible(button, "Preferences button should be visible");
 
-  EventUtils.synthesizeMouseAtCenter(pluginEl, { clickCount: 1 }, gManagerWindow);
+  button = gManagerWindow.document.getAnonymousElementByAttribute(pluginEl, "anonid", "details-btn");
+  EventUtils.synthesizeMouseAtCenter(button, { clickCount: 1 }, gManagerWindow);
 
   Services.obs.addObserver(async function observer(subject, topic, data) {
     Services.obs.removeObserver(observer, topic);
 
     // Wait for PluginProvider to do its stuff.
     await new Promise(executeSoon);
 
     let doc = gManagerWindow.document.getElementById("addon-options").contentDocument;
--- a/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
+++ b/toolkit/mozapps/extensions/test/browser/browser_uninstalling.js
@@ -235,17 +235,18 @@ add_test(async function() {
   let aAddon = await AddonManager.getAddonByID(ID);
   ok(aAddon.isActive, "Add-on should be active");
   ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
   ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
 
   var item = get_item_in_list(ID, list);
   isnot(item, null, "Should have found the add-on in the list");
 
-  item.click();
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
   await wait_for_view_load(gManagerWindow);
 
   // Test the uninstall.
   return test_uninstall_details(aAddon, ID);
 });
 
 // Tests that uninstalling a restartless add-on from directly loading the
 // details view switches back to the list view and can be undone
@@ -281,17 +282,18 @@ add_test(async function() {
 
   ok(!aAddon.isActive, "Add-on should be inactive");
   ok(!(aAddon.operationsRequiringRestart & AddonManager.OP_NEEDS_RESTART_UNINSTALL), "Add-on should not require a restart to uninstall");
   ok(!(aAddon.pendingOperations & AddonManager.PENDING_UNINSTALL), "Add-on should not be pending uninstall");
 
   var item = get_item_in_list(ID, list);
   isnot(item, null, "Should have found the add-on in the list");
 
-  item.click();
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 1 }, gManagerWindow);
+  EventUtils.synthesizeMouseAtCenter(item, { clickCount: 2 }, gManagerWindow);
   await wait_for_view_load(gManagerWindow);
   is(get_current_view(gManagerWindow).id, "detail-view", "Should be in the detail view");
 
   var button = gDocument.getElementById("detail-uninstall-btn");
   isnot(button, null, "Should have a remove button");
   ok(!button.disabled, "Button should not be disabled");
 
   EventUtils.synthesizeMouseAtCenter(button, { }, gManagerWindow);
--- a/toolkit/themes/osx/mozapps/extensions/extensions.css
+++ b/toolkit/themes/osx/mozapps/extensions/extensions.css
@@ -11,16 +11,17 @@
 .no-auto-hide > .menulist-dropmarker {
   padding-inline-start: 0px !important;
 }
 
 #header-utils-btn {
   list-style-image: url("chrome://mozapps/skin/extensions/utilities.svg");
   -moz-context-properties: fill;
   fill: #424f5a;
+  margin-inline-end: 18px;
 }
 
 #header-utils-btn > .toolbarbutton-menu-dropmarker {
   list-style-image: url("chrome://mozapps/skin/extensions/toolbarbutton-dropmarker.png");
   padding: 0;
   margin-inline-start: 2px;
 }
 
--- a/toolkit/themes/shared/extensions/extensions.inc.css
+++ b/toolkit/themes/shared/extensions/extensions.inc.css
@@ -9,18 +9,18 @@
   padding: 0;
 }
 
 #nav-header {
   min-height: 39px;
 }
 
 .view-pane > .list > scrollbox {
-  padding-right: 24px;
-  padding-left: 24px;
+  padding-right: 48px;
+  padding-left: 48px;
 }
 
 
 /*** global warnings ***/
 
 .global-warning-container {
   overflow-x: hidden;
 }
@@ -221,56 +221,41 @@ button.warning {
 }
 #category-recentUpdates > .category-icon {
   list-style-image: url("chrome://mozapps/skin/extensions/category-recent.svg");
 }
 
 
 /*** header ***/
 
-#header-inner {
-  margin: 20px 4px 4px;
-  width: 692px;
-}
-
-#header-search {
-  margin-top: 0;
-  margin-bottom: 0;
-  min-height: 32px;
-}
-
-#header-search > moz-input-box > .textbox-search-sign {
-  list-style-image: url(chrome://global/skin/icons/search-textbox.svg);
-  margin-inline-end: 5px;
-}
-
-#search-label {
-  margin: 0;
-  margin-inline-end: 4px;
-  margin-bottom: 2px;
+#header {
+  margin-top: 20px;
+  margin-bottom: 20px;
+  margin-right: 48px;
+  margin-left: 48px;
 }
 
 @media (max-width: 600px) {
   #header-search {
     width: 12em;
   }
 }
 
-.list-view-heading-inner {
-  width: 664px;
+.view-header {
+  margin: 0 48px;
+  border-bottom: 1px solid var(--in-content-box-border-color);
 }
 
 #header-utils-btn {
+  height: 30px;
   line-height: 20px;
   border-color: var(--in-content-box-border-color);
   background-color: var(--in-content-page-background);
   padding-right: 10px;
   padding-left: 10px;
-  /* This button is too tall, adding margin-bottom shrinks it. */
-  margin-bottom: 2px;
 }
 
 #header-utils-btn:not([disabled="true"]):active:hover,
 #header-utils-btn[open="true"] {
   padding-bottom: 0px;
   padding-top: 0px;
   background-color: var(--in-content-box-background-active);
 }
@@ -290,22 +275,16 @@ button.warning {
   background-color: #ebebeb;
   cursor: pointer;
 }
 
 .header-button > .toolbarbutton-text {
   display: none;
 }
 
-#list-view-heading {
-  margin-top: 24px;
-  margin-bottom: 16px;
-  margin-inline-start: 28px;
-}
-
 /*** discover view ***/
 
 .discover-spacer-before,
 .discover-spacer-after {
   -moz-box-flex: 1;
 }
 
 #discover-error .alert {
@@ -339,41 +318,63 @@ button.warning {
 
 .list {
   -moz-appearance: none;
   margin: 0;
   border-width: 0 !important;
   background-color: transparent;
 }
 
+.list > scrollbox > .scrollbox-innerbox {
+  border: 1px dotted transparent;
+}
+
+.list:-moz-focusring > scrollbox > .scrollbox-innerbox {
+  border-color: var(--in-content-border-focus);
+}
+
 richlistbox.list > richlistitem.addon {
   color: var(--in-content-text-color);
+  border-bottom: 1px solid var(--in-content-box-border-color);
+  padding: 5px;
   background-origin: border-box;
 }
 
+.addon:not(:only-child):last-child {
+  border-bottom-width: 0;
+}
+
+.details {
+  cursor: pointer;
+  margin: 0;
+  margin-inline-start: 10px;
+}
+
+.icon-container {
+  width: 48px;
+  height: 48px;
+  margin: 3px 7px;
+  -moz-box-align: center;
+  -moz-box-pack: center;
+}
+
 .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/extensionGeneric.svg");
-  max-width: 24px;
-  max-height: 24px;
-  margin-inline-end: 16px;
+  max-width: 32px;
+  max-height: 32px;
 }
 
 .content-inner-container {
   margin-inline-end: 5px;
 }
 
 .addon[active="false"] .icon {
   filter: grayscale(1);
 }
 
-.addon label,
-.addon {
-  cursor: pointer;
-}
-
 .addon-view[type="theme"] .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/themeGeneric.svg");
 }
 
 .addon-view[type="locale"] .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/localeGeneric.svg");
 }
 
@@ -385,17 +386,18 @@ richlistbox.list > richlistitem.addon {
   list-style-image: url("chrome://mozapps/skin/extensions/dictionaryGeneric.svg");
 }
 
 .addon-view[type="experiment"] .icon {
   list-style-image: url("chrome://mozapps/skin/extensions/experimentGeneric.svg");
 }
 
 .name-container {
-  font-weight: 600;
+  font-size: 1.3rem;
+  font-weight: bold;
   -moz-box-align: end;
   -moz-box-flex: 1;
 }
 
 .legacy-warning {
   background-color: #FFE900;
   color: #3E2800;
   padding: 4px 5px 3px;
@@ -418,17 +420,17 @@ richlistbox.list > richlistitem.addon {
   color: #FFF;
 }
 
 #detail-view .legacy-warning {
   margin-top: 0.78rem;
 }
 
 .creator {
-  font-size: 1.2rem;
+  font-weight: bold;
 }
 
 .description-container {
   margin-inline-start: 6px;
   -moz-box-align: center;
   font-size: 1.25rem;
 }
 
@@ -470,17 +472,18 @@ richlistbox.list > richlistitem.addon {
   -moz-box-pack: center;
 }
 
 .relnotes-toggle-container,
 .icon-outer-container {
   -moz-box-pack: start;
 }
 
-.status-container {
+.status-container,
+.control-container {
   -moz-box-pack: end;
 }
 
 .addon-view .warning {
   color: #d8b826;
 }
 
 .addon-view .error {
@@ -551,25 +554,20 @@ richlistbox.list > richlistitem.addon {
 }
 
 .addon-view[pending="disable"],
 .addon-view[pending="uninstall"] {
   --view-highlight-color: #F2F2F2;
 }
 
 .list > .addon[selected] {
-  background-color: var(--in-content-box-background);
-}
-
-.list:focus > .addon[selected] {
-  box-shadow: var(--card-shadow-focus);
-}
-
-.list > .addon {
-  margin: 8px;
+  background-color: var(--in-content-page-background);
+  color: var(--in-content-page-color);
+  padding-inline-start: 1px; /* compensate the 4px border */
+  border-inline-start: solid 4px var(--in-content-border-focus);
 }
 
 #addon-list .addon[active="false"] > .content-container > .content-inner-container {
   color: #999;
 }
 
 #addon-list .addon[active="false"][selected] > .content-container > .content-inner-container {
   color: #777;
@@ -593,67 +591,66 @@ richlistbox.list > richlistitem.addon {
 .addon[status="uninstalled"][selected] {
   background-color: transparent;
 }
 
 
 /*** detail view ***/
 
 #detail-view > .scrollbox-innerbox {
-  margin: 32px;
+  margin-right: 48px;
+  margin-left: 48px;
 }
 
 #detail-view .loading {
   opacity: 0;
 }
 
 #detail-view[loading-extended] .loading {
   opacity: 1;
   transition-property: opacity;
   transition-duration: 1s;
 }
 
 .detail-view-container {
-  width: 664px;
+  padding-inline-end: 2em;
+  padding-bottom: 2em;
+  font-size: 1.25rem;
+  color: #333;
 }
 
 #detail-notifications {
   margin-top: 1em;
   margin-bottom: 2em;
 }
 
-#detail-view:not([notification="warning"]):not([notification="error"]):not([pending]) #detail-notifications {
-  display: none;
-}
-
 #detail-notifications .warning,
 #detail-notifications .pending,
 #detail-notifications .error {
   margin-inline-start: 0;
 }
 
 #detail-icon-container {
   width: 64px;
+  margin-inline-end: 10px;
   margin-top: 6px;
 }
 
 #detail-icon {
-  max-width: 32px;
-  max-height: 32px;
+  max-width: 64px;
+  max-height: 64px;
 }
 
-.name-container > label,
-#detail-creator,
-#detail-name-container > label {
-  margin-inline-start: 0;
+#detail-summary {
+  margin-bottom: 2em;
 }
 
-#detail-controls {
-  margin-inline-start: -4px;
-  margin-inline-end: -4px;
+#detail-name-container {
+  font-size: 2.5rem;
+  font-weight: normal;
 }
 
 #detail-screenshot-box {
   margin-inline-end: 2em;
   background-image: linear-gradient(rgba(255,255,255,.5), transparent);
   background-color: white;
   box-shadow: 0 1px 2px #666;
   border-radius: 2px;
@@ -677,37 +674,21 @@ richlistbox.list > richlistitem.addon {
   }
 }
 
 #detail-screenshot[loading="error"] {
   background-image: url("chrome://global/skin/media/error.png");
 }
 
 #detail-desc-container {
-  line-height: 1.3;
-  margin: 1em 0;
-}
-
-#detail-controls > button {
-  margin-bottom: 0;
-}
-
-.addon.card {
-  max-width: 664px;
-  /* The .addon-control element on the end has 4px of margin, remove it
-   * from the padding to stay balanced. */
-  padding-inline-end: 12px;
-}
-
-.addon-detail.card:hover {
-  box-shadow: none;
+  margin-bottom: 2em;
 }
 
 #detail-desc, #detail-fulldesc {
-  margin-inline-start: 0;
+  margin-inline-start: 6px;
   /* This is necessary to fix layout issues with multi-line descriptions, see
      bug 592712*/
   outline: solid transparent;
   white-space: pre-wrap;
   min-width: 10em;
 }
 
 #detail-fulldesc {
@@ -771,16 +752,20 @@ richlistbox.list > richlistitem.addon {
 .detail-row-complex {
   border-top: 1px solid var(--in-content-box-border-color);
   -moz-box-align: center;
   min-height: 35px;
   line-height: 20px;
   text-shadow: 0 1px 1px #fefffe;
 }
 
+#detail-controls {
+  margin-bottom: 1em;
+}
+
 .inline-options-browser {
   margin-top: 2em;
 }
 
 .preferences-alignment {
   min-height: 30px;
   -moz-box-align: center;
 }
@@ -934,25 +919,16 @@ richlistbox.list > richlistitem.addon {
 
 
 /*** buttons ***/
 
 .addon-control[disabled="true"]:not(.no-auto-hide) {
   display: none;
 }
 
-.addon-control {
-  cursor: default;
-  margin-top: 0;
-  margin-bottom: 0;
-  min-height: auto;
-  min-width: auto;
-  padding: 2px 4px;
-}
-
 .no-auto-hide .addon-control {
   display: block !important;
 }
 
 button.button-link {
   -moz-appearance: none;
   background: transparent;
   border: none;
--- a/toolkit/themes/shared/in-content/common.inc.css
+++ b/toolkit/themes/shared/in-content/common.inc.css
@@ -35,34 +35,23 @@
   --in-content-link-color-active: #003eaa;
   --in-content-link-color-visited: #0a8dff;
   --in-content-primary-button-background: #0a84ff;
   --in-content-primary-button-background-hover: #0060df;
   --in-content-primary-button-background-active: #003EAA;
   --in-content-table-background: #ebebeb;
   --in-content-table-border-dark-color: #d1d1d1;
   --in-content-table-header-background: #0a84ff;
-
-  --blue-50: #0a84ff;
-  --blue-50-a30: rgba(10, 132, 255, 0.3);
   --grey-20: #ededf0;
-  --grey-30: #d7d7db;
-  --grey-60: #4a4a4f;
   --grey-90: #0c0c0d;
   --grey-90-a10: rgba(12, 12, 13, 0.1);
   --grey-90-a20: rgba(12, 12, 13, 0.2);
   --grey-90-a30: rgba(12, 12, 13, 0.3);
   --yellow-50: #ffe900;
   --yellow-90: #3e2800;
-
-  --shadow-10: 0 1px 4px var(--grey-90-a10);
-  --card-shadow: var(--shadow-10);
-  --card-outline-color: var(--grey-30);
-  --card-shadow-hover: var(--card-shadow), 0 0 0 5px var(--card-outline-color);
-  --card-shadow-focus: 0 0 0 2px var(--blue-50), 0 0 0 6px var(--blue-50-a30);
 }
 
 html|html,
 xul|page,
 xul|window {
   font: message-box;
   -moz-appearance: none;
   background-color: var(--in-content-page-background);
@@ -852,29 +841,16 @@ xul|treechildren::-moz-tree-image(select
   background-color: var(--yellow-50);
   color: var(--yellow-90);
 }
 
 .message-bar-warning > .message-bar-icon {
   list-style-image: url("chrome://browser/skin/warning.svg");
 }
 
-.card {
-  background: var(--in-content-box-background);
-  border-radius: 4px;
-  box-shadow: var(--card-shadow);
-  margin: 0 0 8px;
-  padding: 16px;
-  transition: box-shadow 150ms;
-}
-
-.card:hover {
-  box-shadow: var(--card-shadow-hover);
-}
-
 .sidebar-footer-button {
   padding: 1px; /* Adding padding around help label in order to make entire keyboard focusing outline visible */
 }
 
 .sidebar-footer-button > .text-link {
   -moz-box-flex: 1;
   margin-inline-start: 34px;
   margin-inline-end: 0;
--- a/toolkit/themes/windows/mozapps/extensions/extensions.css
+++ b/toolkit/themes/windows/mozapps/extensions/extensions.css
@@ -7,16 +7,17 @@
 :root > * {
   font-size: 1.25em;
 }
 
 #header-utils-btn {
   list-style-image: url("chrome://mozapps/skin/extensions/utilities.svg");
   -moz-context-properties: fill;
   fill: #424f5a;
+  margin-inline-end: 16px;
 }
 
 @media (-moz-windows-default-theme: 0) {
   #header-utils-btn {
     fill: GrayText;
   }
 }