125 lines
4.1 KiB
C++
125 lines
4.1 KiB
C++
/* -*- 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 "MsaaDocAccessible.h"
|
|
#include "DocAccessibleChild.h"
|
|
#include "mozilla/a11y/DocAccessibleParent.h"
|
|
#include "nsAccessibilityService.h"
|
|
#include "nsAccUtils.h"
|
|
#include "nsWinUtils.h"
|
|
#include "mozilla/a11y/Role.h"
|
|
#include "ISimpleDOM.h"
|
|
|
|
using namespace mozilla;
|
|
using namespace mozilla::a11y;
|
|
|
|
DocAccessible* MsaaDocAccessible::DocAcc() {
|
|
return static_cast<DocAccessible*>(LocalAcc());
|
|
}
|
|
|
|
/* static */
|
|
MsaaDocAccessible* MsaaDocAccessible::GetFrom(DocAccessible* aDoc) {
|
|
return static_cast<MsaaDocAccessible*>(MsaaAccessible::GetFrom(aDoc));
|
|
}
|
|
|
|
/* static */
|
|
MsaaDocAccessible* MsaaDocAccessible::GetFrom(DocAccessibleParent* aDoc) {
|
|
return static_cast<MsaaDocAccessible*>(
|
|
reinterpret_cast<MsaaAccessible*>(aDoc->GetWrapper()));
|
|
}
|
|
|
|
/* static */
|
|
MsaaDocAccessible* MsaaDocAccessible::GetFromOwned(Accessible* aAcc) {
|
|
if (RemoteAccessible* remoteAcc = aAcc->AsRemote()) {
|
|
DocAccessibleParent* doc = remoteAcc->Document();
|
|
if (!doc) {
|
|
return nullptr;
|
|
}
|
|
return MsaaDocAccessible::GetFrom(doc);
|
|
}
|
|
DocAccessible* doc = aAcc->AsLocal()->Document();
|
|
if (!doc) {
|
|
return nullptr;
|
|
}
|
|
return MsaaDocAccessible::GetFrom(doc);
|
|
}
|
|
|
|
// IUnknown
|
|
IMPL_IUNKNOWN_QUERY_HEAD(MsaaDocAccessible)
|
|
IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(ia2AccessibleHypertext)
|
|
|
|
STDMETHODIMP
|
|
MsaaDocAccessible::get_accParent(
|
|
/* [retval][out] */ IDispatch __RPC_FAR* __RPC_FAR* ppdispParent) {
|
|
if (!mAcc) {
|
|
return CO_E_OBJNOTCONNECTED;
|
|
}
|
|
|
|
if (mAcc->IsRemote()) {
|
|
DocAccessibleParent* remoteDoc = mAcc->AsRemote()->AsDoc();
|
|
if (nsWinUtils::IsWindowEmulationStarted() && remoteDoc->IsTopLevel()) {
|
|
// Window emulation is enabled and this is a top level document. Return
|
|
// window system accessible object.
|
|
HWND hwnd = remoteDoc->GetEmulatedWindowHandle();
|
|
MOZ_ASSERT(hwnd);
|
|
if (hwnd &&
|
|
SUCCEEDED(::CreateStdAccessibleObject(
|
|
hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent))) {
|
|
return S_OK;
|
|
}
|
|
}
|
|
return MsaaAccessible::get_accParent(ppdispParent);
|
|
}
|
|
|
|
DocAccessible* docAcc = DocAcc();
|
|
MOZ_ASSERT(docAcc);
|
|
|
|
// Return window system accessible object for root document accessibles, as
|
|
// well as tab document accessibles if window emulation is enabled.
|
|
MOZ_ASSERT(XRE_IsParentProcess());
|
|
if ((!docAcc->ParentDocument() ||
|
|
(nsWinUtils::IsWindowEmulationStarted() &&
|
|
nsCoreUtils::IsTopLevelContentDocInProcess(docAcc->DocumentNode())))) {
|
|
HWND hwnd = static_cast<HWND>(docAcc->GetNativeWindow());
|
|
if (hwnd &&
|
|
SUCCEEDED(::CreateStdAccessibleObject(
|
|
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;
|
|
|
|
// MsaaAccessible::get_accValue should have failed (and thus we should have
|
|
// returned early) if the Accessible is dead.
|
|
MOZ_ASSERT(mAcc);
|
|
// If document is being used to create a widget, don't use the URL hack
|
|
roles::Role role = mAcc->Role();
|
|
if (role != roles::DOCUMENT && role != roles::APPLICATION &&
|
|
role != roles::DIALOG && role != roles::ALERT &&
|
|
role != roles::NON_NATIVE_DOCUMENT)
|
|
return hr;
|
|
|
|
nsAutoString url;
|
|
nsAccUtils::DocumentURL(mAcc, url);
|
|
if (url.IsEmpty()) return S_FALSE;
|
|
|
|
*aValue = ::SysAllocStringLen(url.get(), url.Length());
|
|
return *aValue ? S_OK : E_OUTOFMEMORY;
|
|
}
|