Bug 527003 - separated out xpcom parts of nsAccessibilityService. draft
authorYura Zenevich <yzenevich@mozilla.com>
Tue, 21 Jun 2016 16:46:17 -0400
changeset 380368 290beeedc8ba0e8d8e9854d241835d6edda64b11
parent 380367 85f9c5693ddf93dc0e98dbf998a8ed28a32c7f43
child 380369 abf2c7f58576849edc86460701525e2fea3cf36f
push id21208
push useryura.zenevich@gmail.com
push dateTue, 21 Jun 2016 20:51:29 +0000
bugs527003, 100644
milestone50.0a1
Bug 527003 - separated out xpcom parts of nsAccessibilityService. MozReview-Commit-ID: ALiZp5hUXK1 --- accessible/base/moz.build | 1 + accessible/base/nsAccessibilityService.cpp | 285 +---------------- accessible/base/nsAccessibilityService.h | 45 ++- accessible/interfaces/nsIAccessibilityService.idl | 10 - accessible/xpcom/moz.build | 2 + accessible/xpcom/xpcAccessibilityService.cpp | 356 ++++++++++++++++++++++ accessible/xpcom/xpcAccessibilityService.h | 41 +++ dom/ipc/ContentChild.cpp | 2 +- layout/build/nsLayoutModule.cpp | 4 +- layout/inspector/inDOMView.cpp | 2 +- widget/gtk/nsWindow.cpp | 2 +- widget/nsBaseWidget.cpp | 2 +- widget/windows/nsWindow.cpp | 2 +- 13 files changed, 448 insertions(+), 306 deletions(-) create mode 100644 accessible/xpcom/xpcAccessibilityService.cpp create mode 100644 accessible/xpcom/xpcAccessibilityService.h
accessible/base/moz.build
accessible/base/nsAccessibilityService.cpp
accessible/base/nsAccessibilityService.h
accessible/interfaces/nsIAccessibilityService.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
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -13,16 +13,17 @@ EXPORTS.mozilla.a11y += [
     'AccTypes.h',
     'DocManager.h',
     'FocusManager.h',
     'Platform.h',
     'RelationType.h',
     'Role.h',
     'SelectionManager.h',
     'States.h',
+    'Statistics.h',
 ]
 
 if CONFIG['MOZ_DEBUG']:
     EXPORTS.mozilla.a11y += [
         'Logging.h',
     ]
 
 UNIFIED_SOURCES += [
--- 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"
@@ -63,17 +62,16 @@
 #include "nsPluginFrame.h"
 #include "nsSVGPathGeometryFrame.h"
 #include "nsTreeBodyFrame.h"
 #include "nsTreeColumns.h"
 #include "nsTreeUtils.h"
 #include "nsXBLPrototypeBinding.h"
 #include "nsXBLBinding.h"
 #include "mozilla/ArrayUtils.h"
-#include "mozilla/dom/DOMStringList.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "nsDeckFrame.h"
 
 #ifdef MOZ_XUL
 #include "XULAlertAccessible.h"
 #include "XULColorPickerAccessible.h"
 #include "XULComboboxAccessible.h"
@@ -335,17 +333,16 @@ nsAccessibilityService::ListenersChanged
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsISupports
 
 NS_IMPL_ISUPPORTS_INHERITED(nsAccessibilityService,
                             DocManager,
-                            nsIAccessibilityService,
                             nsIObserver,
                             nsIListenerChangeListener,
                             nsISelectionListener) // from SelectionManager
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIObserver
 
 NS_IMETHODIMP
@@ -726,288 +723,48 @@ void
 nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
                                            nsIContent* aContent)
 {
   DocAccessible* document = GetDocAccessible(aPresShell);
   if (document)
     document->RecreateAccessible(aContent);
 }
 
