1 /* 2 * Copyright (C) 2011 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Neither the name of Google Inc. nor the names of its 11 * contributors may be used to endorse or promote products derived from 12 * this software without specific prior written permission. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27 #ifndef ShadowRoot_h 28 #define ShadowRoot_h 29 30 #include "core/dom/ContainerNode.h" 31 #include "core/dom/Document.h" 32 #include "core/dom/DocumentFragment.h" 33 #include "core/dom/Element.h" 34 #include "core/dom/TreeScope.h" 35 #include "wtf/DoublyLinkedList.h" 36 37 namespace WebCore { 38 39 class ElementShadow; 40 class ExceptionState; 41 class HTMLShadowElement; 42 class InsertionPoint; 43 class ShadowRootRareData; 44 45 class ShadowRoot FINAL : public DocumentFragment, public TreeScope, public DoublyLinkedListNode<ShadowRoot> { 46 WILL_BE_USING_GARBAGE_COLLECTED_MIXIN(ShadowRoot); 47 friend class WTF::DoublyLinkedListNode<ShadowRoot>; 48 public: 49 // FIXME: We will support multiple shadow subtrees, however current implementation does not work well 50 // if a shadow root is dynamically created. So we prohibit multiple shadow subtrees 51 // in several elements for a while. 52 // See https://bugs.webkit.org/show_bug.cgi?id=77503 and related bugs. 53 enum ShadowRootType { 54 UserAgentShadowRoot = 0, 55 AuthorShadowRoot 56 }; 57 58 static PassRefPtrWillBeRawPtr<ShadowRoot> create(Document& document, ShadowRootType type) 59 { 60 return adoptRefWillBeNoop(new ShadowRoot(document, type)); 61 } 62 63 void recalcStyle(StyleRecalcChange); 64 65 // Disambiguate between Node and TreeScope hierarchies; TreeScope's implementation is simpler. 66 using TreeScope::document; 67 using TreeScope::getElementById; 68 69 Element* host() const { return toElement(parentOrShadowHostNode()); } 70 ElementShadow* owner() const { return host() ? host()->shadow() : 0; } 71 72 ShadowRoot* youngerShadowRoot() const { return prev(); } 73 74 ShadowRoot* olderShadowRootForBindings() const; 75 bool shouldExposeToBindings() const { return type() == AuthorShadowRoot; } 76 77 bool isYoungest() const { return !youngerShadowRoot(); } 78 bool isOldest() const { return !olderShadowRoot(); } 79 bool isOldestAuthorShadowRoot() const; 80 81 virtual void attach(const AttachContext& = AttachContext()) OVERRIDE; 82 83 virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE; 84 virtual void removedFrom(ContainerNode*) OVERRIDE; 85 86 void registerScopedHTMLStyleChild(); 87 void unregisterScopedHTMLStyleChild(); 88 89 bool containsShadowElements() const; 90 bool containsContentElements() const; 91 bool containsInsertionPoints() const { return containsShadowElements() || containsContentElements(); } 92 bool containsShadowRoots() const; 93 94 unsigned descendantShadowElementCount() const; 95 96 // For Internals, don't use this. 97 unsigned childShadowRootCount() const; 98 unsigned numberOfStyles() const { return m_numberOfStyles; } 99 100 HTMLShadowElement* shadowInsertionPointOfYoungerShadowRoot() const; 101 void setShadowInsertionPointOfYoungerShadowRoot(PassRefPtrWillBeRawPtr<HTMLShadowElement>); 102 103 void didAddInsertionPoint(InsertionPoint*); 104 void didRemoveInsertionPoint(InsertionPoint*); 105 const WillBeHeapVector<RefPtrWillBeMember<InsertionPoint> >& descendantInsertionPoints(); 106 107 ShadowRootType type() const { return static_cast<ShadowRootType>(m_type); } 108 109 // Make protected methods from base class public here. 110 using TreeScope::setDocument; 111 using TreeScope::setParentTreeScope; 112 113 public: 114 Element* activeElement() const; 115 116 ShadowRoot* olderShadowRoot() const { return next(); } 117 118 String innerHTML() const; 119 void setInnerHTML(const String&, ExceptionState&); 120 121 PassRefPtrWillBeRawPtr<Node> cloneNode(bool, ExceptionState&); 122 PassRefPtrWillBeRawPtr<Node> cloneNode(ExceptionState& exceptionState) { return cloneNode(true, exceptionState); } 123 124 StyleSheetList* styleSheets(); 125 126 virtual void trace(Visitor*) OVERRIDE; 127 128 private: 129 ShadowRoot(Document&, ShadowRootType); 130 virtual ~ShadowRoot(); 131 132 #if !ENABLE(OILPAN) 133 virtual void dispose() OVERRIDE; 134 #endif 135 136 virtual void childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) OVERRIDE; 137 138 ShadowRootRareData* ensureShadowRootRareData(); 139 140 void addChildShadowRoot(); 141 void removeChildShadowRoot(); 142 void invalidateDescendantInsertionPoints(); 143 144 // ShadowRoots should never be cloned. 145 virtual PassRefPtrWillBeRawPtr<Node> cloneNode(bool) OVERRIDE { return nullptr; } 146 147 // FIXME: This shouldn't happen. https://bugs.webkit.org/show_bug.cgi?id=88834 148 bool isOrphan() const { return !host(); } 149 150 RawPtrWillBeMember<ShadowRoot> m_prev; 151 RawPtrWillBeMember<ShadowRoot> m_next; 152 OwnPtrWillBeMember<ShadowRootRareData> m_shadowRootRareData; 153 unsigned m_numberOfStyles : 27; 154 unsigned m_type : 1; 155 unsigned m_registeredWithParentShadowRoot : 1; 156 unsigned m_descendantInsertionPointsIsValid : 1; 157 }; 158 159 inline Element* ShadowRoot::activeElement() const 160 { 161 return adjustedFocusedElement(); 162 } 163 164 DEFINE_NODE_TYPE_CASTS(ShadowRoot, isShadowRoot()); 165 DEFINE_TYPE_CASTS(ShadowRoot, TreeScope, treeScope, treeScope->rootNode().isShadowRoot(), treeScope.rootNode().isShadowRoot()); 166 167 } // namespace 168 169 #endif 170