Title: [220817] trunk
Revision
220817
Author
cdu...@apple.com
Date
2017-08-16 17:28:25 -0700 (Wed, 16 Aug 2017)

Log Message

Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight
https://bugs.webkit.org/show_bug.cgi?id=175628
<rdar://problem/33919278>

Reviewed by Geoffrey Garen.

LayoutTests/imported/w3c:

Rebaseline a few web-platform-tests due to revert of r220779.

* web-platform-tests/beacon/headers/header-content-type-expected.txt:
* web-platform-tests/fetch/api/basic/request-headers.any-expected.txt:
* web-platform-tests/fetch/api/basic/request-headers.any.worker-expected.txt:

Source/WebCore:

Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight.
To achieve this, the following changes were made:
1. Revert r220779 which caused us to use a non CORS-safelisted Content-Type header for such payload
2. Teach PingLoad how to deal with "simple" cross origin requests (i.e. Don't assume we need a CORS
   preflight merely because the fetch mode is set to "cors").

Test: http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html

* Modules/fetch/FetchBody.cpp:
(WebCore::FetchBody::extract):
* loader/CrossOriginAccessControl.h:
* loader/LoaderStrategy.h:
* loader/PingLoader.cpp:
(WebCore::PingLoader::loadImage):
(WebCore::PingLoader::sendPing):
(WebCore::PingLoader::sendViolationReport):
(WebCore::PingLoader::startPingLoad):
* loader/PingLoader.h:
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::CachedResource):
(WebCore::CachedResource::load):
* loader/cache/CachedResource.h:
* loader/cache/CachedResourceRequest.cpp:
(WebCore::CachedResourceRequest::CachedResourceRequest):
* loader/cache/CachedResourceRequest.h:
(WebCore::CachedResourceRequest::releaseOriginalRequestHeaders):
* platform/network/HTTPHeaderValues.cpp:
* platform/network/HTTPHeaderValues.h:

Source/WebKit:

Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight.
To achieve this, the following changes were made:
1. Revert r220779 which caused us to use a non CORS-safelisted Content-Type header for such payload
2. Teach PingLoad how to deal with "simple" cross origin requests (i.e. Don't assume we need a CORS
   preflight merely because the fetch mode is set to "cors").

* NetworkProcess/NetworkCORSPreflightChecker.cpp:
(WebKit::NetworkCORSPreflightChecker::startPreflight):
* NetworkProcess/NetworkResourceLoadParameters.cpp:
(WebKit::NetworkResourceLoadParameters::encode const):
(WebKit::NetworkResourceLoadParameters::decode):
* NetworkProcess/NetworkResourceLoadParameters.h:
* NetworkProcess/PingLoad.cpp:
(WebKit::PingLoad::PingLoad):
(WebKit::PingLoad::loadRequest):
(WebKit::PingLoad::originalRequestHeaders const):
(WebKit::PingLoad::willPerformHTTPRedirection):
(WebKit::PingLoad::isAllowedRedirect const):
(WebKit::PingLoad::makeCrossOriginAccessRequest):
(WebKit::PingLoad::makeSimpleCrossOriginAccessRequest):
(WebKit::PingLoad::makeCrossOriginAccessRequestWithPreflight):
(WebKit::PingLoad::preflightSuccess):
* NetworkProcess/PingLoad.h:
* WebProcess/Network/WebLoaderStrategy.cpp:
(WebKit::WebLoaderStrategy::createPingHandle):
* WebProcess/Network/WebLoaderStrategy.h:

Source/WebKitLegacy:

* WebCoreSupport/WebResourceLoadScheduler.cpp:
(WebResourceLoadScheduler::createPingHandle):
* WebCoreSupport/WebResourceLoadScheduler.h:

LayoutTests:

* http/tests/blink/sendbeacon/beacon-same-origin-expected.txt:
* http/wpt/fetch/fetch-request-arraybuffer-content-type-expected.txt:
* http/wpt/fetch/fetch-request-arraybuffer-content-type.html:
Rebaseline test due to revert of r220779.

* http/wpt/beacon/cors/cors-preflight-arraybufferview-failure-expected.txt: Removed.
* http/wpt/beacon/cors/cors-preflight-arraybufferview-failure.html: Removed.
Drop outdated test. CORS preflight failure is still covered by the corresponding Blob payload test.

* http/wpt/beacon/cors/cors-preflight-arraybufferview-success-expected.txt: Removed.
* http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html: Removed.
* http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight-expected.txt: Added.
* http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html: Added.
Rename and update test so that it checks that we no longer do a CORS preflight for cross origin
beacons that have an ArrayBuffer payload.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (220816 => 220817)


--- trunk/LayoutTests/ChangeLog	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/ChangeLog	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +1,27 @@
+2017-08-16  Chris Dumez  <cdu...@apple.com>
+
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight
+        https://bugs.webkit.org/show_bug.cgi?id=175628
+        <rdar://problem/33919278>
+
+        Reviewed by Geoffrey Garen.
+
+        * http/tests/blink/sendbeacon/beacon-same-origin-expected.txt:
+        * http/wpt/fetch/fetch-request-arraybuffer-content-type-expected.txt:
+        * http/wpt/fetch/fetch-request-arraybuffer-content-type.html:
+        Rebaseline test due to revert of r220779.
+
+        * http/wpt/beacon/cors/cors-preflight-arraybufferview-failure-expected.txt: Removed.
+        * http/wpt/beacon/cors/cors-preflight-arraybufferview-failure.html: Removed.
+        Drop outdated test. CORS preflight failure is still covered by the corresponding Blob payload test.
+
+        * http/wpt/beacon/cors/cors-preflight-arraybufferview-success-expected.txt: Removed.
+        * http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html: Removed.
+        * http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight-expected.txt: Added.
+        * http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html: Added.
+        Rename and update test so that it checks that we no longer do a CORS preflight for cross origin
+        beacons that have an ArrayBuffer payload.
+
 2017-08-16  Matt Baker  <mattba...@apple.com>
 
         Web Inspector: capture async stack trace when workers/main context posts a message

Modified: trunk/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin-expected.txt (220816 => 220817)


--- trunk/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/tests/blink/sendbeacon/beacon-same-origin-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -16,7 +16,7 @@
 Sending beacon with type: [object Uint32Array]
 PASS navigator.sendBeacon("resources/save-beacon.php?name=same-origin", payload); is true
 PASS Beacon sent successfully
-PASS Content-Type: application/octet-stream
+PASS Content-Type: application/x-www-form-urlencoded
 PASS Origin: http://127.0.0.1:8000
 PASS Referer: http://127.0.0.1:8000/blink/sendbeacon/beacon-same-origin.html
 PASS Request-Method: POST

Deleted: trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure-expected.txt (220816 => 220817)


--- trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +0,0 @@
-
-PASS CORS preflight failure test 
-

Deleted: trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure.html (220816 => 220817)


--- trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure.html	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-failure.html	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,63 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>SendBeacon CORS preflight test</title>
-    <script src=""
-    <script src=""
-  </head>
-  <body>
-    <script src=""
-    <script src=""
-    <script>
-var RESOURCES_DIR = "/WebKit/beacon/resources/";
-
-function pollResult(test, id) {
-  var checkUrl = RESOURCES_DIR + "beacon-preflight.py?cmd=get&id=" + id;
-
-  return new Promise(resolve => {
-    step_timeout(test.step_func(() => {
-      fetch(checkUrl).then(response => {
-        response.json().then(body => {
-          resolve(body);
-        });
-      });
-    }), 1000);
-  });
-}
-
-function testCORSPreflightFailure(what) {
-  var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR;
-  var id = self.token();
-  var testUrl = testBase + "beacon-preflight.py?allowCors=0&cmd=put&id=" + id;
-
-  promise_test(function(test) {
-    assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded");
-    return pollResult(test, id) .then(result => {
-      assert_equals(result['preflight'], 1, "Received preflight")
-      assert_equals(result['preflight_referer'], document.URL, "Preflight referer header")
-      assert_equals(result['preflight_requested_method'], "POST", "Preflight requested method")
-      let requested_headers = result['preflight_requested_headers'].toLowerCase()
-      assert_true(requested_headers.includes("content-type"), "Content-Type header is requested")
-      assert_true(requested_headers.includes("referer"), "Referer header is requested")
-      assert_true(requested_headers.includes("origin"), "Origin header is requested")
-      assert_equals(result['beacon'], 0, "Did not receive beacon")
-    });
-  }, "CORS preflight failure test");
-}
-
-function stringToArrayBufferView(input) {
-  var buffer = new ArrayBuffer(input.length * 2);
-  var view = new Uint16Array(buffer);
-
-  // dumbly copy over the bytes
-  for (var i = 0, len = input.length; i < len; i++) {
-    view[i] = input.charCodeAt(i);
-  }
-  return view;
-}
-
-testCORSPreflightFailure(stringToArrayBufferView("123"));
-    </script>
-  </body>
-</html>

Deleted: trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success-expected.txt (220816 => 220817)


--- trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +0,0 @@
-
-PASS CORS preflight success test 
-

Deleted: trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html (220816 => 220817)


--- trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,63 +0,0 @@
-<!doctype html>
-<html>
-  <head>
-    <meta charset="utf-8">
-    <title>SendBeacon CORS preflight test</title>
-    <script src=""
-    <script src=""
-  </head>
-  <body>
-    <script src=""
-    <script src=""
-    <script>
-var RESOURCES_DIR = "/WebKit/beacon/resources/";
-
-function pollResult(test, id) {
-  var checkUrl = RESOURCES_DIR + "beacon-preflight.py?cmd=get&id=" + id;
-
-  return new Promise(resolve => {
-    step_timeout(test.step_func(() => {
-      fetch(checkUrl).then(response => {
-        response.json().then(body => {
-          resolve(body);
-        });
-      });
-    }), 1000);
-  });
-}
-
-function testCORSPreflightSuccess(what) {
-  var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR;
-  var id = self.token();
-  var testUrl = testBase + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id;
-
-  promise_test(function(test) {
-    assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded");
-    return pollResult(test, id) .then(result => {
-      assert_equals(result['preflight'], 1, "Received preflight")
-      assert_equals(result['preflight_referer'], document.URL, "Preflight referer header")
-      assert_equals(result['preflight_requested_method'], "POST", "Preflight requested method")
-      let requested_headers = result['preflight_requested_headers'].toLowerCase()
-      assert_true(requested_headers.includes("content-type"), "Content-Type header is requested")
-      assert_true(requested_headers.includes("referer"), "Referer header is requested")
-      assert_true(requested_headers.includes("origin"), "Origin header is requested")
-      assert_equals(result['beacon'], 1, "Received beacon")
-    });
-  }, "CORS preflight success test");
-}
-
-function stringToArrayBufferView(input) {
-  var buffer = new ArrayBuffer(input.length * 2);
-  var view = new Uint16Array(buffer);
-
-  // dumbly copy over the bytes
-  for (var i = 0, len = input.length; i < len; i++) {
-    view[i] = input.charCodeAt(i);
-  }
-  return view;
-}
-
-testCORSPreflightSuccess(stringToArrayBufferView("123"));
-    </script>
-  </body>
-</html>

Added: trunk/LayoutTests/http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight-expected.txt (0 => 220817)


--- trunk/LayoutTests/http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -0,0 +1,3 @@
+
+PASS Should send beacon with no CORS preflight 
+

Copied: trunk/LayoutTests/http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html (from rev 220816, trunk/LayoutTests/http/wpt/beacon/cors/cors-preflight-arraybufferview-success.html) (0 => 220817)


--- trunk/LayoutTests/http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html	2017-08-17 00:28:25 UTC (rev 220817)
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8">
+    <title>SendBeacon cross origin with an ArrayBuffer / ArrayBufferView payload should not do a CORS preflight</title>
+    <script src=""
+    <script src=""
+  </head>
+  <body>
+    <script src=""
+    <script src=""
+    <script>
+var RESOURCES_DIR = "/WebKit/beacon/resources/";
+
+function pollResult(test, id) {
+  var checkUrl = RESOURCES_DIR + "beacon-preflight.py?cmd=get&id=" + id;
+
+  return new Promise(resolve => {
+    step_timeout(test.step_func(() => {
+      fetch(checkUrl).then(response => {
+        response.json().then(body => {
+          resolve(body);
+        });
+      });
+    }), 1000);
+  });
+}
+
+function testCORSPreflightSuccess(what) {
+  var testBase = get_host_info().HTTP_REMOTE_ORIGIN + RESOURCES_DIR;
+  var id = self.token();
+  var testUrl = testBase + "beacon-preflight.py?allowCors=1&cmd=put&id=" + id;
+
+  promise_test(function(test) {
+    assert_true(navigator.sendBeacon(testUrl, what), "SendBeacon Succeeded");
+    return pollResult(test, id) .then(result => {
+      assert_equals(result['preflight'], 0, "Did not receive CORS preflight")
+      assert_equals(result['beacon'], 1, "Received beacon")
+    });
+  }, "Should send beacon with no CORS preflight");
+}
+
+function stringToArrayBufferView(input) {
+  var buffer = new ArrayBuffer(input.length * 2);
+  var view = new Uint16Array(buffer);
+
+  // dumbly copy over the bytes
+  for (var i = 0, len = input.length; i < len; i++) {
+    view[i] = input.charCodeAt(i);
+  }
+  return view;
+}
+
+testCORSPreflightSuccess(stringToArrayBufferView("123"));
+    </script>
+  </body>
+</html>

Modified: trunk/LayoutTests/http/wpt/fetch/fetch-request-arraybuffer-content-type-expected.txt (220816 => 220817)


