diff options
Diffstat (limited to 'testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html')
-rw-r--r-- | testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html b/testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html new file mode 100644 index 0000000000..cf5176606e --- /dev/null +++ b/testing/web-platform/tests/html/cross-origin-embedder-policy/block-local-documents-inheriting-none.https.html @@ -0,0 +1,112 @@ +<!doctype html> +<meta charset=utf-8> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/common/get-host-info.sub.js"></script> +<script src="/common/utils.js"></script> +<div id=log></div> + +<script> +const script = ` + <script> + top.postMessage({event: "loaded", type: location.protocol}, "*"); + <\/script>`; + +const test_cases = [ + {name: "data", url: encodeURI(`data:text/html,${script}`)}, + {name: "blob", url: URL.createObjectURL(new Blob([script], { type: "text/html" }))}, + {name: "about", url: "about:blank"}, + ]; + +const observeReports = async (frame) => { + const reports = []; + + const observer = new frame.contentWindow.ReportingObserver( + rs => reports.push(...rs.map(r => r.toJSON())) + ); + observer.observe(); + + // Wait for reports. Use a timeout to catch both expected and unexpected + // reports. + await new Promise(resolve => step_timeout(resolve, 3000)); + return reports; +}; + +promise_test(async t => { + const this_window_token = token(); + + // Expect the nested frame to not load, since they inherit COEP: none from the + // top frame, which is incompatible with first_frame's COEP: require-corp. + const received_events = []; + addEventListener("message", event => { + if(event.data.event == "loaded") + received_events.push(`Nested ${event.data.type} loaded!`); + }); + + // Create an iframe with COEP: require-corp + const first_iframe = document.createElement("iframe"); + t.add_cleanup( () => first_iframe.remove() ); + first_iframe.src = "/common/blank.html?pipe=header(cross-origin-embedder-policy,require-corp)"; + let iframe_load_promise = new Promise( resolve => first_iframe.addEventListener("load", resolve) ); + + document.body.append(first_iframe); + await iframe_load_promise; + + const reportPromise = observeReports(first_iframe); + // 1. Create nested frames. + // They initially navigate to blank.html and have COEP: require-corp set. + // This initial navigation is required because it uses the parent frame as the + // initiator. That is first_iframe is the initiator, while we want top to be + // the initiator for this test, which will be done in step 4 with a second + // navigation from that blank.html document to the local scheme one. + const nested_frames = {}; + const nested_frames_promises = []; + test_cases.forEach(test => { + nested_frame = document.createElement("iframe"); + nested_frame.src = "/common/blank.html?pipe=header(cross-origin-embedder-policy,require-corp)"; + t.add_cleanup( () => nested_frame.remove() ); + nested_frames_promises.push(new Promise( resolve => nested_frame.addEventListener("load", resolve) ) ); + first_iframe.contentDocument.body.append(nested_frame); + nested_frames[test.name] = nested_frame; + }); + + // 2. Wait for the loads of all iframes to complete. + await Promise.all(nested_frames_promises); + + // 3. Navigate a dummy frame. This is required because some browsers (Chrome) + // might consider the first navigation in 4. as a redirect otherwise. + const dummy_Frame = document.createElement("iframe"); + t.add_cleanup( () => dummy_Frame.remove() ); + dummy_Frame.src = "/common/blank.html"; + iframe_load_promise = new Promise( resolve => dummy_Frame.addEventListener("load", resolve) ); + document.body.append(dummy_Frame); + await iframe_load_promise; + + // 4. Navigate nested frames to a local scheme document. + // COEP should be inherited from the initiator or blobURL's creator (top in both + // cases), this results in COEP being none and the documents not being allowed + // to load under the COEP: require-corp iframe (first_iframe). + test_cases.forEach(test => { + // Top navigates nested_frame_[test.name] to a test.url + const frame = nested_frames[test.name]; + // Use frame.contentDocument.location to ensure the initiator is this (top) + // frame. frame.src is not used here as this makes the parent of the nested + // frame (first_iframe) the initiator. + frame.contentDocument.location = test.url; + }); + + // 5. Wait and validate reports. + const reports = await reportPromise; + assert_equals(reports.length, test_cases.length); + test_cases.forEach(test => { + assert_true(reports.some( report => { + return report.type == 'coep' && + report.body.type == 'navigation' && + report.body.blockedURL == test.url; + }), `No report matched for test "${test.name}"`); + }); + // Also verify that no message was sent by the nested frames and stored in + // received_events. + assert_equals(received_events.length, 0); +}, "Prevent local scheme documents from loading within a COEP: require-corp iframe if they inherit COEP: none"); +</script> |