Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/accessible/xpcom/xpcAccessibilityService.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This Source Code Form is subject to the terms of the Mozilla Public
2
 * License, v. 2.0. If a copy of the MPL was not distributed with this
3
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5
#include "xpcAccessibilityService.h"
6
7
#include "nsAccessiblePivot.h"
8
#include "nsAccessibilityService.h"
9
#include "Platform.h"
10
11
#ifdef A11Y_LOG
12
#include "Logging.h"
13
#endif
14
15
using namespace mozilla;
16
using namespace mozilla::a11y;
17
using namespace mozilla::dom;
18
19
xpcAccessibilityService *xpcAccessibilityService::gXPCAccessibilityService = nullptr;
20
21
////////////////////////////////////////////////////////////////////////////////
22
// nsISupports
23
24
void
25
xpcAccessibilityService::ShutdownCallback(nsITimer* aTimer, void* aClosure)
26
0
{
27
0
  MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
28
0
  xpcAccessibilityService* xpcAccService =
29
0
    reinterpret_cast<xpcAccessibilityService*>(aClosure);
30
0
31
0
  if (xpcAccService->mShutdownTimer) {
32
0
    xpcAccService->mShutdownTimer->Cancel();
33
0
    xpcAccService->mShutdownTimer = nullptr;
34
0
  }
35
0
}
36
37
NS_IMETHODIMP_(MozExternalRefCountType)
38
xpcAccessibilityService::AddRef(void)
39
0
{
40
0
  MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(xpcAccessibilityService)
41
0
  MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
42
0
  if (!nsAutoRefCnt::isThreadSafe)
43
0
    NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
44
0
  nsrefcnt count = ++mRefCnt;
45
0
  NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this));
46
0
47
0
  // We want refcount to be > 1 because one reference is added in the XPCOM
48
0
  // accessibility service getter.
49
0
  if (mRefCnt > 1) {
50
0
    if (mShutdownTimer) {
51
0
      mShutdownTimer->Cancel();
52
0
      mShutdownTimer = nullptr;
53
0
    }
54
0
55
0
    GetOrCreateAccService(nsAccessibilityService::eXPCOM);
56
0
  }
57
0
58
0
  return count;
59
0
}
60
61
NS_IMETHODIMP_(MozExternalRefCountType)
62
xpcAccessibilityService::Release(void)
63
0
{
64
0
  MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
65
0
66
0
  if (!nsAutoRefCnt::isThreadSafe) {
67
0
    NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
68
0
  }
69
0
70
0
  nsrefcnt count = --mRefCnt;
71
0
  NS_LOG_RELEASE(this, count, "xpcAccessibilityService");
72
0
73
0
  if (count == 0) {
74
0
    if (!nsAutoRefCnt::isThreadSafe) {
75
0
      NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
76
0
    }
77
0
78
0
    mRefCnt = 1; /* stabilize */
79
0
    delete (this);
80
0
    return 0;
81
0
  }
82
0
83
0
  // When ref count goes down to 1 (held internally as a static reference),
84
0
  // it means that there are no more external references to the
85
0
  // xpcAccessibilityService and we can attempt to shut down acceessiblity
86
0
  // service.
87
0
  if (count == 1 && !mShutdownTimer) {
88
0
    NS_NewTimerWithFuncCallback(getter_AddRefs(mShutdownTimer),
89
0
                                ShutdownCallback,
90
0
                                this,
91
0
                                100,
92
0
                                nsITimer::TYPE_ONE_SHOT,
93
0
                                "xpcAccessibilityService::Release");
94
0
  }
95
0
96
0
  return count;
97
0
}
98
99
NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService)
100
101
NS_IMETHODIMP
102
xpcAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
103
0
{
104
0
  NS_ENSURE_ARG_POINTER(aAccessibleApplication);
105
0
106
0
  NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
107
0
  return NS_OK;
108
0
}
109
110
NS_IMETHODIMP
111
xpcAccessibilityService::GetAccessibleFor(nsINode *aNode,
112
                                          nsIAccessible **aAccessible)
113
0
{
114
0
  NS_ENSURE_ARG_POINTER(aAccessible);
115
0
  *aAccessible = nullptr;
116
0
  if (!aNode) {
117
0
    return NS_OK;
118
0
  }
119
0
120
0
  nsAccessibilityService* accService = GetAccService();
121
0
  if (!accService) {
122
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
123
0
  }
124
0
125
0
  DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
126
0
  if (document) {
127
0
    NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(aNode)));
128
0
  }
129
0
130
0
  return NS_OK;
131
0
}
132
133
NS_IMETHODIMP
134
xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString)
135
0
{
136
0
  nsAccessibilityService* accService = GetAccService();
137
0
  if (!accService) {
138
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
139
0
  }
140
0
141
0
  accService->GetStringRole(aRole, aString);
142
0
  return NS_OK;
143
0
}
144
145
NS_IMETHODIMP
146
xpcAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
147
                                         nsISupports **aStringStates)
