summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/fullscreen/api
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/fullscreen/api')
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html27
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html35
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html69
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html47
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html46
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html54
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html28
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html47
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html19
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html37
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html63
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html30
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html37
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html17
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html26
-rw-r--r--testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html24
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-allowed.html33
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html31
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html40
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html25
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html32
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html23
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html42
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html26
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html43
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html40
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html97
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html61
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html26
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html49
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html24
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html25
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html143
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html24
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html37
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html28
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html24
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html28
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.html27
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html27
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html34
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html31
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html20
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html48
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html34
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html36
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html30
-rw-r--r--testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html19
-rw-r--r--testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html56
-rw-r--r--testing/web-platform/tests/fullscreen/api/historical.html38
-rw-r--r--testing/web-platform/tests/fullscreen/api/promises-reject.html22
-rw-r--r--testing/web-platform/tests/fullscreen/api/promises-resolve.html31
-rw-r--r--testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html48
-rw-r--r--testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html11
-rw-r--r--testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html86
-rw-r--r--testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html11
-rw-r--r--testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html47
57 files changed, 2163 insertions, 0 deletions
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html
new file mode 100644
index 0000000000..c96a56f352
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-active-document.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>
+ Document#exitFullscreen() when the document is not the active document
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<script>
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ const stolenTypeError = iframe.contentWindow.TypeError;
+ const documentBeforeNav = iframe.contentDocument;
+
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.src = "about:blank";
+ });
+
+ await promise_rejects_js(
+ t,
+ stolenTypeError,
+ documentBeforeNav.documentElement.requestFullscreen(),
+ "Promise should be undefined after navigation"
+ );
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html
new file mode 100644
index 0000000000..893814dec3
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-in-iframe.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Document#exitFullscreen() for nested fullscreen inside an iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<iframe allowfullscreen></iframe>
+<script>
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.srcdoc = "<div id='outer'><div id='inner'></div></div>";
+ });
+ const iframeDoc = iframe.contentDocument;
+ const outer = iframeDoc.getElementById("outer");
+ const inner = iframeDoc.getElementById("inner");
+
+ // First request fullscreen for the outer element.
+ await Promise.all([fullScreenChange(), trusted_request(outer)]);
+ assert_equals(document.fullscreenElement, iframe);
+ assert_equals(iframeDoc.fullscreenElement, outer);
+
+ // Then request fullscreen for the inner element.
+ await Promise.all([fullScreenChange(), trusted_request(inner)]);
+ assert_equals(document.fullscreenElement, iframe);
+ assert_equals(iframeDoc.fullscreenElement, inner);
+
+ // Now exit fullscreen for the iframe's content document.
+ await Promise.all([fullScreenChange(), iframeDoc.exitFullscreen()]);
+ assert_equals(document.fullscreenElement, null);
+ assert_equals(iframeDoc.fullscreenElement, null);
+ }, "Exit fullscreen for nested fullscreen inside an iframe");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html
new file mode 100644
index 0000000000..695ae00322
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested-shadow-dom.html
@@ -0,0 +1,69 @@
+<!doctype html>
+<title>Exiting fullscreen from a nested shadow root should work correctly.</title>
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1652155">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="host">
+ <button>
+ <!--
+ This is gross, but testdriver doesn't let us click stuff in shadow
+ DOM, so here we are instead, using nested slots.
+ -->
+ fullscreen
+ </button>
+</div>
+<script>
+promise_test(async function() {
+ let host = document.getElementById("host");
+ host.attachShadow({ mode: "open" }).innerHTML = `
+ <style>
+ #outer { width: 200px; height: 200px; background: blue }
+ </style>
+ <div id="outer">
+ <slot></slot>
+ </div>
+ `;
+
+ let outer = host.shadowRoot.getElementById("outer");
+ outer.attachShadow({ mode: "open" }).innerHTML = `
+ <style>
+ #inner { width: 100px; height: 100px; background: purple }
+ </style>
+ <div id="inner"></div>
+ <slot></slot>
+ `;
+
+ let button = document.querySelector("button");
+
+ let inner = outer.shadowRoot.getElementById("inner");
+ let finished = new Promise(resolve => {
+ button.addEventListener("click", async function() {
+ await outer.requestFullscreen();
+ assert_equals(outer.getRootNode().fullscreenElement, outer);
+ assert_equals(document.fullscreenElement, host);
+
+ button.addEventListener("click", async function() {
+ await inner.requestFullscreen();
+ assert_equals(inner.getRootNode().fullscreenElement, inner);
+ assert_equals(document.fullscreenElement, host);
+ await document.exitFullscreen();
+ assert_equals(inner.getRootNode().fullscreenElement, null);
+ assert_equals(outer.getRootNode().fullscreenElement, outer);
+ assert_equals(document.fullscreenElement, host);
+ resolve();
+ }, { once: true });
+
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ test_driver.click(button);
+ }));
+ }, { once: true });
+ });
+
+ test_driver.click(button);
+ await finished;
+}, "Exiting fullscreen from a nested shadow root works correctly.");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html
new file mode 100644
index 0000000000..37332b9b8f
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-nested.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>Document#exitFullscreen() for nested fullscreen</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div><div></div></div>
+<script>
+ promise_test(async (t) => {
+ const outer = document.querySelector("div");
+ const inner = outer.firstChild;
+
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+
+ // First request fullscreen for the outer element.
+ await Promise.all([
+ fullScreenChange(),
+ trusted_request(outer),
+ ]);
+
+ assert_equals(document.fullscreenElement, outer);
+
+ // Then request fullscreen for the inner element.
+ const p = trusted_request(inner);
+
+ // Even though we are already in fullscreen, the change in
+ // document.fullscreenElement should not happen synchronously.
+ assert_equals(document.fullscreenElement, outer);
+ await Promise.all([
+ fullScreenChange(),
+ p,
+ ]);
+ assert_equals(document.fullscreenElement, inner);
+
+ // Now exit fullscreen.
+ const exitP = document.exitFullscreen();
+ // Even though we don't need to exit fullscreen, the change in
+ // document.fullscreenElement should not happen synchronously.
+ assert_equals(document.fullscreenElement, inner);
+ await Promise.all([
+ exitP,
+ fullScreenChange(),
+ ]);
+ assert_equals(document.fullscreenElement, outer);
+ }, "Exit fullscreen for nested fullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html
new file mode 100644
index 0000000000..43e01743b9
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-timing.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Document#exitFullscreen() timing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ const div = document.querySelector("div");
+ await trusted_request(div);
+
+ await Promise.all([
+ new Promise((r) => (document.onfullscreenchange = r)),
+ document.exitFullscreen(),
+ ]);
+
+ // If fullscreenchange is an animation frame event, then animation frame
+ // callbacks should be run after it is fired, before the timer callback.
+ // The resize event should fire before the fullscreenchange event.
+ const events = [];
+ const callback = t.step_func((event) => {
+ // fullscreenElement should have changed before either event is fired.
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ `fullscreenElement in ${event.type} event`
+ );
+ events.push(event.type);
+ if (event.type == "fullscreenchange") {
+ step_timeout(t.unreached_func("timer callback"));
+ requestAnimationFrame(
+ t.step_func_done(() => {
+ assert_array_equals(
+ events,
+ ["resize", "fullscreenchange"],
+ "event order"
+ );
+ })
+ );
+ }
+ });
+ document.onfullscreenchange = window.onresize = callback;
+ }, "Timing of fullscreenchange and resize events");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html
new file mode 100644
index 0000000000..aa8538cce4
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen-twice.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Document#exitFullscreen() called twice</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ const once = { once: true };
+ const div = document.querySelector("div");
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+
+ await Promise.all([
+ fullScreenChange(),
+ trusted_request(div),
+ ]);
+
+ // We are now in fullscreen.
+ assert_equals(document.fullscreenElement, div);
+
+ // Exit fullscreen twice.
+ const firstPromise = document.exitFullscreen();
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement after first exitFullscreen()"
+ );
+
+ const secondPromise = document.exitFullscreen();
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement after second exitFullscreen()"
+ );
+ const eventChange = new Promise((resolve) => {
+ document.addEventListener("fullscreenchange", resolve, once);
+ document.addEventListener(
+ "fullscreenchange",
+ t.unreached_func("second event fired"),
+ once
+ );
+ });
+
+ await Promise.all([
+ fullScreenChange,
+ firstPromise,
+ secondPromise,
+ eventChange,
+ ]);
+ assert_equals(document.fullscreenElement, null);
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html
new file mode 100644
index 0000000000..666950ff55
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-exit-fullscreen.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Document#exitFullscreen()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<body></body>
+<script>
+ promise_test(async function (t) {
+ const div = document.querySelector("div");
+ // enter fullscreen
+ await trusted_request(div);
+
+ // Exit fullscreen
+ const [event] = await Promise.all([
+ fullScreenChange(),
+ document.exitFullscreen(),
+ ]);
+
+ // Check event from exiting fullscreen
+ assert_equals(event.target, div, "event.target");
+ assert_true(event.bubbles, "event.bubbles");
+ assert_false(event.cancelable, "event.cancelable");
+ assert_true(event.composed, "event.composed");
+ }, "Checks that the fullscreenchange event is fired when exiting fullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html
new file mode 100644
index 0000000000..8b3a16a2a8
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-element.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<title>Document#fullscreenElement</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async function (t) {
+ const div = document.querySelector("div");
+
+ await trusted_click();
+
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "fullscreenElement before requestFullscreen()"
+ );
+
+ const fsPromise = div.requestFullscreen();
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "fullscreenElement after requestFullscreen()"
+ );
+ await fsPromise;
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement before exitFullscreen()"
+ );
+ const exitPromise = document.exitFullscreen();
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement after exitFullscreen()"
+ );
+ await Promise.all([fullScreenChange(), exitPromise]);
+
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "fullscreenElement after exiting fullscreen"
+ );
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html
new file mode 100644
index 0000000000..360982c4a5
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-active-document.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>
+ Document#fullscreenEnabled when the document is not the active document
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<script>
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ const documentBeforeNav = iframe.contentDocument;
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.src = "/common/blank.html";
+ });
+ assert_false(documentBeforeNav.fullscreenEnabled)
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html
new file mode 100644
index 0000000000..bcfc98bbca
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-cross-origin.sub.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Document#fullscreenEnabled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe src="resources/report-fullscreen-enabled.html" name="same-origin-default"></iframe>
+<iframe src="resources/report-fullscreen-enabled.html" allowfullscreen name="same-origin-allow"></iframe>
+<iframe src="http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/report-fullscreen-enabled.html" name="cross-origin-default"></iframe>
+<iframe src="http://{{hosts[][]}}:{{ports[http][1]}}/fullscreen/api/resources/report-fullscreen-enabled.html" allowfullscreen name="cross-origin-allow"></iframe>
+<script>
+var expectations = {
+ "same-origin-default": true,
+ "same-origin-allow": true,
+ "cross-origin-default": false,
+ "cross-origin-allow": true
+};
+
+var tests = {};
+for (var name in expectations) {
+ tests[name] = async_test( 'Fullscreen enabled test: ' + name);
+}
+
+// When a message is received from a child frame, ensure that the report
+// matches the expectations.
+window.addEventListener('message', e => {
+ if (e.data.report && e.data.report.api == "fullscreen") {
+ if (e.data.report.frame in expectations) {
+ tests[e.data.report.frame].step(() => {
+ assert_equals(e.data.report.enabled, expectations[e.data.report.frame],
+ e.data.report.frame + " frame fullscreenEnabled");
+ });
+ delete expectations[e.data.report.frame];
+ tests[e.data.report.frame].done();
+ }
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html
new file mode 100644
index 0000000000..687a4ff1e4
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-removing-allowfullscreen.sub.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<title>
+ Document#fullscreenEnabled removing allowfullscreen after load and then
+ navigating
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe></iframe>
+<script>
+ function requestStatus(iframe) {
+ iframe.contentWindow.postMessage(
+ "What is document.fullscreenEnabled?",
+ "*"
+ );
+ return new Promise((resolve) => {
+ window.addEventListener("message", function listener(e) {
+ window.removeEventListener("message", listener);
+ resolve(event.data);
+ });
+ });
+ }
+
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ iframe.allowFullscreen = true;
+ assert_true(iframe.allowFullscreen, "allowFullscreen is false");
+ assert_true(
+ iframe.hasAttribute("allowfullscreen"),
+ "allowFullscreen attribute is present"
+ );
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ const path = location.pathname.substring(
+ 0,
+ location.pathname.lastIndexOf("/") + 1
+ );
+ iframe.src = `http://{{hosts[][]}}:{{ports[http][0]}}${path}resources/echo-fullscreenEnabled.html`;
+ });
+
+ assert_true(
+ await requestStatus(iframe),
+ "document.fullscreenEnabled in the iframe, before navigation"
+ );
+
+ iframe.allowFullscreen = false;
+ assert_false(iframe.allowFullscreen, "allowFullscreen is false");
+ assert_false(
+ iframe.hasAttribute("allowfullscreen"),
+ "allowFullscreen attribute is not present"
+ );
+
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.contentWindow.location.href = iframe.src + "?2";
+ });
+
+ assert_false(
+ await requestStatus(iframe),
+ "document.fullscreenEnabled in the iframe, after navigation"
+ );
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html
new file mode 100644
index 0000000000..49d91c8501
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen-timing.sub.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Document#fullscreenEnabled setting allowfullscreen after document creation, before response</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+// Set allowfullscreen attribute in a timeout after <iframe> has been inserted to the document.
+// The iframe's response is delayed so it happens after the attribute is set.
+
+async_test((t) => {
+ const iframe = document.createElement('iframe');
+ // no allowfullscreen attribute
+
+ const path = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1);
+ iframe.src = "http://{{hosts[][]}}:{{ports[http][0]}}" + path + "resources/echo-fullscreenEnabled.html?pipe=trickle(d1)";
+ iframe.onload = t.step_func(() => {
+ iframe.contentWindow.postMessage('What is document.fullscreenEnabled?', '*');
+ });
+
+ window.onmessage = t.step_func_done((e) => {
+ assert_false(e.data, 'document.fullscreenEnabled in the iframe');
+ });
+
+ document.body.appendChild(iframe);
+
+ t.step_timeout(() => {
+ iframe.allowFullscreen = true;
+ }, 10);
+});
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html
new file mode 100644
index 0000000000..4894fa0663
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled-setting-allowfullscreen.sub.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Document#fullscreenEnabled setting allowfullscreen after load and then navigating</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+async_test((t) => {
+ const iframe = document.createElement('iframe');
+ // no allowfullscreen attribute
+
+ let i = 0;
+
+ const path = location.pathname.substring(0, location.pathname.lastIndexOf('/') + 1);
+ iframe.src = "http://{{hosts[][]}}:{{ports[http][0]}}" + path + "resources/echo-fullscreenEnabled.html";
+ iframe.onload = t.step_func(() => {
+ if (i === 0) {
+ iframe.allowFullscreen = true;
+ }
+ iframe.contentWindow.postMessage('What is document.fullscreenEnabled?', '*');
+ });
+
+ window.onmessage = t.step_func((e) => {
+ i++;
+ if (i === 1) {
+ assert_false(e.data, 'document.fullscreenEnabled in the iframe, before navigation');
+
+ // Navigate the iframe. This will fire a second 'load' event on the iframe.
+ iframe.contentWindow.location.href = iframe.src + '?2';
+ } else {
+ assert_true(e.data, 'document.fullscreenEnabled in the iframe, after navigation');
+ t.done();
+ }
+ });
+
+ document.body.appendChild(iframe);
+});
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html
new file mode 100644
index 0000000000..40430d7bbf
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-fullscreen-enabled.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Document#fullscreenEnabled</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe></iframe>
+<script>
+test(function()
+{
+ assert_true(document.fullscreenEnabled, "top-level document");
+ const iframe = document.querySelector("iframe");
+ assert_true(iframe.contentDocument.fullscreenEnabled, "same-origin iframe");
+});
+
+// The cross-origin iframe case is tested in
+// /html/semantics/embedded-content/the-iframe-element/iframe-allowfullscreen.html
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html b/testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html
new file mode 100644
index 0000000000..10503c6ccb
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-onfullscreenchange.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Document#onfullscreenchange</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ const div = document.querySelector("div");
+ assert_equals(
+ document.onfullscreenchange,
+ null,
+ "initial onfullscreenchange"
+ );
+ const [, event] = await Promise.all([
+ trusted_request(div),
+ new Promise((r) =>
+ document.addEventListener("fullscreenchange", r)
+ ),
+ ]);
+ assert_true(event instanceof Event);
+ assert_equals(event.target, div);
+ }, "Checks that the fullscreenchange event is fired when entering fullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html b/testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html
new file mode 100644
index 0000000000..ac92a9c24b
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/document-onfullscreenerror.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Document#onfullscreenerror</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ assert_equals(
+ document.onfullscreenerror,
+ null,
+ "initial onfullscreenerror"
+ );
+ const [, event] = await Promise.all([
+ promise_rejects_js(
+ t,
+ TypeError,
+ document.documentElement.requestFullscreen()
+ ),
+ new Promise((r) => document.addEventListener("fullscreenerror", r)),
+ ]);
+ assert_equals(event.target, document.documentElement);
+ assert_true(event instanceof Event);
+ }, "Checks that the fullscreenerror event is fired when entering fullscreen fails");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-allowed.html b/testing/web-platform/tests/fullscreen/api/element-ready-allowed.html
new file mode 100644
index 0000000000..79890fa82f
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-allowed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Element ready check with enabled flag not set</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe></iframe>
+<script>
+ promise_test(async function (t) {
+ const iframe = document.querySelector("iframe");
+ await new Promise((r) => {
+ iframe.onload = r;
+ iframe.src = "about:blank";
+ });
+ document.onfullscreenchange = t.unreached_func(
+ "document fullscreenchange event"
+ );
+ document.onfullscreenerror = t.unreached_func(
+ "document fullscreenerror event"
+ );
+ iframe.contentDocument.onfullscreenchange = t.unreached_func(
+ "iframe fullscreenchange event"
+ );
+ assert_false(iframe.allowFullscreen, "fullscreen enabled flag");
+ assert_true(
+ iframe.contentDocument.fullscreenEnabled,
+ "fullscreen enabled flag"
+ );
+ return trusted_request(iframe.contentDocument.body, document.body);
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html
new file mode 100644
index 0000000000..9c93ed006b
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-allowed-cross-origin.sub.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Element ready check with allowfullscreen attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<iframe name="cross-origin-allowed" allowfullscreen></iframe>
+<script>
+ promise_test(async (t) => {
+ // Trigger the child frame to report as soon as its content is loaded.
+ const iframe = document.querySelector("iframe");
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.src =
+ "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/attempt-fullscreen.html";
+ });
+
+ // Activate the child frame.
+ await test_driver.click(iframe);
+
+ // When a message is received from a child frame, ensure that the report
+ // matches the expectations.
+ const messagePromise = promiseMessage(iframe);
+ const data = await messagePromise;
+ assert_true(
+ data.report.result,
+ `${data.report.frame} frame did enter fullscreen`
+ );
+ }, "Element ready check with allowfullscreen attribute");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html
new file mode 100644
index 0000000000..8d55aea563
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-containing-iframe.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>Element ready check for containing iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<iframe allowfullscreen></iframe>
+<script>
+ // wait for load event to avoid https://bugzil.la/1493878
+ window.onload = function () {
+ promise_test(async function (t) {
+ const [iframe1, iframe2] = document.getElementsByTagName("iframe");
+
+ iframe2.contentDocument.onfullscreenerror = t.unreached_func(
+ "fullscreenerror event"
+ );
+
+ await Promise.all([
+ trusted_request(
+ iframe1.contentDocument.body,
+ iframe1.contentDocument.body
+ ),
+ fullScreenChange(),
+ ]);
+
+ assert_equals(document.fullscreenElement, iframe1);
+
+ await Promise.all([
+ trusted_request(
+ iframe2.contentDocument.body,
+ iframe1.contentDocument.body
+ ),
+ fullScreenChange(iframe2.contentDocument),
+ ]);
+ }, "Element ready check for containing iframe");
+ };
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html
new file mode 100644
index 0000000000..6394c13ee3
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-element-sibling.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Element ready check for sibling of fullscreen element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="a"></div>
+<div id="b"></div>
+<script>
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func(
+ "second fullscreenchange event"
+ );
+ const a = document.getElementById("a");
+ const b = document.getElementById("b");
+ await Promise.all([trusted_request(a), fullScreenChange()]);
+
+ assert_equals(document.fullscreenElement, a, "fullscreen element is a");
+
+ await Promise.all([trusted_request(b, a), fullScreenChange()]);
+ assert_equals(document.fullscreenElement, b, "fullscreen element is b");
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html
new file mode 100644
index 0000000000..77aad41e7d
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-fullscreen-iframe-child.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Element ready check for child of a fullscreen iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe><!-- script inserts div here --></iframe>
+<script>
+ // Verify that an iframe can itself go fullscreen, and that this doesn't
+ // influence the iframe ancestor test of the element ready check.
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+ const iframe = document.querySelector("iframe");
+ await Promise.all([trusted_request(iframe), fullScreenChange()]);
+
+ assert_equals(document.fullscreenElement, iframe, "fullscreen element");
+
+ // This adds the div to the iframe element itself, not to the iframe's
+ // contentDocument. It's done here because the HTML parser treats the
+ // content of iframe as a text node.
+ var div = document.createElement("div");
+ iframe.appendChild(div);
+
+ await Promise.all([
+ trusted_request(div, iframe.contentDocument.body),
+ fullScreenChange(),
+ ]);
+ assert_equals(document.fullscreenElement, div);
+ }, "Element ready check for child of a fullscreen iframe");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html
new file mode 100644
index 0000000000..9b9d06ad75
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-iframe-child.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Element ready check for child of iframe</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe><!-- script inserts child here --></iframe>
+<script>
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+ const div = document.createElement("div");
+ document.querySelector("iframe").appendChild(div);
+
+ await Promise.all([
+ trusted_request(div, document.body),
+ fullScreenChange(),
+ ]);
+
+ assert_equals(document.fullscreenElement, div);
+ }, "Element ready check for child of iframe");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html
new file mode 100644
index 0000000000..a59906ba9f
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-allowed-cross-origin.sub.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<title>Element ready check with no allowfullscreen attribute</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<body>
+ <iframe name="cross-origin-default"></iframe>
+</body>
+
+<script>
+ // Allow the time bomb to be triggered.
+ setup({ allow_uncaught_exception: true });
+
+ promise_test(async (t) => {
+ t.add_cleanup(() => {
+ if (document.fullscreenElement) return document.exitFullscreen();
+ });
+ const iframe = document.querySelector("iframe");
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.src =
+ "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/attempt-fullscreen.html";
+ });
+ // Trigger the child frame to report as soon as its content is loaded.
+ await trusted_click();
+ const timeBomb = new Promise((resolve, reject) => {
+ t.step_timeout(() => {
+ const error = new Error("Timed out waiting for message");
+ reject(error);
+ }, 5000);
+ });
+ const data = await Promise.race([promiseMessage(iframe), timeBomb]);
+ // When a message is received from a child frame, ensure that the report
+ // matches the expectations.
+ assert_false(
+ data.report.result,
+ `${data.report.frame} frame entered fullscreen, but allowfullscreen was not set`
+ );
+ }, "Cross-origin element ready check with no allowfullscreen or allow attribute");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html
new file mode 100644
index 0000000000..210ccc2ace
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-ready-check-not-in-document.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Element ready check for element not in a document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async function (t) {
+ const div = document.createElement("div");
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ await Promise.all([
+ promise_rejects_js(
+ t,
+ TypeError,
+ trusted_request(div, document.body)
+ ),
+ new Promise((resolve) => {
+ document.onfullscreenerror = resolve;
+ }),
+ ]);
+ }, "Element ready check for element not in a document");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html
new file mode 100644
index 0000000000..bac8631059
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-active-document.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() when the document is not the active document
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<script>
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ const typeErrorConstructor = iframe.contentWindow.TypeError;
+ const documentBeforeNav = iframe.contentDocument;
+
+ documentBeforeNav.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ documentBeforeNav.onfullscreenerror = t.unreached_func(
+ "fullscreenerror event"
+ );
+
+ await new Promise((r) => {
+ iframe.src = "/common/blank.html";
+ iframe.onload = r;
+ });
+
+ await promise_rejects_js(
+ t,
+ typeErrorConstructor,
+ documentBeforeNav.documentElement.requestFullscreen()
+ );
+
+ // Per spec the fullscreenerror event should be fired at the next animation
+ // frame, but at least Gecko and WebKit will instead effectively do "queue a
+ // task to fire ...". Use both rAF and setTimeout to fail even if the timing
+ // of the (unexpected) event isn't as expected.
+ await new Promise((resolve) => {
+ requestAnimationFrame(() => {
+ t.step_timeout(resolve);
+ });
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html
new file mode 100644
index 0000000000..4278382770
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-after-error.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() after error</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="log"></div>
+<script>
+promise_test(async t => {
+ await new Promise(r => window.onload = r);
+
+ const element1 = document.createElement("div");
+ document.body.appendChild(element1);
+
+ await test_driver.bless("request full screen");
+ let promise = element1.requestFullscreen()
+ await new Promise(r => t.step_timeout(r, 0))
+ document.body.removeChild(element1);
+ try {
+ await promise;
+ assert_unreached("requestFullscreen shouldn't be successful");
+ } catch (e) {
+ }
+ try {
+ await document.exitFullscreen();
+ } catch (e) {
+ }
+
+ const element2 = document.createElement("div");
+ document.body.appendChild(element2);
+
+ await test_driver.bless("request full screen");
+ try {
+ await element2.requestFullscreen();
+ } catch (e) {
+ assert_unreached("requestFullscreen shouldn't throw an error - " + e.message);
+ }
+ await document.exitFullscreen();
+}, "requestFullscreen works even if previous requestFullscreen causes an error");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html
new file mode 100644
index 0000000000..f0bf5f6bac
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-exit-iframe.html
@@ -0,0 +1,97 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() and Document#exitFullscreen() in iframe
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<script>
+ const iframe = document.querySelector("iframe");
+ let iframeDoc;
+ let iframeBody;
+
+ promise_setup(async () => {
+ const iframe = document.querySelector("iframe");
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.src = "about:blank";
+ });
+ iframeDoc = iframe.contentDocument;
+ iframeBody = iframeDoc.body;
+ });
+ /**
+ *
+ * @param {Document} doc
+ * @param {HTMLElement} value
+ * @returns {Promise<Event>}
+ */
+ function makeChangeListener(doc) {
+ return new Promise((resolve) => {
+ doc.addEventListener("fullscreenchange", resolve, { once: true });
+ });
+ }
+
+ // Both when entering and exiting, the fullscreenchange event is fired first
+ // on the outer document and then on the iframe's document. This is because
+ // the events are fired in animation frame tasks, which run in "frame tree"
+ // order.
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func(
+ "document fullscreenerror event"
+ );
+ iframeDoc.onfullscreenerror = t.unreached_func(
+ "iframe fullscreenerror event"
+ );
+ const outerPromise = makeChangeListener(document);
+ const innerPromise = makeChangeListener(iframeDoc);
+ const request = trusted_request(iframeBody, iframeBody);
+
+ const winningEvent = await Promise.race([outerPromise, innerPromise]);
+ assert_equals(winningEvent.target, iframe);
+
+ await Promise.allSettled([outerPromise, innerPromise, request]);
+
+ assert_equals(
+ document.fullscreenElement,
+ iframe,
+ "outer fullscreenElement"
+ );
+
+ assert_equals(
+ iframeDoc.fullscreenElement,
+ iframeBody,
+ "inner fullscreenElement"
+ );
+ }, "Checks that the fullscreenchange events fire in right order when entering fullscreen");
+
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func(
+ "document fullscreenerror event"
+ );
+ iframeDoc.onfullscreenerror = t.unreached_func(
+ "iframe fullscreenerror event"
+ );
+ const outerPromise = makeChangeListener(document);
+ const innerPromise = makeChangeListener(iframeDoc);
+ const exitPromise = iframeDoc.exitFullscreen();
+
+ const winningEvent = await Promise.race([outerPromise, innerPromise]);
+ assert_equals(winningEvent.target, iframe);
+
+ await Promise.allSettled([outerPromise, innerPromise, exitPromise]);
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "outer fullscreenElement"
+ );
+ assert_equals(
+ iframeDoc.fullscreenElement,
+ null,
+ "inner fullscreenElement"
+ );
+ }, "Checks that the fullscreenchange events fire in right order when exiting fullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html
new file mode 100644
index 0000000000..f758835012
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move-to-iframe.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() followed by moving the element into an iframe
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="target"></div>
+<iframe allowfullscreen></iframe>
+<script>
+ // rfsPromise will be uncaught
+ setup({ allow_uncaught_exception: true });
+
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ await new Promise((r) => {
+ iframe.onload = r;
+ iframe.src = "about:blank";
+ });
+ const target = document.getElementById("target");
+ const iframeDoc = iframe.contentDocument;
+
+ iframeDoc.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event in iframe"
+ );
+ iframeDoc.onfullscreenerror = t.unreached_func(
+ "fullscreenerror event in iframe"
+ );
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+
+ const errorPromise = new Promise(
+ (resolve) => (document.onfullscreenerror = resolve)
+ );
+ await trusted_click(document.body);
+ const rfsPromise = target.requestFullscreen();
+ iframeDoc.body.appendChild(target);
+ const event = await errorPromise;
+ assert_equals(
+ iframeDoc.fullscreenElement,
+ null,
+ "inner fullscreen element"
+ );
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "outer fullscreen element"
+ );
+ assert_equals(event.target, document, "event target");
+ await promise_rejects_js(
+ t,
+ TypeError,
+ rfsPromise,
+ "requestFullscreen promise"
+ );
+ }, "Element#requestFullscreen() followed by moving the element into an iframe");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html
new file mode 100644
index 0000000000..f031461ce5
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-move.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() followed by moving the element within the
+ document
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="target"></div>
+<div id="moveto"></div>
+<script>
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+ const target = document.getElementById("target");
+ const moveTo = document.getElementById("moveto");
+ await trusted_click(document.body);
+ const p = target.requestFullscreen();
+ moveTo.appendChild(target);
+ await Promise.all([p, fullScreenChange()]);
+ assert_equals(document.fullscreenElement, target);
+ assert_equals(target.parentNode, moveTo);
+ }, "Element#requestFullscreen() followed by moving the element within the document");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html
new file mode 100644
index 0000000000..991799a48d
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove-iframe.html
@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() in iframe followed by removing the iframe
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<iframe allowfullscreen></iframe>
+<script>
+ promise_test(async (t) => {
+ const iframe = document.querySelector("iframe");
+ await new Promise((resolve) => {
+ iframe.onload = resolve;
+ iframe.src = "about:blank";
+ });
+
+ const iframeDocument = iframe.contentDocument;
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+ iframeDocument.onfullscreenchange = t.unreached_func(
+ "iframe fullscreenchange event"
+ );
+ iframeDocument.onfullscreenerror = t.unreached_func(
+ "iframe fullscreenerror event"
+ );
+ await trusted_click(document.body);
+ const p = iframeDocument.body.requestFullscreen();
+ const typeErrorConstructor = iframe.contentWindow.TypeError;
+ iframe.remove();
+ // Prevent the tests from hanging if the promise never rejects.
+ const errorPromise = new Promise((_, reject) =>
+ t.step_timeout(() => {
+ assert_unreached("Promise didn't reject.");
+ reject(new Error("Promise didn't reject."));
+ }, 1000)
+ );
+ await Promise.race([
+ promise_rejects_js(t, typeErrorConstructor, p),
+ errorPromise,
+ ]);
+ assert_equals(document.fullscreenElement, null);
+ assert_equals(iframeDocument.fullscreenElement, null);
+ }, "requestFullscreen() in iframe followed by removing the iframe");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html
new file mode 100644
index 0000000000..436a61b6e1
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-and-remove.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() followed by removing the element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="target"></div>
+<script>
+ promise_test(async (t) => {
+ const target = document.getElementById("target");
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ const errorEventPromise = new Promise(
+ (resolve) => (document.onfullscreenerror = resolve)
+ );
+ await trusted_click(document.body);
+ const p = target.requestFullscreen();
+ target.remove();
+ Promise.all([promise_rejects_js(t, TypeError, p), errorEventPromise]);
+ }, "requestFullscreen() followed by removing the element");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html
new file mode 100644
index 0000000000..cc4806711d
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-consume-user-activation.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() consumes user activation</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="log"></div>
+<script>
+promise_test(async (t) => {
+ t.add_cleanup(() => {
+ if (document.fullscreenElement) return document.exitFullscreen();
+ });
+ const div = document.querySelector("div");
+
+ await test_driver.bless("fullscreen");
+ assert_true(navigator.userActivation.isActive, "Activation must be active");
+ // Request fullscreen twice in a row. The first request should consume the
+ // user activation and succeed, and the second request should fail because
+ // of the user activation requirement.
+ const p1 = div.requestFullscreen();
+ assert_false(navigator.userActivation.isActive, "Transient activation is consumed");
+ const p2 = promise_rejects_js(t, TypeError, div.requestFullscreen());
+ await Promise.all([p1, p2]);
+});
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html
new file mode 100644
index 0000000000..5f3a397bbc
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-cross-origin.sub.html
@@ -0,0 +1,143 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() works properly with a tree of cross-origin iframes
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<body>
+ <script>
+ function waitFor(action, frameName) {
+ return new Promise((resolve) => {
+ window.addEventListener("message", function listener(e) {
+ if (e.data.action === action && e.data.name === frameName) {
+ window.removeEventListener("message", listener);
+ resolve(event.data);
+ }
+ });
+ });
+ }
+
+ function compare_report(report, expectedEvents) {
+ assert_equals(
+ report.events.length,
+ expectedEvents.length,
+ `Expected report for iframe "${report.frame}" to have ${expectedEvents.length} events: [${expectedEvents}]`
+ );
+ report.events.forEach((value, i) => {
+ assert_equals(
+ value,
+ expectedEvents[i],
+ "Event type matches in order expected"
+ );
+ });
+
+ report.events.length
+ ? assert_false(
+ report.fullscreenElementIsNull,
+ "Event fired, fullscreenElement is set"
+ )
+ : assert_true(
+ report.fullscreenElementIsNull,
+ "No event fired, fullscreenElement is null"
+ );
+ }
+
+ const iframes = [
+ {
+ name: "A",
+ src: "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?a",
+ allow_fullscreen: true,
+ expectedEvents: ["fullscreenchange"],
+ },
+ {
+ name: "B",
+ src: "http://{{hosts[][]}}:{{ports[http][1]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?b",
+ allow_fullscreen: true,
+ expectedEvents: ["fullscreenchange"],
+ },
+ {
+ name: "C",
+ src: "http://{{hosts[alt][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?c",
+ allow_fullscreen: true,
+ expectedEvents: ["fullscreenchange"],
+ },
+ {
+ name: "D",
+ src: "http://{{hosts[alt][]}}:{{ports[http][1]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?d",
+ allow_fullscreen: true,
+ expectedEvents: ["fullscreenchange"],
+ },
+ {
+ name: "E",
+ src: "http://{{hosts[][]}}:{{ports[http][0]}}/fullscreen/api/resources/recursive-iframe-fullscreen.html?e",
+ allow_fullscreen: true,
+ expectedEvents: [],
+ },
+ ];
+
+ promise_setup(async () => {
+ // Add the first iframe.
+ const iframeDetails = iframes[0];
+ const child_frame = document.createElement("iframe");
+ child_frame.allow = iframeDetails.allow_fullscreen ? "fullscreen" : "";
+ child_frame.name = iframeDetails.name;
+ child_frame.style.width = "100%";
+ child_frame.style.height = "100%";
+ child_frame.src = iframeDetails.src;
+ await new Promise((resolve) => {
+ child_frame.onload = resolve;
+ document.body.appendChild(child_frame);
+ });
+
+ // Create the nested iframes.
+ for (let i = 1; i < iframes.length; i++) {
+ const parentName = iframes[i - 1].name;
+ const details = iframes[i];
+ child_frame.contentWindow.postMessage(
+ { action: "addIframe", iframe: details, name: parentName },
+ "*"
+ );
+ await waitFor("load", details.name);
+ }
+ });
+
+ promise_test(async (t) => {
+ t.add_cleanup(() => {
+ if (document.fullscreenElement) {
+ return document.exitFullscreen();
+ }
+ });
+ document.onfullscreenerror = t.unreached_func(
+ "fullscreenerror event fired"
+ );
+ const fsChangeFiredPromise = new Promise((resolve) => {
+ document.onfullscreenchange = resolve;
+ });
+
+ const child_frame = document.querySelector("iframe[name=A]");
+ child_frame.contentWindow.postMessage(
+ {
+ action: "requestFullscreen",
+ name: "D",
+ },
+ "*"
+ );
+
+ await waitFor("requestFullscreen", "D");
+
+ for (const frame of iframes.slice(1)) {
+ const data = {
+ action: "requestReport",
+ name: frame.name,
+ };
+ child_frame.contentWindow.postMessage(data, "*");
+ const { report } = await waitFor("report", frame.name);
+ compare_report(report, frame.expectedEvents);
+ }
+ await fsChangeFiredPromise;
+ }, "Element#requestFullscreen() works properly with a tree of cross-origin iframes");
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html
new file mode 100644
index 0000000000..ee5e21306a
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-dialog.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() for dialog element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="log"></div>
+<dialog></dialog>
+<script>
+ promise_test(async (t) => {
+ const dialog = document.querySelector("dialog");
+ assert_true(dialog instanceof HTMLDialogElement);
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ const errorEventPromise = new Promise(
+ (resolve) => (document.onfullscreenerror = resolve)
+ );
+ Promise.all([
+ promise_rejects_js(t, TypeError, dialog.requestFullscreen()),
+ errorEventPromise,
+ ]);
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html
new file mode 100644
index 0000000000..dffa8dbc90
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-namespaces.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() for an element in null namespace</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ const supportedNS = [
+ { ns: "http://www.w3.org/1999/xhtml", elemName: "div" },
+ { ns: "http://www.w3.org/2000/svg", elemName: "svg" },
+ { ns: "http://www.w3.org/1998/Math/MathML", elemName: "math" },
+ ];
+
+ const unsupportedNS = [null, "https://unknown.namespace", ""];
+
+ for (const ns of unsupportedNS) {
+ promise_test(async (t) => {
+ const element = document.createElementNS(ns, "element");
+ document.body.appendChild(element);
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ await promise_rejects_js(t, TypeError, trusted_request(element));
+ }, `requestFullscreen() fails for an element in ${ns} namespace`);
+ }
+
+ for (const { ns, elemName } of supportedNS) {
+ promise_test(async (t) => {
+ const element = document.createElementNS(ns, elemName);
+ document.body.appendChild(element);
+ await Promise.all([trusted_request(element), fullScreenChange()]);
+ await document.exitFullscreen();
+ }, `requestFullscreen() succeed for an element in ${ns} namespace`);
+ }
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html
new file mode 100644
index 0000000000..9bed70d695
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-non-top.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() for non-top element in fullscreen element stack
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="first">
+ <div id="last"></div>
+</div>
+<script>
+ promise_test(async (t) => {
+ const first = document.getElementById("first");
+ const last = document.getElementById("last");
+
+ await Promise.all([trusted_request(first), fullScreenChange()]);
+ assert_equals(document.fullscreenElement, first);
+
+ await Promise.all([trusted_request(last), fullScreenChange()]);
+ assert_equals(document.fullscreenElement, last);
+
+ await Promise.all([trusted_request(first, last), fullScreenChange()]);
+ assert_equals(document.fullscreenElement, first);
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html
new file mode 100644
index 0000000000..e52895ad7e
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-not-allowed.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() when not allowed to request fullscreen
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ const div = document.querySelector("div");
+ const errorEventPromise = new Promise(
+ (resolve) => (document.onfullscreenerror = resolve)
+ );
+ const [, event] = await Promise.all([
+ promise_rejects_js(t, TypeError, div.requestFullscreen()),
+ errorEventPromise,
+ ]);
+ assert_equals(event.type, "fullscreenerror");
+ assert_equals(event.target, div, "event.target");
+ assert_true(event.bubbles, "event.bubbles");
+ assert_false(event.cancelable, "event.cancelable");
+ assert_true(event.composed, "event.composed");
+ }, "requestFullscreen() when not allowed to request fullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html
new file mode 100644
index 0000000000..c11f54f7b5
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen({ navigationUI }) support</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body></body>
+<script>
+ // Tests for https://github.com/whatwg/fullscreen/pull/129. Because there are
+ // no normative requirements on what navigationUI should do, just test for
+ // basic support. (One could also check that the three allowed enum valid are
+ // supported and no others, but that would overlap with UA-specific tests.)
+ promise_test(async (t) => {
+ const invalidDict = {
+ get navigationUI() {
+ return "invalid-value";
+ },
+ };
+ await promise_rejects_js(
+ t,
+ TypeError,
+ document.body.requestFullscreen(invalidDict)
+ );
+ await promise_rejects_js(
+ t,
+ TypeError,
+ document.body.requestFullscreen({ navigationUI: "other-invalid-value" })
+ );
+ }, "requestFullscreen() with invalid navigationUI values");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.html
new file mode 100644
index 0000000000..b2eb60088a
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-options.tentative.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen({ screen }) tentative support</title>
+<link rel="help" href="https://w3c.github.io/window-placement/" />
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+ promise_test(async (t) => {
+ await test_driver.set_permission(
+ { name: "window-placement" },
+ "granted"
+ );
+
+ const options = {
+ get screen() {
+ return undefined;
+ },
+ };
+
+ await promise_rejects_js(
+ t,
+ TypeError,
+ document.body.requestFullscreen(options)
+ );
+ }, "fullscreenOptions.screen getter is invoked on requestFullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html
new file mode 100644
index 0000000000..a2b04dd173
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same-element.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() on the current fullscreen element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<div id="log"></div>
+<script>
+promise_test(async (t) => {
+ t.add_cleanup(() => {
+ if (document.fullscreenElement) return document.exitFullscreen();
+ });
+
+ // Use the body element as the fullscreen element, because the second
+ // test_driver.bless() call needs to insert a button inside of it, which
+ // can't be clicked if another element is already fullscreen.
+ const target = document.body;
+
+ // First enter fullscreen.
+ await test_driver.bless("fullscreen", () => target.requestFullscreen());
+ assert_equals(document.fullscreenElement, target, "fullscreen element after first request");
+
+ // Now request fullscreen again, which should be a no-op.
+ await test_driver.bless("fullscreen", () => target.requestFullscreen());
+ assert_equals(document.fullscreenElement, target, "fullscreen element after second request");
+});
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html
new file mode 100644
index 0000000000..8569c4df79
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-same.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() on the current fullscreen element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="target"></div>
+<script>
+ promise_test(async (t) => {
+ const target = document.getElementById("target");
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+
+ await Promise.all([
+ fullScreenChange(),
+ trusted_request(target),
+ ]);
+
+ assert_equals(document.fullscreenElement, target);
+
+ // The next requestFullscreen() should fire no events due to "If element is
+ // doc's fullscreen element, terminate these subsubsteps."
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+
+ await trusted_click(target);
+ await target.requestFullscreen();
+ assert_equals(document.fullscreenElement, target);
+ // Wait until after the next animation frame.
+ await new Promise((r) => requestAnimationFrame(r));
+ }, "Element#requestFullscreen() on the current fullscreen element");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html
new file mode 100644
index 0000000000..44adfa6898
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-rect.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() for SVG rect element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<svg>
+ <rect
+ width="300"
+ height="300"
+ style="fill: rgb(0, 255, 153)"
+ />
+</svg>
+<script>
+ promise_test(async (t) => {
+ const rect = document.querySelector("rect");
+ assert_true(rect instanceof SVGRectElement);
+ document.onfullscreenchange = t.unreached_func(
+ "fullscreenchange event"
+ );
+ await trusted_click(document.body);
+ await Promise.all([
+ promise_rejects_js(t, TypeError, rect.requestFullscreen()),
+ new Promise((resolve) => {
+ document.onfullscreenerror = resolve;
+ }),
+ ]);
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html
new file mode 100644
index 0000000000..e579f6e7d7
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-svg-svg.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() for SVG svg element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<svg></svg>
+<script>
+ promise_test(async (t) => {
+ const svg = document.querySelector("svg");
+ assert_true(svg instanceof SVGSVGElement);
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+ await Promise.all([
+ fullScreenChange(),
+ trusted_request(svg),
+ ]);
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html
new file mode 100644
index 0000000000..b7986575ff
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-timing.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() timing</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+promise_test(async t => {
+ const div = document.querySelector('div');
+
+ // If fullscreenchange is an animation frame event, then animation frame
+ // callbacks should be run after it is fired, before the timer callback.
+ // The resize event should fire before the fullscreenchange event.
+ const events = [];
+ const callback = t.step_func(event => {
+ // fullscreenElement should have changed before either event is fired.
+ assert_equals(document.fullscreenElement, div, `fullscreenElement in {event.type} event`);
+ events.push(event.type);
+ if (event.type == 'fullscreenchange') {
+ step_timeout(t.unreached_func('timer callback'));
+ requestAnimationFrame(t.step_func_done(() => {
+ assert_array_equals(events, ['resize', 'fullscreenchange'], 'event order');
+ }));
+ }
+ });
+ document.onfullscreenchange = window.onresize = callback;
+ await trusted_request(div);
+}, 'Timing of fullscreenchange and resize events');
+
+async_test(t => {
+ // Gecko throttles requestAnimationFrame before the first paint, so
+ // wrap the test to work around that.
+ requestAnimationFrame(t.step_func(() => {
+ var promise = document.createElement('a').requestFullscreen();
+ var promise_executed = false;
+ promise.catch(()=>{promise_executed = true; });
+ // If fullscreenerror is an animation frame event, then animation frame
+ // callbacks should be run after it is fired, before the timer callback.
+ document.onfullscreenerror = t.step_func(() => {
+ assert_true(promise_executed, "promise executed");
+ step_timeout(t.unreached_func('timer callback'));
+ requestAnimationFrame(t.step_func_done());
+ });
+ }));
+}, 'Timing of fullscreenerror event');
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html
new file mode 100644
index 0000000000..59211856ab
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-top.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>
+ Element#requestFullscreen() for top element in fullscreen element stack
+</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<div id="top"></div>
+<script>
+ promise_test(async function (t) {
+ const top = document.getElementById("top");
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+
+ await Promise.all([
+ trusted_request(top),
+ new Promise((r) =>
+ document.addEventListener("fullscreenchange", r)
+ ),
+ ]);
+ assert_equals(document.fullscreenElement, top);
+ await trusted_click(top);
+ await top.requestFullscreen();
+ // A fullscreenerror event would be fired after an async section
+ // and an animation frame task, so wait until after that.
+ await new Promise((resolve) => {
+ t.step_timeout(() => {
+ requestAnimationFrame(resolve);
+ });
+ });
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html
new file mode 100644
index 0000000000..db53aec544
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-twice.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() twice</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ const div = document.querySelector("div");
+ await trusted_click(document.body);
+ const p = div.requestFullscreen();
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "fullscreenElement after first requestFullscreen()"
+ );
+ const rejectedPromises = [
+ promise_rejects_js(t, TypeError, div.requestFullscreen()),
+ promise_rejects_js(t, TypeError, div.requestFullscreen()),
+ ];
+ await Promise.all([p, fullScreenChange()]);
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement after entering fullscreen"
+ );
+ // Ensure that there's are not more changes fullscreenchange event.
+ document.onfullscreenchange = t.unreached_func(
+ "second fullscreenchange event"
+ );
+ await Promise.all(rejectedPromises);
+ await new Promise((r) => requestAnimationFrame(r));
+ }, "requestFullscreen() multiple times after going fullscreen");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html
new file mode 100644
index 0000000000..54419ea8fd
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen-two-elements.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen() on two elements in the same document</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<body>
+ <div id="a"></div>
+ <div id="b"></div>
+</body>
+<script>
+ promise_test(async (t) => {
+ document.onfullscreenerror = t.unreached_func("fullscreenerror event");
+
+ // Request fullscreen on both elements, but in reverse tree order.
+ const a = document.getElementById("a");
+ const b = document.getElementById("b");
+
+ // Expect two fullscreenchange events, with document.fullscreenElement
+ // changing in the same order as the requests.
+ await trusted_click(b);
+ await Promise.all([b.requestFullscreen(), fullScreenChange()]);
+ assert_equals(document.fullscreenElement, b);
+
+ await trusted_click(b);
+ await Promise.all([a.requestFullscreen(), fullScreenChange()]);
+ assert_equals(document.fullscreenElement, a);
+ }, "Element#requestFullscreen() on two elements in the same document");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html
new file mode 100644
index 0000000000..fd9f249551
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/element-request-fullscreen.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Element#requestFullscreen()</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async function (t) {
+ const div = document.querySelector("div");
+ await Promise.all([fullScreenChange(), trusted_request(div)]);
+ assert_equals(event.target, div, "event.target");
+ assert_true(event.bubbles, "event.bubbles");
+ assert_false(event.cancelable, "event.cancelable");
+ assert_true(event.composed, "event.composed");
+ await document.exitFullscreen();
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html b/testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html
new file mode 100644
index 0000000000..fc6f232747
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/fullscreen-display-contents.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+ <title>
+ Test that display:contents on fullscreen elements acts like
+ display:block
+ </title>
+ <meta charset="utf-8" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script src="../trusted-click.js"></script>
+ <link rel="author" href="mailto:masonf@chromium.org" />
+ <link
+ rel="help"
+ href="https://fullscreen.spec.whatwg.org/#new-stacking-layer"
+ />
+ <div id="target"></div>
+ <style>
+ #target {
+ display: contents;
+ background-color: green;
+ }
+ #target::backdrop {
+ display: contents;
+ }
+ </style>
+
+ <script>
+ promise_test(async (t) => {
+ const target = document.querySelector("#target");
+ await test_driver.bless("fullscreen");
+ await target.requestFullscreen();
+ await new Promise((resolve) => requestAnimationFrame(resolve));
+ assert_equals(document.fullscreenElement, target);
+ assert_equals(
+ getComputedStyle(target).display,
+ "block",
+ "fullscreen element should have display:block"
+ );
+ assert_equals(
+ getComputedStyle(target, "::backdrop").display,
+ "block",
+ "fullscreen element's ::backdrop should have display:block"
+ );
+ await document.exitFullscreen();
+ new Promise((resolve) => requestAnimationFrame(resolve));
+ assert_equals(document.fullscreenElement, null);
+ assert_equals(
+ getComputedStyle(target).display,
+ "contents",
+ "fullscreen element should have display:contents after exiting fullscreen"
+ );
+ });
+ </script>
+</html>
diff --git a/testing/web-platform/tests/fullscreen/api/historical.html b/testing/web-platform/tests/fullscreen/api/historical.html
new file mode 100644
index 0000000000..8b3e3c03e9
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/historical.html
@@ -0,0 +1,38 @@
+<!doctype html>
+<title>Historical Fullscreen features</title>
+<script src=/resources/testharness.js></script>
+<script src=/resources/testharnessreport.js></script>
+<script>
+[
+ "onwebkitfullscreenchange",
+ "onwebkitfullscreenerror",
+ "webkitCurrentFullScreenElement",
+ "webkitFullscreenElement",
+ "webkitFullscreenEnabled",
+ "webkitIsFullScreen",
+ "webkitRequestFullScreen",
+ "webkitRequestFullscreen",
+ "webkitDisplayingFullscreen",
+ "webkitEnterFullScreen",
+ "webkitEnterFullscreen",
+ "webkitExitFullScreen",
+ "webkitExitFullscreen",
+ "webkitSupportsFullscreen",
+].forEach(function(member) {
+ ["webkit", "moz", "ms"].forEach(function(prefix) {
+ var alias = member.replace("webkit", prefix);
+ var clarifyTestName = (alias.indexOf('FullScreen') != -1 ? ' (uppercase S)' : '');
+
+ test(function() {
+ assert_false(alias in document.createElement('video'));
+ }, '<video> member must not be supported: ' + alias + clarifyTestName);
+
+ test(function() {
+ assert_false(alias in document);
+ }, 'Document member must not be supported: ' + alias + clarifyTestName);
+
+ // Some of the combinations tested here have never been supported, but
+ // it is convenient to just test all names on both <video> and document.
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/promises-reject.html b/testing/web-platform/tests/fullscreen/api/promises-reject.html
new file mode 100644
index 0000000000..4385b1646d
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/promises-reject.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Promises#reject</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async (t) => {
+ const e = document.createElement("span");
+ await promise_rejects_js(
+ t,
+ TypeError,
+ e.requestFullscreen(),
+ "Rejects if the element is not connected"
+ );
+ await promise_rejects_js(
+ t,
+ TypeError,
+ document.exitFullscreen(),
+ "Not in fullscreen"
+ );
+ }, "Rejects if the element is not connected");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/promises-resolve.html b/testing/web-platform/tests/fullscreen/api/promises-resolve.html
new file mode 100644
index 0000000000..5b8a090628
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/promises-resolve.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>Promises#resolve</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="../trusted-click.js"></script>
+<div id="log"></div>
+<script>
+ promise_test(async function (t) {
+ const div = document.querySelector("div");
+ await trusted_request(div, document.body);
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement before exitFullscreen()"
+ );
+ const p = document.exitFullscreen();
+ assert_equals(
+ document.fullscreenElement,
+ div,
+ "fullscreenElement after exitFullscreen()"
+ );
+ await p;
+ assert_equals(
+ document.fullscreenElement,
+ null,
+ "fullscreenElement after exiting fullscreen"
+ );
+ });
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html b/testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html
new file mode 100644
index 0000000000..98cca04516
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/resources/attempt-fullscreen.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>IFrame Fullscreen API success reporter</title>
+<body></body>
+<script>
+ window.addEventListener("message", async (e) => {
+ switch (e.data.action) {
+ case "report":
+ await sendReport();
+ break;
+ default:
+ parent.postMessage(
+ {
+ report: {
+ api: "fullscreen",
+ result: `Unknown action ${e.data.action}`,
+ frame: window.name,
+ },
+ },
+ "*"
+ );
+ }
+ });
+
+ async function sendReport() {
+ let didSucceed = true;
+ let error;
+ let errorMessage;
+ try {
+ await document.body.requestFullscreen();
+ } catch (e) {
+ didSucceed = false;
+ error = e.name;
+ errorMessage = e.message;
+ } finally {
+ const data = {
+ report: {
+ api: "fullscreen",
+ result: didSucceed,
+ frame: window.name,
+ error,
+ errorMessage,
+ },
+ };
+ parent.postMessage(data, "*");
+ }
+ }
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html b/testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html
new file mode 100644
index 0000000000..ad5edf7986
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/resources/echo-fullscreenEnabled.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<script>
+window.onmessage = (e) => {
+ if (e.data === 'What is document.fullscreenEnabled?') {
+ e.source.postMessage(document.fullscreenEnabled, '*');
+ } else {
+ e.source.postMessage('Incorrect message', '*');
+ }
+}
+</script>
+<p>This page echos document.fullscreenEnabled.</p>
diff --git a/testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html b/testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html
new file mode 100644
index 0000000000..d242a3b3e6
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/resources/recursive-iframe-fullscreen.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<meta charset="utf-8" />
+<title>Recursive IFrame Fullscreen API success reporter</title>
+<body>
+ <script src="/resources/testdriver.js"></script>
+ <script src="/resources/testdriver-vendor.js"></script>
+ <script src="../../trusted-click.js"></script>
+ <script>
+ let child_frame = null;
+ const events = [];
+
+ document.onfullscreenchange = () => {
+ events.push("fullscreenchange");
+ };
+
+ document.onfullscreenerror = () => {
+ events.push("fullscreenerror");
+ };
+
+ function send_report() {
+ window.top.postMessage(
+ {
+ name: window.name,
+ action: "report",
+ report: {
+ api: "fullscreen",
+ frame: window.name,
+ fullscreenElementIsNull: document.fullscreenElement === null,
+ events,
+ },
+ },
+ "*"
+ );
+ }
+
+ async function create_child_frame({ src, name, allow_fullscreen }) {
+ child_frame = document.createElement("iframe");
+ child_frame.allow = allow_fullscreen ? "fullscreen" : "";
+ child_frame.name = name;
+ child_frame.style.width = "100%";
+ child_frame.style.height = "100%";
+ document.body.appendChild(child_frame);
+ await new Promise((resolve) => {
+ child_frame.addEventListener("load", resolve, { once: true });
+ child_frame.src = src;
+ });
+ window.top.postMessage({ action: "load", name }, "*");
+ }
+
+ async function go_fullscreen() {
+ await trusted_click(document.body);
+ let error;
+ try {
+ await document.body.requestFullscreen();
+ } catch (err) {
+ error = err.name;
+ } finally {
+ window.top.postMessage(
+ { action: "requestFullscreen", name: window.name, error },
+ "*"
+ );
+ }
+ }
+
+ window.addEventListener("message", async (e) => {
+ // Massage is not for us, try to pass it on...
+ if (e.data.name !== window.name) {
+ child_frame?.contentWindow.postMessage(e.data, "*");
+ return;
+ }
+ switch (e.data.action) {
+ case "requestReport":
+ send_report();
+ break;
+ case "requestFullscreen":
+ await go_fullscreen();
+ break;
+ case "addIframe":
+ await create_child_frame(e.data.iframe);
+ break;
+ default:
+ window.top.postMessage(e.data, "*");
+ }
+ });
+ </script>
+</body>
diff --git a/testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html b/testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html
new file mode 100644
index 0000000000..ee8d4cfab7
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/resources/report-fullscreen-enabled.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>IFrame fullscreenEnabled attribute reporter</title>
+<body>
+<script>
+parent.postMessage({"report": {
+ "api": "fullscreen",
+ "enabled": document.fullscreenEnabled,
+ "frame": window.name
+}}, "*");
+</script>
diff --git a/testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html b/testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html
new file mode 100644
index 0000000000..5e605f00aa
--- /dev/null
+++ b/testing/web-platform/tests/fullscreen/api/shadowroot-fullscreen-element.html
@@ -0,0 +1,47 @@
+<!doctype html>
+<html>
+<head>
+ <title>shadowRoot.fullscreenElement works correctly</title>
+ <link rel="author" title="Tim Nguyen" href="https://github.com/nt1m">
+ <link rel="help" href="https://fullscreen.spec.whatwg.org/#dom-document-fullscreenelement">
+</head>
+<div id="host">
+ <button onclick="document.exitFullscreen()" id="exitButton">Exit fullscreen</button>
+</div>
+<button id="requestButton">Go fullscreen</button>
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script>
+promise_test(async function() {
+ let host = document.getElementById("host");
+ host.attachShadow({ mode: "open" }).innerHTML = `
+ <style>
+ #outer { width: 200px; height: 200px; background: blue }
+ </style>
+ <div id="outer">
+ <slot></slot>
+ </div>
+ `;
+ let outer = host.shadowRoot.querySelector("#outer");
+ await new Promise((resolve) => {
+ addEventListener("fullscreenchange", resolve, { once: true });
+ requestButton.addEventListener("click", () => outer.requestFullscreen());
+ test_driver.click(requestButton);
+ });
+
+ assert_equals(outer.getRootNode().fullscreenElement, outer, "Correct shadowRoot.fullscreenElement after entering");
+ assert_equals(document.fullscreenElement, host, "Correct document.fullscreenElement after entering");
+
+ await new Promise((resolve) => {
+ addEventListener("fullscreenchange", resolve, { once: true });
+ test_driver.click(exitButton);
+ });
+
+ assert_equals(outer.getRootNode().fullscreenElement, null, "Correct shadowRoot.fullscreenElement after exiting");
+ assert_equals(document.fullscreenElement, null, "Correct document.fullscreenElement after exiting");
+}, "shadowRoot.fullscreenElement works correctly");
+</script>
+</html>