--- trunk/LayoutTests/http/wpt/fetch/fetch-request-arraybuffer-content-type-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/wpt/fetch/fetch-request-arraybuffer-content-type-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +1,3 @@
 
-PASS Content-Type header for payload of ArrayBuffer type should be 'application/octet-stream' 
+PASS Content-Type header for payload of ArrayBuffer type should be null 
 

Modified: trunk/LayoutTests/http/wpt/fetch/fetch-request-arraybuffer-content-type.html (220816 => 220817)


--- trunk/LayoutTests/http/wpt/fetch/fetch-request-arraybuffer-content-type.html	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/http/wpt/fetch/fetch-request-arraybuffer-content-type.html	2017-08-17 00:28:25 UTC (rev 220817)
@@ -6,8 +6,8 @@
 <script>
 test(function(t) {
   let request = new Request("http://localhost", { method: "POST", body: new ArrayBuffer() });
-  assert_equals(request.headers.get('Content-Type'), "application/octet-stream");
-}, "Content-Type header for payload of ArrayBuffer type should be 'application/octet-stream'");
+  assert_equals(request.headers.get('Content-Type'), null);
+}, "Content-Type header for payload of ArrayBuffer type should be null");
 </script>
 </body>
 </html>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (220816 => 220817)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,5 +1,19 @@
 2017-08-16  Chris Dumez  <cdu...@apple.com>
 
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight
+        https://bugs.webkit.org/show_bug.cgi?id=175628
+        <rdar://problem/33919278>
+
+        Reviewed by Geoffrey Garen.
+
+        Rebaseline a few web-platform-tests due to revert of r220779.
+
+        * web-platform-tests/beacon/headers/header-content-type-expected.txt:
+        * web-platform-tests/fetch/api/basic/request-headers.any-expected.txt:
+        * web-platform-tests/fetch/api/basic/request-headers.any.worker-expected.txt:
+
+2017-08-16  Chris Dumez  <cdu...@apple.com>
+
         EventSource: ignore IDs with U+0000
         https://bugs.webkit.org/show_bug.cgi?id=175178
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt (220816 => 220817)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/beacon/headers/header-content-type-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,7 +1,7 @@
 
 PASS Test content-type header for a body string 
-FAIL Test content-type header for a body ArrayBufferView assert_equals: Correct Content-Type header result expected "" but got "application/octet-stream"
-FAIL Test content-type header for a body ArrayBuffer assert_equals: Correct Content-Type header result expected "" but got "application/octet-stream"
+FAIL Test content-type header for a body ArrayBufferView assert_equals: Correct Content-Type header result expected "" but got "application/x-www-form-urlencoded"
+FAIL Test content-type header for a body ArrayBuffer assert_equals: Correct Content-Type header result expected "" but got "application/x-www-form-urlencoded"
 PASS Test content-type header for a body Blob 
 PASS Test content-type header for a body FormData 
 PASS Test content-type header for a body URLSearchParams 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers.any-expected.txt (220816 => 220817)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers.any-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers.any-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -8,12 +8,12 @@
 PASS Fetch with POST with FormData body 
 PASS Fetch with POST with URLSearchParams body 
 FAIL Fetch with POST with Blob body assert_equals: Request should have header content-type: null expected (object) null but got (string) ""
-FAIL Fetch with POST with ArrayBuffer body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Uint8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Int8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Float32Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Float64Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with DataView body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
+FAIL Fetch with POST with ArrayBuffer body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Uint8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Int8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Float32Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Float64Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with DataView body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
 PASS Fetch with POST with Blob body with mime type 
 FAIL Fetch with Chicken assert_equals: Request should have header content-length: null expected (object) null but got (string) "0"
 PASS Fetch with Chicken with body 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers.any.worker-expected.txt (220816 => 220817)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers.any.worker-expected.txt	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/request-headers.any.worker-expected.txt	2017-08-17 00:28:25 UTC (rev 220817)
@@ -8,12 +8,12 @@
 FAIL Fetch with POST with FormData body Can't find variable: FormData
 PASS Fetch with POST with URLSearchParams body 
 FAIL Fetch with POST with Blob body assert_equals: Request should have header content-type: null expected (object) null but got (string) ""
-FAIL Fetch with POST with ArrayBuffer body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Uint8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Int8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Float32Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with Float64Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
-FAIL Fetch with POST with DataView body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/octet-stream"
+FAIL Fetch with POST with ArrayBuffer body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Uint8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Int8Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Float32Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with Float64Array body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
+FAIL Fetch with POST with DataView body assert_equals: Request should have header content-type: null expected (object) null but got (string) "application/x-www-form-urlencoded"
 PASS Fetch with POST with Blob body with mime type 
 FAIL Fetch with Chicken assert_equals: Request should have header content-length: null expected (object) null but got (string) "0"
 PASS Fetch with Chicken with body 

Modified: trunk/Source/WebCore/ChangeLog (220816 => 220817)


--- trunk/Source/WebCore/ChangeLog	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/ChangeLog	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +1,40 @@
+2017-08-16  Chris Dumez  <cdu...@apple.com>
+
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight
+        https://bugs.webkit.org/show_bug.cgi?id=175628
+        <rdar://problem/33919278>
+
+        Reviewed by Geoffrey Garen.
+
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight.
+        To achieve this, the following changes were made:
+        1. Revert r220779 which caused us to use a non CORS-safelisted Content-Type header for such payload
+        2. Teach PingLoad how to deal with "simple" cross origin requests (i.e. Don't assume we need a CORS
+           preflight merely because the fetch mode is set to "cors").
+
+        Test: http/wpt/beacon/cors/crossorigin-arraybufferview-no-preflight.html
+
+        * Modules/fetch/FetchBody.cpp:
+        (WebCore::FetchBody::extract):
+        * loader/CrossOriginAccessControl.h:
+        * loader/LoaderStrategy.h:
+        * loader/PingLoader.cpp:
+        (WebCore::PingLoader::loadImage):
+        (WebCore::PingLoader::sendPing):
+        (WebCore::PingLoader::sendViolationReport):
+        (WebCore::PingLoader::startPingLoad):
+        * loader/PingLoader.h:
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::CachedResource):
+        (WebCore::CachedResource::load):
+        * loader/cache/CachedResource.h:
+        * loader/cache/CachedResourceRequest.cpp:
+        (WebCore::CachedResourceRequest::CachedResourceRequest):
+        * loader/cache/CachedResourceRequest.h:
+        (WebCore::CachedResourceRequest::releaseOriginalRequestHeaders):
+        * platform/network/HTTPHeaderValues.cpp:
+        * platform/network/HTTPHeaderValues.h:
+
 2017-08-16  Matt Baker  <mattba...@apple.com>
 
         Web Inspector: capture async stack trace when workers/main context posts a message

Modified: trunk/Source/WebCore/Modules/fetch/FetchBody.cpp (220816 => 220817)


