Home | History | Annotate | Download | only in shadow
      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