1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=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/. */
7 #include "ServiceProvider.h"
9 #include "AccessibleApplication_i.c"
10 #include "ApplicationAccessibleWrap.h"
11 #include "DocAccessible.h"
12 #include "nsAccUtils.h"
13 #include "nsCoreUtils.h"
15 #include "RootAccessible.h"
16 #include "uiaRawElmProvider.h"
18 #include "mozilla/a11y/DocAccessibleChild.h"
19 #include "mozilla/Preferences.h"
21 #include "ISimpleDOM.h"
26 IMPL_IUNKNOWN_QUERY_HEAD(ServiceProvider
)
27 IMPL_IUNKNOWN_QUERY_IFACE(IServiceProvider
)
28 IMPL_IUNKNOWN_QUERY_TAIL_AGGREGATED(mMsaa
)
30 ////////////////////////////////////////////////////////////////////////////////
34 ServiceProvider::QueryService(REFGUID aGuidService
, REFIID aIID
,
35 void** aInstancePtr
) {
36 if (!aInstancePtr
) return E_INVALIDARG
;
38 *aInstancePtr
= nullptr;
39 Accessible
* acc
= mMsaa
->Acc();
41 return CO_E_OBJNOTCONNECTED
;
43 AccessibleWrap
* localAcc
= mMsaa
->LocalAcc();
46 if (aGuidService
== IID_IAccessibleEx
&&
47 Preferences::GetBool("accessibility.uia.enable") && localAcc
) {
48 uiaRawElmProvider
* accEx
= new uiaRawElmProvider(localAcc
);
49 HRESULT hr
= accEx
->QueryInterface(aIID
, aInstancePtr
);
50 if (FAILED(hr
)) delete accEx
;
55 // Provide a special service ID for getting the accessible for the browser tab
56 // document that contains this accessible object. If this accessible object
57 // is not inside a browser tab then the service fails with E_NOINTERFACE.
58 // A use case for this is for screen readers that need to switch context or
59 // 'virtual buffer' when focus moves from one browser tab area to another.
60 static const GUID SID_IAccessibleContentDocument
= {
64 {0x95, 0x21, 0x07, 0xed, 0x28, 0xfb, 0x07, 0x2e}};
65 if (aGuidService
== SID_IAccessibleContentDocument
&& localAcc
) {
66 if (aIID
!= IID_IAccessible
) return E_NOINTERFACE
;
68 // If acc is within an OOP iframe document, the top level document
69 // lives in a different process.
70 if (XRE_IsContentProcess()) {
71 RootAccessible
* root
= localAcc
->RootAccessible();
72 // root will be null if acc is the ApplicationAccessible.
74 DocAccessibleChild
* ipcDoc
= root
->IPCDoc();
76 RefPtr
<IAccessible
> topDoc
= ipcDoc
->GetTopLevelDocIAccessible();
77 // topDoc will be null if this isn't an OOP iframe document.
79 topDoc
.forget(aInstancePtr
);
86 Relation rel
= localAcc
->RelationByType(RelationType::CONTAINING_TAB_PANE
);
87 AccessibleWrap
* tabDoc
= static_cast<AccessibleWrap
*>(rel
.Next());
88 if (!tabDoc
) return E_NOINTERFACE
;
90 RefPtr
<IAccessible
> result
;
91 tabDoc
->GetNativeInterface(getter_AddRefs(result
));
92 result
.forget(aInstancePtr
);
96 // Can get to IAccessibleApplication from any node via QS
97 // Note: in case of JAWS we want to check if aIID is
98 // IID_IAccessibleApplication.
99 if (aGuidService
== IID_IAccessibleApplication
||
100 aIID
== IID_IAccessibleApplication
) {
101 ApplicationAccessibleWrap
* applicationAcc
=
102 static_cast<ApplicationAccessibleWrap
*>(ApplicationAcc());
103 if (!applicationAcc
) return E_NOINTERFACE
;
105 RefPtr
<IAccessible
> appIa
;
106 applicationAcc
->GetNativeInterface(getter_AddRefs(appIa
));
107 return appIa
->QueryInterface(aIID
, aInstancePtr
);
110 static const GUID IID_SimpleDOMDeprecated
= {
114 {0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}};
115 if (aGuidService
== IID_ISimpleDOMNode
||
116 aGuidService
== IID_SimpleDOMDeprecated
||
117 aGuidService
== IID_IAccessible
|| aGuidService
== IID_IAccessible2
)
118 return mMsaa
->QueryInterface(aIID
, aInstancePtr
);
124 } // namespace mozilla