From 4845de63360d67423233b07b247fc058239acf9f Mon Sep 17 00:00:00 2001 From: Matt Falkenhagen Date: Tue, 23 Jan 2018 19:53:06 -0800 Subject: [PATCH] S13nServiceWorker: Support network fallback with blob request body. For subresource requests only. This makes a clone of the request body before passing it to the service worker in ServiceWorkerSubresourceLoader. This way if the service worker does network fallback, the request can be passed to network with the request body intact. Change-Id: I00c1861449e997a50c417336961a7c8c62bc710e Bug: 778878 Reviewed-on: https://chromium-review.googlesource.com/867817 Commit-Queue: Matt Falkenhagen Reviewed-by: Kinuko Yasuda Cr-Commit-Position: refs/heads/master@{#531414} --- .../service-worker/fetch-event.https.html | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/service-workers/service-worker/fetch-event.https.html b/service-workers/service-worker/fetch-event.https.html index 240219b082dc7f..a960a8010012ed 100644 --- a/service-workers/service-worker/fetch-event.https.html +++ b/service-workers/service-worker/fetch-event.https.html @@ -456,6 +456,43 @@ }); }, 'FetchEvent#body is a string'); +// Test that the request body is sent to network upon network fallback, +// for a string body. +promise_test(t => { + // Set scope to "?ignore" so the service worker falls back to network + // for the main resource request, and add a suffix to avoid colliding + // with other tests. + const scope = 'resources/?ignore-for-request-body-fallback-string'; + let frame; + + return service_worker_unregister_and_register(t, worker, scope) + .then(reg => { + add_completion_callback(() => { reg.unregister(); }); + return wait_for_state(t, reg.installing, 'activated'); + }) + .then(() => { + return with_iframe(scope); }) + .then(f => { + frame = f; + // Add "?ignore" so the service worker falls back to echo-content.py. + const echo_url = '/fetch/api/resources/echo-content.py?ignore'; + return frame.contentWindow.fetch(echo_url, { + method: 'POST', + body: 'i am the request body' + }); + }) + .then(response => { + return response.text(); + }) + .then(response_text => { + frame.remove(); + assert_equals( + response_text, + 'i am the request body', + 'the network fallback request should include the request body'); + }); + }, 'FetchEvent#body is a string and is passed to network fallback'); + // Test that the service worker can read FetchEvent#body when it is a blob. // It responds with request body it read. promise_test(t => { @@ -489,6 +526,44 @@ }); }, 'FetchEvent#body is a blob'); +// Test that the request body is sent to network upon network fallback, +// for a blob body. +promise_test(t => { + // Set scope to "?ignore" so the service worker falls back to network + // for the main resource request, and add a suffix to avoid colliding + // with other tests. + const scope = 'resources/simple.html?ignore-for-request-body-fallback-blob'; + let frame; + + return service_worker_unregister_and_register(t, worker, scope) + .then(reg => { + add_completion_callback(() => { reg.unregister(); }); + return wait_for_state(t, reg.installing, 'activated'); + }) + .then(() => { + return with_iframe(scope); }) + .then(f => { + frame = f; + const blob = new Blob(['it\'s me the blob', ' ', 'and more blob!']); + // Add "?ignore" so the service worker falls back to echo-content.py. + const echo_url = '/fetch/api/resources/echo-content.py?ignore'; + return frame.contentWindow.fetch(echo_url, { + method: 'POST', + body: blob + }); + }) + .then(response => { + return response.text(); + }) + .then(response_text => { + frame.remove(); + assert_equals( + response_text, + 'it\'s me the blob and more blob!', + 'the network fallback request should include the request body'); + }); + }, 'FetchEvent#body is a blob and is passed to network fallback'); + promise_test(async (t) => { const scope = 'resources/simple.html?keepalive';