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