tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

xpcAccessibilityService.cpp (9124B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 #include "xpcAccessibilityService.h"
      6 
      7 #include "mozilla/dom/Document.h"
      8 
      9 #include "xpcAccessiblePivot.h"
     10 #include "nsAccessibilityService.h"
     11 #include "xpcAccessibleApplication.h"
     12 #include "xpcAccessibleDocument.h"
     13 #include "xpcAccessibleTextLeafRange.h"
     14 
     15 #ifdef A11Y_LOG
     16 #  include "Logging.h"
     17 #endif
     18 
     19 using namespace mozilla;
     20 using namespace mozilla::a11y;
     21 using namespace mozilla::dom;
     22 
     23 xpcAccessibilityService* xpcAccessibilityService::gXPCAccessibilityService =
     24    nullptr;
     25 
     26 ////////////////////////////////////////////////////////////////////////////////
     27 // nsISupports
     28 
     29 void xpcAccessibilityService::ShutdownCallback(nsITimer* aTimer,
     30                                               void* aClosure) {
     31  MaybeShutdownAccService(nsAccessibilityService::eXPCOM);
     32  xpcAccessibilityService* xpcAccService =
     33      reinterpret_cast<xpcAccessibilityService*>(aClosure);
     34 
     35  if (xpcAccService->mShutdownTimer) {
     36    xpcAccService->mShutdownTimer->Cancel();
     37    xpcAccService->mShutdownTimer = nullptr;
     38  }
     39 }
     40 
     41 NS_IMETHODIMP_(MozExternalRefCountType)
     42 xpcAccessibilityService::AddRef(void) {
     43  MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(xpcAccessibilityService)
     44  MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt");
     45  if (!nsAutoRefCnt::isThreadSafe) {
     46    NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
     47  }
     48  nsrefcnt count = ++mRefCnt;
     49  NS_LOG_ADDREF(this, count, "xpcAccessibilityService", sizeof(*this));
     50 
     51  // We want refcount to be > 1 because one reference is added in the XPCOM
     52  // accessibility service getter.
     53  if (mRefCnt > 1) {
     54    if (mShutdownTimer) {
     55      mShutdownTimer->Cancel();
     56      mShutdownTimer = nullptr;
     57    }
     58 
     59    GetOrCreateAccService(nsAccessibilityService::eXPCOM);
     60  }
     61 
     62  return count;
     63 }
     64 
     65 NS_IMETHODIMP_(MozExternalRefCountType)
     66 xpcAccessibilityService::Release(void) {
     67  MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release");
     68 
     69  if (!nsAutoRefCnt::isThreadSafe) {
     70    NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
     71  }
     72 
     73  nsrefcnt count = --mRefCnt;
     74  NS_LOG_RELEASE(this, count, "xpcAccessibilityService");
     75 
     76  if (count == 0) {
     77    if (!nsAutoRefCnt::isThreadSafe) {
     78      NS_ASSERT_OWNINGTHREAD(xpcAccessibilityService);
     79    }
     80 
     81    mRefCnt = 1; /* stabilize */
     82    delete (this);
     83    return 0;
     84  }
     85 
     86  // When ref count goes down to 1 (held internally as a static reference),
     87  // it means that there are no more external references to the
     88  // xpcAccessibilityService and we can attempt to shut down acceessiblity
     89  // service.
     90  if (count == 1 && !mShutdownTimer) {
     91    NS_NewTimerWithFuncCallback(
     92        getter_AddRefs(mShutdownTimer), ShutdownCallback, this, 100,
     93        nsITimer::TYPE_ONE_SHOT, "xpcAccessibilityService::Release"_ns);
     94  }
     95 
     96  return count;
     97 }
     98 
     99 NS_IMPL_QUERY_INTERFACE(xpcAccessibilityService, nsIAccessibilityService)
    100 
    101 NS_IMETHODIMP
    102 xpcAccessibilityService::GetApplicationAccessible(
    103    nsIAccessible** aAccessibleApplication) {
    104  NS_ENSURE_ARG_POINTER(aAccessibleApplication);
    105 
    106  NS_IF_ADDREF(*aAccessibleApplication = XPCApplicationAcc());
    107  return NS_OK;
    108 }
    109 
    110 NS_IMETHODIMP
    111 xpcAccessibilityService::GetAccessibleFor(nsINode* aNode,
    112                                          nsIAccessible** aAccessible) {
    113  NS_ENSURE_ARG_POINTER(aAccessible);
    114  *aAccessible = nullptr;
    115  if (!aNode) {
    116    return NS_OK;
    117  }
    118 
    119  nsAccessibilityService* accService = GetAccService();
    120  if (!accService) {
    121    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    122  }
    123 
    124  DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
    125  if (document) {
    126    NS_IF_ADDREF(*aAccessible =
    127                     ToXPC(document->GetAccessibleEvenIfNotInMap(aNode)));
    128  }
    129 
    130  return NS_OK;
    131 }
    132 
    133 NS_IMETHODIMP
    134 xpcAccessibilityService::GetAccessibleDescendantFor(
    135    nsINode* aNode, nsIAccessible** aAccessible) {
    136  NS_ENSURE_ARG_POINTER(aAccessible);
    137  *aAccessible = nullptr;
    138  if (!aNode) {
    139    return NS_OK;
    140  }
    141 
    142  nsAccessibilityService* accService = GetAccService();
    143  if (!accService) {
    144    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    145  }
    146 
    147  DocAccessible* document = accService->GetDocAccessible(aNode->OwnerDoc());
    148  if (document) {
    149    NS_IF_ADDREF(*aAccessible =
    150                     ToXPC(document->GetAccessibleOrDescendant(aNode)));
    151  }
    152 
    153  return NS_OK;
    154 }
    155 
    156 NS_IMETHODIMP
    157 xpcAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString) {
    158  nsAccessibilityService* accService = GetAccService();
    159  if (!accService) {
    160    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    161  }
    162 
    163  accService->GetStringRole(aRole, aString);
    164  return NS_OK;
    165 }
    166 
    167 NS_IMETHODIMP
    168 xpcAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
    169                                         nsISupports** aStringStates) {
    170  nsAccessibilityService* accService = GetAccService();
    171  if (!accService) {
    172    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    173  }
    174 
    175  accService->GetStringStates(aState, aExtraState, aStringStates);
    176  return NS_OK;
    177 }
    178 
    179 NS_IMETHODIMP
    180 xpcAccessibilityService::GetStringEventType(uint32_t aEventType,
    181                                            nsAString& aString) {
    182  nsAccessibilityService* accService = GetAccService();
    183  if (!accService) {
    184    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    185  }
    186 
    187  accService->GetStringEventType(aEventType, aString);
    188  return NS_OK;
    189 }
    190 
    191 NS_IMETHODIMP
    192 xpcAccessibilityService::GetStringRelationType(uint32_t aRelationType,
    193                                               nsAString& aString) {
    194  nsAccessibilityService* accService = GetAccService();
    195  if (!accService) {
    196    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    197  }
    198 
    199  accService->GetStringRelationType(aRelationType, aString);
    200  return NS_OK;
    201 }
    202 
    203 NS_IMETHODIMP
    204 xpcAccessibilityService::GetAccessibleFromCache(nsINode* aNode,
    205                                                nsIAccessible** aAccessible) {
    206  NS_ENSURE_ARG_POINTER(aAccessible);
    207  *aAccessible = nullptr;
    208  if (!aNode) {
    209    return NS_OK;
    210  }
    211 
    212  nsAccessibilityService* accService = GetAccService();
    213  if (!accService) {
    214    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    215  }
    216 
    217  // Search for an accessible in each of our per document accessible object
    218  // caches. If we don't find it, and the given node is itself a document, check
    219  // our cache of document accessibles (document cache). Note usually shutdown
    220  // document accessibles are not stored in the document cache, however an
    221  // "unofficially" shutdown document (i.e. not from DocManager) can still
    222  // exist in the document cache.
    223  LocalAccessible* accessible = accService->FindAccessibleInCache(aNode);
    224  if (!accessible && aNode->IsDocument()) {
    225    accessible = mozilla::a11y::GetExistingDocAccessible(aNode->AsDocument());
    226  }
    227 
    228  NS_IF_ADDREF(*aAccessible = ToXPC(accessible));
    229  return NS_OK;
    230 }
    231 
    232 NS_IMETHODIMP
    233 xpcAccessibilityService::SetCacheDomains(uint64_t aCacheDomains) {
    234  nsAccessibilityService* accService = GetAccService();
    235  if (!accService) {
    236    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    237  }
    238 
    239  accService->SetCacheDomains(aCacheDomains);
    240  return NS_OK;
    241 }
    242 
    243 NS_IMETHODIMP
    244 xpcAccessibilityService::CreateAccessiblePivot(nsIAccessible* aRoot,
    245                                               nsIAccessiblePivot** aPivot) {
    246  NS_ENSURE_ARG_POINTER(aPivot);
    247  NS_ENSURE_ARG(aRoot);
    248  *aPivot = nullptr;
    249 
    250  xpcAccessiblePivot* pivot = new xpcAccessiblePivot(aRoot);
    251  NS_ADDREF(*aPivot = pivot);
    252 
    253  return NS_OK;
    254 }
    255 
    256 NS_IMETHODIMP
    257 xpcAccessibilityService::CreateTextLeafPoint(
    258    nsIAccessible* aAccessible, int32_t aOffset,
    259    nsIAccessibleTextLeafPoint** aPoint) {
    260  NS_ENSURE_ARG_POINTER(aPoint);
    261  NS_ENSURE_ARG(aAccessible);
    262  *aPoint = nullptr;
    263 
    264  RefPtr<xpcAccessibleTextLeafPoint> point =
    265      new xpcAccessibleTextLeafPoint(aAccessible, aOffset);
    266  point.forget(aPoint);
    267 
    268  return NS_OK;
    269 }
    270 
    271 NS_IMETHODIMP
    272 xpcAccessibilityService::SetLogging(const nsACString& aModules) {
    273 #ifdef A11Y_LOG
    274  logging::Enable(PromiseFlatCString(aModules));
    275 #endif
    276  return NS_OK;
    277 }
    278 
    279 NS_IMETHODIMP
    280 xpcAccessibilityService::IsLogged(const nsAString& aModule, bool* aIsLogged) {
    281  NS_ENSURE_ARG_POINTER(aIsLogged);
    282  *aIsLogged = false;
    283 
    284 #ifdef A11Y_LOG
    285  *aIsLogged = logging::IsEnabled(aModule);
    286 #endif
    287 
    288  return NS_OK;
    289 }
    290 
    291 NS_IMETHODIMP
    292 xpcAccessibilityService::GetConsumers(nsAString& aString) {
    293  nsAccessibilityService* accService = GetAccService();
    294  if (!accService) {
    295    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    296  }
    297 
    298  accService->GetConsumers(aString);
    299  return NS_OK;
    300 }
    301 
    302 ////////////////////////////////////////////////////////////////////////////////
    303 // NS_GetAccessibilityService
    304 ////////////////////////////////////////////////////////////////////////////////
    305 
    306 nsresult NS_GetAccessibilityService(nsIAccessibilityService** aResult) {
    307  NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
    308  *aResult = nullptr;
    309 
    310  if (!GetOrCreateAccService(nsAccessibilityService::eXPCOM)) {
    311    return NS_ERROR_SERVICE_NOT_AVAILABLE;
    312  }
    313 
    314  xpcAccessibilityService* service = new xpcAccessibilityService();
    315  xpcAccessibilityService::gXPCAccessibilityService = service;
    316  NS_ADDREF(*aResult = service);
    317 
    318  return NS_OK;
    319 }