mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-27 07:34:20 +00:00
Bug 1688972 - Make FocusedChild work across document/process boundaries. r=Jamie
Differential Revision: https://phabricator.services.mozilla.com/D103102
This commit is contained in:
parent
78590ae20c
commit
ba6174e679
@ -1524,15 +1524,30 @@ mozilla::ipc::IPCResult DocAccessibleChild::RecvTakeFocus(const uint64_t& aID) {
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult DocAccessibleChild::RecvFocusedChild(
|
||||
const uint64_t& aID, uint64_t* aChild, bool* aOk) {
|
||||
*aChild = 0;
|
||||
*aOk = false;
|
||||
const uint64_t& aID, PDocAccessibleChild** aResultDoc,
|
||||
uint64_t* aResultID) {
|
||||
*aResultDoc = nullptr;
|
||||
*aResultID = 0;
|
||||
Accessible* acc = IdToAccessible(aID);
|
||||
if (acc) {
|
||||
Accessible* child = acc->FocusedChild();
|
||||
if (child) {
|
||||
*aChild = reinterpret_cast<uint64_t>(child->UniqueID());
|
||||
*aOk = true;
|
||||
if (!acc) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
Accessible* result = acc->FocusedChild();
|
||||
if (result) {
|
||||
// Accessible::FocusedChild can return an Accessible from a descendant
|
||||
// document.
|
||||
DocAccessibleChild* resultDoc = result->Document()->IPCDoc();
|
||||
// We've sent the constructor for this document to the parent process.
|
||||
// However, because the constructor is async, the parent process might
|
||||
// get the result of this (sync) method before it runs the constructor.
|
||||
// If we send this document in this case, the parent process will crash.
|
||||
// Therefore, we only do this if the parent process has explicitly told
|
||||
// us that the document has been constructed there.
|
||||
if (resultDoc && resultDoc->IsConstructedInParentProcess()) {
|
||||
*aResultDoc = resultDoc;
|
||||
*aResultID =
|
||||
result->IsDoc() ? 0 : reinterpret_cast<uint64_t>(result->UniqueID());
|
||||
}
|
||||
}
|
||||
return IPC_OK();
|
||||
|
@ -442,9 +442,9 @@ class DocAccessibleChild : public DocAccessibleChildBase {
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvTakeFocus(const uint64_t& aID) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvFocusedChild(const uint64_t& aID,
|
||||
uint64_t* aChild,
|
||||
bool* aOk) override;
|
||||
virtual mozilla::ipc::IPCResult RecvFocusedChild(
|
||||
const uint64_t& aID, PDocAccessibleChild** aResultDoc,
|
||||
uint64_t* aResultID) override;
|
||||
|
||||
virtual mozilla::ipc::IPCResult RecvLanguage(const uint64_t& aID,
|
||||
nsString* aLocale) override;
|
||||
|
@ -310,7 +310,7 @@ child:
|
||||
|
||||
async TakeFocus(uint64_t aID);
|
||||
nested(inside_sync) sync FocusedChild(uint64_t aID)
|
||||
returns(uint64_t aChild, bool aOk);
|
||||
returns(nullable PDocAccessible aResultDoc, uint64_t aResultID);
|
||||
|
||||
nested(inside_sync) sync Language(uint64_t aID) returns(nsString aLocale);
|
||||
nested(inside_sync) sync DocType(uint64_t aID) returns(nsString aType);
|
||||
|
@ -762,10 +762,37 @@ double ProxyAccessible::Step() {
|
||||
void ProxyAccessible::TakeFocus() { Unused << mDoc->SendTakeFocus(mID); }
|
||||
|
||||
ProxyAccessible* ProxyAccessible::FocusedChild() {
|
||||
uint64_t childID = 0;
|
||||
bool ok = false;
|
||||
Unused << mDoc->SendFocusedChild(mID, &childID, &ok);
|
||||
return ok ? mDoc->GetAccessible(childID) : nullptr;
|
||||
if (mOuterDoc) {
|
||||
// If FocusedChild was called on an outer doc, it should behave
|
||||
// like a non-doc accessible and return its focused child, or null.
|
||||
// If the inner doc is OOP (fission), calling FocusedChild on the outer
|
||||
// doc would return null.
|
||||
MOZ_ASSERT(ChildrenCount() == 1);
|
||||
ProxyAccessible* child = FirstChild();
|
||||
MOZ_ASSERT(child->IsDoc());
|
||||
return (child->State() & states::FOCUSED) ? child : nullptr;
|
||||
}
|
||||
|
||||
auto* doc = mDoc;
|
||||
uint64_t id = mID;
|
||||
if (IsDoc()) {
|
||||
// If this is a doc we should return the focused descendant, not just the
|
||||
// direct child. In order to do that, we get the focused parent doc,
|
||||
// which may be an OOP iframe.
|
||||
if (dom::BrowserParent* browser = dom::BrowserParent::GetFocused()) {
|
||||
if (auto* focusedDoc = browser->GetTopLevelDocAccessible()) {
|
||||
doc = focusedDoc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PDocAccessibleParent* resultDoc = nullptr;
|
||||
uint64_t resultID = 0;
|
||||
Unused << doc->SendFocusedChild(id, &resultDoc, &resultID);
|
||||
|
||||
auto* useDoc = static_cast<DocAccessibleParent*>(resultDoc);
|
||||
// If useDoc is null, this means there is no focused child.
|
||||
return useDoc ? useDoc->GetAccessible(resultID) : nullptr;
|
||||
}
|
||||
|
||||
ProxyAccessible* ProxyAccessible::ChildAtPoint(
|
||||
|
@ -11,9 +11,15 @@ loadScripts(
|
||||
);
|
||||
|
||||
addAccessibleTask(
|
||||
`<input id="textbox" value="hello"/>`,
|
||||
`<div role="group"><input id="textbox" value="hello"/></div>`,
|
||||
async function(browser, iframeDocAcc, contentDocAcc) {
|
||||
const textbox = findAccessibleChildByID(iframeDocAcc, "textbox");
|
||||
const iframe = findAccessibleChildByID(contentDocAcc, "default-iframe-id");
|
||||
const iframeDoc = findAccessibleChildByID(
|
||||
contentDocAcc,
|
||||
"default-iframe-body-id"
|
||||
);
|
||||
|
||||
testStates(textbox, STATE_FOCUSABLE, 0, STATE_FOCUSED);
|
||||
|
||||
let onFocus = waitForEvent(EVENT_FOCUS, textbox);
|
||||
@ -21,6 +27,35 @@ addAccessibleTask(
|
||||
await onFocus;
|
||||
|
||||
testStates(textbox, STATE_FOCUSABLE | STATE_FOCUSED, 0);
|
||||
|
||||
is(
|
||||
getAccessibleDOMNodeID(contentDocAcc.focusedChild),
|
||||
"textbox",
|
||||
"correct focusedChild from top doc"
|
||||
);
|
||||
|
||||
is(
|
||||
getAccessibleDOMNodeID(iframeDocAcc.focusedChild),
|
||||
"textbox",
|
||||
"correct focusedChild from child doc"
|
||||
);
|
||||
|
||||
ok(!iframe.focusedChild, "correct focusedChild from iframe (null)");
|
||||
|
||||
onFocus = waitForEvent(EVENT_FOCUS, iframeDoc);
|
||||
iframeDoc.takeFocus();
|
||||
await onFocus;
|
||||
|
||||
is(
|
||||
getAccessibleDOMNodeID(contentDocAcc.focusedChild),
|
||||
"default-iframe-body-id",
|
||||
"correct focusedChild of child doc from top doc"
|
||||
);
|
||||
is(
|
||||
getAccessibleDOMNodeID(iframe.focusedChild),
|
||||
"default-iframe-body-id",
|
||||
"correct focusedChild of child doc from iframe"
|
||||
);
|
||||
},
|
||||
{ topLevel: false, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user