--- trunk/Source/WebCore/Modules/fetch/FetchBody.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/Modules/fetch/FetchBody.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -62,16 +62,10 @@
 
     if (WTF::holds_alternative<RefPtr<ArrayBuffer>>(value)) {
         Ref<const ArrayBuffer> buffer = WTF::get<RefPtr<ArrayBuffer>>(value).releaseNonNull();
-        // FIXME: We should not set a Content-Type here but we need to do this until all network stacks
-        // support sending no Content-Type header (<dar://problem/33906567).
-        contentType = HTTPHeaderValues::octetStreamContentType();
         return FetchBody(WTFMove(buffer));
     }
     if (WTF::holds_alternative<RefPtr<ArrayBufferView>>(value)) {
         Ref<const ArrayBufferView> buffer = WTF::get<RefPtr<ArrayBufferView>>(value).releaseNonNull();
-        // FIXME: We should not set a Content-Type here but we need to do this until all network stacks
-        // support sending no Content-Type header (<dar://problem/33906567).
-        contentType = HTTPHeaderValues::octetStreamContentType();
         return FetchBody(WTFMove(buffer));
     }
 

Modified: trunk/Source/WebCore/loader/CrossOriginAccessControl.h (220816 => 220817)


--- trunk/Source/WebCore/loader/CrossOriginAccessControl.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/CrossOriginAccessControl.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -37,7 +37,7 @@
 class SecurityOrigin;
 class URL;
 
-bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&);
+WEBCORE_EXPORT bool isSimpleCrossOriginAccessRequest(const String& method, const HTTPHeaderMap&);
 bool isOnAccessControlSimpleRequestMethodWhitelist(const String&);
 
 WEBCORE_EXPORT void updateRequestForAccessControl(ResourceRequest&, SecurityOrigin&, StoredCredentials);

Modified: trunk/Source/WebCore/loader/LoaderStrategy.h (220816 => 220817)


--- trunk/Source/WebCore/loader/LoaderStrategy.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/LoaderStrategy.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -36,6 +36,7 @@
 class CachedResource;
 class ContentSecurityPolicy;
 class Frame;
+class HTTPHeaderMap;
 class NetscapePlugInStreamLoader;
 class NetscapePlugInStreamLoaderClient;
 class NetworkingContext;
@@ -63,7 +64,7 @@
     virtual void suspendPendingRequests() = 0;
     virtual void resumePendingRequests() = 0;
 
-    virtual void createPingHandle(NetworkingContext*, ResourceRequest&, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy*, const FetchOptions&) = 0;
+    virtual void createPingHandle(NetworkingContext*, ResourceRequest&, HTTPHeaderMap&& originalRequestHeaders, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy*, const FetchOptions&) = 0;
 
     virtual void storeDerivedDataToCache(const SHA1::Digest& bodyKey, const String& type, const String& partition, WebCore::SharedBuffer&) = 0;
 

Modified: trunk/Source/WebCore/loader/PingLoader.cpp (220816 => 220817)


--- trunk/Source/WebCore/loader/PingLoader.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/PingLoader.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -98,12 +98,15 @@
     document.contentSecurityPolicy()->upgradeInsecureRequestIfNeeded(request, ContentSecurityPolicy::InsecureRequestType::Load);
 
     request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
+
+    HTTPHeaderMap originalRequestHeader = request.httpHeaderFields();
+
     String referrer = SecurityPolicy::generateReferrerHeader(document.referrerPolicy(), request.url(), frame.loader().outgoingReferrer());
     if (!referrer.isEmpty())
         request.setHTTPReferrer(referrer);
     frame.loader().addExtraFieldsToSubresourceRequest(request);
 
-    startPingLoad(frame, request, document, ShouldFollowRedirects::Yes);
+    startPingLoad(frame, request, WTFMove(originalRequestHeader), document, ShouldFollowRedirects::Yes);
 }
 
 // http://www.whatwg.org/specs/web-apps/current-work/multipage/links.html#hyperlink-auditing
@@ -125,6 +128,9 @@
     request.setHTTPContentType("text/ping");
     request.setHTTPBody(FormData::create("PING"));
     request.setHTTPHeaderField(HTTPHeaderName::CacheControl, "max-age=0");
+
+    HTTPHeaderMap originalRequestHeader = request.httpHeaderFields();
+
     frame.loader().addExtraFieldsToSubresourceRequest(request);
 
     auto& sourceOrigin = document.securityOrigin();
@@ -139,7 +145,7 @@
         }
     }
 
-    startPingLoad(frame, request, document, ShouldFollowRedirects::Yes);
+    startPingLoad(frame, request, WTFMove(originalRequestHeader), document, ShouldFollowRedirects::Yes);
 }
 
 void PingLoader::sendViolationReport(Frame& frame, const URL& reportURL, Ref<FormData>&& report, ViolationReportType reportType)
@@ -170,6 +176,8 @@
     if (removeCookies)
         request.setAllowCookies(false);
 
+    HTTPHeaderMap originalRequestHeader = request.httpHeaderFields();
+
     frame.loader().addExtraFieldsToSubresourceRequest(request);
 
     String referrer = SecurityPolicy::generateReferrerHeader(document.referrerPolicy(), reportURL, frame.loader().outgoingReferrer());
@@ -176,10 +184,10 @@
     if (!referrer.isEmpty())
         request.setHTTPReferrer(referrer);
 
-    startPingLoad(frame, request, document, ShouldFollowRedirects::No);
+    startPingLoad(frame, request, WTFMove(originalRequestHeader), document, ShouldFollowRedirects::No);
 }
 
-void PingLoader::startPingLoad(Frame& frame, ResourceRequest& request, Document& document, ShouldFollowRedirects shouldFollowRedirects)
+void PingLoader::startPingLoad(Frame& frame, ResourceRequest& request, HTTPHeaderMap&& originalRequestHeaders, Document& document, ShouldFollowRedirects shouldFollowRedirects)
 {
     unsigned long identifier = frame.page()->progress().createUniqueIdentifier();
     // FIXME: Why activeDocumentLoader? I would have expected documentLoader().
@@ -195,7 +203,7 @@
     InspectorInstrumentation::continueAfterPingLoader(frame, identifier, frame.loader().activeDocumentLoader(), request, ResourceResponse());
 
     auto* contentSecurityPolicy = document.shouldBypassMainWorldContentSecurityPolicy() ? nullptr : document.contentSecurityPolicy();
-    platformStrategies()->loaderStrategy()->createPingHandle(frame.loader().networkingContext(), request, document.securityOrigin(), contentSecurityPolicy, options);
+    platformStrategies()->loaderStrategy()->createPingHandle(frame.loader().networkingContext(), request, WTFMove(originalRequestHeaders), document.securityOrigin(), contentSecurityPolicy, options);
 }
 
 }

Modified: trunk/Source/WebCore/loader/PingLoader.h (220816 => 220817)


--- trunk/Source/WebCore/loader/PingLoader.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/PingLoader.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -40,6 +40,7 @@
 class Document;
 class FormData;
 class Frame;
