Commit 8809405d authored by japhet@chromium.org's avatar japhet@chromium.org

Source/WebCore: Unload events can crash us when they blank out

a parent frame.
https://bugs.webkit.org/show_bug.cgi?id=64741

Reviewed by Adam Barth.

Test: fast/loader/document-destruction-within-unload.html

* loader/FrameLoader.cpp:
(WebCore::FrameLoader::stopLoading): Prevent unload events
    from going into infinite recursion.
(WebCore::FrameLoader::setDocumentLoader): Ensure we don't
    let set m_documentLoader to a DocumentLoader with a null Frame*.
(WebCore::FrameLoader::detachChildren): Save off a vector of
    children to detach, rather than doing it inline.

LayoutTests: Test for https://bugs.webkit.org/show_bug.cgi?id=64741.

Reviewed by Adam Barth.

* fast/loader/document-destruction-within-unload-expected.txt: Added.
* fast/loader/document-destruction-within-unload.html: Added.
* fast/loader/resources/document-destruction-within-unload-iframe.html: Added.
* fast/loader/resources/document-destruction-within-unload.svg: Added.


git-svn-id: svn://svn.chromium.org/blink/trunk@93521 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 97ae7c2a
2011-08-22 Nate Chapin <japhet@chromium.org>
Test for https://bugs.webkit.org/show_bug.cgi?id=64741.
Reviewed by Adam Barth.
* fast/loader/document-destruction-within-unload-expected.txt: Added.
* fast/loader/document-destruction-within-unload.html: Added.
* fast/loader/resources/document-destruction-within-unload-iframe.html: Added.
* fast/loader/resources/document-destruction-within-unload.svg: Added.
2011-08-22 Adrienne Walker <enne@google.com>
[chromium] Skip rtl-composited, as it causes other tests to crash.
<html>
<body>
<script>
if (window.layoutTestController) {
layoutTestController.dumpAsText();
layoutTestController.waitUntilDone();
}
function done() {
if (window.layoutTestController)
layoutTestController.notifyDone();
}
</script>
<iframe src="resources/document-destruction-within-unload-iframe.html"></iframe>
<p>For the test to pass there should be no crash.</p>
</body>
</html>
<html>
<body>
<script>
function runTest() {
var test = document.getElementById('root').contentDocument;
test.firstChild.setAttribute('onunload', "parent.clearUs();");
location.reload();
}
function clearUs() {
document.write();
parent.done();
}
</script>
<object data="does_not_exist"></object>
<object data="document-destruction-within-unload.svg" id="root" onload="runTest();"></object>
</body>
</html>
2011-08-22 Nate Chapin <japhet@chromium.org>
Unload events can crash us when they blank out
a parent frame.
https://bugs.webkit.org/show_bug.cgi?id=64741
Reviewed by Adam Barth.
Test: fast/loader/document-destruction-within-unload.html
* loader/FrameLoader.cpp:
(WebCore::FrameLoader::stopLoading): Prevent unload events
from going into infinite recursion.
(WebCore::FrameLoader::setDocumentLoader): Ensure we don't
let set m_documentLoader to a DocumentLoader with a null Frame*.
(WebCore::FrameLoader::detachChildren): Save off a vector of
children to detach, rather than doing it inline.
2011-08-22 Young Han Lee <joybro@company100.net>
Reviewed by Dirk Schulze.
......@@ -372,7 +372,7 @@ void FrameLoader::stopLoading(UnloadEventPolicy unloadEventPolicy)
Node* currentFocusedNode = m_frame->document()->focusedNode();
if (currentFocusedNode)
currentFocusedNode->aboutToUnload();
if (m_frame->domWindow()) {
if (m_frame->domWindow() && m_pageDismissalEventBeingDispatched == NoDismissal) {
if (unloadEventPolicy == UnloadEventPolicyUnloadAndPageHide) {
m_pageDismissalEventBeingDispatched = PageHideDismissal;
m_frame->domWindow()->dispatchEvent(PageTransitionEvent::create(eventNames().pagehideEvent, m_frame->document()->inPageCache()), m_frame->document());
......@@ -1686,6 +1686,20 @@ void FrameLoader::setDocumentLoader(DocumentLoader* loader)
m_documentLoader->detachFromFrame();
m_documentLoader = loader;
// The following abomination is brought to you by the unload event.
// The detachChildren() call above may trigger a child frame's unload event,
// which could do something obnoxious like call document.write("") on
// the main frame, which results in detaching children while detaching children.
// This can cause the new m_documentLoader to be detached from its Frame*, but still
// be alive. To make matters worse, DocumentLoaders with a null Frame* aren't supposed
// to happen when they're still alive (and many places below us on the stack think the
// DocumentLoader is still usable). Ergo, we reattach loader to its Frame, and pretend
// like nothing ever happened.
if (m_documentLoader && !m_documentLoader->frame()) {
ASSERT(!m_documentLoader->isLoading());
m_documentLoader->setFrame(m_frame);
}
}
void FrameLoader::setPolicyDocumentLoader(DocumentLoader* loader)
......@@ -2362,12 +2376,14 @@ void FrameLoader::frameLoadCompleted()
void FrameLoader::detachChildren()
{
// FIXME: Is it really necessary to do this in reverse order?
Frame* previous;
for (Frame* child = m_frame->tree()->lastChild(); child; child = previous) {
previous = child->tree()->previousSibling();
child->loader()->detachFromParent();
}
typedef Vector<RefPtr<Frame> > FrameVector;
FrameVector childrenToDetach;
childrenToDetach.reserveCapacity(m_frame->tree()->childCount());
for (Frame* child = m_frame->tree()->lastChild(); child; child = child->tree()->previousSibling())
childrenToDetach.append(child);
FrameVector::iterator end = childrenToDetach.end();
for (FrameVector::iterator it = childrenToDetach.begin(); it != end; it++)
(*it)->loader()->detachFromParent();
}
void FrameLoader::closeAndRemoveChild(Frame* child)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment