--- a/accessible/base/DocManager.cpp
+++ b/accessible/base/DocManager.cpp
@@ -84,24 +84,33 @@ DocManager::FindAccessibleInCache(nsINod
}
return nullptr;
}
void
DocManager::NotifyOfDocumentShutdown(DocAccessible* aDocument,
nsIDocument* aDOMDocument)
{
+ // We need to remove listeners in both cases, when document is being shutdown
+ // or when accessibility service is being shut down as well.
+ RemoveListeners(aDOMDocument);
+
+ // Document will already be removed when accessibility service is shutting
+ // down so we do not need to remove it twice.
+ if (nsAccessibilityService::IsShutdown()) {
+ return;
+ }
+
xpcAccessibleDocument* xpcDoc = mXPCDocumentCache.GetWeak(aDocument);
if (xpcDoc) {
xpcDoc->Shutdown();
mXPCDocumentCache.Remove(aDocument);
}
mDocAccessibleCache.Remove(aDOMDocument);
- RemoveListeners(aDOMDocument);
}
void
DocManager::NotifyOfRemoteDocShutdown(DocAccessibleParent* aDoc)
{
xpcAccessibleDocument* doc = GetCachedXPCDocument(aDoc);
if (doc) {
doc->Shutdown();
@@ -525,29 +534,42 @@ DocManager::CreateDocOrRootAccessible(ns
}
////////////////////////////////////////////////////////////////////////////////
// DocManager static
void
DocManager::ClearDocCache()
{
- // This unusual do-one-element-per-iterator approach is required because each
- // DocAccessible is removed elsewhere upon its Shutdown() method being
- // called, which invalidates the existing iterator.
while (mDocAccessibleCache.Count() > 0) {
auto iter = mDocAccessibleCache.Iter();
MOZ_ASSERT(!iter.Done());
DocAccessible* docAcc = iter.UserData();
NS_ASSERTION(docAcc,
"No doc accessible for the object in doc accessible cache!");
if (docAcc) {
docAcc->Shutdown();
}
+
+ iter.Remove();
}
+
+ // Ensure that all xpcom accessible documents are shut down as well.
+ while (mXPCDocumentCache.Count() > 0) {
+ auto iter = mXPCDocumentCache.Iter();
+ MOZ_ASSERT(!iter.Done());
+ xpcAccessibleDocument* xpcDoc = iter.UserData();
+ NS_ASSERTION(xpcDoc, "No xpc doc for the object in xpc doc cache!");
+
+ if (xpcDoc) {
+ xpcDoc->Shutdown();
+ }
+
+ iter.Remove();
+ }
}
void
DocManager::RemoteDocAdded(DocAccessibleParent* aDoc)
{
if (!sRemoteDocuments) {
sRemoteDocuments = new nsTArray<DocAccessibleParent*>;
ClearOnShutdown(&sRemoteDocuments);
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -15,17 +15,16 @@
#include "HTMLElementAccessibles.h"
#include "HTMLImageMapAccessible.h"
#include "HTMLLinkAccessible.h"
#include "HTMLListAccessible.h"
#include "HTMLSelectAccessible.h"
#include "HTMLTableAccessibleWrap.h"
#include "HyperTextAccessibleWrap.h"
#include "RootAccessible.h"
-#include "nsAccessiblePivot.h"
#include "nsAccUtils.h"
#include "nsArrayUtils.h"
#include "nsAttrName.h"
#include "nsEventShell.h"
#include "nsIURI.h"
#include "OuterDocAccessible.h"
#include "Platform.h"
#include "Role.h"
@@ -260,16 +259,17 @@ static const MarkupMapInfo sMarkupMapLis
////////////////////////////////////////////////////////////////////////////////
// nsAccessibilityService
////////////////////////////////////////////////////////////////////////////////
nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nullptr;
ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
xpcAccessibleApplication* nsAccessibilityService::gXPCApplicationAccessible = nullptr;
bool nsAccessibilityService::gIsShutdown = true;
+bool nsAccessibilityService::gIsPlatformCaller = false;
nsAccessibilityService::nsAccessibilityService() :
DocManager(), FocusManager(), mMarkupMaps(ArrayLength(sMarkupMapList))
{
}
nsAccessibilityService::~nsAccessibilityService()
{
@@ -335,18 +335,16 @@ nsAccessibilityService::ListenersChanged
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsISupports
NS_IMPL_ISUPPORTS_INHERITED(nsAccessibilityService,
DocManager,
- nsIAccessibilityService,
- nsIAccessibleRetrieval,
nsIObserver,
nsIListenerChangeListener,
nsISelectionListener) // from SelectionManager
////////////////////////////////////////////////////////////////////////////////
// nsIObserver
NS_IMETHODIMP
@@ -354,39 +352,34 @@ nsAccessibilityService::Observe(nsISuppo
const char16_t *aData)
{
if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
Shutdown();
return NS_OK;
}
-// nsIAccessibilityService
void
nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent* aTargetNode)
{
nsIDocument* documentNode = aTargetNode->GetUncomposedDoc();
if (documentNode) {
DocAccessible* document = GetDocAccessible(documentNode);
if (document)
document->SetAnchorJump(aTargetNode);
}
}
-// nsIAccessibilityService
void
nsAccessibilityService::FireAccessibleEvent(uint32_t aEvent,
Accessible* aTarget)
{
nsEventShell::FireEvent(aEvent, aTarget);
}
-////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibilityService
-
Accessible*
nsAccessibilityService::GetRootDocumentAccessible(nsIPresShell* aPresShell,
bool aCanCreate)
{
nsIPresShell* ps = aPresShell;
nsIDocument* documentNode = aPresShell->GetDocument();
if (documentNode) {
nsCOMPtr<nsIDocShellTreeItem> treeItem(documentNode->GetDocShell());
@@ -732,290 +725,233 @@ void
nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
nsIContent* aContent)
{
DocAccessible* document = GetDocAccessible(aPresShell);
if (document)
document->RecreateAccessible(aContent);
}
-////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibleRetrieval
-
-NS_IMETHODIMP
-nsAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
-{
- NS_ENSURE_ARG_POINTER(aAccessibleApplication);
-
- NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsAccessibilityService::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 = GetDocAccessible(node->OwnerDoc());
- if (document)
- NS_IF_ADDREF(*aAccessible = ToXPC(document->GetAccessible(node)));
-
- return NS_OK;
-}
-
-NS_IMETHODIMP
+void
nsAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString)
{
#define ROLE(geckoRole, stringRole, atkRole, \
macRole, msaaRole, ia2Role, nameRule) \
case roles::geckoRole: \
CopyUTF8toUTF16(stringRole, aString); \
- return NS_OK;
+ return;
switch (aRole) {
#include "RoleMap.h"
default:
aString.AssignLiteral("unknown");
- return NS_OK;
+ return;
}
#undef ROLE
}
-NS_IMETHODIMP
+void
nsAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
nsISupports **aStringStates)
{
RefPtr<DOMStringList> stringStates = new DOMStringList();
uint64_t state = nsAccUtils::To64State(aState, aExtraState);
// states
- if (state & states::UNAVAILABLE)
+ if (state & states::UNAVAILABLE) {
stringStates->Add(NS_LITERAL_STRING("unavailable"));
- if (state & states::SELECTED)
+ }
+ if (state & states::SELECTED) {
stringStates->Add(NS_LITERAL_STRING("selected"));
- if (state & states::FOCUSED)
+ }
+ if (state & states::FOCUSED) {
stringStates->Add(NS_LITERAL_STRING("focused"));
- if (state & states::PRESSED)
+ }
+ if (state & states::PRESSED) {
stringStates->Add(NS_LITERAL_STRING("pressed"));
- if (state & states::CHECKED)
+ }
+ if (state & states::CHECKED) {
stringStates->Add(NS_LITERAL_STRING("checked"));
- if (state & states::MIXED)
+ }
+ if (state & states::MIXED) {
stringStates->Add(NS_LITERAL_STRING("mixed"));
- if (state & states::READONLY)
+ }
+ if (state & states::READONLY) {
stringStates->Add(NS_LITERAL_STRING("readonly"));
- if (state & states::HOTTRACKED)
+ }
+ if (state & states::HOTTRACKED) {
stringStates->Add(NS_LITERAL_STRING("hottracked"));
- if (state & states::DEFAULT)
+ }
+ if (state & states::DEFAULT) {
stringStates->Add(NS_LITERAL_STRING("default"));
- if (state & states::EXPANDED)
+ }
+ if (state & states::EXPANDED) {
stringStates->Add(NS_LITERAL_STRING("expanded"));
- if (state & states::COLLAPSED)
+ }
+ if (state & states::COLLAPSED) {
stringStates->Add(NS_LITERAL_STRING("collapsed"));
- if (state & states::BUSY)
+ }
+ if (state & states::BUSY) {
stringStates->Add(NS_LITERAL_STRING("busy"));
- if (state & states::FLOATING)
+ }
+ if (state & states::FLOATING) {
stringStates->Add(NS_LITERAL_STRING("floating"));
- if (state & states::ANIMATED)
+ }
+ if (state & states::ANIMATED) {
stringStates->Add(NS_LITERAL_STRING("animated"));
- if (state & states::INVISIBLE)
+ }
+ if (state & states::INVISIBLE) {
stringStates->Add(NS_LITERAL_STRING("invisible"));
- if (state & states::OFFSCREEN)
+ }
+ if (state & states::OFFSCREEN) {
stringStates->Add(NS_LITERAL_STRING("offscreen"));
- if (state & states::SIZEABLE)
+ }
+ if (state & states::SIZEABLE) {
stringStates->Add(NS_LITERAL_STRING("sizeable"));
- if (state & states::MOVEABLE)
+ }
+ if (state & states::MOVEABLE) {
stringStates->Add(NS_LITERAL_STRING("moveable"));
- if (state & states::SELFVOICING)
+ }
+ if (state & states::SELFVOICING) {
stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
- if (state & states::FOCUSABLE)
+ }
+ if (state & states::FOCUSABLE) {
stringStates->Add(NS_LITERAL_STRING("focusable"));
- if (state & states::SELECTABLE)
+ }
+ if (state & states::SELECTABLE) {
stringStates->Add(NS_LITERAL_STRING("selectable"));
- if (state & states::LINKED)
+ }
+ if (state & states::LINKED) {
stringStates->Add(NS_LITERAL_STRING("linked"));
- if (state & states::TRAVERSED)
+ }
+ if (state & states::TRAVERSED) {
stringStates->Add(NS_LITERAL_STRING("traversed"));
- if (state & states::MULTISELECTABLE)
+ }
+ if (state & states::MULTISELECTABLE) {
stringStates->Add(NS_LITERAL_STRING("multiselectable"));
- if (state & states::EXTSELECTABLE)
+ }
+ if (state & states::EXTSELECTABLE) {
stringStates->Add(NS_LITERAL_STRING("extselectable"));
- if (state & states::PROTECTED)
+ }
+ if (state & states::PROTECTED) {
stringStates->Add(NS_LITERAL_STRING("protected"));
- if (state & states::HASPOPUP)
+ }
+ if (state & states::HASPOPUP) {
stringStates->Add(NS_LITERAL_STRING("haspopup"));
- if (state & states::REQUIRED)
+ }
+ if (state & states::REQUIRED) {
stringStates->Add(NS_LITERAL_STRING("required"));
- if (state & states::ALERT)
+ }
+ if (state & states::ALERT) {
stringStates->Add(NS_LITERAL_STRING("alert"));
- if (state & states::INVALID)
+ }
+ if (state & states::INVALID) {
stringStates->Add(NS_LITERAL_STRING("invalid"));
- if (state & states::CHECKABLE)
+ }
+ if (state & states::CHECKABLE) {
stringStates->Add(NS_LITERAL_STRING("checkable"));
+ }
// extraStates
- if (state & states::SUPPORTS_AUTOCOMPLETION)
+ if (state & states::SUPPORTS_AUTOCOMPLETION) {
stringStates->Add(NS_LITERAL_STRING("autocompletion"));
- if (state & states::DEFUNCT)
+ }
+ if (state & states::DEFUNCT) {
stringStates->Add(NS_LITERAL_STRING("defunct"));
- if (state & states::SELECTABLE_TEXT)
+ }
+ if (state & states::SELECTABLE_TEXT) {
stringStates->Add(NS_LITERAL_STRING("selectable text"));
- if (state & states::EDITABLE)
+ }
+ if (state & states::EDITABLE) {
stringStates->Add(NS_LITERAL_STRING("editable"));
- if (state & states::ACTIVE)
+ }
+ if (state & states::ACTIVE) {
stringStates->Add(NS_LITERAL_STRING("active"));
- if (state & states::MODAL)
+ }
+ if (state & states::MODAL) {
stringStates->Add(NS_LITERAL_STRING("modal"));
- if (state & states::MULTI_LINE)
+ }
+ if (state & states::MULTI_LINE) {
stringStates->Add(NS_LITERAL_STRING("multi line"));
- if (state & states::HORIZONTAL)
+ }
+ if (state & states::HORIZONTAL) {
stringStates->Add(NS_LITERAL_STRING("horizontal"));
- if (state & states::OPAQUE1)
+ }
+ if (state & states::OPAQUE1) {
stringStates->Add(NS_LITERAL_STRING("opaque"));
- if (state & states::SINGLE_LINE)
+ }
+ if (state & states::SINGLE_LINE) {
stringStates->Add(NS_LITERAL_STRING("single line"));
- if (state & states::TRANSIENT)
+ }
+ if (state & states::TRANSIENT) {
stringStates->Add(NS_LITERAL_STRING("transient"));
- if (state & states::VERTICAL)
+ }
+ if (state & states::VERTICAL) {
stringStates->Add(NS_LITERAL_STRING("vertical"));
- if (state & states::STALE)
+ }
+ if (state & states::STALE) {
stringStates->Add(NS_LITERAL_STRING("stale"));
- if (state & states::ENABLED)
+ }
+ if (state & states::ENABLED) {
stringStates->Add(NS_LITERAL_STRING("enabled"));
- if (state & states::SENSITIVE)
+ }
+ if (state & states::SENSITIVE) {
stringStates->Add(NS_LITERAL_STRING("sensitive"));
- if (state & states::EXPANDABLE)
+ }
+ if (state & states::EXPANDABLE) {
stringStates->Add(NS_LITERAL_STRING("expandable"));
+ }
//unknown states
- if (!stringStates->Length())
+ if (!stringStates->Length()) {
stringStates->Add(NS_LITERAL_STRING("unknown"));
+ }
stringStates.forget(aStringStates);
- return NS_OK;
}
-// nsIAccessibleRetrieval::getStringEventType()
-NS_IMETHODIMP
+void
nsAccessibilityService::GetStringEventType(uint32_t aEventType,
nsAString& aString)
{
NS_ASSERTION(nsIAccessibleEvent::EVENT_LAST_ENTRY == ArrayLength(kEventTypeNames),
"nsIAccessibleEvent constants are out of sync to kEventTypeNames");
if (aEventType >= ArrayLength(kEventTypeNames)) {
aString.AssignLiteral("unknown");
- return NS_OK;
+ return;
}
CopyUTF8toUTF16(kEventTypeNames[aEventType], aString);
- return NS_OK;
}
-// nsIAccessibleRetrieval::getStringRelationType()
-NS_IMETHODIMP
+void
nsAccessibilityService::GetStringRelationType(uint32_t aRelationType,
nsAString& aString)
{
- NS_ENSURE_ARG(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
+ NS_ENSURE_TRUE_VOID(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
case RelationType::geckoType: \
aString.AssignLiteral(geckoTypeName); \
- return NS_OK;
+ return;
RelationType relationType = static_cast<RelationType>(aRelationType);
switch (relationType) {
#include "RelationTypeMap.h"
default:
aString.AssignLiteral("unknown");
- return NS_OK;
+ return;
}
#undef RELATIONTYPE
}
-NS_IMETHODIMP
-nsAccessibilityService::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 = FindAccessibleInCache(node);
- if (!accessible) {
- nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
- if (document)
- accessible = GetExistingDocAccessible(document);
- }
-
- NS_IF_ADDREF(*aAccessible = ToXPC(accessible));
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsAccessibilityService::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
-nsAccessibilityService::SetLogging(const nsACString& aModules)
-{
-#ifdef A11Y_LOG
- logging::Enable(PromiseFlatCString(aModules));
-#endif
- return NS_OK;
-}
-
-NS_IMETHODIMP
-nsAccessibilityService::IsLogged(const nsAString& aModule, bool* aIsLogged)
-{
- NS_ENSURE_ARG_POINTER(aIsLogged);
- *aIsLogged = false;
-
-#ifdef A11Y_LOG
- *aIsLogged = logging::IsEnabled(aModule);
-#endif
-
- return NS_OK;
-}
-
////////////////////////////////////////////////////////////////////////////////
// nsAccessibilityService public
Accessible*
nsAccessibilityService::CreateAccessible(nsINode* aNode,
Accessible* aContext,
bool* aIsSubtreeHidden)
{
@@ -1322,16 +1258,17 @@ nsAccessibilityService::Init()
for (uint32_t i = 0; i < ArrayLength(sMarkupMapList); i++)
mMarkupMaps.Put(*sMarkupMapList[i].tag, &sMarkupMapList[i]);
#ifdef A11Y_LOG
logging::CheckEnv();
#endif
gAccessibilityService = this;
+ NS_ADDREF(gAccessibilityService); // will release in Shutdown()
if (XRE_IsParentProcess())
gApplicationAccessible = new ApplicationAccessibleWrap();
else
gApplicationAccessible = new ApplicationAccessible();
NS_ADDREF(gApplicationAccessible); // will release in Shutdown()
gApplicationAccessible->Init();
@@ -1354,16 +1291,25 @@ nsAccessibilityService::Init()
PlatformInit();
return true;
}
void
nsAccessibilityService::Shutdown()
{
+ // Application is going to be closed, shutdown accessibility and mark
+ // accessibility service as shutdown to prevent calls of its methods.
+ // Don't null accessibility service static member at this point to be safe
+ // if someone will try to operate with it.
+
+ MOZ_ASSERT(!gIsShutdown, "Accessibility was shutdown already");
+
+ gIsShutdown = true;
+
// Remove observers.
nsCOMPtr<nsIObserverService> observerService =
mozilla::services::GetObserverService();
if (observerService) {
observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
static const char16_t kShutdownIndicator[] = { '0', 0 };
observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kShutdownIndicator);
@@ -1379,34 +1325,29 @@ nsAccessibilityService::Shutdown()
uint32_t timerCount = sPluginTimers->Length();
for (uint32_t i = 0; i < timerCount; i++)
sPluginTimers->ElementAt(i)->Cancel();
sPluginTimers = nullptr;
#endif
- // Application is going to be closed, shutdown accessibility and mark
- // accessibility service as shutdown to prevent calls of its methods.
- // Don't null accessibility service static member at this point to be safe
- // if someone will try to operate with it.
-
- NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already");
-
- gIsShutdown = true;
-
if (XRE_IsParentProcess())
PlatformShutdown();
gApplicationAccessible->Shutdown();
NS_RELEASE(gApplicationAccessible);
gApplicationAccessible = nullptr;
NS_IF_RELEASE(gXPCApplicationAccessible);
gXPCApplicationAccessible = nullptr;
+
+ NS_RELEASE(gAccessibilityService);
+ gAccessibilityService = nullptr;
+ gIsPlatformCaller = false;
}
already_AddRefed<Accessible>
nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
DocAccessible* aDoc)
{
nsAutoString role;
nsCoreUtils::XBLBindingRole(aContent, role);
@@ -1751,19 +1692,16 @@ nsAccessibilityService::MarkupAttributes
continue;
}
nsAccUtils::SetAccAttr(aAttributes, *info->name, *info->value);
}
}
-////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibilityService (DON'T put methods here)
-
Accessible*
nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
{
#ifdef MOZ_ACCESSIBILITY_ATK
ApplicationAccessible* applicationAcc = ApplicationAcc();
if (!applicationAcc)
return nullptr;
@@ -1798,48 +1736,16 @@ nsAccessibilityService::HasAccessible(ns
DocAccessible* document = GetDocAccessible(node->OwnerDoc());
if (!document)
return false;
return document->HasAccessible(node);
}
////////////////////////////////////////////////////////////////////////////////
-// NS_GetAccessibilityService
-////////////////////////////////////////////////////////////////////////////////
-
-/**
- * Return accessibility service; creating one if necessary.
- */
-nsresult
-NS_GetAccessibilityService(nsIAccessibilityService** aResult)
-{
- NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
- *aResult = nullptr;
-
- if (nsAccessibilityService::gAccessibilityService) {
- NS_ADDREF(*aResult = nsAccessibilityService::gAccessibilityService);
- return NS_OK;
- }
-
- RefPtr<nsAccessibilityService> service = new nsAccessibilityService();
- NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
-
- if (!service->Init()) {
- service->Shutdown();
- return NS_ERROR_FAILURE;
- }
-
- statistics::A11yInitialized();
-
- NS_ADDREF(*aResult = service);
- return NS_OK;
-}
-
-////////////////////////////////////////////////////////////////////////////////
// nsAccessibilityService private (DON'T put methods here)
#ifdef MOZ_XUL
already_AddRefed<Accessible>
nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
DocAccessible* aDoc)
{
nsIContent* child = nsTreeUtils::GetDescendantChild(aContent,
@@ -1864,16 +1770,48 @@ nsAccessibilityService::CreateAccessible
// Table or tree table accessible.
RefPtr<Accessible> accessible =
new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame);
return accessible.forget();
}
#endif
+nsAccessibilityService*
+GetOrCreateAccService(bool aIsPlatformCaller)
+{
+ if (aIsPlatformCaller) {
+ nsAccessibilityService::gIsPlatformCaller = aIsPlatformCaller;
+ }
+
+ if (!nsAccessibilityService::gAccessibilityService) {
+ RefPtr<nsAccessibilityService> service = new nsAccessibilityService();
+ if (!service->Init()) {
+ service->Shutdown();
+ return nullptr;
+ }
+ }
+
+ MOZ_ASSERT(nsAccessibilityService::gAccessibilityService,
+ "Accessible service is not initialized.");
+ return nsAccessibilityService::gAccessibilityService;
+}
+
+bool
+CanShutdownAccService()
+{
+ nsAccessibilityService* accService = nsAccessibilityService::gAccessibilityService;
+ if (!accService) {
+ return false;
+ }
+ return !xpcAccessibilityService::IsInUse() &&
+ !accService->IsPlatformCaller() && !accService->IsShutdown() &&
+ !nsCoreUtils::AccEventObserversExist();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Services
////////////////////////////////////////////////////////////////////////////////
namespace mozilla {
namespace a11y {
FocusManager*
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -1,34 +1,39 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef __nsAccessibilityService_h__
#define __nsAccessibilityService_h__
-#include "nsIAccessibilityService.h"
-
#include "mozilla/a11y/DocManager.h"
#include "mozilla/a11y/FocusManager.h"
#include "mozilla/a11y/Role.h"
#include "mozilla/a11y/SelectionManager.h"
#include "mozilla/Preferences.h"
#include "nsIObserver.h"
+#include "nsIAccessibleEvent.h"
#include "nsIEventListenerService.h"
+#include "xpcAccessibilityService.h"
class nsImageFrame;
class nsIArray;
class nsIPersistentProperties;
class nsPluginFrame;
class nsITreeView;
namespace mozilla {
+
+namespace dom {
+ class ContentChild;
+}
+
namespace a11y {
class ApplicationAccessible;
class xpcAccessibleApplication;
/**
* Return focus manager.
*/
@@ -63,50 +68,68 @@ struct MarkupMapInfo {
};
} // namespace a11y
} // namespace mozilla
class nsAccessibilityService final : public mozilla::a11y::DocManager,
public mozilla::a11y::FocusManager,
public mozilla::a11y::SelectionManager,
- public nsIAccessibilityService,
public nsIListenerChangeListener,
public nsIObserver
{
public:
typedef mozilla::a11y::Accessible Accessible;
typedef mozilla::a11y::DocAccessible DocAccessible;
// nsIListenerChangeListener
NS_IMETHOD ListenersChanged(nsIArray* aEventChanges) override;
protected:
- virtual ~nsAccessibilityService();
+ ~nsAccessibilityService();
public:
NS_DECL_ISUPPORTS_INHERITED
- NS_DECL_NSIACCESSIBLERETRIEVAL
NS_DECL_NSIOBSERVER
- // nsIAccessibilityService
- virtual Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
- bool aCanCreate) override;
+ Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
+ bool aCanCreate);
already_AddRefed<Accessible>
CreatePluginAccessible(nsPluginFrame* aFrame, nsIContent* aContent,
Accessible* aContext);
/**
* Adds/remove ATK root accessible for gtk+ native window to/from children
* of the application accessible.
*/
- virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible) override;
- virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible) override;
+ Accessible* AddNativeRootAccessible(void* aAtkAccessible);
+ void RemoveNativeRootAccessible(Accessible* aRootAccessible);
+
+ bool HasAccessible(nsIDOMNode* aDOMNode);
+
+ /**
+ * Get a string equivalent for an accessilbe role value.
+ */
+ void GetStringRole(uint32_t aRole, nsAString& aString);
- virtual bool HasAccessible(nsIDOMNode* aDOMNode) override;
+ /**
+ * Get a string equivalent for an accessible state/extra state.
+ */
+ void GetStringStates(uint32_t aState, uint32_t aExtraState,
+ nsISupports **aStringStates);
+
+ /**
+ * Get a string equivalent for an accessible event value.
+ */
+ void GetStringEventType(uint32_t aEventType, nsAString& aString);
+
+ /**
+ * Get a string equivalent for an accessible relation type.
+ */
+ void GetStringRelationType(uint32_t aRelationType, nsAString& aString);
// nsAccesibilityService
/**
* Notification used to update the accessible tree when deck panel is
* switched.
*/
void DeckPanelSwitched(nsIPresShell* aPresShell, nsIContent* aDeckNode,
nsIFrame* aPrevBoxFrame, nsIFrame* aCurrentBoxFrame);
@@ -118,35 +141,35 @@ public:
void ContentRangeInserted(nsIPresShell* aPresShell, nsIContent* aContainer,
nsIContent* aStartChild, nsIContent* aEndChild);
/**
* Notification used to update the accessible tree when content is removed.
*/
void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aChild);
- virtual void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent);
+ void UpdateText(nsIPresShell* aPresShell, nsIContent* aContent);
/**
* Update XUL:tree accessible tree when treeview is changed.
*/
void TreeViewChanged(nsIPresShell* aPresShell, nsIContent* aContent,
nsITreeView* aView);
/**
* Notify of input@type="element" value change.
*/
void RangeValueChanged(nsIPresShell* aPresShell, nsIContent* aContent);
/**
* Update list bullet accessible.
*/
- virtual void UpdateListBullet(nsIPresShell* aPresShell,
- nsIContent* aHTMLListItemContent,
- bool aHasBullet);
+ void UpdateListBullet(nsIPresShell* aPresShell,
+ nsIContent* aHTMLListItemContent,
+ bool aHasBullet);
/**
* Update the image map.
*/
void UpdateImageMap(nsImageFrame* aImageFrame);
/**
* Update the label accessible tree when rendered @value is changed.
@@ -158,33 +181,38 @@ public:
* Notify accessibility that anchor jump has been accomplished to the given
* target. Used by layout.
*/
void NotifyOfAnchorJumpTo(nsIContent *aTarget);
/**
* Notify that presshell is activated.
*/
- virtual void PresShellActivated(nsIPresShell* aPresShell);
+ void PresShellActivated(nsIPresShell* aPresShell);
/**
* Recreate an accessible for the given content node in the presshell.
*/
void RecreateAccessible(nsIPresShell* aPresShell, nsIContent* aContent);
- virtual void FireAccessibleEvent(uint32_t aEvent, Accessible* aTarget) override;
+ void FireAccessibleEvent(uint32_t aEvent, Accessible* aTarget);
// nsAccessibiltiyService
/**
* Return true if accessibility service has been shutdown.
*/
static bool IsShutdown() { return gIsShutdown; }
/**
+ * Return true if accessibility service has been initialized by platform.
+ */
+ static bool IsPlatformCaller() { return gIsPlatformCaller; };
+
+ /**
* Creates an accessible for the given DOM node.
*
* @param aNode [in] the given node
* @param aContext [in] context the accessible is created in
* @param aIsSubtreeHidden [out, optional] indicates whether the node's
* frame and its subtree is hidden
*/
Accessible* CreateAccessible(nsINode* aNode, Accessible* aContext,
@@ -200,17 +228,17 @@ public:
/**
* Set the object attribute defined by markup for the given element.
*/
void MarkupAttributes(const nsIContent* aContent,
nsIPersistentProperties* aAttributes) const;
private:
// nsAccessibilityService creation is controlled by friend
- // NS_GetAccessibilityService, keep constructors private.
+ // GetOrCreateAccService, keep constructors private.
nsAccessibilityService();
nsAccessibilityService(const nsAccessibilityService&);
nsAccessibilityService& operator =(const nsAccessibilityService&);
private:
/**
* Initialize accessibility service.
*/
@@ -253,53 +281,70 @@ private:
static mozilla::a11y::ApplicationAccessible* gApplicationAccessible;
static mozilla::a11y::xpcAccessibleApplication* gXPCApplicationAccessible;
/**
* Indicates whether accessibility service was shutdown.
*/
static bool gIsShutdown;
+ /**
+ * Indicates whether accessibility service was initialized by platform.
+ */
+ static bool gIsPlatformCaller;
+
nsDataHashtable<nsPtrHashKey<const nsIAtom>, const mozilla::a11y::MarkupMapInfo*> mMarkupMaps;
friend nsAccessibilityService* GetAccService();
+ friend nsAccessibilityService* GetOrCreateAccService(bool);
+ friend bool CanShutdownAccService();
friend mozilla::a11y::FocusManager* mozilla::a11y::FocusMgr();
friend mozilla::a11y::SelectionManager* mozilla::a11y::SelectionMgr();
friend mozilla::a11y::ApplicationAccessible* mozilla::a11y::ApplicationAcc();
friend mozilla::a11y::xpcAccessibleApplication* mozilla::a11y::XPCApplicationAcc();
-
- friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult);
+ friend class mozilla::dom::ContentChild;
+ friend class xpcAccessibilityService;
};
/**
* Return the accessibility service instance. (Handy global function)
*/
inline nsAccessibilityService*
GetAccService()
{
return nsAccessibilityService::gAccessibilityService;
}
/**
+ * Return accessibility service instance; creating one if necessary.
+ */
+nsAccessibilityService* GetOrCreateAccService(bool aIsPlatformCaller = true);
+
+/**
+ * Return a flag indicating if accessibility service can be shutdown.
+ */
+bool CanShutdownAccService();
+
+/**
* Return true if we're in a content process and not B2G.
*/
inline bool
IPCAccessibilityActive()
{
#ifdef MOZ_B2G
return false;
#else
return XRE_IsContentProcess() &&
mozilla::Preferences::GetBool("accessibility.ipc_architecture.enabled", true);
#endif
}
/**
* Map nsIAccessibleEvents constants to strings. Used by
- * nsIAccessibleRetrieval::getStringEventType() method.
+ * nsAccessibilityService::GetStringEventType() method.
*/
static const char kEventTypeNames[][40] = {
"unknown", //
"show", // EVENT_SHOW
"hide", // EVENT_HIDE
"reorder", // EVENT_REORDER
"active decendent change", // EVENT_ACTIVE_DECENDENT_CHANGED
"focus", // EVENT_FOCUS
@@ -382,10 +427,9 @@ static const char kEventTypeNames[][40]
"hyperlink start index changed", // EVENT_HYPERLINK_START_INDEX_CHANGED
"hypertext changed", // EVENT_HYPERTEXT_CHANGED
"hypertext links count changed", // EVENT_HYPERTEXT_NLINKS_CHANGED
"object attribute changed", // EVENT_OBJECT_ATTRIBUTE_CHANGED
"virtual cursor changed", // EVENT_VIRTUALCURSOR_CHANGED
"text value change", // EVENT_TEXT_VALUE_CHANGE
};
-#endif /* __nsIAccessibilityService_h__ */
-
+#endif
--- a/accessible/interfaces/moz.build
+++ b/accessible/interfaces/moz.build
@@ -3,43 +3,38 @@
# 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/.
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows' and CONFIG['COMPILE_ENVIRONMENT']:
DIRS += ['msaa', 'ia2']
XPIDL_SOURCES += [
+ 'nsIAccessibilityService.idl',
'nsIAccessible.idl',
'nsIAccessibleApplication.idl',
'nsIAccessibleCaretMoveEvent.idl',
'nsIAccessibleDocument.idl',
'nsIAccessibleEditableText.idl',
'nsIAccessibleEvent.idl',
'nsIAccessibleHideEvent.idl',
'nsIAccessibleHyperLink.idl',
'nsIAccessibleHyperText.idl',
'nsIAccessibleImage.idl',
'nsIAccessibleObjectAttributeChangedEvent.idl',
'nsIAccessiblePivot.idl',
'nsIAccessibleRelation.idl',
- 'nsIAccessibleRetrieval.idl',
'nsIAccessibleRole.idl',
'nsIAccessibleSelectable.idl',
'nsIAccessibleStateChangeEvent.idl',
'nsIAccessibleStates.idl',
'nsIAccessibleTable.idl',
'nsIAccessibleTableChangeEvent.idl',
'nsIAccessibleText.idl',
'nsIAccessibleTextChangeEvent.idl',
'nsIAccessibleTextRange.idl',
'nsIAccessibleTypes.idl',
'nsIAccessibleValue.idl',
'nsIAccessibleVirtualCursorChangeEvent.idl',
'nsIXBLAccessible.idl',
]
XPIDL_MODULE = 'accessibility'
-
-EXPORTS += [
- 'nsIAccessibilityService.h',
-]
-
deleted file mode 100644
--- a/accessible/interfaces/nsIAccessibilityService.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
- *
- * 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/. */
-
-#ifndef _nsIAccessibilityService_h_
-#define _nsIAccessibilityService_h_
-
-#include "nsIAccessibleRetrieval.h"
-#include "nsIAccessibleEvent.h"
-
-namespace mozilla {
-namespace a11y {
-
-class Accessible;
-
-} // namespace a11y
-} // namespace mozilla
-
-class nsIPresShell;
-
-// 0e7e6879-854b-4260-bc6e-525b5fb5cf34
-#define NS_IACCESSIBILITYSERVICE_IID \
-{ 0x0e7e6879, 0x854b, 0x4260, \
- { 0xbc, 0x6e, 0x52, 0x5b, 0x5f, 0xb5, 0xcf, 0x34 } }
-
-class nsIAccessibilityService : public nsIAccessibleRetrieval
-{
-public:
- NS_DECLARE_STATIC_IID_ACCESSOR(NS_IACCESSIBILITYSERVICE_IID)
-
- /**
- * Return root document accessible that is or contains a document accessible
- * for the given presshell.
- *
- * @param aPresShell [in] the presshell
- * @param aCanCreate [in] points whether the root document accessible
- * should be returned from the cache or can be created
- */
- virtual mozilla::a11y::Accessible*
- GetRootDocumentAccessible(nsIPresShell* aPresShell, bool aCanCreate) = 0;
-
- /**
- * Adds/remove ATK root accessible for gtk+ native window to/from children
- * of the application accessible.
- */
- virtual mozilla::a11y::Accessible*
- AddNativeRootAccessible(void* aAtkAccessible) = 0;
- virtual void
- RemoveNativeRootAccessible(mozilla::a11y::Accessible* aRootAccessible) = 0;
-
- /**
- * Fire accessible event of the given type for the given target.
- *
- * @param aEvent [in] accessible event type
- * @param aTarget [in] target of accessible event
- */
- virtual void FireAccessibleEvent(uint32_t aEvent,
- mozilla::a11y::Accessible* aTarget) = 0;
-
- /**
- * Return true if the given DOM node has accessible object.
- */
- virtual bool HasAccessible(nsIDOMNode* aDOMNode) = 0;
-};
-
-NS_DEFINE_STATIC_IID_ACCESSOR(nsIAccessibilityService,
- NS_IACCESSIBILITYSERVICE_IID)
-
-// for component registration
-// {DE401C37-9A7F-4278-A6F8-3DE2833989EF}
-#define NS_ACCESSIBILITY_SERVICE_CID \
-{ 0xde401c37, 0x9a7f, 0x4278, { 0xa6, 0xf8, 0x3d, 0xe2, 0x83, 0x39, 0x89, 0xef } }
-
-extern nsresult
-NS_GetAccessibilityService(nsIAccessibilityService** aResult);
-
-#endif
rename from accessible/interfaces/nsIAccessibleRetrieval.idl
rename to accessible/interfaces/nsIAccessibilityService.idl
--- a/accessible/interfaces/nsIAccessibleRetrieval.idl
+++ b/accessible/interfaces/nsIAccessibilityService.idl
@@ -11,18 +11,18 @@ interface nsIWeakReference;
interface nsIPresShell;
interface nsIAccessiblePivot;
/**
* An interface for in-process accessibility clients wishing to get an
* nsIAccessible for a given DOM node. More documentation at:
* http://www.mozilla.org/projects/ui/accessibility
*/
-[scriptable, builtinclass, uuid(17f86615-1a3d-4021-b227-3a2ef5cbffd8)]
-interface nsIAccessibleRetrieval : nsISupports
+[scriptable, builtinclass, uuid(9a6f80fe-25cc-405c-9f8f-25869bc9f94e)]
+interface nsIAccessibilityService : nsISupports
{
/**
* Return application accessible.
*/
nsIAccessible getApplicationAccessible();
/**
* Return an nsIAccessible for a DOM node in pres shell 0.
@@ -94,17 +94,15 @@ interface nsIAccessibleRetrieval : nsISu
void setLogging(in ACString aModules);
/**
* Return true if the given module is logged.
*/
boolean isLogged(in AString aModule);
};
-
-%{ C++
-
-// for component registration
-// {663CA4A8-D219-4000-925D-D8F66406B626}
-#define NS_ACCESSIBLE_RETRIEVAL_CID \
-{ 0x663ca4a8, 0xd219, 0x4000, { 0x92, 0x5d, 0xd8, 0xf6, 0x64, 0x6, 0xb6, 0x26 } }
-
-%}
+/**
+ * @deprecated, use nsIAccessibilityService instead.
+ */
+[scriptable, builtinclass, uuid(d85e0cbe-47ce-490c-8488-f821dd2be0c2)]
+interface nsIAccessibleRetrieval : nsIAccessibilityService
+{
+};
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -1,16 +1,17 @@
# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# 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/.
UNIFIED_SOURCES += [
'nsAccessibleRelation.cpp',
+ 'xpcAccessibilityService.cpp',
'xpcAccessible.cpp',
'xpcAccessibleApplication.cpp',
'xpcAccessibleDocument.cpp',
'xpcAccessibleGeneric.cpp',
'xpcAccessibleHyperLink.cpp',
'xpcAccessibleHyperText.cpp',
'xpcAccessibleImage.cpp',
'xpcAccessibleSelectable.cpp',
@@ -21,16 +22,17 @@ UNIFIED_SOURCES += [
]
SOURCES += [
'!xpcAccEvents.cpp',
]
EXPORTS += [
'!xpcAccEvents.h',
+ 'xpcAccessibilityService.h',
]
LOCAL_INCLUDES += [
'/accessible/base',
'/accessible/generic',
]
if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']:
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.cpp
@@ -0,0 +1,249 @@
+/* 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)
+{
+ if (CanShutdownAccService()) {
+ GetAccService()->Shutdown();
+ }
+
+ 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(false);
+ }
+
+ 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(false);
+
+ xpcAccessibilityService* service = new xpcAccessibilityService();
+ NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
+ xpcAccessibilityService::gXPCAccessibilityService = service;
+ NS_ADDREF(*aResult = service);
+
+ return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.h
@@ -0,0 +1,66 @@
+/* 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/. */
+
+#ifndef mozilla_a11y_xpcAccessibilityService_h_
+#define mozilla_a11y_xpcAccessibilityService_h_
+
+#include "nsIAccessibilityService.h"
+
+class xpcAccessibilityService : public nsIAccessibleRetrieval
+{
+
+public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIACCESSIBILITYSERVICE
+ NS_DECL_NSIACCESSIBLERETRIEVAL
+
+ /**
+ * Return true if xpc accessibility service is in use.
+ */
+ static bool IsInUse() {
+ // When ref count goes down to 1 (held internally as a static reference),
+ // it means that there are no more external references and thus it is not in
+ // use.
+ return gXPCAccessibilityService ? gXPCAccessibilityService->mRefCnt > 1 : false;
+ }
+
+protected:
+ virtual ~xpcAccessibilityService() {
+ if (mShutdownTimer) {
+ mShutdownTimer->Cancel();
+ mShutdownTimer = nullptr;
+ }
+ gXPCAccessibilityService = nullptr;
+ }
+
+private:
+ // xpcAccessibilityService creation is controlled by friend
+ // NS_GetAccessibilityService, keep constructor private.
+ xpcAccessibilityService() { };
+
+ nsCOMPtr<nsITimer> mShutdownTimer;
+
+ /**
+ * Reference for xpc accessibility service instance.
+ */
+ static xpcAccessibilityService* gXPCAccessibilityService;
+
+ /**
+ * Used to shutdown nsAccessibilityService if xpcom accessible service is not
+ * in use any more.
+ */
+ static void ShutdownCallback(nsITimer* aTimer, void* aClosure);
+
+ friend nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult);
+};
+
+// for component registration
+// {3b265b69-f813-48ff-880d-d88d101af404}
+#define NS_ACCESSIBILITY_SERVICE_CID \
+{ 0x3b265b69, 0xf813, 0x48ff, { 0x88, 0x0d, 0xd8, 0x8d, 0x10, 0x1a, 0xf4, 0x04 } }
+
+extern nsresult
+NS_GetAccessibilityService(nsIAccessibilityService** aResult);
+
+#endif