Bug 1554238 - Remove 'richlistitem' and 'category' bindings. r=aswan
authorTim Nguyen <ntim.bugs@gmail.com>
Fri, 19 Jul 2019 20:04:19 +0000
changeset 483563 c6d99b3e8e8751251037107a41900405dc7d2bbc
parent 483562 b7c71380b52eb3c82ba1f792b9a76b7154f51f7c
child 483564 f693512f2155124f2b478215ffa7dbed5e9e9521
push id36322
push userapavel@mozilla.com
push dateSat, 20 Jul 2019 09:48:59 +0000
treeherdermozilla-central@74908c04ec0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaswan
bugs1554238
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1554238 - Remove 'richlistitem' and 'category' bindings. r=aswan Differential Revision: https://phabricator.services.mozilla.com/D38261
toolkit/content/jar.mn
toolkit/content/widgets/richlistbox.js
toolkit/content/widgets/richlistbox.xml
toolkit/mozapps/extensions/content/extensions.css
toolkit/mozapps/extensions/content/extensions.js
toolkit/mozapps/extensions/content/extensions.xml
toolkit/mozapps/extensions/content/extensions.xul
toolkit/mozapps/extensions/jar.mn
toolkit/themes/shared/extensions/extensions.inc.css
--- a/toolkit/content/jar.mn
+++ b/toolkit/content/jar.mn
@@ -63,17 +63,16 @@ toolkit.jar:
    content/global/widgets.css
    content/global/bindings/autocomplete.xml    (widgets/autocomplete.xml)
    content/global/bindings/calendar.js         (widgets/calendar.js)
    content/global/bindings/datekeeper.js       (widgets/datekeeper.js)
    content/global/bindings/datepicker.js       (widgets/datepicker.js)
    content/global/bindings/datetimebox.css     (widgets/datetimebox.css)
    content/global/bindings/general.xml         (widgets/general.xml)
    content/global/bindings/popup.xml           (widgets/popup.xml)
-   content/global/bindings/richlistbox.xml     (widgets/richlistbox.xml)
    content/global/bindings/scrollbox.xml       (widgets/scrollbox.xml)
    content/global/bindings/spinner.js          (widgets/spinner.js)
    content/global/bindings/textbox.xml         (widgets/textbox.xml)
    content/global/bindings/timekeeper.js       (widgets/timekeeper.js)
    content/global/bindings/timepicker.js       (widgets/timepicker.js)
    content/global/elements/autocomplete-popup.js              (widgets/autocomplete-popup.js)
    content/global/elements/autocomplete-richlistitem.js       (widgets/autocomplete-richlistitem.js)
    content/global/elements/browser-custom-element.js          (widgets/browser-custom-element.js)
--- a/toolkit/content/widgets/richlistbox.js
+++ b/toolkit/content/widgets/richlistbox.js
@@ -1042,13 +1042,10 @@
       return this.getAttribute("current") == "true";
     }
   };
 
   MozXULElement.implementCustomInterface(MozElements.MozRichlistitem, [
     Ci.nsIDOMXULSelectControlItemElement,
   ]);
 
-  // Remove documentURI check when new about:addons interface is finished, see 1554238.
-  if (document.documentURI != "about:addons") {
-    customElements.define("richlistitem", MozElements.MozRichlistitem);
-  }
+  customElements.define("richlistitem", MozElements.MozRichlistitem);
 }
