diff options
Diffstat (limited to 'testing/web-platform/tests/content-security-policy/inheritance/history.sub.html')
-rw-r--r-- | testing/web-platform/tests/content-security-policy/inheritance/history.sub.html | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/testing/web-platform/tests/content-security-policy/inheritance/history.sub.html b/testing/web-platform/tests/content-security-policy/inheritance/history.sub.html new file mode 100644 index 0000000000..5ea6abe8fb --- /dev/null +++ b/testing/web-platform/tests/content-security-policy/inheritance/history.sub.html @@ -0,0 +1,195 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/utils.js"></script> + +<meta http-equiv="Content-Security-Policy" content="img-src 'none'"> + +<script> + let message_from = (source_token, starts_with) => { + return new Promise(resolve => { + window.addEventListener('message', msg => { + if (msg.data.token === source_token) { + if (!starts_with || msg.data.msg.startsWith(starts_with)) + resolve(msg.data.msg); + } + }); + }); + }; + + const img_url = window.origin + "/content-security-policy/support/fail.png"; + + const function_addImage_string = img_token => ` + function addImage() { + let img = document.createElement('img'); + img.src = '${img_url}'; + img.onload = () => opener.postMessage( + {msg: 'img loaded', token: '${img_token}'}, '*'); + img.onerror = () => opener.postMessage( + {msg: 'img blocked', token: '${img_token}'}, '*'); + document.body.appendChild(img); + } + `; + + const img_tag_string = img_token => ` + <img src="${img_url}" + onload="opener.postMessage( + {msg: 'img loaded', token: '${img_token}'}, '*');" + onerror="opener.postMessage( + {msg: 'img blocked', token: '${img_token}'}, '*');" + > + `; + + let write_img_to_popup = (popup, img_token) => { + let div = popup.document.createElement('div'); + div.innerHTML = img_tag_string(img_token); + popup.document.body.appendChild(div); + }; + + // A beforeunload event listener disables bfcache (Firefox only). + // + // Note: Chrome enables bfcache only on HTTP/HTTPS documents, so a blob will + // never be put in the bfcache. Moreover with Chrome, bfcache needs a single + // top-level browsing context in the browsing context group. Since we are + // using window.open() below, the back-forward cache is not triggered. + const disable_bfcache = ` + window.addEventListener('beforeunload', function(event) { + eval('1+1'); + }); + `; + + const blob_payload = blob_token => ` + <!doctype html> + <script>window.window_token = "${blob_token}";</scr`+`ipt> + <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt> + <body onpageshow="addImage();"></body> + `; + let blob_url = blob_token => URL.createObjectURL( + new Blob([blob_payload(blob_token)], { type: 'text/html' })); + + const blob_payload_no_bfcache = blob_token => ` + <!doctype html> + <script>window.window_token = "${blob_token}";</scr`+`ipt> + <script>${disable_bfcache}</scr`+`ipt> + <script>${function_addImage_string(`${blob_token}`)}</scr`+`ipt> + <body onpageshow="addImage();"></body> + `; + let blob_url_no_bfcache = blob_token => URL.createObjectURL( + new Blob([blob_payload_no_bfcache(blob_token)], { type: 'text/html' })); + + let testCases = [ + test_token => ({ + token: test_token, + url: "about:blank", + add_img_function: popup => write_img_to_popup(popup, test_token), + other_origin: window.origin, + name: '"about:blank" document is navigated back from history same-origin.', + }), + test_token => ({ + token: test_token, + url: "about:blank", + add_img_function: popup => write_img_to_popup(popup, test_token), + other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}", + name: '"about:blank" document is navigated back from history cross-origin.', + }), + test_token => ({ + token: test_token, + url: blob_url(test_token), + other_origin: window.origin, + name: 'blob URL document is navigated back from history same-origin.', + }), + test_token => ({ + token: test_token, + url: blob_url(test_token), + other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}", + name: 'blob URL document is navigated back from history cross-origin.', + }), + test_token => ({ + token: test_token, + url: blob_url_no_bfcache(test_token), + other_origin: window.origin, + name: 'blob URL document is navigated back from history (without bfcache on Firefox) same-origin.', + }), + test_token => ({ + token: test_token, + url: blob_url_no_bfcache(test_token), + other_origin: "http://{{hosts[alt][]}}:{{ports[http][0]}}", + name: 'blob URL document is navigated back from history (without bfcache on Firefox) cross-origin.', + }), + ].map(f => f(token())); + + let async_promise_test = (promise, description) => { + async_test(test => { + promise(test) + .then(() => {test.done();}) + .catch(test.step_func(error => { throw error; })); + }, description); + }; + + testCases.forEach(testCase => { + async_promise_test(async t => { + // Create a popup. + let popup = window.open(); + + // Closing fails sometimes on Firefox: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1698093 + t.add_cleanup(() => { popup.close(); }); + + // Perform a real navigation in the popup. This is needed because the + // initial empty document is not stored in history (so there is no way of + // navigating back to it and test history inheritance). + const token_1 = token(); + let loaded_1 = message_from(token_1); + popup.location = testCase.other_origin + + `/content-security-policy/inheritance/support` + + `/postmessage-opener.html?token=${token_1}`; + assert_equals(await loaded_1, "ready", + "Could not open and navigate popup."); + + // Navigate to the local scheme document. We need to wait for the + // navigation to succeed. + let wait = () => t.step_wait( + condition = () => { + try { + return popup.location.href == testCase.url; + } catch {} + return false; + }, + description = "Wait for the popup to navigate.", + timeout=3000, + interval=50); + + let message = message_from(testCase.token); + popup.location = testCase.url; + await wait(); + if (testCase.add_img_function) { + testCase.add_img_function(popup); + } + + // Check that the local scheme document inherits CSP from the initiator. + assert_equals(await message, "img blocked", + "Image should be blocked by CSP inherited from navigation initiator."); + + const token_2 = token(); + let loaded_2 = message_from(token_2, "ready"); + let message_2 = message_from(testCase.token, "img"); + // Navigate to another page, which will navigate back. + popup.location = testCase.other_origin + + `/content-security-policy/inheritance/support` + + `/message-opener-and-navigate-back.html?token=${token_2}`; + assert_equals(await loaded_2, "ready", + "Could not navigate popup."); + + // We need to wait for the history navigation to be performed. + await wait(); + + // Check that the "about:blank" document reloaded from history has the + // original CSPs. + if (testCase.add_img_function) { + testCase.add_img_function(popup); + } + assert_equals(await message_2, "img blocked", + "Image should be blocked by CSP reloaded from history."); + }, "History navigation: " + testCase.name); + }); +</script> |