-////////////////////////////////////////////////////////////////////////////////
-// nsIAccessibilityService
-
-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
-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)
-    stringStates->Add(NS_LITERAL_STRING("unavailable"));
-  if (state & states::SELECTED)
-    stringStates->Add(NS_LITERAL_STRING("selected"));
-  if (state & states::FOCUSED)
-    stringStates->Add(NS_LITERAL_STRING("focused"));
-  if (state & states::PRESSED)
-    stringStates->Add(NS_LITERAL_STRING("pressed"));
-  if (state & states::CHECKED)
-    stringStates->Add(NS_LITERAL_STRING("checked"));
-  if (state & states::MIXED)
-    stringStates->Add(NS_LITERAL_STRING("mixed"));
-  if (state & states::READONLY)
-    stringStates->Add(NS_LITERAL_STRING("readonly"));
-  if (state & states::HOTTRACKED)
-    stringStates->Add(NS_LITERAL_STRING("hottracked"));
-  if (state & states::DEFAULT)
-    stringStates->Add(NS_LITERAL_STRING("default"));
-  if (state & states::EXPANDED)
-    stringStates->Add(NS_LITERAL_STRING("expanded"));
-  if (state & states::COLLAPSED)
-    stringStates->Add(NS_LITERAL_STRING("collapsed"));
-  if (state & states::BUSY)
-    stringStates->Add(NS_LITERAL_STRING("busy"));
-  if (state & states::FLOATING)
-    stringStates->Add(NS_LITERAL_STRING("floating"));
-  if (state & states::ANIMATED)
-    stringStates->Add(NS_LITERAL_STRING("animated"));
-  if (state & states::INVISIBLE)
-    stringStates->Add(NS_LITERAL_STRING("invisible"));
-  if (state & states::OFFSCREEN)
-    stringStates->Add(NS_LITERAL_STRING("offscreen"));
-  if (state & states::SIZEABLE)
-    stringStates->Add(NS_LITERAL_STRING("sizeable"));
-  if (state & states::MOVEABLE)
-    stringStates->Add(NS_LITERAL_STRING("moveable"));
-  if (state & states::SELFVOICING)
-    stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
-  if (state & states::FOCUSABLE)
-    stringStates->Add(NS_LITERAL_STRING("focusable"));
-  if (state & states::SELECTABLE)
-    stringStates->Add(NS_LITERAL_STRING("selectable"));
-  if (state & states::LINKED)
-    stringStates->Add(NS_LITERAL_STRING("linked"));
-  if (state & states::TRAVERSED)
-    stringStates->Add(NS_LITERAL_STRING("traversed"));
-  if (state & states::MULTISELECTABLE)
-    stringStates->Add(NS_LITERAL_STRING("multiselectable"));
-  if (state & states::EXTSELECTABLE)
-    stringStates->Add(NS_LITERAL_STRING("extselectable"));
-  if (state & states::PROTECTED)
-    stringStates->Add(NS_LITERAL_STRING("protected"));
-  if (state & states::HASPOPUP)
-    stringStates->Add(NS_LITERAL_STRING("haspopup"));
-  if (state & states::REQUIRED)
-    stringStates->Add(NS_LITERAL_STRING("required"));
-  if (state & states::ALERT)
-    stringStates->Add(NS_LITERAL_STRING("alert"));
-  if (state & states::INVALID)
-    stringStates->Add(NS_LITERAL_STRING("invalid"));
-  if (state & states::CHECKABLE)
-    stringStates->Add(NS_LITERAL_STRING("checkable"));
-
-  // extraStates
-  if (state & states::SUPPORTS_AUTOCOMPLETION)
-    stringStates->Add(NS_LITERAL_STRING("autocompletion"));
-  if (state & states::DEFUNCT)
-    stringStates->Add(NS_LITERAL_STRING("defunct"));
-  if (state & states::SELECTABLE_TEXT)
-    stringStates->Add(NS_LITERAL_STRING("selectable text"));
-  if (state & states::EDITABLE)
-    stringStates->Add(NS_LITERAL_STRING("editable"));
-  if (state & states::ACTIVE)
-    stringStates->Add(NS_LITERAL_STRING("active"));
-  if (state & states::MODAL)
-    stringStates->Add(NS_LITERAL_STRING("modal"));
-  if (state & states::MULTI_LINE)
-    stringStates->Add(NS_LITERAL_STRING("multi line"));
-  if (state & states::HORIZONTAL)
-    stringStates->Add(NS_LITERAL_STRING("horizontal"));
-  if (state & states::OPAQUE1)
-    stringStates->Add(NS_LITERAL_STRING("opaque"));
-  if (state & states::SINGLE_LINE)
-    stringStates->Add(NS_LITERAL_STRING("single line"));
-  if (state & states::TRANSIENT)
-    stringStates->Add(NS_LITERAL_STRING("transient"));
-  if (state & states::VERTICAL)
-    stringStates->Add(NS_LITERAL_STRING("vertical"));
-  if (state & states::STALE)
-    stringStates->Add(NS_LITERAL_STRING("stale"));
-  if (state & states::ENABLED)
-    stringStates->Add(NS_LITERAL_STRING("enabled"));
-  if (state & states::SENSITIVE)
-    stringStates->Add(NS_LITERAL_STRING("sensitive"));
-  if (state & states::EXPANDABLE)
-    stringStates->Add(NS_LITERAL_STRING("expandable"));
-
-  //unknown states
-  if (!stringStates->Length())
-    stringStates->Add(NS_LITERAL_STRING("unknown"));
-
-  stringStates.forget(aStringStates);
-  return NS_OK;
-}
-
-// nsIAccessibilityService::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;
-}
-
-// nsIAccessibilityService::getStringRelationType()
-NS_IMETHODIMP
-nsAccessibilityService::GetStringRelationType(uint32_t aRelationType,
-                                              nsAString& aString)
-{
-  NS_ENSURE_ARG(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
-
-#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
-  case RelationType::geckoType: \
-    aString.AssignLiteral(geckoTypeName); \
-    return NS_OK;
-
-  RelationType relationType = static_cast<RelationType>(aRelationType);
-  switch (relationType) {
-#include "RelationTypeMap.h"
-    default:
-      aString.AssignLiteral("unknown");
-      return NS_OK;
-  }
-
-#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,
@@ -1789,48 +1546,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(nsAccessibilityService** 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,
--- a/accessible/base/nsAccessibilityService.h
+++ b/accessible/base/nsAccessibilityService.h
@@ -1,22 +1,21 @@
 /* -*- 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/a11y/Statistics.h"
 #include "mozilla/Preferences.h"
 
 #include "nsIObserver.h"
 #include "nsIEventListenerService.h"
 
 class nsImageFrame;
 class nsIArray;
 class nsIPersistentProperties;
@@ -63,33 +62,31 @@ 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();
 
 public:
   NS_DECL_ISUPPORTS_INHERITED
-  NS_DECL_NSIACCESSIBILITYSERVICE
   NS_DECL_NSIOBSERVER
 
   virtual Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
                                                 bool aCanCreate);
   already_AddRefed<Accessible>
     CreatePluginAccessible(nsPluginFrame* aFrame, nsIContent* aContent,
                            Accessible* aContext);
 
@@ -97,16 +94,26 @@ public:
    * Adds/remove ATK root accessible for gtk+ native window to/from children
    * of the application accessible.
    */
   virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible);
   virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible);
 
   virtual bool HasAccessible(nsIDOMNode* aDOMNode);
 
+  /**
+   * Get a string equivalent for an accessilbe role value.
+   */
+  void GetStringRole(uint32_t aRole, nsAString& aString);
+
+  /**
+   * Get a string equivalent for an accessible event value.
+   */
+  void GetStringEventType(uint32_t aEventType, 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);
 
@@ -199,17 +206,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.
    */
@@ -255,50 +262,71 @@ private:
   /**
    * Indicates whether accessibility service was shutdown.
    */
   static bool gIsShutdown;
 
   nsDataHashtable<nsPtrHashKey<const nsIAtom>, const mozilla::a11y::MarkupMapInfo*> mMarkupMaps;
 
   friend nsAccessibilityService* GetAccService();
+  friend nsAccessibilityService* GetOrCreateAccService();
   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(nsAccessibilityService** aResult);
 };
 
 /**
  * Return the accessibility service instance. (Handy global function)
  */
 inline nsAccessibilityService*
 GetAccService()
 {
   return nsAccessibilityService::gAccessibilityService;
 }
 
 /**
+ * Return accessibility service instance; creating one if necessary.
+ */
+inline nsAccessibilityService*
+GetOrCreateAccService()
+{
+  if (nsAccessibilityService::gAccessibilityService) {
+    return nsAccessibilityService::gAccessibilityService;
+  }
+
+  RefPtr<nsAccessibilityService> service = new nsAccessibilityService();
+
+  if (!service->Init()) {
+    service->Shutdown();
+    return nullptr;
+  }
+
+  mozilla::a11y::statistics::A11yInitialized();
+  NS_ADDREF(service);
+  return service;
+}
+
+/**
  * 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
- * nsIAccessibilityService::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,9 +410,8 @@ static const char kEventTypeNames[][40] 
   "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
-
--- a/accessible/interfaces/nsIAccessibilityService.idl
+++ b/accessible/interfaces/nsIAccessibilityService.idl
@@ -93,18 +93,8 @@ interface nsIAccessibilityService : nsIS
    */
   void setLogging(in ACString aModules);
 
   /**
    * Return true if the given module is logged.
    */
   boolean isLogged(in AString aModule);
 };
