зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1694865 part 13: Move DocAccessibleWrap's MSAA overrides to a new MsaaDocAccessible class. r=morgan
For now, DocAccessibleWrap inherits from MsaaDocAccessible and MsaaDocAccessible inherits from DocAccessible. DocAccessible calls are made via a DocAcc() method which in turn calls MsaaAccessible::LocalAcc(). Since MsaaAccessible::LocalAcc() returns null if defunct, defunct checks have been adjusted accordingly. Differential Revision: https://phabricator.services.mozilla.com/D112945
This commit is contained in:
Родитель
7c5d88731c
Коммит
29737325ac
|
@ -8,18 +8,13 @@
|
|||
|
||||
#include "Compatibility.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/dom/BrowserChild.h"
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "DocAccessibleChild.h"
|
||||
#include "nsWinUtils.h"
|
||||
#include "Role.h"
|
||||
#include "RootAccessible.h"
|
||||
#include "sdnDocAccessible.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
|
@ -29,7 +24,7 @@ using namespace mozilla::a11y;
|
|||
|
||||
DocAccessibleWrap::DocAccessibleWrap(dom::Document* aDocument,
|
||||
PresShell* aPresShell)
|
||||
: DocAccessible(aDocument, aPresShell), mHWND(nullptr) {}
|
||||
: MsaaDocAccessible(aDocument, aPresShell), mHWND(nullptr) {}
|
||||
|
||||
DocAccessibleWrap::~DocAccessibleWrap() {}
|
||||
|
||||
|
@ -42,97 +37,6 @@ if (aIID == IID_ISimpleDOMDocument) {
|
|||
}
|
||||
IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(HyperTextAccessibleWrap)
|
||||
|
||||
STDMETHODIMP
|
||||
DocAccessibleWrap::get_accParent(
|
||||
/* [retval][out] */ IDispatch __RPC_FAR* __RPC_FAR* ppdispParent) {
|
||||
if (IsDefunct()) {
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
|
||||
// We might be a top-level document in a content process.
|
||||
DocAccessibleChild* ipcDoc = IPCDoc();
|
||||
if (ipcDoc && static_cast<dom::BrowserChild*>(ipcDoc->Manager())
|
||||
->GetTopLevelDocAccessibleChild() == ipcDoc) {
|
||||
// Emulated window proxy is only set for the top level content document when
|
||||
// emulation is enabled.
|
||||
RefPtr<IDispatch> dispParent = ipcDoc->GetEmulatedWindowIAccessible();
|
||||
if (!dispParent) {
|
||||
dispParent = ipcDoc->GetParentIAccessible();
|
||||
}
|
||||
|
||||
if (!dispParent) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
dispParent.forget(ppdispParent);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// In the parent process, return window system accessible object for root
|
||||
// document accessibles, as well as tab document accessibles if window
|
||||
// emulation is enabled.
|
||||
if (XRE_IsParentProcess() &&
|
||||
(!ParentDocument() ||
|
||||
(nsWinUtils::IsWindowEmulationStarted() &&
|
||||
nsCoreUtils::IsTopLevelContentDocInProcess(DocumentNode())))) {
|
||||
HWND hwnd = static_cast<HWND>(GetNativeWindow());
|
||||
if (hwnd && !ParentDocument()) {
|
||||
nsIFrame* frame = GetFrame();
|
||||
if (frame) {
|
||||
nsIWidget* widget = frame->GetNearestWidget();
|
||||
if (widget->WindowType() == eWindowType_child && !widget->GetParent()) {
|
||||
// Bug 1427304: Windows opened with popup=yes (such as the WebRTC
|
||||
// sharing indicator) get two HWNDs. The root widget is associated
|
||||
// with the inner HWND, but the outer HWND still answers to
|
||||
// WM_GETOBJECT queries. This means that getting the parent of the
|
||||
// oleacc window accessible for the inner HWND returns this
|
||||
// root accessible. Thus, to avoid a loop, we must never return the
|
||||
// oleacc window accessible for the inner HWND. Instead, we use the
|
||||
// outer HWND here.
|
||||
HWND parentHwnd = ::GetParent(hwnd);
|
||||
if (parentHwnd) {
|
||||
MOZ_ASSERT(::GetWindowLongW(parentHwnd, GWL_STYLE) & WS_POPUP,
|
||||
"Parent HWND should be a popup!");
|
||||
hwnd = parentHwnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hwnd &&
|
||||
SUCCEEDED(::AccessibleObjectFromWindow(
|
||||
hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent))) {
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return DocAccessible::get_accParent(ppdispParent);
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
DocAccessibleWrap::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue) {
|
||||
if (!aValue) return E_INVALIDARG;
|
||||
*aValue = nullptr;
|
||||
|
||||
// For backwards-compat, we still support old MSAA hack to provide URL in
|
||||
// accValue Check for real value first
|
||||
HRESULT hr = AccessibleWrap::get_accValue(aVarChild, aValue);
|
||||
if (FAILED(hr) || *aValue || aVarChild.lVal != CHILDID_SELF) return hr;
|
||||
|
||||
// If document is being used to create a widget, don't use the URL hack
|
||||
roles::Role role = Role();
|
||||
if (role != roles::DOCUMENT && role != roles::APPLICATION &&
|
||||
role != roles::DIALOG && role != roles::ALERT &&
|
||||
role != roles::NON_NATIVE_DOCUMENT)
|
||||
return hr;
|
||||
|
||||
nsAutoString url;
|
||||
URL(url);
|
||||
if (url.IsEmpty()) return S_FALSE;
|
||||
|
||||
*aValue = ::SysAllocStringLen(url.get(), url.Length());
|
||||
return *aValue ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// LocalAccessible
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef mozilla_a11y_DocAccessibleWrap_h__
|
||||
#define mozilla_a11y_DocAccessibleWrap_h__
|
||||
|
||||
#include "DocAccessible.h"
|
||||
#include "MsaaDocAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -15,53 +15,24 @@ class PresShell;
|
|||
|
||||
namespace a11y {
|
||||
|
||||
class DocAccessibleWrap : public DocAccessible {
|
||||
class DocAccessibleWrap : public MsaaDocAccessible {
|
||||
public:
|
||||
DocAccessibleWrap(dom::Document* aDocument, PresShell* aPresShell);
|
||||
virtual ~DocAccessibleWrap();
|
||||
|
||||
DECL_IUNKNOWN_INHERITED
|
||||
|
||||
// IAccessible
|
||||
|
||||
// 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;
|
||||
|
||||
// LocalAccessible
|
||||
virtual void Shutdown();
|
||||
|
||||
// DocAccessible
|
||||
virtual void* GetNativeWindow() const;
|
||||
|
||||
/**
|
||||
* Manage the mapping from id to Accessible.
|
||||
*/
|
||||
void AddID(uint32_t aID, AccessibleWrap* aAcc) {
|
||||
mIDToAccessibleMap.InsertOrUpdate(aID, aAcc);
|
||||
}
|
||||
void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
|
||||
AccessibleWrap* GetAccessibleByID(uint32_t aID) const {
|
||||
return mIDToAccessibleMap.Get(aID);
|
||||
}
|
||||
|
||||
protected:
|
||||
// DocAccessible
|
||||
virtual void DoInitialUpdate();
|
||||
|
||||
protected:
|
||||
void* mHWND;
|
||||
|
||||
/*
|
||||
* This provides a mapping from 32 bit id to accessible objects.
|
||||
*/
|
||||
nsTHashMap<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
|
||||
// DocAccessible
|
||||
virtual void DoInitialUpdate();
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/* -*- 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 "MsaaDocAccessible.h"
|
||||
|
||||
#include "DocAccessibleChild.h"
|
||||
#include "nsWinUtils.h"
|
||||
#include "Role.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::a11y;
|
||||
|
||||
DocAccessible* MsaaDocAccessible::DocAcc() {
|
||||
// XXX This first static_cast is a necessary hack until we get rid of the
|
||||
// inheritance of DocAccessibleWrap.
|
||||
auto wrap = static_cast<DocAccessible*>(this);
|
||||
AccessibleWrap* acc = static_cast<MsaaAccessible*>(wrap)->LocalAcc();
|
||||
return static_cast<DocAccessible*>(acc);
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
MsaaDocAccessible::get_accParent(
|
||||
/* [retval][out] */ IDispatch __RPC_FAR* __RPC_FAR* ppdispParent) {
|
||||
DocAccessible* docAcc = DocAcc();
|
||||
if (!docAcc) {
|
||||
return CO_E_OBJNOTCONNECTED;
|
||||
}
|
||||
|
||||
// We might be a top-level document in a content process.
|
||||
DocAccessibleChild* ipcDoc = docAcc->IPCDoc();
|
||||
if (ipcDoc && static_cast<dom::BrowserChild*>(ipcDoc->Manager())
|
||||
->GetTopLevelDocAccessibleChild() == ipcDoc) {
|
||||
// Emulated window proxy is only set for the top level content document when
|
||||
// emulation is enabled.
|
||||
RefPtr<IDispatch> dispParent = ipcDoc->GetEmulatedWindowIAccessible();
|
||||
if (!dispParent) {
|
||||
dispParent = ipcDoc->GetParentIAccessible();
|
||||
}
|
||||
|
||||
if (!dispParent) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
dispParent.forget(ppdispParent);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// In the parent process, return window system accessible object for root
|
||||
// document accessibles, as well as tab document accessibles if window
|
||||
// emulation is enabled.
|
||||
if (XRE_IsParentProcess() &&
|
||||
(!docAcc->ParentDocument() ||
|
||||
(nsWinUtils::IsWindowEmulationStarted() &&
|
||||
nsCoreUtils::IsTopLevelContentDocInProcess(docAcc->DocumentNode())))) {
|
||||
HWND hwnd = static_cast<HWND>(docAcc->GetNativeWindow());
|
||||
if (hwnd && !docAcc->ParentDocument()) {
|
||||
nsIFrame* frame = docAcc->GetFrame();
|
||||
if (frame) {
|
||||
nsIWidget* widget = frame->GetNearestWidget();
|
||||
if (widget->WindowType() == eWindowType_child && !widget->GetParent()) {
|
||||
// Bug 1427304: Windows opened with popup=yes (such as the WebRTC
|
||||
// sharing indicator) get two HWNDs. The root widget is associated
|
||||
// with the inner HWND, but the outer HWND still answers to
|
||||
// WM_GETOBJECT queries. This means that getting the parent of the
|
||||
// oleacc window accessible for the inner HWND returns this
|
||||
// root accessible. Thus, to avoid a loop, we must never return the
|
||||
// oleacc window accessible for the inner HWND. Instead, we use the
|
||||
// outer HWND here.
|
||||
HWND parentHwnd = ::GetParent(hwnd);
|
||||
if (parentHwnd) {
|
||||
MOZ_ASSERT(::GetWindowLongW(parentHwnd, GWL_STYLE) & WS_POPUP,
|
||||
"Parent HWND should be a popup!");
|
||||
hwnd = parentHwnd;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hwnd &&
|
||||
SUCCEEDED(::AccessibleObjectFromWindow(
|
||||
hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent))) {
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return MsaaAccessible::get_accParent(ppdispParent);
|
||||
}
|
||||
|
||||
STDMETHODIMP
|
||||
MsaaDocAccessible::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue) {
|
||||
if (!aValue) return E_INVALIDARG;
|
||||
*aValue = nullptr;
|
||||
|
||||
// For backwards-compat, we still support old MSAA hack to provide URL in
|
||||
// accValue Check for real value first
|
||||
HRESULT hr = MsaaAccessible::get_accValue(aVarChild, aValue);
|
||||
if (FAILED(hr) || *aValue || aVarChild.lVal != CHILDID_SELF) return hr;
|
||||
|
||||
DocAccessible* docAcc = DocAcc();
|
||||
// MsaaAccessible::get_accValue should have failed (and thus we should have
|
||||
// returned early) if the Accessible is dead.
|
||||
MOZ_ASSERT(docAcc);
|
||||
// If document is being used to create a widget, don't use the URL hack
|
||||
roles::Role role = docAcc->Role();
|
||||
if (role != roles::DOCUMENT && role != roles::APPLICATION &&
|
||||
role != roles::DIALOG && role != roles::ALERT &&
|
||||
role != roles::NON_NATIVE_DOCUMENT)
|
||||
return hr;
|
||||
|
||||
nsAutoString url;
|
||||
docAcc->URL(url);
|
||||
if (url.IsEmpty()) return S_FALSE;
|
||||
|
||||
*aValue = ::SysAllocStringLen(url.get(), url.Length());
|
||||
return *aValue ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
/* -*- 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_MsaaDocAccessible_h__
|
||||
#define mozilla_a11y_MsaaDocAccessible_h__
|
||||
|
||||
#include "DocAccessible.h"
|
||||
#include "MsaaAccessible.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class PresShell;
|
||||
|
||||
namespace a11y {
|
||||
class DocAccessible;
|
||||
|
||||
// XXX This should inherit from MsaaAccessible. Inheriting from DocAccessible
|
||||
// is a necessary hack until we remove the inheritance of DocAccessibleWrap.
|
||||
class MsaaDocAccessible : public DocAccessible {
|
||||
public:
|
||||
MsaaDocAccessible(dom::Document* aDocument, PresShell* aPresShell)
|
||||
: DocAccessible(aDocument, aPresShell) {}
|
||||
|
||||
// IAccessible
|
||||
|
||||
// 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;
|
||||
|
||||
/**
|
||||
* Manage the mapping from id to Accessible.
|
||||
*/
|
||||
void AddID(uint32_t aID, AccessibleWrap* aAcc) {
|
||||
mIDToAccessibleMap.InsertOrUpdate(aID, aAcc);
|
||||
}
|
||||
void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
|
||||
AccessibleWrap* GetAccessibleByID(uint32_t aID) const {
|
||||
return mIDToAccessibleMap.Get(aID);
|
||||
}
|
||||
|
||||
protected:
|
||||
/*
|
||||
* This provides a mapping from 32 bit id to accessible objects.
|
||||
*/
|
||||
nsTHashMap<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
|
||||
|
||||
private:
|
||||
DocAccessible* DocAcc();
|
||||
};
|
||||
|
||||
} // namespace a11y
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -32,6 +32,7 @@ UNIFIED_SOURCES += [
|
|||
"ImageAccessibleWrap.cpp",
|
||||
"IUnknownImpl.cpp",
|
||||
"MsaaAccessible.cpp",
|
||||
"MsaaDocAccessible.cpp",
|
||||
"MsaaIdGenerator.cpp",
|
||||
"nsWinUtils.cpp",
|
||||
"Platform.cpp",
|
||||
|
|
Загрузка…
Ссылка в новой задаче