+class HTTPHeaderMap;
 class URL;
 class ResourceRequest;
 
@@ -56,7 +57,7 @@
 
 private:
     enum class ShouldFollowRedirects { No, Yes };
-    static void startPingLoad(Frame&, ResourceRequest&, Document&, ShouldFollowRedirects);
+    static void startPingLoad(Frame&, ResourceRequest&, HTTPHeaderMap&& originalRequestHeaders, Document&, ShouldFollowRedirects);
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (220816 => 220817)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -117,6 +117,7 @@
 
 CachedResource::CachedResource(CachedResourceRequest&& request, Type type, SessionID sessionID)
     : m_resourceRequest(request.releaseResourceRequest())
+    , m_originalRequestHeaders(request.releaseOriginalRequestHeaders())
     , m_options(request.options())
     , m_decodedDataDeletionTimer(*this, &CachedResource::destroyDecodedData, deadDecodedDataDeletionIntervalForResourceType(type))
     , m_sessionID(sessionID)
@@ -272,7 +273,7 @@
             // Beacon is not exposed to workers so it is safe to rely on the document here.
             auto* document = cachedResourceLoader.document();
             auto* contentSecurityPolicy = document && !document->shouldBypassMainWorldContentSecurityPolicy() ? document->contentSecurityPolicy() : nullptr;
-            platformStrategies()->loaderStrategy()->createPingHandle(frame.loader().networkingContext(), request, *m_origin, contentSecurityPolicy, m_options);
+            platformStrategies()->loaderStrategy()->createPingHandle(frame.loader().networkingContext(), request, HTTPHeaderMap(m_originalRequestHeaders), *m_origin, contentSecurityPolicy, m_options);
             // FIXME: We currently do not get notified when ping loads finish so we treat them as finishing right away.
             finishLoading(nullptr);
             return;

Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (220816 => 220817)


--- trunk/Source/WebCore/loader/cache/CachedResource.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -294,6 +294,7 @@
     // FIXME: Make the rest of these data members private and use functions in derived classes instead.
     HashCountedSet<CachedResourceClient*> m_clients;
     ResourceRequest m_resourceRequest;
+    HTTPHeaderMap m_originalRequestHeaders;
     RefPtr<SubresourceLoader> m_loader;
     ResourceLoaderOptions m_options;
     ResourceResponse m_response;

Modified: trunk/Source/WebCore/loader/cache/CachedResourceRequest.cpp (220816 => 220817)


--- trunk/Source/WebCore/loader/cache/CachedResourceRequest.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/cache/CachedResourceRequest.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -41,6 +41,7 @@
 
 CachedResourceRequest::CachedResourceRequest(ResourceRequest&& resourceRequest, const ResourceLoaderOptions& options, std::optional<ResourceLoadPriority> priority, String&& charset)
     : m_resourceRequest(WTFMove(resourceRequest))
+    , m_originalRequestHeaders(m_resourceRequest.httpHeaderFields())
     , m_charset(WTFMove(charset))
     , m_options(options)
     , m_priority(priority)

Modified: trunk/Source/WebCore/loader/cache/CachedResourceRequest.h (220816 => 220817)


--- trunk/Source/WebCore/loader/cache/CachedResourceRequest.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/loader/cache/CachedResourceRequest.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -51,6 +51,7 @@
     CachedResourceRequest(ResourceRequest&&, const ResourceLoaderOptions&, std::optional<ResourceLoadPriority> = std::nullopt, String&& charset = String());
 
     ResourceRequest&& releaseResourceRequest() { return WTFMove(m_resourceRequest); }
+    HTTPHeaderMap&& releaseOriginalRequestHeaders() { return WTFMove(m_originalRequestHeaders); }
     const ResourceRequest& resourceRequest() const { return m_resourceRequest; }
     const String& charset() const { return m_charset; }
     void setCharset(const String& charset) { m_charset = charset; }
@@ -94,6 +95,7 @@
 
 private:
     ResourceRequest m_resourceRequest;
+    HTTPHeaderMap m_originalRequestHeaders;
     String m_charset;
     ResourceLoaderOptions m_options;
     std::optional<ResourceLoadPriority> m_priority;

Modified: trunk/Source/WebCore/platform/network/HTTPHeaderValues.cpp (220816 => 220817)


--- trunk/Source/WebCore/platform/network/HTTPHeaderValues.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/platform/network/HTTPHeaderValues.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -44,12 +44,6 @@
     return contentType;
 }
 
-const String& octetStreamContentType()
-{
-    static NeverDestroyed<const String> contentType(MAKE_STATIC_STRING_IMPL("application/octet-stream"));
-    return contentType;
-}
-
 const String& noCache()
 {
     static NeverDestroyed<const String> value(MAKE_STATIC_STRING_IMPL("no-cache"));

Modified: trunk/Source/WebCore/platform/network/HTTPHeaderValues.h (220816 => 220817)


--- trunk/Source/WebCore/platform/network/HTTPHeaderValues.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebCore/platform/network/HTTPHeaderValues.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -32,7 +32,6 @@
 
 const String& textPlainContentType();
 const String& formURLEncodedContentType();
-const String& octetStreamContentType();
 const String& noCache();
 const String& maxAge0();
 }

Modified: trunk/Source/WebKit/ChangeLog (220816 => 220817)


--- trunk/Source/WebKit/ChangeLog	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/ChangeLog	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +1,38 @@
+2017-08-16  Chris Dumez  <cdu...@apple.com>
+
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight
+        https://bugs.webkit.org/show_bug.cgi?id=175628
+        <rdar://problem/33919278>
+
+        Reviewed by Geoffrey Garen.
+
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight.
+        To achieve this, the following changes were made:
+        1. Revert r220779 which caused us to use a non CORS-safelisted Content-Type header for such payload
+        2. Teach PingLoad how to deal with "simple" cross origin requests (i.e. Don't assume we need a CORS
+           preflight merely because the fetch mode is set to "cors").
+
+        * NetworkProcess/NetworkCORSPreflightChecker.cpp:
+        (WebKit::NetworkCORSPreflightChecker::startPreflight):
+        * NetworkProcess/NetworkResourceLoadParameters.cpp:
+        (WebKit::NetworkResourceLoadParameters::encode const):
+        (WebKit::NetworkResourceLoadParameters::decode):
+        * NetworkProcess/NetworkResourceLoadParameters.h:
+        * NetworkProcess/PingLoad.cpp:
+        (WebKit::PingLoad::PingLoad):
+        (WebKit::PingLoad::loadRequest):
+        (WebKit::PingLoad::originalRequestHeaders const):
+        (WebKit::PingLoad::willPerformHTTPRedirection):
+        (WebKit::PingLoad::isAllowedRedirect const):
+        (WebKit::PingLoad::makeCrossOriginAccessRequest):
+        (WebKit::PingLoad::makeSimpleCrossOriginAccessRequest):
+        (WebKit::PingLoad::makeCrossOriginAccessRequestWithPreflight):
+        (WebKit::PingLoad::preflightSuccess):
+        * NetworkProcess/PingLoad.h:
+        * WebProcess/Network/WebLoaderStrategy.cpp:
+        (WebKit::WebLoaderStrategy::createPingHandle):
+        * WebProcess/Network/WebLoaderStrategy.h:
+
 2017-08-16  Yoshiaki Jitsukawa  <yoshiaki.jitsuk...@sony.com>
 
         [PAL] Move spi/ios and spi/win directories into PAL

