<!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>[196656] trunk/Source</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/196656">196656</a></dd>
<dt>Author</dt> <dd>achristensen@apple.com</dd>
<dt>Date</dt> <dd>2016-02-16 13:25:30 -0800 (Tue, 16 Feb 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add checks before redirecting with NetworkSession
https://bugs.webkit.org/show_bug.cgi?id=154298

Reviewed by Andy Estes.

Source/WebCore:

This fixes http/tests/security/cors-post-redirect-307.html and 
http/tests/navigation/post-307-response.html when using NetworkSession.

* platform/network/ResourceRequestBase.h:
WEBCORE_EXPORT some functions newly used in WebKit2.

Source/WebKit2:

* NetworkProcess/NetworkDataTask.h:
(WebKit::NetworkDataTask::create):
(WebKit::NetworkDataTask::setPendingDownload):
* NetworkProcess/NetworkLoad.cpp:
(WebKit::NetworkLoad::NetworkLoad):
* NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
(WebKit::NetworkDataTask::NetworkDataTask):
(WebKit::NetworkDataTask::~NetworkDataTask):
(WebKit::NetworkDataTask::willPerformHTTPRedirection):
Implemented based on ResourceHandle::willSendRequest but with two notable exceptions:
1. When using NSURLConnection, the last http method and the current http method are not always equal, and this
check needs to change the current http method to match the last http method when being redirected with an http
status code 307.  When using NSURLSession, the current http method is already updated properly.
2. I did not copy the part of ResourceHandle::willSendRequest that uses a CredentialStorage.  I'm trying to avoid
using CredentialStorages with NSURLSession.
(WebKit::NetworkDataTask::scheduleFailure):
* NetworkProcess/cocoa/NetworkSessionCocoa.mm:
(-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformnetworkResourceRequestBaseh">trunk/Source/WebCore/platform/network/ResourceRequestBase.h</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkDataTaskh">trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkLoadcpp">trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoamm">trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcesscocoaNetworkSessionCocoamm">trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebCore/ChangeLog        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-02-16  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Add checks before redirecting with NetworkSession
+        https://bugs.webkit.org/show_bug.cgi?id=154298
+
+        Reviewed by Andy Estes.
+
+        This fixes http/tests/security/cors-post-redirect-307.html and 
+        http/tests/navigation/post-307-response.html when using NetworkSession.
+
+        * platform/network/ResourceRequestBase.h:
+        WEBCORE_EXPORT some functions newly used in WebKit2.
+
</ins><span class="cx"> 2016-02-16  Daniel Bates  &lt;dabates@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         CSP: Fix parsing of 'host/path' source expressions
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformnetworkResourceRequestBaseh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/network/ResourceRequestBase.h (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/network/ResourceRequestBase.h        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebCore/platform/network/ResourceRequestBase.h        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -93,19 +93,19 @@
</span><span class="cx">         template&lt;size_t length&gt; void setHTTPHeaderField(const char (&amp;)[length], const String&amp;) = delete;
</span><span class="cx">         template&lt;size_t length&gt; void addHTTPHeaderField(const char (&amp;)[length], const String&amp;) = delete;
</span><span class="cx"> 
</span><del>-        void clearHTTPAuthorization();
</del><ins>+        WEBCORE_EXPORT void clearHTTPAuthorization();
</ins><span class="cx"> 
</span><span class="cx">         WEBCORE_EXPORT String httpContentType() const;
</span><span class="cx">         WEBCORE_EXPORT void setHTTPContentType(const String&amp;);
</span><span class="cx">         void clearHTTPContentType();
</span><span class="cx"> 
</span><del>-        String httpReferrer() const;
</del><ins>+        WEBCORE_EXPORT String httpReferrer() const;
</ins><span class="cx">         WEBCORE_EXPORT void setHTTPReferrer(const String&amp;);
</span><del>-        void clearHTTPReferrer();
</del><ins>+        WEBCORE_EXPORT void clearHTTPReferrer();
</ins><span class="cx">         
</span><span class="cx">         String httpOrigin() const;
</span><span class="cx">         void setHTTPOrigin(const String&amp;);
</span><del>-        void clearHTTPOrigin();
</del><ins>+        WEBCORE_EXPORT void clearHTTPOrigin();
</ins><span class="cx"> 
</span><span class="cx">         String httpUserAgent() const;
</span><span class="cx">         void setHTTPUserAgent(const String&amp;);
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebKit2/ChangeLog        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -1,3 +1,29 @@
</span><ins>+2016-02-16  Alex Christensen  &lt;achristensen@webkit.org&gt;
+
+        Add checks before redirecting with NetworkSession
+        https://bugs.webkit.org/show_bug.cgi?id=154298
+
+        Reviewed by Andy Estes.
+
+        * NetworkProcess/NetworkDataTask.h:
+        (WebKit::NetworkDataTask::create):
+        (WebKit::NetworkDataTask::setPendingDownload):
+        * NetworkProcess/NetworkLoad.cpp:
+        (WebKit::NetworkLoad::NetworkLoad):
+        * NetworkProcess/cocoa/NetworkDataTaskCocoa.mm:
+        (WebKit::NetworkDataTask::NetworkDataTask):
+        (WebKit::NetworkDataTask::~NetworkDataTask):
+        (WebKit::NetworkDataTask::willPerformHTTPRedirection):
+        Implemented based on ResourceHandle::willSendRequest but with two notable exceptions:
+        1. When using NSURLConnection, the last http method and the current http method are not always equal, and this
+        check needs to change the current http method to match the last http method when being redirected with an http
+        status code 307.  When using NSURLSession, the current http method is already updated properly.
+        2. I did not copy the part of ResourceHandle::willSendRequest that uses a CredentialStorage.  I'm trying to avoid
+        using CredentialStorages with NSURLSession.
+        (WebKit::NetworkDataTask::scheduleFailure):
+        * NetworkProcess/cocoa/NetworkSessionCocoa.mm:
+        (-[WKNetworkSessionDelegate URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:]):
+
</ins><span class="cx"> 2016-02-16  Brady Eidson  &lt;beidson@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Modern IDB: WK2 IPC Scaffolding.
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkDataTaskh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkDataTask.h        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &lt;WebCore/FrameLoaderTypes.h&gt;
</span><span class="cx"> #include &lt;WebCore/ResourceHandleTypes.h&gt;
</span><span class="cx"> #include &lt;WebCore/ResourceLoaderOptions.h&gt;
</span><ins>+#include &lt;WebCore/ResourceRequest.h&gt;
</ins><span class="cx"> #include &lt;WebCore/Timer.h&gt;
</span><span class="cx"> #include &lt;wtf/RetainPtr.h&gt;
</span><span class="cx"> #include &lt;wtf/text/WTFString.h&gt;
</span><span class="lines">@@ -80,9 +81,9 @@
</span><span class="cx"> class NetworkDataTask : public RefCounted&lt;NetworkDataTask&gt; {
</span><span class="cx">     friend class NetworkSession;
</span><span class="cx"> public:
</span><del>-    static Ref&lt;NetworkDataTask&gt; create(NetworkSession&amp; session, NetworkDataTaskClient&amp; client, const WebCore::ResourceRequest&amp; request, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff)
</del><ins>+    static Ref&lt;NetworkDataTask&gt; create(NetworkSession&amp; session, NetworkDataTaskClient&amp; client, const WebCore::ResourceRequest&amp; request, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect)
</ins><span class="cx">     {
</span><del>-        return adoptRef(*new NetworkDataTask(session, client, request, storedCredentials, shouldContentSniff));
</del><ins>+        return adoptRef(*new NetworkDataTask(session, client, request, storedCredentials, shouldContentSniff, shouldClearReferrerOnHTTPSToHTTPRedirect));
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void suspend();
</span><span class="lines">@@ -110,9 +111,10 @@
</span><span class="cx">         m_pendingDownload = &amp;pendingDownload;
</span><span class="cx">     }
</span><span class="cx">     bool tryPasswordBasedAuthentication(const WebCore::AuthenticationChallenge&amp;, ChallengeCompletionHandler);
</span><ins>+    void willPerformHTTPRedirection(const WebCore::ResourceResponse&amp;, WebCore::ResourceRequest&amp;&amp;, RedirectCompletionHandler);
</ins><span class="cx">     
</span><span class="cx"> private:
</span><del>-    NetworkDataTask(NetworkSession&amp;, NetworkDataTaskClient&amp;, const WebCore::ResourceRequest&amp;, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy);
</del><ins>+    NetworkDataTask(NetworkSession&amp;, NetworkDataTaskClient&amp;, const WebCore::ResourceRequest&amp;, WebCore::StoredCredentials, WebCore::ContentSniffingPolicy, bool shouldClearReferrerOnHTTPSToHTTPRedirect);
</ins><span class="cx">     
</span><span class="cx">     enum FailureType {
</span><span class="cx">         NoFailure,
</span><span class="lines">@@ -130,6 +132,9 @@
</span><span class="cx">     DownloadID m_pendingDownloadID;
</span><span class="cx">     String m_user;
</span><span class="cx">     String m_password;
</span><ins>+    String m_lastHTTPMethod;
+    WebCore::ResourceRequest m_firstRequest;
+    bool m_shouldClearReferrerOnHTTPSToHTTPRedirect;
</ins><span class="cx"> #if PLATFORM(COCOA)
</span><span class="cx">     RetainPtr&lt;NSURLSessionDataTask&gt; m_task;
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkLoadcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkLoad.cpp        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -54,7 +54,7 @@
</span><span class="cx">         return;
</span><span class="cx">     }
</span><span class="cx">     if (auto* networkSession = SessionTracker::networkSession(parameters.sessionID)) {
</span><del>-        m_task = NetworkDataTask::create(*networkSession, *this, parameters.request, parameters.allowStoredCredentials, parameters.contentSniffingPolicy);
</del><ins>+        m_task = NetworkDataTask::create(*networkSession, *this, parameters.request, parameters.allowStoredCredentials, parameters.contentSniffingPolicy, parameters.shouldClearReferrerOnHTTPSToHTTPRedirect);
</ins><span class="cx">         if (!parameters.defersLoading)
</span><span class="cx">             m_task-&gt;resume();
</span><span class="cx">     } else
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkDataTaskCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkDataTaskCocoa.mm        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -35,10 +35,13 @@
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="cx"> 
</span><del>-NetworkDataTask::NetworkDataTask(NetworkSession&amp; session, NetworkDataTaskClient&amp; client, const WebCore::ResourceRequest&amp; requestWithCredentials, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff)
</del><ins>+NetworkDataTask::NetworkDataTask(NetworkSession&amp; session, NetworkDataTaskClient&amp; client, const WebCore::ResourceRequest&amp; requestWithCredentials, WebCore::StoredCredentials storedCredentials, WebCore::ContentSniffingPolicy shouldContentSniff, bool shouldClearReferrerOnHTTPSToHTTPRedirect)
</ins><span class="cx">     : m_failureTimer(*this, &amp;NetworkDataTask::failureTimerFired)
</span><span class="cx">     , m_session(session)
</span><span class="cx">     , m_client(client)
</span><ins>+    , m_lastHTTPMethod(requestWithCredentials.httpMethod())
+    , m_firstRequest(requestWithCredentials)
+    , m_shouldClearReferrerOnHTTPSToHTTPRedirect(shouldClearReferrerOnHTTPSToHTTPRedirect)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(isMainThread());
</span><span class="cx">     
</span><span class="lines">@@ -83,6 +86,39 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void NetworkDataTask::willPerformHTTPRedirection(const WebCore::ResourceResponse&amp; redirectResponse, WebCore::ResourceRequest&amp;&amp; request, RedirectCompletionHandler completionHandler)
+{
+    if (redirectResponse.httpStatusCode() == 307) {
+        ASSERT(m_lastHTTPMethod == request.httpMethod());
+        WebCore::FormData* body = m_firstRequest.httpBody();
+        if (body &amp;&amp; !body-&gt;isEmpty() &amp;&amp; !equalLettersIgnoringASCIICase(m_lastHTTPMethod, &quot;get&quot;))
+            request.setHTTPBody(body);
+        
+        String originalContentType = m_firstRequest.httpContentType();
+        if (!originalContentType.isEmpty())
+            request.setHTTPHeaderField(WebCore::HTTPHeaderName::ContentType, originalContentType);
+    }
+    
+    // Should not set Referer after a redirect from a secure resource to non-secure one.
+    if (m_shouldClearReferrerOnHTTPSToHTTPRedirect &amp;&amp; !request.url().protocolIs(&quot;https&quot;) &amp;&amp; WebCore::protocolIs(request.httpReferrer(), &quot;https&quot;))
+        request.clearHTTPReferrer();
+    
+    const auto&amp; url = request.url();
+    m_user = url.user();
+    m_password = url.pass();
+    m_lastHTTPMethod = request.httpMethod();
+    request.removeCredentials();
+    
+    if (!protocolHostAndPortAreEqual(request.url(), redirectResponse.url())) {
+        // The network layer might carry over some headers from the original request that
+        // we want to strip here because the redirect is cross-origin.
+        request.clearHTTPAuthorization();
+        request.clearHTTPOrigin();
+    }
+    
+    client().willPerformHTTPRedirection(redirectResponse, request, completionHandler);
+}
+    
</ins><span class="cx"> void NetworkDataTask::scheduleFailure(FailureType type)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(type != NoFailure);
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcesscocoaNetworkSessionCocoamm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm (196655 => 196656)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm        2016-02-16 21:18:19 UTC (rev 196655)
+++ trunk/Source/WebKit2/NetworkProcess/cocoa/NetworkSessionCocoa.mm        2016-02-16 21:25:30 UTC (rev 196656)
</span><span class="lines">@@ -105,7 +105,7 @@
</span><span class="cx"> {
</span><span class="cx">     if (auto* networkDataTask = _session-&gt;dataTaskForIdentifier(task.taskIdentifier)) {
</span><span class="cx">         auto completionHandlerCopy = Block_copy(completionHandler);
</span><del>-        networkDataTask-&gt;client().willPerformHTTPRedirection(response, request, [completionHandlerCopy](const WebCore::ResourceRequest&amp; request) {
</del><ins>+        networkDataTask-&gt;willPerformHTTPRedirection(response, request, [completionHandlerCopy](const WebCore::ResourceRequest&amp; request) {
</ins><span class="cx">             completionHandlerCopy(request.nsURLRequest(WebCore::UpdateHTTPBody));
</span><span class="cx">             Block_release(completionHandlerCopy);
</span><span class="cx">         });
</span></span></pre>
</div>
</div>

</body>
</html>