| <!DOCTYPE html> | |
| <title>Test that user activation propagation is fenced.</title> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="/resources/testdriver.js"></script> | |
| <script src="/resources/testdriver-actions.js"></script> | |
| <script src="/resources/testdriver-vendor.js"></script> | |
| <script src="/common/utils.js"></script> | |
| <script src="/common/dispatcher/dispatcher.js"></script> | |
| <script src="resources/utils.js"></script> | |
| <body> | |
| <script> | |
| // Simulate a click in frame context `frame`. | |
| async function click(frame) { | |
| var actions = new test_driver.Actions(); | |
| await actions.pointerMove(0, 0, {origin: frame}) | |
| .pointerDown() | |
| .pointerUp() | |
| .send(); | |
| } | |
| assert_activation = (should_be_active, frame_name) => { | |
| if (should_be_active) { | |
| assert_true(navigator.userActivation.hasBeenActive, | |
| frame_name + " has been activated."); | |
| assert_true(navigator.userActivation.isActive, | |
| frame_name + " is currently active."); | |
| } else { | |
| assert_false(navigator.userActivation.hasBeenActive, | |
| frame_name + " has not been activated yet."); | |
| assert_false(navigator.userActivation.isActive, | |
| frame_name + " is not currently active."); | |
| } | |
| }; | |
| promise_test(async () => { | |
| // This test ensures that user activations (e.g. click events) don't | |
| // propagate across fenced frame boundaries. Specifically, activations | |
| // are visible through the `navigator.userActivation` object. | |
| // | |
| // The layout of the page is as follows: | |
| // A: top-level frame | |
| // B: iframe | |
| // C: fencedframe | |
| // D: iframe | |
| // E: fencedframe | |
| // | |
| // This order is chosen to test all kinds of fenced tree traversal. We: | |
| // - Click in C and check that only C gets activated (not A, B, D, or E) | |
| // - Click in A and check that only A, B, and D get activated (not E) | |
| // - Click in B and D and check that E wasn't activated | |
| const B = attachIFrameContext(); | |
| const C = attachFencedFrameContext(); | |
| const D = attachIFrameContext(); | |
| const E = attachFencedFrameContext(); | |
| // Define some helpers to check activations more concisely. | |
| const frames = [[B, "B"], [C, "C"], [D, "D"], [E, "E"]]; | |
| const assert_activations = async (should_be_actives) => { | |
| assert_equals(frames.length, should_be_actives.length); | |
| for ([i, [frame, frame_name]] of frames.entries()) { | |
| await frame.execute(assert_activation, [should_be_actives[i], frame_name]); | |
| } | |
| }; | |
| // Check that all the frames are inactive before we start. | |
| assert_activation(false, "A"); | |
| await assert_activations([false/*B*/, false/*C*/, false/*D*/, false/*E*/]); | |
| // Simulate a click in C (the first fenced frame). | |
| await click(C.element); | |
| // Check that only C has been activated. | |
| assert_activation(false, "A"); | |
| await assert_activations([false/*B*/, true/*C*/, false/*D*/, false/*E*/]); | |
| // Simulate a click in A (the top-level site). | |
| await click(document.documentElement); | |
| // Check that A, B, and D were activated. | |
| assert_activation(true, "A"); | |
| await assert_activations([true/*B*/, true/*C*/, true/*D*/, false/*E*/]); | |
| // Simulate a click in B and D (the two iframes). | |
| await click(B.element); | |
| await click(D.element); | |
| // Check that E has still not been activated. | |
| assert_activation(true, "A"); | |
| await assert_activations([true/*B*/, true/*C*/, true/*D*/, false/*E*/]); | |
| }, 'user-activation'); | |
| </script> | |
| </body> |