Bug 527003 - separating XPCOM parts from nsAccessibilityService. Removing a11y service in favour of using nsAccessibilityService directly. Adding support for a11y service shutdown. r=surkov
authorYura Zenevich <yzenevich@mozilla.com>
Mon, 08 Aug 2016 11:35:56 -0400
changeset 350022 13c9ca2db92104b11bf1999c7ea05004d9e864e1
parent 350021 5a153f865cb1f9ed33b54f1905e3d69d5d4e8123
child 350023 e283da610b05190190d77fc6573895e12c78b05e
push id6570
push userraliiev@mozilla.com
push dateMon, 14 Nov 2016 12:26:13 +0000
treeherdermozilla-beta@f455459b2ae5 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssurkov
bugs527003
milestone51.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 527003 - separating XPCOM parts from nsAccessibilityService. Removing a11y service in favour of using nsAccessibilityService directly. Adding support for a11y service shutdown. r=surkov MozReview-Commit-ID: KKeywNi3fQb
accessible/base/DocManager.cpp
accessible/base/nsAccessibilityService.cpp
accessible/base/nsAccessibilityService.h
accessible/interfaces/moz.build
accessible/interfaces/nsIAccessibilityService.h
accessible/interfaces/nsIAccessibilityService.idl
accessible/interfaces/nsIAccessibleRetrieval.idl
accessible/xpcom/moz.build
accessible/xpcom/xpcAccessibilityService.cpp
accessible/xpcom/xpcAccessibilityService.h
dom/ipc/ContentChild.cpp
layout/build/nsLayoutModule.cpp
layout/inspector/inDOMView.cpp
widget/gtk/nsWindow.cpp
widget/nsBaseWidget.cpp
widget/windows/nsWindow.cpp
xpcom/build/ServiceList.h
xpcom/build/Services.cpp
--- 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,26 +1,26 @@
 /* -*- 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 {
@@ -63,50 +63,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 +136,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 +176,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 +223,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 +276,69 @@ 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 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 +421,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
new file mode 100644
--- /dev/null
+++ b/accessible/interfaces/nsIAccessibilityService.idl
@@ -0,0 +1,108 @@
+/* -*- 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/. */
+
+#include "nsISupports.idl"
+
+interface nsIDOMNode;
+interface nsIAccessible;
+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(9a6f80fe-25cc-405c-9f8f-25869bc9f94e)]
+interface nsIAccessibilityService : nsISupports
+{
+  /**
+   * Return application accessible.
+   */
+  nsIAccessible getApplicationAccessible();
+
+  /**
+   * Return an nsIAccessible for a DOM node in pres shell 0.
+   * Create a new accessible of the appropriate type if necessary,
+   * or use one from the accessibility cache if it already exists.
+   * @param aNode The DOM node to get an accessible for.
+   * @return The nsIAccessible for the given DOM node.
+   */
+  nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
+
+   /**
+    * Returns accessible role as a string.
+    *
+    * @param aRole - the accessible role constants.
+    */
+  AString getStringRole(in unsigned long aRole);
+
+   /**
+    * Returns list which contains accessible states as a strings.
+    *
+    * @param aStates - accessible states.
+    * @param aExtraStates - accessible extra states.
+    */
+  nsISupports getStringStates(in unsigned long aStates,
+                              in unsigned long aExtraStates);
+
+  /**
+   * Get the type of accessible event as a string.
+   *
+   * @param aEventType - the accessible event type constant
+   * @return - accessible event type presented as human readable string
+   */
+  AString getStringEventType(in unsigned long aEventType);
+
+  /**
+   * Get the type of accessible relation as a string.
+   *
+   * @param aRelationType - the accessible relation type constant
+   * @return - accessible relation type presented as human readable string
+   */
+  AString getStringRelationType(in unsigned long aRelationType);
+
+  /**
+   * Return an accessible for the given DOM node from the cache.
+   * @note  the method is intended for testing purposes
+   *
+   * @param aNode  [in] the DOM node to get an accessible for
+   *
+   * @return       cached accessible for the given DOM node if any
+   */
+  nsIAccessible getAccessibleFromCache(in nsIDOMNode aNode);
+
+  /**
+   * Create a new pivot for tracking a position and traversing a subtree.
+   *
+   * @param aRoot [in] the accessible root for the pivot
+   * @return a new pivot
+   */
+  nsIAccessiblePivot createAccessiblePivot(in nsIAccessible aRoot);
+
+  /**
+   * Enable logging for the given modules, all other modules aren't logged.
+   *
+   * @param aModules [in] list of modules, format is comma separated list
+   *                      like 'docload,doccreate'.
+   * @note Works on debug build only.
+   * @see Logging.cpp for list of possible values.
+   */
+  void setLogging(in ACString aModules);
+
+  /**
+   * Return true if the given module is logged.
+   */
+  boolean isLogged(in AString aModule);
+};
+
+/**
+ * @deprecated, use nsIAccessibilityService instead.
+ */
+[scriptable, builtinclass, uuid(d85e0cbe-47ce-490c-8488-f821dd2be0c2)]
+interface nsIAccessibleRetrieval : nsIAccessibilityService
+{
+};
deleted file mode 100644
--- a/accessible/interfaces/nsIAccessibleRetrieval.idl
+++ /dev/null
@@ -1,110 +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/. */
-
-#include "nsISupports.idl"
-
-interface nsIDOMNode;
-interface nsIAccessible;
-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
-{
-  /**
-   * Return application accessible.
-   */
-  nsIAccessible getApplicationAccessible();
-
-  /**
-   * Return an nsIAccessible for a DOM node in pres shell 0.
-   * Create a new accessible of the appropriate type if necessary,
-   * or use one from the accessibility cache if it already exists.
-   * @param aNode The DOM node to get an accessible for.
-   * @return The nsIAccessible for the given DOM node.
-   */
-  nsIAccessible getAccessibleFor(in nsIDOMNode aNode);
-
-   /**
-    * Returns accessible role as a string.
-    *
-    * @param aRole - the accessible role constants.
-    */
-  AString getStringRole(in unsigned long aRole);
-
-   /**
-    * Returns list which contains accessible states as a strings.
-    *
-    * @param aStates - accessible states.
-    * @param aExtraStates - accessible extra states.
-    */
-  nsISupports getStringStates(in unsigned long aStates,
-                              in unsigned long aExtraStates);
-
-  /**
-   * Get the type of accessible event as a string.
-   *
-   * @param aEventType - the accessible event type constant
-   * @return - accessible event type presented as human readable string
-   */
-  AString getStringEventType(in unsigned long aEventType);
-
-  /**
-   * Get the type of accessible relation as a string.
-   *
-   * @param aRelationType - the accessible relation type constant
-   * @return - accessible relation type presented as human readable string
-   */
-  AString getStringRelationType(in unsigned long aRelationType);
-
-  /**
-   * Return an accessible for the given DOM node from the cache.
-   * @note  the method is intended for testing purposes
-   *
-   * @param aNode  [in] the DOM node to get an accessible for
-   *
-   * @return       cached accessible for the given DOM node if any
-   */
-  nsIAccessible getAccessibleFromCache(in nsIDOMNode aNode);
-
-  /**
-   * Create a new pivot for tracking a position and traversing a subtree.
-   *
-   * @param aRoot [in] the accessible root for the pivot
-   * @return a new pivot
-   */
-  nsIAccessiblePivot createAccessiblePivot(in nsIAccessible aRoot);
-
-  /**
-   * Enable logging for the given modules, all other modules aren't logged.
-   *
-   * @param aModules [in] list of modules, format is comma separated list
-   *                      like 'docload,doccreate'.
-   * @note Works on debug build only.
-   * @see Logging.cpp for list of possible values.
-   */
-  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 } }
-
-%}
--- 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
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -159,17 +159,17 @@
 #include "mozilla/widget/AudioSession.h"
 #endif
 
 #ifdef MOZ_X11
 #include "mozilla/X11Util.h"
 #endif
 
 #ifdef ACCESSIBILITY
