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/html/HTMLFrameOwnerElement.h" 32 33 namespace WebCore { 34 35 void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoDocument(ContainerNode* node) 36 { 37 ChildNodesLazySnapshot snapshot(node); 38 while (RefPtr<Node> child = snapshot.nextNode()) { 39 // If we have been removed from the document during this loop, then 40 // we don't want to tell the rest of our children that they've been 41 // inserted into the document because they haven't. 42 if (node->inDocument() && child->parentNode() == node) 43 notifyNodeInsertedIntoDocument(child.get()); 44 } 45 46 if (!node->isElementNode()) 47 return; 48 49 if (ElementShadow* shadow = toElement(node)->shadow()) { 50 ShadowRootVector roots(shadow); 51 for (size_t i = 0; i < roots.size(); ++i) { 52 if (node->inDocument() && roots[i]->host() == node) 53 notifyNodeInsertedIntoDocument(roots[i].get()); 54 } 55 } 56 } 57 58 void ChildNodeInsertionNotifier::notifyDescendantInsertedIntoTree(ContainerNode* node) 59 { 60 for (Node* child = node->firstChild(); child; child = child->nextSibling()) { 61 if (child->isContainerNode()) 62 notifyNodeInsertedIntoTree(toContainerNode(child)); 63 } 64 65 for (ShadowRoot* root = node->youngestShadowRoot(); root; root = root->olderShadowRoot()) 66 notifyNodeInsertedIntoTree(root); 67 } 68 69 void ChildNodeRemovalNotifier::notifyDescendantRemovedFromDocument(ContainerNode* node) 70 { 71 ChildNodesLazySnapshot snapshot(node); 72 while (RefPtr<Node> child = snapshot.nextNode()) { 73 // If we have been added to the document during this loop, then we 74 // don't want to tell the rest of our children that they've been 75 // removed from the document because they haven't. 76 if (!node->inDocument() && child->parentNode() == node) 77 notifyNodeRemovedFromDocument(child.get()); 78 } 79 80 if (!node->isElementNode()) 81 return; 82 83 if (node->document()->cssTarget() == node) 84 node->document()->setCSSTarget(0); 85 86 if (ElementShadow* shadow = toElement(node)->shadow()) { 87 ShadowRootVector roots(shadow); 88 for (size_t i = 0; i < roots.size(); ++i) { 89 if (!node->inDocument() && roots[i]->host() == node) 90 notifyNodeRemovedFromDocument(roots[i].get()); 91 } 92 } 93 } 94 95 void ChildNodeRemovalNotifier::notifyDescendantRemovedFromTree(ContainerNode* node) 96 { 97 for (Node* child = node->firstChild(); child; child = child->nextSibling()) { 98 if (child->isContainerNode()) 99 notifyNodeRemovedFromTree(toContainerNode(child)); 100 } 101 102 if (!node->isElementNode()) 103 return; 104 105 if (ElementShadow* shadow = toElement(node)->shadow()) { 106 ShadowRootVector roots(shadow); 107 for (size_t i = 0; i < roots.size(); ++i) 108 notifyNodeRemovedFromTree(roots[i].get()); 109 } 110 } 111 112 void ChildFrameDisconnector::collectFrameOwners(ElementShadow* shadow) 113 { 114 for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot()) 115 collectFrameOwners(root); 116 } 117 118 #ifndef NDEBUG 119 unsigned assertConnectedSubrameCountIsConsistent(Node* node) 120 { 121 unsigned count = 0; 122 123 if (node->isElementNode()) { 124 if (node->isFrameOwnerElement() && toFrameOwnerElement(node)->contentFrame()) 125 count++; 126 127 if (ElementShadow* shadow = toElement(node)->shadow()) { 128 for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot()) 129 count += assertConnectedSubrameCountIsConsistent(root); 130 } 131 } 132 133 for (Node* child = node->firstChild(); child; child = child->nextSibling()) 134 count += assertConnectedSubrameCountIsConsistent(child); 135 136 // If we undercount there's possibly a security bug since we'd leave frames 137 // in subtrees outside the document. 138 ASSERT(node->connectedSubframeCount() >= count); 139 140 // If we overcount it's safe, but not optimal because it means we'll traverse 141 // through the document in ChildFrameDisconnector looking for frames that have 142 // already been disconnected. 143 ASSERT(node->connectedSubframeCount() == count); 144 145 return count; 146 } 147 #endif 148 149 } 150