Modified: trunk/Source/WebKit/NetworkProcess/NetworkCORSPreflightChecker.cpp (220816 => 220817)


--- trunk/Source/WebKit/NetworkProcess/NetworkCORSPreflightChecker.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/NetworkProcess/NetworkCORSPreflightChecker.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -33,7 +33,6 @@
 #include "NetworkLoadParameters.h"
 #include "SessionTracker.h"
 #include <WebCore/CrossOriginAccessControl.h>
-#include <WebCore/CrossOriginPreflightResultCache.h>
 #include <WebCore/SecurityOrigin.h>
 
 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_parameters.sessionID.isAlwaysOnLoggingAllowed(), Network, "%p - NetworkCORSPreflightChecker::" fmt, this, ##__VA_ARGS__)
@@ -60,11 +59,6 @@
 void NetworkCORSPreflightChecker::startPreflight()
 {
     RELEASE_LOG_IF_ALLOWED("startPreflight");
-    if (CrossOriginPreflightResultCache::singleton().canSkipPreflight(m_parameters.sourceOrigin->toString(), m_parameters.originalRequest.url(), m_parameters.allowStoredCredentials, m_parameters.originalRequest.httpMethod(), m_parameters.originalRequest.httpHeaderFields())) {
-        RELEASE_LOG_IF_ALLOWED("startPreflight - preflight can be skipped thanks to cached result");
-        m_completionCallback(Result::Success);
-        return;
-    }
 
     NetworkLoadParameters loadParameters;
     loadParameters.sessionID = m_parameters.sessionID;

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp (220816 => 220817)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -88,6 +88,7 @@
         encoder << SecurityOriginData::fromSecurityOrigin(*sourceOrigin);
     encoder.encodeEnum(mode);
     encoder << cspResponseHeaders;
+    encoder << originalRequestHeaders;
 }
 
 bool NetworkResourceLoadParameters::decode(IPC::Decoder& decoder, NetworkResourceLoadParameters& result)
@@ -166,6 +167,8 @@
         return false;
     if (!decoder.decode(result.cspResponseHeaders))
         return false;
+    if (!decoder.decode(result.originalRequestHeaders))
+        return false;
 
     return true;
 }

Modified: trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h (220816 => 220817)


--- trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/NetworkProcess/NetworkResourceLoadParameters.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -30,6 +30,7 @@
 #include "SandboxExtension.h"
 #include <WebCore/ContentSecurityPolicyResponseHeaders.h>
 #include <WebCore/FetchOptions.h>
+#include <WebCore/HTTPHeaderMap.h>
 #include <WebCore/ResourceHandle.h>
 #include <WebCore/ResourceLoaderOptions.h>
 #include <WebCore/ResourceRequest.h>
@@ -59,6 +60,7 @@
     RefPtr<WebCore::SecurityOrigin> sourceOrigin;
     WebCore::FetchOptions::Mode mode;
     std::optional<WebCore::ContentSecurityPolicyResponseHeaders> cspResponseHeaders;
+    std::optional<WebCore::HTTPHeaderMap> originalRequestHeaders;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/NetworkProcess/PingLoad.cpp (220816 => 220817)


--- trunk/Source/WebKit/NetworkProcess/PingLoad.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/NetworkProcess/PingLoad.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -34,6 +34,7 @@
 #include "SessionTracker.h"
 #include <WebCore/ContentSecurityPolicy.h>
 #include <WebCore/CrossOriginAccessControl.h>
+#include <WebCore/CrossOriginPreflightResultCache.h>
 
 #define RELEASE_LOG_IF_ALLOWED(fmt, ...) RELEASE_LOG_IF(m_parameters.sessionID.isAlwaysOnLoggingAllowed(), Network, "%p - PingLoad::" fmt, this, ##__VA_ARGS__)
 
@@ -46,14 +47,19 @@
     , m_timeoutTimer(*this, &PingLoad::timeoutTimerFired)
     , m_isSameOriginRequest(securityOrigin().canRequest(m_parameters.request.url()))
 {
+    ASSERT(m_parameters.sourceOrigin);
+    ASSERT(m_parameters.originalRequestHeaders);
+
     // If the server never responds, this object will hang around forever.
     // Set a very generous timeout, just in case.
     m_timeoutTimer.startOneShot(60000_s);
 
-    if (needsCORSPreflight(m_parameters.request))
-        doCORSPreflight(m_parameters.request);
-    else
-        loadRequest(m_parameters.request);
+    if (m_isSameOriginRequest || m_parameters.mode == FetchOptions::Mode::NoCors) {
+        loadRequest(ResourceRequest { m_parameters.request });
+        return;
+    }
+
+    makeCrossOriginAccessRequest(ResourceRequest { m_parameters.request });
 }
 
 PingLoad::~PingLoad()
@@ -68,12 +74,12 @@
     }
 }
 
-void PingLoad::loadRequest(const ResourceRequest& request)
+void PingLoad::loadRequest(ResourceRequest&& request)
 {
     RELEASE_LOG_IF_ALLOWED("startNetworkLoad");
     if (auto* networkSession = SessionTracker::networkSession(m_parameters.sessionID)) {
         auto loadParameters = m_parameters;
-        loadParameters.request = request;
+        loadParameters.request = WTFMove(request);
         m_task = NetworkDataTask::create(*networkSession, *this, WTFMove(loadParameters));
         m_task->resume();
     } else
@@ -85,6 +91,11 @@
     return m_origin ? *m_origin : *m_parameters.sourceOrigin;
 }
 