148
0
{
149
0
  nsAccessibilityService* accService = GetAccService();
150
0
  if (!accService) {
151
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
152
0
  }
153
0
154
0
  accService->GetStringStates(aState, aExtraState, aStringStates);
155
0
  return NS_OK;
156
0
}
157
158
NS_IMETHODIMP
159
xpcAccessibilityService::GetStringEventType(uint32_t aEventType,
160
                                            nsAString& aString)
161
0
{
162
0
  nsAccessibilityService* accService = GetAccService();
163
0
  if (!accService) {
164
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
165
0
  }
166
0
167
0
  accService->GetStringEventType(aEventType, aString);
168
0
  return NS_OK;
169
0
}
170
171
NS_IMETHODIMP
172
xpcAccessibilityService::GetStringRelationType(uint32_t aRelationType,
173
                                               nsAString& aString)
174
0
{
175
0
  nsAccessibilityService* accService = GetAccService();
176
0
  if (!accService) {
177
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
178
0
  }
179
0
180
0
  accService->GetStringRelationType(aRelationType, aString);
181
0
  return NS_OK;
182
0
}
183
184
NS_IMETHODIMP
185
xpcAccessibilityService::GetAccessibleFromCache(nsINode* aNode,
186
                                                nsIAccessible** aAccessible)
187
0
{
188
0
  NS_ENSURE_ARG_POINTER(aAccessible);
189
0
  *aAccessible = nullptr;
190
0
  if (!aNode) {
191
0
    return NS_OK;
192
0
  }
193
0
194
0
  nsAccessibilityService* accService = GetAccService();
195
0
  if (!accService) {
196
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
197
0
  }
198
0
199
0
  // Search for an accessible in each of our per document accessible object
200
0
  // caches. If we don't find it, and the given node is itself a document, check
201
0
  // our cache of document accessibles (document cache). Note usually shutdown
202
0
  // document accessibles are not stored in the document cache, however an
203
0
  // "unofficially" shutdown document (i.e. not from DocManager) can still
204
0
  // exist in the document cache.
205
0
  Accessible* accessible = accService->FindAccessibleInCache(aNode);
206
0
  if (!accessible) {
207
0
    nsCOMPtr<nsIDocument> document(do_QueryInterface(aNode));
208
0
    if (document) {
209
0
      accessible = mozilla::a11y::GetExistingDocAccessible(document);
210
0
    }
211
0
  }
212
0
213
0
  NS_IF_ADDREF(*aAccessible = ToXPC(accessible));
214
0
  return NS_OK;
215
0
}
216
217
NS_IMETHODIMP
218
xpcAccessibilityService::CreateAccessiblePivot(nsIAccessible* aRoot,
219
                                               nsIAccessiblePivot** aPivot)
220
0
{
221
0
  NS_ENSURE_ARG_POINTER(aPivot);
222
0
  NS_ENSURE_ARG(aRoot);
223
0
  *aPivot = nullptr;
224
0
225
0
  Accessible* accessibleRoot = aRoot->ToInternalAccessible();
226
0
  NS_ENSURE_TRUE(accessibleRoot, NS_ERROR_INVALID_ARG);
227
0
228
0
  nsAccessiblePivot* pivot = new nsAccessiblePivot(accessibleRoot);
229
0
  NS_ADDREF(*aPivot = pivot);
230
0
231
0
  return NS_OK;
232
0
}
233
234
NS_IMETHODIMP
235
xpcAccessibilityService::SetLogging(const nsACString& aModules)
236
0
{
237
0
#ifdef A11Y_LOG
238
0
  logging::Enable(PromiseFlatCString(aModules));
239
0
#endif
240
0
  return NS_OK;
241
0
}
242
243
NS_IMETHODIMP
244
xpcAccessibilityService::IsLogged(const nsAString& aModule, bool* aIsLogged)
245
0
{
246
0
  NS_ENSURE_ARG_POINTER(aIsLogged);
247
0
  *aIsLogged = false;
248
0
249
0
#ifdef A11Y_LOG
250
0
  *aIsLogged = logging::IsEnabled(aModule);
251
0
#endif
252
0
253
0
  return NS_OK;
254
0
}
255
256
NS_IMETHODIMP
257
xpcAccessibilityService::GetConsumers(nsAString& aString)
258
0
{
259
0
  nsAccessibilityService* accService = GetAccService();
260
0
  if (!accService) {
261
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
262
0
  }
263
0
264
0
  accService->GetConsumers(aString);
265
0
  return NS_OK;
266
0
}
267
268
////////////////////////////////////////////////////////////////////////////////
269
// NS_GetAccessibilityService
270
////////////////////////////////////////////////////////////////////////////////
271
272
nsresult
273
NS_GetAccessibilityService(nsIAccessibilityService** aResult)
274
0
{
275
0
  NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
276
0
  *aResult = nullptr;
277
0
278
0
  if (!GetOrCreateAccService(nsAccessibilityService::eXPCOM)) {
279
0
    return NS_ERROR_SERVICE_NOT_AVAILABLE;
280
0
  }
281
0
282
0
  xpcAccessibilityService* service = new xpcAccessibilityService();
283
0
  NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
284
0
  xpcAccessibilityService::gXPCAccessibilityService = service;
285
0
  NS_ADDREF(*aResult = service);
286
0
287
0
  return NS_OK;
288
0
}