Bug 1581040: handle late creation/re-creation of OuterDocAccessible for OOP iframe. r=yzen,nika

1. When creating a DocAccessibleParent for an embedded document in an OOP iframe, it's possible that the embedder accessible hasn't been set yet.
    This can occur if the iframe is initially hidden.
    Previously, we incorrectly set the document up as a top level document (e.g. tab document) in this case.
    Now, we set up the document as top level in its content process, set up the proxy, etc.
    The document will be added to its child document later when the embedder is set.

2. When setting the embedder accessible for an OOP iframe, check if the embedded DocAccessibleParent already exists.
    This can happen if an iframe is hidden and then shown or an iframe is reflowed by layout.
    If it already exists, add the embedded (child) document to its embedder.

Differential Revision: https://phabricator.services.mozilla.com/D51357

--HG--
extra : moz-landing-system : lando
This commit is contained in:
James Teh 2019-11-01 17:12:19 +00:00
parent 0d0fd1b7e8
commit fea47468f5
2 changed files with 37 additions and 15 deletions

View File

@ -232,6 +232,17 @@ IPCResult BrowserBridgeParent::RecvSetEmbedderAccessible(
#ifdef ACCESSIBILITY
mEmbedderAccessibleDoc = static_cast<a11y::DocAccessibleParent*>(aDoc);
mEmbedderAccessibleID = aID;
if (auto embeddedBrowser = GetBrowserParent()) {
a11y::DocAccessibleParent* childDocAcc =
embeddedBrowser->GetTopLevelDocAccessible();
if (childDocAcc && !childDocAcc->IsShutdown()) {
// The embedded DocAccessibleParent has already been created. This can
// happen if, for example, an iframe is hidden and then shown or
// an iframe is reflowed by layout.
mEmbedderAccessibleDoc->AddChildDoc(childDocAcc, aID,
/* aCreating */ false);
}
}
#endif
return IPC_OK();
}

View File

@ -10,6 +10,8 @@
#ifdef ACCESSIBILITY
# include "mozilla/a11y/DocAccessibleParent.h"
# include "mozilla/a11y/Platform.h"
# include "mozilla/a11y/ProxyAccessibleBase.h"
# include "nsAccessibilityService.h"
#endif
#include "mozilla/BrowserElementParent.h"
@ -1173,35 +1175,44 @@ mozilla::ipc::IPCResult BrowserParent::RecvPDocAccessibleConstructor(
return IPC_OK();
}
a11y::DocAccessibleParent* embedderDoc;
uint64_t embedderID;
Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
if (embedderDoc) {
if (auto bridge = GetBrowserBridgeParent()) {
// Iframe document rendered in a different process to its embedder.
// In this case, we don't get aParentDoc and aParentID.
MOZ_ASSERT(!aParentDoc && !aParentID);
MOZ_ASSERT(embedderID);
doc->SetTopLevelInContentProcess();
# ifdef XP_WIN
MOZ_ASSERT(!aDocCOMProxy.IsNull());
RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
doc->SetCOMInterface(proxy);
# endif
mozilla::ipc::IPCResult added = embedderDoc->AddChildDoc(doc, embedderID);
if (!added) {
# ifdef DEBUG
return added;
# else
return IPC_OK();
# endif
}
a11y::ProxyCreated(
doc, a11y::Interfaces::DOCUMENT | a11y::Interfaces::HYPERTEXT);
# ifdef XP_WIN
// This *must* be called after AddChildDoc because AddChildDoc
// calls ProxyCreated and WrapperFor will fail before that.
// This *must* be called after ProxyCreated because WrapperFor will fail
// before that.
a11y::AccessibleWrap* wrapper = a11y::WrapperFor(doc);
MOZ_ASSERT(wrapper);
wrapper->SetID(aMsaaID);
# endif
a11y::DocAccessibleParent* embedderDoc;
uint64_t embedderID;
Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
// It's possible the embedder accessible hasn't been set yet; e.g.
// a hidden iframe. In that case, embedderDoc will be null and this will
// be handled when the embedder is set.
if (embedderDoc) {
MOZ_ASSERT(embedderID);
mozilla::ipc::IPCResult added =
embedderDoc->AddChildDoc(doc, embedderID,
/* aCreating */ false);
if (!added) {
# ifdef DEBUG
return added;
# else
return IPC_OK();
# endif
}
}
return IPC_OK();
} else {
// null aParentDoc means this document is at the top level in the child