Changeset 220497 in webkit
- Timestamp:
- Aug 9, 2017 4:23:58 PM (7 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 14 edited
- 3 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r220495 r220497 1 2017-08-09 Chris Dumez <cdumez@apple.com> 2 3 [Beacon][NetworkSession] Support CORS-preflighting on redirects 4 https://bugs.webkit.org/show_bug.cgi?id=175386 5 <rdar://problem/33801370> 6 7 Reviewed by Youenn Fablet. 8 9 Add layout test coverage. 10 11 * http/wpt/beacon/cors/cors-preflight-redirect-failure-expected.txt: Added. 12 * http/wpt/beacon/cors/cors-preflight-redirect-failure.html: Added. 13 * http/wpt/beacon/cors/cors-preflight-redirect-from-crossorigin-to-sameorigin-expected.txt: Added. 14 * http/wpt/beacon/cors/cors-preflight-redirect-from-crossorigin-to-sameorigin.html: Added. 15 * http/wpt/beacon/cors/cors-preflight-redirect-success-expected.txt: Added. 16 * http/wpt/beacon/cors/cors-preflight-redirect-success.html: Added. 17 * http/wpt/beacon/resources/beacon-preflight.py: 18 (main): 19 * http/wpt/beacon/resources/redirect.py: Added. 20 (main): 21 1 22 2017-08-09 Chris Dumez <cdumez@apple.com> 2 23 -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure.html
r220442 r220497 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 34 34 promise_test(function(test) { 35 35 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 36 return pollResult(test, id) .then(result => { 38 37 assert_equals(result['preflight'], 1, "Received preflight") 39 38 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html
r220442 r220497 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 34 34 promise_test(function(test) { 35 35 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 36 return pollResult(test, id) .then(result => { 38 37 assert_equals(result['preflight'], 1, "Received preflight") 39 38 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-blob-failure.html
r220442 r220497 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 34 34 promise_test(function(test) { 35 35 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 36 return pollResult(test, id) .then(result => { 38 37 assert_equals(result['preflight'], 1, "Received preflight") 39 38 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-blob-success.html
r220442 r220497 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 34 34 promise_test(function(test) { 35 35 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 36 return pollResult(test, id) .then(result => { 38 37 assert_equals(result['preflight'], 1, "Received preflight") 39 38 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-cookie.html
r220442 r220497 22 22 step_timeout(test.step_func(() => { 23 23 fetch(checkUrl).then(response => { 24 response. text().then(body => {24 response.json().then(body => { 25 25 resolve(body); 26 26 }); … … 47 47 return fetchCORSCookie(testBase, "testCookie", "/").then(() => { 48 48 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 49 return pollResult(test, id).then(json => { 50 result = JSON.parse(json); 49 return pollResult(test, id).then(result => { 51 50 assert_equals(result['preflight'], 1, "Received preflight") 52 51 assert_equals(result['preflight_cookie_header'], "", "Preflight cookie header") -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-redirect-failure.html
r220496 r220497 3 3 <head> 4 4 <meta charset="utf-8"> 5 <title>SendBeacon CORS preflight test</title>5 <title>SendBeacon CORS preflight on redirect test</title> 6 6 <script src=/resources/testharness.js></script> 7 7 <script src=/resources/testharnessreport.js></script> … … 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 27 27 } 28 28 29 function testCORSPreflight Failure(what) {29 function testCORSPreflightRedirectSuccess(what) { 30 30 var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR; 31 31 var id = self.token(); 32 var testUrl = testBase + "beacon-preflight.py?allowCors=0&cmd=put&id=" + id; 32 var target = encodeURIComponent(testBase + "beacon-preflight.py?allowCors=0&cmd=put&id=" + id); 33 34 // 307 & 308 redirections are the only ones that maintain the POST method. 35 var testUrl = RESOURCES_DIR + "redirect.py?redirect_status=307&location=" + target; 33 36 34 37 promise_test(function(test) { 35 38 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 39 return pollResult(test, id) .then(result => { 38 40 assert_equals(result['preflight'], 1, "Received preflight") 39 41 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") 40 42 assert_equals(result['preflight_requested_method'], "POST", "Preflight requested method") 41 let requested_headers = result['preflight_requested_headers'].toLowerCase()42 assert_true(requested_headers.includes("content-type"), "Content-Type header is requested")43 assert_true(requested_headers.includes("referer"), "Referer header is requested")44 assert_true(requested_headers.includes("origin"), "Origin header is requested")45 43 assert_equals(result['beacon'], 0, "Did not receive beacon") 46 44 }); … … 49 47 50 48 let blob = new Blob(["123"], {type: "application/octet-stream"}); 51 testCORSPreflight Failure(blob);49 testCORSPreflightRedirectSuccess(blob); 52 50 </script> 53 51 </body> -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-redirect-from-crossorigin-to-sameorigin.html
r220496 r220497 3 3 <head> 4 4 <meta charset="utf-8"> 5 <title>SendBeacon CORS preflight test</title>5 <title>SendBeacon CORS preflight on redirect test from cross origin to same origin</title> 6 6 <script src=/resources/testharness.js></script> 7 7 <script src=/resources/testharnessreport.js></script> … … 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 27 27 } 28 28 29 function testCORSPreflight Success(what) {29 function testCORSPreflightRedirectSuccess(what) { 30 30 var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR; 31 31 var id = self.token(); 32 var testUrl = testBase + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id; 32 var target = encodeURIComponent(get_host_info().HTTP_ORIGIN + RESOURCES_DIR + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id); 33 34 // 307 & 308 redirections are the only ones that maintain the POST method. 35 var testUrl = testBase + "redirect.py?redirect_status=307&location=" + target; 33 36 34 37 promise_test(function(test) { 35 38 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 39 return pollResult(test, id) .then(result => { 38 40 assert_equals(result['preflight'], 1, "Received preflight") 39 41 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") 40 42 assert_equals(result['preflight_requested_method'], "POST", "Preflight requested method") 41 let requested_headers = result['preflight_requested_headers'].toLowerCase() 42 assert_true(requested_headers.includes("content-type"), "Content-Type header is requested") 43 assert_true(requested_headers.includes("referer"), "Referer header is requested") 44 assert_true(requested_headers.includes("origin"), "Origin header is requested") 43 assert_equals(result['preflight_origin'], "null", "Received beacon") 45 44 assert_equals(result['beacon'], 1, "Received beacon") 45 assert_equals(result['beacon_origin'], "null", "Received beacon") 46 46 }); 47 47 }, "CORS preflight success test"); … … 49 49 50 50 let blob = new Blob(["123"], {type: "application/octet-stream"}); 51 testCORSPreflight Success(blob);51 testCORSPreflightRedirectSuccess(blob); 52 52 </script> 53 53 </body> -
trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-redirect-success.html
r220496 r220497 3 3 <head> 4 4 <meta charset="utf-8"> 5 <title>SendBeacon CORS preflight test</title>5 <title>SendBeacon CORS preflight on redirect test</title> 6 6 <script src=/resources/testharness.js></script> 7 7 <script src=/resources/testharnessreport.js></script> … … 19 19 step_timeout(test.step_func(() => { 20 20 fetch(checkUrl).then(response => { 21 response. text().then(body => {21 response.json().then(body => { 22 22 resolve(body); 23 23 }); … … 27 27 } 28 28 29 function testCORSPreflight Success(what) {29 function testCORSPreflightRedirectSuccess(what) { 30 30 var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR; 31 31 var id = self.token(); 32 var testUrl = testBase + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id; 32 var target = encodeURIComponent(testBase + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id); 33 34 // 307 & 308 redirections are the only ones that maintain the POST method. 35 var testUrl = RESOURCES_DIR + "redirect.py?redirect_status=307&location=" + target; 33 36 34 37 promise_test(function(test) { 35 38 assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded"); 36 return pollResult(test, id) .then(json => { 37 result = JSON.parse(json); 39 return pollResult(test, id) .then(result => { 38 40 assert_equals(result['preflight'], 1, "Received preflight") 39 41 assert_equals(result['preflight_referer'], document.URL, "Preflight referer header") 40 42 assert_equals(result['preflight_requested_method'], "POST", "Preflight requested method") 41 let requested_headers = result['preflight_requested_headers'].toLowerCase()42 assert_true(requested_headers.includes("content-type"), "Content-Type header is requested")43 assert_true(requested_headers.includes("referer"), "Referer header is requested")44 assert_true(requested_headers.includes("origin"), "Origin header is requested")45 43 assert_equals(result['beacon'], 1, "Received beacon") 46 44 }); … … 49 47 50 48 let blob = new Blob(["123"], {type: "application/octet-stream"}); 51 testCORSPreflight Success(blob);49 testCORSPreflightRedirectSuccess(blob); 52 50 </script> 53 51 </body> -
trunk/LayoutTests/http/wpt/beacon/resources/beacon-preflight.py
r220442 r220497 36 36 stashed_data['preflight_cookie_header'] = request.headers.get("Cookie", ""); 37 37 stashed_data['preflight_referer'] = request.headers.get("Referer", "") 38 stashed_data['preflight_origin'] = request.headers.get("Origin", "") 38 39 request.server.stash.put(test_id, stashed_data) 39 40 return respondToCORSPreflight(request, response) … … 41 42 stashed_data['beacon'] = 1; 42 43 stashed_data['beacon_cookie_header'] = request.headers.get("Cookie", "") 44 stashed_data['beacon_origin'] = request.headers.get("Origin", "") 43 45 request.server.stash.put(test_id, stashed_data) 44 46 return [("Content-Type", "text/plain")], "" -
trunk/Source/WebCore/ChangeLog
r220496 r220497 1 2017-08-09 Chris Dumez <cdumez@apple.com> 2 3 [Beacon][NetworkSession] Support CORS-preflighting on redirects 4 https://bugs.webkit.org/show_bug.cgi?id=175386 5 <rdar://problem/33801370> 6 7 Reviewed by Youenn Fablet. 8 9 Export a couple of WebCore symbols so I can use them in WebKit2. 10 11 Tests: http/wpt/beacon/cors/cors-preflight-redirect-failure.html 12 http/wpt/beacon/cors/cors-preflight-redirect-from-crossorigin-to-sameorigin.html 13 http/wpt/beacon/cors/cors-preflight-redirect-success.html 14 15 * loader/CrossOriginAccessControl.h: 16 * page/SecurityOrigin.h: 17 1 18 2017-08-09 Jeremy Jones <jeremyj@apple.com> 2 19 -
trunk/Source/WebCore/loader/CrossOriginAccessControl.h
r220442 r220497 41 41 bool isOnAccessControlSimpleRequestMethodWhitelist(const String&); 42 42 43 void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin&, StoredCredentials);43 WEBCORE_EXPORT void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin&, StoredCredentials); 44 44 WEBCORE_EXPORT ResourceRequest createAccessControlPreflightRequest(const ResourceRequest&, SecurityOrigin&, const String&); 45 45 -
trunk/Source/WebCore/page/SecurityOrigin.h
r220442 r220497 51 51 52 52 WEBCORE_EXPORT static Ref<SecurityOrigin> create(const URL&); 53 static Ref<SecurityOrigin> createUnique();53 WEBCORE_EXPORT static Ref<SecurityOrigin> createUnique(); 54 54 55 55 WEBCORE_EXPORT static Ref<SecurityOrigin> createFromString(const String&); -
trunk/Source/WebKit/ChangeLog
r220496 r220497 1 2017-08-09 Chris Dumez <cdumez@apple.com> 2 3 [Beacon][NetworkSession] Support CORS-preflighting on redirects 4 https://bugs.webkit.org/show_bug.cgi?id=175386 5 <rdar://problem/33801370> 6 7 Reviewed by Youenn Fablet. 8 9 Add support to Beacon for doing CORS-preflighting upon redirect to a different 10 domain. 11 12 * NetworkProcess/NetworkCORSPreflightChecker.h: 13 * NetworkProcess/PingLoad.cpp: 14 (WebKit::PingLoad::PingLoad): 15 (WebKit::PingLoad::~PingLoad): 16 (WebKit::PingLoad::loadRequest): 17 (WebKit::PingLoad::securityOrigin const): 18 (WebKit::PingLoad::willPerformHTTPRedirection): 19 (WebKit::PingLoad::didReceiveResponseNetworkSession): 20 (WebKit::PingLoad::needsCORSPreflight const): 21 (WebKit::PingLoad::doCORSPreflight): 22 * NetworkProcess/PingLoad.h: 23 1 24 2017-08-09 Jeremy Jones <jeremyj@apple.com> 2 25 -
trunk/Source/WebKit/NetworkProcess/NetworkCORSPreflightChecker.h
r220442 r220497 55 55 NetworkCORSPreflightChecker(Parameters&&, CompletionCallback&&); 56 56 ~NetworkCORSPreflightChecker(); 57 const WebCore::ResourceRequest& originalRequest() const { return m_parameters.originalRequest; } 57 58 58 59 void startPreflight(); -
trunk/Source/WebKit/NetworkProcess/PingLoad.cpp
r220442 r220497 33 33 #include "NetworkCORSPreflightChecker.h" 34 34 #include "SessionTracker.h" 35 #include <WebCore/CrossOriginAccessControl.h> 35 36 36 37 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_parameters.sessionID.isAlwaysOnLoggingAllowed(), Network, "%p - PingLoad::" fmt, this, ##__VA_ARGS__) … … 43 44 : m_parameters(WTFMove(parameters)) 44 45 , m_timeoutTimer(*this, &PingLoad::timeoutTimerFired) 46 , m_isSameOriginRequest(securityOrigin().canRequest(m_parameters.request.url())) 45 47 { 46 48 // If the server never responds, this object will hang around forever. … … 51 53 doCORSPreflight(m_parameters.request); 52 54 else 53 startNetworkLoad();55 loadRequest(m_parameters.request); 54 56 } 55 57 56 58 PingLoad::~PingLoad() 57 59 { 60 if (m_redirectHandler) 61 m_redirectHandler({ }); 62 58 63 if (m_task) { 59 64 ASSERT(m_task->client() == this); … … 63 68 } 64 69 65 void PingLoad:: startNetworkLoad()70 void PingLoad::loadRequest(const ResourceRequest& request) 66 71 { 67 72 RELEASE_LOG_IF_ALLOWED("startNetworkLoad"); 68 73 if (auto* networkSession = SessionTracker::networkSession(m_parameters.sessionID)) { 69 m_task = NetworkDataTask::create(*networkSession, *this, m_parameters); 74 auto loadParameters = m_parameters; 75 loadParameters.request = request; 76 m_task = NetworkDataTask::create(*networkSession, *this, WTFMove(loadParameters)); 70 77 m_task->resume(); 71 78 } else … … 73 80 } 74 81 75 void PingLoad::willPerformHTTPRedirection(ResourceResponse&&, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler) 76 { 77 RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection"); 78 // FIXME: Do a CORS preflight if necessary. 82 SecurityOrigin& PingLoad::securityOrigin() const 83 { 84 return m_origin ? *m_origin : *m_parameters.sourceOrigin; 85 } 86 87 void PingLoad::willPerformHTTPRedirection(ResourceResponse&& redirectResponse, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler) 88 { 89 RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - shouldFollowRedirects? %d", m_parameters.shouldFollowRedirects); 90 if (!m_parameters.shouldFollowRedirects) { 91 completionHandler({ }); 92 return; 93 } 94 // FIXME: Do CSP check. 79 95 // FIXME: We should ensure the number of redirects does not exceed 20. 80 completionHandler(m_parameters.shouldFollowRedirects ? request : ResourceRequest()); 96 if (!needsCORSPreflight(request)) { 97 completionHandler(request); 98 return; 99 } 100 RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - Redirect requires a CORS preflight"); 101 102 // Use a unique origin for subsequent loads if needed. 103 // https://fetch.spec.whatwg.org/#concept-http-redirect-fetch (Step 10). 104 ASSERT(m_parameters.mode == FetchOptions::Mode::Cors); 105 if (!securityOrigin().canRequest(redirectResponse.url()) && !protocolHostAndPortAreEqual(redirectResponse.url(), request.url())) { 106 if (!m_origin || !m_origin->isUnique()) 107 m_origin = SecurityOrigin::createUnique(); 108 } 109 110 m_isSameOriginRequest = false; 111 m_redirectHandler = WTFMove(completionHandler); 112 113 // Let's fetch the request with the original headers (equivalent to request cloning specified by fetch algorithm). 114 request.setHTTPHeaderFields(m_parameters.request.httpHeaderFields()); 115 116 doCORSPreflight(request); 81 117 } 82 118 … … 88 124 } 89 125 90 void PingLoad::didReceiveResponseNetworkSession(ResourceResponse&& , ResponseCompletionHandler&& completionHandler)91 { 92 RELEASE_LOG_IF_ALLOWED("didReceiveResponseNetworkSession ");126 void PingLoad::didReceiveResponseNetworkSession(ResourceResponse&& response, ResponseCompletionHandler&& completionHandler) 127 { 128 RELEASE_LOG_IF_ALLOWED("didReceiveResponseNetworkSession - httpStatusCode: %d", response.httpStatusCode()); 93 129 completionHandler(PolicyAction::PolicyIgnore); 94 130 delete this; … … 134 170 bool PingLoad::needsCORSPreflight(const ResourceRequest& request) const 135 171 { 136 if (m_parameters.mode == FetchOptions::Mode::Cors) { 137 ASSERT(m_parameters.sourceOrigin); 138 return !m_parameters.sourceOrigin->canRequest(request.url()); 139 } 140 return false; 172 if (m_parameters.mode == FetchOptions::Mode::NoCors) 173 return false; 174 175 return !m_isSameOriginRequest || !securityOrigin().canRequest(request.url()); 141 176 } 142 177 … … 145 180 RELEASE_LOG_IF_ALLOWED("doCORSPreflight"); 146 181 ASSERT(!m_corsPreflightChecker); 147 ASSERT(m_parameters.sourceOrigin);148 182 149 183 NetworkCORSPreflightChecker::Parameters parameters = { 150 184 request, 151 *m_parameters.sourceOrigin,185 securityOrigin(), 152 186 m_parameters.sessionID, 153 187 m_parameters.allowStoredCredentials 154 188 }; 155 189 m_corsPreflightChecker = std::make_unique<NetworkCORSPreflightChecker>(WTFMove(parameters), [this](NetworkCORSPreflightChecker::Result result) { 156 RELEASE_LOG_IF_ALLOWED("doCORSPreflight complete, success: %d", result == NetworkCORSPreflightChecker::Result::Success); 190 RELEASE_LOG_IF_ALLOWED("doCORSPreflight complete, success: %d forRedirect? %d", result == NetworkCORSPreflightChecker::Result::Success, !!m_redirectHandler); 191 auto corsPreflightChecker = WTFMove(m_corsPreflightChecker); 157 192 if (result == NetworkCORSPreflightChecker::Result::Success) { 158 m_corsPreflightChecker = nullptr; 159 startNetworkLoad(); 193 ResourceRequest actualRequest = corsPreflightChecker->originalRequest(); 194 updateRequestForAccessControl(actualRequest, securityOrigin(), m_parameters.allowStoredCredentials); 195 if (auto redirectHandler = std::exchange(m_redirectHandler, nullptr)) 196 redirectHandler(actualRequest); 197 else 198 loadRequest(actualRequest); 160 199 } else 161 200 delete this; -
trunk/Source/WebKit/NetworkProcess/PingLoad.h
r220442 r220497 52 52 void timeoutTimerFired(); 53 53 54 void startNetworkLoad();54 void loadRequest(const WebCore::ResourceRequest&); 55 55 bool needsCORSPreflight(const WebCore::ResourceRequest&) const; 56 56 void doCORSPreflight(const WebCore::ResourceRequest&); 57 58 WebCore::SecurityOrigin& securityOrigin() const; 57 59 58 60 NetworkResourceLoadParameters m_parameters; … … 60 62 WebCore::Timer m_timeoutTimer; 61 63 std::unique_ptr<NetworkCORSPreflightChecker> m_corsPreflightChecker; 64 RefPtr<WebCore::SecurityOrigin> m_origin; 65 bool m_isSameOriginRequest; 66 RedirectCompletionHandler m_redirectHandler; 62 67 }; 63 68
Note: See TracChangeset
for help on using the changeset viewer.