Title: [227339] trunk
Revision
227339
Author
commit-qu...@webkit.org
Date
2018-01-22 10:33:30 -0800 (Mon, 22 Jan 2018)

Log Message

Fetch Headers from an Opaque response should be filtered out
https://bugs.webkit.org/show_bug.cgi?id=181926

Patch by Youenn Fablet <you...@apple.com> on 2018-01-22
Reviewed by Chris Dumez.

Source/WebCore:

Covered by updated test.

Refactor to use the same FetchResponse::create for Cache API and cloning.
In this method, ensure that response and headers are filtered correctly according response tainting.
Make also sure that synthetic responses do not get filtered (not needed since created by _javascript_).

Introduce helper routine to set the header map of a resource response.
Use this routine when cloning a synthetic response as in that case, m_internalResponse has no header at all.

* Modules/cache/DOMCache.cpp:
(WebCore::DOMCache::updateRecords):
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::create):
(WebCore::FetchResponse::clone):
* Modules/fetch/FetchResponse.h:
* platform/network/ResourceResponseBase.cpp:
(WebCore::ResourceResponseBase::setHTTPHeaderFields):
* platform/network/ResourceResponseBase.h:
* testing/ServiceWorkerInternals.cpp:
(WebCore::ServiceWorkerInternals::createOpaqueWithBlobBodyResponse):

LayoutTests:

* http/wpt/fetch/response-opaque-clone-expected.txt:
* http/wpt/fetch/response-opaque-clone.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (227338 => 227339)


--- trunk/LayoutTests/ChangeLog	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/LayoutTests/ChangeLog	2018-01-22 18:33:30 UTC (rev 227339)
@@ -1,3 +1,13 @@
+2018-01-22  Youenn Fablet  <you...@apple.com>
+
+        Fetch Headers from an Opaque response should be filtered out
+        https://bugs.webkit.org/show_bug.cgi?id=181926
+
+        Reviewed by Chris Dumez.
+
+        * http/wpt/fetch/response-opaque-clone-expected.txt:
+        * http/wpt/fetch/response-opaque-clone.html:
+
 2018-01-22  Andy Estes  <aes...@apple.com>
 
         LayoutTest http/tests/paymentrequest/payment-request-abort-method.https.html is a flaky failure

Modified: trunk/LayoutTests/http/wpt/fetch/response-opaque-clone-expected.txt (227338 => 227339)


--- trunk/LayoutTests/http/wpt/fetch/response-opaque-clone-expected.txt	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/LayoutTests/http/wpt/fetch/response-opaque-clone-expected.txt	2018-01-22 18:33:30 UTC (rev 227339)
@@ -1,3 +1,3 @@
 
-PASS Check opaque response can be cloned 
+PASS Check opaque response can be cloned and cached correctly 
 

Modified: trunk/LayoutTests/http/wpt/fetch/response-opaque-clone.html (227338 => 227339)


--- trunk/LayoutTests/http/wpt/fetch/response-opaque-clone.html	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/LayoutTests/http/wpt/fetch/response-opaque-clone.html	2018-01-22 18:33:30 UTC (rev 227339)
@@ -10,16 +10,42 @@
   <body>
     <script src=""
     <script>
-promise_test(function(test) {
-    return fetch(get_host_info().HTTP_REMOTE_ORIGIN, { mode: "no-cors" }).then((response) => {
-        var clone = response.clone();
-        assert_equals(response.body, null, "opaque response body should be null");
-        assert_equals(clone.body, null, "clone body should be null");
-        return clone.arrayBuffer();
-    }).then((buffer) => {
-        assert_equals(buffer.byteLength, 0, "cloned opaque response buffer should be null");
-    });
-}, "Check opaque response can be cloned");
+
+function testResponseOpacity(response, test, testName)
+{
+    assert_equals(response.type, "opaque", testName + " type");
+    assert_equals(response.status, 0, testName + " status");
+    assert_equals(response.statusText, "", testName + " statusText");
+    assert_false(response.redirected, testName + " redirected");
+    assert_true(response.headers.values().next().done, testName + " headers");
+    assert_equals(response.body, null, testName + " opaque response body should be null");
+}
+promise_test(async function(test) {
+    var request = new Request(get_host_info().HTTP_REMOTE_ORIGIN, { mode: "no-cors" });
+    var response = await fetch(request);
+
+    testResponseOpacity(response, test, "fetched response");
+
+    var clone = response.clone();
+
+    testResponseOpacity(clone, test, "cloned response");
+    var buffer = await clone.arrayBuffer();
+    assert_equals(buffer.byteLength, 0, "cloned opaque response buffer should be null");
+
+    // WK1 does not support Cache API yet.
+    if (!self.caches)
+        return;
+
+    var cache = await self.caches.open("test");
+    await cache.put(request, response);
+    var cached = await cache.match(request.url);
+
+    testResponseOpacity(cached, test,  "cached response")
+    buffer = await cached.arrayBuffer();
+    assert_equals(buffer.byteLength, 0, "cached opaque response buffer should be null");
+
+    await self.caches.delete("test");
+}, "Check opaque response can be cloned and cached correctly");
     </script>
   </body>
 </html>

