| <!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> |