LCOV - code coverage report
Current view: top level - dom/html - HTMLContentElement.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 172 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 37 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/HTMLContentElement.h"
       8             : #include "mozilla/dom/HTMLContentElementBinding.h"
       9             : #include "mozilla/dom/HTMLUnknownElement.h"
      10             : #include "mozilla/dom/NodeListBinding.h"
      11             : #include "mozilla/dom/ShadowRoot.h"
      12             : #include "mozilla/css/StyleRule.h"
      13             : #include "mozilla/GenericSpecifiedValuesInlines.h"
      14             : #include "nsGkAtoms.h"
      15             : #include "nsStyleConsts.h"
      16             : #include "nsIAtom.h"
      17             : #include "nsCSSRuleProcessor.h"
      18             : #include "nsRuleProcessorData.h"
      19             : #include "nsRuleWalker.h"
      20             : #include "nsCSSParser.h"
      21             : #include "nsDocument.h"
      22             : 
      23             : // Expand NS_IMPL_NS_NEW_HTML_ELEMENT(Content) to add check for web components
      24             : // being enabled.
      25             : nsGenericHTMLElement*
      26           0 : NS_NewHTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
      27             :                          mozilla::dom::FromParser aFromParser)
      28             : {
      29             :   // When this check is removed, remove the nsDocument.h and
      30             :   // HTMLUnknownElement.h includes.  Also remove nsINode::IsHTMLContentElement.
      31             :   //
      32             :   // We have to jump through some hoops to be able to produce both NodeInfo* and
      33             :   // already_AddRefed<NodeInfo>& for our callees.
      34           0 :   RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);
      35           0 :   if (!nsDocument::IsWebComponentsEnabled(nodeInfo)) {
      36           0 :     already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget());
      37           0 :     return new mozilla::dom::HTMLUnknownElement(nodeInfoArg);
      38             :   }
      39             : 
      40           0 :   already_AddRefed<mozilla::dom::NodeInfo> nodeInfoArg(nodeInfo.forget());
      41           0 :   return new mozilla::dom::HTMLContentElement(nodeInfoArg);
      42             : }
      43             : 
      44             : using namespace mozilla::dom;
      45             : 
      46           0 : HTMLContentElement::HTMLContentElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
      47           0 :   : nsGenericHTMLElement(aNodeInfo), mValidSelector(true), mIsInsertionPoint(false)
      48             : {
      49           0 : }
      50             : 
      51           0 : HTMLContentElement::~HTMLContentElement()
      52             : {
      53           0 : }
      54             : 
      55           0 : NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLContentElement,
      56             :                                    nsGenericHTMLElement,
      57             :                                    mMatchedNodes)
      58             : 
      59           0 : NS_IMPL_ADDREF_INHERITED(HTMLContentElement, Element)
      60           0 : NS_IMPL_RELEASE_INHERITED(HTMLContentElement, Element)
      61             : 
      62           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(HTMLContentElement)
      63           0 : NS_INTERFACE_MAP_END_INHERITING(nsGenericHTMLElement)
      64             : 
      65           0 : NS_IMPL_ELEMENT_CLONE(HTMLContentElement)
      66             : 
      67             : JSObject*
      68           0 : HTMLContentElement::WrapNode(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
      69             : {
      70           0 :   return HTMLContentElementBinding::Wrap(aCx, this, aGivenProto);
      71             : }
      72             : 
      73             : nsresult
      74           0 : HTMLContentElement::BindToTree(nsIDocument* aDocument,
      75             :                                nsIContent* aParent,
      76             :                                nsIContent* aBindingParent,
      77             :                                bool aCompileEventHandlers)
      78             : {
      79           0 :   RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow();
      80             : 
      81           0 :   nsresult rv = nsGenericHTMLElement::BindToTree(aDocument, aParent,
      82             :                                                  aBindingParent,
      83           0 :                                                  aCompileEventHandlers);
      84           0 :   NS_ENSURE_SUCCESS(rv, rv);
      85             : 
      86           0 :   ShadowRoot* containingShadow = GetContainingShadow();
      87           0 :   if (containingShadow && !oldContainingShadow) {
      88           0 :     nsINode* parentNode = nsINode::GetParentNode();
      89           0 :     while (parentNode && parentNode != containingShadow) {
      90           0 :       if (parentNode->IsHTMLContentElement()) {
      91             :         // Content element in fallback content is not an insertion point.
      92           0 :         return NS_OK;
      93             :       }
      94           0 :       parentNode = parentNode->GetParentNode();
      95             :     }
      96             : 
      97             :     // If the content element is being inserted into a ShadowRoot,
      98             :     // add this element to the list of insertion points.
      99           0 :     mIsInsertionPoint = true;
     100           0 :     containingShadow->AddInsertionPoint(this);
     101           0 :     containingShadow->SetInsertionPointChanged();
     102             :   }
     103             : 
     104           0 :   return NS_OK;
     105             : }
     106             : 
     107             : void
     108           0 : HTMLContentElement::UnbindFromTree(bool aDeep, bool aNullParent)
     109             : {
     110           0 :   RefPtr<ShadowRoot> oldContainingShadow = GetContainingShadow();
     111             : 
     112           0 :   nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
     113             : 
     114           0 :   if (oldContainingShadow && !GetContainingShadow() && mIsInsertionPoint) {
     115           0 :     oldContainingShadow->RemoveInsertionPoint(this);
     116             : 
     117             :     // Remove all the matched nodes now that the
     118             :     // insertion point is no longer an insertion point.
     119           0 :     ClearMatchedNodes();
     120           0 :     oldContainingShadow->SetInsertionPointChanged();
     121             : 
     122           0 :     mIsInsertionPoint = false;
     123             :   }
     124           0 : }
     125             : 
     126             : void
     127           0 : HTMLContentElement::AppendMatchedNode(nsIContent* aContent)
     128             : {
     129           0 :   mMatchedNodes.AppendElement(aContent);
     130           0 :   nsTArray<nsIContent*>& destInsertionPoint = aContent->DestInsertionPoints();
     131           0 :   destInsertionPoint.AppendElement(this);
     132             : 
     133           0 :   if (mMatchedNodes.Length() == 1) {
     134             :     // Fallback content gets dropped so we need to updated fallback
     135             :     // content distribution.
     136           0 :     UpdateFallbackDistribution();
     137             :   }
     138           0 : }
     139             : 
     140             : void
     141           0 : HTMLContentElement::UpdateFallbackDistribution()
     142             : {
     143           0 :   for (nsIContent* child = nsINode::GetFirstChild();
     144           0 :        child;
     145           0 :        child = child->GetNextSibling()) {
     146           0 :     nsTArray<nsIContent*>& destInsertionPoint = child->DestInsertionPoints();
     147           0 :     destInsertionPoint.Clear();
     148           0 :     if (mMatchedNodes.IsEmpty()) {
     149           0 :       destInsertionPoint.AppendElement(this);
     150             :     }
     151             :   }
     152           0 : }
     153             : 
     154             : void
     155           0 : HTMLContentElement::RemoveMatchedNode(nsIContent* aContent)
     156             : {
     157           0 :   mMatchedNodes.RemoveElement(aContent);
     158           0 :   ShadowRoot::RemoveDestInsertionPoint(this, aContent->DestInsertionPoints());
     159             : 
     160           0 :   if (mMatchedNodes.IsEmpty()) {
     161             :     // Fallback content is activated so we need to update fallback
     162             :     // content distribution.
     163           0 :     UpdateFallbackDistribution();
     164             :   }
     165           0 : }
     166             : 
     167             : void
     168           0 : HTMLContentElement::InsertMatchedNode(uint32_t aIndex, nsIContent* aContent)
     169             : {
     170           0 :   mMatchedNodes.InsertElementAt(aIndex, aContent);
     171           0 :   nsTArray<nsIContent*>& destInsertionPoint = aContent->DestInsertionPoints();
     172           0 :   destInsertionPoint.AppendElement(this);
     173             : 
     174           0 :   if (mMatchedNodes.Length() == 1) {
     175             :     // Fallback content gets dropped so we need to updated fallback
     176             :     // content distribution.
     177           0 :     UpdateFallbackDistribution();
     178             :   }
     179           0 : }
     180             : 
     181             : void
     182           0 : HTMLContentElement::ClearMatchedNodes()
     183             : {
     184           0 :   for (uint32_t i = 0; i < mMatchedNodes.Length(); i++) {
     185           0 :     ShadowRoot::RemoveDestInsertionPoint(this, mMatchedNodes[i]->DestInsertionPoints());
     186             :   }
     187             : 
     188           0 :   mMatchedNodes.Clear();
     189             : 
     190           0 :   UpdateFallbackDistribution();
     191           0 : }
     192             : 
     193             : static bool
     194           0 : IsValidContentSelectors(nsCSSSelector* aSelector)
     195             : {
     196           0 :   nsCSSSelector* currentSelector = aSelector;
     197           0 :   while (currentSelector) {
     198             :     // Blacklist invalid selector fragments.
     199           0 :     if (currentSelector->IsPseudoElement() ||
     200           0 :         currentSelector->mPseudoClassList ||
     201           0 :         currentSelector->mNegations ||
     202           0 :         currentSelector->mOperator) {
     203           0 :       return false;
     204             :     }
     205             : 
     206           0 :     currentSelector = currentSelector->mNext;
     207             :   }
     208             : 
     209           0 :   return true;
     210             : }
     211             : 
     212             : nsresult
     213           0 : HTMLContentElement::AfterSetAttr(int32_t aNamespaceID, nsIAtom* aName,
     214             :                                  const nsAttrValue* aValue,
     215             :                                  const nsAttrValue* aOldValue, bool aNotify)
     216             : {
     217           0 :   if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::select) {
     218           0 :     if (aValue) {
     219             :       // Select attribute was updated, the insertion point may match different
     220             :       // elements.
     221           0 :       nsIDocument* doc = OwnerDoc();
     222           0 :       nsCSSParser parser(doc->CSSLoader());
     223             : 
     224           0 :       mValidSelector = true;
     225           0 :       mSelectorList = nullptr;
     226             : 
     227           0 :       nsAutoString valueStr;
     228           0 :       aValue->ToString(valueStr);
     229           0 :       nsresult rv = parser.ParseSelectorString(valueStr,
     230             :                                                doc->GetDocumentURI(),
     231             :                                                // Bug 11240
     232             :                                                0, // XXX get the line number!
     233           0 :                                                getter_Transfers(mSelectorList));
     234             : 
     235             :       // We don't want to return an exception if parsing failed because
     236             :       // the spec does not define it as an exception case.
     237           0 :       if (NS_SUCCEEDED(rv)) {
     238             :         // Ensure that all the selectors are valid
     239           0 :         nsCSSSelectorList* selectors = mSelectorList;
     240           0 :         while (selectors) {
     241           0 :           if (!IsValidContentSelectors(selectors->mSelectors)) {
     242             :             // If we have an invalid selector, we can not match anything.
     243           0 :             mValidSelector = false;
     244           0 :             mSelectorList = nullptr;
     245           0 :             break;
     246             :           }
     247           0 :           selectors = selectors->mNext;
     248             :         }
     249             :       }
     250             : 
     251           0 :       ShadowRoot* containingShadow = GetContainingShadow();
     252           0 :       if (containingShadow) {
     253           0 :         containingShadow->DistributeAllNodes();
     254             :       }
     255             :     } else {
     256             :       // The select attribute was removed. This insertion point becomes
     257             :       // a universal selector.
     258           0 :       mValidSelector = true;
     259           0 :       mSelectorList = nullptr;
     260             : 
     261           0 :       ShadowRoot* containingShadow = GetContainingShadow();
     262           0 :       if (containingShadow) {
     263           0 :         containingShadow->DistributeAllNodes();
     264             :       }
     265             :     }
     266             :   }
     267             : 
     268           0 :   return nsGenericHTMLElement::AfterSetAttr(aNamespaceID, aName, aValue,
     269           0 :                                             aOldValue, aNotify);
     270             : }
     271             : 
     272             : bool
     273           0 : HTMLContentElement::Match(nsIContent* aContent)
     274             : {
     275           0 :   if (!mValidSelector) {
     276           0 :     return false;
     277             :   }
     278             : 
     279           0 :   if (mSelectorList) {
     280           0 :     nsIDocument* doc = OwnerDoc();
     281           0 :     ShadowRoot* containingShadow = GetContainingShadow();
     282           0 :     nsIContent* host = containingShadow->GetHost();
     283             : 
     284             :     TreeMatchContext matchingContext(false, nsRuleWalker::eRelevantLinkUnvisited,
     285           0 :                                      doc, TreeMatchContext::eNeverMatchVisited);
     286           0 :     matchingContext.SetHasSpecifiedScope();
     287           0 :     matchingContext.AddScopeElement(host->AsElement());
     288             : 
     289           0 :     if (!aContent->IsElement()) {
     290           0 :       return false;
     291             :     }
     292             : 
     293           0 :     return nsCSSRuleProcessor::SelectorListMatches(aContent->AsElement(),
     294             :                                                    matchingContext,
     295           0 :                                                    mSelectorList);
     296             :   }
     297             : 
     298           0 :   return true;
     299             : }
     300             : 
     301             : already_AddRefed<DistributedContentList>
     302           0 : HTMLContentElement::GetDistributedNodes()
     303             : {
     304           0 :   RefPtr<DistributedContentList> list = new DistributedContentList(this);
     305           0 :   return list.forget();
     306             : }
     307             : 
     308           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DistributedContentList, mParent,
     309             :                                       mDistributedNodes)
     310             : 
     311           0 : NS_INTERFACE_TABLE_HEAD(DistributedContentList)
     312           0 :   NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
     313           0 :   NS_INTERFACE_TABLE(DistributedContentList, nsINodeList, nsIDOMNodeList)
     314           0 :   NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DistributedContentList)
     315           0 : NS_INTERFACE_MAP_END
     316             : 
     317           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DistributedContentList)
     318           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DistributedContentList)
     319             : 
     320           0 : DistributedContentList::DistributedContentList(HTMLContentElement* aHostElement)
     321           0 :   : mParent(aHostElement)
     322             : {
     323           0 :   if (aHostElement->IsInsertionPoint()) {
     324           0 :     if (aHostElement->MatchedNodes().IsEmpty()) {
     325             :       // Fallback content.
     326           0 :       nsINode* contentNode = aHostElement;
     327           0 :       for (nsIContent* content = contentNode->GetFirstChild();
     328           0 :            content;
     329           0 :            content = content->GetNextSibling()) {
     330           0 :         mDistributedNodes.AppendElement(content);
     331             :       }
     332             :     } else {
     333           0 :       mDistributedNodes.AppendElements(aHostElement->MatchedNodes());
     334             :     }
     335             :   }
     336           0 : }
     337             : 
     338           0 : DistributedContentList::~DistributedContentList()
     339             : {
     340           0 : }
     341             : 
     342             : nsIContent*
     343           0 : DistributedContentList::Item(uint32_t aIndex)
     344             : {
     345           0 :   return mDistributedNodes.SafeElementAt(aIndex);
     346             : }
     347             : 
     348             : NS_IMETHODIMP
     349           0 : DistributedContentList::Item(uint32_t aIndex, nsIDOMNode** aReturn)
     350             : {
     351           0 :   nsIContent* item = Item(aIndex);
     352           0 :   if (!item) {
     353           0 :     return NS_ERROR_FAILURE;
     354             :   }
     355             : 
     356           0 :   return CallQueryInterface(item, aReturn);
     357             : }
     358             : 
     359             : NS_IMETHODIMP
     360           0 : DistributedContentList::GetLength(uint32_t* aLength)
     361             : {
     362           0 :   *aLength = mDistributedNodes.Length();
     363           0 :   return NS_OK;
     364             : }
     365             : 
     366             : int32_t
     367           0 : DistributedContentList::IndexOf(nsIContent* aContent)
     368             : {
     369           0 :   return mDistributedNodes.IndexOf(aContent);
     370             : }
     371             : 
     372             : JSObject*
     373           0 : DistributedContentList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     374             : {
     375           0 :   return NodeListBinding::Wrap(aCx, this, aGivenProto);
     376             : }
     377             : 

Generated by: LCOV version 1.13