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 if (!ppv) return E_INVALIDARG;
22
23 *ppv = nullptr;
24
25 if (IID_IAccessibleAction == iid &&
26 !static_cast<AccessibleWrap*>(this)->IsProxy()) {
27 *ppv = static_cast<IAccessibleAction*>(this);
28 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
29 return S_OK;
30 }
31
32 return E_NOINTERFACE;
33 }
34
35 // IAccessibleAction
36
37 STDMETHODIMP
nActions(long * aActionCount)38 ia2AccessibleAction::nActions(long* aActionCount) {
39 if (!aActionCount) return E_INVALIDARG;
40
41 *aActionCount = 0;
42
43 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
44 if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
45
46 *aActionCount = acc->ActionCount();
47 return S_OK;
48 }
49
50 STDMETHODIMP
doAction(long aActionIndex)51 ia2AccessibleAction::doAction(long aActionIndex) {
52 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
53 if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
54
55 uint8_t index = static_cast<uint8_t>(aActionIndex);
56 return acc->DoAction(index) ? S_OK : E_INVALIDARG;
57 }
58
59 STDMETHODIMP
get_description(long aActionIndex,BSTR * aDescription)60 ia2AccessibleAction::get_description(long aActionIndex, BSTR* aDescription) {
61 if (!aDescription) return E_INVALIDARG;
62 *aDescription = nullptr;
63
64 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
65 if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
66
67 nsAutoString description;
68 uint8_t index = static_cast<uint8_t>(aActionIndex);
69 acc->ActionDescriptionAt(index, description);
70 if (description.IsEmpty()) return S_FALSE;
71
72 *aDescription = ::SysAllocStringLen(description.get(), description.Length());
73 return *aDescription ? S_OK : E_OUTOFMEMORY;
74 }
75
76 STDMETHODIMP
get_keyBinding(long aActionIndex,long aNumMaxBinding,BSTR ** aKeyBinding,long * aNumBinding)77 ia2AccessibleAction::get_keyBinding(long aActionIndex, long aNumMaxBinding,
78 BSTR** aKeyBinding, long* aNumBinding) {
79 if (!aKeyBinding) return E_INVALIDARG;
80 *aKeyBinding = nullptr;
81
82 if (!aNumBinding) return E_INVALIDARG;
83 *aNumBinding = 0;
84
85 if (aActionIndex != 0 || aNumMaxBinding < 1) return E_INVALIDARG;
86
87 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
88 if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
89
90 // Expose keyboard shortcut if it's not exposed via MSAA keyboard shortcut.
91 KeyBinding keyBinding = acc->AccessKey();
92 if (keyBinding.IsEmpty()) return S_FALSE;
93
94 keyBinding = acc->KeyboardShortcut();
95 if (keyBinding.IsEmpty()) return S_FALSE;
96
97 nsAutoString keyStr;
98 keyBinding.ToString(keyStr);
99
100 *aKeyBinding = static_cast<BSTR*>(::CoTaskMemAlloc(sizeof(BSTR*)));
101 if (!*aKeyBinding) return E_OUTOFMEMORY;
102
103 *(aKeyBinding[0]) = ::SysAllocStringLen(keyStr.get(), keyStr.Length());
104 if (!*(aKeyBinding[0])) {
105 ::CoTaskMemFree(*aKeyBinding);
106 return E_OUTOFMEMORY;
107 }
108
109 *aNumBinding = 1;
110 return S_OK;
111 }
112
113 STDMETHODIMP
get_name(long aActionIndex,BSTR * aName)114 ia2AccessibleAction::get_name(long aActionIndex, BSTR* aName) {
115 if (!aName) return E_INVALIDARG;
116
117 *aName = nullptr;
118
119 AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
120 if (acc->IsDefunct()) return CO_E_OBJNOTCONNECTED;
121
122 nsAutoString name;
123 uint8_t index = static_cast<uint8_t>(aActionIndex);
124 acc->ActionNameAt(index, name);
125 if (name.IsEmpty()) return E_INVALIDARG;
126
127 *aName = ::SysAllocStringLen(name.get(), name.Length());
128 return *aName ? S_OK : E_OUTOFMEMORY;
129 }
130
131 STDMETHODIMP
get_localizedName(long aActionIndex,BSTR * aLocalizedName)132 ia2AccessibleAction::get_localizedName(long aActionIndex,
133 BSTR* aLocalizedName) {
134 if (!aLocalizedName) return E_INVALIDARG;
135
136 *aLocalizedName = nullptr;
137 return E_NOTIMPL;
138 }
139