Title: [161567] trunk/Source/WebCore
- Revision
- 161567
- Author
- [email protected]
- Date
- 2014-01-09 12:09:53 -0800 (Thu, 09 Jan 2014)
Log Message
Disconnect child frames iteratively
https://bugs.webkit.org/show_bug.cgi?id=126700
Reviewed by Andreas Kling.
Use descendant iterator instead of recursion for traversal.
* dom/ContainerNode.cpp:
(WebCore::willRemoveChild):
(WebCore::willRemoveChildren):
(WebCore::ContainerNode::disconnectDescendantFrames):
* dom/ContainerNodeAlgorithms.cpp:
(WebCore::assertConnectedSubrameCountIsConsistent):
(WebCore::collectFrameOwners):
(WebCore::disconnectSubframes):
Get rid of the strange ChildFrameDisconnector class in favor of a function.
* dom/ContainerNodeAlgorithms.h:
(WebCore::disconnectSubframesIfNeeded):
Modified Paths
Diff
Modified: trunk/Source/WebCore/ChangeLog (161566 => 161567)
--- trunk/Source/WebCore/ChangeLog 2014-01-09 19:38:41 UTC (rev 161566)
+++ trunk/Source/WebCore/ChangeLog 2014-01-09 20:09:53 UTC (rev 161567)
@@ -1,3 +1,26 @@
+2014-01-09 Antti Koivisto <[email protected]>
+
+ Disconnect child frames iteratively
+ https://bugs.webkit.org/show_bug.cgi?id=126700
+
+ Reviewed by Andreas Kling.
+
+ Use descendant iterator instead of recursion for traversal.
+
+ * dom/ContainerNode.cpp:
+ (WebCore::willRemoveChild):
+ (WebCore::willRemoveChildren):
+ (WebCore::ContainerNode::disconnectDescendantFrames):
+ * dom/ContainerNodeAlgorithms.cpp:
+ (WebCore::assertConnectedSubrameCountIsConsistent):
+ (WebCore::collectFrameOwners):
+ (WebCore::disconnectSubframes):
+
+ Get rid of the strange ChildFrameDisconnector class in favor of a function.
+
+ * dom/ContainerNodeAlgorithms.h:
+ (WebCore::disconnectSubframesIfNeeded):
+
2014-01-09 Joseph Pecoraro <[email protected]>
Unreviewed Windows build fix for r161563.
Modified: trunk/Source/WebCore/dom/ContainerNode.cpp (161566 => 161567)
--- trunk/Source/WebCore/dom/ContainerNode.cpp 2014-01-09 19:38:41 UTC (rev 161566)
+++ trunk/Source/WebCore/dom/ContainerNode.cpp 2014-01-09 20:09:53 UTC (rev 161567)
@@ -489,7 +489,7 @@
dispatchChildRemovalEvents(child);
child.document().nodeWillBeRemoved(&child); // e.g. mutation event listener can create a new range.
if (child.isContainerNode())
- ChildFrameDisconnector(toContainerNode(child)).disconnect();
+ disconnectSubframesIfNeeded(toContainerNode(child), RootAndDescendants);
}
static void willRemoveChildren(ContainerNode& container)
@@ -509,12 +509,12 @@
container.document().nodeChildrenWillBeRemoved(container);
- ChildFrameDisconnector(container).disconnect(ChildFrameDisconnector::DescendantsOnly);
+ disconnectSubframesIfNeeded(container, DescendantsOnly);
}
void ContainerNode::disconnectDescendantFrames()
{
- ChildFrameDisconnector(*this).disconnect();
+ disconnectSubframesIfNeeded(*this, RootAndDescendants);
}
bool ContainerNode::removeChild(Node* oldChild, ExceptionCode& ec)
Modified: trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp (161566 => 161567)
--- trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp 2014-01-09 19:38:41 UTC (rev 161566)
+++ trunk/Source/WebCore/dom/ContainerNodeAlgorithms.cpp 2014-01-09 20:09:53 UTC (rev 161567)
@@ -98,7 +98,7 @@
}
#ifndef NDEBUG
-unsigned assertConnectedSubrameCountIsConsistent(Node& node)
+static unsigned assertConnectedSubrameCountIsConsistent(ContainerNode& node)
{
unsigned count = 0;
@@ -110,15 +110,15 @@
count += assertConnectedSubrameCountIsConsistent(*root);
}
- for (Node* child = node.firstChild(); child; child = child->nextSibling())
- count += assertConnectedSubrameCountIsConsistent(*child);
+ for (auto& child : childrenOfType<Element>(node))
+ count += assertConnectedSubrameCountIsConsistent(child);
// If we undercount there's possibly a security bug since we'd leave frames
// in subtrees outside the document.
ASSERT(node.connectedSubframeCount() >= count);
// If we overcount it's safe, but not optimal because it means we'll traverse
- // through the document in ChildFrameDisconnector looking for frames that have
+ // through the document in disconnectSubframes looking for frames that have
// already been disconnected.
ASSERT(node.connectedSubframeCount() == count);
@@ -126,4 +126,54 @@
}
#endif
+static void collectFrameOwners(Vector<Ref<HTMLFrameOwnerElement>>& frameOwners, ContainerNode& root)
+{
+ auto elementDescendants = descendantsOfType<Element>(root);
+ auto it = elementDescendants.begin();
+ auto end = elementDescendants.end();
+ while (it != end) {
+ Element& element = *it;
+ if (!element.connectedSubframeCount()) {
+ it.traverseNextSkippingChildren();
+ continue;
+ }
+
+ if (element.isHTMLElement() && element.isFrameOwnerElement())
+ frameOwners.append(toHTMLFrameOwnerElement(element));
+
+ if (ShadowRoot* shadowRoot = element.shadowRoot())
+ collectFrameOwners(frameOwners, *shadowRoot);
+ ++it;
+ }
}
+
+void disconnectSubframes(ContainerNode& root, SubframeDisconnectPolicy policy)
+{
+#ifndef NDEBUG
+ assertConnectedSubrameCountIsConsistent(root);
+#endif
+ ASSERT(root.connectedSubframeCount());
+
+ Vector<Ref<HTMLFrameOwnerElement>> frameOwners;
+
+ if (policy == RootAndDescendants) {
+ if (root.isHTMLElement() && root.isFrameOwnerElement())
+ frameOwners.append(toHTMLFrameOwnerElement(root));
+ }
+
+ collectFrameOwners(frameOwners, root);
+
+ // Must disable frame loading in the subtree so an unload handler cannot
+ // insert more frames and create loaded frames in detached subtrees.
+ SubframeLoadingDisabler disabler(root);
+
+ for (unsigned i = 0; i < frameOwners.size(); ++i) {
+ auto& owner = frameOwners[i].get();
+ // Don't need to traverse up the tree for the first owner since no
+ // script could have moved it.
+ if (!i || root.containsIncludingShadowDOM(&owner))
+ owner.disconnectContentFrame();
+ }
+}
+
+}
Modified: trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h (161566 => 161567)
--- trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h 2014-01-09 19:38:41 UTC (rev 161566)
+++ trunk/Source/WebCore/dom/ContainerNodeAlgorithms.h 2014-01-09 20:09:53 UTC (rev 161567)
@@ -23,7 +23,7 @@
#define ContainerNodeAlgorithms_h
#include "Document.h"
-#include "ElementTraversal.h"
+#include "ElementIterator.h"
#include "Frame.h"
#include "HTMLFrameOwnerElement.h"
#include "InspectorInstrumentation.h"
@@ -262,82 +262,19 @@
notifyNodeRemovedFromTree(toContainerNode(node));
}
-class ChildFrameDisconnector {
-public:
- enum DisconnectPolicy {
- RootAndDescendants,
- DescendantsOnly
- };
-
- explicit ChildFrameDisconnector(ContainerNode& root)
- : m_root(root)
- {
- }
-
- void disconnect(DisconnectPolicy = RootAndDescendants);
-
-private:
- void collectFrameOwners(ContainerNode& root);
- void disconnectCollectedFrameOwners();
-
- Vector<Ref<HTMLFrameOwnerElement>, 10> m_frameOwners;
- ContainerNode& m_root;
+enum SubframeDisconnectPolicy {
+ RootAndDescendants,
+ DescendantsOnly
};
+void disconnectSubframes(ContainerNode& root, SubframeDisconnectPolicy);
-#ifndef NDEBUG
-unsigned assertConnectedSubrameCountIsConsistent(Node&);
-#endif
-
-inline void ChildFrameDisconnector::collectFrameOwners(ContainerNode& root)
+inline void disconnectSubframesIfNeeded(ContainerNode& root, SubframeDisconnectPolicy policy)
{
if (!root.connectedSubframeCount())
return;
-
- if (root.isHTMLElement() && root.isFrameOwnerElement())
- m_frameOwners.append(toHTMLFrameOwnerElement(root));
-
- for (Element* child = ElementTraversal::firstChild(&root); child; child = ElementTraversal::nextSibling(child))
- collectFrameOwners(*child);
-
- ShadowRoot* shadow = root.isElementNode() ? toElement(root).shadowRoot() : 0;
- if (shadow)
- collectFrameOwners(*shadow);
+ disconnectSubframes(root, policy);
}
-inline void ChildFrameDisconnector::disconnectCollectedFrameOwners()
-{
- // Must disable frame loading in the subtree so an unload handler cannot
- // insert more frames and create loaded frames in detached subtrees.
- SubframeLoadingDisabler disabler(m_root);
-
- for (unsigned i = 0; i < m_frameOwners.size(); ++i) {
- HTMLFrameOwnerElement& owner = m_frameOwners[i].get();
- // Don't need to traverse up the tree for the first owner since no
- // script could have moved it.
- if (!i || m_root.containsIncludingShadowDOM(&owner))
- owner.disconnectContentFrame();
- }
-}
-
-inline void ChildFrameDisconnector::disconnect(DisconnectPolicy policy)
-{
-#ifndef NDEBUG
- assertConnectedSubrameCountIsConsistent(m_root);
-#endif
-
- if (!m_root.connectedSubframeCount())
- return;
-
- if (policy == RootAndDescendants)
- collectFrameOwners(m_root);
- else {
- for (Element* child = ElementTraversal::firstChild(&m_root); child; child = ElementTraversal::nextSibling(child))
- collectFrameOwners(*child);
- }
-
- disconnectCollectedFrameOwners();
-}
-
} // namespace WebCore
#endif // ContainerNodeAlgorithms_h
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes