Bug 1481286 - Use a custom element to add/remove command updater. r=bz
authorBrendan Dahl <bdahl@mozilla.com>
Tue, 07 Aug 2018 09:01:54 -0700
changeset 430623 fc0dcbca21b57768a0bcd3aee60ed496318e9574
parent 430622 8de32e539a2c0499acef9cb7324c831b46eb3e91
child 430624 271ad78ecd803a2baf59be86975aad3084fa1bd9
push id106207
push userbdahl@mozilla.com
push dateWed, 08 Aug 2018 16:02:16 +0000
treeherdermozilla-inbound@271ad78ecd80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs1481286
milestone63.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 1481286 - Use a custom element to add/remove command updater. r=bz Create a "commandset" custom element that performs the job of adding and removing command updaters that XULDocument use to do. Previously, the "commandupdater" attribute was allowed on any element, but in tree it is only every used on "commandset" elements. MozReview-Commit-ID: HUXMG9kx4ft
dom/xul/XULDocument.cpp
dom/xul/nsXULContentUtils.cpp
dom/xul/nsXULContentUtils.h
toolkit/content/widgets/general.js
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -1014,26 +1014,17 @@ XULDocument::AddElementToDocumentPre(Ele
     // called when creating elements from prototypes.
     nsAtom* id = aElement->GetID();
     if (id) {
         // FIXME: Shouldn't BindToTree take care of this?
         nsAutoScriptBlocker scriptBlocker;
         AddToIdTable(aElement, id);
     }
 
-    // 2. If the element is a 'command updater' (i.e., has a
-    // "commandupdater='true'" attribute), then add the element to the
-    // document's command dispatcher
-    if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::commandupdater,
-                              nsGkAtoms::_true, eCaseMatters)) {
-        rv = nsXULContentUtils::SetCommandUpdater(this, aElement);
-        if (NS_FAILED(rv)) return rv;
-    }
-
-    // 3. Check for a broadcaster hookup attribute, in which case
+    // 2. Check for a broadcaster hookup attribute, in which case
     // we'll hook the node up as a listener on a broadcaster.
     bool listener, resolved;
     rv = CheckBroadcasterHookup(aElement, &listener, &resolved);
     if (NS_FAILED(rv)) return rv;
 
     // If it's not there yet, we may be able to defer hookup until
     // later.
     if (listener && !resolved && (mResolutionPhase != nsForwardReference::eDone)) {
@@ -1101,17 +1092,17 @@ XULDocument::RemoveSubtreeFromDocument(n
     // Do a bunch of cleanup to remove an element from the XUL
     // document.
     nsresult rv;
 
     if (aElement->NodeInfo()->Equals(nsGkAtoms::keyset, kNameSpaceID_XUL)) {
         nsXBLService::DetachGlobalKeyHandler(aElement);
     }
 
-    // 1. Remove any children from the document.
+    // Remove any children from the document.
     for (nsIContent* child = aElement->GetLastChild();
          child;
          child = child->GetPreviousSibling()) {
 
         rv = RemoveSubtreeFromDocument(child);
         if (NS_FAILED(rv))
             return rv;
     }
@@ -1120,25 +1111,17 @@ XULDocument::RemoveSubtreeFromDocument(n
     // AddElementToDocumentPre().
     nsAtom* id = aElement->GetID();
     if (id) {
         // FIXME: Shouldn't UnbindFromTree take care of this?
         nsAutoScriptBlocker scriptBlocker;
         RemoveFromIdTable(aElement, id);
     }
 
-    // 3. If the element is a 'command updater', then remove the
-    // element from the document's command dispatcher.
-    if (aElement->AttrValueIs(kNameSpaceID_None, nsGkAtoms::commandupdater,
-                              nsGkAtoms::_true, eCaseMatters)) {
-        rv = mCommandDispatcher->RemoveCommandUpdater(aElement);
-        if (NS_FAILED(rv)) return rv;
-    }
-
-    // 4. Remove the element from our broadcaster map, since it is no longer
+    // Remove the element from our broadcaster map, since it is no longer
     // in the document.
     nsCOMPtr<Element> broadcaster, listener;
     nsAutoString attribute, broadcasterID;
     rv = FindBroadcaster(aElement, getter_AddRefs(listener),
                          broadcasterID, attribute, getter_AddRefs(broadcaster));
     if (rv == NS_FINDBROADCASTER_FOUND) {
         RemoveBroadcastListenerFor(*broadcaster, *listener, attribute);
     }
--- a/dom/xul/nsXULContentUtils.cpp
+++ b/dom/xul/nsXULContentUtils.cpp
@@ -81,53 +81,8 @@ nsXULContentUtils::FindChildByTag(nsICon
             NS_ADDREF(*aResult = child->AsElement());
             return NS_OK;
         }
     }
 
     *aResult = nullptr;
     return NS_RDF_NO_VALUE; // not found
 }
-
-nsresult
-nsXULContentUtils::SetCommandUpdater(nsIDocument* aDocument, Element* aElement)
-{
-    // Deal with setting up a 'commandupdater'. Pulls the 'events' and
-    // 'targets' attributes off of aElement, and adds it to the
-    // document's command dispatcher.
-    MOZ_ASSERT(aDocument != nullptr, "null ptr");
-    if (! aDocument)
-        return NS_ERROR_NULL_POINTER;
-
-    MOZ_ASSERT(aElement != nullptr, "null ptr");
-    if (! aElement)
-        return NS_ERROR_NULL_POINTER;
-
-    nsresult rv;
-
-    NS_ASSERTION(aDocument->IsXULDocument(), "not a xul document");
-    if (! aDocument->IsXULDocument())
-        return NS_ERROR_UNEXPECTED;
-
-    XULDocument* xuldoc = aDocument->AsXULDocument();
-    nsCOMPtr<nsIDOMXULCommandDispatcher> dispatcher =
-        xuldoc->GetCommandDispatcher();
-    NS_ASSERTION(dispatcher != nullptr, "no dispatcher");
-    if (! dispatcher)
-        return NS_ERROR_UNEXPECTED;
-
-    nsAutoString events;
-    aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::events, events);
-    if (events.IsEmpty())
-        events.Assign('*');
-
-    nsAutoString targets;
-    aElement->GetAttr(kNameSpaceID_None, nsGkAtoms::targets, targets);
-
-    if (targets.IsEmpty())
-        targets.Assign('*');
-
-    rv = dispatcher->AddCommandUpdater(aElement, events, targets);
-    if (NS_FAILED(rv)) return rv;
-
-    return NS_OK;
-}
-
--- a/dom/xul/nsXULContentUtils.h
+++ b/dom/xul/nsXULContentUtils.h
@@ -40,16 +40,13 @@ public:
     Finish();
 
     static nsresult
     FindChildByTag(nsIContent *aElement,
                    int32_t aNameSpaceID,
                    nsAtom* aTag,
                    mozilla::dom::Element** aResult);
 
-    static nsresult
-    SetCommandUpdater(nsIDocument* aDocument, mozilla::dom::Element* aElement);
-
     static nsICollation*
     GetCollation();
 };
 
 #endif // nsXULContentUtils_h__
--- a/toolkit/content/widgets/general.js
+++ b/toolkit/content/widgets/general.js
@@ -43,9 +43,33 @@ class MozDropmarker extends MozXULElemen
       image.classList.add("dropmarker-icon");
       this.appendChild(image);
     }
   }
 }
 
 customElements.define("dropmarker", MozDropmarker);
 
+class MozCommandSet extends MozXULElement {
+  connectedCallback() {
+    if (this.getAttribute("commandupdater")) {
+      let events = this.getAttribute("events");
+      if (events === "") {
+        events = "*";
+      }
+      let targets = this.getAttribute("targets");
+      if (targets === "") {
+        targets = "*";
+      }
+      document.commandDispatcher.addCommandUpdater(this, events, targets);
+    }
+  }
+
+  disconnectedCallback() {
+    if (this.getAttribute("commandupdater")) {
+      document.commandDispatcher.removeCommandUpdater(this);
+    }
+  }
 }
+
+customElements.define("commandset", MozCommandSet);
+
+}