WebKit Bugzilla
Attachment 342056 Details for
Bug 186335
: Add Accept-Encoding: identity to Range requests
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-186335-20180606101550.patch (text/plain), 34.70 KB, created by
youenn fablet
on 2018-06-06 10:15:51 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
youenn fablet
Created:
2018-06-06 10:15:51 PDT
Size:
34.70 KB
patch
obsolete
>Subversion Revision: 232536 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index aa2f11dcd57355b4188b752ac9eb7ae2895e28ea..3dd3b638d017335dcded9e8a8edd15fc5ced456a 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,20 @@ >+2018-06-06 Youenn Fablet <youenn@apple.com> >+ >+ Add Accept-Encoding: identity to Range requests >+ https://bugs.webkit.org/show_bug.cgi?id=186335 >+ <rdar://problem/40837190> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Tests: imported/w3c/web-platform-tests/fetch/range/general.any.html >+ imported/w3c/web-platform-tests/fetch/range/general.any.worker.html >+ >+ * loader/cache/CachedResourceLoader.cpp: >+ (WebCore::CachedResourceLoader::updateHTTPRequestHeaders): >+ * loader/cache/CachedResourceRequest.cpp: >+ (WebCore::CachedResourceRequest::updateAcceptEncodingHeader): >+ * loader/cache/CachedResourceRequest.h: >+ > 2018-06-05 Per Arne Vollan <pvollan@apple.com> > > Move OpenGL display mask to screen data struct. >diff --git a/Source/WebCore/loader/cache/CachedResourceLoader.cpp b/Source/WebCore/loader/cache/CachedResourceLoader.cpp >index 7c2bf27e0b872a6852d43db03eb3eb11b3dc6fec..a703e5e40f2a6b78cc93bb7e37fcf21a6dbff8b1 100644 >--- a/Source/WebCore/loader/cache/CachedResourceLoader.cpp >+++ b/Source/WebCore/loader/cache/CachedResourceLoader.cpp >@@ -727,6 +727,7 @@ void CachedResourceLoader::updateHTTPRequestHeaders(CachedResource::Type type, C > } > > request.updateAccordingCacheMode(); >+ request.updateAcceptEncodingHeader(); > } > > static FetchOptions::Destination destinationForType(CachedResource::Type type) >diff --git a/Source/WebCore/loader/cache/CachedResourceRequest.cpp b/Source/WebCore/loader/cache/CachedResourceRequest.cpp >index 0012e964b30dff2429b2db33277b75cdcf409c24..496450b21b36bf5fe96dcbba11fe04e078ac648d 100644 >--- a/Source/WebCore/loader/cache/CachedResourceRequest.cpp >+++ b/Source/WebCore/loader/cache/CachedResourceRequest.cpp >@@ -206,6 +206,17 @@ void CachedResourceRequest::updateAccordingCacheMode() > } > } > >+void CachedResourceRequest::updateAcceptEncodingHeader() >+{ >+ if (!m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::Range)) >+ return; >+ >+ // FIXME: We should ask the media engine to not set this header. >+ ASSERT(!m_resourceRequest.hasHTTPHeaderField(HTTPHeaderName::AcceptEncoding) || m_options.destination == FetchOptions::Destination::Audio || m_options.destination == FetchOptions::Destination::Video); >+ >+ m_resourceRequest.addHTTPHeaderFieldIfNotPresent(HTTPHeaderName::AcceptEncoding, ASCIILiteral("identity")); >+} >+ > void CachedResourceRequest::removeFragmentIdentifierIfNeeded() > { > URL url = MemoryCache::removeFragmentIdentifierIfNeeded(m_resourceRequest.url()); >diff --git a/Source/WebCore/loader/cache/CachedResourceRequest.h b/Source/WebCore/loader/cache/CachedResourceRequest.h >index 90e96c2046ce6da8b8fe805e4702bfd2a3e14297..3a825c77af9d138d5be457dbab61d111a24d22dd 100644 >--- a/Source/WebCore/loader/cache/CachedResourceRequest.h >+++ b/Source/WebCore/loader/cache/CachedResourceRequest.h >@@ -80,6 +80,8 @@ public: > void upgradeInsecureRequestIfNeeded(Document&); > void setAcceptHeaderIfNone(CachedResource::Type); > void updateAccordingCacheMode(); >+ void updateAcceptEncodingHeader(); >+ > void removeFragmentIdentifierIfNeeded(); > #if ENABLE(CONTENT_EXTENSIONS) > void applyBlockedStatus(const ContentExtensions::BlockedStatus&, Page*); >diff --git a/LayoutTests/imported/w3c/ChangeLog b/LayoutTests/imported/w3c/ChangeLog >index 5be1710baf367d82bef81ba714574a272e49fbbc..02cefd991cccf05d612f23e8e934a9639ca4a290 100644 >--- a/LayoutTests/imported/w3c/ChangeLog >+++ b/LayoutTests/imported/w3c/ChangeLog >@@ -1,3 +1,28 @@ >+2018-06-06 Youenn Fablet <youenn@apple.com> >+ >+ Add Accept-Encoding: identity to Range requests >+ https://bugs.webkit.org/show_bug.cgi?id=186335 >+ <rdar://problem/40837190> >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * resources/import-expectations.json: >+ * web-platform-tests/fetch/range/general.any-expected.txt: Added. >+ * web-platform-tests/fetch/range/general.any.html: Added. >+ * web-platform-tests/fetch/range/general.any.js: Added. >+ * web-platform-tests/fetch/range/general.any.worker-expected.txt: Added. >+ * web-platform-tests/fetch/range/general.any.worker.html: Added. >+ * web-platform-tests/fetch/range/general.window.js: Added. >+ * web-platform-tests/fetch/range/resources/basic.html: Added. >+ * web-platform-tests/fetch/range/resources/long-wav.py: Added. >+ * web-platform-tests/fetch/range/resources/partial-script.py: Added. >+ * web-platform-tests/fetch/range/resources/range-sw.js: Added. >+ * web-platform-tests/fetch/range/resources/stash-take.py: Added. >+ * web-platform-tests/fetch/range/resources/utils.js: Added. >+ * web-platform-tests/fetch/range/resources/w3c-import.log: Added. >+ * web-platform-tests/fetch/range/sw.https.window.js: Added. >+ * web-platform-tests/fetch/range/w3c-import.log: Added. >+ > 2018-06-05 Youenn Fablet <youenn@apple.com> > > ServiceWorker registration should store any script fetched through importScripts >diff --git a/LayoutTests/imported/w3c/resources/import-expectations.json b/LayoutTests/imported/w3c/resources/import-expectations.json >index 811b989c48684a4d1ccd0a3f21b5ee10c21f210b..d771685db5321a560cc78f9b39a6bf2dd1ba6e44 100644 >--- a/LayoutTests/imported/w3c/resources/import-expectations.json >+++ b/LayoutTests/imported/w3c/resources/import-expectations.json >@@ -144,6 +144,8 @@ > "web-platform-tests/feature-policy/resources": "import", > "web-platform-tests/feature-policy/resources/": "import", > "web-platform-tests/fetch": "import", >+ "web-platform-tests/fetch/api": "import", >+ "web-platform-tests/fetch/range": "import", > "web-platform-tests/fullscreen": "skip", > "web-platform-tests/gamepad": "skip", > "web-platform-tests/generic-sensor": "skip", >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..f6a9f387d6b529f8ce730e534ed2021495e09703 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any-expected.txt >@@ -0,0 +1,7 @@ >+ >+PASS Range header setting allowed for guard type: none >+PASS Range header setting allowed for guard type: response >+PASS Range header setting allowed for guard type: request >+PASS Privileged header not allowed for guard type: request-no-cors >+PASS Fetch with range header will be sent with Accept-Encoding: identity >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.html b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.html >new file mode 100644 >index 0000000000000000000000000000000000000000..2382913528e693b3a5d56c660a45060980b548c3 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.html >@@ -0,0 +1 @@ >+<!-- This file is required for WebKit test infrastructure to run the templated test --> >\ No newline at end of file >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js >new file mode 100644 >index 0000000000000000000000000000000000000000..656ac1ceea2511d960cdb21b25a2846eb092b8c4 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js >@@ -0,0 +1,90 @@ >+// META: script=/common/utils.js >+ >+// Helpers that return headers objects with a particular guard >+function headersGuardNone(fill) { >+ if (fill) return new Headers(fill); >+ return new Headers(); >+} >+ >+function headersGuardResponse(fill) { >+ const opts = {}; >+ if (fill) opts.headers = fill; >+ return new Response('', opts).headers; >+} >+ >+function headersGuardRequest(fill) { >+ const opts = {}; >+ if (fill) opts.headers = fill; >+ return new Request('./', opts).headers; >+} >+ >+function headersGuardRequestNoCors(fill) { >+ const opts = { mode: 'no-cors' }; >+ if (fill) opts.headers = fill; >+ return new Request('./', opts).headers; >+} >+ >+const headerGuardTypes = [ >+ ['none', headersGuardNone], >+ ['response', headersGuardResponse], >+ ['request', headersGuardRequest] >+]; >+ >+for (const [guardType, createHeaders] of headerGuardTypes) { >+ test(() => { >+ // There are three ways to set headers. >+ // Filling, appending, and setting. Test each: >+ let headers = createHeaders({ Range: 'foo' }); >+ assert_equals(headers.get('Range'), 'foo'); >+ >+ headers = createHeaders(); >+ headers.append('Range', 'foo'); >+ assert_equals(headers.get('Range'), 'foo'); >+ >+ headers = createHeaders(); >+ headers.set('Range', 'foo'); >+ assert_equals(headers.get('Range'), 'foo'); >+ }, `Range header setting allowed for guard type: ${guardType}`); >+} >+ >+test(() => { >+ let headers = headersGuardRequestNoCors({ Range: 'foo' }); >+ assert_false(headers.has('Range')); >+ >+ headers = headersGuardRequestNoCors(); >+ headers.append('Range', 'foo'); >+ assert_false(headers.has('Range')); >+ >+ headers = headersGuardRequestNoCors(); >+ headers.set('Range', 'foo'); >+ assert_false(headers.has('Range')); >+}, `Privileged header not allowed for guard type: request-no-cors`); >+ >+promise_test(async () => { >+ const wavURL = new URL('resources/long-wav.py', location); >+ const stashTakeURL = new URL('resources/stash-take.py', location); >+ >+ function changeToken() { >+ const stashToken = token(); >+ wavURL.searchParams.set('accept-encoding-key', stashToken); >+ stashTakeURL.searchParams.set('key', stashToken); >+ } >+ >+ const rangeHeaders = [ >+ 'bytes=0-10', >+ 'foo=0-10', >+ 'foo', >+ '' >+ ]; >+ >+ for (const rangeHeader of rangeHeaders) { >+ changeToken(); >+ >+ await fetch(wavURL, { >+ headers: { Range: rangeHeader } >+ }); >+ >+ const response = await fetch(stashTakeURL); >+ assert_equals(await response.json(), 'identity', `Expect identity accept-encoding if range header is ${JSON.stringify(rangeHeader)}`); >+ } >+}, `Fetch with range header will be sent with Accept-Encoding: identity`); >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..f6a9f387d6b529f8ce730e534ed2021495e09703 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker-expected.txt >@@ -0,0 +1,7 @@ >+ >+PASS Range header setting allowed for guard type: none >+PASS Range header setting allowed for guard type: response >+PASS Range header setting allowed for guard type: request >+PASS Privileged header not allowed for guard type: request-no-cors >+PASS Fetch with range header will be sent with Accept-Encoding: identity >+ >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker.html b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker.html >new file mode 100644 >index 0000000000000000000000000000000000000000..2382913528e693b3a5d56c660a45060980b548c3 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.worker.html >@@ -0,0 +1 @@ >+<!-- This file is required for WebKit test infrastructure to run the templated test --> >\ No newline at end of file >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.window.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.window.js >new file mode 100644 >index 0000000000000000000000000000000000000000..afe80d63a6b263f684c01284b867c13a22236a8f >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.window.js >@@ -0,0 +1,29 @@ >+// META: script=resources/utils.js >+// META: script=/common/utils.js >+ >+const onload = new Promise(r => window.addEventListener('load', r)); >+ >+// It's weird that browsers do this, but it should continue to work. >+promise_test(async t => { >+ await loadScript('resources/partial-script.py?pretend-offset=90000'); >+ assert_true(self.scriptExecuted); >+}, `Script executed from partial response`); >+ >+promise_test(async () => { >+ const wavURL = new URL('resources/long-wav.py', location); >+ const stashTakeURL = new URL('resources/stash-take.py', location); >+ const stashToken = token(); >+ wavURL.searchParams.set('accept-encoding-key', stashToken); >+ stashTakeURL.searchParams.set('key', stashToken); >+ >+ // The testing framework waits for window onload. If the audio element >+ // is appended before onload, it extends it, and the test times out. >+ await onload; >+ >+ const audio = appendAudio(document, wavURL); >+ await new Promise(r => audio.addEventListener('progress', r)); >+ audio.remove(); >+ >+ const response = await fetch(stashTakeURL); >+ assert_equals(await response.json(), 'identity', `Expect identity accept-encoding on media request`); >+}, `Fetch with range header will be sent with Accept-Encoding: identity`); >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/basic.html b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/basic.html >new file mode 100644 >index 0000000000000000000000000000000000000000..0e76edd65b7baf5316fc9d0c4da59a3502e4c27a >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/basic.html >@@ -0,0 +1 @@ >+<!DOCTYPE html> >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py >new file mode 100644 >index 0000000000000000000000000000000000000000..5df28eb741e670046176777955c5bd346938154e >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py >@@ -0,0 +1,128 @@ >+""" >+This generates a 30 minute silent wav, and is capable of >+responding to Range requests. >+""" >+import time >+import re >+import struct >+ >+ >+def create_wav_header(sample_rate, bit_depth, channels, duration): >+ bytes_per_sample = bit_depth / 8 >+ block_align = bytes_per_sample * channels >+ byte_rate = sample_rate * block_align >+ sub_chunk_2_size = duration * byte_rate >+ >+ data = b'' >+ # ChunkID >+ data += b'RIFF' >+ # ChunkSize >+ data += struct.pack('<L', 36 + sub_chunk_2_size) >+ # Format >+ data += b'WAVE' >+ # Subchunk1ID >+ data += b'fmt ' >+ # Subchunk1Size >+ data += struct.pack('<L', 16) >+ # AudioFormat >+ data += struct.pack('<H', 1) >+ # NumChannels >+ data += struct.pack('<H', channels) >+ # SampleRate >+ data += struct.pack('<L', sample_rate) >+ # ByteRate >+ data += struct.pack('<L', byte_rate) >+ # BlockAlign >+ data += struct.pack('<H', block_align) >+ # BitsPerSample >+ data += struct.pack('<H', bit_depth) >+ # Subchunk2ID >+ data += b'data' >+ # Subchunk2Size >+ data += struct.pack('<L', sub_chunk_2_size) >+ >+ return data >+ >+ >+def main(request, response): >+ response.headers.set("Content-Type", "audio/wav") >+ response.headers.set("Accept-Ranges", "bytes") >+ response.headers.set("Cache-Control", "no-cache") >+ >+ range_header = request.headers.get('Range', '') >+ range_header_match = range_header and re.search(r'^bytes=(\d*)-(\d*)$', range_header) >+ range_received_key = request.GET.first('range-received-key', '') >+ accept_encoding_key = request.GET.first('accept-encoding-key', '') >+ >+ if range_received_key and range_header: >+ # Remove any current value >+ request.server.stash.take(range_received_key, '/fetch/range/') >+ # This is later collected using stash-take.py >+ request.server.stash.put(range_received_key, 'range-header-received', '/fetch/range/') >+ >+ if accept_encoding_key: >+ # Remove any current value >+ request.server.stash.take( >+ accept_encoding_key, >+ '/fetch/range/' >+ ) >+ # This is later collected using stash-take.py >+ request.server.stash.put( >+ accept_encoding_key, >+ request.headers.get('Accept-Encoding', ''), >+ '/fetch/range/' >+ ) >+ >+ # Audio details >+ sample_rate = 8000 >+ bit_depth = 8 >+ channels = 1 >+ duration = 60 * 5 >+ >+ total_length = (sample_rate * bit_depth * channels * duration) / 8 >+ bytes_remaining_to_send = total_length >+ initial_write = '' >+ >+ if range_header_match: >+ response.status = 206 >+ start, end = range_header_match.groups() >+ >+ start = int(start) >+ end = int(end) if end else 0 >+ >+ if end: >+ bytes_remaining_to_send = (end + 1) - start >+ else: >+ bytes_remaining_to_send = total_length - start >+ >+ wav_header = create_wav_header(sample_rate, bit_depth, channels, duration) >+ >+ if start < len(wav_header): >+ initial_write = wav_header[start:] >+ >+ if bytes_remaining_to_send < len(initial_write): >+ initial_write = initial_write[0:bytes_remaining_to_send] >+ >+ content_range = "bytes {}-{}/{}".format(start, end or total_length - 1, total_length) >+ >+ response.headers.set("Content-Range", content_range) >+ else: >+ initial_write = create_wav_header(sample_rate, bit_depth, channels, duration) >+ >+ response.headers.set("Content-Length", bytes_remaining_to_send) >+ >+ response.write_status_headers() >+ response.writer.write(initial_write) >+ >+ bytes_remaining_to_send -= len(initial_write) >+ >+ while bytes_remaining_to_send > 0: >+ if not response.writer.flush(): >+ break >+ >+ to_send = b'\x00' * min(bytes_remaining_to_send, sample_rate) >+ bytes_remaining_to_send -= len(to_send) >+ >+ response.writer.write(to_send) >+ # Throttle the stream >+ time.sleep(0.5) >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/partial-script.py b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/partial-script.py >new file mode 100644 >index 0000000000000000000000000000000000000000..5b642c601d89dcd30632074d877252b0bbb07ee1 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/partial-script.py >@@ -0,0 +1,30 @@ >+""" >+This generates a partial response containing valid JavaScript. >+""" >+ >+ >+def main(request, response): >+ require_range = request.GET.first('require-range', '') >+ pretend_offset = int(request.GET.first('pretend-offset', '0')) >+ range_header = request.headers.get('Range', '') >+ >+ if require_range and not range_header: >+ response.set_error(412, "Range header required") >+ response.write() >+ return >+ >+ response.headers.set("Content-Type", "text/plain") >+ response.headers.set("Accept-Ranges", "bytes") >+ response.headers.set("Cache-Control", "no-cache") >+ response.status = 206 >+ >+ to_send = 'self.scriptExecuted = true;' >+ length = len(to_send) >+ >+ content_range = "bytes {}-{}/{}".format( >+ pretend_offset, pretend_offset + length - 1, pretend_offset + length) >+ >+ response.headers.set("Content-Range", content_range) >+ response.headers.set("Content-Length", length) >+ >+ response.content = to_send >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/range-sw.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/range-sw.js >new file mode 100644 >index 0000000000000000000000000000000000000000..3680c0c471d3d5f36c4aba4cc58dcd52c38a08df >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/range-sw.js >@@ -0,0 +1,159 @@ >+importScripts('/resources/testharness.js'); >+ >+setup({ explicit_done: true }); >+ >+function assert_range_request(request, expectedRangeHeader, name) { >+ assert_equals(request.headers.get('Range'), expectedRangeHeader, name); >+} >+ >+async function broadcast(msg) { >+ for (const client of await clients.matchAll()) { >+ client.postMessage(msg); >+ } >+} >+ >+addEventListener('fetch', event => { >+ /** @type Request */ >+ const request = event.request; >+ const url = new URL(request.url); >+ const action = url.searchParams.get('action'); >+ >+ switch (action) { >+ case 'range-header-filter-test': >+ rangeHeaderFilterTest(request); >+ return; >+ case 'range-header-passthrough-test': >+ rangeHeaderPassthroughTest(event); >+ return; >+ case 'store-ranged-response': >+ storeRangedResponse(event); >+ return; >+ case 'use-stored-ranged-response': >+ useStoredRangeResponse(event); >+ return; >+ case 'broadcast-accept-encoding': >+ broadcastAcceptEncoding(event); >+ return; >+ } >+}); >+ >+/** >+ * @param {Request} request >+ */ >+function rangeHeaderFilterTest(request) { >+ const rangeValue = request.headers.get('Range'); >+ >+ test(() => { >+ assert_range_request(new Request(request), rangeValue, `Untampered`); >+ assert_range_request(new Request(request, {}), rangeValue, `Untampered (no init props set)`); >+ assert_range_request(new Request(request, { __foo: 'bar' }), rangeValue, `Untampered (only invalid props set)`); >+ assert_range_request(new Request(request, { mode: 'cors' }), rangeValue, `More permissive mode`); >+ assert_range_request(request.clone(), rangeValue, `Clone`); >+ }, "Range headers correctly preserved"); >+ >+ test(() => { >+ assert_range_request(new Request(request, { headers: { Range: 'foo' } }), null, `Tampered - range header set`); >+ assert_range_request(new Request(request, { headers: {} }), null, `Tampered - empty headers set`); >+ assert_range_request(new Request(request, { mode: 'no-cors' }), null, `Tampered â mode set`); >+ assert_range_request(new Request(request, { cache: 'no-cache' }), null, `Tampered â cache mode set`); >+ }, "Range headers correctly removed"); >+ >+ test(() => { >+ let headers; >+ >+ headers = new Request(request).headers; >+ headers.delete('does-not-exist'); >+ assert_equals(headers.get('Range'), rangeValue, `Preserved if no header actually removed`); >+ >+ headers = new Request(request).headers; >+ headers.append('foo', 'bar'); >+ assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on append (due to request-no-cors guard)`); >+ >+ headers = new Request(request).headers; >+ headers.set('foo', 'bar'); >+ assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on set (due to request-no-cors guard)`); >+ >+ headers = new Request(request).headers; >+ headers.append('Range', 'foo'); >+ assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on append (due to request-no-cors guard)`); >+ >+ headers = new Request(request).headers; >+ headers.set('Range', 'foo'); >+ assert_equals(headers.get('Range'), rangeValue, `Preserved if silent-failure on set (due to request-no-cors guard)`); >+ >+ headers = new Request(request).headers; >+ headers.append('Accept', 'whatever'); >+ assert_equals(headers.get('Range'), null, `Stripped if header successfully appended`); >+ >+ headers = new Request(request).headers; >+ headers.set('Accept', 'whatever'); >+ assert_equals(headers.get('Range'), null, `Stripped if header successfully set`); >+ >+ headers = new Request(request).headers; >+ headers.delete('Accept'); >+ assert_equals(headers.get('Range'), null, `Stripped if header successfully deleted`); >+ >+ headers = new Request(request).headers; >+ headers.delete('Range'); >+ assert_equals(headers.get('Range'), null, `Stripped if range header successfully deleted`); >+ }, "Headers correctly filtered"); >+ >+ done(); >+} >+ >+function rangeHeaderPassthroughTest(event) { >+ /** @type Request */ >+ const request = event.request; >+ const url = new URL(request.url); >+ const key = url.searchParams.get('range-received-key'); >+ >+ event.waitUntil(new Promise(resolve => { >+ promise_test(async () => { >+ await fetch(event.request); >+ const response = await fetch('stash-take.py?key=' + key); >+ assert_equals(await response.json(), 'range-header-received'); >+ resolve(); >+ }, `Include range header in network request`); >+ >+ done(); >+ })); >+ >+ // Just send back any response, it isn't important for the test. >+ event.respondWith(new Response('')); >+} >+ >+let storedRangeResponseP; >+ >+function storeRangedResponse(event) { >+ /** @type Request */ >+ const request = event.request; >+ const id = new URL(request.url).searchParams.get('id'); >+ >+ storedRangeResponseP = fetch(event.request); >+ broadcast({ id }); >+ >+ // Just send back any response, it isn't important for the test. >+ event.respondWith(new Response('')); >+} >+ >+function useStoredRangeResponse(event) { >+ event.respondWith(async function() { >+ const response = await storedRangeResponseP; >+ if (!response) throw Error("Expected stored range response"); >+ return response.clone(); >+ }()); >+} >+ >+function broadcastAcceptEncoding(event) { >+ /** @type Request */ >+ const request = event.request; >+ const id = new URL(request.url).searchParams.get('id'); >+ >+ broadcast({ >+ id, >+ acceptEncoding: request.headers.get('Accept-Encoding') >+ }); >+ >+ // Just send back any response, it isn't important for the test. >+ event.respondWith(new Response('')); >+} >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/stash-take.py b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/stash-take.py >new file mode 100644 >index 0000000000000000000000000000000000000000..4ec1fe57647f41ea8196dad102815d06f8b1109f >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/stash-take.py >@@ -0,0 +1,7 @@ >+from wptserve.handlers import json_handler >+ >+ >+@json_handler >+def main(request, response): >+ key = request.GET.first("key") >+ return request.server.stash.take(key, '/fetch/range/') >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/utils.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/utils.js >new file mode 100644 >index 0000000000000000000000000000000000000000..16ed737f63e8eee26a306c70acb0589e424db35d >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/utils.js >@@ -0,0 +1,24 @@ >+function loadScript(url, { doc = document }={}) { >+ return new Promise((resolve, reject) => { >+ const script = doc.createElement('script'); >+ script.onload = () => resolve(); >+ script.onerror = () => reject(Error("Script load failed")); >+ script.src = url; >+ doc.body.appendChild(script); >+ }) >+} >+ >+/** >+ * >+ * @param {Document} document >+ * @param {string|URL} url >+ * @returns {HTMLAudioElement} >+ */ >+function appendAudio(document, url) { >+ const audio = document.createElement('audio'); >+ audio.muted = true; >+ audio.src = url; >+ audio.preload = true; >+ document.body.appendChild(audio); >+ return audio; >+} >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/w3c-import.log >new file mode 100644 >index 0000000000000000000000000000000000000000..e88dcc0790f178b98bd94128077860f13d577427 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/w3c-import.log >@@ -0,0 +1,22 @@ >+The tests in this directory were imported from the W3C repository. >+Do NOT modify these tests directly in WebKit. >+Instead, create a pull request on the WPT github: >+ https://github.com/w3c/web-platform-tests >+ >+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport >+ >+Do NOT modify or remove this file. >+ >+------------------------------------------------------------------------ >+Properties requiring vendor prefixes: >+None >+Property values requiring vendor prefixes: >+None >+------------------------------------------------------------------------ >+List of files: >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/basic.html >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/long-wav.py >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/partial-script.py >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/range-sw.js >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/stash-take.py >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/resources/utils.js >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/sw.https.window.js b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/sw.https.window.js >new file mode 100644 >index 0000000000000000000000000000000000000000..faaee86734e93bb514095e34671a57e00bcbcd98 >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/sw.https.window.js >@@ -0,0 +1,151 @@ >+// META: script=../../../service-workers/service-worker/resources/test-helpers.sub.js >+// META: script=/common/utils.js >+// META: script=/common/get-host-info.sub.js >+// META: script=resources/utils.js >+ >+const { REMOTE_HOST } = get_host_info(); >+const BASE_SCOPE = 'resources/basic.html?'; >+ >+async function cleanup() { >+ for (const iframe of document.querySelectorAll('.test-iframe')) { >+ iframe.parentNode.removeChild(iframe); >+ } >+ >+ for (const reg of await navigator.serviceWorker.getRegistrations()) { >+ await reg.unregister(); >+ } >+} >+ >+async function setupRegistration(t, scope) { >+ await cleanup(); >+ const reg = await navigator.serviceWorker.register('resources/range-sw.js', { scope }); >+ await wait_for_state(t, reg.installing, 'activated'); >+ return reg; >+} >+ >+function awaitMessage(obj, id) { >+ return new Promise(resolve => { >+ obj.addEventListener('message', function listener(event) { >+ if (event.data.id !== id) return; >+ obj.removeEventListener('message', listener); >+ resolve(event.data); >+ }); >+ }); >+} >+ >+promise_test(async t => { >+ const scope = BASE_SCOPE + Math.random(); >+ const reg = await setupRegistration(t, scope); >+ const iframe = await with_iframe(scope); >+ const w = iframe.contentWindow; >+ >+ // Trigger a cross-origin range request using media >+ const url = new URL('long-wav.py?action=range-header-filter-test', w.location); >+ url.hostname = REMOTE_HOST; >+ appendAudio(w.document, url); >+ >+ // See rangeHeaderFilterTest in resources/range-sw.js >+ await fetch_tests_from_worker(reg.active); >+}, `Defer range header filter tests to service worker`); >+ >+promise_test(async t => { >+ const scope = BASE_SCOPE + Math.random(); >+ const reg = await setupRegistration(t, scope); >+ const iframe = await with_iframe(scope); >+ const w = iframe.contentWindow; >+ >+ // Trigger a cross-origin range request using media >+ const url = new URL('long-wav.py', w.location); >+ url.searchParams.set('action', 'range-header-passthrough-test'); >+ url.searchParams.set('range-received-key', token()); >+ url.hostname = REMOTE_HOST; >+ appendAudio(w.document, url); >+ >+ // See rangeHeaderPassthroughTest in resources/range-sw.js >+ await fetch_tests_from_worker(reg.active); >+}, `Defer range header passthrough tests to service worker`); >+ >+promise_test(async t => { >+ const scope = BASE_SCOPE + Math.random(); >+ await setupRegistration(t, scope); >+ const iframe = await with_iframe(scope); >+ const w = iframe.contentWindow; >+ const id = Math.random() + ''; >+ const storedRangeResponse = awaitMessage(w.navigator.serviceWorker, id); >+ >+ // Trigger a cross-origin range request using media >+ const url = new URL('partial-script.py', w.location); >+ url.searchParams.set('require-range', '1'); >+ url.searchParams.set('action', 'store-ranged-response'); >+ url.searchParams.set('id', id); >+ url.hostname = REMOTE_HOST; >+ >+ appendAudio(w.document, url); >+ >+ await storedRangeResponse; >+ >+ // Fetching should reject >+ const fetchPromise = w.fetch('?action=use-stored-ranged-response', { mode: 'no-cors' }); >+ promise_rejects(t, new TypeError(), fetchPromise); >+ >+ // Script loading should error too >+ const loadScriptPromise = loadScript('?action=use-stored-ranged-response', { doc: w.document }); >+ promise_rejects(t, new Error(), loadScriptPromise); >+ >+ await loadScriptPromise.catch(() => {}); >+ >+ assert_false(!!w.scriptExecuted, `Partial response shouldn't be executed`); >+}, `Ranged response not allowed following no-cors ranged request`); >+ >+promise_test(async t => { >+ const scope = BASE_SCOPE + Math.random(); >+ await setupRegistration(t, scope); >+ const iframe = await with_iframe(scope); >+ const w = iframe.contentWindow; >+ const id = Math.random() + ''; >+ const storedRangeResponse = awaitMessage(w.navigator.serviceWorker, id); >+ >+ // Trigger a range request using media >+ const url = new URL('partial-script.py', w.location); >+ url.searchParams.set('require-range', '1'); >+ url.searchParams.set('action', 'store-ranged-response'); >+ url.searchParams.set('id', id); >+ >+ appendAudio(w.document, url); >+ >+ await storedRangeResponse; >+ >+ // This should not throw >+ await w.fetch('?action=use-stored-ranged-response'); >+ >+ // This shouldn't throw either >+ await loadScript('?action=use-stored-ranged-response', { doc: w.document }); >+ >+ assert_true(w.scriptExecuted, `Partial response should be executed`); >+}, `Non-opaque ranged response executed`); >+ >+promise_test(async t => { >+ const scope = BASE_SCOPE + Math.random(); >+ await setupRegistration(t, scope); >+ const iframe = await with_iframe(scope); >+ const w = iframe.contentWindow; >+ const fetchId = Math.random() + ''; >+ const fetchBroadcast = awaitMessage(w.navigator.serviceWorker, fetchId); >+ const audioId = Math.random() + ''; >+ const audioBroadcast = awaitMessage(w.navigator.serviceWorker, audioId); >+ >+ const url = new URL('long-wav.py', w.location); >+ url.searchParams.set('action', 'broadcast-accept-encoding'); >+ url.searchParams.set('id', fetchId); >+ >+ await w.fetch(url, { >+ headers: { Range: 'bytes=0-10' } >+ }); >+ >+ assert_equals((await fetchBroadcast).acceptEncoding, null, "Accept-Encoding should not be set for fetch"); >+ >+ url.searchParams.set('id', audioId); >+ appendAudio(w.document, url); >+ >+ assert_equals((await audioBroadcast).acceptEncoding, null, "Accept-Encoding should not be set for media"); >+}, `Accept-Encoding should not appear in a service worker`); >diff --git a/LayoutTests/imported/w3c/web-platform-tests/fetch/range/w3c-import.log b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/w3c-import.log >new file mode 100644 >index 0000000000000000000000000000000000000000..c23bcdbb52dd7af245dfcf1379bd311d0d8d479e >--- /dev/null >+++ b/LayoutTests/imported/w3c/web-platform-tests/fetch/range/w3c-import.log >@@ -0,0 +1,19 @@ >+The tests in this directory were imported from the W3C repository. >+Do NOT modify these tests directly in WebKit. >+Instead, create a pull request on the WPT github: >+ https://github.com/w3c/web-platform-tests >+ >+Then run the Tools/Scripts/import-w3c-tests in WebKit to reimport >+ >+Do NOT modify or remove this file. >+ >+------------------------------------------------------------------------ >+Properties requiring vendor prefixes: >+None >+Property values requiring vendor prefixes: >+None >+------------------------------------------------------------------------ >+List of files: >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.any.js >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/general.window.js >+/LayoutTests/imported/w3c/web-platform-tests/fetch/range/sw.https.window.js
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 186335
:
342056
|
342113