deleted file mode 100644
--- a/toolkit/content/widgets/richlistbox.xml
+++ /dev/null
@@ -1,162 +0,0 @@
-<?xml version="1.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/. -->
-
-<!-- This file relies on these specific Chrome/XBL globals -->
-<!-- globals ChromeNodeList -->
-
-<bindings id="richlistboxBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl">
-
-  <binding id="richlistitem"
-           extends="chrome://global/content/bindings/general.xml#basetext">
-    <implementation implements="nsIDOMXULSelectControlItemElement">
-      <field name="selectedByMouseOver">false</field>
-
-      <destructor>
-        <![CDATA[
-          var control = this.control;
-          if (!control)
-            return;
-          // When we are destructed and we are current or selected, unselect ourselves
-          // so that richlistbox's selection doesn't point to something not in the DOM.
-          // We don't want to reset last-selected, so we set _suppressOnSelect.
-          if (this.selected) {
-            var suppressSelect = control._suppressOnSelect;
-            control._suppressOnSelect = true;
-            control.removeItemFromSelection(this);
-            control._suppressOnSelect = suppressSelect;
-          }
-          if (this.current)
-            control.currentItem = null;
-        ]]>
-      </destructor>
-
-      <!-- nsIDOMXULSelectControlItemElement -->
-      <property name="label" readonly="true">
-        <!-- Setter purposely not implemented; the getter returns a
-             concatentation of label text to expose via accessibility APIs -->
-        <getter>
-          <![CDATA[
-            const XULNS =
-              "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-            return Array.from(this.getElementsByTagNameNS(XULNS, "label"),
-                             label => label.value)
-                        .join(" ");
-          ]]>
-        </getter>
-      </property>
-
-      <property name="searchLabel">
-        <getter>
-          <![CDATA[
-            return this.hasAttribute("searchlabel") ?
-                   this.getAttribute("searchlabel") : this.label;
-          ]]>
-        </getter>
-        <setter>
-          <![CDATA[
-            if (val !== null)
-              this.setAttribute("searchlabel", val);
-            else
-              // fall back to the label property (default value)
-              this.removeAttribute("searchlabel");
-            return val;
-          ]]>
-        </setter>
-      </property>
-
-      <!-- nsIDOMXULSelectControlItemElement -->
-      <property name="value" onget="return this.getAttribute('value');"
-                             onset="this.setAttribute('value', val); return val;"/>
-
-      <!-- nsIDOMXULSelectControlItemElement -->
-      <property name="selected" onget="return this.getAttribute('selected') == 'true';">
-        <setter><![CDATA[
-          if (val)
-            this.setAttribute("selected", "true");
-          else
-            this.removeAttribute("selected");
-
-          return val;
-        ]]></setter>
-      </property>
-
-      <!-- nsIDOMXULSelectControlItemElement -->
-      <property name="control">
-        <getter><![CDATA[
-          var parent = this.parentNode;
-          while (parent) {
-            if (parent.localName == "richlistbox")
-              return parent;
-            parent = parent.parentNode;
-          }
-          return null;
-        ]]></getter>
-      </property>
-
-      <property name="current" onget="return this.getAttribute('current') == 'true';">
-        <setter><![CDATA[
-          if (val)
-            this.setAttribute("current", "true");
-          else
-            this.removeAttribute("current");
-          return val;
-        ]]></setter>
-      </property>
-    </implementation>
-
-    <handlers>
-      <!-- If there is no modifier key, we select on mousedown, not
-           click, so that drags work correctly. -->
-      <handler event="mousedown">
-        <![CDATA[
-          var control = this.control;
-          if (!control || control.disabled)
-            return;
-          if ((!event.ctrlKey || (/Mac/.test(navigator.platform) && event.button == 2)) &&
-              !event.shiftKey && !event.metaKey) {
-            if (!this.selected) {
-              control.selectItem(this);
-            }
-            control.currentItem = this;
-          }
-        ]]>
-      </handler>
-
-      <!-- On a click (up+down on the same item), deselect everything
-           except this item. -->
-      <handler event="click" button="0">
-        <![CDATA[
-          var control = this.control;
-          if (!control || control.disabled)
-            return;
-          control._userSelecting = true;
-          if (control.selType != "multiple") {
-            control.selectItem(this);
-          } else if (event.ctrlKey || event.metaKey) {
-            control.toggleItemSelection(this);
-            control.currentItem = this;
-          } else if (event.shiftKey) {
-            control.selectItemRange(null, this);
-            control.currentItem = this;
-          } else {
-            /* We want to deselect all the selected items except what was
-              clicked, UNLESS it was a right-click.  We have to do this
-              in click rather than mousedown so that you can drag a
-              selected group of items */
-
-            // use selectItemRange instead of selectItem, because this
-            // doesn't de- and reselect this item if it is selected
-            control.selectItemRange(this, this);
-          }
-          control._userSelecting = false;
-        ]]>
-      </handler>
-    </handlers>
-  </binding>
-</bindings>
--- a/toolkit/mozapps/extensions/content/extensions.css
+++ b/toolkit/mozapps/extensions/content/extensions.css
@@ -4,20 +4,16 @@
 
 @namespace xhtml "http://www.w3.org/1999/xhtml";
 
 /* HTML link elements do weird things to the layout if they are not hidden */
 xhtml|link {
   display: none;
 }
 
