summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fenced-frame
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/fenced-frame')
-rw-r--r--testing/web-platform/tests/fenced-frame/notify-event-iframe.https.html102
-rw-r--r--testing/web-platform/tests/fenced-frame/notify-event-invalid.https.html96
-rw-r--r--testing/web-platform/tests/fenced-frame/notify-event-nested-fenced-frames.https.html41
-rw-r--r--testing/web-platform/tests/fenced-frame/notify-event-success.https.html55
-rw-r--r--testing/web-platform/tests/fenced-frame/notify-event-transient-user-activation.https.html53
-rw-r--r--testing/web-platform/tests/fenced-frame/resources/utils.js21
-rw-r--r--testing/web-platform/tests/fenced-frame/revoke-popup.https.html47
7 files changed, 415 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fenced-frame/notify-event-iframe.https.html b/testing/web-platform/tests/fenced-frame/notify-event-iframe.https.html
new file mode 100644
index 0000000000..854db2f303
--- /dev/null
+++ b/testing/web-platform/tests/fenced-frame/notify-event-iframe.https.html
@@ -0,0 +1,102 @@
+<!DOCTYPE html>
+<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="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test fenced frame notifyEvent() functionality with iframes</title>
+
+<body>
+ <script>
+ async function runNestedIFrameTest(frame_type) {
+ // Create a fenced frame that will respond to window.fence.notifyEvent().
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.addEventListener('fencedtreeclick', () => notified = true);
+
+ await fencedframe.execute(async (frame_type) => {
+ window.addEventListener('message', (event) => {
+ window.click_error = event.data;
+ });
+
+ let iframe = null;
+ if (frame_type === 'same-origin') {
+ iframe = await attachIFrameContext({
+ origin: get_host_info().HTTPS_ORIGIN
+ });
+ } else if (frame_type === 'cross-origin') {
+ iframe = await attachIFrameContext({
+ origin: get_host_info().HTTPS_REMOTE_ORIGIN
+ });
+ }
+
+ // Calling notifyEvent() on click in the iframe should fail, but we need
+ // to move the exception out of the click handler to assert on it.
+ await iframe.execute(() => {
+ document.addEventListener('click', (e) => {
+ try {
+ window.fence.notifyEvent(e);
+ } catch (err) {
+ window.parent.postMessage(err, '*');
+ return;
+ }
+ window.parent.postMessage(new TypeError('No exception'), '*');
+ });
+ });
+ }, [frame_type]);
+
+ await multiClick(10, 10, fencedframe.element);
+
+ // Ensure the correct exception was thrown.
+ await fencedframe.execute(() => {
+ assert_equals(window.click_error.name, 'SecurityError');
+ assert_equals(window.click_error.message,
+ "Failed to execute 'notifyEvent' on 'Fence': notifyEvent is only available in fenced frame roots.");
+ });
+
+ // Because the notifyEvent() call failed, no event was sent to the
+ // top-level fenced frame.
+ assert_false(notified);
+ }
+
+ promise_test(async (t) => {
+ return runNestedIFrameTest('same-origin');
+ }, "Test that fenced frame notifyEvent() fails in a nested same-origin iframe.");
+
+ promise_test(async (t) => {
+ return runNestedIFrameTest('cross-origin');
+ }, "Test that fenced frame notifyEvent() fails in a nested cross-origin iframe.");
+
+ promise_test(async (t) => {
+ window.addEventListener('message', (event) => {
+ window.click_error = event.data;
+ });
+
+ const urn_iframe = await attachIFrameContext(
+ {generator_api: 'fledge'});
+
+ await urn_iframe.execute(() => {
+ document.addEventListener('click', (e) => {
+ try {
+ window.fence.notifyEvent(e);
+ } catch (err) {
+ window.parent.postMessage(err, '*');
+ return;
+ }
+ window.parent.postMessage(new TypeError('No exception'), '*');
+ });
+ });
+
+ await multiClick(10, 10, urn_iframe.element);
+
+ assert_equals(window.click_error.name, 'SecurityError');
+ assert_equals(window.click_error.message,
+ "Failed to execute 'notifyEvent' on 'Fence': notifyEvent is only available in fenced frame roots.");
+ }, "Test that notifyEvent() fails in a URN iframe.");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fenced-frame/notify-event-invalid.https.html b/testing/web-platform/tests/fenced-frame/notify-event-invalid.https.html
new file mode 100644
index 0000000000..7695f49e0b
--- /dev/null
+++ b/testing/web-platform/tests/fenced-frame/notify-event-invalid.https.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<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="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test that fenced frame notifyEvent() fails with invalid event parameters</title>
+
+<body>
+ <script>
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.addEventListener('fencedtreeclick', () => notified = true);
+
+ // Only "click" is supported for now, so any other type of event should
+ // fail to notify.
+ await fencedframe.execute(() => {
+ document.addEventListener('mousedown', (e) => {
+ try {
+ window.fence.notifyEvent(e);
+ } catch (err) {
+ window.click_error = err;
+ return;
+ }
+ window.click_error = new TypeError('No exception');
+ });
+ });
+
+ await multiClick(10, 10, fencedframe.element);
+
+ await fencedframe.execute(() => {
+ assert_equals(window.click_error.name, 'SecurityError');
+ assert_equals(window.click_error.message,
+ "Failed to execute 'notifyEvent' on 'Fence': notifyEvent called with an unsupported event type.");
+ });
+
+ assert_false(notified);
+ }, "Test that fenced frame notifyEvent() fails using the incorrect event type.");
+
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.addEventListener('fencedtreeclick', () => notified = true);
+
+ await fencedframe.execute(() => {
+ // Event objects constructed manually are not "trusted", so this event
+ // should fail to notify. "Trusted" means that the event was created by
+ // the user agent itself.
+ let fake_click = new Event('click');
+ try {
+ window.fence.notifyEvent(fake_click);
+ } catch (err) {
+ assert_equals(err.name, 'SecurityError');
+ assert_equals(err.message, "Failed to execute 'notifyEvent' on 'Fence': The triggering_event object is in an invalid state.");
+ return;
+ }
+ assert_unreached('An untrusted event must cause a SecurityError.');
+ });
+
+ assert_false(notified);
+ }, "Test that fenced frame notifyEvent() fails using an untrusted event.");
+
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.addEventListener('fencedtreemousedown', () => {
+ notified = true;
+ });
+
+ // This click handler should not trigger the above handler on the
+ // HTMLFencedFrameElement, because its type is not 'fencedtreeclick'.
+ await fencedframe.execute(() => {
+ document.addEventListener('click', (e) => {
+ window.fence.notifyEvent(e);
+ });
+ });
+
+ await multiClick(10, 10, fencedframe.element);
+
+ // Wait 2s to let any event handling code settle.
+ await new Promise((resolve) => t.step_timeout(
+ () => resolve(), 2000));
+
+ assert_false(notified);
+ }, "Test that fenced frame notifyEvent() only invokes 'fencedtreeclick'.");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fenced-frame/notify-event-nested-fenced-frames.https.html b/testing/web-platform/tests/fenced-frame/notify-event-nested-fenced-frames.https.html
new file mode 100644
index 0000000000..d435cbc009
--- /dev/null
+++ b/testing/web-platform/tests/fenced-frame/notify-event-nested-fenced-frames.https.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<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="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test that notifyEvent() in a nested fenced frame only notifies the immediate parent.</title>
+
+<body>
+ <script>
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext();
+ let topmost_notified = false;
+ fencedframe.element.addEventListener('fencedtreeclick', () => topmost_notified = true);
+
+ await fencedframe.execute(async () => {
+ const innerframe = await attachFencedFrameContext();
+ window.parent_notified = false;
+ innerframe.element.addEventListener('fencedtreeclick', () => window.parent_notified = true);
+
+ await innerframe.execute(() => {
+ document.addEventListener('click', (e) => {
+ window.fence.notifyEvent(e);
+ });
+ });
+ });
+
+ await multiClick(10, 10, fencedframe.element);
+
+ await fencedframe.execute(() => {
+ assert_true(window.parent_notified);
+ });
+
+ assert_false(topmost_notified);
+ }, "Test that notifyEvent() in a nested fenced frame only notifies the immediate parent.");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fenced-frame/notify-event-success.https.html b/testing/web-platform/tests/fenced-frame/notify-event-success.https.html
new file mode 100644
index 0000000000..76ed9abbfa
--- /dev/null
+++ b/testing/web-platform/tests/fenced-frame/notify-event-success.https.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<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="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test that fenced frame notifyEvent() succeeds on click</title>
+
+<body>
+ <script>
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.addEventListener('fencedtreeclick', () => notified = true);
+
+ // Add a click handler to the fenced frame's content, which will
+ // trigger the fenced handler registered above on the fencedframe
+ // element.
+ await fencedframe.execute(() => {
+ document.addEventListener('click', (e) => {
+ window.fence.notifyEvent(e);
+ });
+ });
+
+ await multiClick(10, 10, fencedframe.element);
+
+ assert_true(notified);
+ }, "Test that fenced frame notifyEvent() succeeds on click");
+
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.onfencedtreeclick = () => notified = true;
+
+ // Add a click handler to the fenced frame's content, which will
+ // trigger the fenced handler registered above on the fencedframe
+ // element.
+ await fencedframe.execute(() => {
+ document.addEventListener('click', (e) => {
+ window.fence.notifyEvent(e);
+ });
+ });
+
+ await multiClick(10, 10, fencedframe.element);
+
+ assert_true(notified);
+ }, "Test that fenced frame notifyEvent() succeeds on click when using the 'onfencedtreeclick' attribute.");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fenced-frame/notify-event-transient-user-activation.https.html b/testing/web-platform/tests/fenced-frame/notify-event-transient-user-activation.https.html
new file mode 100644
index 0000000000..ebf93940e5
--- /dev/null
+++ b/testing/web-platform/tests/fenced-frame/notify-event-transient-user-activation.https.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<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="/common/get-host-info.sub.js"></script>
+<script src="resources/utils.js"></script>
+<title>Test that fenced frame notifyEvent() requires transient activation</title>
+
+<body>
+ <script>
+ promise_test(async (t) => {
+ const fencedframe = await attachFencedFrameContext(
+ {generator_api: 'fledge'});
+ let notified = false;
+ fencedframe.element.addEventListener('fencedtreeclick', () => notified = true);
+
+ await fencedframe.execute(() => {
+ window.retained_activation = false;
+ document.addEventListener('click', async (e) => {
+ // Opening a new window consumes transient activation here, but that
+ // is *not explicitly stated in the spec.* However, we can't rely
+ // on other APIs to consume activation for us, since most of them are
+ // gated by permissions policies that fenced frames will not inherit.
+ // This call will just open a blank page, which is sufficient for
+ // this test.
+ window.open();
+ await new Promise((resolve) => t.step_timeout(
+ () => resolve(), 1000));
+ if (navigator.userActivation.isActive) {
+ window.retained_activation = true;
+ }
+ window.fence.notifyEvent(e);
+ });
+ });
+
+ await multiClick(10, 10, fencedframe.element);
+
+ // Wait 3s to let any event handling code settle.
+ await new Promise((resolve) => t.step_timeout(
+ () => resolve(), 3000));
+
+ await fencedframe.execute(() => {
+ assert_false(window.retained_activation);
+ });
+
+ assert_false(notified);
+ }, "Test that fenced frame notifyEvent() requires transient activation");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fenced-frame/resources/utils.js b/testing/web-platform/tests/fenced-frame/resources/utils.js
index cbea173f17..d6cca91437 100644
--- a/testing/web-platform/tests/fenced-frame/resources/utils.js
+++ b/testing/web-platform/tests/fenced-frame/resources/utils.js
@@ -250,6 +250,11 @@ function buildRemoteContextForObject(object, uuid, html) {
}
};
+ // If `object` is null (e.g. a window created with noopener), set it to a
+ // dummy value so that the Proxy constructor won't fail.
+ if (object == null) {
+ object = {};
+ }
const proxy = new Proxy(object, handler);
return proxy;
}
@@ -646,3 +651,19 @@ function setupCSP(csp, second_csp=null) {
document.head.appendChild(second_meta);
}
}
+
+// Clicking in WPT tends to be flaky (https://crbug.com/1066891), so you may
+// need to click multiple times to have an effect. This function clicks at
+// coordinates `{x, y}` relative to `click_origin`, by default 3 times. Should
+// not be used for tests where multiple clicks have distinct impact on the state
+// of the page, but rather to bruteforce through flakes that rely on only one
+// click.
+async function multiClick(x, y, click_origin, times = 3) {
+ for (let i = 0; i < times; i++) {
+ let actions = new test_driver.Actions();
+ await actions.pointerMove(x, y, {origin: click_origin})
+ .pointerDown()
+ .pointerUp()
+ .send();
+ }
+}
diff --git a/testing/web-platform/tests/fenced-frame/revoke-popup.https.html b/testing/web-platform/tests/fenced-frame/revoke-popup.https.html
new file mode 100644
index 0000000000..e4a2bb26ad
--- /dev/null
+++ b/testing/web-platform/tests/fenced-frame/revoke-popup.https.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>Test that window.fence.disableUntrustedNetwork disables
+ popup navigations.</title>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="resources/utils.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<body>
+<script>
+
+promise_test(async(t) => {
+ const fencedframe = await attachFencedFrameContext({generator_api: 'fledge'});
+ await fencedframe.execute(() => {});
+
+ const actions = new test_driver.Actions();
+ await actions.setContext(window)
+ .pointerMove(0, 0, {origin: fencedframe.element})
+ .pointerDown()
+ .pointerUp()
+ .send();
+
+ await fencedframe.execute(async () => {
+ await window.fence.disableUntrustedNetwork();
+ // After disabling network, popup navigations should not work.
+ assert_true(navigator.userActivation.isActive,
+ 'The frame should have user activation.');
+ window.popup = attachWindowContext();
+ });
+
+ const result = await Promise.race([
+ fencedframe.execute(async () => {
+ return await window.popup.execute(() => { return 'popup_loaded'; });
+ }),
+ new Promise((resolve) => t.step_timeout(
+ () => resolve('timeout'), 2000))
+ ]);
+ assert_equals(result, 'timeout');
+}, 'window.fence.disableUntrustedNetwork disables popup navigations');
+
+</script>
+</body>