forked from mirrors/gecko-dev
Bug 1898198: Fix RemoteAccessible::TakeFocus when the browser UI has focus. r=eeejay
Previously, this didn't move the focus at all in this case. Differential Revision: https://phabricator.services.mozilla.com/D211314
This commit is contained in:
parent
ebd4094092
commit
f0250b65b5
2 changed files with 90 additions and 1 deletions
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsAccessibilityService.h"
|
||||
#include "mozilla/Unused.h"
|
||||
#include "nsAccUtils.h"
|
||||
#include "nsFocusManager.h"
|
||||
#include "nsTextEquivUtils.h"
|
||||
#include "Pivot.h"
|
||||
#include "Relation.h"
|
||||
|
|
@ -1874,7 +1875,47 @@ bool RemoteAccessible::HasPrimaryAction() const {
|
|||
return mCachedFields && mCachedFields->HasAttribute(CacheKey::PrimaryAction);
|
||||
}
|
||||
|
||||
void RemoteAccessible::TakeFocus() const { Unused << mDoc->SendTakeFocus(mID); }
|
||||
void RemoteAccessible::TakeFocus() const {
|
||||
Unused << mDoc->SendTakeFocus(mID);
|
||||
if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
|
||||
auto* bp = static_cast<dom::BrowserParent*>(mDoc->Manager());
|
||||
MOZ_ASSERT(bp);
|
||||
dom::Element* owner = bp->GetOwnerElement();
|
||||
if (fm->GetFocusedElement() == owner) {
|
||||
// This remote document tree is already focused. We don't need to do
|
||||
// anything else.
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Otherwise, we need to focus the <browser> or <iframe> element embedding the
|
||||
// remote document in the parent process. If `this` is in an OOP iframe, we
|
||||
// first need to focus the embedder iframe (and any ancestor OOP iframes). If
|
||||
// the parent process embedder element were already focused, that would happen
|
||||
// automatically, but it isn't. We can't simply focus the parent process
|
||||
// embedder element before calling mDoc->SendTakeFocus because that would
|
||||
// cause the remote document to restore focus to the last focused element,
|
||||
// which we don't want.
|
||||
DocAccessibleParent* embeddedDoc = mDoc;
|
||||
Accessible* embedder = mDoc->Parent();
|
||||
while (embedder) {
|
||||
MOZ_ASSERT(embedder->IsOuterDoc());
|
||||
RemoteAccessible* embedderRemote = embedder->AsRemote();
|
||||
if (!embedderRemote) {
|
||||
// This is the element in the parent process which embeds the remote
|
||||
// document.
|
||||
embedder->TakeFocus();
|
||||
break;
|
||||
}
|
||||
// This is a remote <iframe>.
|
||||
if (embeddedDoc->IsTopLevelInContentProcess()) {
|
||||
// We only need to focus OOP iframes because these are where we cross
|
||||
// process boundaries.
|
||||
Unused << embedderRemote->mDoc->SendTakeFocus(embedderRemote->mID);
|
||||
}
|
||||
embeddedDoc = embedderRemote->mDoc;
|
||||
embedder = embeddedDoc->Parent();
|
||||
}
|
||||
}
|
||||
|
||||
void RemoteAccessible::ScrollTo(uint32_t aHow) const {
|
||||
Unused << mDoc->SendScrollTo(mID, aHow);
|
||||
|
|
|
|||
|
|
@ -71,3 +71,51 @@ addAccessibleTask(
|
|||
},
|
||||
{ topLevel: false, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
||||
function focusURLBar() {
|
||||
info("Focusing the URL bar");
|
||||
const focused = waitForEvent(
|
||||
EVENT_FOCUS,
|
||||
event => event.accessible.role == ROLE_ENTRY
|
||||
);
|
||||
gURLBar.focus();
|
||||
return focused;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test takeFocus on web content when focus is in the browser UI.
|
||||
*/
|
||||
addAccessibleTask(
|
||||
`
|
||||
<button id="outerButton">outerButton</button>
|
||||
<iframe src="data:text/html,<body id='innerDoc'><button id='innerButton'>innerButton</button>"></iframe>
|
||||
`,
|
||||
async function testFocusContentWhileUiFocused(browser, docAcc) {
|
||||
await focusURLBar();
|
||||
info("Focusing docAcc");
|
||||
let focused = waitForEvent(EVENT_FOCUS, docAcc);
|
||||
docAcc.takeFocus();
|
||||
await focused;
|
||||
|
||||
await focusURLBar();
|
||||
info("Focusing outerButton");
|
||||
const outerButton = findAccessibleChildByID(docAcc, "outerButton");
|
||||
focused = waitForEvent(EVENT_FOCUS, outerButton);
|
||||
outerButton.takeFocus();
|
||||
await focused;
|
||||
|
||||
await focusURLBar();
|
||||
info("Focusing innerButton");
|
||||
const innerButton = findAccessibleChildByID(docAcc, "outerButton");
|
||||
focused = waitForEvent(EVENT_FOCUS, innerButton);
|
||||
innerButton.takeFocus();
|
||||
await focused;
|
||||
|
||||
await focusURLBar();
|
||||
info("Focusing outerButton");
|
||||
focused = waitForEvent(EVENT_FOCUS, outerButton);
|
||||
outerButton.takeFocus();
|
||||
await focused;
|
||||
},
|
||||
{ chrome: true, topLevel: true, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
|
|
|||
Loading…
Reference in a new issue