Bug 1646642 [wpt PR 24230] - Support ServiceWorker interception for requests made...
[gecko.git] / testing / web-platform / tests / service-workers / service-worker / fetch-event.https.html
blob48f71e46cb22136958f63aedd3ff16758a5de581
1 <!DOCTYPE html>
2 <meta name=timeout content=long>
3 <script src="/resources/testharness.js"></script>
4 <script src="/resources/testharnessreport.js"></script>
5 <script src="/common/get-host-info.sub.js"></script>
6 <script src="/common/utils.js"></script>
7 <script src="resources/test-helpers.sub.js"></script>
8 <body>
9 <script>
10 var worker = 'resources/fetch-event-test-worker.js';
11 function wait(ms) {
12 return new Promise(resolve => step_timeout(resolve, ms));
15 promise_test(async t => {
16 const scope = 'resources/';
17 const registration =
18 await service_worker_unregister_and_register(t, worker, scope);
19 await wait_for_state(t, registration.installing, 'activated');
20 promise_test(t => {
21 return registration.unregister();
22 }, 'restore global state');
23 }, 'global setup');
25 promise_test(t => {
26 const page_url = 'resources/simple.html?headers';
27 return with_iframe(page_url)
28 .then(function(frame) {
29 t.add_cleanup(() => { frame.remove(); });
30 const headers = JSON.parse(frame.contentDocument.body.textContent);
31 const header_names = {};
32 for (const [name, value] of headers) {
33 header_names[name] = true;
36 assert_true(
37 header_names.hasOwnProperty('accept'),
38 'request includes "Accept" header as inserted by Fetch'
40 });
41 }, 'Service Worker headers in the request of a fetch event');
43 promise_test(t => {
44 const page_url = 'resources/simple.html?string';
45 return with_iframe(page_url)
46 .then(function(frame) {
47 t.add_cleanup(() => { frame.remove(); });
48 assert_equals(
49 frame.contentDocument.body.textContent,
50 'Test string',
51 'Service Worker should respond to fetch with a test string');
52 assert_equals(
53 frame.contentDocument.contentType,
54 'text/plain',
55 'The content type of the response created with a string should be text/plain');
56 assert_equals(
57 frame.contentDocument.characterSet,
58 'UTF-8',
59 'The character set of the response created with a string should be UTF-8');
60 });
61 }, 'Service Worker responds to fetch event with string');
63 promise_test(t => {
64 const page_url = 'resources/simple.html?string';
65 var frame;
66 return with_iframe(page_url)
67 .then(function(f) {
68 frame = f;
69 t.add_cleanup(() => { frame.remove(); });
70 return frame.contentWindow.fetch(page_url + "#foo")
72 .then(function(response) { return response.text() })
73 .then(function(text) {
74 assert_equals(
75 text,
76 'Test string',
77 'Service Worker should respond to fetch with a test string');
78 });
79 }, 'Service Worker responds to fetch event using request fragment with string');
81 promise_test(t => {
82 const page_url = 'resources/simple.html?blob';
83 return with_iframe(page_url)
84 .then(frame => {
85 t.add_cleanup(() => { frame.remove(); });
86 assert_equals(
87 frame.contentDocument.body.textContent,
88 'Test blob',
89 'Service Worker should respond to fetch with a test string');
90 });
91 }, 'Service Worker responds to fetch event with blob body');
93 promise_test(t => {
94 const page_url = 'resources/simple.html?referrer';
95 return with_iframe(page_url)
96 .then(frame => {
97 t.add_cleanup(() => { frame.remove(); });
98 assert_equals(
99 frame.contentDocument.body.textContent,
100 'Referrer: ' + document.location.href,
101 'Service Worker should respond to fetch with the referrer URL');
103 }, 'Service Worker responds to fetch event with the referrer URL');
105 promise_test(t => {
106 const page_url = 'resources/simple.html?clientId';
107 var frame;
108 return with_iframe(page_url)
109 .then(function(f) {
110 frame = f;
111 t.add_cleanup(() => { frame.remove(); });
112 assert_equals(
113 frame.contentDocument.body.textContent,
114 'Client ID Not Found',
115 'Service Worker should respond to fetch with a client id');
116 return frame.contentWindow.fetch('resources/other.html?clientId');
118 .then(function(response) { return response.text(); })
119 .then(function(response_text) {
120 assert_equals(
121 response_text.substr(0, 15),
122 'Client ID Found',
123 'Service Worker should respond to fetch with an existing client id');
125 }, 'Service Worker responds to fetch event with an existing client id');
127 promise_test(t => {
128 const page_url = 'resources/simple.html?resultingClientId';
129 const expected_found = 'Resulting Client ID Found';
130 const expected_not_found = 'Resulting Client ID Not Found';
131 return with_iframe(page_url)
132 .then(function(frame) {
133 t.add_cleanup(() => { frame.remove(); });
134 assert_equals(
135 frame.contentDocument.body.textContent.substr(0, expected_found.length),
136 expected_found,
137 'Service Worker should respond with an existing resulting client id for non-subresource requests');
138 return frame.contentWindow.fetch('resources/other.html?resultingClientId');
140 .then(function(response) { return response.text(); })
141 .then(function(response_text) {
142 assert_equals(
143 response_text.substr(0),
144 expected_not_found,
145 'Service Worker should respond with an empty resulting client id for subresource requests');
147 }, 'Service Worker responds to fetch event with the correct resulting client id');
149 promise_test(t => {
150 const page_url = 'resources/simple.html?ignore';
151 return with_iframe(page_url)
152 .then(function(frame) {
153 t.add_cleanup(() => { frame.remove(); });
154 assert_equals(frame.contentDocument.body.textContent,
155 'Here\'s a simple html file.\n',
156 'Response should come from fallback to native fetch');
158 }, 'Service Worker does not respond to fetch event');
160 promise_test(t => {
161 const page_url = 'resources/simple.html?null';
162 return with_iframe(page_url)
163 .then(function(frame) {
164 t.add_cleanup(() => { frame.remove(); });
165 assert_equals(frame.contentDocument.body.textContent,
167 'Response should be the empty string');
169 }, 'Service Worker responds to fetch event with null response body');
171 promise_test(t => {
172 const page_url = 'resources/simple.html?fetch';
173 return with_iframe(page_url)
174 .then(function(frame) {
175 t.add_cleanup(() => { frame.remove(); });
176 assert_equals(frame.contentDocument.body.textContent,
177 'Here\'s an other html file.\n',
178 'Response should come from fetched other file');
180 }, 'Service Worker fetches other file in fetch event');
182 // Creates a form and an iframe and does a form submission that navigates the
183 // frame to |action_url|. Returns the frame after navigation.
184 function submit_form(action_url) {
185 return new Promise(resolve => {
186 const frame = document.createElement('iframe');
187 frame.name = 'post-frame';
188 document.body.appendChild(frame);
189 const form = document.createElement('form');
190 form.target = frame.name;
191 form.action = action_url;
192 form.method = 'post';
193 const input1 = document.createElement('input');
194 input1.type = 'text';
195 input1.value = 'testValue1';
196 input1.name = 'testName1'
197 form.appendChild(input1);
198 const input2 = document.createElement('input');
199 input2.type = 'text';
200 input2.value = 'testValue2';
201 input2.name = 'testName2'
202 form.appendChild(input2);
203 document.body.appendChild(form);
204 frame.onload = function() {
205 form.remove();
206 resolve(frame);
208 form.submit();
212 promise_test(t => {
213 const page_url = 'resources/simple.html?form-post';
214 return submit_form(page_url)
215 .then(frame => {
216 t.add_cleanup(() => { frame.remove(); });
217 assert_equals(frame.contentDocument.body.textContent,
218 'POST:application/x-www-form-urlencoded:' +
219 'testName1=testValue1&testName2=testValue2');
221 }, 'Service Worker responds to fetch event with POST form');
223 promise_test(t => {
224 // Add '?ignore' so the service worker falls back to network.
225 const page_url = 'resources/echo-content.py?ignore';
226 return submit_form(page_url)
227 .then(frame => {
228 t.add_cleanup(() => { frame.remove(); });
229 assert_equals(frame.contentDocument.body.textContent,
230 'testName1=testValue1&testName2=testValue2');
232 }, 'Service Worker falls back to network in fetch event with POST form');
234 promise_test(t => {
235 const page_url = 'resources/simple.html?multiple-respond-with';
236 return with_iframe(page_url)
237 .then(frame => {
238 t.add_cleanup(() => { frame.remove(); });
239 assert_equals(
240 frame.contentDocument.body.textContent,
241 '(0)(1)[InvalidStateError](2)[InvalidStateError]',
242 'Multiple calls of respondWith must throw InvalidStateErrors.');
244 }, 'Multiple calls of respondWith must throw InvalidStateErrors');
246 promise_test(t => {
247 const page_url = 'resources/simple.html?used-check';
248 var first_frame;
249 return with_iframe(page_url)
250 .then(function(frame) {
251 assert_equals(frame.contentDocument.body.textContent,
252 'Here\'s an other html file.\n',
253 'Response should come from fetched other file');
254 first_frame = frame;
255 t.add_cleanup(() => { first_frame.remove(); });
256 return with_iframe(page_url);
258 .then(function(frame) {
259 t.add_cleanup(() => { frame.remove(); });
260 // When we access to the page_url in the second time, the content of the
261 // response is generated inside the ServiceWorker. The body contains
262 // the value of bodyUsed of the first response which is already
263 // consumed by FetchEvent.respondWith method.
264 assert_equals(
265 frame.contentDocument.body.textContent,
266 'bodyUsed: true',
267 'event.respondWith must set the used flag.');
269 }, 'Service Worker event.respondWith must set the used flag');
271 promise_test(t => {
272 const page_url = 'resources/simple.html?fragment-check';
273 var fragment = '#/some/fragment';
274 var first_frame;
275 return with_iframe(page_url + fragment)
276 .then(function(frame) {
277 t.add_cleanup(() => { frame.remove(); });
278 assert_equals(
279 frame.contentDocument.body.textContent,
280 'Fragment Found :' + fragment,
281 'Service worker should expose URL fragments in request.');
283 }, 'Service Worker should expose FetchEvent URL fragments.');
285 promise_test(t => {
286 const page_url = 'resources/simple.html?cache';
287 var frame;
288 var cacheTypes = [
289 undefined, 'default', 'no-store', 'reload', 'no-cache', 'force-cache', 'only-if-cached'
291 return with_iframe(page_url)
292 .then(function(f) {
293 frame = f;
294 t.add_cleanup(() => { frame.remove(); });
295 assert_equals(frame.contentWindow.document.body.textContent, 'default');
296 var tests = cacheTypes.map(function(type) {
297 return new Promise(function(resolve, reject) {
298 var init = {cache: type};
299 if (type === 'only-if-cached') {
300 // For privacy reasons, for the time being, only-if-cached
301 // requires the mode to be same-origin.
302 init.mode = 'same-origin';
304 return frame.contentWindow.fetch(page_url + '=' + type, init)
305 .then(function(response) { return response.text(); })
306 .then(function(response_text) {
307 var expected = (type === undefined) ? 'default' : type;
308 assert_equals(response_text, expected,
309 'Service Worker should respond to fetch with the correct type');
311 .then(resolve)
312 .catch(reject);
315 return Promise.all(tests);
317 .then(function() {
318 return new Promise(function(resolve, reject) {
319 frame.addEventListener('load', function onLoad() {
320 frame.removeEventListener('load', onLoad);
321 try {
322 assert_equals(frame.contentWindow.document.body.textContent,
323 'no-cache');
324 resolve();
325 } catch (e) {
326 reject(e);
329 frame.contentWindow.location.reload();
332 }, 'Service Worker responds to fetch event with the correct cache types');
334 promise_test(t => {
335 const page_url = 'resources/simple.html?eventsource';
336 var frame;
338 function test_eventsource(opts) {
339 return new Promise(function(resolve, reject) {
340 var eventSource = new frame.contentWindow.EventSource(page_url, opts);
341 eventSource.addEventListener('message', function(msg) {
342 eventSource.close();
343 try {
344 var data = JSON.parse(msg.data);
345 assert_equals(data.mode, 'cors',
346 'EventSource should make CORS requests.');
347 assert_equals(data.cache, 'no-store',
348 'EventSource should bypass the http cache.');
349 var expectedCredentials = opts.withCredentials ? 'include'
350 : 'same-origin';
351 assert_equals(data.credentials, expectedCredentials,
352 'EventSource should pass correct credentials mode.');
353 resolve();
354 } catch (e) {
355 reject(e);
358 eventSource.addEventListener('error', function(e) {
359 eventSource.close();
360 reject('The EventSource fired an error event.');
365 return with_iframe(page_url)
366 .then(function(f) {
367 frame = f;
368 t.add_cleanup(() => { frame.remove(); });
369 return test_eventsource({ withCredentials: false });
371 .then(function() {
372 return test_eventsource({ withCredentials: true });
374 }, 'Service Worker should intercept EventSource');
376 promise_test(t => {
377 const page_url = 'resources/simple.html?integrity';
378 var frame;
379 var integrity_metadata = 'gs0nqru8KbsrIt5YToQqS9fYao4GQJXtcId610g7cCU=';
381 return with_iframe(page_url)
382 .then(function(f) {
383 frame = f;
384 t.add_cleanup(() => { frame.remove(); });
385 // A request has associated integrity metadata (a string).
386 // Unless stated otherwise, it is the empty string.
387 assert_equals(
388 frame.contentDocument.body.textContent, '');
390 return frame.contentWindow.fetch(page_url, {'integrity': integrity_metadata});
392 .then(response => {
393 return response.text();
395 .then(response_text => {
396 assert_equals(response_text, integrity_metadata, 'integrity');
398 }, 'Service Worker responds to fetch event with the correct integrity_metadata');
400 // Test that the service worker can read FetchEvent#body when it is a string.
401 // It responds with request body it read.
402 promise_test(t => {
403 // Set page_url to "?ignore" so the service worker falls back to network
404 // for the main resource request, and add a suffix to avoid colliding
405 // with other tests.
406 const page_url = 'resources/simple.html?ignore-for-request-body-string';
407 let frame;
409 return with_iframe(page_url)
410 .then(f => {
411 frame = f;
412 t.add_cleanup(() => { frame.remove(); });
413 return frame.contentWindow.fetch('simple.html?request-body', {
414 method: 'POST',
415 body: 'i am the request body'
418 .then(response => {
419 return response.text();
421 .then(response_text => {
422 assert_equals(response_text, 'i am the request body');
424 }, 'FetchEvent#body is a string');
426 // Test that the service worker can read FetchEvent#body when it is made from
427 // a ReadableStream. It responds with request body it read.
428 promise_test(async t => {
429 const rs = new ReadableStream({start(c) {
430 c.enqueue('i a');
431 c.enqueue('m the request');
432 step_timeout(t.step_func(() => {
433 c.enqueue(' body');
434 c.close();
435 }, 10));
436 }});
438 // Set page_url to "?ignore" so the service worker falls back to network
439 // for the main resource request, and add a suffix to avoid colliding
440 // with other tests.
441 const page_url = `resources/simple.html?ignore&id=${token()}`;
443 const frame = await with_iframe(page_url);
444 t.add_cleanup(() => { frame.remove(); });
445 const res = await frame.contentWindow.fetch('simple.html?request-body', {
446 method: 'POST',
447 body: rs.pipeThrough(new TextEncoderStream())
449 assert_equals(await res.text(), 'i am the request body');
450 }, 'FetchEvent#body is a ReadableStream');
452 // Test that the request body is sent to network upon network fallback,
453 // for a string body.
454 promise_test(t => {
455 // Set page_url to "?ignore" so the service worker falls back to network
456 // for the main resource request, and add a suffix to avoid colliding
457 // with other tests.
458 const page_url = 'resources/?ignore-for-request-body-fallback-string';
459 let frame;
461 return with_iframe(page_url)
462 .then(f => {
463 frame = f;
464 t.add_cleanup(() => { frame.remove(); });
465 // Add "?ignore" so the service worker falls back to echo-content.py.
466 const echo_url = '/fetch/api/resources/echo-content.py?ignore';
467 return frame.contentWindow.fetch(echo_url, {
468 method: 'POST',
469 body: 'i am the request body'
472 .then(response => {
473 return response.text();
475 .then(response_text => {
476 assert_equals(
477 response_text,
478 'i am the request body',
479 'the network fallback request should include the request body');
481 }, 'FetchEvent#body is a string and is passed to network fallback');
483 // Test that the service worker can read FetchEvent#body when it is a blob.
484 // It responds with request body it read.
485 promise_test(t => {
486 // Set page_url to "?ignore" so the service worker falls back to network
487 // for the main resource request, and add a suffix to avoid colliding
488 // with other tests.
489 const page_url = 'resources/simple.html?ignore-for-request-body-blob';
490 let frame;
492 return with_iframe(page_url)
493 .then(f => {
494 frame = f;
495 t.add_cleanup(() => { frame.remove(); });
496 const blob = new Blob(['it\'s me the blob', ' ', 'and more blob!']);
497 return frame.contentWindow.fetch('simple.html?request-body', {
498 method: 'POST',
499 body: blob
502 .then(response => {
503 return response.text();
505 .then(response_text => {
506 assert_equals(response_text, 'it\'s me the blob and more blob!');
508 }, 'FetchEvent#body is a blob');
510 // Test that the request body is sent to network upon network fallback,
511 // for a blob body.
512 promise_test(t => {
513 // Set page_url to "?ignore" so the service worker falls back to network
514 // for the main resource request, and add a suffix to avoid colliding
515 // with other tests.
516 const page_url = 'resources/simple.html?ignore-for-request-body-fallback-blob';
517 let frame;
519 return with_iframe(page_url)
520 .then(f => {
521 frame = f;
522 t.add_cleanup(() => { frame.remove(); });
523 const blob = new Blob(['it\'s me the blob', ' ', 'and more blob!']);
524 // Add "?ignore" so the service worker falls back to echo-content.py.
525 const echo_url = '/fetch/api/resources/echo-content.py?ignore';
526 return frame.contentWindow.fetch(echo_url, {
527 method: 'POST',
528 body: blob
531 .then(response => {
532 return response.text();
534 .then(response_text => {
535 assert_equals(
536 response_text,
537 'it\'s me the blob and more blob!',
538 'the network fallback request should include the request body');
540 }, 'FetchEvent#body is a blob and is passed to network fallback');
542 promise_test(async (t) => {
543 const page_url = 'resources/simple.html?keepalive';
544 const frame = await with_iframe(page_url);
545 t.add_cleanup(() => { frame.remove(); });
546 assert_equals(frame.contentDocument.body.textContent, 'false');
547 const response = await frame.contentWindow.fetch(page_url, {keepalive: true});
548 const text = await response.text();
549 assert_equals(text, 'true');
550 }, 'Service Worker responds to fetch event with the correct keepalive value');
552 promise_test(async (t) => {
553 const page_url = 'resources/simple.html?isReloadNavigation';
554 const frame = await with_iframe(page_url);
555 t.add_cleanup(() => { frame.remove(); });
556 assert_equals(frame.contentDocument.body.textContent,
557 'method = GET, isReloadNavigation = false');
558 await new Promise((resolve) => {
559 frame.addEventListener('load', resolve);
560 frame.contentWindow.location.reload();
562 assert_equals(frame.contentDocument.body.textContent,
563 'method = GET, isReloadNavigation = true');
564 }, 'FetchEvent#request.isReloadNavigation is true (location.reload())');
566 promise_test(async (t) => {
567 const page_url = 'resources/simple.html?isReloadNavigation';
568 const frame = await with_iframe(page_url);
569 t.add_cleanup(() => { frame.remove(); });
570 assert_equals(frame.contentDocument.body.textContent,
571 'method = GET, isReloadNavigation = false');
572 await new Promise((resolve) => {
573 frame.addEventListener('load', resolve);
574 frame.contentWindow.history.go(0);
576 assert_equals(frame.contentDocument.body.textContent,
577 'method = GET, isReloadNavigation = true');
578 }, 'FetchEvent#request.isReloadNavigation is true (history.go(0))');
580 promise_test(async (t) => {
581 const page_url = 'resources/simple.html?isReloadNavigation';
582 const frame = await with_iframe(page_url);
583 t.add_cleanup(() => { frame.remove(); });
584 assert_equals(frame.contentDocument.body.textContent,
585 'method = GET, isReloadNavigation = false');
586 await new Promise((resolve) => {
587 frame.addEventListener('load', resolve);
588 const form = frame.contentDocument.createElement('form');
589 form.method = 'POST';
590 form.name = 'form';
591 form.action = new Request(page_url).url;
592 frame.contentDocument.body.appendChild(form);
593 form.submit();
595 assert_equals(frame.contentDocument.body.textContent,
596 'method = POST, isReloadNavigation = false');
597 await new Promise((resolve) => {
598 frame.addEventListener('load', resolve);
599 frame.contentWindow.location.reload();
601 assert_equals(frame.contentDocument.body.textContent,
602 'method = POST, isReloadNavigation = true');
603 }, 'FetchEvent#request.isReloadNavigation is true (POST + location.reload())');
605 promise_test(async (t) => {
606 const page_url = 'resources/simple.html?isReloadNavigation';
607 const anotherUrl = new Request('resources/simple.html').url;
608 let frame = await with_iframe(page_url);
609 t.add_cleanup(() => { frame.remove(); });
610 assert_equals(frame.contentDocument.body.textContent,
611 'method = GET, isReloadNavigation = false');
612 // Use step_timeout(0) to ensure the history entry is created for Blink
613 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
614 await wait(0);
615 await new Promise((resolve) => {
616 frame.addEventListener('load', resolve);
617 frame.src = anotherUrl;
619 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
620 await new Promise((resolve) => {
621 frame.addEventListener('load', resolve);
622 frame.contentWindow.history.go(-1);
624 assert_equals(frame.contentDocument.body.textContent,
625 'method = GET, isReloadNavigation = false');
626 await new Promise((resolve) => {
627 frame.addEventListener('load', resolve);
628 frame.contentWindow.history.go(0);
630 assert_equals(frame.contentDocument.body.textContent,
631 'method = GET, isReloadNavigation = true');
632 await new Promise((resolve) => {
633 frame.addEventListener('load', resolve);
634 frame.contentWindow.history.go(1);
636 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
637 }, 'FetchEvent#request.isReloadNavigation is true (with history traversal)');
639 promise_test(async (t) => {
640 const page_url = 'resources/simple.html?isHistoryNavigation';
641 const anotherUrl = new Request('resources/simple.html?ignore').url;
642 const frame = await with_iframe(page_url);
643 t.add_cleanup(() => { frame.remove(); });
644 assert_equals(frame.contentDocument.body.textContent,
645 'method = GET, isHistoryNavigation = false');
646 // Use step_timeout(0) to ensure the history entry is created for Blink
647 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
648 await wait(0);
649 await new Promise((resolve) => {
650 frame.addEventListener('load', resolve);
651 frame.src = anotherUrl;
653 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
654 await new Promise((resolve) => {
655 frame.addEventListener('load', resolve);
656 frame.contentWindow.history.go(-1);
658 assert_equals(frame.contentDocument.body.textContent,
659 'method = GET, isHistoryNavigation = true');
660 }, 'FetchEvent#request.isHistoryNavigation is true (with history.go(-1))');
662 promise_test(async (t) => {
663 const page_url = 'resources/simple.html?isHistoryNavigation';
664 const anotherUrl = new Request('resources/simple.html?ignore').url;
665 const frame = await with_iframe(anotherUrl);
666 t.add_cleanup(() => { frame.remove(); });
667 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
668 // Use step_timeout(0) to ensure the history entry is created for Blink
669 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
670 await wait(0);
671 await new Promise((resolve) => {
672 frame.addEventListener('load', resolve);
673 frame.src = page_url;
675 assert_equals(frame.contentDocument.body.textContent,
676 'method = GET, isHistoryNavigation = false');
677 await new Promise((resolve) => {
678 frame.addEventListener('load', resolve);
679 frame.contentWindow.history.go(-1);
681 await new Promise((resolve) => {
682 frame.addEventListener('load', resolve);
683 frame.contentWindow.history.go(1);
685 assert_equals(frame.contentDocument.body.textContent,
686 'method = GET, isHistoryNavigation = true');
687 }, 'FetchEvent#request.isHistoryNavigation is true (with history.go(1))');
689 promise_test(async (t) => {
690 const page_url = 'resources/simple.html?isHistoryNavigation';
691 const anotherUrl = new Request('resources/simple.html?ignore').url;
692 const frame = await with_iframe(anotherUrl);
693 t.add_cleanup(() => { frame.remove(); });
694 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
695 // Use step_timeout(0) to ensure the history entry is created for Blink
696 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
697 await wait(0);
698 await new Promise((resolve) => {
699 frame.addEventListener('load', resolve);
700 frame.src = page_url;
702 assert_equals(frame.contentDocument.body.textContent,
703 'method = GET, isHistoryNavigation = false');
704 await new Promise((resolve) => {
705 frame.addEventListener('load', resolve);
706 frame.contentWindow.history.go(-1);
708 await new Promise((resolve) => {
709 frame.addEventListener('load', resolve);
710 frame.contentWindow.history.go(1);
712 assert_equals(frame.contentDocument.body.textContent,
713 'method = GET, isHistoryNavigation = true');
714 await new Promise((resolve) => {
715 frame.addEventListener('load', resolve);
716 frame.contentWindow.history.go(0);
718 assert_equals(frame.contentDocument.body.textContent,
719 'method = GET, isHistoryNavigation = false');
720 }, 'FetchEvent#request.isHistoryNavigation is false (with history.go(0))');
722 promise_test(async (t) => {
723 const page_url = 'resources/simple.html?isHistoryNavigation';
724 const anotherUrl = new Request('resources/simple.html?ignore').url;
725 const frame = await with_iframe(anotherUrl);
726 t.add_cleanup(() => { frame.remove(); });
727 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
728 // Use step_timeout(0) to ensure the history entry is created for Blink
729 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
730 await wait(0);
731 await new Promise((resolve) => {
732 frame.addEventListener('load', resolve);
733 frame.src = page_url;
735 assert_equals(frame.contentDocument.body.textContent,
736 'method = GET, isHistoryNavigation = false');
737 await new Promise((resolve) => {
738 frame.addEventListener('load', resolve);
739 frame.contentWindow.history.go(-1);
741 await new Promise((resolve) => {
742 frame.addEventListener('load', resolve);
743 frame.contentWindow.history.go(1);
745 assert_equals(frame.contentDocument.body.textContent,
746 'method = GET, isHistoryNavigation = true');
747 await new Promise((resolve) => {
748 frame.addEventListener('load', resolve);
749 frame.contentWindow.location.reload();
751 assert_equals(frame.contentDocument.body.textContent,
752 'method = GET, isHistoryNavigation = false');
753 }, 'FetchEvent#request.isHistoryNavigation is false (with location.reload)');
755 promise_test(async (t) => {
756 const page_url = 'resources/simple.html?isHistoryNavigation';
757 const anotherUrl = new Request('resources/simple.html?ignore').url;
758 const oneAnotherUrl = new Request('resources/simple.html?ignore2').url;
760 const frame = await with_iframe(page_url);
761 t.add_cleanup(() => { frame.remove(); });
762 assert_equals(frame.contentDocument.body.textContent,
763 'method = GET, isHistoryNavigation = false');
764 // Use step_timeout(0) to ensure the history entry is created for Blink
765 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
766 await wait(0);
767 await new Promise((resolve) => {
768 frame.addEventListener('load', resolve);
769 frame.src = anotherUrl;
771 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
772 await wait(0);
773 await new Promise((resolve) => {
774 frame.addEventListener('load', resolve);
775 frame.src = oneAnotherUrl;
777 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
778 await new Promise((resolve) => {
779 frame.addEventListener('load', resolve);
780 frame.contentWindow.history.go(-2);
782 assert_equals(frame.contentDocument.body.textContent,
783 'method = GET, isHistoryNavigation = true');
784 }, 'FetchEvent#request.isHistoryNavigation is true (with history.go(-2))');
786 promise_test(async (t) => {
787 const page_url = 'resources/simple.html?isHistoryNavigation';
788 const anotherUrl = new Request('resources/simple.html?ignore').url;
789 const oneAnotherUrl = new Request('resources/simple.html?ignore2').url;
790 const frame = await with_iframe(anotherUrl);
791 t.add_cleanup(() => { frame.remove(); });
792 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
793 // Use step_timeout(0) to ensure the history entry is created for Blink
794 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
795 await wait(0);
796 await new Promise((resolve) => {
797 frame.addEventListener('load', resolve);
798 frame.src = oneAnotherUrl;
800 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
801 await wait(0);
802 await new Promise((resolve) => {
803 frame.addEventListener('load', resolve);
804 frame.src = page_url;
806 assert_equals(frame.contentDocument.body.textContent,
807 'method = GET, isHistoryNavigation = false');
808 await new Promise((resolve) => {
809 frame.addEventListener('load', resolve);
810 frame.contentWindow.history.go(-2);
812 await new Promise((resolve) => {
813 frame.addEventListener('load', resolve);
814 frame.contentWindow.history.go(2);
816 assert_equals(frame.contentDocument.body.textContent,
817 'method = GET, isHistoryNavigation = true');
818 }, 'FetchEvent#request.isHistoryNavigation is true (with history.go(2))');
820 promise_test(async (t) => {
821 const page_url = 'resources/simple.html?isHistoryNavigation';
822 const anotherUrl = new Request('resources/simple.html?ignore').url;
823 const frame = await with_iframe(page_url);
824 t.add_cleanup(() => { frame.remove(); });
825 assert_equals(frame.contentDocument.body.textContent,
826 'method = GET, isHistoryNavigation = false');
827 await new Promise((resolve) => {
828 frame.addEventListener('load', resolve);
829 const form = frame.contentDocument.createElement('form');
830 form.method = 'POST';
831 form.name = 'form';
832 form.action = new Request(page_url).url;
833 frame.contentDocument.body.appendChild(form);
834 form.submit();
836 assert_equals(frame.contentDocument.body.textContent,
837 'method = POST, isHistoryNavigation = false');
838 // Use step_timeout(0) to ensure the history entry is created for Blink
839 // and WebKit. See https://bugs.webkit.org/show_bug.cgi?id=42861.
840 await wait(0);
841 await new Promise((resolve) => {
842 frame.addEventListener('load', resolve);
843 frame.src = anotherUrl;
845 assert_equals(frame.contentDocument.body.textContent, "Here's a simple html file.\n");
846 await wait(0);
847 await new Promise((resolve) => {
848 frame.addEventListener('load', resolve);
849 frame.contentWindow.history.go(-1);
851 assert_equals(frame.contentDocument.body.textContent,
852 'method = POST, isHistoryNavigation = true');
853 }, 'FetchEvent#request.isHistoryNavigation is true (POST + history.go(-1))');
854 </script>
855 </body>