+const HTTPHeaderMap& PingLoad::originalRequestHeaders() const
+{
+    return *m_parameters.originalRequestHeaders;
+}
+
 void PingLoad::willPerformHTTPRedirection(ResourceResponse&& redirectResponse, ResourceRequest&& request, RedirectCompletionHandler&& completionHandler)
 {
     RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - shouldFollowRedirects? %d", m_parameters.shouldFollowRedirects);
@@ -103,12 +114,15 @@
 
     // FIXME: We should ensure the number of redirects does not exceed 20.
 
-    if (!needsCORSPreflight(request)) {
-        completionHandler(request);
+    if (isAllowedRedirect(request.url())) {
+        completionHandler(WTFMove(request));
         return;
     }
     RELEASE_LOG_IF_ALLOWED("willPerformHTTPRedirection - Redirect requires a CORS preflight");
 
+    // Force any subsequent request to use these checks.
+    m_isSameOriginRequest = false;
+
     // Use a unique origin for subsequent loads if needed.
     // https://fetch.spec.whatwg.org/#concept-http-redirect-fetch (Step 10).
     ASSERT(m_parameters.mode == FetchOptions::Mode::Cors);
@@ -117,13 +131,19 @@
             m_origin = SecurityOrigin::createUnique();
     }
 
-    m_isSameOriginRequest = false;
+    // Except in case where preflight is needed, loading should be able to continue on its own.
+    if (m_isSimpleRequest && isSimpleCrossOriginAccessRequest(request.httpMethod(), originalRequestHeaders())) {
+        completionHandler(WTFMove(request));
+        return;
+    }
+
+    m_parameters.allowStoredCredentials = DoNotAllowStoredCredentials;
     m_redirectHandler = WTFMove(completionHandler);
 
     // Let's fetch the request with the original headers (equivalent to request cloning specified by fetch algorithm).
     request.setHTTPHeaderFields(m_parameters.request.httpHeaderFields());
 
-    doCORSPreflight(request);
+    makeCrossOriginAccessRequest(WTFMove(request));
 }
 
 void PingLoad::didReceiveChallenge(const AuthenticationChallenge&, ChallengeCompletionHandler&& completionHandler)
@@ -177,12 +197,12 @@
     delete this;
 }
 
-bool PingLoad::needsCORSPreflight(const ResourceRequest& request) const
+bool PingLoad::isAllowedRedirect(const URL& url) const
 {
     if (m_parameters.mode == FetchOptions::Mode::NoCors)
-        return false;
+        return true;
 
-    return !m_isSameOriginRequest || !securityOrigin().canRequest(request.url());
+    return m_isSameOriginRequest && securityOrigin().canRequest(url);
 }
 
 ContentSecurityPolicy* PingLoad::contentSecurityPolicy() const
@@ -194,33 +214,73 @@
     return m_contentSecurityPolicy.get();
 }
 
-void PingLoad::doCORSPreflight(const ResourceRequest& request)
+void PingLoad::makeCrossOriginAccessRequest(ResourceRequest&& request)
 {
-    RELEASE_LOG_IF_ALLOWED("doCORSPreflight");
+    ASSERT(m_parameters.mode == FetchOptions::Mode::Cors);
+    RELEASE_LOG_IF_ALLOWED("makeCrossOriginAccessRequest");
+
+    if (isSimpleCrossOriginAccessRequest(request.httpMethod(), originalRequestHeaders())) {
+        makeSimpleCrossOriginAccessRequest(WTFMove(request));
+        return;
+    }
+
+    m_isSimpleRequest = false;
+    if (CrossOriginPreflightResultCache::singleton().canSkipPreflight(securityOrigin().toString(), request.url(), m_parameters.allowStoredCredentials, request.httpMethod(), originalRequestHeaders())) {
+        RELEASE_LOG_IF_ALLOWED("makeCrossOriginAccessRequest - preflight can be skipped thanks to cached result");
+        preflightSuccess(WTFMove(request));
+    } else
+        makeCrossOriginAccessRequestWithPreflight(WTFMove(request));
+}
+
+void PingLoad::makeSimpleCrossOriginAccessRequest(ResourceRequest&& request)
+{
+    ASSERT(isSimpleCrossOriginAccessRequest(request.httpMethod(), originalRequestHeaders()));
+    RELEASE_LOG_IF_ALLOWED("makeSimpleCrossOriginAccessRequest");
+
+    if (!request.url().protocolIsInHTTPFamily()) {
+        RELEASE_LOG_IF_ALLOWED("makeSimpleCrossOriginAccessRequest: Cross origin requests are only supported for HTTP.");
+        return;
+    }
+
+    updateRequestForAccessControl(request, securityOrigin(), m_parameters.allowStoredCredentials);
+    loadRequest(WTFMove(request));
+}
+
+void PingLoad::makeCrossOriginAccessRequestWithPreflight(ResourceRequest&& request)
+{
+    RELEASE_LOG_IF_ALLOWED("makeCrossOriginAccessRequestWithPreflight");
     ASSERT(!m_corsPreflightChecker);
 
     NetworkCORSPreflightChecker::Parameters parameters = {
-        request,
+        WTFMove(request),
         securityOrigin(),
         m_parameters.sessionID,
         m_parameters.allowStoredCredentials
     };
     m_corsPreflightChecker = std::make_unique<NetworkCORSPreflightChecker>(WTFMove(parameters), [this](NetworkCORSPreflightChecker::Result result) {
-        RELEASE_LOG_IF_ALLOWED("doCORSPreflight complete, success: %d forRedirect? %d", result == NetworkCORSPreflightChecker::Result::Success, !!m_redirectHandler);
+        RELEASE_LOG_IF_ALLOWED("makeCrossOriginAccessRequestWithPreflight preflight complete, success: %d forRedirect? %d", result == NetworkCORSPreflightChecker::Result::Success, !!m_redirectHandler);
         auto corsPreflightChecker = WTFMove(m_corsPreflightChecker);
-        if (result == NetworkCORSPreflightChecker::Result::Success) {
-            ResourceRequest actualRequest = corsPreflightChecker->originalRequest();
-            updateRequestForAccessControl(actualRequest, securityOrigin(), m_parameters.allowStoredCredentials);
-            if (auto redirectHandler = std::exchange(m_redirectHandler, nullptr))
-                redirectHandler(actualRequest);
-            else
-                loadRequest(actualRequest);
-        } else
+        if (result == NetworkCORSPreflightChecker::Result::Success)
+            preflightSuccess(ResourceRequest { corsPreflightChecker->originalRequest() });
+        else
             delete this;
     });
     m_corsPreflightChecker->startPreflight();
 }
 
+void PingLoad::preflightSuccess(ResourceRequest&& request)
+{
+    RELEASE_LOG_IF_ALLOWED("preflightSuccess");
+
+    ResourceRequest actualRequest = WTFMove(request);
+    updateRequestForAccessControl(actualRequest, securityOrigin(), m_parameters.allowStoredCredentials);
+
+    if (auto redirectHandler = std::exchange(m_redirectHandler, nullptr))
+        redirectHandler(WTFMove(actualRequest));
+    else
+        loadRequest(WTFMove(actualRequest));
+}
+
 } // namespace WebKit
 
 #endif // USE(NETWORK_SESSION)

Modified: trunk/Source/WebKit/NetworkProcess/PingLoad.h (220816 => 220817)


