1 /* 2 * Copyright (C) 2012 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 #include "config.h" 28 #include "core/dom/shadow/ElementShadow.h" 29 30 #include "core/dom/ContainerNodeAlgorithms.h" 31 32 namespace WebCore { 33 34 ShadowRoot* ElementShadow::addShadowRoot(Element* shadowHost, ShadowRoot::ShadowRootType type) 35 { 36 RefPtr<ShadowRoot> shadowRoot = ShadowRoot::create(shadowHost->document(), type); 37 38 shadowRoot->setParentOrShadowHostNode(shadowHost); 39 shadowRoot->setParentTreeScope(shadowHost->treeScope()); 40 m_shadowRoots.push(shadowRoot.get()); 41 ChildNodeInsertionNotifier(shadowHost).notify(shadowRoot.get()); 42 setNeedsDistributionRecalc(); 43 44 // addShadowRoot() affects apply-author-styles. However, we know that the youngest shadow root has not had any children yet. 45 // The youngest shadow root's apply-author-styles is default (false). So we can just set m_applyAuthorStyles false. 46 m_applyAuthorStyles = false; 47 48 if (shadowHost->attached()) 49 shadowHost->lazyReattach(); 50 51 InspectorInstrumentation::didPushShadowRoot(shadowHost, shadowRoot.get()); 52 53 return shadowRoot.get(); 54 } 55 56 void ElementShadow::removeAllShadowRoots() 57 { 58 // Dont protect this ref count. 59 Element* shadowHost = host(); 60 61 while (RefPtr<ShadowRoot> oldRoot = m_shadowRoots.head()) { 62 InspectorInstrumentation::willPopShadowRoot(shadowHost, oldRoot.get()); 63 shadowHost->document()->removeFocusedElementOfSubtree(oldRoot.get()); 64 65 if (oldRoot->attached()) 66 oldRoot->detach(); 67 68 m_shadowRoots.removeHead(); 69 oldRoot->setParentOrShadowHostNode(0); 70 oldRoot->setParentTreeScope(shadowHost->document()); 71 oldRoot->setPrev(0); 72 oldRoot->setNext(0); 73 ChildNodeRemovalNotifier(shadowHost).notify(oldRoot.get()); 74 } 75 } 76 77 void ElementShadow::attach(const Node::AttachContext& context) 78 { 79 Node::AttachContext childrenContext(context); 80 childrenContext.resolvedStyle = 0; 81 82 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 83 if (!root->attached()) 84 root->attach(childrenContext); 85 } 86 } 87 88 void ElementShadow::detach(const Node::AttachContext& context) 89 { 90 Node::AttachContext childrenContext(context); 91 childrenContext.resolvedStyle = 0; 92 93 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 94 if (root->attached()) 95 root->detach(childrenContext); 96 } 97 } 98 99 void ElementShadow::removeAllEventListeners() 100 { 101 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 102 for (Node* node = root; node; node = NodeTraversal::next(node)) 103 node->removeAllEventListeners(); 104 } 105 } 106 107 void ElementShadow::setNeedsDistributionRecalc() 108 { 109 if (m_needsDistributionRecalc) 110 return; 111 m_needsDistributionRecalc = true; 112 host()->markAncestorsWithChildNeedsDistributionRecalc(); 113 clearDistribution(); 114 } 115 116 bool ElementShadow::didAffectApplyAuthorStyles() 117 { 118 bool applyAuthorStyles = resolveApplyAuthorStyles(); 119 120 if (m_applyAuthorStyles == applyAuthorStyles) 121 return false; 122 123 m_applyAuthorStyles = applyAuthorStyles; 124 return true; 125 } 126 127 bool ElementShadow::containsActiveStyles() const 128 { 129 for (ShadowRoot* root = youngestShadowRoot(); root; root = root->olderShadowRoot()) { 130 if (root->hasScopedHTMLStyleChild()) 131 return true; 132 if (!root->containsShadowElements()) 133 return false; 134 } 135 return false; 136 } 137 138 bool ElementShadow::resolveApplyAuthorStyles() const 139 { 140 for (const ShadowRoot* shadowRoot = youngestShadowRoot(); shadowRoot; shadowRoot = shadowRoot->olderShadowRoot()) { 141 if (shadowRoot->applyAuthorStyles()) 142 return true; 143 if (!shadowRoot->containsShadowElements()) 144 break; 145 } 146 return false; 147 } 148 149 } // namespace 150