1d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)// found in the LICENSE file. 4d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 5d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "config.h" 6d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/dom/ChildFrameDisconnector.h" 7d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 8d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/dom/shadow/ElementShadow.h" 9d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/dom/shadow/ShadowRoot.h" 1076c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)#include "core/html/HTMLFrameOwnerElement.h" 11d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "wtf/Assertions.h" 12d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 13c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 14d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 15197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 165d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static unsigned checkConnectedSubframeCountIsConsistent(Node&); 17d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif 18d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 19d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void ChildFrameDisconnector::disconnect(DisconnectPolicy policy) 20d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 21197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 22c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) checkConnectedSubframeCountIsConsistent(root()); 23d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif 24d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 25c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!root().connectedSubframeCount()) 26d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return; 27d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 28d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (policy == RootAndDescendants) { 29c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) collectFrameOwners(root()); 30d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } else { 31c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) for (Node* child = root().firstChild(); child; child = child->nextSibling()) 32d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) collectFrameOwners(*child); 33d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 34d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 35d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) disconnectCollectedFrameOwners(); 36d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 37d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 38d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void ChildFrameDisconnector::collectFrameOwners(Node& root) 39d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 40d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (!root.connectedSubframeCount()) 41d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return; 42d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 43d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (root.isHTMLElement() && root.isFrameOwnerElement()) 44d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) m_frameOwners.append(&toHTMLFrameOwnerElement(root)); 45d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 46d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) for (Node* child = root.firstChild(); child; child = child->nextSibling()) 47d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) collectFrameOwners(*child); 48d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 49d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ElementShadow* shadow = root.isElementNode() ? toElement(root).shadow() : 0; 50d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (shadow) 51d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) collectFrameOwners(*shadow); 52d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 53d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 54d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void ChildFrameDisconnector::disconnectCollectedFrameOwners() 55d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 56d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // Must disable frame loading in the subtree so an unload handler cannot 57d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // insert more frames and create loaded frames in detached subtrees. 58c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) SubframeLoadingDisabler disabler(root()); 59d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 60d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) for (unsigned i = 0; i < m_frameOwners.size(); ++i) { 61d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) HTMLFrameOwnerElement* owner = m_frameOwners[i].get(); 62d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // Don't need to traverse up the tree for the first owner since no 63d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // script could have moved it. 64c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles) if (!i || root().containsIncludingShadowDOM(owner)) 65d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) owner->disconnectContentFrame(); 66d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 67d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 68d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 69d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)void ChildFrameDisconnector::collectFrameOwners(ElementShadow& shadow) 70d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 71d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) for (ShadowRoot* root = shadow.youngestShadowRoot(); root; root = root->olderShadowRoot()) 72d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) collectFrameOwners(*root); 73d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 74d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 75197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#if ENABLE(ASSERT) 765d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)static unsigned checkConnectedSubframeCountIsConsistent(Node& node) 77d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles){ 78d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) unsigned count = 0; 79d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 80d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (node.isElementNode()) { 81d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (node.isFrameOwnerElement() && toHTMLFrameOwnerElement(node).contentFrame()) 82d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) count++; 83d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 84d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) if (ElementShadow* shadow = toElement(node).shadow()) { 85d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot()) 865d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) count += checkConnectedSubframeCountIsConsistent(*root); 87d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 88d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) } 89d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 90d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) for (Node* child = node.firstChild(); child; child = child->nextSibling()) 915d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles) count += checkConnectedSubframeCountIsConsistent(*child); 92d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 93d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // If we undercount there's possibly a security bug since we'd leave frames 94d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // in subtrees outside the document. 95d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ASSERT(node.connectedSubframeCount() >= count); 96d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 97d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // If we overcount it's safe, but not optimal because it means we'll traverse 98d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // through the document in ChildFrameDisconnector looking for frames that have 99d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) // already been disconnected. 100d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) ASSERT(node.connectedSubframeCount() == count); 101d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 102d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) return count; 103d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 104d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#endif 105d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles) 106d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)} 107