summaryrefslogtreecommitdiffstats
path: root/accessible/xpcom/xpcAccessibilityService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'accessible/xpcom/xpcAccessibilityService.cpp')
-rw-r--r--accessible/xpcom/xpcAccessibilityService.cpp311
1 files changed, 311 insertions, 0 deletions
diff --git a/accessible/xpcom/xpcAccessibilityService.cpp b/accessible/xpcom/xpcAccessibilityService.cpp
new file mode 100644
index 0000000000..128d510769
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -0,0 +1,311 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibilityService.h"
+
+#include "mozilla/dom/Document.h"
+
+#include "nsAccessiblePivot.h"
+#include "nsAccessibilityService.h"
+#include "Platform.h"
+#include "xpcAccessibleApplication.h"
+#include "xpcAccessibleDocument.h"
+#include "xpcAccessibleTextLeafRange.h"
+
+#ifdef A11Y_LOG
+# include "Logging.h"
+#endif
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+using namespace mozilla::dom;
+
+xpcAccessibilityService* xpcAccessibilityService::gXPCAccessibilityService =
+ nullptr;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+void xpcAccessibilityService::ShutdownCallback(nsITimer* aTimer,
+ void* aClosure) {
+ MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
+ xpcAccessibilityService* xpcAccService =
+ reinterpret_cast<xpcAccessibilityService*>(aClosure);
+
+ if (xpcAccService->mShutdownTimer) {
+ xpcAccService->mShutdownTimer->Cancel();
+ xpcAccService->mShutdownTimer = nullptr;
+ }
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+xpcAccessibilityService::AddRef(void) {
+ MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(xpcAccessibilityService)
+ MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
+ if (!nsAutoRefCnt::isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+ nsrefcnt count = ++mRefCnt;
+ NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this));
+
+ // We want refcount to be > 1 because one reference is added in the XPCOM
+ // accessibility service getter.
+ if (mRefCnt > 1) {
+ if (mShutdownTimer) {
+ mShutdownTimer->Cancel();
+ mShutdownTimer = nullptr;
+ }
+
+ GetOrCreateAccService(nsAccessibilityService::eXPCOM);
+ }
+
+ return count;
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+xpcAccessibilityService::Release(void) {
+ MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
+
+ if (!nsAutoRefCnt::isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+
+ nsrefcnt count = --mRefCnt;
+ NS_LOG_RELEASE(this, count, "xpcAccessibilityService");
+
+ if (count == 0) {
+ if (!nsAutoRefCnt::isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+
+ mRefCnt = 1; /* stabilize */
+ delete (this);
+ return 0;
+ }
+
+ // When ref count goes down to 1 (held internally as a static reference),
+ // it means that there are no more external references to the
+ // xpcAccessibilityService and we can attempt to shut down acceessiblity
+ // service.
+ if (count == 1 && !mShutdownTimer) {
+ NS_NewTimerWithFuncCallback(
+ getter_AddRefs(mShutdownTimer), ShutdownCallback, this, 100,
+ nsITimer::TYPE_ONE_SHOT, "xpcAccessibilityService::Release");
+ }
+
+ return count;
+}
+
+NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService)
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetApplicationAccessible(
+ nsIAccessible** aAccessibleApplication) {
+ NS_ENSURE_ARG_POINTER(aAccessibleApplication);
+
+ NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFor(nsINode* aNode,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
+ if (document) {
+ NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(aNode)));
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleDescendantFor(
+ nsINode* aNode, nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
+ if (document) {
+ NS_IF_ADDREF(*aAccessible =
+ ToXPC(document->GetAccessibleOrDescendant(aNode)));
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringRole(aRole, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
+ nsISupports** aStringStates) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringStates(aState, aExtraState, aStringStates);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringEventType(uint32_t aEventType,
+ nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringEventType(aEventType, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringRelationType(uint32_t aRelationType,
+ nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetStringRelationType(aRelationType, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFromCache(nsINode* aNode,
+ nsIAccessible** aAccessible) {
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ // Search for an accessible in each of our per document accessible object
+ // caches. If we don't find it, and the given node is itself a document, check
+ // our cache of document accessibles (document cache). Note usually shutdown
+ // document accessibles are not stored in the document cache, however an
+ // "unofficially" shutdown document (i.e. not from DocManager) can still
+ // exist in the document cache.
+ LocalAccessible* accessible = accService->FindAccessibleInCache(aNode);
+ if (!accessible && aNode->IsDocument()) {
+ accessible = mozilla::a11y::GetExistingDocAccessible(aNode->AsDocument());
+ }
+
+ NS_IF_ADDREF(*aAccessible = ToXPC(accessible));
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::CreateAccessiblePivot(nsIAccessible* aRoot,
+ nsIAccessiblePivot** aPivot) {
+ NS_ENSURE_ARG_POINTER(aPivot);
+ NS_ENSURE_ARG(aRoot);
+ *aPivot = nullptr;
+
+ LocalAccessible* accessibleRoot = aRoot->ToInternalAccessible();
+ NS_ENSURE_TRUE(accessibleRoot, NS_ERROR_INVALID_ARG);
+
+ nsAccessiblePivot* pivot = new nsAccessiblePivot(accessibleRoot);
+ NS_ADDREF(*aPivot = pivot);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::CreateTextLeafPoint(
+ nsIAccessible* aAccessible, int32_t aOffset,
+ nsIAccessibleTextLeafPoint** aPoint) {
+ NS_ENSURE_ARG_POINTER(aPoint);
+ NS_ENSURE_ARG(aAccessible);
+ *aPoint = nullptr;
+
+ RefPtr<xpcAccessibleTextLeafPoint> point =
+ new xpcAccessibleTextLeafPoint(aAccessible, aOffset);
+ point.forget(aPoint);
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::SetLogging(const nsACString& aModules) {
+#ifdef A11Y_LOG
+ logging::Enable(PromiseFlatCString(aModules));
+#endif
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::IsLogged(const nsAString& aModule, bool* aIsLogged) {
+ NS_ENSURE_ARG_POINTER(aIsLogged);
+ *aIsLogged = false;
+
+#ifdef A11Y_LOG
+ *aIsLogged = logging::IsEnabled(aModule);
+#endif
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetConsumers(nsAString& aString) {
+ nsAccessibilityService* accService = GetAccService();
+ if (!accService) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ accService->GetConsumers(aString);
+ return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NS_GetAccessibilityService
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult) {
+ NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
+ *aResult = nullptr;
+
+ if (!GetOrCreateAccService(nsAccessibilityService::eXPCOM)) {
+ return NS_ERROR_SERVICE_NOT_AVAILABLE;
+ }
+
+ xpcAccessibilityService* service = new xpcAccessibilityService();
+ xpcAccessibilityService::gXPCAccessibilityService = service;
+ NS_ADDREF(*aResult = service);
+
+ return NS_OK;
+}