-
-
-%{ C++
-
-// for component registration
-// {DE401C37-9A7F-4278-A6F8-3DE2833989EF}
-#define NS_ACCESSIBILITY_SERVICE_CID \
-{ 0xde401c37, 0x9a7f, 0x4278, { 0xa6, 0xf8, 0x3d, 0xe2, 0x83, 0x39, 0x89, 0xef } }
-
-%}
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -1,16 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; 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,356 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "xpcAccessibilityService.h"
+
+#include "mozilla/dom/DOMStringList.h"
+#include "nsAccessiblePivot.h"
+#include "nsAccessibilityService.h"
+#include "nsAccUtils.h"
+
+#ifdef A11Y_LOG
+#include "Logging.h"
+#endif
+
+using namespace mozilla;
+using namespace mozilla::a11y;
+using namespace mozilla::dom;
+
+xpcAccessibilityService *xpcAccessibilityService::accessibilityService = nullptr;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsISupports
+
+NS_IMPL_ISUPPORTS(xpcAccessibilityService, nsIAccessibilityService)
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
+{
+  NS_ENSURE_ARG_POINTER(aAccessibleApplication);
+
+  NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+xpcAccessibilityService::GetAccessibleFor(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)
+{
+  RefPtr<DOMStringList> stringStates = new DOMStringList();
+
+  uint64_t state = nsAccUtils::To64State(aState, aExtraState);
+
+  // states
+  if (state & states::UNAVAILABLE) {
+    stringStates->Add(NS_LITERAL_STRING("unavailable"));
+  }
+  if (state & states::SELECTED) {
+    stringStates->Add(NS_LITERAL_STRING("selected"));
+  }
+  if (state & states::FOCUSED) {
+    stringStates->Add(NS_LITERAL_STRING("focused"));
+  }
+  if (state & states::PRESSED) {
+    stringStates->Add(NS_LITERAL_STRING("pressed"));
+  }
+  if (state & states::CHECKED) {
+    stringStates->Add(NS_LITERAL_STRING("checked"));
+  }
+  if (state & states::MIXED) {
+    stringStates->Add(NS_LITERAL_STRING("mixed"));
+  }
+  if (state & states::READONLY) {
+    stringStates->Add(NS_LITERAL_STRING("readonly"));
+  }
+  if (state & states::HOTTRACKED) {
+    stringStates->Add(NS_LITERAL_STRING("hottracked"));
+  }
+  if (state & states::DEFAULT) {
+    stringStates->Add(NS_LITERAL_STRING("default"));
+  }
+  if (state & states::EXPANDED) {
+    stringStates->Add(NS_LITERAL_STRING("expanded"));
+  }
+  if (state & states::COLLAPSED) {
+    stringStates->Add(NS_LITERAL_STRING("collapsed"));
+  }
+  if (state & states::BUSY) {
+    stringStates->Add(NS_LITERAL_STRING("busy"));
+  }
+  if (state & states::FLOATING) {
+    stringStates->Add(NS_LITERAL_STRING("floating"));
+  }
+  if (state & states::ANIMATED) {
+    stringStates->Add(NS_LITERAL_STRING("animated"));
+  }
+  if (state & states::INVISIBLE) {
+    stringStates->Add(NS_LITERAL_STRING("invisible"));
+  }
+  if (state & states::OFFSCREEN) {
+    stringStates->Add(NS_LITERAL_STRING("offscreen"));
+  }
+  if (state & states::SIZEABLE) {
+    stringStates->Add(NS_LITERAL_STRING("sizeable"));
+  }
+  if (state & states::MOVEABLE) {
+    stringStates->Add(NS_LITERAL_STRING("moveable"));
+  }
+  if (state & states::SELFVOICING) {
+    stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
+  }
+  if (state & states::FOCUSABLE) {
+    stringStates->Add(NS_LITERAL_STRING("focusable"));
+  }
+  if (state & states::SELECTABLE) {
+    stringStates->Add(NS_LITERAL_STRING("selectable"));
+  }
+  if (state & states::LINKED) {
+    stringStates->Add(NS_LITERAL_STRING("linked"));
+  }
+  if (state & states::TRAVERSED) {
+    stringStates->Add(NS_LITERAL_STRING("traversed"));
+  }
+  if (state & states::MULTISELECTABLE) {
+    stringStates->Add(NS_LITERAL_STRING("multiselectable"));
+  }
+  if (state & states::EXTSELECTABLE) {
+    stringStates->Add(NS_LITERAL_STRING("extselectable"));
+  }
+  if (state & states::PROTECTED) {
+    stringStates->Add(NS_LITERAL_STRING("protected"));
+  }
+  if (state & states::HASPOPUP) {
+    stringStates->Add(NS_LITERAL_STRING("haspopup"));
+  }
+  if (state & states::REQUIRED) {
+    stringStates->Add(NS_LITERAL_STRING("required"));
+  }
+  if (state & states::ALERT) {
+    stringStates->Add(NS_LITERAL_STRING("alert"));
+  }
+  if (state & states::INVALID) {
+    stringStates->Add(NS_LITERAL_STRING("invalid"));
+  }
+  if (state & states::CHECKABLE) {
+    stringStates->Add(NS_LITERAL_STRING("checkable"));
+  }
+
+  // extraStates
+  if (state & states::SUPPORTS_AUTOCOMPLETION) {
+    stringStates->Add(NS_LITERAL_STRING("autocompletion"));
+  }
+  if (state & states::DEFUNCT) {
+    stringStates->Add(NS_LITERAL_STRING("defunct"));
+  }
+  if (state & states::SELECTABLE_TEXT) {
+    stringStates->Add(NS_LITERAL_STRING("selectable text"));
+  }
+  if (state & states::EDITABLE) {
+    stringStates->Add(NS_LITERAL_STRING("editable"));
+  }
+  if (state & states::ACTIVE) {
+    stringStates->Add(NS_LITERAL_STRING("active"));
+  }
+  if (state & states::MODAL) {
+    stringStates->Add(NS_LITERAL_STRING("modal"));
+  }
+  if (state & states::MULTI_LINE) {
+    stringStates->Add(NS_LITERAL_STRING("multi line"));
+  }
+  if (state & states::HORIZONTAL) {
+    stringStates->Add(NS_LITERAL_STRING("horizontal"));
+  }
+  if (state & states::OPAQUE1) {
+    stringStates->Add(NS_LITERAL_STRING("opaque"));
+  }
+  if (state & states::SINGLE_LINE) {
+    stringStates->Add(NS_LITERAL_STRING("single line"));
+  }
+  if (state & states::TRANSIENT) {
+    stringStates->Add(NS_LITERAL_STRING("transient"));
+  }
+  if (state & states::VERTICAL) {
+    stringStates->Add(NS_LITERAL_STRING("vertical"));
+  }
+  if (state & states::STALE) {
+    stringStates->Add(NS_LITERAL_STRING("stale"));
+  }
+  if (state & states::ENABLED) {
+    stringStates->Add(NS_LITERAL_STRING("enabled"));
+  }
+  if (state & states::SENSITIVE) {
+    stringStates->Add(NS_LITERAL_STRING("sensitive"));
+  }
+  if (state & states::EXPANDABLE) {
+    stringStates->Add(NS_LITERAL_STRING("expandable"));
+  }
+
+  //unknown states
+  if (!stringStates->Length()) {
+    stringStates->Add(NS_LITERAL_STRING("unknown"));
+  }
+
+  stringStates.forget(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)
+{
+  NS_ENSURE_ARG(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
+
+#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
+  case RelationType::geckoType: \
+    aString.AssignLiteral(geckoTypeName); \
+    return NS_OK;
+
+  RelationType relationType = static_cast<RelationType>(aRelationType);
+  switch (relationType) {
+#include "RelationTypeMap.h"
+    default:
+      aString.AssignLiteral("unknown");
+      return NS_OK;
+  }
+
+#undef RELATIONTYPE
+}
+
+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;
+
+  if (xpcAccessibilityService::accessibilityService) {
+    NS_ADDREF(*aResult = xpcAccessibilityService::accessibilityService);
+
+    return NS_OK;
+  }
+
+  if (!GetAccService()) {
+    nsAccessibilityService* accService = GetOrCreateAccService();
+  }
+
+  RefPtr<xpcAccessibilityService> service = new xpcAccessibilityService();
+  NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
+  xpcAccessibilityService::accessibilityService = service;
+  NS_ADDREF(*aResult = service);
+
+  return NS_OK;
+}
new file mode 100644
--- /dev/null
+++ b/accessible/xpcom/xpcAccessibilityService.h
@@ -0,0 +1,41 @@
+/* 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 nsIAccessibilityService
+{
+
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIACCESSIBILITYSERVICE
+
+protected:
+  virtual ~xpcAccessibilityService() {}
+
+private:
+  // xpcAccessibilityService creation is controlled by friend
+  // NS_GetAccessibilityService, keep constructor private.
+  xpcAccessibilityService() {};
+
+  /**
+   * Reference for xpc accessibility service instance.
+   */
+  static xpcAccessibilityService* accessibilityService;
+
+  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
@@ -2569,17 +2569,17 @@ ContentChild::RecvFlushMemory(const nsSt
 }
 
 bool
 ContentChild::RecvActivateA11y()
 {
 #ifdef ACCESSIBILITY
   // Start accessibility in content process if it's running in chrome
   // process.
-  nsAccessibilityService* accService = GetAccService();
+  nsAccessibilityService* accService = 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
@@ -672,19 +672,19 @@ 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, nsAccessibilityService, NS_GetAccessibilityService)
+  MAKE_CTOR(CreateA11yService, nsIAccessibilityService, NS_GetAccessibilityService)
 #endif
 
 static nsresult
 Construct_nsIScriptSecurityManager(nsISupports *aOuter, REFNSIID aIID,
                                    void **aResult)
 {
     if (!aResult)
         return NS_ERROR_NULL_POINTER;
--- a/layout/inspector/inDOMView.cpp
+++ b/layout/inspector/inDOMView.cpp
@@ -324,17 +324,17 @@ inDOMView::GetCellProperties(int32_t row
       break;
     case nsIDOMNode::NOTATION_NODE:
       aProps.AppendLiteral("NOTATION_NODE");
       break;
   }
 
 #ifdef ACCESSIBILITY
   if (mShowAccessibleNodes) {
-	  nsAccessibilityService* accService = GetAccService();
+	  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
@@ -6285,17 +6285,17 @@ nsWindow::CreateRootAccessible()
 
 void
 nsWindow::DispatchEventToRootAccessible(uint32_t aEventType)
 {
     if (!a11y::ShouldA11yBeEnabled()) {
         return;
     }
 
-    nsAccessibilityService* accService = GetAccService();
+    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
@@ -1896,17 +1896,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.
-  nsAccessibilityService* accService = GetAccService();
+  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
@@ -6964,17 +6964,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)) {
-      nsAccessibilityService* accService = GetAccService();
+      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());
         }