From 8b6abad682ad55af1357646392280c86762a5421 Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Thu, 4 Feb 2021 12:01:25 -0800 Subject: [PATCH] Portals: focus() inside portal should change active element Allows a portal document's activeElement to update when focus is called. Note that focus events won't be dispatched as the portal doesn't get page focus, and the portal WebContents isn't set as the focused WebContents (with the exception of orphaned portals). Updating the activeElement also means an autofocused element inside a portal will receive focus when the portal is activated. More discussion here: https://github.com/WICG/portals/issues/257 Change-Id: If67be1f424114653983b473a80c515337d49596a Bug: 1059404 --- portals/portals-focus.sub.html | 48 +++++++++++++++++++ .../resources/focus-page-with-autofocus.html | 21 ++++++++ portals/resources/focus-page-with-button.html | 6 +++ .../focus-page-with-x-origin-iframe.sub.html | 6 +-- 4 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 portals/resources/focus-page-with-autofocus.html diff --git a/portals/portals-focus.sub.html b/portals/portals-focus.sub.html index 3e3045adf90aab..54b4312be0ada5 100644 --- a/portals/portals-focus.sub.html +++ b/portals/portals-focus.sub.html @@ -29,6 +29,19 @@ } }, "test that an element inside a portal cannot steal focus"); + promise_test(async () => { + let portal = await createPortal(document, new URL("resources/focus-page-with-button.html", location.href)); + try { + let activeElementUpdated = new Promise(r => { + portal.onmessage = e => r(e.data.activeElementUpdated) + }); + portal.postMessage('focus-update-active-element'); + assert_true(await activeElementUpdated); + } finally { + document.body.removeChild(portal); + } + }, "test that activeElement inside a portal is updated after focus() is called"); + promise_test(async t => { let portal = await createPortal(document, new URL("resources/focus-page-with-x-origin-iframe.sub.html", location.href)); try { @@ -42,6 +55,19 @@ } }, "test that an element inside a portal's x-origin subframe cannot steal focus"); + promise_test(async () => { + let portal = await createPortal(document, new URL("resources/focus-page-with-x-origin-iframe.sub.html", location.href)); + try { + portal.postMessage("focus-update-active-element"); + let {activeElementUpdated} = await new Promise(r => { + portal.onmessage = e => r(e.data); + }); + assert_true(activeElementUpdated); + } finally { + document.body.removeChild(portal); + } + }, "test that a portal's x-origin subframe becomes active element on focus"); + promise_test(async t => { let win = await openBlankPortalHost(); let doc = win.document; @@ -87,6 +113,28 @@ } }, "test that a x-origin iframe inside an adopted portal cannot steal focus"); + promise_test(async () => { + let win = await openBlankPortalHost(); + let doc = win.document; + try { + let portal = await createPortal(doc, new URL("resources/focus-page-with-autofocus.html", location.href)); + portal.postMessage('check-active-element'); + let result = await new Promise(r => { + portal.onmessage = e => r(e.data); + }); + assert_true(result, "autofocused element is active element"); + + await portal.activate(); + win.portalHost.postMessage('check-active-element'); + result = await new Promise(r => { + win.portalHost.onmessage = e => r(e.data) + }); + assert_true(result, "autofocused element is still active element"); + } finally { + win.close(); + } + }, "test that autofocus inside a portal works"); + const TAB = "\ue004"; // https://w3c.github.io/webdriver/#keyboard-actions const SPACE = " " const RETURN = "\r"; diff --git a/portals/resources/focus-page-with-autofocus.html b/portals/resources/focus-page-with-autofocus.html new file mode 100644 index 00000000000000..8c56e73782a814 --- /dev/null +++ b/portals/resources/focus-page-with-autofocus.html @@ -0,0 +1,21 @@ + + + + + + + diff --git a/portals/resources/focus-page-with-button.html b/portals/resources/focus-page-with-button.html index 06722196510018..81ed5465ab10ce 100644 --- a/portals/resources/focus-page-with-button.html +++ b/portals/resources/focus-page-with-button.html @@ -7,6 +7,12 @@ button.onfocus = () => e.source.postMessage({focused: true}, {targetOrigin: "*"}); button.focus(); } + + if (e.data == "focus-update-active-element") { + let button = document.querySelector("button"); + button.focus(); + e.source.postMessage({activeElementUpdated: document.activeElement === button}, {targetOrigin: "*"}); + } } if (window.portalHost) diff --git a/portals/resources/focus-page-with-x-origin-iframe.sub.html b/portals/resources/focus-page-with-x-origin-iframe.sub.html index 9807898a3543ec..df7974e75bb946 100644 --- a/portals/resources/focus-page-with-x-origin-iframe.sub.html +++ b/portals/resources/focus-page-with-x-origin-iframe.sub.html @@ -1,10 +1,10 @@