MsaaDocAccessible.cpp (4155B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "MsaaDocAccessible.h" 8 9 #include "MsaaDocAccessible.h" 10 #include "DocAccessibleChild.h" 11 #include "mozilla/a11y/DocAccessibleParent.h" 12 #include "nsAccessibilityService.h" 13 #include "nsAccUtils.h" 14 #include "nsWinUtils.h" 15 #include "mozilla/a11y/Role.h" 16 #include "ISimpleDOM.h" 17 18 using namespace mozilla; 19 using namespace mozilla::a11y; 20 21 DocAccessible* MsaaDocAccessible::DocAcc() { 22 return static_cast<DocAccessible*>(LocalAcc()); 23 } 24 25 /* static */ 26 MsaaDocAccessible* MsaaDocAccessible::GetFrom(DocAccessible* aDoc) { 27 return static_cast<MsaaDocAccessible*>(MsaaAccessible::GetFrom(aDoc)); 28 } 29 30 /* static */ 31 MsaaDocAccessible* MsaaDocAccessible::GetFrom(DocAccessibleParent* aDoc) { 32 return static_cast<MsaaDocAccessible*>( 33 reinterpret_cast<MsaaAccessible*>(aDoc->GetWrapper())); 34 } 35 36 /* static */ 37 MsaaDocAccessible* MsaaDocAccessible::GetFromOwned(Accessible* aAcc) { 38 if (RemoteAccessible* remoteAcc = aAcc->AsRemote()) { 39 DocAccessibleParent* doc = remoteAcc->Document(); 40 if (!doc) { 41 return nullptr; 42 } 43 return MsaaDocAccessible::GetFrom(doc); 44 } 45 DocAccessible* doc = aAcc->AsLocal()->Document(); 46 if (!doc) { 47 return nullptr; 48 } 49 return MsaaDocAccessible::GetFrom(doc); 50 } 51 52 // IUnknown 53 IMPL_IUNKNOWN_QUERY_HEAD(MsaaDocAccessible) 54 IMPL_IUNKNOWN_QUERY_TAIL_INHERITED(ia2AccessibleHypertext) 55 56 STDMETHODIMP 57 MsaaDocAccessible::get_accParent( 58 /* [retval][out] */ IDispatch __RPC_FAR* __RPC_FAR* ppdispParent) { 59 if (!mAcc) { 60 return CO_E_OBJNOTCONNECTED; 61 } 62 63 if (mAcc->IsRemote()) { 64 DocAccessibleParent* remoteDoc = mAcc->AsRemote()->AsDoc(); 65 if (nsWinUtils::IsWindowEmulationStarted() && remoteDoc->IsTopLevel()) { 66 // Window emulation is enabled and this is a top level document. Return 67 // window system accessible object. 68 HWND hwnd = remoteDoc->GetEmulatedWindowHandle(); 69 MOZ_ASSERT(hwnd); 70 if (hwnd && 71 SUCCEEDED(::CreateStdAccessibleObject( 72 hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent))) { 73 return S_OK; 74 } 75 } 76 return MsaaAccessible::get_accParent(ppdispParent); 77 } 78 79 DocAccessible* docAcc = DocAcc(); 80 MOZ_ASSERT(docAcc); 81 82 // Return window system accessible object for root document accessibles, as 83 // well as tab document accessibles if window emulation is enabled. 84 MOZ_ASSERT(XRE_IsParentProcess()); 85 if ((!docAcc->ParentDocument() || 86 (nsWinUtils::IsWindowEmulationStarted() && 87 nsCoreUtils::IsTopLevelContentDocInProcess(docAcc->DocumentNode())))) { 88 HWND hwnd = static_cast<HWND>(docAcc->GetNativeWindow()); 89 if (hwnd && 90 SUCCEEDED(::CreateStdAccessibleObject( 91 hwnd, OBJID_WINDOW, IID_IAccessible, (void**)ppdispParent))) { 92 return S_OK; 93 } 94 } 95 96 return MsaaAccessible::get_accParent(ppdispParent); 97 } 98 99 STDMETHODIMP 100 MsaaDocAccessible::get_accValue(VARIANT aVarChild, BSTR __RPC_FAR* aValue) { 101 if (!aValue) return E_INVALIDARG; 102 *aValue = nullptr; 103 104 // For backwards-compat, we still support old MSAA hack to provide URL in 105 // accValue Check for real value first 106 HRESULT hr = MsaaAccessible::get_accValue(aVarChild, aValue); 107 if (FAILED(hr) || *aValue || aVarChild.lVal != CHILDID_SELF) return hr; 108 109 // MsaaAccessible::get_accValue should have failed (and thus we should have 110 // returned early) if the Accessible is dead. 111 MOZ_ASSERT(mAcc); 112 // If document is being used to create a widget, don't use the URL hack 113 roles::Role role = mAcc->Role(); 114 if (role != roles::DOCUMENT && role != roles::APPLICATION && 115 role != roles::DIALOG && role != roles::ALERT && 116 role != roles::NON_NATIVE_DOCUMENT) 117 return hr; 118 119 nsAutoString url; 120 nsAccUtils::DocumentURL(mAcc, url); 121 if (url.IsEmpty()) return S_FALSE; 122 123 *aValue = ::SysAllocStringLen(url.get(), url.Length()); 124 return *aValue ? S_OK : E_OUTOFMEMORY; 125 }