-#include "nsIAccessibilityService.h"
+#include "nsAccessibilityService.h"
 #endif
 
 #ifndef MOZ_SIMPLEPUSH
 #include "mozilla/dom/PushNotifier.h"
 #endif
 
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/cellbroadcast/CellBroadcastIPCService.h"
@@ -2464,18 +2464,17 @@ ContentChild::RecvFlushMemory(const nsSt
 }
 
 bool
 ContentChild::RecvActivateA11y()
 {
 #ifdef ACCESSIBILITY
   // Start accessibility in content process if it's running in chrome
   // process.
-  nsCOMPtr<nsIAccessibilityService> accService =
-    services::GetAccessibilityService();
+  GetOrCreateAccService();
 #endif
   return true;
 }
 
 bool
 ContentChild::RecvGarbageCollect()
 {
   // Rebroadcast the "child-gc-request" so that workers will GC.
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -665,17 +665,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(UDPSocket
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(GeckoMediaPluginService, GeckoMediaPluginService::GetGeckoMediaPluginService)
 
 #ifdef MOZ_B2G
 NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(nsIHardwareKeyHandler,
                                          HardwareKeyHandler::GetInstance)
 #endif
 
 #ifdef ACCESSIBILITY
-#include "nsAccessibilityService.h"
+#include "xpcAccessibilityService.h"
 
   MAKE_CTOR(CreateA11yService, nsIAccessibilityService, NS_GetAccessibilityService)
 #endif
 
 static nsresult
 Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
                                    void **aResult)
 {
--- a/layout/inspector/inDOMView.cpp
+++ b/layout/inspector/inDOMView.cpp
@@ -22,17 +22,17 @@
 #include "nsIDocument.h"
 #include "nsIServiceManager.h"
 #include "nsITreeColumns.h"
 #include "nsITreeBoxObject.h"
 #include "mozilla/dom/Element.h"
 #include "mozilla/Services.h"
 
 #ifdef ACCESSIBILITY
-#include "nsIAccessibilityService.h"
+#include "nsAccessibilityService.h"
 #endif
 
 using namespace mozilla;
 
 ////////////////////////////////////////////////////////////////////////
 // inDOMViewNode
 
 class inDOMViewNode
@@ -324,18 +324,17 @@ inDOMView::GetCellProperties(int32_t row
       break;
     case nsIDOMNode::NOTATION_NODE:
       aProps.AppendLiteral("NOTATION_NODE");
       break;
   }
 
 #ifdef ACCESSIBILITY
   if (mShowAccessibleNodes) {
-	  nsCOMPtr<nsIAccessibilityService> accService =
-        services::GetAccessibilityService();
+    nsAccessibilityService* accService = GetOrCreateAccService();
     NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
 
     if (accService->HasAccessible(node->node))
       aProps.AppendLiteral(" ACCESSIBLE_NODE");
   }
 #endif
 
   return NS_OK;
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -6337,18 +6337,17 @@ nsWindow::CreateRootAccessible()
 
 void
 nsWindow::DispatchEventToRootAccessible(uint32_t aEventType)
 {
     if (!a11y::ShouldA11yBeEnabled()) {
         return;
     }
 
-    nsCOMPtr<nsIAccessibilityService> accService =
-        services::GetAccessibilityService();
+    nsAccessibilityService* accService = GetOrCreateAccService();
     if (!accService) {
         return;
     }
 
     // Get the root document accessible and fire event to it.
     a11y::Accessible* acc = GetRootAccessible();
     if (acc) {
         accService->FireAccessibleEvent(aEventType, acc);
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1929,18 +1929,17 @@ nsBaseWidget::GetRootAccessible()
 
   // If container is null then the presshell is not active. This often happens
   // when a preshell is being held onto for fastback.
   nsPresContext* presContext = presShell->GetPresContext();
   NS_ENSURE_TRUE(presContext->GetContainerWeak(), nullptr);
 
   // Accessible creation might be not safe so use IsSafeToRunScript to
   // make sure it's not created at unsafe times.
-  nsCOMPtr<nsIAccessibilityService> accService =
-    services::GetAccessibilityService();
+  nsAccessibilityService* accService = GetOrCreateAccService();
   if (accService) {
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(MOZ_WIDGET_GTK)
     if (!mAccessibilityInUseFlag) {
       mAccessibilityInUseFlag = true;
       uint32_t now = PRTimeToSeconds(PR_Now());
       Preferences::SetInt(kAccessibilityLastRunDatePref, now);
     }
 #endif
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -7044,18 +7044,17 @@ nsWindow::GetAccessible()
     return nullptr;
   }
 
   // In case of popup window return a popup accessible.
   nsView* view = nsView::GetViewFor(this);
   if (view) {
     nsIFrame* frame = view->GetFrame();
     if (frame && nsLayoutUtils::IsPopup(frame)) {
-      nsCOMPtr<nsIAccessibilityService> accService =
-        services::GetAccessibilityService();
+      nsAccessibilityService* accService = GetOrCreateAccService();
       if (accService) {
         a11y::DocAccessible* docAcc =
           GetAccService()->GetDocAccessible(frame->PresContext()->PresShell());
         if (docAcc) {
           NS_LOG_WMGETOBJECT(this, mWnd,
                              docAcc->GetAccessibleOrDescendant(frame->GetContent()));
           return docAcc->GetAccessibleOrDescendant(frame->GetContent());
         }
--- a/xpcom/build/ServiceList.h
+++ b/xpcom/build/ServiceList.h
@@ -1,19 +1,15 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 // IWYU pragma: private, include "mozilla/Services.h"
 
-#ifdef ACCESSIBILITY
-MOZ_SERVICE(AccessibilityService, nsIAccessibilityService,
-            "@mozilla.org/accessibilityService;1")
-#endif
 MOZ_SERVICE(ChromeRegistryService, nsIChromeRegistry,
             "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(ToolkitChromeRegistryService, nsIToolkitChromeRegistry,
             "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(XULChromeRegistryService, nsIXULChromeRegistry,
             "@mozilla.org/chrome/chrome-registry;1")
 MOZ_SERVICE(XULOverlayProviderService, nsIXULOverlayProvider,
             "@mozilla.org/chrome/chrome-registry;1")
--- a/xpcom/build/Services.cpp
+++ b/xpcom/build/Services.cpp
@@ -8,19 +8,16 @@
 #include "mozilla/Services.h"
 #include "nsComponentManager.h"
 #include "nsIObserverService.h"
 #include "nsNetCID.h"
 #include "nsObserverService.h"
 #include "nsXPCOMPrivate.h"
 #include "nsIIOService.h"
 #include "nsIDirectoryService.h"
-#ifdef ACCESSIBILITY
-#include "nsIAccessibilityService.h"
-#endif
 #include "nsIChromeRegistry.h"
 #include "nsIStringBundle.h"
 #include "nsIToolkitChromeRegistry.h"
 #include "nsIXULOverlayProvider.h"
 #include "IHistory.h"
 #include "nsIXPConnect.h"
 #include "inIDOMUtils.h"
 #include "nsIPermissionManager.h"