Opaque being-loaded responses should clone their body
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jan 2018 23:23:18 +0000 (23:23 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 24 Jan 2018 23:23:18 +0000 (23:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=182056

Patch by Youenn Fablet <youenn@apple.com> on 2018-01-24
Reviewed by Brady Eidson.

Source/WebCore:

Test: http/wpt/service-workers/clone-opaque-being-loaded-response.https.html

When cloning a being-loaded response, make sure we create a ReadableStream.
Before the patch, the readableStream was not created in that case for opaque responses.

* Modules/fetch/FetchBodyOwner.cpp:
(WebCore::FetchBodyOwner::readableStream):
(WebCore::FetchBodyOwner::createReadableStream):
* Modules/fetch/FetchBodyOwner.h:
* Modules/fetch/FetchResponse.cpp:
(WebCore::FetchResponse::clone):

LayoutTests:

* http/wpt/service-workers/clone-opaque-being-loaded-response-worker.js: Added.
* http/wpt/service-workers/clone-opaque-being-loaded-response.html: Added.
* http/wpt/service-workers/clone-opaque-being-loaded-response.https-expected.txt: Added.
* http/wpt/service-workers/resources/clone-opaque-being-loaded-response-iframe.html: Added.
* http/wpt/service-workers/resources/lengthy-pass.py: Added.
(main):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@227581 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response-worker.js [new file with mode: 0644]
LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response.https-expected.txt [new file with mode: 0644]
LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response.https.html [new file with mode: 0644]
LayoutTests/http/wpt/service-workers/resources/clone-opaque-being-loaded-response-iframe.html [new file with mode: 0644]
LayoutTests/http/wpt/service-workers/resources/lengthy-pass.py [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/fetch/FetchBodyOwner.cpp
Source/WebCore/Modules/fetch/FetchBodyOwner.h
Source/WebCore/Modules/fetch/FetchResponse.cpp

index 67c24798147e0369704224f84113d11e02117398..dea740738cdb1735f11e2901c12cb572a931d49d 100644 (file)
@@ -1,3 +1,17 @@
+2018-01-24  Youenn Fablet  <youenn@apple.com>
+
+        Opaque being-loaded responses should clone their body
+        https://bugs.webkit.org/show_bug.cgi?id=182056
+
+        Reviewed by Brady Eidson.
+
+        * http/wpt/service-workers/clone-opaque-being-loaded-response-worker.js: Added.
+        * http/wpt/service-workers/clone-opaque-being-loaded-response.html: Added.
+        * http/wpt/service-workers/clone-opaque-being-loaded-response.https-expected.txt: Added.
+        * http/wpt/service-workers/resources/clone-opaque-being-loaded-response-iframe.html: Added.
+        * http/wpt/service-workers/resources/lengthy-pass.py: Added.
+        (main):
+
 2018-01-24  David Hyatt  <hyatt@apple.com>
 
         Implement line clamp for mail.
diff --git a/LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response-worker.js b/LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response-worker.js
new file mode 100644 (file)
index 0000000..7d50471
--- /dev/null
@@ -0,0 +1,8 @@
+importScripts('/common/get-host-info.sub.js');
+
+var remoteUrl = get_host_info()['HTTPS_REMOTE_ORIGIN'] + '/WebKit/service-workers/resources/lengthy-pass.py';
+
+self.addEventListener('fetch', (event) => {
+    if (event.request.url.indexOf("html") === -1)
+        event.respondWith(fetch(remoteUrl, {mode: 'no-cors'}).then(response => response.clone()));
+});
diff --git a/LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response.https-expected.txt b/LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response.https-expected.txt
new file mode 100644 (file)
index 0000000..0da5ae8
--- /dev/null
@@ -0,0 +1,4 @@
+
+PASS Setup worker 
+PASS Ensure opaque response fetch is working 
+
diff --git a/LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response.https.html b/LayoutTests/http/wpt/service-workers/clone-opaque-being-loaded-response.https.html
new file mode 100644 (file)
index 0000000..24ae0dd
--- /dev/null
@@ -0,0 +1,36 @@
+<html>
+<head>
+<title>Service Worker returning an opaque cloned response</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
+</head>
+<body>
+<script>
+var registration;
+var iframe;
+promise_test(async (test) => {
+    registration = await navigator.serviceWorker.getRegistration("resources/");
+    if (registration)
+        await registration.unregister();
+    registration = await navigator.serviceWorker.register("clone-opaque-being-loaded-response-worker.js", { scope : "resources/" });
+    activeWorker = registration.active;
+    if (activeWorker)
+        return;
+    activeWorker = registration.installing;
+    await new Promise(resolve => {
+        activeWorker.addEventListener('statechange', () => {
+            if (activeWorker.state === "activated")
+                resolve();
+        });
+    });
+}, "Setup worker");
+
+promise_test(async (test) => {
+    iframe = await with_iframe("resources/clone-opaque-being-loaded-response-iframe.html");
+    assert_equals(iframe.contentWindow.document.body.innerHTML.trim(), "PASS");
+    iframe.remove();
+}, "Ensure opaque response fetch is working");
+</script>
+</body>
+</html>
diff --git a/LayoutTests/http/wpt/service-workers/resources/clone-opaque-being-loaded-response-iframe.html b/LayoutTests/http/wpt/service-workers/resources/clone-opaque-being-loaded-response-iframe.html
new file mode 100644 (file)
index 0000000..5c9b396
--- /dev/null
@@ -0,0 +1,6 @@
+<html>
+<body>
+FAIL: body should be replaced when executing the script.
+<script src="/WebKit/resources/lengthy-pass.py"></script>
+</body>
+</html>
diff --git a/LayoutTests/http/wpt/service-workers/resources/lengthy-pass.py b/LayoutTests/http/wpt/service-workers/resources/lengthy-pass.py
new file mode 100644 (file)
index 0000000..962a4dc
--- /dev/null
@@ -0,0 +1,15 @@
+import time
+
+def main(request, response):
+    delay = 0.05
+    response.headers.set("Content-type", "text/javascript")
+    response.write_status_headers()
+    time.sleep(delay);
+    response.writer.write_content("document")
+    time.sleep(delay)
+    response.writer.write_content(".body")
+    time.sleep(delay)
+    response.writer.write_content(".innerHTML = ")
+    time.sleep(delay)
+    response.writer.write_content("'PASS'")
+    time.sleep(delay)
index 70182e42a519c1d2d8a9e3d115fb40fa018834c0..5bde6b5b611a912c1958d372db1eed4338dbdc0c 100644 (file)
@@ -1,3 +1,22 @@
+2018-01-24  Youenn Fablet  <youenn@apple.com>
+
+        Opaque being-loaded responses should clone their body
+        https://bugs.webkit.org/show_bug.cgi?id=182056
+
+        Reviewed by Brady Eidson.
+
+        Test: http/wpt/service-workers/clone-opaque-being-loaded-response.https.html
+
+        When cloning a being-loaded response, make sure we create a ReadableStream.
+        Before the patch, the readableStream was not created in that case for opaque responses.
+
+        * Modules/fetch/FetchBodyOwner.cpp:
+        (WebCore::FetchBodyOwner::readableStream):
+        (WebCore::FetchBodyOwner::createReadableStream):
+        * Modules/fetch/FetchBodyOwner.h:
+        * Modules/fetch/FetchResponse.cpp:
+        (WebCore::FetchResponse::clone):
+
 2018-01-24  Chris Dumez  <cdumez@apple.com>
 
         close() operation should not be exposed inside a ServiceWorkerGlobalScope
index 9de02112eb963a9936367e47afe3460974fcbafd..3daf92906b346d32a9f6ae26789e7a04f4aaa6c2 100644 (file)
@@ -290,19 +290,24 @@ RefPtr<ReadableStream> FetchBodyOwner::readableStream(JSC::ExecState& state)
     if (isBodyNullOrOpaque())
         return nullptr;
 
-    if (!m_body->hasReadableStream()) {
-        ASSERT(!m_readableStreamSource);
-        if (isDisturbed()) {
-            m_body->setReadableStream(ReadableStream::create(state, nullptr));
-            m_body->readableStream()->lock();
-        } else {
-            m_readableStreamSource = adoptRef(*new FetchBodySource(*this));
-            m_body->setReadableStream(ReadableStream::create(state, m_readableStreamSource));
-        }
-    }
+    if (!m_body->hasReadableStream())
+        createReadableStream(state);
+
     return m_body->readableStream();
 }
 
+void FetchBodyOwner::createReadableStream(JSC::ExecState& state)
+{
+    ASSERT(!m_readableStreamSource);
+    if (isDisturbed()) {
+        m_body->setReadableStream(ReadableStream::create(state, nullptr));
+        m_body->readableStream()->lock();
+    } else {
+        m_readableStreamSource = adoptRef(*new FetchBodySource(*this));
+        m_body->setReadableStream(ReadableStream::create(state, m_readableStreamSource));
+    }
+}
+
 void FetchBodyOwner::consumeBodyAsStream()
 {
     ASSERT(m_readableStreamSource);
index e4b4afb4c0b28207279670369a9a2abd8c17fe96..82d5dd90734cbd00acbfbdf90f6451f47f01b5e6 100644 (file)
@@ -76,6 +76,7 @@ protected:
     void consumeOnceLoadingFinished(FetchBodyConsumer::Type, Ref<DeferredPromise>&&);
 
     void setBody(FetchBody&& body) { m_body = WTFMove(body); }
+    void createReadableStream(JSC::ExecState&);
 
     // ActiveDOMObject API
     void stop() override;
index 2415e0bff561817dbc2b0cfd96fd14133035f5ef..5a3778da6608fe6ff8d40fd8bb683168814ab295 100644 (file)
@@ -167,8 +167,8 @@ ExceptionOr<Ref<FetchResponse>> FetchResponse::clone(ScriptExecutionContext& con
     ASSERT(scriptExecutionContext());
 
     // If loading, let's create a stream so that data is teed on both clones.
-    if (isLoading())
-        readableStream(*context.execState());
+    if (isLoading() && !m_readableStreamSource)
+        createReadableStream(*context.execState());
 
     // Synthetic responses do not store headers in m_internalResponse.
     if (m_internalResponse.type() == ResourceResponse::Type::Default)