content/base/src/ShadowRoot.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/Preferences.h"
     7 #include "mozilla/dom/ShadowRoot.h"
     8 #include "mozilla/dom/ShadowRootBinding.h"
     9 #include "mozilla/dom/DocumentFragment.h"
    10 #include "ChildIterator.h"
    11 #include "nsContentUtils.h"
    12 #include "nsDOMClassInfoID.h"
    13 #include "nsIDOMHTMLElement.h"
    14 #include "nsIStyleSheetLinkingElement.h"
    15 #include "mozilla/dom/Element.h"
    16 #include "mozilla/dom/HTMLContentElement.h"
    17 #include "mozilla/dom/HTMLShadowElement.h"
    18 #include "nsXBLPrototypeBinding.h"
    20 using namespace mozilla;
    21 using namespace mozilla::dom;
    23 static PLDHashOperator
    24 IdentifierMapEntryTraverse(nsIdentifierMapEntry *aEntry, void *aArg)
    25 {
    26   nsCycleCollectionTraversalCallback *cb =
    27     static_cast<nsCycleCollectionTraversalCallback*>(aArg);
    28   aEntry->Traverse(cb);
    29   return PL_DHASH_NEXT;
    30 }
    32 NS_IMPL_CYCLE_COLLECTION_CLASS(ShadowRoot)
    34 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ShadowRoot,
    35                                                   DocumentFragment)
    36   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPoolHost)
    37   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStyleSheetList)
    38   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOlderShadow)
    39   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mYoungerShadow)
    40   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAssociatedBinding)
    41   tmp->mIdentifierMap.EnumerateEntries(IdentifierMapEntryTraverse, &cb);
    42 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    44 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ShadowRoot,
    45                                                 DocumentFragment)
    46   if (tmp->mPoolHost) {
    47     tmp->mPoolHost->RemoveMutationObserver(tmp);
    48   }
    49   NS_IMPL_CYCLE_COLLECTION_UNLINK(mPoolHost)
    50   NS_IMPL_CYCLE_COLLECTION_UNLINK(mStyleSheetList)
    51   NS_IMPL_CYCLE_COLLECTION_UNLINK(mOlderShadow)
    52   NS_IMPL_CYCLE_COLLECTION_UNLINK(mYoungerShadow)
    53   NS_IMPL_CYCLE_COLLECTION_UNLINK(mAssociatedBinding)
    54   tmp->mIdentifierMap.Clear();
    55 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    57 DOMCI_DATA(ShadowRoot, ShadowRoot)
    59 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRoot)
    60   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
    61   NS_INTERFACE_MAP_ENTRY(nsIMutationObserver)
    62 NS_INTERFACE_MAP_END_INHERITING(DocumentFragment)
    64 NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment)
    65 NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment)
    67 ShadowRoot::ShadowRoot(nsIContent* aContent,
    68                        already_AddRefed<nsINodeInfo>&& aNodeInfo,
    69                        nsXBLPrototypeBinding* aProtoBinding)
    70   : DocumentFragment(aNodeInfo), mPoolHost(aContent),
    71     mProtoBinding(aProtoBinding), mShadowElement(nullptr),
    72     mInsertionPointChanged(false)
    73 {
    74   SetHost(aContent);
    75   SetFlags(NODE_IS_IN_SHADOW_TREE);
    76   // ShadowRoot isn't really in the document but it behaves like it is.
    77   SetInDocument();
    78   DOMSlots()->mBindingParent = aContent;
    79   DOMSlots()->mContainingShadow = this;
    81   // Add the ShadowRoot as a mutation observer on the host to watch
    82   // for mutations because the insertion points in this ShadowRoot
    83   // may need to be updated when the host children are modified.
    84   mPoolHost->AddMutationObserver(this);
    85 }
    87 ShadowRoot::~ShadowRoot()
    88 {
    89   if (mPoolHost) {
    90     // mPoolHost may have been unlinked or a new ShadowRoot may have been
    91     // creating, making this one obsolete.
    92     mPoolHost->RemoveMutationObserver(this);
    93   }
    95   ClearInDocument();
    96   SetHost(nullptr);
    97 }
    99 JSObject*
   100 ShadowRoot::WrapObject(JSContext* aCx)
   101 {
   102   return mozilla::dom::ShadowRootBinding::Wrap(aCx, this);
   103 }
   105 ShadowRoot*
   106 ShadowRoot::FromNode(nsINode* aNode)
   107 {
   108   if (aNode->HasFlag(NODE_IS_IN_SHADOW_TREE) && !aNode->GetParentNode()) {
   109     MOZ_ASSERT(aNode->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
   110                "ShadowRoot is a document fragment.");
   111     return static_cast<ShadowRoot*>(aNode);
   112   }
   114   return nullptr;
   115 }
   117 void
   118 ShadowRoot::Restyle()
   119 {
   120   mProtoBinding->FlushSkinSheets();
   122   nsIPresShell* shell = OwnerDoc()->GetShell();
   123   if (shell) {
   124     OwnerDoc()->BeginUpdate(UPDATE_STYLE);
   125     shell->RestyleShadowRoot(this);
   126     OwnerDoc()->EndUpdate(UPDATE_STYLE);
   127   }
   128 }
   130 void
   131 ShadowRoot::InsertSheet(nsCSSStyleSheet* aSheet,
   132                         nsIContent* aLinkingContent)
   133 {
   134   nsCOMPtr<nsIStyleSheetLinkingElement>
   135     linkingElement = do_QueryInterface(aLinkingContent);
   136   MOZ_ASSERT(linkingElement, "The only styles in a ShadowRoot should come "
   137                              "from <style>.");
   139   linkingElement->SetStyleSheet(aSheet); // This sets the ownerNode on the sheet
   141   nsTArray<nsRefPtr<nsCSSStyleSheet> >* sheets =
   142     mProtoBinding->GetOrCreateStyleSheets();
   143   MOZ_ASSERT(sheets, "Style sheets array should never be null.");
   145   // Find the correct position to insert into the style sheet list (must
   146   // be in tree order).
   147   for (uint32_t i = 0; i <= sheets->Length(); i++) {
   148     if (i == sheets->Length()) {
   149       sheets->AppendElement(aSheet);
   150       break;
   151     }
   153     nsINode* sheetOwnerNode = sheets->ElementAt(i)->GetOwnerNode();
   154     if (nsContentUtils::PositionIsBefore(aLinkingContent, sheetOwnerNode)) {
   155       sheets->InsertElementAt(i, aSheet);
   156       break;
   157     }
   158   }
   160   Restyle();
   161 }
   163 void
   164 ShadowRoot::RemoveSheet(nsCSSStyleSheet* aSheet)
   165 {
   166   nsTArray<nsRefPtr<nsCSSStyleSheet> >* sheets =
   167     mProtoBinding->GetOrCreateStyleSheets();
   168   MOZ_ASSERT(sheets, "Style sheets array should never be null.");
   170   DebugOnly<bool> found = sheets->RemoveElement(aSheet);
   171   MOZ_ASSERT(found, "Trying to remove a sheet from a ShadowRoot "
   172                     "that does not exist.");
   174   Restyle();
   175 }
   177 Element*
   178 ShadowRoot::GetElementById(const nsAString& aElementId)
   179 {
   180   nsIdentifierMapEntry *entry = mIdentifierMap.GetEntry(aElementId);
   181   return entry ? entry->GetIdElement() : nullptr;
   182 }
   184 already_AddRefed<nsContentList>
   185 ShadowRoot::GetElementsByTagName(const nsAString& aTagName)
   186 {
   187   return NS_GetContentList(this, kNameSpaceID_Unknown, aTagName);
   188 }
   190 already_AddRefed<nsContentList>
   191 ShadowRoot::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
   192                                    const nsAString& aLocalName)
   193 {
   194   int32_t nameSpaceId = kNameSpaceID_Wildcard;
   196   if (!aNamespaceURI.EqualsLiteral("*")) {
   197     nsresult rv =
   198       nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
   199                                                             nameSpaceId);
   200     NS_ENSURE_SUCCESS(rv, nullptr);
   201   }
   203   NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
   205   return NS_GetContentList(this, nameSpaceId, aLocalName);
   206 }
   208 void
   209 ShadowRoot::AddToIdTable(Element* aElement, nsIAtom* aId)
   210 {
   211   nsIdentifierMapEntry *entry =
   212     mIdentifierMap.PutEntry(nsDependentAtomString(aId));
   213   if (entry) {
   214     entry->AddIdElement(aElement);
   215   }
   216 }
   218 void
   219 ShadowRoot::RemoveFromIdTable(Element* aElement, nsIAtom* aId)
   220 {
   221   nsIdentifierMapEntry *entry =
   222     mIdentifierMap.GetEntry(nsDependentAtomString(aId));
   223   if (entry) {
   224     entry->RemoveIdElement(aElement);
   225     if (entry->IsEmpty()) {
   226       mIdentifierMap.RawRemoveEntry(entry);
   227     }
   228   }
   229 }
   231 already_AddRefed<nsContentList>
   232 ShadowRoot::GetElementsByClassName(const nsAString& aClasses)
   233 {
   234   return nsContentUtils::GetElementsByClassName(this, aClasses);
   235 }
   237 void
   238 ShadowRoot::AddInsertionPoint(HTMLContentElement* aInsertionPoint)
   239 {
   240   TreeOrderComparator comparator;
   241   mInsertionPoints.InsertElementSorted(aInsertionPoint, comparator);
   242 }
   244 void
   245 ShadowRoot::RemoveInsertionPoint(HTMLContentElement* aInsertionPoint)
   246 {
   247   mInsertionPoints.RemoveElement(aInsertionPoint);
   248 }
   250 void
   251 ShadowRoot::SetYoungerShadow(ShadowRoot* aYoungerShadow)
   252 {
   253   mYoungerShadow = aYoungerShadow;
   254   mYoungerShadow->mOlderShadow = this;
   256   ChangePoolHost(mYoungerShadow->GetShadowElement());
   257 }
   259 void
   260 ShadowRoot::DistributeSingleNode(nsIContent* aContent)
   261 {
   262   // Find the insertion point to which the content belongs.
   263   HTMLContentElement* insertionPoint = nullptr;
   264   for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
   265     if (mInsertionPoints[i]->Match(aContent)) {
   266       if (mInsertionPoints[i]->MatchedNodes().Contains(aContent)) {
   267         // Node is already matched into the insertion point. We are done.
   268         return;
   269       }
   271       // Matching may cause the insertion point to drop fallback content.
   272       if (mInsertionPoints[i]->MatchedNodes().IsEmpty() &&
   273           static_cast<nsINode*>(mInsertionPoints[i])->GetFirstChild()) {
   274         // This match will cause the insertion point to drop all fallback
   275         // content and used matched nodes instead. Give up on the optimization
   276         // and just distribute all nodes.
   277         DistributeAllNodes();
   278         return;
   279       }
   280       insertionPoint = mInsertionPoints[i];
   281       break;
   282     }
   283   }
   285   // Find the index into the insertion point.
   286   if (insertionPoint) {
   287     nsCOMArray<nsIContent>& matchedNodes = insertionPoint->MatchedNodes();
   288     // Find the appropriate position in the matched node list for the
   289     // newly distributed content.
   290     bool isIndexFound = false;
   291     MOZ_ASSERT(mPoolHost, "Where did the content come from if there is no pool host?");
   292     ExplicitChildIterator childIterator(mPoolHost);
   293     for (uint32_t i = 0; i < matchedNodes.Length(); i++) {
   294       // Seek through the host's explicit children until the inserted content
   295       // is found or when the current matched node is reached.
   296       if (childIterator.Seek(aContent, matchedNodes[i])) {
   297         // aContent was found before the current matched node.
   298         matchedNodes.InsertElementAt(i, aContent);
   299         isIndexFound = true;
   300         break;
   301       }
   302     }
   304     if (!isIndexFound) {
   305       // We have still not found an index in the insertion point,
   306       // thus it must be at the end.
   307       MOZ_ASSERT(childIterator.Seek(aContent),
   308                  "Trying to match a node that is not a candidate to be matched");
   309       matchedNodes.AppendElement(aContent);
   310     }
   312     // Handle the case where the parent of the insertion point is a ShadowRoot
   313     // that is projected into the younger ShadowRoot's shadow insertion point.
   314     // The node distributed into the insertion point must be reprojected
   315     // to the shadow insertion point.
   316     if (insertionPoint->GetParent() == this &&
   317         mYoungerShadow && mYoungerShadow->GetShadowElement()) {
   318       mYoungerShadow->GetShadowElement()->DistributeSingleNode(aContent);
   319     }
   321     // Handle the case where the parent of the insertion point has a ShadowRoot.
   322     // The node distributed into the insertion point must be reprojected to the
   323     // insertion points of the parent's ShadowRoot.
   324     ShadowRoot* parentShadow = insertionPoint->GetParent()->GetShadowRoot();
   325     if (parentShadow) {
   326       parentShadow->DistributeSingleNode(aContent);
   327     }
   329     // Handle the case where the parent of the insertion point is the <shadow>
   330     // element. The node distributed into the insertion point must be reprojected
   331     // into the older ShadowRoot's insertion points.
   332     if (mShadowElement && mShadowElement == insertionPoint->GetParent()) {
   333       ShadowRoot* olderShadow = mShadowElement->GetOlderShadowRoot();
   334       if (olderShadow) {
   335         olderShadow->DistributeSingleNode(aContent);
   336       }
   337     }
   338   }
   339 }
   341 void
   342 ShadowRoot::RemoveDistributedNode(nsIContent* aContent)
   343 {
   344   // Find insertion point containing the content and remove the node.
   345   for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
   346     if (mInsertionPoints[i]->MatchedNodes().Contains(aContent)) {
   347       // Removing the matched node may cause the insertion point to use
   348       // fallback content.
   349       if (mInsertionPoints[i]->MatchedNodes().Length() == 1 &&
   350           static_cast<nsINode*>(mInsertionPoints[i])->GetFirstChild()) {
   351         // Removing the matched node will cause fallback content to be
   352         // used instead. Give up optimization and distribute all nodes.
   353         DistributeAllNodes();
   354         return;
   355       }
   357       mInsertionPoints[i]->MatchedNodes().RemoveElement(aContent);
   359       // Handle the case where the parent of the insertion point is a ShadowRoot
   360       // that is projected into the younger ShadowRoot's shadow insertion point.
   361       // The removed node needs to be removed from the shadow insertion point.
   362       if (mInsertionPoints[i]->GetParent() == this) {
   363         if (mYoungerShadow && mYoungerShadow->GetShadowElement()) {
   364           mYoungerShadow->GetShadowElement()->RemoveDistributedNode(aContent);
   365         }
   366       }
   368       // Handle the case where the parent of the insertion point has a ShadowRoot.
   369       // The removed node needs to be removed from the insertion points of the
   370       // parent's ShadowRoot.
   371       ShadowRoot* parentShadow = mInsertionPoints[i]->GetParent()->GetShadowRoot();
   372       if (parentShadow) {
   373         parentShadow->RemoveDistributedNode(aContent);
   374       }
   376       // Handle the case where the parent of the insertion point is the <shadow>
   377       // element. The removed node must be removed from the older ShadowRoot's
   378       // insertion points.
   379       if (mShadowElement && mShadowElement == mInsertionPoints[i]->GetParent()) {
   380         ShadowRoot* olderShadow = mShadowElement->GetOlderShadowRoot();
   381         if (olderShadow) {
   382           olderShadow->RemoveDistributedNode(aContent);
   383         }
   384       }
   386       break;
   387     }
   388   }
   389 }
   391 void
   392 ShadowRoot::DistributeAllNodes()
   393 {
   394   // Create node pool.
   395   nsTArray<nsIContent*> nodePool;
   397   // Make sure there is a pool host, an older shadow may not have
   398   // one if the younger shadow does not have a <shadow> element.
   399   if (mPoolHost) {
   400     ExplicitChildIterator childIterator(mPoolHost);
   401     for (nsIContent* content = childIterator.GetNextChild();
   402          content;
   403          content = childIterator.GetNextChild()) {
   404       nodePool.AppendElement(content);
   405     }
   406   }
   408   nsTArray<ShadowRoot*> shadowsToUpdate;
   410   for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
   411     mInsertionPoints[i]->ClearMatchedNodes();
   412     // Assign matching nodes from node pool.
   413     for (uint32_t j = 0; j < nodePool.Length(); j++) {
   414       if (mInsertionPoints[i]->Match(nodePool[j])) {
   415         mInsertionPoints[i]->MatchedNodes().AppendElement(nodePool[j]);
   416         nodePool[j]->SetXBLInsertionParent(mInsertionPoints[i]);
   417         nodePool.RemoveElementAt(j--);
   418       }
   419     }
   421     // Keep track of instances where the content insertion point is distributed
   422     // (parent of insertion point has a ShadowRoot).
   423     nsIContent* insertionParent = mInsertionPoints[i]->GetParent();
   424     MOZ_ASSERT(insertionParent, "The only way for an insertion point to be in the"
   425                                 "mInsertionPoints array is to be a descendant of a"
   426                                 "ShadowRoot, in which case, it should have a parent");
   428     // If the parent of the insertion point has as ShadowRoot, the nodes distributed
   429     // to the insertion point must be reprojected to the insertion points of the
   430     // parent's ShadowRoot.
   431     ShadowRoot* parentShadow = insertionParent->GetShadowRoot();
   432     if (parentShadow && !shadowsToUpdate.Contains(parentShadow)) {
   433       shadowsToUpdate.AppendElement(parentShadow);
   434     }
   435   }
   437   // If there is a shadow insertion point in this ShadowRoot, the children
   438   // of the shadow insertion point needs to be distributed into the insertion
   439   // points of the older ShadowRoot.
   440   if (mShadowElement && mOlderShadow) {
   441     mOlderShadow->DistributeAllNodes();
   442   }
   444   // If there is a younger ShadowRoot with a shadow insertion point,
   445   // then the children of this ShadowRoot needs to be distributed to
   446   // the younger ShadowRoot's shadow insertion point.
   447   if (mYoungerShadow && mYoungerShadow->GetShadowElement()) {
   448     mYoungerShadow->GetShadowElement()->DistributeAllNodes();
   449   }
   451   for (uint32_t i = 0; i < shadowsToUpdate.Length(); i++) {
   452     shadowsToUpdate[i]->DistributeAllNodes();
   453   }
   454 }
   456 void
   457 ShadowRoot::GetInnerHTML(nsAString& aInnerHTML)
   458 {
   459   GetMarkup(false, aInnerHTML);
   460 }
   462 void
   463 ShadowRoot::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError)
   464 {
   465   SetInnerHTMLInternal(aInnerHTML, aError);
   466 }
   468 bool
   469 ShadowRoot::ApplyAuthorStyles()
   470 {
   471   return mProtoBinding->InheritsStyle();
   472 }
   474 void
   475 ShadowRoot::SetApplyAuthorStyles(bool aApplyAuthorStyles)
   476 {
   477   mProtoBinding->SetInheritsStyle(aApplyAuthorStyles);
   479   nsIPresShell* shell = OwnerDoc()->GetShell();
   480   if (shell) {
   481     OwnerDoc()->BeginUpdate(UPDATE_STYLE);
   482     shell->RestyleShadowRoot(this);
   483     OwnerDoc()->EndUpdate(UPDATE_STYLE);
   484   }
   485 }
   487 StyleSheetList*
   488 ShadowRoot::StyleSheets()
   489 {
   490   if (!mStyleSheetList) {
   491     mStyleSheetList = new ShadowRootStyleSheetList(this);
   492   }
   494   return mStyleSheetList;
   495 }
   497 void
   498 ShadowRoot::SetShadowElement(HTMLShadowElement* aShadowElement)
   499 {
   500   // If there is already a shadow element point, remove
   501   // the projected shadow because it is no longer an insertion
   502   // point.
   503   if (mShadowElement) {
   504     mShadowElement->SetProjectedShadow(nullptr);
   505   }
   507   if (mOlderShadow) {
   508     // Nodes for distribution will come from the new shadow element.
   509     mOlderShadow->ChangePoolHost(aShadowElement);
   510   }
   512   // Set the new shadow element to project the older ShadowRoot because
   513   // it is the current shadow insertion point.
   514   mShadowElement = aShadowElement;
   515   if (mShadowElement) {
   516     mShadowElement->SetProjectedShadow(mOlderShadow);
   517   }
   518 }
   520 void
   521 ShadowRoot::ChangePoolHost(nsIContent* aNewHost)
   522 {
   523   if (mPoolHost) {
   524     mPoolHost->RemoveMutationObserver(this);
   525   }
   527   // Clear the nodes matched to content insertion points
   528   // because it is no longer relevant.
   529   for (uint32_t i = 0; i < mInsertionPoints.Length(); i++) {
   530     mInsertionPoints[i]->ClearMatchedNodes();
   531   }
   533   mPoolHost = aNewHost;
   534   if (mPoolHost) {
   535     mPoolHost->AddMutationObserver(this);
   536   }
   537 }
   539 bool
   540 ShadowRoot::IsShadowInsertionPoint(nsIContent* aContent)
   541 {
   542   if (aContent && aContent->IsHTML(nsGkAtoms::shadow)) {
   543     HTMLShadowElement* shadowElem = static_cast<HTMLShadowElement*>(aContent);
   544     return shadowElem->IsInsertionPoint();
   545   }
   546   return false;
   547 }
   549 /**
   550  * Returns whether the web components pool population algorithm
   551  * on the host would contain |aContent|. This function ignores
   552  * insertion points in the pool, thus should only be used to
   553  * test nodes that have not yet been distributed.
   554  */
   555 bool
   556 ShadowRoot::IsPooledNode(nsIContent* aContent, nsIContent* aContainer,
   557                          nsIContent* aHost)
   558 {
   559   if (nsContentUtils::IsContentInsertionPoint(aContent) ||
   560       IsShadowInsertionPoint(aContent)) {
   561     // Insertion points never end up in the pool.
   562     return false;
   563   }
   565   if (aContainer->IsHTML(nsGkAtoms::content)) {
   566     // Fallback content will end up in pool if its parent is a child of the host.
   567     HTMLContentElement* content = static_cast<HTMLContentElement*>(aContainer);
   568     return content->IsInsertionPoint() && content->MatchedNodes().IsEmpty() &&
   569            aContainer->GetParentNode() == aHost;
   570   }
   572   if (aContainer == aHost) {
   573     // Any other child nodes of the host will end up in the pool.
   574     return true;
   575   }
   577   return false;
   578 }
   580 void
   581 ShadowRoot::AttributeChanged(nsIDocument* aDocument,
   582                              Element* aElement,
   583                              int32_t aNameSpaceID,
   584                              nsIAtom* aAttribute,
   585                              int32_t aModType)
   586 {
   587   if (!IsPooledNode(aElement, aElement->GetParent(), mPoolHost)) {
   588     return;
   589   }
   591   // Attributes may change insertion point matching, find its new distribution.
   592   RemoveDistributedNode(aElement);
   593   DistributeSingleNode(aElement);
   594 }
   596 void
   597 ShadowRoot::ContentAppended(nsIDocument* aDocument,
   598                             nsIContent* aContainer,
   599                             nsIContent* aFirstNewContent,
   600                             int32_t aNewIndexInContainer)
   601 {
   602   if (mInsertionPointChanged) {
   603     DistributeAllNodes();
   604     mInsertionPointChanged = false;
   605     return;
   606   }
   608   // Watch for new nodes added to the pool because the node
   609   // may need to be added to an insertion point.
   610   nsIContent* currentChild = aFirstNewContent;
   611   while (currentChild) {
   612     if (IsPooledNode(currentChild, aContainer, mPoolHost)) {
   613       DistributeSingleNode(currentChild);
   614     }
   615     currentChild = currentChild->GetNextSibling();
   616   }
   617 }
   619 void
   620 ShadowRoot::ContentInserted(nsIDocument* aDocument,
   621                             nsIContent* aContainer,
   622                             nsIContent* aChild,
   623                             int32_t aIndexInContainer)
   624 {
   625   if (mInsertionPointChanged) {
   626     DistributeAllNodes();
   627     mInsertionPointChanged = false;
   628     return;
   629   }
   631   // Watch for new nodes added to the pool because the node
   632   // may need to be added to an insertion point.
   633   if (IsPooledNode(aChild, aContainer, mPoolHost)) {
   634     DistributeSingleNode(aChild);
   635   }
   636 }
   638 void
   639 ShadowRoot::ContentRemoved(nsIDocument* aDocument,
   640                            nsIContent* aContainer,
   641                            nsIContent* aChild,
   642                            int32_t aIndexInContainer,
   643                            nsIContent* aPreviousSibling)
   644 {
   645   if (mInsertionPointChanged) {
   646     DistributeAllNodes();
   647     mInsertionPointChanged = false;
   648     return;
   649   }
   651   // Watch for node that is removed from the pool because
   652   // it may need to be removed from an insertion point.
   653   if (IsPooledNode(aChild, aContainer, mPoolHost)) {
   654     RemoveDistributedNode(aChild);
   655   }
   656 }
   658 NS_IMPL_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList, StyleSheetList,
   659                                    mShadowRoot)
   661 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ShadowRootStyleSheetList)
   662 NS_INTERFACE_MAP_END_INHERITING(StyleSheetList)
   664 NS_IMPL_ADDREF_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
   665 NS_IMPL_RELEASE_INHERITED(ShadowRootStyleSheetList, StyleSheetList)
   667 ShadowRootStyleSheetList::ShadowRootStyleSheetList(ShadowRoot* aShadowRoot)
   668   : mShadowRoot(aShadowRoot)
   669 {
   670   MOZ_COUNT_CTOR(ShadowRootStyleSheetList);
   671 }
   673 ShadowRootStyleSheetList::~ShadowRootStyleSheetList()
   674 {
   675   MOZ_COUNT_DTOR(ShadowRootStyleSheetList);
   676 }
   678 nsCSSStyleSheet*
   679 ShadowRootStyleSheetList::IndexedGetter(uint32_t aIndex, bool& aFound)
   680 {
   681   nsTArray<nsRefPtr<nsCSSStyleSheet>>* sheets =
   682     mShadowRoot->mProtoBinding->GetStyleSheets();
   684   if (!sheets) {
   685     aFound = false;
   686     return nullptr;
   687   }
   689   aFound = aIndex < sheets->Length();
   690   return sheets->SafeElementAt(aIndex);
   691 }
   693 uint32_t
   694 ShadowRootStyleSheetList::Length()
   695 {
   696   nsTArray<nsRefPtr<nsCSSStyleSheet> >* sheets =
   697     mShadowRoot->mProtoBinding->GetStyleSheets();
   699   if (!sheets) {
   700     return 0;
   701   }
   703   return sheets->Length();
   704 }

mercurial