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