Modified: trunk/Source/WebCore/ChangeLog (227338 => 227339)


--- trunk/Source/WebCore/ChangeLog	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/ChangeLog	2018-01-22 18:33:30 UTC (rev 227339)
@@ -1,3 +1,31 @@
+2018-01-22  Youenn Fablet  <you...@apple.com>
+
+        Fetch Headers from an Opaque response should be filtered out
+        https://bugs.webkit.org/show_bug.cgi?id=181926
+
+        Reviewed by Chris Dumez.
+
+        Covered by updated test.
+
+        Refactor to use the same FetchResponse::create for Cache API and cloning.
+        In this method, ensure that response and headers are filtered correctly according response tainting.
+        Make also sure that synthetic responses do not get filtered (not needed since created by _javascript_).
+
+        Introduce helper routine to set the header map of a resource response.
+        Use this routine when cloning a synthetic response as in that case, m_internalResponse has no header at all.
+
+        * Modules/cache/DOMCache.cpp:
+        (WebCore::DOMCache::updateRecords):
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::create):
+        (WebCore::FetchResponse::clone):
+        * Modules/fetch/FetchResponse.h:
+        * platform/network/ResourceResponseBase.cpp:
+        (WebCore::ResourceResponseBase::setHTTPHeaderFields):
+        * platform/network/ResourceResponseBase.h:
+        * testing/ServiceWorkerInternals.cpp:
+        (WebCore::ServiceWorkerInternals::createOpaqueWithBlobBodyResponse):
+
 2018-01-22  Javier Fernandez  <jfernan...@igalia.com>
 
         [css-align] 'overflow' keyword must precede the self-position and content-position value

Modified: trunk/Source/WebCore/Modules/cache/DOMCache.cpp (227338 => 227339)


--- trunk/Source/WebCore/Modules/cache/DOMCache.cpp	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/Modules/cache/DOMCache.cpp	2018-01-22 18:33:30 UTC (rev 227339)
@@ -531,8 +531,7 @@
         if (index != notFound) {
             auto& current = m_records[index];
             if (current.updateResponseCounter != record.updateResponseCounter) {
-                auto responseHeaders = FetchHeaders::create(record.responseHeadersGuard, HTTPHeaderMap { record.response.httpHeaderFields() });
-                auto response = FetchResponse::create(*scriptExecutionContext(), std::nullopt, WTFMove(responseHeaders), WTFMove(record.response));
+                auto response = FetchResponse::create(*scriptExecutionContext(), std::nullopt, record.responseHeadersGuard, WTFMove(record.response));
                 response->setBodyData(WTFMove(record.responseBody), record.responseBodySize);
 
                 current.response = WTFMove(response);
@@ -543,8 +542,7 @@
             auto requestHeaders = FetchHeaders::create(record.requestHeadersGuard, HTTPHeaderMap { record.request.httpHeaderFields() });
             auto request = FetchRequest::create(*scriptExecutionContext(), std::nullopt, WTFMove(requestHeaders),  WTFMove(record.request), WTFMove(record.options), WTFMove(record.referrer));
 
-            auto responseHeaders = FetchHeaders::create(record.responseHeadersGuard, HTTPHeaderMap { record.response.httpHeaderFields() });
-            auto response = FetchResponse::create(*scriptExecutionContext(), std::nullopt, WTFMove(responseHeaders), WTFMove(record.response));
+            auto response = FetchResponse::create(*scriptExecutionContext(), std::nullopt, record.responseHeadersGuard, WTFMove(record.response));
             response->setBodyData(WTFMove(record.responseBody), record.responseBodySize);
 
             newRecords.append(CacheStorageRecord { record.identifier, record.updateResponseCounter, WTFMove(request), WTFMove(response) });

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp (227338 => 227339)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.cpp	2018-01-22 18:33:30 UTC (rev 227339)
@@ -44,10 +44,17 @@
     return status == 101 || status == 204 || status == 205 || status == 304;
 }
 
-Ref<FetchResponse> FetchResponse::create(ScriptExecutionContext& context, std::optional<FetchBody>&& body, Ref<FetchHeaders>&& headers, ResourceResponse&& response)
+Ref<FetchResponse> FetchResponse::create(ScriptExecutionContext& context, std::optional<FetchBody>&& body, FetchHeaders::Guard guard, ResourceResponse&& response)
 {
+    bool isSynthetic = response.type() == ResourceResponse::Type::Default || response.type() == ResourceResponse::Type::Error;
+    bool isOpaque = response.tainting() == ResourceResponse::Tainting::Opaque;
+    auto headers = isOpaque ? FetchHeaders::create(guard) : FetchHeaders::create(guard, HTTPHeaderMap { response.httpHeaderFields() });
+
     auto fetchResponse = adoptRef(*new FetchResponse(context, WTFMove(body), WTFMove(headers), WTFMove(response)));
-    fetchResponse->m_filteredResponse = ResourceResponseBase::filter(fetchResponse->m_internalResponse);
+    if (!isSynthetic)
+        fetchResponse->m_filteredResponse = ResourceResponseBase::filter(fetchResponse->m_internalResponse);
+    if (isOpaque)
+        fetchResponse->setBodyAsOpaque();
     return fetchResponse;
 }
 
@@ -163,10 +170,12 @@
     if (isLoading())
         readableStream(*context.execState());
 
-    auto clone = adoptRef(*new FetchResponse(context, std::nullopt, FetchHeaders::create(headers()), ResourceResponse(m_internalResponse)));
+    // Synthetic responses do not store headers in m_internalResponse.
+    if (m_internalResponse.type() == ResourceResponse::Type::Default)
+        m_internalResponse.setHTTPHeaderFields(HTTPHeaderMap { headers().internalHeaders() });
+
+    auto clone = FetchResponse::create(context, std::nullopt, headers().guard(), ResourceResponse { m_internalResponse });
     clone->cloneBody(*this);
-    if (isBodyOpaque())
-        clone->setBodyAsOpaque();
     clone->m_opaqueLoadIdentifier = m_opaqueLoadIdentifier;
     clone->m_bodySizeWithPadding = m_bodySizeWithPadding;
     return WTFMove(clone);

Modified: trunk/Source/WebCore/Modules/fetch/FetchResponse.h (227338 => 227339)


--- trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/Modules/fetch/FetchResponse.h	2018-01-22 18:33:30 UTC (rev 227339)
@@ -53,7 +53,7 @@
         std::optional<FetchHeaders::Init> headers;
     };
 
