Title: [220622] trunk
Revision
220622
Author
cdu...@apple.com
Date
2017-08-11 19:51:13 -0700 (Fri, 11 Aug 2017)

Log Message

Implement quota limitation for keepalive Fetch requests
https://bugs.webkit.org/show_bug.cgi?id=175482

Reviewed by Sam Weinig and Youenn Fablet.

LayoutTests/imported/w3c:

* web-platform-tests/fetch/api/basic/scheme-about.any-expected.txt:
* web-platform-tests/fetch/api/basic/scheme-about.any.worker-expected.txt:
* web-platform-tests/fetch/api/cors/cors-multiple-origins-expected.txt:
* web-platform-tests/fetch/api/cors/cors-multiple-origins-worker-expected.txt:
* web-platform-tests/fetch/api/cors/cors-preflight-star.any-expected.txt:
* web-platform-tests/fetch/api/cors/cors-preflight-star.any.worker-expected.txt:
* web-platform-tests/fetch/http-cache/cc-request-expected.txt:
Rebaseline tests now that we provide a more helpful error message when rejecting
the fetch() promise.

* web-platform-tests/fetch/api/request/request-keepalive-quota-expected.txt:
Rebaseline test for keepalive Fetch requests quota which is now passing.

Source/WebCore:

Implement quota limitation for keepalive Fetch requests as per:
- https://fetch.spec.whatwg.org/#http-network-or-cache-fetch (Step 9)

This partly works for Beacon as well, meaning that no Beacon with a body
over 64Kb can be sent. However, we don't keep track about wether or not
beacon loads are inflight or not.

Also update CachedResourceLoader::requestResource() so that the caller
can get a ResourceError when it returns null. This is useful for both
Fetch and Beacon to return better error messages.

Test: http/wpt/beacon/beacon-quota.html

* CMakeLists.txt:
* Modules/beacon/NavigatorBeacon.cpp:
(WebCore::NavigatorBeacon::sendBeacon):
* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::BlobLoader::didReceiveResponse):
(WebCore::FetchBodyOwner::BlobLoader::didFail):
* Modules/fetch/FetchBodyOwner.h:
* Modules/fetch/FetchLoader.cpp:
(WebCore::FetchLoader::start):
(WebCore::FetchLoader::didFail):
* Modules/fetch/FetchLoaderClient.h:
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::BodyLoader::didFail):
* Modules/fetch/FetchResponse.h:
* WebCore.xcodeproj/project.pbxproj:
* loader/DocumentThreadableLoader.cpp:
(WebCore::DocumentThreadableLoader::loadRequest):
* loader/cache/CachedResource.cpp:
(WebCore::CachedResource::load):
* loader/cache/CachedResource.h:
(WebCore::CachedResource::isMainOrMediaOrIconOrRawResource const):
* loader/cache/CachedResourceLoader.cpp:
(WebCore::createResource):
(WebCore::CachedResourceLoader::requestImage):
(WebCore::CachedResourceLoader::requestFont):
(WebCore::CachedResourceLoader::requestTextTrack):
(WebCore::CachedResourceLoader::requestCSSStyleSheet):
(WebCore::CachedResourceLoader::requestUserCSSStyleSheet):
(WebCore::CachedResourceLoader::requestScript):
(WebCore::CachedResourceLoader::requestXSLStyleSheet):
(WebCore::CachedResourceLoader::requestSVGDocument):
(WebCore::CachedResourceLoader::requestLinkResource):
(WebCore::CachedResourceLoader::requestMedia):
(WebCore::CachedResourceLoader::requestIcon):
(WebCore::CachedResourceLoader::requestRawResource):
(WebCore::CachedResourceLoader::requestBeaconResource):
(WebCore::CachedResourceLoader::requestMainResource):
(WebCore::CachedResourceLoader::requestResource):
(WebCore::CachedResourceLoader::preload):
* loader/cache/CachedResourceLoader.h:
* loader/cache/KeepaliveRequestTracker.cpp: Added.
(WebCore::KeepaliveRequestTracker::~KeepaliveRequestTracker):
(WebCore::KeepaliveRequestTracker::canLoadRequest):
(WebCore::KeepaliveRequestTracker::registerRequest):
(WebCore::KeepaliveRequestTracker::responseReceived):
(WebCore::KeepaliveRequestTracker::notifyFinished):
(WebCore::KeepaliveRequestTracker::unregisterRequest):
* loader/cache/KeepaliveRequestTracker.h: Added.
* platform/network/FormData.cpp:
(WebCore::FormDataElement::lengthInBytes const):
(WebCore::FormData::lengthInBytes const):
* platform/network/FormData.h:

LayoutTests:

* fast/xmlhttprequest/xmlhttprequest-nonexistent-file-expected.txt:
* http/tests/contentextensions/async-xhr-onerror-expected.txt:
* http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-iframe-expected.txt:
* http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-main-frame-expected.txt:
* http/tests/security/mixedContent/insecure-xhr-in-main-frame-expected.txt:
Rebaseline a few tests now that we provide a more helpful error message when an XHR is failing synchronously.

* http/wpt/beacon/beacon-quota-expected.txt: Added.
* http/wpt/beacon/beacon-quota.html: Added.
Add layout test coverage for keepalive Fetch requests quota in the context of sendBeacon().
The second part of the test is still failing because WebCore does not currently know when
ping loads (e.g. beacon loads) complete. This will be addressed via Bug 175443.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (220621 => 220622)


--- trunk/LayoutTests/ChangeLog	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/ChangeLog	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,3 +1,23 @@
+2017-08-11  Chris Dumez  <cdu...@apple.com>
+
+        Implement quota limitation for keepalive Fetch requests
+        https://bugs.webkit.org/show_bug.cgi?id=175482
+
+        Reviewed by Sam Weinig and Youenn Fablet.
+
+        * fast/xmlhttprequest/xmlhttprequest-nonexistent-file-expected.txt:
+        * http/tests/contentextensions/async-xhr-onerror-expected.txt:
+        * http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-iframe-expected.txt:
+        * http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-main-frame-expected.txt:
+        * http/tests/security/mixedContent/insecure-xhr-in-main-frame-expected.txt:
+        Rebaseline a few tests now that we provide a more helpful error message when an XHR is failing synchronously.
+
+        * http/wpt/beacon/beacon-quota-expected.txt: Added.
+        * http/wpt/beacon/beacon-quota.html: Added.
+        Add layout test coverage for keepalive Fetch requests quota in the context of sendBeacon().
+        The second part of the test is still failing because WebCore does not currently know when
+        ping loads (e.g. beacon loads) complete. This will be addressed via Bug 175443.
+
 2017-08-11  Ryan Haddad  <ryanhad...@apple.com>
 
         Update TestExpectations for failing media/video-controls tests.

Modified: trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-nonexistent-file-expected.txt (220621 => 220622)


--- trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-nonexistent-file-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/fast/xmlhttprequest/xmlhttprequest-nonexistent-file-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,5 +1,5 @@
 CONSOLE MESSAGE: line 64: Not allowed to load local resource: nonexistent.html
-CONSOLE MESSAGE: line 64: XMLHttpRequest cannot load nonexistent.html due to access control checks.
+CONSOLE MESSAGE: line 64: XMLHttpRequest cannot load nonexistent.html. Not allowed to request resource
 
 Bug 22475: REGRESSION: Async XMLHttpRequest never finishes on nonexistent files anymore
 

Modified: trunk/LayoutTests/http/tests/contentextensions/async-xhr-onerror-expected.txt (220621 => 220622)


--- trunk/LayoutTests/http/tests/contentextensions/async-xhr-onerror-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/http/tests/contentextensions/async-xhr-onerror-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,7 +1,7 @@
 CONSOLE MESSAGE: line 30: Content blocker prevented frame displaying http://127.0.0.1:8000/contentextensions/async-xhr-onerror.html from loading a resource from http://127.0.0.1:8000/contentextensions/resources/url-blocking-test.js
-CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/contentextensions/resources/url-blocking-test.js due to access control checks.
+CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/contentextensions/resources/url-blocking-test.js. Resource blocked by content blocker
 CONSOLE MESSAGE: line 30: Content blocker prevented frame displaying http://127.0.0.1:8000/contentextensions/async-xhr-onerror.html from loading a resource from http://127.0.0.1:8000/contentextensions/resources/url-blocking-test.js
-CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/contentextensions/resources/url-blocking-test.js due to access control checks.
+CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/contentextensions/resources/url-blocking-test.js. Resource blocked by content blocker
 Asynchronous onreadystatechange status: 0, readyState:1, responseText: 
 Finished runTest. Waiting for callbacks
 Asynchronous onreadystatechange status: 0, readyState:1, responseText: 

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-iframe-expected.txt (220621 => 220622)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-iframe-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-iframe-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -2,7 +2,7 @@
 main frame - didFinishDocumentLoadForFrame
 frame "<!--framePath //<!--frame0-->-->" - didCommitLoadForFrame
 CONSOLE MESSAGE: Blocked mixed content http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi because 'block-all-mixed-content' appears in the Content Security Policy.
-CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi due to access control checks.
+CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi. Not allowed to request resource
 frame "<!--framePath //<!--frame0-->-->" - didFinishDocumentLoadForFrame
 frame "<!--framePath //<!--frame0-->-->" - didHandleOnloadEventsForFrame
 main frame - didHandleOnloadEventsForFrame

Modified: trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-main-frame-expected.txt (220621 => 220622)


--- trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-main-frame-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/http/tests/security/contentSecurityPolicy/block-all-mixed-content/insecure-xhr-asynchronous-in-main-frame-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -4,7 +4,7 @@
 main frame - didFinishLoadForFrame
 main frame - didCommitLoadForFrame
 CONSOLE MESSAGE: Blocked mixed content http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi because 'block-all-mixed-content' appears in the Content Security Policy.
-CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi due to access control checks.
+CONSOLE MESSAGE: line 30: XMLHttpRequest cannot load http://127.0.0.1:8000/xmlhttprequest/resources/access-control-basic-allow-star.cgi. Not allowed to request resource
 main frame - didFinishDocumentLoadForFrame
 main frame - didHandleOnloadEventsForFrame
 main frame - didFinishLoadForFrame

Modified: trunk/LayoutTests/http/tests/security/mixedContent/insecure-xhr-in-main-frame-expected.txt (220621 => 220622)


--- trunk/LayoutTests/http/tests/security/mixedContent/insecure-xhr-in-main-frame-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/http/tests/security/mixedContent/insecure-xhr-in-main-frame-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,4 +1,4 @@
 CONSOLE MESSAGE: line 28: [blocked] The page at https://127.0.0.1:8443/security/mixedContent/resources/insecure-xhr-in-main-frame-window.html was not allowed to display insecure content from http://127.0.0.1:8000/.
 
-CONSOLE MESSAGE: line 28: XMLHttpRequest cannot load http://127.0.0.1:8000/ due to access control checks.
+CONSOLE MESSAGE: line 28: XMLHttpRequest cannot load http://127.0.0.1:8000/. Not allowed to request resource
 This test opens a HTTPS window that loads insecure data via XHR. We should trigger a mixed content callback because the main frame in the window is HTTPS but now has insecure data.

Added: trunk/LayoutTests/http/wpt/beacon/beacon-quota-expected.txt (0 => 220622)


--- trunk/LayoutTests/http/wpt/beacon/beacon-quota-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/beacon/beacon-quota-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -0,0 +1,5 @@
+CONSOLE MESSAGE: line 14: Reached maximum amount of queued data of 64Kb for keepalive requests
+
+PASS Beacon with a body above the Quota Limit should fail. 
+FAIL Multiple Beacons Quota Limit assert_false: Second beacon should not be sent because we reached the quota expected false got true
+

Added: trunk/LayoutTests/http/wpt/beacon/beacon-quota.html (0 => 220622)


--- trunk/LayoutTests/http/wpt/beacon/beacon-quota.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/beacon/beacon-quota.html	2017-08-12 02:51:13 UTC (rev 220622)
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<script src=""
+<script src=""
+<script>
+    // We should expect 64KiB of rolling quota for any type of keep-alive request sent.
+    var expectedQuota = 65536;
+
+    function createPayload(payloadSize)
+    {
+        return new Blob(["*".repeat(payloadSize)]);
+    }
+
+    test(function() {
+        assert_false(navigator.sendBeacon("/", createPayload(expectedQuota + 1)));
+    }, "Beacon with a body above the Quota Limit should fail.");
+
+    test(function() {
+        assert_true(navigator.sendBeacon("/", createPayload(expectedQuota)), "Beacon with a body at the Quota Limit should succeed.");
+        assert_false(navigator.sendBeacon("/", createPayload(1)), "Second beacon should not be sent because we reached the quota");
+    }, "Multiple Beacons Quota Limit");
+</script>

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,3 +1,23 @@
+2017-08-11  Chris Dumez  <cdu...@apple.com>
+
+        Implement quota limitation for keepalive Fetch requests
+        https://bugs.webkit.org/show_bug.cgi?id=175482
+
+        Reviewed by Sam Weinig and Youenn Fablet.
+
+        * web-platform-tests/fetch/api/basic/scheme-about.any-expected.txt:
+        * web-platform-tests/fetch/api/basic/scheme-about.any.worker-expected.txt:
+        * web-platform-tests/fetch/api/cors/cors-multiple-origins-expected.txt:
+        * web-platform-tests/fetch/api/cors/cors-multiple-origins-worker-expected.txt:
+        * web-platform-tests/fetch/api/cors/cors-preflight-star.any-expected.txt:
+        * web-platform-tests/fetch/api/cors/cors-preflight-star.any.worker-expected.txt:
+        * web-platform-tests/fetch/http-cache/cc-request-expected.txt:
+        Rebaseline tests now that we provide a more helpful error message when rejecting
+        the fetch() promise.
+
+        * web-platform-tests/fetch/api/request/request-keepalive-quota-expected.txt:
+        Rebaseline test for keepalive Fetch requests quota which is now passing.
+
 2017-08-09  Chris Dumez  <cdu...@apple.com>
 
         Import beacon/headers/header-content-type.html from upstream WPT

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about.any-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about.any-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about.any-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -5,9 +5,9 @@
 CONSOLE MESSAGE: line 27: Fetch API cannot load about:config. Cross origin requests are only supported for HTTP.
 CONSOLE MESSAGE: line 27: Fetch API cannot load about:unicorn. Cross origin requests are only supported for HTTP.
 
-FAIL Fetching about:blank (GET) is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL Fetching about:blank (PUT) is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL Fetching about:blank (POST) is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Fetching about:blank (GET) is OK promise_test: Unhandled rejection with value: object "TypeError: Cross origin requests are only supported for HTTP."
+FAIL Fetching about:blank (PUT) is OK promise_test: Unhandled rejection with value: object "TypeError: Preflight response is not successful"
+FAIL Fetching about:blank (POST) is OK promise_test: Unhandled rejection with value: object "TypeError: Cross origin requests are only supported for HTTP."
 PASS Fetching about:invalid.com is KO 
 PASS Fetching about:config is KO 
 PASS Fetching about:unicorn is KO 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about.any.worker-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about.any.worker-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/basic/scheme-about.any.worker-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,7 +1,7 @@
 
-FAIL Fetching about:blank (GET) is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL Fetching about:blank (PUT) is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL Fetching about:blank (POST) is OK promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Fetching about:blank (GET) is OK promise_test: Unhandled rejection with value: object "TypeError: Cross origin requests are only supported for HTTP."
+FAIL Fetching about:blank (PUT) is OK promise_test: Unhandled rejection with value: object "TypeError: Preflight response is not successful"
+FAIL Fetching about:blank (POST) is OK promise_test: Unhandled rejection with value: object "TypeError: Cross origin requests are only supported for HTTP."
 PASS Fetching about:invalid.com is KO 
 PASS Fetching about:config is KO 
 PASS Fetching about:unicorn is KO 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-multiple-origins-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-multiple-origins-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-multiple-origins-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -11,10 +11,10 @@
 CONSOLE MESSAGE: Access-Control-Allow-Origin cannot contain more than one origin.
 CONSOLE MESSAGE: Fetch API cannot load http://localhost:8801/fetch/api/resources/preflight.py?origin=%2C%20http%3A%2F%2Fexample.com%2C%20https%3A%2F%2Fexample2.com. Access-Control-Allow-Origin cannot contain more than one origin.
 
