Bug 1268544: Integrate remote COM objects into a11y code; r?tbsaunde draft
authorAaron Klotz <aklotz@mozilla.com>
Fri, 05 Aug 2016 01:50:59 -0600
changeset 397132 ecafe7039ff5d86f11adfcd007eb4e76759cfdb0
parent 397131 f192b86419ec85970035a86655a000dfb52334cf
child 527380 6bc0e4dc883c71b600bff0f8034ce69c2bf9dfa8
push id25211
push useraklotz@mozilla.com
push dateFri, 05 Aug 2016 07:53:24 +0000
reviewerstbsaunde
bugs1268544
milestone50.0a1
Bug 1268544: Integrate remote COM objects into a11y code; r?tbsaunde MozReview-Commit-ID: ctPgegQ83a
accessible/base/DocManager.cpp
accessible/base/NotificationController.cpp
accessible/base/Platform.h
accessible/base/moz.build
accessible/ipc/win/DocAccessibleChild.cpp
accessible/ipc/win/PlatformChild.cpp
accessible/ipc/win/PlatformChild.h
accessible/ipc/win/moz.build
accessible/windows/msaa/DocAccessibleWrap.cpp
accessible/windows/msaa/DocAccessibleWrap.h
accessible/windows/msaa/Platform.cpp
--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -501,16 +501,21 @@ DocManager::CreateDocOrRootAccessible(ns
         // XXX We may need to handle the case that we don't have a tab child
         // differently.  It may be that this will cause us to fail to notify
         // the parent process about important accessible documents.
         if (tabChild) {
           DocAccessibleChild* ipcDoc = new DocAccessibleChild(docAcc);
           docAcc->SetIPCDoc(ipcDoc);
           static_cast<TabChild*>(tabChild.get())->
             SendPDocAccessibleConstructor(ipcDoc, nullptr, 0);
+
+#if defined(XP_WIN)
+          IAccessibleHolder holder(CreateHolderFromAccessible(docAcc));
+          ipcDoc->SendCOMProxy(holder);
+#endif
         }
       }
     }
   } else {
     parentDocAcc->BindChildDocument(docAcc);
   }
 
 #ifdef A11Y_LOG
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -423,16 +423,20 @@ NotificationController::WillRefresh(mozi
 
       ipcDoc = new DocAccessibleChild(childDoc);
       childDoc->SetIPCDoc(ipcDoc);
       nsCOMPtr<nsITabChild> tabChild =
         do_GetInterface(mDocument->DocumentNode()->GetDocShell());
       if (tabChild) {
         static_cast<TabChild*>(tabChild.get())->
           SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id);
+#if defined(XP_WIN)
+        IAccessibleHolder holder(CreateHolderFromAccessible(childDoc));
+        ipcDoc->SendCOMProxy(holder);
+#endif
       }
     }
   }
 
   mObservingState = eRefreshObserving;
   if (!mDocument)
     return;
 
--- a/accessible/base/Platform.h
+++ b/accessible/base/Platform.h
@@ -1,14 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#ifndef mozilla_a11y_Platform_h
+#define mozilla_a11y_Platform_h
+
 #include <stdint.h>
 
 class nsString;
 
 namespace mozilla {
 namespace a11y {
 
 class ProxyAccessible;
@@ -77,8 +80,9 @@ void ProxyTextChangeEvent(ProxyAccessibl
                           bool aFromUser);
 void ProxyShowHideEvent(ProxyAccessible* aTarget, ProxyAccessible* aParent,
                         bool aInsert, bool aFromUser);
 void ProxySelectionEvent(ProxyAccessible* aTarget, ProxyAccessible* aWidget,
                          uint32_t aType);
 } // namespace a11y
 } // namespace mozilla
 
