Diff
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2020-03-12 15:38:01 UTC (rev 258330)
@@ -1,3 +1,26 @@
+2020-03-12 Rob Buis <[email protected]>
+
+ Implement wildcard behavior for Cross-Origin-Expose-Headers
+ https://bugs.webkit.org/show_bug.cgi?id=208800
+
+ Reviewed by Youenn Fablet.
+
+ Update improved test results and add a test for testing
+ xhr and wildcard behavior for Cross-Origin-Expose-Headers behavior.
+
+ * web-platform-tests/fetch/api/cors/cors-expose-star.sub.any-expected.txt:
+ * web-platform-tests/fetch/api/cors/cors-expose-star.sub.any.worker-expected.txt:
+ * web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt:
+ * web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt:
+ * web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt:
+ * web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https-expected.txt:
+ * web-platform-tests/xhr/cors-expose-star.sub.any-expected.txt: Added.
+ * web-platform-tests/xhr/cors-expose-star.sub.any.html: Added.
+ * web-platform-tests/xhr/cors-expose-star.sub.any.js: Added.
+ (sharedHeaders.string_appeared_here.async_test):
+ (string_appeared_here.async_test):
+ * web-platform-tests/xhr/resources/top.txt: Added.
+
2020-03-11 Antoine Quint <[email protected]>
[ macOS wk1 ] imported/w3c/web-platform-tests/web-animations/timing-model/animations/pausing-an-animation.html is flaky failing
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-expose-star.sub.any-expected.txt (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-expose-star.sub.any-expected.txt 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-expose-star.sub.any-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -1,5 +1,5 @@
-FAIL Basic Access-Control-Expose-Headers: * support assert_equals: expected (string) "X" but got (object) null
+PASS Basic Access-Control-Expose-Headers: * support
PASS * for credentialed fetches only matches literally
-FAIL * can be one of several values assert_equals: expected (string) "X" but got (object) null
+PASS * can be one of several values
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-expose-star.sub.any.worker-expected.txt (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-expose-star.sub.any.worker-expected.txt 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/fetch/api/cors/cors-expose-star.sub.any.worker-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -1,5 +1,5 @@
-FAIL Basic Access-Control-Expose-Headers: * support assert_equals: expected (string) "X" but got (object) null
+PASS Basic Access-Control-Expose-Headers: * support
PASS * for credentialed fetches only matches literally
-FAIL * can be one of several values assert_equals: expected (string) "X" but got (object) null
+PASS * can be one of several values
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -21,7 +21,7 @@
PASS Cache.match with a non-2xx Response
PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
-FAIL cors-exposed header should be stored correctly. assert_equals: expected (string) "bar" but got (object) null
+PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got "text/plain"
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -20,7 +20,7 @@
PASS Cache.match with a non-2xx Response
PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
-FAIL cors-exposed header should be stored correctly. assert_equals: expected (string) "bar" but got (object) null
+PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got "text/plain"
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -20,7 +20,7 @@
PASS Cache.match with a non-2xx Response
PASS Cache.match with a network error Response
PASS Cache produces large Responses that can be cloned and read correctly.
-FAIL cors-exposed header should be stored correctly. assert_equals: expected (string) "bar" but got (object) null
+PASS cors-exposed header should be stored correctly.
PASS MIME type should be set from content-header correctly.
FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got "text/plain"
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https-expected.txt (258329 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https-expected.txt 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-cors-exposed-header-names.https-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -1,4 +1,4 @@
-FAIL CORS-exposed header names for a response from sw assert_equals: expected (string) "bar" but got (object) null
+PASS CORS-exposed header names for a response from sw
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any-expected.txt (0 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any-expected.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any-expected.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -0,0 +1,5 @@
+
+PASS Basic Access-Control-Expose-Headers: * support
+PASS * for credentialed fetches only matches literally
+PASS * can be one of several values
+
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.html (0 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.html (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.html 2020-03-12 15:38:01 UTC (rev 258330)
@@ -0,0 +1 @@
+<!-- This file is required for WebKit test infrastructure to run the templated test -->
\ No newline at end of file
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.js (0 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.js (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.js 2020-03-12 15:38:01 UTC (rev 258330)
@@ -0,0 +1,53 @@
+// META: script=../fetch/api/resources/utils.js
+
+const url = "" + dirname(location.pathname) + "resources/top.txt",
+ sharedHeaders = "?pipe=header(Access-Control-Expose-Headers,*)|header(Test,X)|header(*,whoa)|"
+
+async_test(function() {
+ const headers = "header(Access-Control-Allow-Origin,*)"
+ console.log(url);
+ var client = new XMLHttpRequest();
+ client.open("GET", url + sharedHeaders + headers);
+ client.send();
+ client._onreadystatechange_ = this.step_func(function () {
+ if (this.readyState == this.HEADERS_RECEIVED) {
+ assert_equals(client.getResponseHeader("test"), "X");
+ assert_equals(client.getResponseHeader("set-cookie"), null);
+ assert_equals(client.getResponseHeader("*"), "whoa");
+ this.done();
+ }
+ });
+}, "Basic Access-Control-Expose-Headers: * support")
+
+async_test(function() {
+ const origin = location.origin, // assuming an ASCII origin
+ headers = "header(Access-Control-Allow-Origin," + origin + ")|header(Access-Control-Allow-Credentials,true)"
+ var client = new XMLHttpRequest();
+ client.open("GET", url + sharedHeaders + headers);
+ client.withCredentials = true;
+ client.send();
+ client._onreadystatechange_ = this.step_func(function () {
+ if (this.readyState == this.HEADERS_RECEIVED) {
+ assert_equals(client.getResponseHeader("content-type"), "text/plain"); // safelisted
+ assert_equals(client.getResponseHeader("test"), null);
+ assert_equals(client.getResponseHeader("set-cookie"), null);
+ assert_equals(client.getResponseHeader("*"), "whoa");
+ this.done();
+ }
+ });
+}, "* for credentialed fetches only matches literally")
+
+async_test(function() {
+ const headers = "header(Access-Control-Allow-Origin,*)|header(Access-Control-Expose-Headers,set-cookie\\,*)"
+ var client = new XMLHttpRequest();
+ client.open("GET", url + sharedHeaders + headers);
+ client.send();
+ client._onreadystatechange_ = this.step_func(function () {
+ if (this.readyState == this.HEADERS_RECEIVED) {
+ assert_equals(client.getResponseHeader("test"), "X");
+ assert_equals(client.getResponseHeader("set-cookie"), null);
+ assert_equals(client.getResponseHeader("*"), "whoa");
+ this.done();
+ }
+ });
+}, "* can be one of several values")
Added: trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/resources/top.txt (0 => 258330)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/resources/top.txt (rev 0)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/xhr/resources/top.txt 2020-03-12 15:38:01 UTC (rev 258330)
@@ -0,0 +1 @@
+top
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (258329 => 258330)
--- trunk/Source/WebCore/ChangeLog 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/Source/WebCore/ChangeLog 2020-03-12 15:38:01 UTC (rev 258330)
@@ -1,3 +1,30 @@
+2020-03-12 Rob Buis <[email protected]>
+
+ Implement wildcard behavior for Cross-Origin-Expose-Headers
+ https://bugs.webkit.org/show_bug.cgi?id=208800
+
+ Reviewed by Youenn Fablet.
+
+ Implement wildcard behavior for Cross-Origin-Expose-Headers [1] while also
+ checking for credentials mode.
+
+ Test: imported/w3c/web-platform-tests/xhr/cors-expose-star.sub.any.html
+
+ [1] https://fetch.spec.whatwg.org/#ref-for-concept-response-cors-exposed-header-name-list%E2%91%A2
+
+ * Modules/fetch/FetchResponse.cpp:
+ (WebCore::FetchResponse::create):
+ (WebCore::FetchResponse::BodyLoader::didReceiveResponse):
+ (WebCore::FetchResponse::BodyLoader::start):
+ * Modules/fetch/FetchResponse.h:
+ * loader/DocumentThreadableLoader.cpp:
+ (WebCore::DocumentThreadableLoader::didReceiveResponse):
+ (WebCore::DocumentThreadableLoader::didFinishLoading):
+ * platform/network/ResourceResponseBase.cpp:
+ (WebCore::ResourceResponseBase::filter):
+ (WebCore::ResourceResponseBase::sanitizeHTTPHeaderFieldsAccordingToTainting):
+ * platform/network/ResourceResponseBase.h:
+
2020-03-12 youenn fablet <[email protected]>
Remove no longer used code in LibWebRTCMediaEndpoint to handle remote streams
Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp (258329 => 258330)
--- trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp 2020-03-12 15:38:01 UTC (rev 258330)
@@ -56,7 +56,7 @@
auto fetchResponse = adoptRef(*new FetchResponse(context, WTFMove(body), WTFMove(headers), WTFMove(response)));
fetchResponse->updateContentType();
if (!isSynthetic)
- fetchResponse->m_filteredResponse = ResourceResponseBase::filter(fetchResponse->m_internalResponse);
+ fetchResponse->m_filteredResponse = ResourceResponseBase::filter(fetchResponse->m_internalResponse, ResourceResponse::PerformExposeAllHeadersCheck::Yes);
if (isOpaque)
fetchResponse->setBodyAsOpaque();
return fetchResponse;
@@ -331,7 +331,8 @@
static uint64_t nextOpaqueLoadIdentifier { 0 };
void FetchResponse::BodyLoader::didReceiveResponse(const ResourceResponse& resourceResponse)
{
- m_response.m_filteredResponse = ResourceResponseBase::filter(resourceResponse);
+ auto performCheck = m_credentials == FetchOptions::Credentials::Include ? ResourceResponse::PerformExposeAllHeadersCheck::No : ResourceResponse::PerformExposeAllHeadersCheck::Yes;
+ m_response.m_filteredResponse = ResourceResponseBase::filter(resourceResponse, performCheck);
m_response.m_internalResponse = resourceResponse;
m_response.m_internalResponse.setType(m_response.m_filteredResponse->type());
if (resourceResponse.tainting() == ResourceResponse::Tainting::Opaque) {
@@ -385,6 +386,7 @@
bool FetchResponse::BodyLoader::start(ScriptExecutionContext& context, const FetchRequest& request)
{
+ m_credentials = request.fetchOptions().credentials;
m_loader = makeUnique<FetchLoader>(*this, &m_response.m_body->consumer());
m_loader->start(context, request);
return m_loader->isStarted();
Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.h (258329 => 258330)
--- trunk/Source/WebCore/Modules/fetch/FetchResponse.h 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.h 2020-03-12 15:38:01 UTC (rev 258330)
@@ -155,6 +155,7 @@
ConsumeDataByChunkCallback m_consumeDataCallback;
std::unique_ptr<FetchLoader> m_loader;
Ref<PendingActivity<FetchResponse>> m_pendingActivity;
+ FetchOptions::Credentials m_credentials;
};
mutable Optional<ResourceResponse> m_filteredResponse;
Modified: trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp (258329 => 258330)
--- trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/Source/WebCore/loader/DocumentThreadableLoader.cpp 2020-03-12 15:38:01 UTC (rev 258330)
@@ -393,7 +393,7 @@
}
if (response.type() == ResourceResponse::Type::Default) {
- m_client->didReceiveResponse(identifier, ResourceResponseBase::filter(response));
+ m_client->didReceiveResponse(identifier, ResourceResponse::filter(response, m_options.credentials == FetchOptions::Credentials::Include ? ResourceResponse::PerformExposeAllHeadersCheck::No : ResourceResponse::PerformExposeAllHeadersCheck::Yes));
if (response.tainting() == ResourceResponse::Tainting::Opaque) {
clearResource();
if (m_client)
@@ -466,7 +466,7 @@
} else {
ASSERT(response.type() == ResourceResponse::Type::Default);
- m_client->didReceiveResponse(identifier, ResourceResponseBase::filter(response));
+ m_client->didReceiveResponse(identifier, ResourceResponse::filter(response, m_options.credentials == FetchOptions::Credentials::Include ? ResourceResponse::PerformExposeAllHeadersCheck::No : ResourceResponse::PerformExposeAllHeadersCheck::Yes));
if (m_resource->resourceBuffer())
m_client->didReceiveData(m_resource->resourceBuffer()->data(), m_resource->resourceBuffer()->size());
}
Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp (258329 => 258330)
--- trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp 2020-03-12 15:38:01 UTC (rev 258330)
@@ -148,7 +148,7 @@
return redirectResponse;
}
-ResourceResponse ResourceResponseBase::filter(const ResourceResponse& response)
+ResourceResponse ResourceResponseBase::filter(const ResourceResponse& response, PerformExposeAllHeadersCheck performCheck)
{
if (response.tainting() == Tainting::Opaque) {
ResourceResponse opaqueResponse;
@@ -169,10 +169,11 @@
// Let's initialize filteredResponse to remove some header fields.
filteredResponse.lazyInit(AllFields);
+ filteredResponse.m_httpHeaderFields.remove(HTTPHeaderName::SetCookie);
+ filteredResponse.m_httpHeaderFields.remove(HTTPHeaderName::SetCookie2);
+
if (response.tainting() == Tainting::Basic) {
filteredResponse.setType(Type::Basic);
- filteredResponse.m_httpHeaderFields.remove(HTTPHeaderName::SetCookie);
- filteredResponse.m_httpHeaderFields.remove(HTTPHeaderName::SetCookie2);
return filteredResponse;
}
@@ -180,6 +181,9 @@
filteredResponse.setType(Type::Cors);
auto accessControlExposeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(response.httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders));
+ if (performCheck == PerformExposeAllHeadersCheck::Yes && accessControlExposeHeaderSet.contains("*"))
+ return filteredResponse;
+
filteredResponse.m_httpHeaderFields.uncommonHeaders().removeAllMatching([&](auto& entry) {
return !isCrossOriginSafeHeader(entry.key, accessControlExposeHeaderSet);
});
@@ -443,12 +447,15 @@
case ResourceResponse::Tainting::Basic:
return;
case ResourceResponse::Tainting::Cors: {
+ auto corsSafeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders));
+ if (corsSafeHeaderSet.contains("*"))
+ return;
+
HTTPHeaderMap filteredHeaders;
for (auto& header : m_httpHeaderFields.commonHeaders()) {
if (isSafeCrossOriginResponseHeader(header.key))
filteredHeaders.add(header.key, WTFMove(header.value));
}
- auto corsSafeHeaderSet = parseAccessControlAllowList<ASCIICaseInsensitiveHash>(httpHeaderField(HTTPHeaderName::AccessControlExposeHeaders));
for (auto& headerName : corsSafeHeaderSet) {
if (!filteredHeaders.contains(headerName)) {
auto value = m_httpHeaderFields.get(headerName);
Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.h (258329 => 258330)
--- trunk/Source/WebCore/platform/network/ResourceResponseBase.h 2020-03-12 15:36:33 UTC (rev 258329)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.h 2020-03-12 15:38:01 UTC (rev 258330)
@@ -193,7 +193,8 @@
void setTainting(Tainting tainting) { m_tainting = tainting; }
Tainting tainting() const { return m_tainting; }
- static ResourceResponse filter(const ResourceResponse&);
+ enum class PerformExposeAllHeadersCheck : uint8_t { Yes, No };
+ static ResourceResponse filter(const ResourceResponse&, PerformExposeAllHeadersCheck);
WEBCORE_EXPORT static ResourceResponse syntheticRedirectResponse(const URL& fromURL, const URL& toURL);