Changeset 140807 in webkit
- Timestamp:
- Jan 25, 2013 2:48:14 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 9 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r140803 r140807 1 2013-01-25 Elliott Sprehn <esprehn@gmail.com> 2 3 Assert the connectedSubframeCount is consistent and fix over counting 4 https://bugs.webkit.org/show_bug.cgi?id=107302 5 6 Reviewed by Alexey Proskuryakov. 7 8 Add a test that removing an iframe in the middle of unload causes the 9 contentDocument to become immediately inaccessible. 10 11 * fast/frames/reparent-in-unload-contentdocument-expected.txt: Added. 12 * fast/frames/reparent-in-unload-contentdocument.html: Added. 13 1 14 2013-01-25 Kent Tamura <tkent@chromium.org> 2 15 -
trunk/Source/WebCore/ChangeLog
r140805 r140807 1 2013-01-25 Elliott Sprehn <esprehn@gmail.com> 2 3 Assert the connectedSubframeCount is consistent and fix over counting 4 https://bugs.webkit.org/show_bug.cgi?id=107302 5 6 Reviewed by Alexey Proskuryakov. 7 8 Add a debug assertion that walks the subtree during frame disconnection 9 and manually counts the number of connected subframes to assert that the 10 value from Node::connectedSubframeCount() is the same as if we traversed 11 through the tree. 12 13 In fixing the places where this assertion failed I made document destruction 14 faster by not walking the entire document looking for frames if the entire 15 frame tree has been destroyed by way of FrameLoader::detachChildren(). 16 I had inadvertently introduced this improvement in r133933, but then I 17 regressed it in r140090 when we switched to counting because I didn't 18 realize we destroy the frame tree separate of frame disconnection on 19 document unload so all frames could have been destroyed but the counts 20 left on the ancestors. 21 22 I also fixed another overcounting case where the adoption agency algorithm 23 may call ContainerNode::takeAllChildrenFrom() which in turn calls 24 ContainerNode::removeAllChildren() and could have left a connected subframe 25 count on the node even though all the frames had been removed. 26 27 This assertion did not uncover any cases of undercounting the number of 28 frames. 29 30 This also fixes a rare edge case where removeChild of an iframe that 31 was already being unloaded would not unload the frame until the top level 32 unload was done, and a reparenting of the iframe would not cause it to load. 33 34 Test: fast/frames/reparent-in-unload-contentdocument.html 35 36 * dom/ContainerNode.cpp: 37 (WebCore::ContainerNode::removeAllChildren): 38 (WebCore::ContainerNode::parserInsertBefore): 39 (WebCore::ContainerNode::parserRemoveChild): 40 (WebCore::ContainerNode::parserAppendChild): 41 * dom/ContainerNodeAlgorithms.cpp: 42 (WebCore): 43 (WebCore::assertConnectedSubframeCountIsConsistent): 44 * dom/ContainerNodeAlgorithms.h: 45 (WebCore): 46 (WebCore::ChildFrameDisconnector::disconnect): 47 * dom/Node.cpp: 48 (WebCore::Node::updateAncestorConnectedSubframeCountForRemoval): 49 (WebCore): 50 (WebCore::Node::updateAncestorConnectedSubframeCountForInsertion): 51 * dom/Node.h: 52 (Node): 53 * html/HTMLFrameOwnerElement.cpp: 54 (WebCore::HTMLFrameOwnerElement::clearContentFrame): 55 (WebCore): 56 (WebCore::HTMLFrameOwnerElement::disconnectContentFrame): 57 * html/HTMLFrameOwnerElement.h: 58 (HTMLFrameOwnerElement): 59 1 60 2013-01-25 Pavel Feldman <pfeldman@chromium.org> 2 61 -
trunk/Source/WebCore/dom/ContainerNode.cpp
r140784 r140807 93 93 void ContainerNode::removeDetachedChildren() 94 94 { 95 if (connectedSubframeCount()) { 96 for (Node* child = firstChild(); child; child = child->nextSibling()) 97 child->updateAncestorConnectedSubframeCountForRemoval(); 98 } 95 99 // FIXME: We should be able to ASSERT(!attached()) here: https://bugs.webkit.org/show_bug.cgi?id=107801 96 100 removeDetachedChildrenInContainer<Node, ContainerNode>(this); … … 333 337 insertBeforeCommon(nextChild, newChild.get()); 334 338 335 if (unsigned count = newChild->connectedSubframeCount()) { 336 for (Node* node = newChild->parentOrHostNode(); node; node = node->parentOrHostNode()) 337 node->incrementConnectedSubframeCount(count); 338 } 339 newChild->updateAncestorConnectedSubframeCountForInsertion(); 339 340 340 341 childrenChanged(true, newChild->previousSibling(), nextChild, 1); … … 559 560 Node* next = oldChild->nextSibling(); 560 561 561 if (unsigned count = oldChild->connectedSubframeCount()) { 562 for (Node* node = oldChild->parentOrHostNode(); node; node = node->parentOrHostNode()) 563 node->decrementConnectedSubframeCount(count); 564 } 562 oldChild->updateAncestorConnectedSubframeCountForRemoval(); 565 563 566 564 removeBetween(prev, next, oldChild); … … 708 706 } 709 707 710 if (unsigned count = newChild->connectedSubframeCount()) { 711 for (Node* node = newChild->parentOrHostNode(); node; node = node->parentOrHostNode()) 712 node->incrementConnectedSubframeCount(count); 713 } 708 newChild->updateAncestorConnectedSubframeCountForInsertion(); 714 709 715 710 childrenChanged(true, last, 0, 1); -
trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp
r140090 r140807 122 122 } 123 123 124 #ifndef NDEBUG 125 unsigned assertConnectedSubrameCountIsConsistent(Node* node) 126 { 127 unsigned count = 0; 128 129 if (node->isElementNode()) { 130 if (node->isFrameOwnerElement() && toFrameOwnerElement(node)->contentFrame()) 131 count++; 132 133 if (ElementShadow* shadow = toElement(node)->shadow()) { 134 for (ShadowRoot* root = shadow->youngestShadowRoot(); root; root = root->olderShadowRoot()) 135 count += assertConnectedSubrameCountIsConsistent(root); 136 } 137 } 138 139 for (Node* child = node->firstChild(); child; child = child->nextSibling()) 140 count += assertConnectedSubrameCountIsConsistent(child); 141 142 // If we undercount there's possibly a security bug since we'd leave frames 143 // in subtrees outside the document. 144 ASSERT(node->connectedSubframeCount() >= count); 145 146 // If we overcount it's safe, but not optimal because it means we'll traverse 147 // through the document in ChildFrameDisconnector looking for frames that have 148 // already been disconnected. 149 ASSERT(node->connectedSubframeCount() == count); 150 151 return count; 124 152 } 153 #endif 154 155 } -
trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h
r140784 r140807 298 298 }; 299 299 300 #ifndef NDEBUG 301 unsigned assertConnectedSubrameCountIsConsistent(Node*); 302 #endif 303 300 304 inline void ChildFrameDisconnector::collectFrameOwners(Node* root) 301 305 { … … 331 335 inline void ChildFrameDisconnector::disconnect(DisconnectPolicy policy) 332 336 { 337 #ifndef NDEBUG 338 assertConnectedSubrameCountIsConsistent(m_root); 339 #endif 340 333 341 if (!m_root->connectedSubframeCount()) 334 342 return; -
trunk/Source/WebCore/dom/Node.cpp
r140745 r140807 2621 2621 } 2622 2622 2623 void Node::updateAncestorConnectedSubframeCountForRemoval() const 2624 { 2625 unsigned count = connectedSubframeCount(); 2626 2627 if (!count) 2628 return; 2629 2630 for (Node* node = parentOrHostNode(); node; node = node->parentOrHostNode()) 2631 node->decrementConnectedSubframeCount(count); 2632 } 2633 2634 void Node::updateAncestorConnectedSubframeCountForInsertion() const 2635 { 2636 unsigned count = connectedSubframeCount(); 2637 2638 if (!count) 2639 return; 2640 2641 for (Node* node = parentOrHostNode(); node; node = node->parentOrHostNode()) 2642 node->incrementConnectedSubframeCount(count); 2643 } 2644 2623 2645 void Node::registerScopedHTMLStyleChild() 2624 2646 { -
trunk/Source/WebCore/dom/Node.h
r140546 r140807 682 682 void incrementConnectedSubframeCount(unsigned amount = 1); 683 683 void decrementConnectedSubframeCount(unsigned amount = 1); 684 void updateAncestorConnectedSubframeCountForRemoval() const; 685 void updateAncestorConnectedSubframeCountForInsertion() const; 684 686 685 687 private: -
trunk/Source/WebCore/html/HTMLFrameOwnerElement.cpp
r140090 r140807 63 63 } 64 64 65 void HTMLFrameOwnerElement::clearContentFrame() 66 { 67 if (!m_contentFrame) 68 return; 69 70 m_contentFrame = 0; 71 72 for (ContainerNode* node = this; node; node = node->parentOrHostNode()) 73 node->decrementConnectedSubframeCount(); 74 } 75 65 76 void HTMLFrameOwnerElement::disconnectContentFrame() 66 77 { … … 71 82 // see if this behavior is really needed as Gecko does not allow this. 72 83 if (Frame* frame = contentFrame()) { 73 for (ContainerNode* node = this; node; node = node->parentOrHostNode())74 node->decrementConnectedSubframeCount();75 76 84 RefPtr<Frame> protect(frame); 77 85 frame->loader()->frameDetached(); -
trunk/Source/WebCore/html/HTMLFrameOwnerElement.h
r134775 r140807 44 44 45 45 void setContentFrame(Frame*); 46 void clearContentFrame() { m_contentFrame = 0; }46 void clearContentFrame(); 47 47 48 48 void disconnectContentFrame();
Note: See TracChangeset
for help on using the changeset viewer.