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