<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[214201] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/214201">214201</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2017-03-20 18:13:50 -0700 (Mon, 20 Mar 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>WebPageProxy DecidePolicyForNavigationAction and DecidePolicyForResponseSync should be Delayed reply messages
https://bugs.webkit.org/show_bug.cgi?id=167183
&lt;rdar://problem/30203539&gt;

Reviewed by Andy Estes.

Source/WebKit2:

Before this patch, the WKNavigationDelegate's decidePolicyForNavigationAction must synchronously call the decisionHandler.
If it stores the decisionHandler and calls it after decidePolicyForNavigationAction returns, we can get incorrect behavior.
This can be seen when the _WKWebsitePolicies given to the decisionHandler had no effect.
Now, we will have the WebProcess waiting on the UIProcess to respond to the Delayed reply before continuing.
This will not be a regression because currently everybody is either calling the decisionHandler immediately or getting incorrect behavior,
and the behavior will be the same if the decisionHandler is called immediately. It is possible that we could make the WebProcess
not wait on the response, but we would need to make WebCore's loading truly asynchronous first
(getting rid of ResourceHandleClient's synchronous methods).

Covered by making an API test asynchronously call the decisionHandler.

* UIProcess/API/C/WKPage.cpp:
(WKPageSetPageNavigationClient):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::receivedPolicyDecision):
(WebKit::WebPageProxy::decidePolicyForNavigationAction):
(WebKit::WebPageProxy::decidePolicyForResponseSync):
* UIProcess/WebPageProxy.h:
* UIProcess/WebPageProxy.messages.in:
* WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
(WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):

Tools:

* TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm:
(-[WebsitePoliciesDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICWKPagecpp">trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxycpp">trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxyh">trunk/Source/WebKit2/UIProcess/WebPageProxy.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebPageProxymessagesin">trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebCoreSupportWebFrameLoaderClientcpp">trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2CocoaWebsitePoliciesmm">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Source/WebKit2/ChangeLog        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -1,5 +1,36 @@
</span><span class="cx"> 2017-03-20  Alex Christensen  &lt;achristensen@webkit.org&gt;
</span><span class="cx"> 
</span><ins>+        WebPageProxy DecidePolicyForNavigationAction and DecidePolicyForResponseSync should be Delayed reply messages
+        https://bugs.webkit.org/show_bug.cgi?id=167183
+        &lt;rdar://problem/30203539&gt;
+
+        Reviewed by Andy Estes.
+
+        Before this patch, the WKNavigationDelegate's decidePolicyForNavigationAction must synchronously call the decisionHandler.
+        If it stores the decisionHandler and calls it after decidePolicyForNavigationAction returns, we can get incorrect behavior.
+        This can be seen when the _WKWebsitePolicies given to the decisionHandler had no effect.
+        Now, we will have the WebProcess waiting on the UIProcess to respond to the Delayed reply before continuing.
+        This will not be a regression because currently everybody is either calling the decisionHandler immediately or getting incorrect behavior,
+        and the behavior will be the same if the decisionHandler is called immediately. It is possible that we could make the WebProcess
+        not wait on the response, but we would need to make WebCore's loading truly asynchronous first
+        (getting rid of ResourceHandleClient's synchronous methods).
+
+        Covered by making an API test asynchronously call the decisionHandler.
+
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetPageNavigationClient):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::receivedPolicyDecision):
+        (WebKit::WebPageProxy::decidePolicyForNavigationAction):
+        (WebKit::WebPageProxy::decidePolicyForResponseSync):
+        * UIProcess/WebPageProxy.h:
+        * UIProcess/WebPageProxy.messages.in:
+        * WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp:
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForResponse):
+        (WebKit::WebFrameLoaderClient::dispatchDecidePolicyForNavigationAction):
+
+2017-03-20  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
</ins><span class="cx">         Fix GTK build after r214190
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=169885
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICWKPagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKPage.cpp        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -2265,15 +2265,19 @@
</span><span class="cx">     private:
</span><span class="cx">         void decidePolicyForNavigationAction(WebPageProxy&amp; page, API::NavigationAction&amp; navigationAction, Ref&lt;WebKit::WebFramePolicyListenerProxy&gt;&amp;&amp; listener, API::Object* userData) override
</span><span class="cx">         {
</span><del>-            if (!m_client.decidePolicyForNavigationAction)
</del><ins>+            if (!m_client.decidePolicyForNavigationAction) {
+                listener-&gt;use({ });
</ins><span class="cx">                 return;
</span><ins>+            }
</ins><span class="cx">             m_client.decidePolicyForNavigationAction(toAPI(&amp;page), toAPI(&amp;navigationAction), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         void decidePolicyForNavigationResponse(WebPageProxy&amp; page, API::NavigationResponse&amp; navigationResponse, Ref&lt;WebKit::WebFramePolicyListenerProxy&gt;&amp;&amp; listener, API::Object* userData) override
</span><span class="cx">         {
</span><del>-            if (!m_client.decidePolicyForNavigationResponse)
</del><ins>+            if (!m_client.decidePolicyForNavigationResponse) {
+                listener-&gt;use({ });
</ins><span class="cx">                 return;
</span><ins>+            }
</ins><span class="cx">             m_client.decidePolicyForNavigationResponse(toAPI(&amp;page), toAPI(&amp;navigationResponse), toAPI(listener.ptr()), toAPI(userData), m_client.base.clientInfo);
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.cpp        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -384,15 +384,6 @@
</span><span class="cx">     , m_canRunModal(false)
</span><span class="cx">     , m_isInPrintingMode(false)
</span><span class="cx">     , m_isPerformingDOMPrintOperation(false)
</span><del>-    , m_inDecidePolicyForResponseSync(false)
-    , m_decidePolicyForResponseRequest(0)
-    , m_syncMimeTypePolicyActionIsValid(false)
-    , m_syncMimeTypePolicyAction(PolicyUse)
-    , m_syncMimeTypePolicyDownloadID(0)
-    , m_inDecidePolicyForNavigationAction(false)
-    , m_syncNavigationActionPolicyActionIsValid(false)
-    , m_syncNavigationActionPolicyAction(PolicyUse)
-    , m_syncNavigationActionPolicyDownloadID(0)
</del><span class="cx">     , m_processingMouseMoveEvent(false)
</span><span class="cx">     , m_pageID(pageID)
</span><span class="cx">     , m_sessionID(m_configuration-&gt;sessionID())
</span><span class="lines">@@ -2298,29 +2289,27 @@
</span><span class="cx">     DownloadID downloadID = { };
</span><span class="cx">     if (action == PolicyDownload) {
</span><span class="cx">         // Create a download proxy.
</span><del>-        // FIXME: We should ensure that the downloadRequest is never empty.
-        const ResourceRequest&amp; downloadRequest = m_decidePolicyForResponseRequest ? *m_decidePolicyForResponseRequest : ResourceRequest();
-        DownloadProxy* download = m_process-&gt;processPool().createDownloadProxy(downloadRequest);
</del><ins>+        DownloadProxy* download = m_process-&gt;processPool().createDownloadProxy(m_decidePolicyForResponseRequest);
</ins><span class="cx">         downloadID = download-&gt;downloadID();
</span><span class="cx">         handleDownloadRequest(download);
</span><ins>+        m_decidePolicyForResponseRequest = { };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // If we received a policy decision while in decidePolicyForResponse the decision will
</span><span class="cx">     // be sent back to the web process by decidePolicyForResponse.
</span><del>-    if (m_inDecidePolicyForResponseSync) {
-        m_syncMimeTypePolicyActionIsValid = true;
-        m_syncMimeTypePolicyAction = action;
-        m_syncMimeTypePolicyDownloadID = downloadID;
</del><ins>+    if (m_responsePolicyReply) {
+        m_responsePolicyReply-&gt;send(action, downloadID);
+        ASSERT(!m_newNavigationID);
+        m_responsePolicyReply = nullptr;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // If we received a policy decision while in decidePolicyForNavigationAction the decision will 
</span><span class="cx">     // be sent back to the web process by decidePolicyForNavigationAction. 
</span><del>-    if (m_inDecidePolicyForNavigationAction) {
-        m_syncNavigationActionPolicyActionIsValid = true;
-        m_syncNavigationActionPolicyAction = action;
-        m_syncNavigationActionPolicyDownloadID = downloadID;
-        m_syncNavigationActionPolicyWebsitePolicies = websitePolicies;
</del><ins>+    if (m_navigationActionPolicyReply) {
+        m_navigationActionPolicyReply-&gt;send(m_newNavigationID, action, downloadID, websitePolicies);
+        m_newNavigationID = 0;
+        m_navigationActionPolicyReply = nullptr;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -3648,7 +3637,7 @@
</span><span class="cx">         m_frameSetLargestFrame = value ? m_mainFrame : 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const SecurityOriginData&amp; frameSecurityOrigin, uint64_t navigationID, const NavigationActionData&amp; navigationActionData, uint64_t originatingFrameID, const SecurityOriginData&amp; originatingFrameSecurityOrigin, const WebCore::ResourceRequest&amp; originalRequest, const ResourceRequest&amp; request, uint64_t listenerID, const UserData&amp; userData, bool&amp; receivedPolicyAction, uint64_t&amp; newNavigationID, uint64_t&amp; policyAction, DownloadID&amp; downloadID, WebsitePolicies&amp; websitePolicies)
</del><ins>+void WebPageProxy::decidePolicyForNavigationAction(uint64_t frameID, const SecurityOriginData&amp; frameSecurityOrigin, uint64_t navigationID, const NavigationActionData&amp; navigationActionData, uint64_t originatingFrameID, const SecurityOriginData&amp; originatingFrameSecurityOrigin, const WebCore::ResourceRequest&amp; originalRequest, const ResourceRequest&amp; request, uint64_t listenerID, const UserData&amp; userData, Ref&lt;Messages::WebPageProxy::DecidePolicyForNavigationAction::DelayedReply&gt;&amp;&amp; reply)
</ins><span class="cx"> {
</span><span class="cx">     PageClientProtector protector(m_pageClient);
</span><span class="cx"> 
</span><span class="lines">@@ -3664,28 +3653,26 @@
</span><span class="cx"> 
</span><span class="cx">     WebFrameProxy* originatingFrame = m_process-&gt;webFrame(originatingFrameID);
</span><span class="cx">     
</span><ins>+    m_newNavigationID = 0;
</ins><span class="cx">     Ref&lt;WebFramePolicyListenerProxy&gt; listener = frame-&gt;setUpPolicyListenerProxy(listenerID);
</span><span class="cx">     if (!navigationID &amp;&amp; frame-&gt;isMainFrame()) {
</span><span class="cx">         auto navigation = m_navigationState-&gt;createLoadRequestNavigation(request);
</span><del>-        newNavigationID = navigation-&gt;navigationID();
</del><ins>+        m_newNavigationID = navigation-&gt;navigationID();
</ins><span class="cx">         listener-&gt;setNavigation(WTFMove(navigation));
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(CONTENT_FILTERING)
</span><span class="cx">     if (frame-&gt;didHandleContentFilterUnblockNavigation(request)) {
</span><del>-        receivedPolicyAction = true;
-        policyAction = PolicyIgnore;
</del><ins>+        reply-&gt;send(m_newNavigationID, PolicyIgnore, { }, { });
+        m_newNavigationID = 0;
</ins><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-    ASSERT(!m_inDecidePolicyForNavigationAction);
-
-    m_inDecidePolicyForNavigationAction = true;
-    m_syncNavigationActionPolicyActionIsValid = false;
</del><span class="cx"> #if ENABLE(DOWNLOAD_ATTRIBUTE)
</span><span class="cx">     m_syncNavigationActionHasDownloadAttribute = !navigationActionData.downloadAttribute.isNull();
</span><span class="cx"> #endif
</span><ins>+    m_navigationActionPolicyReply = WTFMove(reply);
</ins><span class="cx"> 
</span><span class="cx">     if (m_navigationClient) {
</span><span class="cx">         RefPtr&lt;API::FrameInfo&gt; destinationFrameInfo;
</span><span class="lines">@@ -3709,15 +3696,6 @@
</span><span class="cx">         m_policyClient-&gt;decidePolicyForNavigationAction(*this, frame, navigationActionData, originatingFrame, originalRequest, request, WTFMove(listener), m_process-&gt;transformHandlesToObjects(userData.object()).get());
</span><span class="cx"> 
</span><span class="cx">     m_shouldSuppressAppLinksInNextNavigationPolicyDecision = false;
</span><del>-    m_inDecidePolicyForNavigationAction = false;
-
-    // Check if we received a policy decision already. If we did, we can just pass it back.
-    receivedPolicyAction = m_syncNavigationActionPolicyActionIsValid;
-    if (m_syncNavigationActionPolicyActionIsValid) {
-        policyAction = m_syncNavigationActionPolicyAction;
-        downloadID = m_syncNavigationActionPolicyDownloadID;
-        websitePolicies = m_syncNavigationActionPolicyWebsitePolicies;
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::decidePolicyForNewWindowAction(uint64_t frameID, const SecurityOriginData&amp; frameSecurityOrigin, const NavigationActionData&amp; navigationActionData, const ResourceRequest&amp; request, const String&amp; frameName, uint64_t listenerID, const UserData&amp; userData)
</span><span class="lines">@@ -3763,27 +3741,14 @@
</span><span class="cx">         m_policyClient-&gt;decidePolicyForResponse(*this, *frame, response, request, canShowMIMEType, WTFMove(listener), m_process-&gt;transformHandlesToObjects(userData.object()).get());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const SecurityOriginData&amp; frameSecurityOrigin, const ResourceResponse&amp; response, const ResourceRequest&amp; request, bool canShowMIMEType, uint64_t listenerID, const UserData&amp; userData, bool&amp; receivedPolicyAction, uint64_t&amp; policyAction, DownloadID&amp; downloadID)
</del><ins>+void WebPageProxy::decidePolicyForResponseSync(uint64_t frameID, const SecurityOriginData&amp; frameSecurityOrigin, const ResourceResponse&amp; response, const ResourceRequest&amp; request, bool canShowMIMEType, uint64_t listenerID, const UserData&amp; userData, Ref&lt;Messages::WebPageProxy::DecidePolicyForResponseSync::DelayedReply&gt;&amp;&amp; reply)
</ins><span class="cx"> {
</span><span class="cx">     PageClientProtector protector(m_pageClient);
</span><span class="cx"> 
</span><del>-    ASSERT(!m_inDecidePolicyForResponseSync);
</del><ins>+    m_decidePolicyForResponseRequest = request;
+    m_responsePolicyReply = WTFMove(reply);
</ins><span class="cx"> 
</span><del>-    m_inDecidePolicyForResponseSync = true;
-    m_decidePolicyForResponseRequest = &amp;request;
-    m_syncMimeTypePolicyActionIsValid = false;
-
</del><span class="cx">     decidePolicyForResponse(frameID, frameSecurityOrigin, response, request, canShowMIMEType, listenerID, userData);
</span><del>-
-    m_inDecidePolicyForResponseSync = false;
-    m_decidePolicyForResponseRequest = 0;
-
-    // Check if we received a policy decision already. If we did, we can just pass it back.
-    receivedPolicyAction = m_syncMimeTypePolicyActionIsValid;
-    if (m_syncMimeTypePolicyActionIsValid) {
-        policyAction = m_syncMimeTypePolicyAction;
-        downloadID = m_syncMimeTypePolicyDownloadID;
-    }
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebPageProxy::unableToImplementPolicy(uint64_t frameID, const ResourceError&amp; error, const UserData&amp; userData)
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.h (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.h        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -1261,10 +1261,10 @@
</span><span class="cx"> 
</span><span class="cx">     void didDestroyNavigation(uint64_t navigationID);
</span><span class="cx"> 
</span><del>-    void decidePolicyForNavigationAction(uint64_t frameID, const WebCore::SecurityOriginData&amp; frameSecurityOrigin, uint64_t navigationID, const NavigationActionData&amp;, uint64_t originatingFrameID, const WebCore::SecurityOriginData&amp; originatingFrameSecurityOrigin, const WebCore::ResourceRequest&amp; originalRequest, const WebCore::ResourceRequest&amp;, uint64_t listenerID, const UserData&amp;, bool&amp; receivedPolicyAction, uint64_t&amp; newNavigationID, uint64_t&amp; policyAction, DownloadID&amp;, WebsitePolicies&amp;);
</del><ins>+    void decidePolicyForNavigationAction(uint64_t frameID, const WebCore::SecurityOriginData&amp; frameSecurityOrigin, uint64_t navigationID, const NavigationActionData&amp;, uint64_t originatingFrameID, const WebCore::SecurityOriginData&amp; originatingFrameSecurityOrigin, const WebCore::ResourceRequest&amp; originalRequest, const WebCore::ResourceRequest&amp;, uint64_t listenerID, const UserData&amp;, Ref&lt;Messages::WebPageProxy::DecidePolicyForNavigationAction::DelayedReply&gt;&amp;&amp;);
</ins><span class="cx">     void decidePolicyForNewWindowAction(uint64_t frameID, const WebCore::SecurityOriginData&amp; frameSecurityOrigin, const NavigationActionData&amp;, const WebCore::ResourceRequest&amp;, const String&amp; frameName, uint64_t listenerID, const UserData&amp;);
</span><span class="cx">     void decidePolicyForResponse(uint64_t frameID, const WebCore::SecurityOriginData&amp; frameSecurityOrigin, const WebCore::ResourceResponse&amp;, const WebCore::ResourceRequest&amp;, bool canShowMIMEType, uint64_t listenerID, const UserData&amp;);
</span><del>-    void decidePolicyForResponseSync(uint64_t frameID, const WebCore::SecurityOriginData&amp; frameSecurityOrigin, const WebCore::ResourceResponse&amp;, const WebCore::ResourceRequest&amp;, bool canShowMIMEType, uint64_t listenerID, const UserData&amp;, bool&amp; receivedPolicyAction, uint64_t&amp; policyAction, DownloadID&amp;);
</del><ins>+    void decidePolicyForResponseSync(uint64_t frameID, const WebCore::SecurityOriginData&amp; frameSecurityOrigin, const WebCore::ResourceResponse&amp;, const WebCore::ResourceRequest&amp;, bool canShowMIMEType, uint64_t listenerID, const UserData&amp;, Ref&lt;Messages::WebPageProxy::DecidePolicyForResponseSync::DelayedReply&gt;&amp;&amp;);
</ins><span class="cx">     void unableToImplementPolicy(uint64_t frameID, const WebCore::ResourceError&amp;, const UserData&amp;);
</span><span class="cx"> 
</span><span class="cx">     void willSubmitForm(uint64_t frameID, uint64_t sourceFrameID, const Vector&lt;std::pair&lt;String, String&gt;&gt;&amp; textFieldValues, uint64_t listenerID, const UserData&amp;);
</span><span class="lines">@@ -1775,17 +1775,11 @@
</span><span class="cx">     bool m_isInPrintingMode;
</span><span class="cx">     bool m_isPerformingDOMPrintOperation;
</span><span class="cx"> 
</span><del>-    bool m_inDecidePolicyForResponseSync;
-    const WebCore::ResourceRequest* m_decidePolicyForResponseRequest;
-    bool m_syncMimeTypePolicyActionIsValid;
-    WebCore::PolicyAction m_syncMimeTypePolicyAction;
-    DownloadID m_syncMimeTypePolicyDownloadID;
</del><ins>+    RefPtr&lt;Messages::WebPageProxy::DecidePolicyForNavigationAction::DelayedReply&gt; m_navigationActionPolicyReply;
+    uint64_t m_newNavigationID { 0 };
+    RefPtr&lt;Messages::WebPageProxy::DecidePolicyForResponseSync::DelayedReply&gt; m_responsePolicyReply;
+    WebCore::ResourceRequest m_decidePolicyForResponseRequest;
</ins><span class="cx"> 
</span><del>-    bool m_inDecidePolicyForNavigationAction;
-    bool m_syncNavigationActionPolicyActionIsValid;
-    WebCore::PolicyAction m_syncNavigationActionPolicyAction;
-    DownloadID m_syncNavigationActionPolicyDownloadID;
-    WebsitePolicies m_syncNavigationActionPolicyWebsitePolicies;
</del><span class="cx">     bool m_shouldSuppressAppLinksInNextNavigationPolicyDecision { false };
</span><span class="cx"> 
</span><span class="cx">     Deque&lt;NativeWebKeyboardEvent&gt; m_keyEventQueue;
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebPageProxymessagesin"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Source/WebKit2/UIProcess/WebPageProxy.messages.in        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -100,8 +100,8 @@
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     # Policy messages
</span><del>-    DecidePolicyForResponseSync(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, WebCore::ResourceResponse response, WebCore::ResourceRequest request, bool canShowMIMEType, uint64_t listenerID, WebKit::UserData userData) -&gt; (bool receivedPolicyAction, uint64_t policyAction, WebKit::DownloadID downloadID)
-    DecidePolicyForNavigationAction(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, struct WebKit::NavigationActionData navigationActionData, uint64_t originatingFrameID, struct WebCore::SecurityOriginData originatingFrameSecurityOrigin, WebCore::ResourceRequest originalRequest, WebCore::ResourceRequest request, uint64_t listenerID, WebKit::UserData userData) -&gt; (bool receivedPolicyAction, uint64_t newNavigationID, uint64_t policyAction, WebKit::DownloadID downloadID, struct WebKit::WebsitePolicies websitePolicies)
</del><ins>+    DecidePolicyForResponseSync(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, WebCore::ResourceResponse response, WebCore::ResourceRequest request, bool canShowMIMEType, uint64_t listenerID, WebKit::UserData userData) -&gt; (uint64_t policyAction, WebKit::DownloadID downloadID) Delayed
+    DecidePolicyForNavigationAction(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, uint64_t navigationID, struct WebKit::NavigationActionData navigationActionData, uint64_t originatingFrameID, struct WebCore::SecurityOriginData originatingFrameSecurityOrigin, WebCore::ResourceRequest originalRequest, WebCore::ResourceRequest request, uint64_t listenerID, WebKit::UserData userData) -&gt; (uint64_t newNavigationID, uint64_t policyAction, WebKit::DownloadID downloadID, struct WebKit::WebsitePolicies websitePolicies) Delayed
</ins><span class="cx">     DecidePolicyForNewWindowAction(uint64_t frameID, struct WebCore::SecurityOriginData frameSecurityOrigin, struct WebKit::NavigationActionData navigationActionData, WebCore::ResourceRequest request, String frameName, uint64_t listenerID, WebKit::UserData userData)
</span><span class="cx">     UnableToImplementPolicy(uint64_t frameID, WebCore::ResourceError error, WebKit::UserData userData)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebCoreSupportWebFrameLoaderClientcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Source/WebKit2/WebProcess/WebCoreSupport/WebFrameLoaderClient.cpp        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -685,20 +685,18 @@
</span><span class="cx">     bool canShowMIMEType = webPage-&gt;canShowMIMEType(response.mimeType());
</span><span class="cx"> 
</span><span class="cx">     uint64_t listenerID = m_frame-&gt;setUpPolicyListener(WTFMove(function));
</span><del>-    bool receivedPolicyAction;
</del><span class="cx">     uint64_t policyAction;
</span><span class="cx">     DownloadID downloadID;
</span><span class="cx"> 
</span><span class="cx">     Ref&lt;WebFrame&gt; protect(*m_frame);
</span><span class="cx">     WebCore::Frame* coreFrame = m_frame-&gt;coreFrame();
</span><del>-    if (!webPage-&gt;sendSync(Messages::WebPageProxy::DecidePolicyForResponseSync(m_frame-&gt;frameID(), SecurityOriginData::fromFrame(coreFrame), response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForResponseSync::Reply(receivedPolicyAction, policyAction, downloadID), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend)) {
</del><ins>+    if (!webPage-&gt;sendSync(Messages::WebPageProxy::DecidePolicyForResponseSync(m_frame-&gt;frameID(), SecurityOriginData::fromFrame(coreFrame), response, request, canShowMIMEType, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForResponseSync::Reply(policyAction, downloadID), Seconds::infinity(), IPC::SendSyncOption::InformPlatformProcessWillSuspend)) {
</ins><span class="cx">         m_frame-&gt;didReceivePolicyDecision(listenerID, PolicyIgnore, 0, { });
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // We call this synchronously because CFNetwork can only convert a loading connection to a download from its didReceiveResponse callback.
</span><del>-    if (receivedPolicyAction)
-        m_frame-&gt;didReceivePolicyDecision(listenerID, static_cast&lt;PolicyAction&gt;(policyAction), 0, downloadID);
</del><ins>+    m_frame-&gt;didReceivePolicyDecision(listenerID, static_cast&lt;PolicyAction&gt;(policyAction), 0, downloadID);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebFrameLoaderClient::dispatchDecidePolicyForNewWindowAction(const NavigationAction&amp; navigationAction, const ResourceRequest&amp; request, FormState* formState, const String&amp; frameName, FramePolicyFunction function)
</span><span class="lines">@@ -763,7 +761,6 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     uint64_t listenerID = m_frame-&gt;setUpPolicyListener(WTFMove(function));
</span><del>-    bool receivedPolicyAction;
</del><span class="cx">     uint64_t newNavigationID;
</span><span class="cx">     uint64_t policyAction;
</span><span class="cx">     DownloadID downloadID;
</span><span class="lines">@@ -808,7 +805,7 @@
</span><span class="cx">     Ref&lt;WebFrame&gt; protect(*m_frame);
</span><span class="cx">     WebCore::Frame* originatingCoreFrame = originatingFrame ? originatingFrame-&gt;coreFrame() : nullptr;
</span><span class="cx">     WebsitePolicies websitePolicies;
</span><del>-    if (!webPage-&gt;sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame-&gt;frameID(), SecurityOriginData::fromFrame(coreFrame), documentLoader-&gt;navigationID(), navigationActionData, originatingFrame ? originatingFrame-&gt;frameID() : 0, SecurityOriginData::fromFrame(originatingCoreFrame), navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(receivedPolicyAction, newNavigationID, policyAction, downloadID, websitePolicies))) {
</del><ins>+    if (!webPage-&gt;sendSync(Messages::WebPageProxy::DecidePolicyForNavigationAction(m_frame-&gt;frameID(), SecurityOriginData::fromFrame(coreFrame), documentLoader-&gt;navigationID(), navigationActionData, originatingFrame ? originatingFrame-&gt;frameID() : 0, SecurityOriginData::fromFrame(originatingCoreFrame), navigationAction.resourceRequest(), request, listenerID, UserData(WebProcess::singleton().transformObjectsToHandles(userData.get()).get())), Messages::WebPageProxy::DecidePolicyForNavigationAction::Reply(newNavigationID, policyAction, downloadID, websitePolicies))) {
</ins><span class="cx">         m_frame-&gt;didReceivePolicyDecision(listenerID, PolicyIgnore, 0, { });
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="lines">@@ -835,8 +832,7 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // We call this synchronously because WebCore cannot gracefully handle a frame load without a synchronous navigation policy reply.
</span><del>-    if (receivedPolicyAction)
-        m_frame-&gt;didReceivePolicyDecision(listenerID, static_cast&lt;PolicyAction&gt;(policyAction), newNavigationID, downloadID);
</del><ins>+    m_frame-&gt;didReceivePolicyDecision(listenerID, static_cast&lt;PolicyAction&gt;(policyAction), newNavigationID, downloadID);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void WebFrameLoaderClient::cancelPolicyCheck()
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Tools/ChangeLog        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2017-03-20  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        WebPageProxy DecidePolicyForNavigationAction and DecidePolicyForResponseSync should be Delayed reply messages
+        https://bugs.webkit.org/show_bug.cgi?id=167183
+        &lt;rdar://problem/30203539&gt;
+
+        Reviewed by Andy Estes.
+
+        * TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm:
+        (-[WebsitePoliciesDelegate _webView:decidePolicyForNavigationAction:decisionHandler:]):
+
</ins><span class="cx"> 2017-03-20  Jonathan Bedard  &lt;jbedard@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         webkitpy: Work around simctl launch returning dead processes
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2CocoaWebsitePoliciesmm"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm (214200 => 214201)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm        2017-03-21 01:10:20 UTC (rev 214200)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/WebsitePolicies.mm        2017-03-21 01:13:50 UTC (rev 214201)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #import &lt;WebKit/WKWebViewPrivate.h&gt;
</span><span class="cx"> #import &lt;WebKit/_WKUserContentExtensionStorePrivate.h&gt;
</span><span class="cx"> #import &lt;WebKit/_WKWebsitePolicies.h&gt;
</span><ins>+#import &lt;wtf/MainThread.h&gt;
</ins><span class="cx"> #import &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="lines">@@ -107,9 +108,18 @@
</span><span class="cx">         // Verify the content blockers behave correctly with the default behavior.
</span><span class="cx">         break;
</span><span class="cx">     case 2:
</span><del>-        // Verify disabling content blockers works correctly.
-        websitePolicies.contentBlockersEnabled = false;
-        break;
</del><ins>+        {
+            // Verify disabling content blockers works correctly.
+            websitePolicies.contentBlockersEnabled = false;
+            
+            // Verify calling the decisionHandler asynchronously works correctly.
+            auto decisionHandlerCopy = Block_copy(decisionHandler);
+            callOnMainThread([decisionHandlerCopy, websitePolicies = RetainPtr&lt;_WKWebsitePolicies&gt;(websitePolicies)] {
+                decisionHandlerCopy(WKNavigationActionPolicyAllow, websitePolicies.get());
+                Block_release(decisionHandlerCopy);
+            });
+        }
+        return;
</ins><span class="cx">     case 3:
</span><span class="cx">         // Verify enabling content blockers has no effect when reloading without content blockers.
</span><span class="cx">         websitePolicies.contentBlockersEnabled = true;
</span></span></pre>
</div>
</div>

</body>
</html>