-    WEBCORE_EXPORT static Ref<FetchResponse> create(ScriptExecutionContext&, std::optional<FetchBody>&&, Ref<FetchHeaders>&&, ResourceResponse&&);
+    WEBCORE_EXPORT static Ref<FetchResponse> create(ScriptExecutionContext&, std::optional<FetchBody>&&, FetchHeaders::Guard, ResourceResponse&&);
 
     static ExceptionOr<Ref<FetchResponse>> create(ScriptExecutionContext&, std::optional<FetchBody::Init>&&, Init&&);
     static Ref<FetchResponse> error(ScriptExecutionContext&);

Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp (227338 => 227339)


--- trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.cpp	2018-01-22 18:33:30 UTC (rev 227339)
@@ -399,6 +399,13 @@
     // FIXME: Should invalidate or update platform response if present.
 }
 
+void ResourceResponseBase::setHTTPHeaderFields(HTTPHeaderMap&& headerFields)
+{
+    lazyInit(AllFields);
+
+    m_httpHeaderFields = WTFMove(headerFields);
+}
+
 void ResourceResponseBase::setHTTPHeaderField(HTTPHeaderName name, const String& value)
 {
     lazyInit(AllFields);

Modified: trunk/Source/WebCore/platform/network/ResourceResponseBase.h (227338 => 227339)


--- trunk/Source/WebCore/platform/network/ResourceResponseBase.h	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/platform/network/ResourceResponseBase.h	2018-01-22 18:33:30 UTC (rev 227339)
@@ -101,6 +101,7 @@
     WEBCORE_EXPORT bool isHTTP09() const;
 
     WEBCORE_EXPORT const HTTPHeaderMap& httpHeaderFields() const;
+    void setHTTPHeaderFields(HTTPHeaderMap&&);
 
     String httpHeaderField(const String& name) const;
     WEBCORE_EXPORT String httpHeaderField(HTTPHeaderName) const;

Modified: trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp (227338 => 227339)


--- trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp	2018-01-22 18:24:15 UTC (rev 227338)
+++ trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp	2018-01-22 18:33:30 UTC (rev 227339)
@@ -75,7 +75,7 @@
     ResourceResponse response;
     response.setType(ResourceResponse::Type::Cors);
     response.setTainting(ResourceResponse::Tainting::Opaque);
-    auto fetchResponse = FetchResponse::create(context, FetchBody::fromFormData(formData), FetchHeaders::create(), WTFMove(response));
+    auto fetchResponse = FetchResponse::create(context, FetchBody::fromFormData(formData), FetchHeaders::Guard::Response, WTFMove(response));
     fetchResponse->initializeOpaqueLoadIdentifierForTesting();
     return fetchResponse;
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to