-FAIL 3 origins allowed, match the 3rd (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match the 3rd ("*") promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match twice (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match twice ("*") promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match twice ("*" and http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL 3 origins allowed, match the 3rd (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match the 3rd ("*") promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match twice (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match twice ("*") promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match twice ("*" and http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
 PASS 3 origins allowed, no match 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-multiple-origins-worker-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-multiple-origins-worker-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-multiple-origins-worker-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -5,10 +5,10 @@
 CONSOLE MESSAGE: Access-Control-Allow-Origin cannot contain more than one origin.
 CONSOLE MESSAGE: Access-Control-Allow-Origin cannot contain more than one origin.
 
-FAIL 3 origins allowed, match the 3rd (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match the 3rd ("*") promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match twice (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match twice ("*") promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL 3 origins allowed, match twice ("*" and http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL 3 origins allowed, match the 3rd (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match the 3rd ("*") promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match twice (http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match twice ("*") promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
+FAIL 3 origins allowed, match twice ("*" and http://localhost:8800) promise_test: Unhandled rejection with value: object "TypeError: Access-Control-Allow-Origin cannot contain more than one origin."
 PASS 3 origins allowed, no match 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-star.any-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-star.any-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-star.any-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -7,8 +7,8 @@
 CONSOLE MESSAGE: Fetch API cannot load http://127.0.0.1:8800/fetch/api/resources/preflight.py?origin=http://localhost:8800&credentials&allow_methods=*&allow_headers=*&. Request header field X-Test is not allowed by Access-Control-Allow-Headers.
 
 PASS CORS that succeeds with credentials: false; method: GET (allowed: get); header: X-Test,1 (allowed: x-test) 
-FAIL CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) promise_test: Unhandled rejection with value: object "TypeError: Method SUPER is not allowed by Access-Control-Allow-Methods."
+FAIL CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) promise_test: Unhandled rejection with value: object "TypeError: Method OK is not allowed by Access-Control-Allow-Methods."
 PASS CORS that fails with credentials: true; method: OK (allowed: *); header: X-Test,1 (allowed: *) 
 PASS CORS that fails with credentials: true; method: PUT (allowed: *); header: undefined (allowed: ) 
 PASS CORS that fails with credentials: true; method: PUT (allowed: put); header: undefined (allowed: *) 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-star.any.worker-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-star.any.worker-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-preflight-star.any.worker-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,7 +1,7 @@
 
 PASS CORS that succeeds with credentials: false; method: GET (allowed: get); header: X-Test,1 (allowed: x-test) 
-FAIL CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL CORS that succeeds with credentials: false; method: SUPER (allowed: *); header: X-Test,1 (allowed: x-test) promise_test: Unhandled rejection with value: object "TypeError: Method SUPER is not allowed by Access-Control-Allow-Methods."
+FAIL CORS that succeeds with credentials: false; method: OK (allowed: *); header: X-Test,1 (allowed: *) promise_test: Unhandled rejection with value: object "TypeError: Method OK is not allowed by Access-Control-Allow-Methods."
 PASS CORS that fails with credentials: true; method: OK (allowed: *); header: X-Test,1 (allowed: *) 
 PASS CORS that fails with credentials: true; method: PUT (allowed: *); header: undefined (allowed: ) 
 PASS CORS that fails with credentials: true; method: PUT (allowed: put); header: undefined (allowed: *) 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,12 +1,12 @@
 
-FAIL Redirect 301 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 301 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 301 21 times 
-FAIL Redirect 302 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 302 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 302 21 times 
-FAIL Redirect 303 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 303 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 303 21 times 
-FAIL Redirect 307 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 307 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 307 21 times 
-FAIL Redirect 308 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 308 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 308 21 times 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-worker-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-worker-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/redirect/redirect-count-worker-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,12 +1,12 @@
 
-FAIL Redirect 301 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 301 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 301 21 times 
-FAIL Redirect 302 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 302 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 302 21 times 
-FAIL Redirect 303 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 303 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 303 21 times 
-FAIL Redirect 307 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 307 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 307 21 times 
-FAIL Redirect 308 20 times promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL Redirect 308 20 times promise_test: Unhandled rejection with value: object "TypeError: too many HTTP redirects"
 PASS Redirect 308 21 times 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-keepalive-quota-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-keepalive-quota-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/request/request-keepalive-quota-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,8 +1,14 @@
+CONSOLE MESSAGE: line 44: Fetch API cannot load http://localhost:8800/fetch/api/resources/trickle.py?count=1&ms=0. Reached maximum amount of queued data of 64Kb for keepalive requests
+CONSOLE MESSAGE: line 71: Fetch API cannot load http://localhost:8800/fetch/api/resources/trickle.py?count=1&ms=0. Reached maximum amount of queued data of 64Kb for keepalive requests
+CONSOLE MESSAGE: Unhandled Promise Rejection: TypeError: Reached maximum amount of queued data of 64Kb for keepalive requests
+CONSOLE MESSAGE: line 88: Fetch API cannot load http://localhost:8800/fetch/api/resources/trickle.py?count=1&ms=0. Reached maximum amount of queued data of 64Kb for keepalive requests
 
+Harness Error (FAIL), message = Reached maximum amount of queued data of 64Kb for keepalive requests
+
 PASS A Keep-Alive fetch() with a small body should succeed. 
 PASS A Keep-Alive fetch() with a body at the Quota Limit should succeed. 
-FAIL A Keep-Alive fetch() with a body over the Quota Limit should reject. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS A Keep-Alive fetch() with a body over the Quota Limit should reject. 
 PASS A Keep-Alive fetch() should return it's allocated Quota upon promise resolution. 
 PASS A Keep-Alive fetch() should return only it's allocated Quota upon promise resolution. 
-FAIL A Keep-Alive fetch() should not be allowed if the Quota is used up. assert_unreached: Should have rejected: undefined Reached unreachable code
+PASS A Keep-Alive fetch() should not be allowed if the Quota is used up. 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/http-cache/cc-request-expected.txt (220621 => 220622)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/http-cache/cc-request-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/http-cache/cc-request-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -10,5 +10,5 @@
 PASS HTTP cache validates fresh response with Last-Modified when request contains Cache-Control: no-cache. 
 PASS HTTP cache validates fresh response with ETag when request contains Cache-Control: no-cache. 
 FAIL HTTP cache doesn't reuse fresh response when request contains Cache-Control: no-store. assert_equals: Response used expected 2 but got 1
-FAIL HTTP cache generates 504 status code when nothing is in cache and request contains Cache-Control: only-if-cached. promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL HTTP cache generates 504 status code when nothing is in cache and request contains Cache-Control: only-if-cached. promise_test: Unhandled rejection with value: object "TypeError: can’t load from network"
 

Modified: trunk/LayoutTests/inspector/worker/resources-in-worker-expected.txt (220621 => 220622)


--- trunk/LayoutTests/inspector/worker/resources-in-worker-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/inspector/worker/resources-in-worker-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 1: Unhandled Promise Rejection: TypeError: Type error
+CONSOLE MESSAGE: line 1: Unhandled Promise Rejection: TypeError: The requested URL was not found on this server.
 Test for Resources in a Worker.
 
 

Modified: trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/fetch/api/request/request-cache-only-if-cached-expected.txt (220621 => 220622)


--- trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/fetch/api/request/request-cache-only-if-cached-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/fetch/api/request/request-cache-only-if-cached-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -5,10 +5,10 @@
 PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and avoids revalidation for fresh responses with Last-Modified and fresh response 
 PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and does not go to the network if a cached response is not found with Etag and fresh response 
 PASS RequestCache "only-if-cached" mode checks the cache for previously cached content and does not go to the network if a cached response is not found with Last-Modified and fresh response 
-FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Etag and fresh response promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Last-Modified and fresh response promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Etag and stale response promise_test: Unhandled rejection with value: object "TypeError: Type error"
-FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Last-Modified and stale response promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Etag and fresh response promise_test: Unhandled rejection with value: object "TypeError: resource unavailable"
+FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Last-Modified and fresh response promise_test: Unhandled rejection with value: object "TypeError: resource unavailable"
+FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Etag and stale response promise_test: Unhandled rejection with value: object "TypeError: resource unavailable"
+FAIL RequestCache "only-if-cached" (with "same-origin") uses cached same-origin redirects to same-origin content with Last-Modified and stale response promise_test: Unhandled rejection with value: object "TypeError: resource unavailable"
 PASS RequestCache "only-if-cached" (with "same-origin") does not follow redirects across origins and rejects with Etag and fresh response 
 PASS RequestCache "only-if-cached" (with "same-origin") does not follow redirects across origins and rejects with Last-Modified and fresh response 
 PASS RequestCache "only-if-cached" (with "same-origin") does not follow redirects across origins and rejects with Etag and stale response 

Modified: trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/fetch/http-cache/cc-request-expected.txt (220621 => 220622)


--- trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/fetch/http-cache/cc-request-expected.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/LayoutTests/platform/mac-wk1/imported/w3c/web-platform-tests/fetch/http-cache/cc-request-expected.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -10,5 +10,5 @@
 PASS HTTP cache validates fresh response with Last-Modified when request contains Cache-Control: no-cache. 
 PASS HTTP cache validates fresh response with ETag when request contains Cache-Control: no-cache. 
 PASS HTTP cache doesn't reuse fresh response when request contains Cache-Control: no-store. 
-FAIL HTTP cache generates 504 status code when nothing is in cache and request contains Cache-Control: only-if-cached. promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL HTTP cache generates 504 status code when nothing is in cache and request contains Cache-Control: only-if-cached. promise_test: Unhandled rejection with value: object "TypeError: can’t load from network"
 

Modified: trunk/Source/WebCore/CMakeLists.txt (220621 => 220622)


--- trunk/Source/WebCore/CMakeLists.txt	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/CMakeLists.txt	2017-08-12 02:51:13 UTC (rev 220622)
@@ -2074,6 +2074,7 @@
     loader/cache/CachedSVGFont.cpp
     loader/cache/CachedScript.cpp
     loader/cache/CachedXSLStyleSheet.cpp
+    loader/cache/KeepaliveRequestTracker.cpp
     loader/cache/MemoryCache.cpp
 
     loader/icon/IconLoader.cpp

Modified: trunk/Source/WebCore/ChangeLog (220621 => 220622)


--- trunk/Source/WebCore/ChangeLog	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/ChangeLog	2017-08-12 02:51:13 UTC (rev 220622)
@@ -1,3 +1,76 @@
+2017-08-11  Chris Dumez  <cdu...@apple.com>
+
+        Implement quota limitation for keepalive Fetch requests
+        https://bugs.webkit.org/show_bug.cgi?id=175482
+
+        Reviewed by Sam Weinig and Youenn Fablet.
+
+        Implement quota limitation for keepalive Fetch requests as per:
+        - https://fetch.spec.whatwg.org/#http-network-or-cache-fetch (Step 9)
+
+        This partly works for Beacon as well, meaning that no Beacon with a body
+        over 64Kb can be sent. However, we don't keep track about wether or not
+        beacon loads are inflight or not.
+
+        Also update CachedResourceLoader::requestResource() so that the caller
+        can get a ResourceError when it returns null. This is useful for both
+        Fetch and Beacon to return better error messages.
+
+        Test: http/wpt/beacon/beacon-quota.html
+
+        * CMakeLists.txt:
+        * Modules/beacon/NavigatorBeacon.cpp:
+        (WebCore::NavigatorBeacon::sendBeacon):
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::BlobLoader::didReceiveResponse):
+        (WebCore::FetchBodyOwner::BlobLoader::didFail):
+        * Modules/fetch/FetchBodyOwner.h:
+        * Modules/fetch/FetchLoader.cpp:
+        (WebCore::FetchLoader::start):
+        (WebCore::FetchLoader::didFail):
+        * Modules/fetch/FetchLoaderClient.h:
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::BodyLoader::didFail):
+        * Modules/fetch/FetchResponse.h:
+        * WebCore.xcodeproj/project.pbxproj:
+        * loader/DocumentThreadableLoader.cpp:
+        (WebCore::DocumentThreadableLoader::loadRequest):
+        * loader/cache/CachedResource.cpp:
+        (WebCore::CachedResource::load):
+        * loader/cache/CachedResource.h:
+        (WebCore::CachedResource::isMainOrMediaOrIconOrRawResource const):
+        * loader/cache/CachedResourceLoader.cpp:
+        (WebCore::createResource):
+        (WebCore::CachedResourceLoader::requestImage):
+        (WebCore::CachedResourceLoader::requestFont):
+        (WebCore::CachedResourceLoader::requestTextTrack):
+        (WebCore::CachedResourceLoader::requestCSSStyleSheet):
+        (WebCore::CachedResourceLoader::requestUserCSSStyleSheet):
+        (WebCore::CachedResourceLoader::requestScript):
+        (WebCore::CachedResourceLoader::requestXSLStyleSheet):
+        (WebCore::CachedResourceLoader::requestSVGDocument):
+        (WebCore::CachedResourceLoader::requestLinkResource):
+        (WebCore::CachedResourceLoader::requestMedia):
+        (WebCore::CachedResourceLoader::requestIcon):
+        (WebCore::CachedResourceLoader::requestRawResource):
+        (WebCore::CachedResourceLoader::requestBeaconResource):
+        (WebCore::CachedResourceLoader::requestMainResource):
+        (WebCore::CachedResourceLoader::requestResource):
+        (WebCore::CachedResourceLoader::preload):
+        * loader/cache/CachedResourceLoader.h:
+        * loader/cache/KeepaliveRequestTracker.cpp: Added.
+        (WebCore::KeepaliveRequestTracker::~KeepaliveRequestTracker):
+        (WebCore::KeepaliveRequestTracker::canLoadRequest):
+        (WebCore::KeepaliveRequestTracker::registerRequest):
+        (WebCore::KeepaliveRequestTracker::responseReceived):
+        (WebCore::KeepaliveRequestTracker::notifyFinished):
+        (WebCore::KeepaliveRequestTracker::unregisterRequest):
+        * loader/cache/KeepaliveRequestTracker.h: Added.
+        * platform/network/FormData.cpp:
+        (WebCore::FormDataElement::lengthInBytes const):
+        (WebCore::FormData::lengthInBytes const):
+        * platform/network/FormData.h:
+
 2017-08-11  Don Olmstead  <don.olmst...@sony.com>
 
         [WTF] Move ValueToString into WTF

Modified: trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp (220621 => 220622)


--- trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/beacon/NavigatorBeacon.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -73,7 +73,12 @@
                 options.mode = FetchOptions::Mode::NoCors;
         }
     }
-    document.cachedResourceLoader().requestBeaconResource({ WTFMove(request), options });
+    ResourceError error;
+    if (!document.cachedResourceLoader().requestBeaconResource({ WTFMove(request), options }, &error)) {
+        if (!error.isNull())
+            document.addConsoleMessage(MessageSource::Network, MessageLevel::Error, error.localizedDescription());
+        return false;
+    }
     return true;
 }
 

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp (220621 => 220622)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -32,6 +32,7 @@
 #include "FetchLoader.h"
 #include "HTTPParsers.h"
 #include "JSBlob.h"
+#include "ResourceError.h"
 #include "ResourceResponse.h"
 
 namespace WebCore {
@@ -277,10 +278,10 @@
 void FetchBodyOwner::BlobLoader::didReceiveResponse(const ResourceResponse& response)
 {
     if (response.httpStatusCode() != 200)
-        didFail();
+        didFail({ });
 }
 
-void FetchBodyOwner::BlobLoader::didFail()
+void FetchBodyOwner::BlobLoader::didFail(const ResourceError&)
 {
     // didFail might be called within FetchLoader::start call.
     if (loader->isStarted())

Modified: trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h (220621 => 220622)


--- trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/fetch/FetchBodyOwner.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -88,7 +88,7 @@
         // FetchLoaderClient API
         void didReceiveResponse(const ResourceResponse&) final;
         void didReceiveData(const char* data, size_t size) final { owner.blobChunk(data, size); }
-        void didFail() final;
+        void didFail(const ResourceError&) final;
         void didSucceed() final { owner.blobLoadingSucceeded(); }
 
         FetchBodyOwner& owner;

Modified: trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp (220621 => 220622)


--- trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/fetch/FetchLoader.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -35,6 +35,7 @@
 #include "FetchBody.h"
 #include "FetchLoaderClient.h"
 #include "FetchRequest.h"
+#include "ResourceError.h"
 #include "ResourceRequest.h"
 #include "ScriptExecutionContext.h"
 #include "SecurityOrigin.h"
@@ -48,7 +49,7 @@
 {
     auto urlForReading = BlobURL::createPublicURL(context.securityOrigin());
     if (urlForReading.isEmpty()) {
-        m_client.didFail();
+        m_client.didFail({ errorDomainWebKitInternal, 0, URL(), ASCIILiteral("Could not create URL for Blob") });
         return;
     }
 
@@ -88,7 +89,7 @@
     contentSecurityPolicy.upgradeInsecureRequestIfNeeded(fetchRequest, ContentSecurityPolicy::InsecureRequestType::Load);
 
     if (!context.shouldBypassMainWorldContentSecurityPolicy() && !contentSecurityPolicy.allowConnectToSource(fetchRequest.url())) {
-        m_client.didFail();
+        m_client.didFail({ errorDomainWebKitInternal, 0, fetchRequest.url(), ASCIILiteral("Not allowed by ContentSecurityPolicy"), ResourceError::Type::AccessControl });
         return;
     }
 
@@ -144,9 +145,9 @@
     m_client.didSucceed();
 }
 
-void FetchLoader::didFail(const ResourceError&)
+void FetchLoader::didFail(const ResourceError& error)
 {
-    m_client.didFail();
+    m_client.didFail(error);
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/fetch/FetchLoaderClient.h (220621 => 220622)


--- trunk/Source/WebCore/Modules/fetch/FetchLoaderClient.h	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/fetch/FetchLoaderClient.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -32,6 +32,7 @@
 
 namespace WebCore {
 
+class ResourceError;
 class ResourceResponse;
 
 class FetchLoaderClient {
@@ -43,7 +44,7 @@
     virtual void didReceiveData(const char*, size_t) { }
 
     virtual void didSucceed() = 0;
-    virtual void didFail() = 0;
+    virtual void didFail(const ResourceError&) = 0;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp (220621 => 220622)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -33,6 +33,7 @@
 #include "HTTPParsers.h"
 #include "JSBlob.h"
 #include "JSFetchResponse.h"
+#include "ResourceError.h"
 #include "ScriptExecutionContext.h"
 
 namespace WebCore {
@@ -138,11 +139,11 @@
     }
 }
 
-void FetchResponse::BodyLoader::didFail()
+void FetchResponse::BodyLoader::didFail(const ResourceError& error)
 {
     ASSERT(m_response.hasPendingActivity());
     if (m_promise)
-        std::exchange(m_promise, std::nullopt)->reject(TypeError);
+        std::exchange(m_promise, std::nullopt)->reject(Exception { TypeError, String(error.localizedDescription()) });
 
 #if ENABLE(STREAMS_API)
     if (m_response.m_readableStreamSource) {

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.h (220621 => 220622)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -118,7 +118,7 @@
     private:
         // FetchLoaderClient API
         void didSucceed() final;
-        void didFail() final;
+        void didFail(const ResourceError&) final;
         void didReceiveResponse(const ResourceResponse&) final;
         void didReceiveData(const char*, size_t) final;
 

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (220621 => 220622)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2017-08-12 02:51:13 UTC (rev 220622)
@@ -3475,6 +3475,8 @@
 		839AAFED1A0C0C8D00605F99 /* HTMLWBRElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 839AAFEB1A0C0C8D00605F99 /* HTMLWBRElement.h */; };
 		83A4A9F91CE7FD8100709B00 /* JSXMLDocumentCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83A4A9F81CE7FD7E00709B00 /* JSXMLDocumentCustom.cpp */; };
 		83B2D1751B8BCD6A00A02E47 /* NativeNodeFilter.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E959E11B8BC22B004D9385 /* NativeNodeFilter.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		83B74EF51F3E0BF200996BC7 /* KeepaliveRequestTracker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83B74EF21F3E0BD700996BC7 /* KeepaliveRequestTracker.cpp */; };
+		83B74EF61F3E0BF200996BC7 /* KeepaliveRequestTracker.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B74EF31F3E0BD700996BC7 /* KeepaliveRequestTracker.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		83B9687B19F8AB83004EF7AF /* StyleBuilderConverter.h in Headers */ = {isa = PBXBuildFile; fileRef = 83B9687919F8AB83004EF7AF /* StyleBuilderConverter.h */; };
 		83BB5C881D5D6F45005A71F4 /* AllDescendantsCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 83BB5C871D5D6F3A005A71F4 /* AllDescendantsCollection.h */; };
 		83C05A5A1A686212007E5DEA /* StylePropertyShorthandFunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83C05A581A686212007E5DEA /* StylePropertyShorthandFunctions.cpp */; };
@@ -11599,6 +11601,8 @@
 		839AAFEA1A0C0C8D00605F99 /* HTMLWBRElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = HTMLWBRElement.cpp; sourceTree = "<group>"; };
 		839AAFEB1A0C0C8D00605F99 /* HTMLWBRElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLWBRElement.h; sourceTree = "<group>"; };
 		83A4A9F81CE7FD7E00709B00 /* JSXMLDocumentCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXMLDocumentCustom.cpp; sourceTree = "<group>"; };
+		83B74EF21F3E0BD700996BC7 /* KeepaliveRequestTracker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeepaliveRequestTracker.cpp; sourceTree = "<group>"; };
+		83B74EF31F3E0BD700996BC7 /* KeepaliveRequestTracker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeepaliveRequestTracker.h; sourceTree = "<group>"; };
 		83B9687919F8AB83004EF7AF /* StyleBuilderConverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleBuilderConverter.h; sourceTree = "<group>"; };
 		83BB5C871D5D6F3A005A71F4 /* AllDescendantsCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AllDescendantsCollection.h; sourceTree = "<group>"; };
 		83C05A581A686212007E5DEA /* StylePropertyShorthandFunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StylePropertyShorthandFunctions.cpp; sourceTree = "<group>"; };
@@ -22365,6 +22369,8 @@
 				BCB16C0E0979C3BD00467741 /* CachedXSLStyleSheet.cpp */,
 				BCB16C0F0979C3BD00467741 /* CachedXSLStyleSheet.h */,
 				F587864902DE3A9A01EA4122 /* CachePolicy.h */,
+				83B74EF21F3E0BD700996BC7 /* KeepaliveRequestTracker.cpp */,
+				83B74EF31F3E0BD700996BC7 /* KeepaliveRequestTracker.h */,
 				BCB16BFE0979C3BD00467741 /* MemoryCache.cpp */,
 				BCB16BFF0979C3BD00467741 /* MemoryCache.h */,
 			);
@@ -26818,7 +26824,6 @@
 				A584FE2C1863870F00843B10 /* CommandLineAPIModule.h in Headers */,
 				A584FE2618637DAB00843B10 /* CommandLineAPIModuleSource.h in Headers */,
 				6550B6A2099DF0270090D781 /* Comment.h in Headers */,
-				511CA67E1F3905A60019E074 /* ServiceWorkerJob.h in Headers */,
 				57E664FC1E73703300765536 /* CommonCryptoDERUtilities.h in Headers */,
 				E1FE137518402A6700892F13 /* CommonCryptoUtilities.h in Headers */,
 				0F60F32B1DFBB10700416D6C /* CommonVM.h in Headers */,
@@ -27541,7 +27546,6 @@
 				93F198E508245E59001E9ABC /* HTMLDocument.h in Headers */,
 				977B3867122883E900B81FF8 /* HTMLDocumentParser.h in Headers */,
 				93F198E608245E59001E9ABC /* HTMLElement.h in Headers */,
-				51BEB6391F3B94B0005029B9 /* ServiceWorkerRegistrationOptions.h in Headers */,
 				A17C81230F2A5CF7005DAAEB /* HTMLElementFactory.h in Headers */,
 				977B37241228721700B81FF8 /* HTMLElementStack.h in Headers */,
 				B562DB6017D3CD630010AF96 /* HTMLElementTypeHelpers.h in Headers */,
@@ -28570,6 +28574,7 @@
 				1A762C780A074F2600989F5B /* JSXPathNSResolver.h in Headers */,
 				1A762C7A0A074F2600989F5B /* JSXPathResult.h in Headers */,
 				BCEFE1EB0DCA5F6400739219 /* JSXSLTProcessor.h in Headers */,
+				83B74EF61F3E0BF200996BC7 /* KeepaliveRequestTracker.h in Headers */,
 				85031B440A44EFC700F992E0 /* KeyboardEvent.h in Headers */,
 				1AE00D59182DAC8D00087DD7 /* KeyedCoding.h in Headers */,
 				517A63C51B74318F00E7DCDC /* KeyedDecoderCF.h in Headers */,
@@ -28800,7 +28805,6 @@
 				07EE76EC1BE96DB000F89133 /* MockRealtimeVideoSource.h in Headers */,
 				07EE76EF1BEA619800F89133 /* MockRealtimeVideoSourceMac.h in Headers */,
 				CDF2B0171820540700F2B424 /* MockSourceBufferPrivate.h in Headers */,
-				511CA6801F39331F0019E074 /* ServiceWorkerJobClient.h in Headers */,
 				CDF2B0191820540700F2B424 /* MockTracks.h in Headers */,
 				C6D74AD509AA282E000B0A52 /* ModifySelectionListLevel.h in Headers */,
 				709A01FE1E3D0BDD006B0D4C /* ModuleFetchFailureKind.h in Headers */,
@@ -29113,7 +29117,6 @@
 				07C1C0E51BFB60ED00BD2256 /* RealtimeMediaSourceSupportedConstraints.h in Headers */,
 				41103AAC1E39791000769F03 /* RealtimeOutgoingAudioSource.h in Headers */,
 				BC4368E80C226E32005EFB5F /* Rect.h in Headers */,
-				511CA6841F3A3CD90019E074 /* ServiceWorkerRegistrationParameters.h in Headers */,
 				FD45A958175D414C00C21EC8 /* RectangleShape.h in Headers */,
 				9831AE4A154225C900FE2644 /* ReferrerPolicy.h in Headers */,
 				BCAB418213E356E800D8AAF3 /* Region.h in Headers */,
@@ -29458,6 +29461,9 @@
 				5182C23F1F313A090059BA7C /* ServiceWorker.h in Headers */,
 				5182C2411F313A090059BA7C /* ServiceWorkerContainer.h in Headers */,
 				5182C2431F313A090059BA7C /* ServiceWorkerGlobalScope.h in Headers */,
+				511CA67E1F3905A60019E074 /* ServiceWorkerJob.h in Headers */,
+				511CA6801F39331F0019E074 /* ServiceWorkerJobClient.h in Headers */,
+				511CA67A1F3904B10019E074 /* ServiceWorkerProvider.h in Headers */,
 				5182C2451F313A090059BA7C /* ServiceWorkerRegistration.h in Headers */,
 				51F174FF1F35899700C74950 /* ServiceWorkerUpdateViaCache.h in Headers */,
 				756B2CE118B7101600FECFAA /* SessionID.h in Headers */,
@@ -29792,7 +29798,6 @@
 				83C1D42F178D5AB500141E68 /* SVGPathSegLinetoAbs.h in Headers */,
 				B2227A780D00BF220071B782 /* SVGPathSegLinetoHorizontal.h in Headers */,
 				83C1D430178D5AB500141E68 /* SVGPathSegLinetoHorizontalAbs.h in Headers */,
-				511CA67A1F3904B10019E074 /* ServiceWorkerProvider.h in Headers */,
 				83C1D431178D5AB500141E68 /* SVGPathSegLinetoHorizontalRel.h in Headers */,
 				83C1D432178D5AB500141E68 /* SVGPathSegLinetoRel.h in Headers */,
 				B2227A7D0D00BF220071B782 /* SVGPathSegLinetoVertical.h in Headers */,
@@ -31509,7 +31514,6 @@
 				51741D120B07259A00ED442C /* HistoryItem.cpp in Sources */,
 				5160F4980B0AA75F00C1D2AF /* HistoryItemMac.mm in Sources */,
 				4969B0F213D0B33F00DF3521 /* HitTestingTransformState.cpp in Sources */,
-				511CA6831F3A3CD90019E074 /* ServiceWorkerRegistrationParameters.cpp in Sources */,
 				2D8287F616E4A0380086BD00 /* HitTestLocation.cpp in Sources */,
 				9307F1D70AF2D59000DBA31A /* HitTestResult.cpp in Sources */,
 				FD31609812B026F700C1A359 /* HRTFDatabase.cpp in Sources */,
@@ -32578,7 +32582,6 @@
 				E1C8BE5D0E8BD15A0064CB7D /* JSWorker.cpp in Sources */,
 				E182568F0EF2B02D00933242 /* JSWorkerGlobalScope.cpp in Sources */,
 				E1C36D340EB0A094007410BC /* JSWorkerGlobalScopeBase.cpp in Sources */,
-				511CA6791F3904B10019E074 /* ServiceWorkerProvider.cpp in Sources */,
 				E18258AC0EF3CD7000933242 /* JSWorkerGlobalScopeCustom.cpp in Sources */,
 				E1C362F00EAF2AA9007410BC /* JSWorkerLocation.cpp in Sources */,
 				E1271A590EEECDE400F61213 /* JSWorkerNavigator.cpp in Sources */,
@@ -32599,6 +32602,7 @@
 				1A762C790A074F2600989F5B /* JSXPathResult.cpp in Sources */,
 				A1C7FAA2133A5D3500D6732D /* JSXPathResultCustom.cpp in Sources */,
 				BCEFE1EA0DCA5F6400739219 /* JSXSLTProcessor.cpp in Sources */,
+				83B74EF51F3E0BF200996BC7 /* KeepaliveRequestTracker.cpp in Sources */,
 				85031B430A44EFC700F992E0 /* KeyboardEvent.cpp in Sources */,
 				517A63C31B74318700E7DCDC /* KeyedDecoderCF.cpp in Sources */,
 				517A63C41B74318B00E7DCDC /* KeyedEncoderCF.cpp in Sources */,
@@ -33125,7 +33129,6 @@
 				A8DF4AE80980C42C0052981B /* RenderTableCol.cpp in Sources */,
 				A8DF4AF00980C42C0052981B /* RenderTableRow.cpp in Sources */,
 				A8DF4AED0980C42C0052981B /* RenderTableSection.cpp in Sources */,
-				511CA67D1F3905A60019E074 /* ServiceWorkerJob.cpp in Sources */,
 				BCEA488B097D93020094C9E4 /* RenderText.cpp in Sources */,
 				AB67D1A8097F3AE300F9392E /* RenderTextControl.cpp in Sources */,
 				083DAEA60F01A7FB00342754 /* RenderTextControlMultiLine.cpp in Sources */,
@@ -33311,7 +33314,10 @@
 				5182C23E1F313A090059BA7C /* ServiceWorker.cpp in Sources */,
 				5182C2401F313A090059BA7C /* ServiceWorkerContainer.cpp in Sources */,
 				5182C2421F313A090059BA7C /* ServiceWorkerGlobalScope.cpp in Sources */,
+				511CA67D1F3905A60019E074 /* ServiceWorkerJob.cpp in Sources */,
+				511CA6791F3904B10019E074 /* ServiceWorkerProvider.cpp in Sources */,
 				5182C2441F313A090059BA7C /* ServiceWorkerRegistration.cpp in Sources */,
+				511CA6831F3A3CD90019E074 /* ServiceWorkerRegistrationParameters.cpp in Sources */,
 				511F7D441EB1C39100E47B83 /* SessionID.cpp in Sources */,
 				93309E0F099E64920056E581 /* SetNodeAttributeCommand.cpp in Sources */,
 				B8DBDB4B130B0F8A00F5CDB1 /* SetSelectionCommand.cpp in Sources */,

Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp (220621 => 220622)


--- trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -451,12 +451,16 @@
 
         // We create an URL here as the request will be moved in requestRawResource
         URL requestUrl = newRequest.resourceRequest().url();
-        m_resource = m_document.cachedResourceLoader().requestRawResource(WTFMove(newRequest));
+        ResourceError error;
+        m_resource = m_document.cachedResourceLoader().requestRawResource(WTFMove(newRequest), &error);
         if (m_resource)
             m_resource->addClient(*this);
         else {
-            // FIXME: Since we receive a synchronous error, this is probably due to some AccessControl checks. We should try to retrieve the actual error.
-            logErrorAndFail(ResourceError(String(), 0, requestUrl, String(), ResourceError::Type::AccessControl));
+            if (error.isNull()) {
+                // FIXME: Since we receive a synchronous error, this is probably due to some AccessControl checks. We should try to retrieve the actual error.
+                logErrorAndFail(ResourceError(String(), 0, requestUrl, String(), ResourceError::Type::AccessControl));
+            } else
+                logErrorAndFail(error);
         }
         return;
     }

Modified: trunk/Source/WebCore/loader/cache/CachedResource.cpp (220621 => 220622)


--- trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/loader/cache/CachedResource.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -259,14 +259,23 @@
         m_fragmentIdentifierForRequest = String();
     }
 
-    // FIXME: We should not special-case Beacon here.
-    if (m_options.keepAlive && type() == CachedResource::Beacon) {
+    if (m_options.keepAlive) {
+        if (!cachedResourceLoader.keepaliveRequestTracker().tryRegisterRequest(*this)) {
+            setResourceError({ errorDomainWebKitInternal, 0, request.url(), ASCIILiteral("Reached maximum amount of queued data of 64Kb for keepalive requests") });
+            failBeforeStarting();
+            return;
+        }
+        // FIXME: We should not special-case Beacon here.
+        if (type() == CachedResource::Beacon) {
         ASSERT(m_origin);
-        // 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);
-        return;
+            // 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);
+            // FIXME: We currently do not get notified when ping loads finish so we treat them as finishing right away.
+            finishLoading(nullptr);
+            return;
+        }
     }
 
     m_loader = platformStrategies()->loaderStrategy()->loadResource(frame, *this, request, m_options);

Modified: trunk/Source/WebCore/loader/cache/CachedResource.h (220621 => 220622)


--- trunk/Source/WebCore/loader/cache/CachedResource.h	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/loader/cache/CachedResource.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -163,7 +163,7 @@
 
     bool isImage() const { return type() == ImageResource; }
     // FIXME: CachedRawResource could be a main resource, an audio/video resource, or a raw XHR/icon resource.
-    bool isMainOrMediaOrIconOrRawResource() const { return type() == MainResource || type() == MediaResource || type() == Icon || type() == RawResource; }
+    bool isMainOrMediaOrIconOrRawResource() const { return type() == MainResource || type() == MediaResource || type() == Icon || type() == RawResource || type() == Beacon; }
     bool ignoreForRequestCount() const
     {
         return m_resourceRequest.ignoreForRequestCount()

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp (220621 => 220622)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -103,13 +103,12 @@
 #endif
     case CachedResource::FontResource:
         return new CachedFont(WTFMove(request), sessionID);
+    case CachedResource::Beacon:
     case CachedResource::MediaResource:
     case CachedResource::RawResource:
     case CachedResource::Icon:
     case CachedResource::MainResource:
         return new CachedRawResource(WTFMove(request), type, sessionID);
-    case CachedResource::Beacon:
-        return new CachedResource(WTFMove(request), CachedResource::Beacon, sessionID);
 #if ENABLE(XSLT)
     case CachedResource::XSLStyleSheet:
         return new CachedXSLStyleSheet(WTFMove(request), sessionID);
@@ -182,7 +181,7 @@
     return sessionID;
 }
 
-CachedResourceHandle<CachedImage> CachedResourceLoader::requestImage(CachedResourceRequest&& request)
+CachedResourceHandle<CachedImage> CachedResourceLoader::requestImage(CachedResourceRequest&& request, ResourceError* error)
 {
     if (Frame* frame = this->frame()) {
         if (frame->loader().pageDismissalEventBeingDispatched() != FrameLoader::PageDismissalType::None) {
@@ -196,33 +195,33 @@
     }
 
     auto defer = clientDefersImage(request.resourceRequest().url()) ? DeferOption::DeferredByClient : DeferOption::NoDefer;
-    return downcast<CachedImage>(requestResource(CachedResource::ImageResource, WTFMove(request), ForPreload::No, defer).get());
+    return downcast<CachedImage>(requestResource(CachedResource::ImageResource, WTFMove(request), error, ForPreload::No, defer).get());
 }
 
-CachedResourceHandle<CachedFont> CachedResourceLoader::requestFont(CachedResourceRequest&& request, bool isSVG)
+CachedResourceHandle<CachedFont> CachedResourceLoader::requestFont(CachedResourceRequest&& request, bool isSVG, ResourceError* error)
 {
 #if ENABLE(SVG_FONTS)
     if (isSVG)
-        return downcast<CachedSVGFont>(requestResource(CachedResource::SVGFontResource, WTFMove(request)).get());
+        return downcast<CachedSVGFont>(requestResource(CachedResource::SVGFontResource, WTFMove(request), error).get());
 #else
     UNUSED_PARAM(isSVG);
 #endif
-    return downcast<CachedFont>(requestResource(CachedResource::FontResource, WTFMove(request)).get());
+    return downcast<CachedFont>(requestResource(CachedResource::FontResource, WTFMove(request), error).get());
 }
 
 #if ENABLE(VIDEO_TRACK)
-CachedResourceHandle<CachedTextTrack> CachedResourceLoader::requestTextTrack(CachedResourceRequest&& request)
+CachedResourceHandle<CachedTextTrack> CachedResourceLoader::requestTextTrack(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedTextTrack>(requestResource(CachedResource::TextTrackResource, WTFMove(request)).get());
+    return downcast<CachedTextTrack>(requestResource(CachedResource::TextTrackResource, WTFMove(request), error).get());
 }
 #endif
 
-CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestCSSStyleSheet(CachedResourceRequest&& request)
+CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestCSSStyleSheet(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedCSSStyleSheet>(requestResource(CachedResource::CSSStyleSheet, WTFMove(request)).get());
+    return downcast<CachedCSSStyleSheet>(requestResource(CachedResource::CSSStyleSheet, WTFMove(request), error).get());
 }
 
-CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestUserCSSStyleSheet(CachedResourceRequest&& request)
+CachedResourceHandle<CachedCSSStyleSheet> CachedResourceLoader::requestUserCSSStyleSheet(CachedResourceRequest&& request, ResourceError*)
 {
     ASSERT(document());
     request.setDomainForCachePartition(*document());
@@ -248,55 +247,55 @@
     return userSheet;
 }
 
-CachedResourceHandle<CachedScript> CachedResourceLoader::requestScript(CachedResourceRequest&& request)
+CachedResourceHandle<CachedScript> CachedResourceLoader::requestScript(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedScript>(requestResource(CachedResource::Script, WTFMove(request)).get());
+    return downcast<CachedScript>(requestResource(CachedResource::Script, WTFMove(request), error).get());
 }
 
 #if ENABLE(XSLT)
-CachedResourceHandle<CachedXSLStyleSheet> CachedResourceLoader::requestXSLStyleSheet(CachedResourceRequest&& request)
+CachedResourceHandle<CachedXSLStyleSheet> CachedResourceLoader::requestXSLStyleSheet(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedXSLStyleSheet>(requestResource(CachedResource::XSLStyleSheet, WTFMove(request)).get());
+    return downcast<CachedXSLStyleSheet>(requestResource(CachedResource::XSLStyleSheet, WTFMove(request), error).get());
 }
 #endif
 
-CachedResourceHandle<CachedSVGDocument> CachedResourceLoader::requestSVGDocument(CachedResourceRequest&& request)
+CachedResourceHandle<CachedSVGDocument> CachedResourceLoader::requestSVGDocument(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedSVGDocument>(requestResource(CachedResource::SVGDocumentResource, WTFMove(request)).get());
+    return downcast<CachedSVGDocument>(requestResource(CachedResource::SVGDocumentResource, WTFMove(request), error).get());
 }
 
 #if ENABLE(LINK_PREFETCH)
-CachedResourceHandle<CachedResource> CachedResourceLoader::requestLinkResource(CachedResource::Type type, CachedResourceRequest&& request)
+CachedResourceHandle<CachedResource> CachedResourceLoader::requestLinkResource(CachedResource::Type type, CachedResourceRequest&& request, ResourceError* error)
 {
     ASSERT(frame());
     ASSERT(type == CachedResource::LinkPrefetch || type == CachedResource::LinkSubresource);
-    return requestResource(type, WTFMove(request));
+    return requestResource(type, WTFMove(request), error);
 }
 #endif
 
-CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestMedia(CachedResourceRequest&& request)
+CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestMedia(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedRawResource>(requestResource(CachedResource::MediaResource, WTFMove(request)).get());
+    return downcast<CachedRawResource>(requestResource(CachedResource::MediaResource, WTFMove(request), error).get());
 }
 
-CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestIcon(CachedResourceRequest&& request)
+CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestIcon(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedRawResource>(requestResource(CachedResource::Icon, WTFMove(request)).get());
+    return downcast<CachedRawResource>(requestResource(CachedResource::Icon, WTFMove(request), error).get());
 }
 
-CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestRawResource(CachedResourceRequest&& request)
+CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestRawResource(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedRawResource>(requestResource(CachedResource::RawResource, WTFMove(request)).get());
+    return downcast<CachedRawResource>(requestResource(CachedResource::RawResource, WTFMove(request), error).get());
 }
 
-CachedResourceHandle<CachedResource> CachedResourceLoader::requestBeaconResource(CachedResourceRequest&& request)
+CachedResourceHandle<CachedResource> CachedResourceLoader::requestBeaconResource(CachedResourceRequest&& request, ResourceError* error)
 {
-    return requestResource(CachedResource::Beacon, WTFMove(request)).get();
+    return requestResource(CachedResource::Beacon, WTFMove(request), error).get();
 }
 
-CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestMainResource(CachedResourceRequest&& request)
+CachedResourceHandle<CachedRawResource> CachedResourceLoader::requestMainResource(CachedResourceRequest&& request, ResourceError* error)
 {
-    return downcast<CachedRawResource>(requestResource(CachedResource::MainResource, WTFMove(request)).get());
+    return downcast<CachedRawResource>(requestResource(CachedResource::MainResource, WTFMove(request), error).get());
 }
 
 static MixedContentChecker::ContentType contentTypeFromResourceType(CachedResource::Type type)
@@ -689,7 +688,7 @@
     request.updateAccordingCacheMode();
 }
 
-CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, CachedResourceRequest&& request, ForPreload forPreload, DeferOption defer)
+CachedResourceHandle<CachedResource> CachedResourceLoader::requestResource(CachedResource::Type type, CachedResourceRequest&& request, ResourceError* error, ForPreload forPreload, DeferOption defer)
 {
     if (Document* document = this->document())
         request.upgradeInsecureRequestIfNeeded(*document);
@@ -700,6 +699,8 @@
 
     if (!url.isValid()) {
         RELEASE_LOG_IF_ALLOWED("requestResource: URL is invalid (frame = %p)", frame());
+        if (error)
+            *error = { errorDomainWebKitInternal, 0, url, ASCIILiteral("URL is invalid") };
         return nullptr;
     }
 
@@ -708,6 +709,8 @@
     // We are passing url as well as request, as request url may contain a fragment identifier.
     if (!canRequest(type, url, request, forPreload)) {
         RELEASE_LOG_IF_ALLOWED("requestResource: Not allowed to request resource (frame = %p)", frame());
+        if (error)
+            *error = { errorDomainWebKitInternal, 0, url, ASCIILiteral("Not allowed to request resource"), ResourceError::Type::AccessControl };
         return nullptr;
     }
 
@@ -725,6 +728,8 @@
                 resource->setResourceError(ResourceError(ContentExtensions::WebKitContentBlockerDomain, 0, resourceRequest.url(), WEB_UI_STRING("The URL was blocked by a content blocker", "WebKitErrorBlockedByContentBlocker description")));
                 return resource;
             }
+            if (error)
+                *error = { errorDomainWebKitInternal, 0, url, ASCIILiteral("Resource blocked by content blocker"), ResourceError::Type::AccessControl };
             return nullptr;
         }
         if (blockedStatus.madeHTTPS
@@ -829,6 +834,8 @@
         if (resource->errorOccurred()) {
             if (resource->allowsCaching() && resource->inCache())
                 memoryCache.remove(*resource);
+            if (error)
+                *error = resource->resourceError();
             return nullptr;
         }
     }
@@ -1245,7 +1252,7 @@
     if (request.charset().isEmpty() && (type == CachedResource::Script || type == CachedResource::CSSStyleSheet))
         request.setCharset(m_document->charset());
 
-    CachedResourceHandle<CachedResource> resource = requestResource(type, WTFMove(request), ForPreload::Yes);
+    CachedResourceHandle<CachedResource> resource = requestResource(type, WTFMove(request), nullptr, ForPreload::Yes);
     if (resource && (!m_preloads || !m_preloads->contains(resource.get()))) {
         // Fonts need special treatment since just creating the resource doesn't trigger a load.
         if (type == CachedResource::FontResource)

Modified: trunk/Source/WebCore/loader/cache/CachedResourceLoader.h (220621 => 220622)


--- trunk/Source/WebCore/loader/cache/CachedResourceLoader.h	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/loader/cache/CachedResourceLoader.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -30,6 +30,7 @@
 #include "CachedResourceHandle.h"
 #include "CachedResourceRequest.h"
 #include "ContentSecurityPolicy.h"
+#include "KeepaliveRequestTracker.h"
 #include "ResourceTimingInformation.h"
 #include "Timer.h"
 #include <wtf/HashMap.h>
@@ -71,25 +72,25 @@
     static Ref<CachedResourceLoader> create(DocumentLoader* documentLoader) { return adoptRef(*new CachedResourceLoader(documentLoader)); }
     ~CachedResourceLoader();
 
-    CachedResourceHandle<CachedImage> requestImage(CachedResourceRequest&&);
-    CachedResourceHandle<CachedCSSStyleSheet> requestCSSStyleSheet(CachedResourceRequest&&);
-    CachedResourceHandle<CachedCSSStyleSheet> requestUserCSSStyleSheet(CachedResourceRequest&&);
-    CachedResourceHandle<CachedScript> requestScript(CachedResourceRequest&&);
-    CachedResourceHandle<CachedFont> requestFont(CachedResourceRequest&&, bool isSVG);
-    CachedResourceHandle<CachedRawResource> requestMedia(CachedResourceRequest&&);
-    CachedResourceHandle<CachedRawResource> requestIcon(CachedResourceRequest&&);
-    CachedResourceHandle<CachedResource> requestBeaconResource(CachedResourceRequest&&);
-    CachedResourceHandle<CachedRawResource> requestRawResource(CachedResourceRequest&&);
-    CachedResourceHandle<CachedRawResource> requestMainResource(CachedResourceRequest&&);
-    CachedResourceHandle<CachedSVGDocument> requestSVGDocument(CachedResourceRequest&&);
+    CachedResourceHandle<CachedImage> requestImage(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedCSSStyleSheet> requestCSSStyleSheet(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedCSSStyleSheet> requestUserCSSStyleSheet(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedScript> requestScript(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedFont> requestFont(CachedResourceRequest&&, bool isSVG, ResourceError* = nullptr);
+    CachedResourceHandle<CachedRawResource> requestMedia(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedRawResource> requestIcon(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedResource> requestBeaconResource(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedRawResource> requestRawResource(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedRawResource> requestMainResource(CachedResourceRequest&&, ResourceError* = nullptr);
+    CachedResourceHandle<CachedSVGDocument> requestSVGDocument(CachedResourceRequest&&, ResourceError* = nullptr);
 #if ENABLE(XSLT)
-    CachedResourceHandle<CachedXSLStyleSheet> requestXSLStyleSheet(CachedResourceRequest&&);
+    CachedResourceHandle<CachedXSLStyleSheet> requestXSLStyleSheet(CachedResourceRequest&&, ResourceError* = nullptr);
 #endif
 #if ENABLE(LINK_PREFETCH)
-    CachedResourceHandle<CachedResource> requestLinkResource(CachedResource::Type, CachedResourceRequest&&);
+    CachedResourceHandle<CachedResource> requestLinkResource(CachedResource::Type, CachedResourceRequest&&, ResourceError* = nullptr);
 #endif
 #if ENABLE(VIDEO_TRACK)
-    CachedResourceHandle<CachedTextTrack> requestTextTrack(CachedResourceRequest&&);
+    CachedResourceHandle<CachedTextTrack> requestTextTrack(CachedResourceRequest&&, ResourceError* = nullptr);
 #endif
 
     // Logs an access denied message to the console for the specified URL.
@@ -146,6 +147,8 @@
 
     bool isAlwaysOnLoggingAllowed() const;
 
+    KeepaliveRequestTracker& keepaliveRequestTracker() { return m_keepaliveRequestTracker; }
+
 private:
     explicit CachedResourceLoader(DocumentLoader*);
 
@@ -152,7 +155,7 @@
     enum class ForPreload { Yes, No };
     enum class DeferOption { NoDefer, DeferredByClient };
 
-    CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, CachedResourceRequest&&, ForPreload = ForPreload::No, DeferOption = DeferOption::NoDefer);
+    CachedResourceHandle<CachedResource> requestResource(CachedResource::Type, CachedResourceRequest&&, ResourceError* = nullptr, ForPreload = ForPreload::No, DeferOption = DeferOption::NoDefer);
     CachedResourceHandle<CachedResource> revalidateResource(CachedResourceRequest&&, CachedResource&);
     CachedResourceHandle<CachedResource> loadResource(CachedResource::Type, CachedResourceRequest&&);
 
@@ -193,6 +196,7 @@
     Timer m_garbageCollectDocumentResourcesTimer;
 
     ResourceTimingInformation m_resourceTimingInfo;
+    KeepaliveRequestTracker m_keepaliveRequestTracker;
 
     // 29 bits left
     bool m_autoLoadImages : 1;

Added: trunk/Source/WebCore/loader/cache/KeepaliveRequestTracker.cpp (0 => 220622)


--- trunk/Source/WebCore/loader/cache/KeepaliveRequestTracker.cpp	                        (rev 0)
+++ trunk/Source/WebCore/loader/cache/KeepaliveRequestTracker.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "KeepaliveRequestTracker.h"
+
+namespace WebCore {
+
+const uint64_t maxInflightKeepaliveBytes { 65536 }; // 64 kibibytes as per Fetch specification.
+
+KeepaliveRequestTracker::~KeepaliveRequestTracker()
+{
+    auto inflightRequests = WTFMove(m_inflightKeepaliveRequests);
+    for (auto& resource : inflightRequests)
+        resource->removeClient(*this);
+}
+
+bool KeepaliveRequestTracker::tryRegisterRequest(CachedResource& resource)
+{
+    ASSERT(resource.options().keepAlive);
+    auto* body = resource.resourceRequest().httpBody();
+    if (!body)
+        return true;
+
+    uint64_t bodySize = body->lengthInBytes();
+    if (m_inflightKeepaliveBytes + bodySize > maxInflightKeepaliveBytes)
+        return false;
+
+    registerRequest(resource);
+    return true;
+}
+
+void KeepaliveRequestTracker::registerRequest(CachedResource& resource)
+{
+    ASSERT(resource.options().keepAlive);
+    auto* body = resource.resourceRequest().httpBody();
+    if (!body)
+        return;
+    ASSERT(!m_inflightKeepaliveRequests.contains(&resource));
+    m_inflightKeepaliveRequests.append(&resource);
+    m_inflightKeepaliveBytes += body->lengthInBytes();
+    ASSERT(m_inflightKeepaliveBytes <= maxInflightKeepaliveBytes);
+
+    resource.addClient(*this);
+}
+
+void KeepaliveRequestTracker::responseReceived(CachedResource& resource, const ResourceResponse&)
+{
+    // Per Fetch specification, allocated quota should be returned before the promise is resolved,
+    // which is when the response is received.
+    unregisterRequest(resource);
+}
+
+void KeepaliveRequestTracker::notifyFinished(CachedResource& resource)
+{
+    unregisterRequest(resource);
+}
+
+void KeepaliveRequestTracker::unregisterRequest(CachedResource& resource)
+{
+    ASSERT(resource.options().keepAlive);
+    resource.removeClient(*this);
+    bool wasRemoved = m_inflightKeepaliveRequests.removeFirst(&resource);
+    ASSERT_UNUSED(wasRemoved, wasRemoved);
+    m_inflightKeepaliveBytes -= resource.resourceRequest().httpBody()->lengthInBytes();
+    ASSERT(m_inflightKeepaliveBytes <= maxInflightKeepaliveBytes);
+}
+
+}

Added: trunk/Source/WebCore/loader/cache/KeepaliveRequestTracker.h (0 => 220622)


--- trunk/Source/WebCore/loader/cache/KeepaliveRequestTracker.h	                        (rev 0)
+++ trunk/Source/WebCore/loader/cache/KeepaliveRequestTracker.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CachedRawResourceClient.h"
+#include "CachedResource.h"
+#include "CachedResourceHandle.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class KeepaliveRequestTracker final : public CachedRawResourceClient {
+public:
+    ~KeepaliveRequestTracker();
+    bool tryRegisterRequest(CachedResource&);
+
+    // CachedRawResourceClient.
+    void responseReceived(CachedResource&, const ResourceResponse&) final;
+    void notifyFinished(CachedResource&) final;
+
+private:
+    void registerRequest(CachedResource&);
+    void unregisterRequest(CachedResource&);
+
+    Vector<CachedResourceHandle<CachedResource>> m_inflightKeepaliveRequests;
+    uint64_t m_inflightKeepaliveBytes { 0 };
+};
+
+}

Modified: trunk/Source/WebCore/platform/network/FormData.cpp (220621 => 220622)


--- trunk/Source/WebCore/platform/network/FormData.cpp	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/platform/network/FormData.cpp	2017-08-12 02:51:13 UTC (rev 220622)
@@ -33,6 +33,7 @@
 #include "FormDataList.h"
 #include "Page.h"
 #include "TextEncoding.h"
+#include "ThreadableBlobRegistry.h"
 
 namespace WebCore {
 
@@ -124,6 +125,26 @@
     return formData;
 }
 
+uint64_t FormDataElement::lengthInBytes() const
+{
+    switch (m_type) {
+    case Type::Data:
+        return m_data.size();
+    case Type::EncodedFile: {
+        if (m_fileLength != BlobDataItem::toEndOfFile)
+            return m_fileLength;
+        long long fileSize;
+        if (getFileSize(m_shouldGenerateFile ? m_generatedFilename : m_filename, fileSize))
+            return fileSize;
+        return 0;
+    }
+    case Type::EncodedBlob:
+        return blobRegistry().blobSize(m_url);
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
 FormDataElement FormDataElement::isolatedCopy() const
 {
     switch (m_type) {
@@ -146,16 +167,19 @@
 void FormData::appendFile(const String& filename, bool shouldGenerateFile)
 {
     m_elements.append(FormDataElement(filename, 0, BlobDataItem::toEndOfFile, invalidFileTime(), shouldGenerateFile));
+    m_lengthInBytes = std::nullopt;
 }
 
 void FormData::appendFileRange(const String& filename, long long start, long long length, double expectedModificationTime, bool shouldGenerateFile)
 {
     m_elements.append(FormDataElement(filename, start, length, expectedModificationTime, shouldGenerateFile));
+    m_lengthInBytes = std::nullopt;
 }
 
 void FormData::appendBlob(const URL& blobURL)
 {
     m_elements.append(FormDataElement(blobURL));
+    m_lengthInBytes = std::nullopt;
 }
 
 void FormData::appendKeyValuePairItems(const FormDataList& list, const TextEncoding& encoding, bool isMultiPartForm, Document* document, EncodingType encodingType)
@@ -244,6 +268,7 @@
 
 char* FormData::expandDataStore(size_t size)
 {
+    m_lengthInBytes = std::nullopt;
     if (m_elements.isEmpty() || m_elements.last().m_type != FormDataElement::Type::Data)
         m_elements.append(FormDataElement());
     FormDataElement& e = m_elements.last();
@@ -386,4 +411,15 @@
     }
 }
 
+uint64_t FormData::lengthInBytes() const
+{
+    if (!m_lengthInBytes) {
+        uint64_t length = 0;
+        for (auto& element : m_elements)
+            length += element.lengthInBytes();
+        m_lengthInBytes = length;
+    }
+    return *m_lengthInBytes;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/platform/network/FormData.h (220621 => 220622)


--- trunk/Source/WebCore/platform/network/FormData.h	2017-08-12 01:13:47 UTC (rev 220621)
+++ trunk/Source/WebCore/platform/network/FormData.h	2017-08-12 02:51:13 UTC (rev 220622)
@@ -69,6 +69,8 @@
     {
     }
 
+    uint64_t lengthInBytes() const;
+
     FormDataElement isolatedCopy() const;
 
     template<typename Encoder>
@@ -254,12 +256,13 @@
         return FormURLEncoded;
     }
 
+    uint64_t lengthInBytes() const;
+
 private:
     FormData();
     FormData(const FormData&);
 
     void appendKeyValuePairItems(const FormDataList&, const TextEncoding&, bool isMultiPartForm, Document*, EncodingType = FormURLEncoded);
-
     bool hasGeneratedFiles() const;
     bool hasOwnedGeneratedFiles() const;
 
@@ -269,6 +272,7 @@
     bool m_alwaysStream { false };
     Vector<char> m_boundary;
     bool m_containsPasswordData { false };
+    mutable std::optional<uint64_t> m_lengthInBytes;
 };
 
 inline bool operator==(const FormData& a, const FormData& b)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to