Bug 1404420: Always enable custom elements in chrome. draft
authorDave Townsend <dtownsend@oxymoronical.com>
Fri, 20 Oct 2017 11:02:33 -0700
changeset 684115 8ca38fd95cc15f60686c7cfcb2f38f01b9ba897b
parent 681661 cc0ed1f8b1e28a90068b20dfe40907b46ab95db3
child 736816 d68d03b61967df359a214f555f6eb616c1786e11
push id85559
push userdtownsend@mozilla.com
push dateFri, 20 Oct 2017 21:17:54 +0000
bugs1404420
milestone58.0a1
Bug 1404420: Always enable custom elements in chrome. MozReview-Commit-ID: CMiLzmp60jA
dom/base/CustomElementRegistry.cpp
dom/base/CustomElementRegistry.h
dom/base/Element.cpp
dom/base/nsDocument.cpp
dom/base/nsNodeUtils.cpp
dom/bindings/Codegen.py
dom/html/nsHTMLContentSink.cpp
dom/xul/nsXULElement.cpp
--- a/dom/base/CustomElementRegistry.cpp
+++ b/dom/base/CustomElementRegistry.cpp
@@ -8,16 +8,17 @@
 
 #include "mozilla/CycleCollectedJSContext.h"
 #include "mozilla/dom/CustomElementRegistryBinding.h"
 #include "mozilla/dom/HTMLElementBinding.h"
 #include "mozilla/dom/WebComponentsBinding.h"
 #include "mozilla/dom/DocGroup.h"
 #include "nsHTMLTags.h"
 #include "jsapi.h"
+#include "nsGlobalWindow.h"
 
 namespace mozilla {
 namespace dom {
 
 void
 CustomElementCallback::Call()
 {
   IgnoredErrorResult rv;
@@ -219,16 +220,44 @@ CustomElementRegistry::CustomElementRegi
   mozilla::HoldJSObjects(this);
 }
 
 CustomElementRegistry::~CustomElementRegistry()
 {
   mozilla::DropJSObjects(this);
 }
 
+bool
+CustomElementRegistry::IsCustomElementEnabled(JSContext* aCx, JSObject* aObject)
+{
+  // This might not be the right object, if there are wrappers. Unwrap if we can.
+  JSObject* obj = js::CheckedUnwrap(aObject);
+  if (obj) {
+    nsGlobalWindow* window = xpc::WindowGlobalOrNull(obj);
+    if (window && window->IsChromeWindow()) {
+      return true;
+    }
+  }
+
+  return nsContentUtils::IsCustomElementsEnabled() ||
+         nsContentUtils::IsWebComponentsEnabled();
+}
+
+bool
+CustomElementRegistry::IsCustomElementEnabled(nsIDocument* aDoc)
+{
+  nsGlobalWindow* window = nsGlobalWindow::Cast(aDoc->GetInnerWindow());
+  if (window && window->IsChromeWindow()) {
+    return true;
+  }
+
+  return nsContentUtils::IsCustomElementsEnabled() ||
+         nsContentUtils::IsWebComponentsEnabled();
+}
+
 CustomElementDefinition*
 CustomElementRegistry::LookupCustomElementDefinition(const nsAString& aLocalName,
                                                      const nsAString* aIs) const
 {
   RefPtr<nsAtom> localNameAtom = NS_Atomize(aLocalName);
   RefPtr<nsAtom> typeAtom = aIs ? NS_Atomize(*aIs) : localNameAtom;
 
   CustomElementDefinition* data = mCustomDefinitions.GetWeak(typeAtom);
--- a/dom/base/CustomElementRegistry.h
+++ b/dom/base/CustomElementRegistry.h
@@ -345,22 +345,18 @@ class CustomElementRegistry final : publ
   // Allow nsDocument to access mCustomDefinitions and mCandidatesMap.
   friend class ::nsDocument;
 
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CustomElementRegistry)
 
 public:
-  static bool IsCustomElementEnabled(JSContext* aCx = nullptr,
-                                     JSObject* aObject = nullptr)
-  {
-    return nsContentUtils::IsCustomElementsEnabled() ||
-           nsContentUtils::IsWebComponentsEnabled();
-  }
+  static bool IsCustomElementEnabled(JSContext* aCx, JSObject* aObject);
+  static bool IsCustomElementEnabled(nsIDocument* aDoc);
 
   explicit CustomElementRegistry(nsPIDOMWindowInner* aWindow);
 
   /**
    * Looking up a custom element definition.
    * https://html.spec.whatwg.org/#look-up-a-custom-element-definition
    */
   CustomElementDefinition* LookupCustomElementDefinition(
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1647,17 +1647,17 @@ Element::BindToTree(nsIDocument* aDocume
     UnsetFlags(NODE_FORCE_XBL_BINDINGS | NODE_NEEDS_FRAME |
                NODE_DESCENDANTS_NEED_FRAMES | ELEMENT_ALL_RESTYLE_FLAGS);
   } else {
     // If we're not in the doc and not in a shadow tree,
     // update our subtree pointer.
     SetSubtreeRootPointer(aParent->SubtreeRoot());
   }
 
-  if (CustomElementRegistry::IsCustomElementEnabled() && IsInComposedDoc()) {
+  if (CustomElementRegistry::IsCustomElementEnabled(OwnerDoc()) && IsInComposedDoc()) {
     // Connected callback must be enqueued whenever a custom element becomes
     // connected.
     if (GetCustomElementData()) {
       nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, this);
     }
   }
 
   // Propagate scoped style sheet tracking bit.
@@ -1977,17 +1977,17 @@ Element::UnbindFromTree(bool aDeep, bool
           /* aNullParent */ false);
       }
     }
 
     document->ClearBoxObjectFor(this);
 
      // Disconnected must be enqueued whenever a connected custom element becomes
      // disconnected.
-    if (CustomElementRegistry::IsCustomElementEnabled() &&
+    if (CustomElementRegistry::IsCustomElementEnabled(OwnerDoc()) &&
         GetCustomElementData()) {
       nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eDisconnected,
                                                this);
     }
   }
 
   // This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
   //  because it has to happen after unsetting the parent pointer, but before
