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.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/accessible/xpcom/xpcAccessibilityService.cpp b/accessible/xpcom/xpcAccessibilityService.cpp
new file mode 100644
index 000000000..97c0d0e72
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -0,0 +1,246 @@
+/* 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 "nsAccessiblePivot.h"
+#include "nsAccessibilityService.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 (!mRefCnt.isThreadSafe)
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ nsrefcnt count = ++mRefCnt;
+ NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this));
+
+ if (mRefCnt > 1) {
+ GetOrCreateAccService(nsAccessibilityService::eXPCOM);
+ }
+
+ return count;
+}
+
+NS_IMETHODIMP_(MozExternalRefCountType)
+xpcAccessibilityService::Release(void)
+{
+ MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
+
+ if (!mRefCnt.isThreadSafe) {
+ NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
+ }
+
+ nsrefcnt count = --mRefCnt;
+ NS_LOG_RELEASE(this, count, "xpcAccessibilityService");
+
+ if (count == 0) {
+ if (!mRefCnt.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) {
+ mShutdownTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+ if (mShutdownTimer) {
+ mShutdownTimer->InitWithFuncCallback(ShutdownCallback, this, 100,
+ nsITimer::TYPE_ONE_SHOT);
+ }
+ }
+
+ return count;
+}
+
+NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService,
+ nsIAccessibleRetrieval)
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
+{
+ NS_ENSURE_ARG_POINTER(aAccessibleApplication);
+
+ NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
+ nsIAccessible **aAccessible)
+{
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
+ if (!node) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ DocAccessible* document = GetAccService()->GetDocAccessible(node->OwnerDoc());
+ if (document) {
+ NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(node)));
+ }
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString)
+{
+ GetAccService()->GetStringRole(aRole, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
+ nsISupports **aStringStates)
+{
+ GetAccService()->GetStringStates(aState, aExtraState, aStringStates);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringEventType(uint32_t aEventType,
+ nsAString& aString)
+{
+ GetAccService()->GetStringEventType(aEventType, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetStringRelationType(uint32_t aRelationType,
+ nsAString& aString)
+{
+ GetAccService()->GetStringRelationType(aRelationType, aString);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
+ nsIAccessible** aAccessible)
+{
+ NS_ENSURE_ARG_POINTER(aAccessible);
+ *aAccessible = nullptr;
+ if (!aNode) {
+ return NS_OK;
+ }
+
+ nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
+ if (!node) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ // 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.
+ Accessible* accessible = GetAccService()->FindAccessibleInCache(node);
+ if (!accessible) {
+ nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
+ if (document) {
+ accessible = mozilla::a11y::GetExistingDocAccessible(document);
+ }
+ }
+
+ 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;
+
+ Accessible* 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::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_GetAccessibilityService
+////////////////////////////////////////////////////////////////////////////////
+
+nsresult
+NS_GetAccessibilityService(nsIAccessibilityService** aResult)
+{
+ NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
+ *aResult = nullptr;
+
+ GetOrCreateAccService(nsAccessibilityService::eXPCOM);
+
+ xpcAccessibilityService* service = new xpcAccessibilityService();
+ NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
+ xpcAccessibilityService::gXPCAccessibilityService = service;
+ NS_ADDREF(*aResult = service);
+
+ return NS_OK;
+}