Blame accessible/xpcom/xpcAccessibilityService.cpp

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