+#endif // mozilla_a11y_Platform_h
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -58,16 +58,28 @@ if CONFIG['A11Y_LOG']:
     UNIFIED_SOURCES += [
         'Logging.cpp',
     ]
 
 LOCAL_INCLUDES += [
     '/accessible/generic',
     '/accessible/html',
     '/accessible/ipc',
+]
+
+if CONFIG['OS_ARCH'] == 'WINNT':
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/win',
+    ]
+else:
+    LOCAL_INCLUDES += [
+        '/accessible/ipc/other',
+    ]
+
+LOCAL_INCLUDES += [
     '/accessible/xpcom',
     '/accessible/xul',
     '/dom/base',
     '/dom/xbl',
     '/ipc/chromium/src',
     '/layout/generic',
     '/layout/style',
     '/layout/svg',
--- a/accessible/ipc/win/DocAccessibleChild.cpp
+++ b/accessible/ipc/win/DocAccessibleChild.cpp
@@ -2,24 +2,32 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DocAccessibleChild.h"
 
 #include "Accessible-inl.h"
+#include "mozilla/a11y/PlatformChild.h"
+#include "mozilla/ClearOnShutdown.h"
 
 namespace mozilla {
 namespace a11y {
 
+static StaticAutoPtr<PlatformChild> sPlatformChild;
+
 DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc)
   : DocAccessibleChildBase(aDoc)
 {
   MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
+  if (!sPlatformChild) {
+    sPlatformChild = new PlatformChild();
+    ClearOnShutdown(&sPlatformChild, ShutdownPhase::ShutdownThreads);
+  }
 }
 
 DocAccessibleChild::~DocAccessibleChild()
 {
   MOZ_COUNT_DTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase);
 }
 
 void
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/PlatformChild.cpp
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "mozilla/a11y/PlatformChild.h"
+#include "mozilla/mscom/EnsureMTA.h"
+#include "mozilla/mscom/InterceptorLog.h"
+
+#include "Accessible2.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * Unfortunately the COM interceptor does not intrinsically handle array
+ * outparams. Instead we manually define the relevant metadata here, and
+ * register it in a call to mozilla::mscom::RegisterArrayData.
+ * @see mozilla::mscom::ArrayData
+ */
+static const mozilla::mscom::ArrayData sPlatformChildArrayData[] = {
+  {IID_IEnumVARIANT, 3, 1, VT_DISPATCH, IID_IDispatch, 2},
+  {IID_IAccessible2, 30, 1, VT_UNKNOWN | VT_BYREF, IID_IAccessibleRelation, 2},
+  {IID_IAccessibleRelation, 7, 1, VT_UNKNOWN | VT_BYREF, IID_IUnknown, 2}
+};
+
+// Type libraries are thread-neutral, so we can register those from any
+// apartment. OTOH, proxies must be registered from within the apartment where
+// we intend to instantiate them. Therefore RegisterProxy() must be called
+// via EnsureMTA.
+PlatformChild::PlatformChild()
+  : mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll",
+        mozilla::mscom::RegistrationFlags::eUseSystemDirectory))
+  , mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb"))
+{
+  mozilla::mscom::InterceptorLog::Init();
+  mozilla::mscom::RegisterArrayData(sPlatformChildArrayData);
+
+  UniquePtr<mozilla::mscom::RegisteredProxy> ia2Proxy;
+  mozilla::mscom::EnsureMTA([&ia2Proxy]() -> void {
+    ia2Proxy = Move(mozilla::mscom::RegisterProxy(L"ia2marshal.dll"));
+  });
+  mIA2Proxy = Move(ia2Proxy);
+}
+
+} // namespace a11y
+} // namespace mozilla
+
new file mode 100644
--- /dev/null
+++ b/accessible/ipc/win/PlatformChild.h
@@ -0,0 +1,35 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_a11y_PlatformChild_h
+#define mozilla_a11y_PlatformChild_h
+
+#include "mozilla/mscom/Registration.h"
+
+namespace mozilla {
+namespace a11y {
+
+class PlatformChild
+{
+public:
+  PlatformChild();
+
+  PlatformChild(PlatformChild&) = delete;
+  PlatformChild(PlatformChild&&) = delete;
+  PlatformChild& operator=(PlatformChild&) = delete;
+  PlatformChild& operator=(PlatformChild&&) = delete;
+
+private:
+  UniquePtr<mozilla::mscom::RegisteredProxy> mIA2Proxy;
+  UniquePtr<mozilla::mscom::RegisteredProxy> mAccTypelib;
+  UniquePtr<mozilla::mscom::RegisteredProxy> mMiscTypelib;
+};
+
+} // namespace mozilla
+} // namespace a11y
+
+#endif // mozilla_a11y_PlatformChild_h
+
--- a/accessible/ipc/win/moz.build
+++ b/accessible/ipc/win/moz.build
@@ -7,22 +7,24 @@
 IPDL_SOURCES += ['PDocAccessible.ipdl']
 
 # with --disable-accessibility we need to compile PDocAccessible.ipdl, but not
 # the C++.
 if CONFIG['ACCESSIBILITY']:
     EXPORTS.mozilla.a11y += [
         'COMPtrTypes.h',
         'DocAccessibleChild.h',
+        'PlatformChild.h',
         'ProxyAccessible.h'
     ]
 
     SOURCES += [
         'COMPtrTypes.cpp',
         'DocAccessibleChild.cpp',
+        'PlatformChild.cpp',
         'ProxyAccessible.cpp',
     ]
 
     LOCAL_INCLUDES += [
         '/accessible/base',
         '/accessible/generic',
         '/accessible/windows/ia2',
         '/accessible/windows/msaa',
--- a/accessible/windows/msaa/DocAccessibleWrap.cpp
+++ b/accessible/windows/msaa/DocAccessibleWrap.cpp
@@ -2,16 +2,17 @@
 /* vim: set ts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "DocAccessibleWrap.h"
 
 #include "Compatibility.h"
+#include "DocAccessibleChild.h"
 #include "nsWinUtils.h"
 #include "mozilla/dom/TabChild.h"
 #include "Role.h"
 #include "RootAccessible.h"
 #include "sdnDocAccessible.h"
 #include "Statistics.h"
 
 #include "nsIDocShell.h"
@@ -39,16 +40,40 @@ IMPL_IUNKNOWN_QUERY_HEAD(DocAccessibleWr
     statistics::ISimpleDOMUsed();
     *aInstancePtr = static_cast<ISimpleDOMDocument*>(new sdnDocAccessible(this));
     static_cast<IUnknown*>(*aInstancePtr)->AddRef();
     return S_OK;
   }
 IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(HyperTextAccessibleWrap)
 
 STDMETHODIMP
+DocAccessibleWrap::get_accParent(
+      /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispParent)
+{
+  if (!Parent()) {
+    *ppdispParent = nullptr;
+    return S_FALSE;
+  }
+
+  if (!IPCDoc()) {
+    return DocAccessible::get_accParent(ppdispParent);
+  }
+
+  IAccessible* dispParent = IPCDoc()->GetParentIAccessible();
+  MOZ_ASSERT(dispParent);
+  if (!dispParent) {
+    return E_UNEXPECTED;
+  }
+
+  dispParent->AddRef();
+  *ppdispParent = static_cast<IDispatch*>(dispParent);
+  return S_OK;
+}
+
+STDMETHODIMP
 DocAccessibleWrap::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aValue)
     return E_INVALIDARG;
   *aValue = nullptr;
 
--- a/accessible/windows/msaa/DocAccessibleWrap.h
+++ b/accessible/windows/msaa/DocAccessibleWrap.h
@@ -17,20 +17,24 @@ class DocAccessibleWrap : public DocAcce
 public:
   DocAccessibleWrap(nsIDocument* aDocument, nsIPresShell* aPresShell);
   virtual ~DocAccessibleWrap();
 
   DECL_IUNKNOWN_INHERITED
 
   // IAccessible
 
-    // Override get_accValue to provide URL when no other value is available
-    virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue( 
-        /* [optional][in] */ VARIANT varChild,
-        /* [retval][out] */ BSTR __RPC_FAR *pszValue);
+  // Override get_accParent for e10s
+  virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accParent(
+      /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispParent) override;
+
+  // Override get_accValue to provide URL when no other value is available
+  virtual /* [id][propget] */ HRESULT STDMETHODCALLTYPE get_accValue(
+      /* [optional][in] */ VARIANT varChild,
+      /* [retval][out] */ BSTR __RPC_FAR *pszValue) override;
 
   // Accessible
   virtual void Shutdown();
 
   // DocAccessible
   virtual void* GetNativeWindow() const;
 
   /**
--- a/accessible/windows/msaa/Platform.cpp
+++ b/accessible/windows/msaa/Platform.cpp
@@ -5,38 +5,63 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Platform.h"
 
 #include "AccEvent.h"
 #include "Compatibility.h"
 #include "HyperTextAccessibleWrap.h"
 #include "ia2AccessibleText.h"
+#include "nsIXULRuntime.h"
 #include "nsWinUtils.h"
 #include "mozilla/a11y/ProxyAccessible.h"
+#include "mozilla/mscom/InterceptorLog.h"
+#include "mozilla/mscom/Registration.h"
+#include "mozilla/StaticPtr.h"
 #include "ProxyWrappers.h"
 
 using namespace mozilla;
 using namespace mozilla::a11y;
+using namespace mozilla::mscom;
+
+static StaticAutoPtr<RegisteredProxy> gRegProxy;
+static StaticAutoPtr<RegisteredProxy> gRegAccTlb;
+static StaticAutoPtr<RegisteredProxy> gRegMiscTlb;
 
 void
 a11y::PlatformInit()
 {
   Compatibility::Init();
 
   nsWinUtils::MaybeStartWindowEmulation();
   ia2AccessibleText::InitTextChangeData();
+  if (BrowserTabsRemoteAutostart()) {
+    mscom::InterceptorLog::Init();
+    UniquePtr<RegisteredProxy> regProxy(
+        mscom::RegisterProxy(L"ia2marshal.dll"));
+    gRegProxy = regProxy.release();
+    UniquePtr<RegisteredProxy> regAccTlb(
+        mscom::RegisterTypelib(L"oleacc.dll",
+                               RegistrationFlags::eUseSystemDirectory));
+    gRegAccTlb = regAccTlb.release();
+    UniquePtr<RegisteredProxy> regMiscTlb(
+        mscom::RegisterTypelib(L"Accessible.tlb"));
+    gRegMiscTlb = regMiscTlb.release();
+  }
 }
 
 void
 a11y::PlatformShutdown()
 {
   ::DestroyCaret();
 
   nsWinUtils::ShutdownWindowEmulation();
+  gRegProxy = nullptr;
+  gRegAccTlb = nullptr;
+  gRegMiscTlb = nullptr;
 }
 
 void
 a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
   AccessibleWrap* wrapper = nullptr;
   if (aInterfaces & Interfaces::DOCUMENT) {
     wrapper = new DocProxyAccessibleWrap(aProxy);