+2015-11-30 Jiewen Tan <jiewen_tan@apple.com>
+
+ Null dereference loading Blink layout test http/tests/misc/detach-during-notifyDone.html
+ https://bugs.webkit.org/show_bug.cgi?id=149309
+ <rdar://problem/22748363>
+
+ Reviewed by Brent Fulgham.
+
+ The test case is from Blink r175601:
+ https://codereview.chromium.org/317513002
+ The test case will generate a set of weird ordering events that affects the documentLoader:
+ 1. The subframe finishes loading, and since the frame’s testRunner is not set to wait until
+ done, WebKitTestRunner stops the load (by calling WKBundlePageStopLoading()).
+ 2. This causes the in-progress XHR to be aborted, which causes its readyState to become DONE
+ (this bug doesn’t always reproduce because sometimes the XHR has already finished before the
+ frame finishes loading).
+ 3. The onreadystatechange callback is executed, which sets innerHTML on the parent frame.
+ 4. Setting innerHTML disconnects the subframe, nulling out its DocumentLoader.
+ 5. We return to WebFrameLoaderClient::dispatchDidFinishLoad() from step #1, but now the
+ FrameLoader’s DocumentLoader is null. And WebKit crashes here.
+
+ Note that steps 2-4 happen synchronously inside WebFrameLoaderClient::dispatchDidFinishLoad().
+
+ * http/tests/misc/detach-during-notifyDone-expected.txt: Added.
+ * http/tests/misc/detach-during-notifyDone.html: Added.
+ * http/tests/misc/resources/detached-frame.html: Added.
+
2015-11-30 Commit Queue <commit-queue@webkit.org>
Unreviewed, rolling out r192819.
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationAnchorNavigation, userData);
// Notify the UIProcess.
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
- webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationAnchorNavigation, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchDidPushStateWithinPage()
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStatePush, userData);
// Notify the UIProcess.
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
- webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePush, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchDidReplaceStateWithinPage()
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStateReplace, userData);
// Notify the UIProcess.
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
- webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStateReplace, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchDidPopStateWithinPage()
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didSameDocumentNavigationForFrame(webPage, m_frame, SameDocumentNavigationSessionStatePop, userData);
// Notify the UIProcess.
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
- webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), documentLoader.navigationID(), SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidSameDocumentNavigationForFrame(m_frame->frameID(), navigationID, SameDocumentNavigationSessionStatePop, m_frame->coreFrame()->document()->url().string(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchWillClose()
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didFailLoadWithErrorForFrame(webPage, m_frame, error, userData);
// Notify the UIProcess.
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
- webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidFailLoadForFrame(m_frame->frameID(), navigationID, error, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
// If we have a load listener, notify it.
if (WebFrame::LoadListener* loadListener = m_frame->loadListener())
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didFinishDocumentLoadForFrame(webPage, m_frame, userData);
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
-
// Notify the UIProcess.
- webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidFinishDocumentLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
}
void WebFrameLoaderClient::dispatchDidFinishLoad()
RefPtr<API::Object> userData;
+ auto navigationID = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader()).navigationID();
+
// Notify the bundle client.
webPage->injectedBundleLoaderClient().didFinishLoadForFrame(webPage, m_frame, userData);
- WebDocumentLoader& documentLoader = static_cast<WebDocumentLoader&>(*m_frame->coreFrame()->loader().documentLoader());
-
// Notify the UIProcess.
- webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), documentLoader.navigationID(), UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
+ webPage->send(Messages::WebPageProxy::DidFinishLoadForFrame(m_frame->frameID(), navigationID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())));
// If we have a load listener, notify it.
if (WebFrame::LoadListener* loadListener = m_frame->loadListener())