Skip to content

Commit 82dbcc1

Browse files
committed
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
1 parent efc16a2 commit 82dbcc1

File tree

3 files changed

+39
-16
lines changed

3 files changed

+39
-16
lines changed

accessible/ipc/DocAccessibleParent.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ uint32_t DocAccessibleParent::AddSubtree(
139139
break;
140140
}
141141
}
142+
DebugOnly<bool> isOuterDoc = newProxy->ChildrenCount() == 1;
142143

143144
uint32_t accessibles = 1;
144145
uint32_t kids = newChild.ChildrenCount();
@@ -149,7 +150,7 @@ uint32_t DocAccessibleParent::AddSubtree(
149150
accessibles += consumed;
150151
}
151152

152-
MOZ_ASSERT(newProxy->ChildrenCount() == kids);
153+
MOZ_ASSERT(isOuterDoc && kids == 0 || newProxy->ChildrenCount() == kids);
153154

154155
return accessibles;
155156
}

dom/ipc/BrowserBridgeParent.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,17 @@ IPCResult BrowserBridgeParent::RecvSetEmbedderAccessible(
232232
#ifdef ACCESSIBILITY
233233
mEmbedderAccessibleDoc = static_cast<a11y::DocAccessibleParent*>(aDoc);
234234
mEmbedderAccessibleID = aID;
235+
if (auto embeddedBrowser = GetBrowserParent()) {
236+
a11y::DocAccessibleParent* childDocAcc =
237+
embeddedBrowser->GetTopLevelDocAccessible();
238+
if (childDocAcc && !childDocAcc->IsShutdown()) {
239+
// The embedded DocAccessibleParent has already been created. This can
240+
// happen if, for example, an iframe is hidden and then shown or
241+
// an iframe is reflowed by layout.
242+
mEmbedderAccessibleDoc->AddChildDoc(childDocAcc, aID,
243+
/* aCreating */ false);
244+
}
245+
}
235246
#endif
236247
return IPC_OK();
237248
}

dom/ipc/BrowserParent.cpp

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
#ifdef ACCESSIBILITY
1212
# include "mozilla/a11y/DocAccessibleParent.h"
13+
# include "mozilla/a11y/Platform.h"
14+
# include "mozilla/a11y/ProxyAccessibleBase.h"
1315
# include "nsAccessibilityService.h"
1416
#endif
1517
#include "mozilla/BrowserElementParent.h"
@@ -1173,35 +1175,44 @@ mozilla::ipc::IPCResult BrowserParent::RecvPDocAccessibleConstructor(
11731175
return IPC_OK();
11741176
}
11751177

1176-
a11y::DocAccessibleParent* embedderDoc;
1177-
uint64_t embedderID;
1178-
Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
1179-
if (embedderDoc) {
1178+
if (GetBrowserBridgeParent()) {
11801179
// Iframe document rendered in a different process to its embedder.
11811180
// In this case, we don't get aParentDoc and aParentID.
11821181
MOZ_ASSERT(!aParentDoc && !aParentID);
1183-
MOZ_ASSERT(embedderID);
11841182
doc->SetTopLevelInContentProcess();
11851183
# ifdef XP_WIN
11861184
MOZ_ASSERT(!aDocCOMProxy.IsNull());
11871185
RefPtr<IAccessible> proxy(aDocCOMProxy.Get());
11881186
doc->SetCOMInterface(proxy);
11891187
# endif
1190-
mozilla::ipc::IPCResult added = embedderDoc->AddChildDoc(doc, embedderID);
1191-
if (!added) {
1192-
# ifdef DEBUG
1193-
return added;
1194-
# else
1195-
return IPC_OK();
1196-
# endif
1197-
}
1188+
a11y::ProxyCreated(
1189+
doc, a11y::Interfaces::DOCUMENT | a11y::Interfaces::HYPERTEXT);
11981190
# ifdef XP_WIN
1199-
// This *must* be called after AddChildDoc because AddChildDoc
1200-
// calls ProxyCreated and WrapperFor will fail before that.
1191+
// This *must* be called after ProxyCreated because WrapperFor will fail
1192+
// before that.
12011193
a11y::AccessibleWrap* wrapper = a11y::WrapperFor(doc);
12021194
MOZ_ASSERT(wrapper);
12031195
wrapper->SetID(aMsaaID);
12041196
# endif
1197+
a11y::DocAccessibleParent* embedderDoc;
1198+
uint64_t embedderID;
1199+
Tie(embedderDoc, embedderID) = doc->GetRemoteEmbedder();
1200+
// It's possible the embedder accessible hasn't been set yet; e.g.
1201+
// a hidden iframe. In that case, embedderDoc will be null and this will
1202+
// be handled when the embedder is set.
1203+
if (embedderDoc) {
1204+
MOZ_ASSERT(embedderID);
1205+
mozilla::ipc::IPCResult added =
1206+
embedderDoc->AddChildDoc(doc, embedderID,
1207+
/* aCreating */ false);
1208+
if (!added) {
1209+
# ifdef DEBUG
1210+
return added;
1211+
# else
1212+
return IPC_OK();
1213+
# endif
1214+
}
1215+
}
12051216
return IPC_OK();
12061217
} else {
12071218
// null aParentDoc means this document is at the top level in the child

0 commit comments

Comments
 (0)