summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fetch/range/sw.https.window.js
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/fetch/range/sw.https.window.js')
-rw-r--r--testing/web-platform/tests/fetch/range/sw.https.window.js228
1 files changed, 228 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fetch/range/sw.https.window.js b/testing/web-platform/tests/fetch/range/sw.https.window.js
new file mode 100644
index 0000000000..62ad894da3
--- /dev/null
+++ b/testing/web-platform/tests/fetch/range/sw.https.window.js
@@ -0,0 +1,228 @@
+// 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' });
+ await promise_rejects_js(t, w.TypeError, fetchPromise);
+
+ // Script loading should error too
+ const loadScriptPromise = loadScript('?action=use-stored-ranged-response', { doc: w.document });
+ await promise_rejects_js(t, 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`);
+
+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 length = 100;
+ const count = 3;
+ const counts = {};
+
+ // test a single range request size
+ async function testSizedRange(size, partialResponseCode) {
+ const rangeId = Math.random() + '';
+ const rangeBroadcast = awaitMessage(w.navigator.serviceWorker, rangeId);
+
+ // Create a bogus audio element to trick the browser into sending
+ // cross-origin range requests that can be manipulated by the service worker.
+ const sound_url = new URL('partial-text.py', w.location);
+ sound_url.hostname = REMOTE_HOST;
+ sound_url.searchParams.set('action', 'record-media-range-request');
+ sound_url.searchParams.set('length', length);
+ sound_url.searchParams.set('size', size);
+ sound_url.searchParams.set('partial', partialResponseCode);
+ sound_url.searchParams.set('id', rangeId);
+ sound_url.searchParams.set('type', 'audio/mp4');
+ appendAudio(w.document, sound_url);
+
+ // wait for the range requests to happen
+ await rangeBroadcast;
+
+ // Create multiple preload requests and count the number of resource timing
+ // entries that get created to make sure 206 and 416 range responses are treated
+ // the same.
+ const url = new URL('partial-text.py', w.location);
+ url.searchParams.set('action', 'use-media-range-request');
+ url.searchParams.set('size', size);
+ url.searchParams.set('type', 'audio/mp4');
+ counts['size' + size] = 0;
+ for (let i = 0; i < count; i++) {
+ await preloadImage(url, { doc: w.document });
+ }
+ }
+
+ // Test range requests from 1 smaller than the correct size to 1 larger than
+ // the correct size to exercise the various permutations using the default 206
+ // response code for successful range requests.
+ for (let size = length - 1; size <= length + 1; size++) {
+ await testSizedRange(size, '206');
+ }
+
+ // Test a successful range request using a 200 response.
+ await testSizedRange(length - 2, '200');
+
+ // Check the resource timing entries and count the reported number of fetches of each type
+ const resources = w.performance.getEntriesByType("resource");
+ for (const entry of resources) {
+ const url = new URL(entry.name);
+ if (url.searchParams.has('action') &&
+ url.searchParams.get('action') == 'use-media-range-request' &&
+ url.searchParams.has('size')) {
+ counts['size' + url.searchParams.get('size')]++;
+ }
+ }
+
+ // Make sure there are a non-zero number of preload requests and they are all the same
+ let counts_valid = true;
+ const first = 'size' + (length - 2);
+ for (let size = length - 2; size <= length + 1; size++) {
+ let key = 'size' + size;
+ if (!(key in counts) || counts[key] <= 0 || counts[key] != counts[first]) {
+ counts_valid = false;
+ break;
+ }
+ }
+
+ assert_true(counts_valid, `Opaque range request preloads were different for error and success`);
+}, `Opaque range preload successes and failures should be indistinguishable`);