--- trunk/Source/WebKit/NetworkProcess/PingLoad.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/NetworkProcess/PingLoad.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -32,6 +32,7 @@
 
 namespace WebCore {
 class ContentSecurityPolicy;
+class URL;
 }
 
 namespace WebKit {
@@ -57,11 +58,15 @@
     void cannotShowURL() final;
     void timeoutTimerFired();
 
-    void loadRequest(const WebCore::ResourceRequest&);
-    bool needsCORSPreflight(const WebCore::ResourceRequest&) const;
-    void doCORSPreflight(const WebCore::ResourceRequest&);
+    void loadRequest(WebCore::ResourceRequest&&);
+    bool isAllowedRedirect(const WebCore::URL&) const;
+    void makeCrossOriginAccessRequest(WebCore::ResourceRequest&&);
+    void makeSimpleCrossOriginAccessRequest(WebCore::ResourceRequest&&);
+    void makeCrossOriginAccessRequestWithPreflight(WebCore::ResourceRequest&&);
+    void preflightSuccess(WebCore::ResourceRequest&&);
 
     WebCore::SecurityOrigin& securityOrigin() const;
+    const WebCore::HTTPHeaderMap& originalRequestHeaders() const; // Needed for CORS checks.
     
     NetworkResourceLoadParameters m_parameters;
     RefPtr<NetworkDataTask> m_task;
@@ -69,6 +74,7 @@
     std::unique_ptr<NetworkCORSPreflightChecker> m_corsPreflightChecker;
     RefPtr<WebCore::SecurityOrigin> m_origin;
     bool m_isSameOriginRequest;
+    bool m_isSimpleRequest { true };
     RedirectCompletionHandler m_redirectHandler;
     mutable std::unique_ptr<WebCore::ContentSecurityPolicy> m_contentSecurityPolicy;
 };

Modified: trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp (220816 => 220817)


--- trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -386,7 +386,7 @@
     }
 }
 
-void WebLoaderStrategy::createPingHandle(NetworkingContext* networkingContext, ResourceRequest& request, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy* contentSecurityPolicy, const FetchOptions& options)
+void WebLoaderStrategy::createPingHandle(NetworkingContext* networkingContext, ResourceRequest& request, HTTPHeaderMap&& originalRequestHeaders, Ref<SecurityOrigin>&& sourceOrigin, ContentSecurityPolicy* contentSecurityPolicy, const FetchOptions& options)
 {
     // It's possible that call to createPingHandle might be made during initial empty Document creation before a NetworkingContext exists.
     // It is not clear that we should send ping loads during that process anyways.
@@ -400,6 +400,7 @@
     
     NetworkResourceLoadParameters loadParameters;
     loadParameters.request = request;
+    loadParameters.originalRequestHeaders = WTFMove(originalRequestHeaders);
     loadParameters.sourceOrigin = WTFMove(sourceOrigin);
     loadParameters.sessionID = webPage ? webPage->sessionID() : SessionID::defaultSessionID();
     loadParameters.allowStoredCredentials = options.credentials == FetchOptions::Credentials::Omit ? DoNotAllowStoredCredentials : AllowStoredCredentials;
@@ -409,7 +410,7 @@
     if (contentSecurityPolicy)
         loadParameters.cspResponseHeaders = contentSecurityPolicy->responseHeaders();
 
-    WebProcess::singleton().networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::LoadPing(loadParameters), 0);
+    WebProcess::singleton().networkConnection().connection().send(Messages::NetworkConnectionToWebProcess::LoadPing(WTFMove(loadParameters)), 0);
 }
 
 void WebLoaderStrategy::storeDerivedDataToCache(const SHA1::Digest& bodyHash, const String& type, const String& partition, WebCore::SharedBuffer& data)

Modified: trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h (220816 => 220817)


--- trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKit/WebProcess/Network/WebLoaderStrategy.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -59,7 +59,7 @@
     void suspendPendingRequests() final;
     void resumePendingRequests() final;
 
-    void createPingHandle(WebCore::NetworkingContext*, WebCore::ResourceRequest&, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&) final;
+    void createPingHandle(WebCore::NetworkingContext*, WebCore::ResourceRequest&, WebCore::HTTPHeaderMap&& originalRequestHeaders, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&) final;
 
     void storeDerivedDataToCache(const SHA1::Digest& bodyHash, const String& type, const String& partition, WebCore::SharedBuffer&) final;
 

Modified: trunk/Source/WebKitLegacy/ChangeLog (220816 => 220817)


--- trunk/Source/WebKitLegacy/ChangeLog	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKitLegacy/ChangeLog	2017-08-17 00:28:25 UTC (rev 220817)
@@ -1,3 +1,15 @@
+2017-08-16  Chris Dumez  <cdu...@apple.com>
+
+        Cross origin Beacon requests with a ArrayBuffer / ArrayBufferView payload should not do a CORS preflight
+        https://bugs.webkit.org/show_bug.cgi?id=175628
+        <rdar://problem/33919278>
+
+        Reviewed by Geoffrey Garen.
+
+        * WebCoreSupport/WebResourceLoadScheduler.cpp:
+        (WebResourceLoadScheduler::createPingHandle):
+        * WebCoreSupport/WebResourceLoadScheduler.h:
+
 2017-08-16  Yoshiaki Jitsukawa  <yoshiaki.jitsuk...@sony.com>
 
         [PAL] Move spi/ios and spi/win directories into PAL

Modified: trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.cpp (220816 => 220817)


--- trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.cpp	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.cpp	2017-08-17 00:28:25 UTC (rev 220817)
@@ -363,7 +363,7 @@
     return m_requestsLoading.size() >= (webResourceLoadScheduler().isSerialLoadingEnabled() ? 1 : m_maxRequestsInFlight);
 }
 
-void WebResourceLoadScheduler::createPingHandle(NetworkingContext* networkingContext, ResourceRequest& request, Ref<SecurityOrigin>&&, WebCore::ContentSecurityPolicy*, const FetchOptions& options)
+void WebResourceLoadScheduler::createPingHandle(NetworkingContext* networkingContext, ResourceRequest& request, HTTPHeaderMap&&, Ref<SecurityOrigin>&&, WebCore::ContentSecurityPolicy*, const FetchOptions& options)
 {
     // PingHandle manages its own lifetime, deleting itself when its purpose has been fulfilled.
     new PingHandle(networkingContext, request, options.credentials != FetchOptions::Credentials::Omit, PingHandle::UsesAsyncCallbacks::No, options.redirect == FetchOptions::Redirect::Follow);

Modified: trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h (220816 => 220817)


--- trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h	2017-08-16 23:29:47 UTC (rev 220816)
+++ trunk/Source/WebKitLegacy/WebCoreSupport/WebResourceLoadScheduler.h	2017-08-17 00:28:25 UTC (rev 220817)
@@ -59,7 +59,7 @@
     void suspendPendingRequests() override;
     void resumePendingRequests() override;
 
-    void createPingHandle(WebCore::NetworkingContext*, WebCore::ResourceRequest&, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&) override;
+    void createPingHandle(WebCore::NetworkingContext*, WebCore::ResourceRequest&, WebCore::HTTPHeaderMap&&, Ref<WebCore::SecurityOrigin>&& sourceOrigin, WebCore::ContentSecurityPolicy*, const WebCore::FetchOptions&) override;
 
     void storeDerivedDataToCache(const SHA1::Digest&, const String&, const String&, WebCore::SharedBuffer&) override { }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to