From 9c133fb86d645d52c0c610b8d68ad14ec7ca6ba2 Mon Sep 17 00:00:00 2001 From: Aaron Klotz Date: Mon, 15 Aug 2016 14:24:12 -0600 Subject: [PATCH] Bug 1268544: Integrate remote COM objects into a11y code; r=tbsaunde MozReview-Commit-ID: ctPgegQ83a --- accessible/base/DocManager.cpp | 5 ++ accessible/base/NotificationController.cpp | 4 ++ accessible/base/Platform.h | 4 ++ accessible/base/moz.build | 12 +++++ accessible/ipc/win/DocAccessibleChild.cpp | 8 +++ accessible/ipc/win/PlatformChild.cpp | 49 +++++++++++++++++++ accessible/ipc/win/PlatformChild.h | 35 +++++++++++++ accessible/ipc/win/moz.build | 2 + accessible/windows/msaa/DocAccessibleWrap.cpp | 26 ++++++++++ accessible/windows/msaa/DocAccessibleWrap.h | 12 +++-- accessible/windows/msaa/Platform.cpp | 25 ++++++++++ 11 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 accessible/ipc/win/PlatformChild.cpp create mode 100644 accessible/ipc/win/PlatformChild.h diff --git a/accessible/base/DocManager.cpp b/accessible/base/DocManager.cpp index dddfdd3715dd..d50fa0f0d4d1 100644 --- a/accessible/base/DocManager.cpp +++ b/accessible/base/DocManager.cpp @@ -515,6 +515,11 @@ DocManager::CreateDocOrRootAccessible(nsIDocument* aDocument) docAcc->SetIPCDoc(ipcDoc); static_cast(tabChild.get())-> SendPDocAccessibleConstructor(ipcDoc, nullptr, 0); + +#if defined(XP_WIN) + IAccessibleHolder holder(CreateHolderFromAccessible(docAcc)); + ipcDoc->SendCOMProxy(holder); +#endif } } } diff --git a/accessible/base/NotificationController.cpp b/accessible/base/NotificationController.cpp index e711ed67ce23..5c47d0aa8a34 100644 --- a/accessible/base/NotificationController.cpp +++ b/accessible/base/NotificationController.cpp @@ -420,6 +420,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime) if (tabChild) { static_cast(tabChild.get())-> SendPDocAccessibleConstructor(ipcDoc, parentIPCDoc, id); +#if defined(XP_WIN) + IAccessibleHolder holder(CreateHolderFromAccessible(childDoc)); + ipcDoc->SendCOMProxy(holder); +#endif } } } diff --git a/accessible/base/Platform.h b/accessible/base/Platform.h index da60a118c433..25204565b897 100644 --- a/accessible/base/Platform.h +++ b/accessible/base/Platform.h @@ -4,6 +4,9 @@ * 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 class nsString; @@ -82,3 +85,4 @@ void ProxySelectionEvent(ProxyAccessible* aTarget, ProxyAccessible* aWidget, } // namespace a11y } // namespace mozilla +#endif // mozilla_a11y_Platform_h diff --git a/accessible/base/moz.build b/accessible/base/moz.build index 92cd0c797497..dcccc4b54c80 100644 --- a/accessible/base/moz.build +++ b/accessible/base/moz.build @@ -63,6 +63,18 @@ 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', diff --git a/accessible/ipc/win/DocAccessibleChild.cpp b/accessible/ipc/win/DocAccessibleChild.cpp index 5231c344d54e..6b278919850d 100644 --- a/accessible/ipc/win/DocAccessibleChild.cpp +++ b/accessible/ipc/win/DocAccessibleChild.cpp @@ -7,14 +7,22 @@ #include "DocAccessibleChild.h" #include "Accessible-inl.h" +#include "mozilla/a11y/PlatformChild.h" +#include "mozilla/ClearOnShutdown.h" namespace mozilla { namespace a11y { +static StaticAutoPtr sPlatformChild; + DocAccessibleChild::DocAccessibleChild(DocAccessible* aDoc) : DocAccessibleChildBase(aDoc) { MOZ_COUNT_CTOR_INHERITED(DocAccessibleChild, DocAccessibleChildBase); + if (!sPlatformChild) { + sPlatformChild = new PlatformChild(); + ClearOnShutdown(&sPlatformChild, ShutdownPhase::ShutdownThreads); + } } DocAccessibleChild::~DocAccessibleChild() diff --git a/accessible/ipc/win/PlatformChild.cpp b/accessible/ipc/win/PlatformChild.cpp new file mode 100644 index 000000000000..b946ed8ee48e --- /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 ia2Proxy; + mozilla::mscom::EnsureMTA([&ia2Proxy]() -> void { + ia2Proxy = Move(mozilla::mscom::RegisterProxy(L"ia2marshal.dll")); + }); + mIA2Proxy = Move(ia2Proxy); +} + +} // namespace a11y +} // namespace mozilla + diff --git a/accessible/ipc/win/PlatformChild.h b/accessible/ipc/win/PlatformChild.h new file mode 100644 index 000000000000..49daf161d7c1 --- /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 mIA2Proxy; + UniquePtr mAccTypelib; + UniquePtr mMiscTypelib; +}; + +} // namespace mozilla +} // namespace a11y + +#endif // mozilla_a11y_PlatformChild_h + diff --git a/accessible/ipc/win/moz.build b/accessible/ipc/win/moz.build index 1238d346dc36..6251a2f7f05b 100644 --- a/accessible/ipc/win/moz.build +++ b/accessible/ipc/win/moz.build @@ -12,12 +12,14 @@ if CONFIG['ACCESSIBILITY']: EXPORTS.mozilla.a11y += [ 'COMPtrTypes.h', 'DocAccessibleChild.h', + 'PlatformChild.h', 'ProxyAccessible.h' ] SOURCES += [ 'COMPtrTypes.cpp', 'DocAccessibleChild.cpp', + 'PlatformChild.cpp', 'ProxyAccessible.cpp', ] diff --git a/accessible/windows/msaa/DocAccessibleWrap.cpp b/accessible/windows/msaa/DocAccessibleWrap.cpp index d2215a996958..04c99e3df877 100644 --- a/accessible/windows/msaa/DocAccessibleWrap.cpp +++ b/accessible/windows/msaa/DocAccessibleWrap.cpp @@ -7,6 +7,7 @@ #include "DocAccessibleWrap.h" #include "Compatibility.h" +#include "DocAccessibleChild.h" #include "nsWinUtils.h" #include "mozilla/dom/TabChild.h" #include "Role.h" @@ -43,6 +44,31 @@ IMPL_IUNKNOWN_QUERY_HEAD(DocAccessibleWrap) } IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(HyperTextAccessibleWrap) +STDMETHODIMP +DocAccessibleWrap::get_accParent( + /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispParent) +{ + HRESULT hr = DocAccessible::get_accParent(ppdispParent); + if (*ppdispParent) { + return hr; + } + + // We might be a top-level document in a content process. + DocAccessibleChild* ipcDoc = IPCDoc(); + if (!ipcDoc) { + return S_FALSE; + } + IAccessible* dispParent = ipcDoc->GetParentIAccessible(); + MOZ_ASSERT(dispParent); + if (!dispParent) { + return E_UNEXPECTED; + } + + dispParent->AddRef(); + *ppdispParent = static_cast(dispParent); + return S_OK; +} + STDMETHODIMP DocAccessibleWrap::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue) { diff --git a/accessible/windows/msaa/DocAccessibleWrap.h b/accessible/windows/msaa/DocAccessibleWrap.h index 8350782d7a05..90ae3d052725 100644 --- a/accessible/windows/msaa/DocAccessibleWrap.h +++ b/accessible/windows/msaa/DocAccessibleWrap.h @@ -22,10 +22,14 @@ public: // 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(); diff --git a/accessible/windows/msaa/Platform.cpp b/accessible/windows/msaa/Platform.cpp index ab66ccd91ced..14fe797d2770 100644 --- a/accessible/windows/msaa/Platform.cpp +++ b/accessible/windows/msaa/Platform.cpp @@ -10,12 +10,21 @@ #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 gRegProxy; +static StaticAutoPtr gRegAccTlb; +static StaticAutoPtr gRegMiscTlb; void a11y::PlatformInit() @@ -24,6 +33,19 @@ a11y::PlatformInit() nsWinUtils::MaybeStartWindowEmulation(); ia2AccessibleText::InitTextChangeData(); + if (BrowserTabsRemoteAutostart()) { + mscom::InterceptorLog::Init(); + UniquePtr regProxy( + mscom::RegisterProxy(L"ia2marshal.dll")); + gRegProxy = regProxy.release(); + UniquePtr regAccTlb( + mscom::RegisterTypelib(L"oleacc.dll", + RegistrationFlags::eUseSystemDirectory)); + gRegAccTlb = regAccTlb.release(); + UniquePtr regMiscTlb( + mscom::RegisterTypelib(L"Accessible.tlb")); + gRegMiscTlb = regMiscTlb.release(); + } } void @@ -32,6 +54,9 @@ a11y::PlatformShutdown() ::DestroyCaret(); nsWinUtils::ShutdownWindowEmulation(); + gRegProxy = nullptr; + gRegAccTlb = nullptr; + gRegMiscTlb = nullptr; } void