Bug 1570848: When an OuterDocAccessible is constructed, send it as the parent COM proxy for its remote document (if any). r=MarcoZ a=pascalc DEVEDITION_69_0b11_BUILD1 DEVEDITION_69_0b11_RELEASE FIREFOX_69_0b11_BUILD1 FIREFOX_69_0b11_RELEASE
authorJames Teh <jteh@mozilla.com>
Fri, 02 Aug 2019 04:24:54 +0000
changeset 544949 e2da69ccbc88af33399b87b2998946565ab07c2f
parent 544948 e429e0d918bea5229bdddfe60d725334b8f2113b
child 544950 a0a695337bed3db31edaa1a38d36ab4828d46385
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMarcoZ, pascalc
Bug 1570848: When an OuterDocAccessible is constructed, send it as the parent COM proxy for its remote document (if any). r=MarcoZ a=pascalc Normally, the OuterDocAccessible is created first and the DocAccessibleParent for a remote document is created after that. So, we get the OuterDocAccessible and call DocAccessibleParent::SendParentCOMProxy when the DocAccessibleParent is constructed (BrowserParent::RecvPDocAccessibleConstructor). However, sometimes, the OuterDocAccessible is created *after* the DocAccessibleParent. This sometimes happens for extension popups, for example. In that case, we previously never sent the parent COM proxy. Aside from leaving the remote document with a null parent, this also meant we never sent any events for the document, since events are buffered for remote documents until the parent COM proxy is received. This effectively left the remote document (e.g. extension popup) inaccessible. Now, we also call SendParentCOMProxy in the OuterDocAccessible constructor. Note that this doesn't result in duplicates because if the OuterDocAccessible was created first, there won't be a DocAccessibleParent for the remote document yet, so this code won't run. That said, if the OuterDocAccessible is recreated (e.g. due to frame reconstruction), we may call SendParentCOMProxy again. This should be okay, but it required an assertion in DocAccessibleChild::RecvParentCOMProxy to be tweaked. Differential Revision: https://phabricator.services.mozilla.com/D40358
--- a/accessible/generic/OuterDocAccessible.cpp
+++ b/accessible/generic/OuterDocAccessible.cpp
@@ -29,16 +29,22 @@ using namespace mozilla::a11y;
 // OuterDocAccessible
 OuterDocAccessible::OuterDocAccessible(nsIContent* aContent,
                                        DocAccessible* aDoc)
     : AccessibleWrap(aContent, aDoc) {
   mType = eOuterDocType;
+#ifdef XP_WIN
+  if (DocAccessibleParent* remoteDoc = RemoteChildDoc()) {
+    remoteDoc->SendParentCOMProxy(this);
+  }
   if (IPCAccessibilityActive()) {
     auto bridge = dom::BrowserBridgeChild::GetFrom(aContent);
     if (bridge) {
       // This is an iframe which will be rendered in another process.
--- a/accessible/ipc/DocAccessibleParent.h
+++ b/accessible/ipc/DocAccessibleParent.h
@@ -213,16 +213,19 @@ class DocAccessibleParent : public Proxy
   DocAccessibleParent* ChildDocAt(size_t aIdx) {
     return LiveDocs().Get(mChildDocs[aIdx]);
 #if defined(XP_WIN)
   void MaybeInitWindowEmulation();
+   * Note that an OuterDocAccessible can be created before the
+   * DocAccessibleParent or vice versa. Therefore, this must be conditionally
+   * called when either of these is created.
    * @param aOuterDoc The OuterDocAccessible to be returned as the parent of
    *        this document. Only GetNativeInterface() is called on this, so it
    *        may be a ProxyAccessibleWrap or similar.
   void SendParentCOMProxy(Accessible* aOuterDoc);
   virtual mozilla::ipc::IPCResult RecvGetWindowedPluginIAccessible(
       const WindowsHandle& aHwnd, IAccessibleHolder* aPluginCOMProxy) override;
--- a/accessible/ipc/win/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -41,17 +41,17 @@ void DocAccessibleChild::Shutdown() {
 ipc::IPCResult DocAccessibleChild::RecvParentCOMProxy(
     const IDispatchHolder& aParentCOMProxy) {
-  MOZ_ASSERT(!mParentProxy && !aParentCOMProxy.IsNull());
+  MOZ_ASSERT(!aParentCOMProxy.IsNull());
   for (uint32_t i = 0, l = mDeferredEvents.Length(); i < l; ++i) {