@@ -2656,17 +2656,17 @@ Element::SetAttrAndNotify(int32_t aNames
 
   if (aComposedDocument || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
     RefPtr<nsXBLBinding> binding = GetXBLBinding();
     if (binding) {
       binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
     }
   }
 
-  if (CustomElementRegistry::IsCustomElementEnabled()) {
+  if (CustomElementRegistry::IsCustomElementEnabled(OwnerDoc())) {
     if (CustomElementData* data = GetCustomElementData()) {
       if (CustomElementDefinition* definition =
             nsContentUtils::GetElementDefinitionIfObservingAttr(this,
                                                                 data->mType,
                                                                 aName)) {
         RefPtr<nsAtom> oldValueAtom;
         if (oldValue) {
           oldValueAtom = oldValue->GetAsAtom();
@@ -2960,17 +2960,17 @@ Element::UnsetAttr(int32_t aNameSpaceID,
 
   if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
     RefPtr<nsXBLBinding> binding = GetXBLBinding();
     if (binding) {
       binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
     }
   }
 
-  if (CustomElementRegistry::IsCustomElementEnabled()) {
+  if (CustomElementRegistry::IsCustomElementEnabled(OwnerDoc())) {
     if (CustomElementData* data = GetCustomElementData()) {
       if (CustomElementDefinition* definition =
             nsContentUtils::GetElementDefinitionIfObservingAttr(this,
                                                                 data->mType,
                                                                 aName)) {
         nsAutoString ns;
         nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
 
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -6036,17 +6036,17 @@ nsDocument::CreateElement(const nsAStrin
   }
 
   const nsString* is = nullptr;
   CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
   if (aOptions.IsElementCreationOptions()) {
     const ElementCreationOptions& options =
       aOptions.GetAsElementCreationOptions();
 
-    if (CustomElementRegistry::IsCustomElementEnabled() &&
+    if (CustomElementRegistry::IsCustomElementEnabled(this) &&
         options.mIs.WasPassed()) {
       is = &options.mIs.Value();
     }
 
     // Check 'pseudo' and throw an exception if it's not one allowed
     // with CSS_PSEUDO_ELEMENT_IS_JS_CREATED_NAC.
     if (options.mPseudo.WasPassed()) {
       pseudoType = GetPseudoElementType(options.mPseudo.Value(), rv);
@@ -6101,17 +6101,17 @@ nsDocument::CreateElementNS(const nsAStr
                                             mNodeInfoManager,
                                             nsIDOMNode::ELEMENT_NODE,
                                             getter_AddRefs(nodeInfo));
   if (rv.Failed()) {
     return nullptr;
   }
 
   const nsString* is = nullptr;
-  if (CustomElementRegistry::IsCustomElementEnabled() &&
+  if (CustomElementRegistry::IsCustomElementEnabled(this) &&
       aOptions.IsElementCreationOptions()) {
     const ElementCreationOptions& options = aOptions.GetAsElementCreationOptions();
     if (options.mIs.WasPassed()) {
       is = &options.mIs.Value();
     }
   }
 
   nsCOMPtr<Element> element;
--- a/dom/base/nsNodeUtils.cpp
+++ b/dom/base/nsNodeUtils.cpp
@@ -460,17 +460,18 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
   nsCOMPtr<nsINode> clone;
   if (aClone) {
     nsresult rv = aNode->Clone(nodeInfo, getter_AddRefs(clone), aDeep);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       aError.Throw(rv);
       return nullptr;
     }
 
-    if (CustomElementRegistry::IsCustomElementEnabled() && clone->IsElement()) {
+    if (CustomElementRegistry::IsCustomElementEnabled(nodeInfo->GetDocument()) &&
+        clone->IsElement()) {
       // The cloned node may be a custom element that may require
       // enqueing upgrade reaction.
       Element* elem = clone->AsElement();
       CustomElementDefinition* definition = nullptr;
       RefPtr<nsAtom> tagAtom = nodeInfo->NameAtom();
       if (nsContentUtils::IsCustomElementName(tagAtom)) {
         definition =
           nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
@@ -528,17 +529,17 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
 
     aNode->mNodeInfo.swap(newNodeInfo);
     if (elem) {
       elem->NodeInfoChanged(oldDoc);
     }
 
     nsIDocument* newDoc = aNode->OwnerDoc();
     if (newDoc) {
-      if (CustomElementRegistry::IsCustomElementEnabled()) {
+      if (CustomElementRegistry::IsCustomElementEnabled(newDoc)) {
         // Adopted callback must be enqueued whenever a node’s
         // shadow-including inclusive descendants that is custom.
         Element* element = aNode->IsElement() ? aNode->AsElement() : nullptr;
         if (element) {
           RefPtr<CustomElementData> data = element->GetCustomElementData();
           if (data && data->mState == CustomElementData::State::eCustom) {
             LifecycleAdoptedCallbackArgs args = {
               oldDoc,
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -7816,17 +7816,17 @@ class CGPerSignatureCall(CGThing):
                 CGIfWrapper(CGList(xraySteps),
                             "objIsXray"))
 
         if (idlNode.getExtendedAttribute('CEReactions') is not None and
             not getter):
             cgThings.append(CGGeneric(fill(
                 """
                 Maybe<AutoCEReaction> ceReaction;
-                if (CustomElementRegistry::IsCustomElementEnabled()) {
+                if (CustomElementRegistry::IsCustomElementEnabled(cx, ${obj})) {
                   CustomElementReactionsStack* reactionsStack = GetCustomElementReactionsStack(${obj});
                   if (reactionsStack) {
                     ceReaction.emplace(reactionsStack);
                   }
                 }
                 """, obj=objectName)))
 
         # If this is a method that was generated by a maplike/setlike
--- a/dom/html/nsHTMLContentSink.cpp
+++ b/dom/html/nsHTMLContentSink.cpp
@@ -258,25 +258,26 @@ NS_NewHTMLElement(Element** aResult, alr
   RefPtr<mozilla::dom::NodeInfo> nodeInfo = aNodeInfo;
 
   nsAtom *name = nodeInfo->NameAtom();
 
   NS_ASSERTION(nodeInfo->NamespaceEquals(kNameSpaceID_XHTML),
                "Trying to HTML elements that don't have the XHTML namespace");
 
   int32_t tag = nsHTMLTags::CaseSensitiveAtomTagToId(name);
+  nsIDocument* doc = nodeInfo->GetDocument();
 
   // https://dom.spec.whatwg.org/#concept-create-element
   // We only handle the "synchronous custom elements flag is set" now.
   // For the unset case (e.g. cloning a node), see bug 1319342 for that.
   // Step 4.
   CustomElementDefinition* definition = nullptr;
-  if (CustomElementRegistry::IsCustomElementEnabled()) {
+  if (CustomElementRegistry::IsCustomElementEnabled(doc)) {
     definition =
-      nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
+      nsContentUtils::LookupCustomElementDefinition(doc,
                                                     nodeInfo->LocalName(),
                                                     nodeInfo->NamespaceID(),
                                                     aIs);
   }
 
   // It might be a problem that parser synchronously calls constructor, so filed
   // bug 1378079 to figure out what we should do for parser case.
   if (definition) {
@@ -320,17 +321,17 @@ NS_NewHTMLElement(Element** aResult, alr
         nsContentUtils::EnqueueUpgradeReaction(*aResult, definition);
       }
 
       return NS_OK;
     }
 
     // Step 6.1.
     if (synchronousCustomElements) {
-      DoCustomElementCreate(aResult, nodeInfo->GetDocument(),
+      DoCustomElementCreate(aResult, doc,
                             nodeInfo->NameAtom(),
                             definition->mConstructor, rv);
       if (rv.MaybeSetPendingException(cx)) {
         NS_IF_ADDREF(*aResult = NS_NewHTMLUnknownElement(nodeInfo.forget(), aFromParser));
       }
       return NS_OK;
     }
 
@@ -349,17 +350,17 @@ NS_NewHTMLElement(Element** aResult, alr
   } else {
     *aResult = CreateHTMLElement(tag, nodeInfo.forget(), aFromParser).take();
   }
 
   if (!*aResult) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  if (CustomElementRegistry::IsCustomElementEnabled() &&
+  if (CustomElementRegistry::IsCustomElementEnabled(doc) &&
       (isCustomElementName || aIs)) {
     nsContentUtils::SetupCustomElement(*aResult, aIs);
   }
 
   return NS_OK;
 }
 
 already_AddRefed<nsGenericHTMLElement>
--- a/dom/xul/nsXULElement.cpp
+++ b/dom/xul/nsXULElement.cpp
@@ -293,17 +293,17 @@ NS_NewXULElement(Element** aResult, alre
         return NS_ERROR_NOT_AVAILABLE;
     }
 
     // https://dom.spec.whatwg.org/#concept-create-element
     // We only handle the "synchronous custom elements flag is set" now.
     // For the unset case (e.g. cloning a node), see bug 1319342 for that.
     // Step 4.
     CustomElementDefinition* definition = nullptr;
-    if (CustomElementRegistry::IsCustomElementEnabled()) {
+    if (CustomElementRegistry::IsCustomElementEnabled(doc)) {
         definition =
             nsContentUtils::LookupCustomElementDefinition(nodeInfo->GetDocument(),
                                                           nodeInfo->LocalName(),
                                                           nodeInfo->NamespaceID(),
                                                           aIs);
     }
 
     // It might be a problem that parser synchronously calls constructor, so filed
@@ -375,17 +375,17 @@ NS_NewXULElement(Element** aResult, alre
         return NS_OK;
     }
 
     NS_IF_ADDREF(*aResult = new nsXULElement(nodeInfo.forget()));
     if (!*aResult) {
         return NS_ERROR_OUT_OF_MEMORY;
     }
 
-    if (CustomElementRegistry::IsCustomElementEnabled() &&
+    if (CustomElementRegistry::IsCustomElementEnabled(doc) &&
         (nsContentUtils::IsCustomElementName(name) || aIs)) {
         nsContentUtils::SetupCustomElement(*aResult, aIs);
     }
 
     return NS_OK;
 }
 
 void