-.category {
-  -moz-binding: url("chrome://mozapps/content/extensions/extensions.xml#category");
-}
-
 .sidebar-footer-button > .text-link {
   margin-top: 0;
   margin-bottom: 0;
 }
 
 
 .text-list {
   white-space: pre-line;
--- a/toolkit/mozapps/extensions/content/extensions.js
+++ b/toolkit/mozapps/extensions/content/extensions.js
@@ -1,14 +1,15 @@
 /* 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/. */
 
 "use strict";
 
+/* import-globals-from ../../../content/customElements.js */
 /* import-globals-from ../../../content/contentAreaUtils.js */
 /* import-globals-from aboutaddonsCommon.js */
 /* globals ProcessingInstruction */
 /* exported loadView */
 
 const { DeferredTask } = ChromeUtils.import(
   "resource://gre/modules/DeferredTask.jsm"
 );
@@ -1326,23 +1327,71 @@ var gCategories = {
       }
     });
   },
 
   shutdown() {
     AddonManager.removeTypeListener(this);
   },
 
+  _defineCustomElement() {
+    class MozCategory extends MozElements.MozRichlistitem {
+      connectedCallback() {
+        if (this.delayConnectedCallback()) {
+          return;
+        }
+        this.textContent = "";
+        this.appendChild(
+          MozXULElement.parseXULToFragment(`
+          <image class="category-icon"/>
+          <label class="category-name" crop="end" flex="1"/>
+          <label class="category-badge"/>
+        `)
+        );
+        this.initializeAttributeInheritance();
+
+        if (!this.hasAttribute("count")) {
+          this.setAttribute("count", 0);
+        }
+      }
+
+      static get inheritedAttributes() {
+        return {
+          ".category-name": "value=name",
+          ".category-badge": "value=count",
+        };
+      }
+
+      set badgeCount(val) {
+        if (this.getAttribute("count") == val) {
+          return;
+        }
+
+        this.setAttribute("count", val);
+      }
+
+      get badgeCount() {
+        return this.getAttribute("count");
+      }
+    }
+
+    customElements.define("addon-category", MozCategory, {
+      extends: "richlistitem",
+    });
+  },
+
   _insertCategory(aId, aName, aView, aPriority, aStartHidden) {
     // If this category already exists then don't re-add it
     if (document.getElementById("category-" + aId)) {
       return;
     }
 
-    var category = document.createXULElement("richlistitem");
+    var category = document.createXULElement("richlistitem", {
+      is: "addon-category",
+    });
     category.setAttribute("id", "category-" + aId);
     category.setAttribute("value", aView);
     category.setAttribute("class", "category");
     category.setAttribute("name", aName);
     category.setAttribute("tooltiptext", aName);
     category.setAttribute("priority", aPriority);
     category.setAttribute("hidden", aStartHidden);
 
@@ -1500,16 +1549,20 @@ var gCategories = {
   setBadge(aId, aCount) {
     let item = this.get(aId);
     if (item) {
       item.badgeCount = aCount;
     }
   },
 };
 
+// This needs to be defined before the XUL is parsed because some of the
+// categories are in the XUL markup.
+gCategories._defineCustomElement();
+
 var gHeader = {
   _search: null,
   _dest: "",
 
   initialize() {
     this._search = document.getElementById("header-search");
 
     this._search.addEventListener("command", function(aEvent) {
deleted file mode 100644
--- a/toolkit/mozapps/extensions/content/extensions.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.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/. -->
-
-
-<!DOCTYPE page [
-<!ENTITY % extensionsDTD SYSTEM "chrome://mozapps/locale/extensions/extensions.dtd">
-%extensionsDTD;
-]>
-
-<!-- import-globals-from extensions.js -->
-
-<bindings id="addonBindings"
-          xmlns="http://www.mozilla.org/xbl"
-          xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-          xmlns:xbl="http://www.mozilla.org/xbl"
-          xmlns:html="http://www.w3.org/1999/xhtml">
-
-
-  <!-- Category item - an item in the category list. -->
-  <binding id="category"
-           extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
-    <content align="center">
-      <xul:image anonid="icon" class="category-icon"/>
-      <xul:label anonid="name" class="category-name" crop="end" flex="1" xbl:inherits="value=name"/>
-      <xul:label anonid="badge" class="category-badge" xbl:inherits="value=count"/>
-    </content>
-
-    <implementation>
-      <constructor><![CDATA[
-        if (!this.hasAttribute("count"))
-          this.setAttribute("count", 0);
-      ]]></constructor>
-
-      <property name="badgeCount">
-        <getter><![CDATA[
-          return this.getAttribute("count");
-        ]]></getter>
-        <setter><![CDATA[
-          if (this.getAttribute("count") == val)
-            return;
-
-          this.setAttribute("count", val);
-          var event = document.createEvent("Events");
-          event.initEvent("CategoryBadgeUpdated", true, true);
-          this.dispatchEvent(event);
-        ]]></setter>
-      </property>
-    </implementation>
-  </binding>
-</bindings>
--- a/toolkit/mozapps/extensions/content/extensions.xul
+++ b/toolkit/mozapps/extensions/content/extensions.xul
@@ -24,17 +24,17 @@
       role="application" windowtype="Addons:Manager">
 
   <xhtml:link rel="shortcut icon"
               href="chrome://mozapps/skin/extensions/extensionGeneric-16.svg"/>
   <linkset>
     <xhtml:link rel="localization" href="branding/brand.ftl"/>
     <xhtml:link rel="localization" href="toolkit/about/aboutAddons.ftl"/>
   </linkset>
-  
+
   <script src="chrome://global/content/contentAreaUtils.js"/>
   <script src="chrome://mozapps/content/extensions/aboutaddonsCommon.js"/>
   <script src="chrome://mozapps/content/extensions/extensions.js"/>
   <script src="chrome://mozapps/content/extensions/abuse-report-frame.js"/>
 
   <popupset>
     <menulist popuponly="true" id="ContentSelectDropdown" hidden="true">
       <menupopup rolluponmousewheel="true"
@@ -89,26 +89,29 @@
 
   <stack id="main-page-stack" flex="1">
   <hbox id="main-page-content" flex="1">
     <vbox id="category-box">
       <!-- category list -->
       <richlistbox id="categories" flex="1">
         <richlistitem id="category-discover" value="addons://discover/"
                       class="category"
+                      is="addon-category"
                       data-l10n-id="extensions-view-discopane"
                       data-l10n-attrs="name"
                       priority="1000"/>
         <richlistitem id="category-availableUpdates" value="addons://updates/available"
                       class="category"
+                      is="addon-category"
                       data-l10n-id="extensions-view-available-updates"
                       data-l10n-attrs="name"
                       hidden="true"/>
         <richlistitem id="category-recentUpdates" value="addons://updates/recent"
                       class="category"
+                      is="addon-category"
                       data-l10n-id="extensions-view-recent-updates"
                       data-l10n-attrs="name"
                       priority="101000"
                       hidden="true"/>
       </richlistbox>
 
       <spacer flex="1"/>
 
--- a/toolkit/mozapps/extensions/jar.mn
+++ b/toolkit/mozapps/extensions/jar.mn
@@ -6,17 +6,16 @@ toolkit.jar:
 % content mozapps %content/mozapps/
   content/mozapps/extensions/shortcuts.html                     (content/shortcuts.html)
   content/mozapps/extensions/shortcuts.css                      (content/shortcuts.css)
   content/mozapps/extensions/shortcuts.js                       (content/shortcuts.js)
 #ifndef MOZ_FENNEC
 * content/mozapps/extensions/extensions.xul                     (content/extensions.xul)
   content/mozapps/extensions/extensions.css                     (content/extensions.css)
   content/mozapps/extensions/extensions.js                      (content/extensions.js)
-  content/mozapps/extensions/extensions.xml                     (content/extensions.xml)
   content/mozapps/extensions/blocklist.xul                      (content/blocklist.xul)
   content/mozapps/extensions/blocklist.js                       (content/blocklist.js)
   content/mozapps/extensions/pluginPrefs.xul                    (content/pluginPrefs.xul)
   content/mozapps/extensions/pluginPrefs.js                     (content/pluginPrefs.js)
   content/mozapps/extensions/OpenH264-license.txt               (content/OpenH264-license.txt)
   content/mozapps/extensions/aboutaddons.html                   (content/aboutaddons.html)
   content/mozapps/extensions/aboutaddons.js                     (content/aboutaddons.js)
   content/mozapps/extensions/aboutaddonsCommon.js               (content/aboutaddonsCommon.js)
--- a/toolkit/themes/shared/extensions/extensions.inc.css
+++ b/toolkit/themes/shared/extensions/extensions.inc.css
@@ -159,16 +159,20 @@ button.warning {
 
 /*** category selector ***/
 
 #categories {
   /* Make room for outlines */
   padding: 1px;
 }
 
+#categories > .category {
+  -moz-box-align: center;
+}
+
 #categories > .category[disabled] {
   overflow: hidden;
   height: 0;
   min-height: 0;
   opacity: 0;
   transition-property: min-height, opacity;
   transition-duration: 1s, 0.8s;
   -moz-user-input: none; /* Prevents list item selection during animation. */