| <!DOCTYPE html> |
| <script src="/common/dispatcher/dispatcher.js" nonce="abc"></script> |
| <script src="/resources/testdriver.js"></script> |
| <script src="/resources/testdriver-vendor.js"></script> |
| <script src="/resources/testdriver-actions.js"></script> |
| <script src="utils.sub.js" nonce="abc"></script> |
| <script nonce="abc"> |
| // For a given string `str` that is escaped by WPT's `.sub.html` or |
| // `pipe=sub(html)` functionality, return the original unescaped string. |
| // |
| // Concretely, for `str` as the result of `html.escape(x, quote=True)`, |
| // return the original unescaped string `x`. |
| // See `/tools/wptserve/wptserve/pipes.py` and |
| // https://docs.python.org/3/library/html.html#html.escape. |
| // |
| // See https://crbug.com/404573971 for fixing the escaping issue. |
| function reverse_html_escape(str) { |
| str = str.replaceAll('<', '<'); |
| str = str.replaceAll('>', '>'); |
| str = str.replaceAll('"', '"'); |
| str = str.replaceAll(''', "'"); |
| str = str.replaceAll('&', '&'); |
| return str; |
| } |
| |
| // To be consistent with https://fetch.spec.whatwg.org/#headers-class |
| // (accessed via iterable), |
| // - The keys are lower-cased header names, and |
| // - The entries are removed when the corresponding headers are non-existent. |
| window.requestHeaders = { |
| "purpose": "{{header_or_default(Purpose, NONEXISTENT)}}", |
| "sec-purpose": "{{header_or_default(Sec-Purpose, NONEXISTENT)}}", |
| "referer": "{{header_or_default(Referer, NONEXISTENT)}}", |
| "sec-fetch-dest": "{{header_or_default(Sec-Fetch-Dest, NONEXISTENT)}}", |
| "sec-fetch-mode": "{{header_or_default(Sec-Fetch-Mode, NONEXISTENT)}}", |
| "service-worker-navigation-preload": |
| "{{header_or_default(Service-Worker-Navigation-Preload, NONEXISTENT)}}", |
| // Convert to the raw string to avoid backslashes from being processed as |
| // escape sequences. |
| // TODO(crbug.com/404573971): Remove `header_or_default` to reflect |
| // `__no_tags__` properly. |
| sec_speculation_tags: |
| String.raw`{{header_or_default(Sec-Speculation-Tags, __no_tags__)}}`, |
| }; |
| Object.keys(requestHeaders).forEach(key => { |
| if (requestHeaders[key] === "NONEXISTENT") { |
| delete requestHeaders[key]; |
| } else { |
| requestHeaders[key] = reverse_html_escape(requestHeaders[key]); |
| } |
| }); |
| |
| // Add a link to the page in order to use during the test |
| function add_link(id, url) { |
| const link_element = document.createElement("a"); |
| const link_text = document.createTextNode(url); |
| link_element.setAttribute("href", url); |
| link_element.setAttribute("id", id); |
| link_element.appendChild(link_text); |
| document.body.appendChild(link_element); |
| } |
| |
| // "id" is the id of the link that we need to hover on in order |
| // to start the prefetch |
| async function start_non_immediate_prefetch_on_hover(id) { |
| let target = document.getElementById(id); |
| |
| test_driver.set_test_context(window.opener); |
| // Inject the inputs to run this test. |
| await new test_driver.Actions().addPointer("mouse").pointerMove(0, 0, {origin: target}).send(); |
| } |
| |
| // "id" is the id of the link that we need to press on in order |
| // to start the prefetch |
| async function start_non_immediate_prefetch_on_pointerdown(id) { |
| let target = document.getElementById(id); |
| |
| test_driver.set_test_context(window.opener); |
| // Inject the inputs to run this test. |
| // Move mouse pointer outside of the anchor so that we don't start the |
| // navigation before making sure the prefetch request started server-side. |
| await new test_driver.Actions().addPointer("mouse").pointerMove(0, 0, {origin: target}).pointerDown().pointerMove(0, 0).pointerUp().send(); |
| } |
| |
| async function navigate_by_form_generated_post(url) { |
| let form = document.createElement('form'); |
| form.method = 'POST'; |
| form.action = url; |
| document.body.appendChild(form); |
| form.submit(); |
| } |
| |
| // The fetch request's URL sent to the server. |
| window.requestUrl = reverse_html_escape( |
| "{{location[server]}}{{location[path]}}{{location[query]}}"); |
| |
| const uuid = new URLSearchParams(location.search).get('uuid'); |
| window.executor = new Executor(uuid); |
| </script> |