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 "AccessibleHyperlink.h"
9 #include "AccessibleHyperlink_i.c"
10
11 #include "AccessibleWrap.h"
12 #include "IUnknownImpl.h"
13 #include "nsIURI.h"
14
15 using namespace mozilla::a11y;
16
Acc()17 Accessible* ia2AccessibleHyperlink::Acc() {
18 return static_cast<MsaaAccessible*>(this)->Acc();
19 }
20
LocalAcc()21 AccessibleWrap* ia2AccessibleHyperlink::LocalAcc() {
22 return static_cast<MsaaAccessible*>(this)->LocalAcc();
23 }
24
25 // IUnknown
26
27 STDMETHODIMP
QueryInterface(REFIID iid,void ** ppv)28 ia2AccessibleHyperlink::QueryInterface(REFIID iid, void** ppv) {
29 if (!ppv) return E_INVALIDARG;
30
31 *ppv = nullptr;
32
33 if (IID_IAccessibleHyperlink == iid) {
34 Accessible* acc = Acc();
35 if (!acc || !acc->IsLink()) {
36 return E_NOINTERFACE;
37 }
38
39 *ppv = static_cast<IAccessibleHyperlink*>(this);
40 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
41 return S_OK;
42 }
43
44 return ia2AccessibleAction::QueryInterface(iid, ppv);
45 }
46
47 // IAccessibleHyperlink
48
49 STDMETHODIMP
get_anchor(long aIndex,VARIANT * aAnchor)50 ia2AccessibleHyperlink::get_anchor(long aIndex, VARIANT* aAnchor) {
51 if (!aAnchor) return E_INVALIDARG;
52
53 VariantInit(aAnchor);
54
55 LocalAccessible* thisObj = LocalAcc();
56 if (!thisObj) {
57 return CO_E_OBJNOTCONNECTED;
58 }
59
60 if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount()))
61 return E_INVALIDARG;
62
63 if (!thisObj->IsLink()) return S_FALSE;
64
65 AccessibleWrap* anchor =
66 static_cast<AccessibleWrap*>(thisObj->AnchorAt(aIndex));
67 if (!anchor) return S_FALSE;
68
69 RefPtr<IAccessible> result;
70 anchor->GetNativeInterface(getter_AddRefs(result));
71 result.forget(&aAnchor->punkVal);
72 aAnchor->vt = VT_UNKNOWN;
73 return S_OK;
74 }
75
76 STDMETHODIMP
get_anchorTarget(long aIndex,VARIANT * aAnchorTarget)77 ia2AccessibleHyperlink::get_anchorTarget(long aIndex, VARIANT* aAnchorTarget) {
78 if (!aAnchorTarget) {
79 return E_INVALIDARG;
80 }
81
82 VariantInit(aAnchorTarget);
83
84 LocalAccessible* thisObj = LocalAcc();
85 if (!thisObj) {
86 return CO_E_OBJNOTCONNECTED;
87 }
88 nsAutoCString uriStr;
89
90 if (aIndex < 0 || aIndex >= static_cast<long>(thisObj->AnchorCount())) {
91 return E_INVALIDARG;
92 }
93
94 if (!thisObj->IsLink()) {
95 return S_FALSE;
96 }
97
98 nsCOMPtr<nsIURI> uri = thisObj->AnchorURIAt(aIndex);
99 if (!uri) {
100 return S_FALSE;
101 }
102
103 nsresult rv = uri->GetSpec(uriStr);
104 if (NS_FAILED(rv)) {
105 return GetHRESULT(rv);
106 }
107
108 nsAutoString stringURI;
109 AppendUTF8toUTF16(uriStr, stringURI);
110
111 aAnchorTarget->vt = VT_BSTR;
112 aAnchorTarget->bstrVal =
113 ::SysAllocStringLen(stringURI.get(), stringURI.Length());
114 return aAnchorTarget->bstrVal ? S_OK : E_OUTOFMEMORY;
115 }
116
117 STDMETHODIMP
get_startIndex(long * aIndex)118 ia2AccessibleHyperlink::get_startIndex(long* aIndex) {
119 if (!aIndex) return E_INVALIDARG;
120
121 *aIndex = 0;
122
123 Accessible* thisObj = Acc();
124 if (!thisObj) {
125 return CO_E_OBJNOTCONNECTED;
126 }
127
128 if (!thisObj->IsLink()) return S_FALSE;
129
130 *aIndex = thisObj->StartOffset();
131 return S_OK;
132 }
133
134 STDMETHODIMP
get_endIndex(long * aIndex)135 ia2AccessibleHyperlink::get_endIndex(long* aIndex) {
136 if (!aIndex) return E_INVALIDARG;
137
138 *aIndex = 0;
139
140 Accessible* thisObj = Acc();
141 if (!thisObj) {
142 return CO_E_OBJNOTCONNECTED;
143 }
144
145 if (!thisObj->IsLink()) return S_FALSE;
146
147 *aIndex = thisObj->EndOffset();
148 return S_OK;
149 }
150
151 STDMETHODIMP
get_valid(boolean * aValid)152 ia2AccessibleHyperlink::get_valid(boolean* aValid) {
153 if (!aValid) return E_INVALIDARG;
154
155 *aValid = false;
156
157 LocalAccessible* thisObj = LocalAcc();
158 if (!thisObj) {
159 return CO_E_OBJNOTCONNECTED;
160 }
161
162 if (!thisObj->IsLink()) return S_FALSE;
163
164 *aValid = thisObj->IsLinkValid();
165 return S_OK;
166 }
167