Title: [181991] trunk/Source/WebKit2
Revision
181991
Author
[email protected]
Date
2015-03-25 19:36:08 -0700 (Wed, 25 Mar 2015)

Log Message

[WK2] WebFrameLoaderClient::dispatchDecidePolicyForResponse() should always call the FramePolicyFunction
https://bugs.webkit.org/show_bug.cgi?id=143036
<rdar://problem/20252438>
<rdar://problem/13811738>

Reviewed by Alexey Proskuryakov.

WebFrameLoaderClient::dispatchDecidePolicyForResponse() should always
call the FramePolicyFunction. Previously, it would fail to do in 2
cases:
- m_frame->page() returns null
or
- webPage->sendSync() returns false

If the FramePolicyFunction is not called, we will fail to clear the
callback in the PolicyChecker and
DocumentLoader::continueAfterContentPolicy() will not be called.

DocumentLoader::continueAfterContentPolicy() is in charge of resetting
m_waitingForContentPolicy flag to false. This could therefore explain
the following assertion being hit in DocumentLoader::detachFromFrame()
(see <rdar://problem/20252438>):
RELEASE_ASSERT(!m_waitingForContentPolicy)

Also, as the PolicyChecker callback is not cleared, it could make it
possible for DocumentLoader::continueAfterContentPolicy() to be called
*after* the load is finished, when later canceling the PolicyCallback:
FrameLoader::stopAllLoaders()
 -> PolicyChecker::stopCheck()
  -> PolicyCallback::cancel()
   -> DocumentLoader::continueAfterContentPolicy(PolicyIgnore)

Calling continueAfterContentPolicy(PolicyIgnore) after the load is
finished would be bad and could explain some of the crashes we've seen
in DocumentLoader::continueAfterContentPolicy() ->
DocumentLoader:: stopLoadingForPolicyChange() (see
<rdar://problem/13811738>).

This patch also applies the same fix to
dispatchDecidePolicyForNewWindowAction() and
dispatchDecidePolicyForNavigationAction() as they use the same pattern.

* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction):
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (181990 => 181991)


--- trunk/Source/WebKit2/ChangeLog	2015-03-26 01:26:56 UTC (rev 181990)
+++ trunk/Source/WebKit2/ChangeLog	2015-03-26 02:36:08 UTC (rev 181991)
@@ -1,3 +1,52 @@
+2015-03-25  Chris Dumez  <[email protected]>
+
+        [WK2] WebFrameLoaderClient::dispatchDecidePolicyForResponse() should always call the FramePolicyFunction
+        https://bugs.webkit.org/show_bug.cgi?id=143036
+        <rdar://problem/20252438>
+        <rdar://problem/13811738>
+
+        Reviewed by Alexey Proskuryakov.
+
+        WebFrameLoaderClient::dispatchDecidePolicyForResponse() should always
+        call the FramePolicyFunction. Previously, it would fail to do in 2
+        cases:
+        - m_frame->page() returns null
+        or
+        - webPage->sendSync() returns false
+
+        If the FramePolicyFunction is not called, we will fail to clear the
+        callback in the PolicyChecker and
+        DocumentLoader::continueAfterContentPolicy() will not be called.
+
+        DocumentLoader::continueAfterContentPolicy() is in charge of resetting
+        m_waitingForContentPolicy flag to false. This could therefore explain
+        the following assertion being hit in DocumentLoader::detachFromFrame()
+        (see <rdar://problem/20252438>):
+        RELEASE_ASSERT(!m_waitingForContentPolicy)
+
+        Also, as the PolicyChecker callback is not cleared, it could make it
+        possible for DocumentLoader::continueAfterContentPolicy() to be called
+        *after* the load is finished, when later canceling the PolicyCallback:
+        FrameLoader::stopAllLoaders()
+         -> PolicyChecker::stopCheck()
+          -> PolicyCallback::cancel()
+           -> DocumentLoader::continueAfterContentPolicy(PolicyIgnore)
+
+        Calling continueAfterContentPolicy(PolicyIgnore) after the load is
+        finished would be bad and could explain some of the crashes we've seen
+        in DocumentLoader::continueAfterContentPolicy() ->
+        DocumentLoader:: stopLoadingForPolicyChange() (see
+        <rdar://problem/13811738>).
+
+        This patch also applies the same fix to
+        dispatchDecidePolicyForNewWindowAction() and
+        dispatchDecidePolicyForNavigationAction() as they use the same pattern.
+
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction):
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
+
 2015-03-25  Tim Horton  <[email protected]>
 
         Add a preference to prevent "user-scalable=no" from having any effect

Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (181990 => 181991)


--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2015-03-26 01:26:56 UTC (rev 181990)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp	2015-03-26 02:36:08 UTC (rev 181991)
@@ -659,8 +659,10 @@
 void WebFrameLoaderClient::dispatchDecidePolicyForResponse(const ResourceResponse& response, const ResourceRequest& request, FramePolicyFunction function)
 {
     WebPage* webPage = m_frame->page();
-    if (!webPage)
+    if (!webPage) {
+        function(PolicyIgnore);
         return;
+    }
 
     if (!request.url().string()) {
         function(PolicyUse);
@@ -686,8 +688,10 @@
     unsigned syncSendFlags = IPC::InformPlatformProcessWillSuspend;
     if (WebPage::synchronousMessagesShouldSpinRunLoop())
         syncSendFlags |= IPC::SpinRunLoopWhileWaitingForReply;
-    if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForResponseSync(m_frame->frameID(), response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForResponseSync::Reply(receivedPolicyAction, policyAction, downloadID), std::chrono::milliseconds::max(), syncSendFlags))
+    if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForResponseSync(m_frame->frameID(), response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForResponseSync::Reply(receivedPolicyAction, policyAction, downloadID), std::chrono::milliseconds::max(), syncSendFlags)) {
+        function(PolicyIgnore);
         return;
+    }
 
     // We call this synchronously because CFNetwork can only convert a loading connection to a download from its didReceiveResponse callback.
     if (receivedPolicyAction)
@@ -697,8 +701,10 @@
 void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState> formState, const String& frameName, FramePolicyFunction function)
 {
     WebPage* webPage = m_frame->page();
-    if (!webPage)
+    if (!webPage) {
+        function(PolicyIgnore);
         return;
+    }
 
     RefPtr<API::Object> userData;
 
@@ -727,8 +733,10 @@
 void WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction(const NavigationAction& navigationAction, const ResourceRequest& request, PassRefPtr<FormState> prpFormState, FramePolicyFunction function)
 {
     WebPage* webPage = m_frame->page();
-    if (!webPage)
+    if (!webPage) {
+        function(PolicyIgnore);
         return;
+    }
 
     // Always ignore requests with empty URLs. 
     if (request.isEmpty()) {
@@ -788,8 +796,10 @@
         documentLoader = static_cast<WebDocumentLoader*>(coreFrame->loader().documentLoader());
 
     // Notify the UIProcess.
-    if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame->frameID(), documentLoader->navigationID(), navigationActionData, originatingFrame ? originatingFrame->frameID() : 0, navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(receivedPolicyAction, newNavigationID, policyAction, downloadID)))
+    if (!webPage->sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame->frameID(), documentLoader->navigationID(), navigationActionData, originatingFrame ? originatingFrame->frameID() : 0, navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(receivedPolicyAction, newNavigationID, policyAction, downloadID))) {
+        function(PolicyIgnore);
         return;
+    }
 
     // We call this synchronously because WebCore cannot gracefully handle a frame load without a synchronous navigation policy reply.
     if (receivedPolicyAction)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to