1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include "ia2AccessibleAction.h"
9
10 #include "AccessibleAction_i.c"
11
12 #include "AccessibleWrap.h"
13 #include "IUnknownImpl.h"
14
15 using namespace mozilla::a11y;
16
17 // IUnknown
18
19 STDMETHODIMP
QueryInterface(REFIID iid,void ** ppv)20 ia2AccessibleAction::QueryInterface(REFIID iid, void** ppv)
21 {
22 if (!ppv)
23 return E_INVALIDARG;
24
25 *ppv = nullptr;
26
27 if (IID_IAccessibleAction == iid &&
28 !static_cast<AccessibleWrap*>(this)->IsProxy()) {
29 *ppv = static_cast<IAccessibleAction*>(this);
30 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
31 return S_OK;
32 }
33
34 return E_NOINTERFACE;
35 }
36
37 // IAccessibleAction
38
39 STDMETHODIMP
nActions(long * aActionCount)40 ia2AccessibleAction::nActions(long* aActionCount)
41 {
42 A11Y_TRYBLOCK_BEGIN
43
44 if (!aActionCount)
45 return E_INVALIDARG;
46
47 *aActionCount = 0;
48
49 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
50 if (acc->IsDefunct())
51 return CO_E_OBJNOTCONNECTED;
52
53 *aActionCount = acc->ActionCount();
54 return S_OK;
55
56 A11Y_TRYBLOCK_END
57 }
58
59 STDMETHODIMP
doAction(long aActionIndex)60 ia2AccessibleAction::doAction(long aActionIndex)
61 {
62 A11Y_TRYBLOCK_BEGIN
63
64 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
65 if (acc->IsDefunct())
66 return CO_E_OBJNOTCONNECTED;
67
68 uint8_t index = static_cast<uint8_t>(aActionIndex);
69 return acc->DoAction(index) ? S_OK : E_INVALIDARG;
70
71 A11Y_TRYBLOCK_END
72 }
73
74 STDMETHODIMP
get_description(long aActionIndex,BSTR * aDescription)75 ia2AccessibleAction::get_description(long aActionIndex, BSTR *aDescription)
76 {
77 A11Y_TRYBLOCK_BEGIN
78
79 if (!aDescription)
80 return E_INVALIDARG;
81 *aDescription = nullptr;
82
83 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
84 if (acc->IsDefunct())
85 return CO_E_OBJNOTCONNECTED;
86
87 nsAutoString description;
88 uint8_t index = static_cast<uint8_t>(aActionIndex);
89 acc->ActionDescriptionAt(index, description);
90 if (description.IsEmpty())
91 return S_FALSE;
92
93 *aDescription = ::SysAllocStringLen(description.get(),
94 description.Length());
95 return *aDescription ? S_OK : E_OUTOFMEMORY;
96
97 A11Y_TRYBLOCK_END
98 }
99
100 STDMETHODIMP
get_keyBinding(long aActionIndex,long aNumMaxBinding,BSTR ** aKeyBinding,long * aNumBinding)101 ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
102 BSTR **aKeyBinding,
103 long *aNumBinding)
104 {
105 A11Y_TRYBLOCK_BEGIN
106
107 if (!aKeyBinding)
108 return E_INVALIDARG;
109 *aKeyBinding = nullptr;
110
111 if (!aNumBinding)
112 return E_INVALIDARG;
113 *aNumBinding = 0;
114
115 if (aActionIndex != 0 || aNumMaxBinding < 1)
116 return E_INVALIDARG;
117
118 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
119 if (acc->IsDefunct())
120 return CO_E_OBJNOTCONNECTED;
121
122 // Expose keyboard shortcut if it's not exposed via MSAA keyboard shortcut.
123 KeyBinding keyBinding = acc->AccessKey();
124 if (keyBinding.IsEmpty())
125 return S_FALSE;
126
127 keyBinding = acc->KeyboardShortcut();
128 if (keyBinding.IsEmpty())
129 return S_FALSE;
130
131 nsAutoString keyStr;
132 keyBinding.ToString(keyStr);
133
134 *aKeyBinding = static_cast<BSTR*>(::CoTaskMemAlloc(sizeof(BSTR*)));
135 if (!*aKeyBinding)
136 return E_OUTOFMEMORY;
137
138 *(aKeyBinding[0]) = ::SysAllocStringLen(keyStr.get(), keyStr.Length());
139 if (!*(aKeyBinding[0])) {
140 ::CoTaskMemFree(*aKeyBinding);
141 return E_OUTOFMEMORY;
142 }
143
144 *aNumBinding = 1;
145 return S_OK;
146
147 A11Y_TRYBLOCK_END
148 }
149
150 STDMETHODIMP
get_name(long aActionIndex,BSTR * aName)151 ia2AccessibleAction::get_name(long aActionIndex, BSTR *aName)
152 {
153 A11Y_TRYBLOCK_BEGIN
154
155 if (!aName)
156 return E_INVALIDARG;
157
158 *aName = nullptr;
159
160 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
161 if (acc->IsDefunct())
162 return CO_E_OBJNOTCONNECTED;
163
164 nsAutoString name;
165 uint8_t index = static_cast<uint8_t>(aActionIndex);
166 acc->ActionNameAt(index, name);
167 if (name.IsEmpty())
168 return E_INVALIDARG;
169
170 *aName = ::SysAllocStringLen(name.get(), name.Length());
171 return *aName ? S_OK : E_OUTOFMEMORY;
172
173 A11Y_TRYBLOCK_END
174 }
175
176 STDMETHODIMP
get_localizedName(long aActionIndex,BSTR * aLocalizedName)177 ia2AccessibleAction::get_localizedName(long aActionIndex, BSTR *aLocalizedName)
178 {
179 A11Y_TRYBLOCK_BEGIN
180
181 if (!aLocalizedName)
182 return E_INVALIDARG;
183
184 *aLocalizedName = nullptr;
185 return E_NOTIMPL;
186
187 A11Y_TRYBLOCK_END
188 }
189