| <!DOCTYPE html> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="resources/test-helpers.sub.js"></script> |
| |
| <script> |
| const timingEventOrder = [ |
| 'startTime', |
| 'workerStart', |
| 'fetchStart', |
| 'requestStart', |
| 'responseStart', |
| 'responseEnd', |
| ]; |
| |
| function verify(timing) { |
| for (let i = 0; i < timingEventOrder.length - 1; i++) { |
| assert_true(timing[timingEventOrder[i]] <= timing[timingEventOrder[i + 1]], |
| `Expected ${timingEventOrder[i]} <= ${timingEventOrder[i + 1]}`); |
| } |
| } |
| |
| function navigate_in_frame(frame, url) { |
| frame.contentWindow.location = url; |
| return new Promise((resolve) => { |
| frame.addEventListener('load', () => { |
| const timing = frame.contentWindow.performance.getEntriesByType('navigation')[0]; |
| resolve(timing); |
| }); |
| }); |
| } |
| |
| const worker_url = 'resources/navigation-timing-worker.js'; |
| |
| promise_test(t => { |
| const scope = 'resources/empty.html'; |
| let frame; |
| |
| return service_worker_unregister_and_register(t, worker_url, scope) |
| .then(r => { |
| return wait_for_state(t, r.installing, 'activated'); |
| }) |
| .then(() => with_iframe(scope)) |
| .then(f => { |
| frame = f; |
| return navigate_in_frame(frame, 'resources/empty.html'); |
| }) |
| .then(timing => { |
| verify(timing); |
| }) |
| .catch(unreached_rejection(t)) |
| .then(() => { |
| if (frame) |
| frame.remove(); |
| return service_worker_unregister(t, scope); |
| }); |
| }, 'Service worker controlled navigation timing'); |
| |
| promise_test(t => { |
| const scope = 'resources/empty.html?network-fallback'; |
| let frame; |
| |
| return service_worker_unregister_and_register(t, worker_url, scope) |
| .then(r => { |
| return wait_for_state(t, r.installing, 'activated'); |
| }) |
| .then(() => with_iframe(scope)) |
| .then(f => { |
| frame = f; |
| return navigate_in_frame(frame, 'resources/empty.html?network-fallback'); |
| }) |
| .then(timing => { |
| verify(timing); |
| }) |
| .catch(unreached_rejection(t)) |
| .then(() => { |
| if (frame) |
| frame.remove(); |
| return service_worker_unregister(t, scope); |
| }); |
| }, 'Service worker controlled navigation timing network fallback'); |
| |
| promise_test(t => { |
| const scope = 'resources/redirect.py?Redirect=empty.html'; |
| let frame; |
| |
| return service_worker_unregister_and_register(t, worker_url, scope) |
| .then(r => { |
| return wait_for_state(t, r.installing, 'activated'); |
| }) |
| .then(() => with_iframe(scope)) |
| .then(f => { |
| frame = f; |
| return navigate_in_frame(frame, 'resources/redirect.py?Redirect=empty.html'); |
| }) |
| .then(timing => { |
| verify(timing); |
| // Additional checks for redirected navigation. |
| assert_true(timing.redirectStart <= timing.redirectEnd, |
| 'Expected redirectStart <= redirectEnd'); |
| assert_true(timing.redirectEnd <= timing.fetchStart, |
| 'Expected redirectEnd <= fetchStart'); |
| }) |
| .catch(unreached_rejection(t)) |
| .then(() => { |
| if (frame) |
| frame.remove(); |
| return service_worker_unregister(t, scope); |
| }); |
| }, 'Service worker controlled navigation timing redirect'); |
| </script> |