Home | History | Annotate | Download | only in dom
      1 /*
      2  * Copyright (C) 1999 Lars Knoll (knoll (at) kde.org)
      3  *           (C) 1999 Antti Koivisto (koivisto (at) kde.org)
      4  *           (C) 2001 Dirk Mueller (mueller (at) kde.org)
      5  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
      6  * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
      7  * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
      8  * Copyright (C) 2012 Google Inc. All rights reserved.
      9  *
     10  * This library is free software; you can redistribute it and/or
     11  * modify it under the terms of the GNU Library General Public
     12  * License as published by the Free Software Foundation; either
     13  * version 2 of the License, or (at your option) any later version.
     14  *
     15  * This library is distributed in the hope that it will be useful,
     16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     18  * Library General Public License for more details.
     19  *
     20  * You should have received a copy of the GNU Library General Public License
     21  * along with this library; see the file COPYING.LIB.  If not, write to
     22  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     23  * Boston, MA 02110-1301, USA.
     24  */
     25 
     26 #include "config.h"
     27 #include "core/dom/ContainerNodeAlgorithms.h"
     28 
     29 #include "core/dom/Element.h"
     30 #include "core/dom/shadow/ElementShadow.h"
     31 #include "core/dom/shadow/ShadowRoot.h"
     32 
     33 namespace WebCore {
     34 
     35 class ShadowRootVector : public Vector<RefPtr<ShadowRoot> > {
     36 public:
     37     explicit ShadowRootVector(ElementShadow* tree)
     38     {
     39         for (ShadowRoot* root = tree->youngestShadowRoot(); root; root = root->olderShadowRoot())
     40             append(root);
     41     }
     42 };
     43 
     44 void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoDocument(ContainerNode& node)
     45 {
     46     ChildNodesLazySnapshot snapshot(node);
     47     while (RefPtr<Node> child = snapshot.nextNode()) {
     48         // If we have been removed from the document during this loop, then
     49         // we don't want to tell the rest of our children that they've been
     50         // inserted into the document because they haven't.
     51         if (node.inDocument() && child->parentNode() == node)
     52             notifyNodeInsertedIntoDocument(*child);
     53     }
     54 
     55     if (!node.isElementNode())
     56         return;
     57 
     58     if (ElementShadow* shadow = toElement(node).shadow()) {
     59         ShadowRootVector roots(shadow);
     60         for (size_t i = 0; i < roots.size(); ++i) {
     61             if (node.inDocument() && roots[i]->host() == node)
     62                 notifyNodeInsertedIntoDocument(*roots[i]);
     63         }
     64     }
     65 }
     66 
     67 void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoTree(ContainerNode& node)
     68 {
     69     for (Node* child = node.firstChild(); child; child = child->nextSibling()) {
     70         if (child->isContainerNode())
     71             notifyNodeInsertedIntoTree(toContainerNode(*child));
     72     }
     73 
     74     for (ShadowRoot* root = node.youngestShadowRoot(); root; root = root->olderShadowRoot())
     75         notifyNodeInsertedIntoTree(*root);
     76 }
     77 
     78 void ChildNodeRemovalNotifier::notifyDescendantRemovedFromDocument(ContainerNode& node)
     79 {
     80     ChildNodesLazySnapshot snapshot(node);
     81     while (RefPtr<Node> child = snapshot.nextNode()) {
     82         // If we have been added to the document during this loop, then we
     83         // don't want to tell the rest of our children that they've been
     84         // removed from the document because they haven't.
     85         if (!node.inDocument() && child->parentNode() == node)
     86             notifyNodeRemovedFromDocument(*child);
     87     }
     88 
     89     if (!node.isElementNode())
     90         return;
     91 
     92     if (node.document().cssTarget() == node)
     93         node.document().setCSSTarget(0);
     94 
     95     if (ElementShadow* shadow = toElement(node).shadow()) {
     96         ShadowRootVector roots(shadow);
     97         for (size_t i = 0; i < roots.size(); ++i) {
     98             if (!node.inDocument() && roots[i]->host() == node)
     99                 notifyNodeRemovedFromDocument(*roots[i]);
    100         }
    101     }
    102 }
    103 
    104 void ChildNodeRemovalNotifier::notifyDescendantRemovedFromTree(ContainerNode& node)
    105 {
    106     for (Node* child = node.firstChild(); child; child = child->nextSibling()) {
    107         if (child->isContainerNode())
    108             notifyNodeRemovedFromTree(toContainerNode(*child));
    109     }
    110 
    111     if (!node.isElementNode())
    112         return;
    113 
    114     if (ElementShadow* shadow = toElement(node).shadow()) {
    115         ShadowRootVector roots(shadow);
    116         for (size_t i = 0; i < roots.size(); ++i)
    117             notifyNodeRemovedFromTree(*roots[i]);
    118     }
    119 }
    120 
    121 void ChildFrameDisconnector::collectFrameOwners(ElementShadow& shadow)
    122 {
    123     for (ShadowRoot* root = shadow.youngestShadowRoot(); root; root = root->olderShadowRoot())
    124         collectFrameOwners(*root);
    125 }
    126 
    127 #ifndef NDEBUG
    128 unsigned assertConnectedSubrameCountIsConsistent(Node& node)
    129 {
    130     unsigned count = 0;
    131 
    132     if (node.isElementNode()) {
    133         if (node.isFrameOwnerElement() && toHTMLFrameOwnerElement(node).contentFrame())
    134             count++;
    135 
    136         if (ElementShadow* shadow = toElement(node).shadow()) {
    137             for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot())
    138                 count += assertConnectedSubrameCountIsConsistent(*root);
    139         }
    140     }
    141 
    142     for (Node* child = node.firstChild(); child; child = child->nextSibling())
    143         count += assertConnectedSubrameCountIsConsistent(*child);
    144 
    145     // If we undercount there's possibly a security bug since we'd leave frames
    146     // in subtrees outside the document.
    147     ASSERT(node.connectedSubframeCount() >= count);
    148 
    149     // If we overcount it's safe, but not optimal because it means we'll traverse
    150     // through the document in ChildFrameDisconnector looking for frames that have
    151     // already been disconnected.
    152     ASSERT(node.connectedSubframeCount() == count);
    153 
    154     return count;
    155 }
    156 #endif
    157 
    158 }
    159