accessible/src/base/nsAccessibilityService.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/accessible/src/base/nsAccessibilityService.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1751 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "nsAccessibilityService.h"
    1.10 +
    1.11 +// NOTE: alphabetically ordered
    1.12 +#include "ApplicationAccessibleWrap.h"
    1.13 +#include "ARIAGridAccessibleWrap.h"
    1.14 +#include "ARIAMap.h"
    1.15 +#include "DocAccessible-inl.h"
    1.16 +#include "FocusManager.h"
    1.17 +#include "HTMLCanvasAccessible.h"
    1.18 +#include "HTMLElementAccessibles.h"
    1.19 +#include "HTMLImageMapAccessible.h"
    1.20 +#include "HTMLLinkAccessible.h"
    1.21 +#include "HTMLListAccessible.h"
    1.22 +#include "HTMLSelectAccessible.h"
    1.23 +#include "HTMLTableAccessibleWrap.h"
    1.24 +#include "HyperTextAccessibleWrap.h"
    1.25 +#include "RootAccessible.h"
    1.26 +#include "nsAccessiblePivot.h"
    1.27 +#include "nsAccUtils.h"
    1.28 +#include "nsAttrName.h"
    1.29 +#include "nsEventShell.h"
    1.30 +#include "nsIURI.h"
    1.31 +#include "OuterDocAccessible.h"
    1.32 +#include "Platform.h"
    1.33 +#include "Role.h"
    1.34 +#ifdef MOZ_ACCESSIBILITY_ATK
    1.35 +#include "RootAccessibleWrap.h"
    1.36 +#endif
    1.37 +#include "States.h"
    1.38 +#include "Statistics.h"
    1.39 +#include "TextLeafAccessibleWrap.h"
    1.40 +
    1.41 +#ifdef MOZ_ACCESSIBILITY_ATK
    1.42 +#include "AtkSocketAccessible.h"
    1.43 +#endif
    1.44 +
    1.45 +#ifdef XP_WIN
    1.46 +#include "mozilla/a11y/Compatibility.h"
    1.47 +#include "HTMLWin32ObjectAccessible.h"
    1.48 +#include "mozilla/StaticPtr.h"
    1.49 +#endif
    1.50 +
    1.51 +#ifdef A11Y_LOG
    1.52 +#include "Logging.h"
    1.53 +#endif
    1.54 +
    1.55 +#ifdef MOZ_CRASHREPORTER
    1.56 +#include "nsExceptionHandler.h"
    1.57 +#endif
    1.58 +
    1.59 +#include "nsImageFrame.h"
    1.60 +#include "nsIObserverService.h"
    1.61 +#include "nsLayoutUtils.h"
    1.62 +#include "nsObjectFrame.h"
    1.63 +#include "nsSVGPathGeometryFrame.h"
    1.64 +#include "nsTreeBodyFrame.h"
    1.65 +#include "nsTreeColumns.h"
    1.66 +#include "nsTreeUtils.h"
    1.67 +#include "nsXBLPrototypeBinding.h"
    1.68 +#include "nsXBLBinding.h"
    1.69 +#include "mozilla/ArrayUtils.h"
    1.70 +#include "mozilla/dom/DOMStringList.h"
    1.71 +#include "mozilla/Preferences.h"
    1.72 +#include "mozilla/Services.h"
    1.73 +#include "nsDeckFrame.h"
    1.74 +
    1.75 +#ifdef MOZ_XUL
    1.76 +#include "XULAlertAccessible.h"
    1.77 +#include "XULColorPickerAccessible.h"
    1.78 +#include "XULComboboxAccessible.h"
    1.79 +#include "XULElementAccessibles.h"
    1.80 +#include "XULFormControlAccessible.h"
    1.81 +#include "XULListboxAccessibleWrap.h"
    1.82 +#include "XULMenuAccessibleWrap.h"
    1.83 +#include "XULSliderAccessible.h"
    1.84 +#include "XULTabAccessible.h"
    1.85 +#include "XULTreeGridAccessibleWrap.h"
    1.86 +#endif
    1.87 +
    1.88 +#if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
    1.89 +#include "nsNPAPIPluginInstance.h"
    1.90 +#endif
    1.91 +
    1.92 +using namespace mozilla;
    1.93 +using namespace mozilla::a11y;
    1.94 +using namespace mozilla::dom;
    1.95 +
    1.96 +////////////////////////////////////////////////////////////////////////////////
    1.97 +// Statics
    1.98 +////////////////////////////////////////////////////////////////////////////////
    1.99 +
   1.100 +/**
   1.101 + * Return true if the element must be accessible.
   1.102 + */
   1.103 +static bool
   1.104 +MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument)
   1.105 +{
   1.106 +  if (aContent->GetPrimaryFrame()->IsFocusable())
   1.107 +    return true;
   1.108 +
   1.109 +  uint32_t attrCount = aContent->GetAttrCount();
   1.110 +  for (uint32_t attrIdx = 0; attrIdx < attrCount; attrIdx++) {
   1.111 +    const nsAttrName* attr = aContent->GetAttrNameAt(attrIdx);
   1.112 +    if (attr->NamespaceEquals(kNameSpaceID_None)) {
   1.113 +      nsIAtom* attrAtom = attr->Atom();
   1.114 +      nsDependentAtomString attrStr(attrAtom);
   1.115 +      if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
   1.116 +        continue; // not ARIA
   1.117 +
   1.118 +      // A global state or a property and in case of token defined.
   1.119 +      uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom);
   1.120 +      if ((attrFlags & ATTR_GLOBAL) && (!(attrFlags & ATTR_VALTOKEN) ||
   1.121 +           nsAccUtils::HasDefinedARIAToken(aContent, attrAtom))) {
   1.122 +        return true;
   1.123 +      }
   1.124 +    }
   1.125 +  }
   1.126 +
   1.127 +  // If the given ID is referred by relation attribute then create an accessible
   1.128 +  // for it.
   1.129 +  nsAutoString id;
   1.130 +  if (nsCoreUtils::GetID(aContent, id) && !id.IsEmpty())
   1.131 +    return aDocument->IsDependentID(id);
   1.132 +
   1.133 +  return false;
   1.134 +}
   1.135 +
   1.136 +////////////////////////////////////////////////////////////////////////////////
   1.137 +// nsAccessibilityService
   1.138 +////////////////////////////////////////////////////////////////////////////////
   1.139 +
   1.140 +nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nullptr;
   1.141 +ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
   1.142 +bool nsAccessibilityService::gIsShutdown = true;
   1.143 +
   1.144 +nsAccessibilityService::nsAccessibilityService() :
   1.145 +  DocManager(), FocusManager()
   1.146 +{
   1.147 +}
   1.148 +
   1.149 +nsAccessibilityService::~nsAccessibilityService()
   1.150 +{
   1.151 +  NS_ASSERTION(gIsShutdown, "Accessibility wasn't shutdown!");
   1.152 +  gAccessibilityService = nullptr;
   1.153 +}
   1.154 +
   1.155 +////////////////////////////////////////////////////////////////////////////////
   1.156 +// nsISupports
   1.157 +
   1.158 +NS_IMPL_ISUPPORTS_INHERITED(nsAccessibilityService,
   1.159 +                            DocManager,
   1.160 +                            nsIAccessibilityService,
   1.161 +                            nsIAccessibleRetrieval,
   1.162 +                            nsIObserver,
   1.163 +                            nsISelectionListener) // from SelectionManager
   1.164 +
   1.165 +////////////////////////////////////////////////////////////////////////////////
   1.166 +// nsIObserver
   1.167 +
   1.168 +NS_IMETHODIMP
   1.169 +nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
   1.170 +                         const char16_t *aData)
   1.171 +{
   1.172 +  if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
   1.173 +    Shutdown();
   1.174 +
   1.175 +  return NS_OK;
   1.176 +}
   1.177 +
   1.178 +// nsIAccessibilityService
   1.179 +void
   1.180 +nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent* aTargetNode)
   1.181 +{
   1.182 +  nsIDocument* documentNode = aTargetNode->GetCurrentDoc();
   1.183 +  if (documentNode) {
   1.184 +    DocAccessible* document = GetDocAccessible(documentNode);
   1.185 +    if (document)
   1.186 +      document->SetAnchorJump(aTargetNode);
   1.187 +  }
   1.188 +}
   1.189 +
   1.190 +// nsIAccessibilityService
   1.191 +void
   1.192 +nsAccessibilityService::FireAccessibleEvent(uint32_t aEvent,
   1.193 +                                            Accessible* aTarget)
   1.194 +{
   1.195 +  nsEventShell::FireEvent(aEvent, aTarget);
   1.196 +}
   1.197 +
   1.198 +////////////////////////////////////////////////////////////////////////////////
   1.199 +// nsIAccessibilityService
   1.200 +
   1.201 +Accessible*
   1.202 +nsAccessibilityService::GetRootDocumentAccessible(nsIPresShell* aPresShell,
   1.203 +                                                  bool aCanCreate)
   1.204 +{
   1.205 +  nsIPresShell* ps = aPresShell;
   1.206 +  nsIDocument* documentNode = aPresShell->GetDocument();
   1.207 +  if (documentNode) {
   1.208 +    nsCOMPtr<nsIDocShellTreeItem> treeItem(documentNode->GetDocShell());
   1.209 +    if (treeItem) {
   1.210 +      nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
   1.211 +      treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
   1.212 +      if (treeItem != rootTreeItem) {
   1.213 +        nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(rootTreeItem));
   1.214 +        ps = docShell->GetPresShell();
   1.215 +      }
   1.216 +
   1.217 +      return aCanCreate ? GetDocAccessible(ps) : ps->GetDocAccessible();
   1.218 +    }
   1.219 +  }
   1.220 +  return nullptr;
   1.221 +}
   1.222 +
   1.223 +#ifdef XP_WIN
   1.224 +static StaticAutoPtr<nsTArray<nsCOMPtr<nsIContent> > > sPendingPlugins;
   1.225 +static StaticAutoPtr<nsTArray<nsCOMPtr<nsITimer> > > sPluginTimers;
   1.226 +
   1.227 +class PluginTimerCallBack MOZ_FINAL : public nsITimerCallback
   1.228 +{
   1.229 +public:
   1.230 +  PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
   1.231 +
   1.232 +  NS_DECL_ISUPPORTS
   1.233 +
   1.234 +  NS_IMETHODIMP Notify(nsITimer* aTimer) MOZ_FINAL
   1.235 +  {
   1.236 +    if (!mContent->IsInDoc())
   1.237 +      return NS_OK;
   1.238 +
   1.239 +    nsIPresShell* ps = mContent->OwnerDoc()->GetShell();
   1.240 +    if (ps) {
   1.241 +      DocAccessible* doc = ps->GetDocAccessible();
   1.242 +      if (doc) {
   1.243 +        // Make sure that if we created an accessible for the plugin that wasn't
   1.244 +        // a plugin accessible we remove it before creating the right accessible.
   1.245 +        doc->RecreateAccessible(mContent);
   1.246 +        sPluginTimers->RemoveElement(aTimer);
   1.247 +        return NS_OK;
   1.248 +      }
   1.249 +    }
   1.250 +
   1.251 +    // We couldn't get a doc accessible so presumably the document went away.
   1.252 +    // In this case don't leak our ref to the content or timer.
   1.253 +    sPendingPlugins->RemoveElement(mContent);
   1.254 +    sPluginTimers->RemoveElement(aTimer);
   1.255 +    return NS_OK;
   1.256 +  }
   1.257 +
   1.258 +private:
   1.259 +  nsCOMPtr<nsIContent> mContent;
   1.260 +};
   1.261 +
   1.262 +NS_IMPL_ISUPPORTS(PluginTimerCallBack, nsITimerCallback)
   1.263 +#endif
   1.264 +
   1.265 +already_AddRefed<Accessible>
   1.266 +nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
   1.267 +                                               nsIContent* aContent,
   1.268 +                                               Accessible* aContext)
   1.269 +{
   1.270 +  // nsObjectFrame means a plugin, so we need to use the accessibility support
   1.271 +  // of the plugin.
   1.272 +  if (aFrame->GetRect().IsEmpty())
   1.273 +    return nullptr;
   1.274 +
   1.275 +#if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
   1.276 +  nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
   1.277 +  if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
   1.278 +      pluginInstance) {
   1.279 +#ifdef XP_WIN
   1.280 +    if (!sPendingPlugins->Contains(aContent) &&
   1.281 +        (Preferences::GetBool("accessibility.delay_plugins") ||
   1.282 +         Compatibility::IsJAWS() || Compatibility::IsWE())) {
   1.283 +      nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
   1.284 +      nsRefPtr<PluginTimerCallBack> cb = new PluginTimerCallBack(aContent);
   1.285 +      timer->InitWithCallback(cb, Preferences::GetUint("accessibility.delay_plugin_time"),
   1.286 +                              nsITimer::TYPE_ONE_SHOT);
   1.287 +      sPluginTimers->AppendElement(timer);
   1.288 +      sPendingPlugins->AppendElement(aContent);
   1.289 +      return nullptr;
   1.290 +    }
   1.291 +
   1.292 +    // We need to remove aContent from the pending plugins here to avoid
   1.293 +    // reentrancy.  When the timer fires it calls
   1.294 +    // DocAccessible::ContentInserted() which does the work async.
   1.295 +    sPendingPlugins->RemoveElement(aContent);
   1.296 +
   1.297 +    // Note: pluginPort will be null if windowless.
   1.298 +    HWND pluginPort = nullptr;
   1.299 +    aFrame->GetPluginPort(&pluginPort);
   1.300 +
   1.301 +    nsRefPtr<Accessible> accessible =
   1.302 +      new HTMLWin32ObjectOwnerAccessible(aContent, aContext->Document(),
   1.303 +                                         pluginPort);
   1.304 +    return accessible.forget();
   1.305 +
   1.306 +#elif MOZ_ACCESSIBILITY_ATK
   1.307 +    if (!AtkSocketAccessible::gCanEmbed)
   1.308 +      return nullptr;
   1.309 +
   1.310 +    // Note this calls into the plugin, so crazy things may happen and aFrame
   1.311 +    // may go away.
   1.312 +    nsCString plugId;
   1.313 +    nsresult rv = pluginInstance->GetValueFromPlugin(
   1.314 +      NPPVpluginNativeAccessibleAtkPlugId, &plugId);
   1.315 +    if (NS_SUCCEEDED(rv) && !plugId.IsEmpty()) {
   1.316 +      nsRefPtr<AtkSocketAccessible> socketAccessible =
   1.317 +        new AtkSocketAccessible(aContent, aContext->Document(), plugId);
   1.318 +
   1.319 +      return socketAccessible.forget();
   1.320 +    }
   1.321 +#endif
   1.322 +  }
   1.323 +#endif
   1.324 +
   1.325 +  return nullptr;
   1.326 +}
   1.327 +
   1.328 +void
   1.329 +nsAccessibilityService::DeckPanelSwitched(nsIPresShell* aPresShell,
   1.330 +                                          nsIContent* aDeckNode,
   1.331 +                                          nsIFrame* aPrevBoxFrame,
   1.332 +                                          nsIFrame* aCurrentBoxFrame)
   1.333 +{
   1.334 +  // Ignore tabpanels elements (a deck having an accessible) since their
   1.335 +  // children are accessible not depending on selected tab.
   1.336 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.337 +  if (!document || document->HasAccessible(aDeckNode))
   1.338 +    return;
   1.339 +
   1.340 +  if (aPrevBoxFrame) {
   1.341 +    nsIContent* panelNode = aPrevBoxFrame->GetContent();
   1.342 +#ifdef A11Y_LOG
   1.343 +    if (logging::IsEnabled(logging::eTree)) {
   1.344 +      logging::MsgBegin("TREE", "deck panel unselected");
   1.345 +      logging::Node("container", panelNode);
   1.346 +      logging::Node("content", aDeckNode);
   1.347 +      logging::MsgEnd();
   1.348 +    }
   1.349 +#endif
   1.350 +
   1.351 +    document->ContentRemoved(aDeckNode, panelNode);
   1.352 +  }
   1.353 +
   1.354 +  if (aCurrentBoxFrame) {
   1.355 +    nsIContent* panelNode = aCurrentBoxFrame->GetContent();
   1.356 +#ifdef A11Y_LOG
   1.357 +    if (logging::IsEnabled(logging::eTree)) {
   1.358 +      logging::MsgBegin("TREE", "deck panel selected");
   1.359 +      logging::Node("container", panelNode);
   1.360 +      logging::Node("content", aDeckNode);
   1.361 +      logging::MsgEnd();
   1.362 +    }
   1.363 +#endif
   1.364 +
   1.365 +    document->ContentInserted(aDeckNode, panelNode, panelNode->GetNextSibling());
   1.366 +  }
   1.367 +}
   1.368 +
   1.369 +void
   1.370 +nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
   1.371 +                                             nsIContent* aContainer,
   1.372 +                                             nsIContent* aStartChild,
   1.373 +                                             nsIContent* aEndChild)
   1.374 +{
   1.375 +#ifdef A11Y_LOG
   1.376 +  if (logging::IsEnabled(logging::eTree)) {
   1.377 +    logging::MsgBegin("TREE", "content inserted");
   1.378 +    logging::Node("container", aContainer);
   1.379 +    for (nsIContent* child = aStartChild; child != aEndChild;
   1.380 +         child = child->GetNextSibling()) {
   1.381 +      logging::Node("content", child);
   1.382 +    }
   1.383 +    logging::MsgEnd();
   1.384 +    logging::Stack();
   1.385 +  }
   1.386 +#endif
   1.387 +
   1.388 +  DocAccessible* docAccessible = GetDocAccessible(aPresShell);
   1.389 +  if (docAccessible)
   1.390 +    docAccessible->ContentInserted(aContainer, aStartChild, aEndChild);
   1.391 +}
   1.392 +
   1.393 +void
   1.394 +nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
   1.395 +                                       nsIContent* aContainer,
   1.396 +                                       nsIContent* aChild)
   1.397 +{
   1.398 +#ifdef A11Y_LOG
   1.399 +  if (logging::IsEnabled(logging::eTree)) {
   1.400 +    logging::MsgBegin("TREE", "content removed");
   1.401 +    logging::Node("container", aContainer);
   1.402 +    logging::Node("content", aChild);
   1.403 +    logging::MsgEnd();
   1.404 +    logging::Stack();
   1.405 +  }
   1.406 +#endif
   1.407 +
   1.408 +  DocAccessible* docAccessible = GetDocAccessible(aPresShell);
   1.409 +  if (docAccessible)
   1.410 +    docAccessible->ContentRemoved(aContainer, aChild);
   1.411 +}
   1.412 +
   1.413 +void
   1.414 +nsAccessibilityService::UpdateText(nsIPresShell* aPresShell,
   1.415 +                                   nsIContent* aContent)
   1.416 +{
   1.417 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.418 +  if (document)
   1.419 +    document->UpdateText(aContent);
   1.420 +}
   1.421 +
   1.422 +void
   1.423 +nsAccessibilityService::TreeViewChanged(nsIPresShell* aPresShell,
   1.424 +                                        nsIContent* aContent,
   1.425 +                                        nsITreeView* aView)
   1.426 +{
   1.427 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.428 +  if (document) {
   1.429 +    Accessible* accessible = document->GetAccessible(aContent);
   1.430 +    if (accessible) {
   1.431 +      XULTreeAccessible* treeAcc = accessible->AsXULTree();
   1.432 +      if (treeAcc) 
   1.433 +        treeAcc->TreeViewChanged(aView);
   1.434 +    }
   1.435 +  }
   1.436 +}
   1.437 +
   1.438 +void
   1.439 +nsAccessibilityService::RangeValueChanged(nsIPresShell* aPresShell,
   1.440 +                                          nsIContent* aContent)
   1.441 +{
   1.442 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.443 +  if (document) {
   1.444 +    Accessible* accessible = document->GetAccessible(aContent);
   1.445 +    if (accessible) {
   1.446 +      document->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
   1.447 +                                 accessible);
   1.448 +    }
   1.449 +  }
   1.450 +}
   1.451 +
   1.452 +void
   1.453 +nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
   1.454 +                                         nsIContent* aHTMLListItemContent,
   1.455 +                                         bool aHasBullet)
   1.456 +{
   1.457 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.458 +  if (document) {
   1.459 +    Accessible* accessible = document->GetAccessible(aHTMLListItemContent);
   1.460 +    if (accessible) {
   1.461 +      HTMLLIAccessible* listItem = accessible->AsHTMLListItem();
   1.462 +      if (listItem)
   1.463 +        listItem->UpdateBullet(aHasBullet);
   1.464 +    }
   1.465 +  }
   1.466 +}
   1.467 +
   1.468 +void
   1.469 +nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
   1.470 +{
   1.471 +  nsIPresShell* presShell = aImageFrame->PresContext()->PresShell();
   1.472 +  DocAccessible* document = GetDocAccessible(presShell);
   1.473 +  if (document) {
   1.474 +    Accessible* accessible =
   1.475 +      document->GetAccessible(aImageFrame->GetContent());
   1.476 +    if (accessible) {
   1.477 +      HTMLImageMapAccessible* imageMap = accessible->AsImageMap();
   1.478 +      if (imageMap) {
   1.479 +        imageMap->UpdateChildAreas();
   1.480 +        return;
   1.481 +      }
   1.482 +
   1.483 +      // If image map was initialized after we created an accessible (that'll
   1.484 +      // be an image accessible) then recreate it.
   1.485 +      RecreateAccessible(presShell, aImageFrame->GetContent());
   1.486 +    }
   1.487 +  }
   1.488 +}
   1.489 +
   1.490 +void
   1.491 +nsAccessibilityService::UpdateLabelValue(nsIPresShell* aPresShell,
   1.492 +                                         nsIContent* aLabelElm,
   1.493 +                                         const nsString& aNewValue)
   1.494 +{
   1.495 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.496 +  if (document) {
   1.497 +    Accessible* accessible = document->GetAccessible(aLabelElm);
   1.498 +    if (accessible) {
   1.499 +      XULLabelAccessible* xulLabel = accessible->AsXULLabel();
   1.500 +      NS_ASSERTION(xulLabel,
   1.501 +                   "UpdateLabelValue was called for wrong accessible!");
   1.502 +      if (xulLabel)
   1.503 +        xulLabel->UpdateLabelValue(aNewValue);
   1.504 +    }
   1.505 +  }
   1.506 +}
   1.507 +
   1.508 +void
   1.509 +nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
   1.510 +{
   1.511 +  DocAccessible* document = aPresShell->GetDocAccessible();
   1.512 +  if (document) {
   1.513 +    RootAccessible* rootDocument = document->RootAccessible();
   1.514 +    NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
   1.515 +    if (rootDocument)
   1.516 +      rootDocument->DocumentActivated(document);
   1.517 +  }
   1.518 +}
   1.519 +
   1.520 +void
   1.521 +nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
   1.522 +                                           nsIContent* aContent)
   1.523 +{
   1.524 +  DocAccessible* document = GetDocAccessible(aPresShell);
   1.525 +  if (document)
   1.526 +    document->RecreateAccessible(aContent);
   1.527 +}
   1.528 +
   1.529 +////////////////////////////////////////////////////////////////////////////////
   1.530 +// nsIAccessibleRetrieval
   1.531 +
   1.532 +NS_IMETHODIMP
   1.533 +nsAccessibilityService::GetApplicationAccessible(nsIAccessible** aAccessibleApplication)
   1.534 +{
   1.535 +  NS_ENSURE_ARG_POINTER(aAccessibleApplication);
   1.536 +
   1.537 +  NS_IF_ADDREF(*aAccessibleApplication = ApplicationAcc());
   1.538 +
   1.539 +  return NS_OK;
   1.540 +}
   1.541 +
   1.542 +NS_IMETHODIMP
   1.543 +nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
   1.544 +                                         nsIAccessible **aAccessible)
   1.545 +{
   1.546 +  NS_ENSURE_ARG_POINTER(aAccessible);
   1.547 +  *aAccessible = nullptr;
   1.548 +  if (!aNode)
   1.549 +    return NS_OK;
   1.550 +
   1.551 +  nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
   1.552 +  if (!node)
   1.553 +    return NS_ERROR_INVALID_ARG;
   1.554 +
   1.555 +  DocAccessible* document = GetDocAccessible(node->OwnerDoc());
   1.556 +  if (document)
   1.557 +    NS_IF_ADDREF(*aAccessible = document->GetAccessible(node));
   1.558 +
   1.559 +  return NS_OK;
   1.560 +}
   1.561 +
   1.562 +NS_IMETHODIMP
   1.563 +nsAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString)
   1.564 +{
   1.565 +#define ROLE(geckoRole, stringRole, atkRole, \
   1.566 +             macRole, msaaRole, ia2Role, nameRule) \
   1.567 +  case roles::geckoRole: \
   1.568 +    CopyUTF8toUTF16(stringRole, aString); \
   1.569 +    return NS_OK;
   1.570 +
   1.571 +  switch (aRole) {
   1.572 +#include "RoleMap.h"
   1.573 +    default:
   1.574 +      aString.AssignLiteral("unknown");
   1.575 +      return NS_OK;
   1.576 +  }
   1.577 +
   1.578 +#undef ROLE
   1.579 +}
   1.580 +
   1.581 +NS_IMETHODIMP
   1.582 +nsAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
   1.583 +                                        nsISupports **aStringStates)
   1.584 +{
   1.585 +  nsRefPtr<DOMStringList> stringStates = new DOMStringList();
   1.586 +
   1.587 +  uint64_t state = nsAccUtils::To64State(aState, aExtraState);
   1.588 +
   1.589 +  // states
   1.590 +  if (state & states::UNAVAILABLE)
   1.591 +    stringStates->Add(NS_LITERAL_STRING("unavailable"));
   1.592 +  if (state & states::SELECTED)
   1.593 +    stringStates->Add(NS_LITERAL_STRING("selected"));
   1.594 +  if (state & states::FOCUSED)
   1.595 +    stringStates->Add(NS_LITERAL_STRING("focused"));
   1.596 +  if (state & states::PRESSED)
   1.597 +    stringStates->Add(NS_LITERAL_STRING("pressed"));
   1.598 +  if (state & states::CHECKED)
   1.599 +    stringStates->Add(NS_LITERAL_STRING("checked"));
   1.600 +  if (state & states::MIXED)
   1.601 +    stringStates->Add(NS_LITERAL_STRING("mixed"));
   1.602 +  if (state & states::READONLY)
   1.603 +    stringStates->Add(NS_LITERAL_STRING("readonly"));
   1.604 +  if (state & states::HOTTRACKED)
   1.605 +    stringStates->Add(NS_LITERAL_STRING("hottracked"));
   1.606 +  if (state & states::DEFAULT)
   1.607 +    stringStates->Add(NS_LITERAL_STRING("default"));
   1.608 +  if (state & states::EXPANDED)
   1.609 +    stringStates->Add(NS_LITERAL_STRING("expanded"));
   1.610 +  if (state & states::COLLAPSED)
   1.611 +    stringStates->Add(NS_LITERAL_STRING("collapsed"));
   1.612 +  if (state & states::BUSY)
   1.613 +    stringStates->Add(NS_LITERAL_STRING("busy"));
   1.614 +  if (state & states::FLOATING)
   1.615 +    stringStates->Add(NS_LITERAL_STRING("floating"));
   1.616 +  if (state & states::ANIMATED)
   1.617 +    stringStates->Add(NS_LITERAL_STRING("animated"));
   1.618 +  if (state & states::INVISIBLE)
   1.619 +    stringStates->Add(NS_LITERAL_STRING("invisible"));
   1.620 +  if (state & states::OFFSCREEN)
   1.621 +    stringStates->Add(NS_LITERAL_STRING("offscreen"));
   1.622 +  if (state & states::SIZEABLE)
   1.623 +    stringStates->Add(NS_LITERAL_STRING("sizeable"));
   1.624 +  if (state & states::MOVEABLE)
   1.625 +    stringStates->Add(NS_LITERAL_STRING("moveable"));
   1.626 +  if (state & states::SELFVOICING)
   1.627 +    stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
   1.628 +  if (state & states::FOCUSABLE)
   1.629 +    stringStates->Add(NS_LITERAL_STRING("focusable"));
   1.630 +  if (state & states::SELECTABLE)
   1.631 +    stringStates->Add(NS_LITERAL_STRING("selectable"));
   1.632 +  if (state & states::LINKED)
   1.633 +    stringStates->Add(NS_LITERAL_STRING("linked"));
   1.634 +  if (state & states::TRAVERSED)
   1.635 +    stringStates->Add(NS_LITERAL_STRING("traversed"));
   1.636 +  if (state & states::MULTISELECTABLE)
   1.637 +    stringStates->Add(NS_LITERAL_STRING("multiselectable"));
   1.638 +  if (state & states::EXTSELECTABLE)
   1.639 +    stringStates->Add(NS_LITERAL_STRING("extselectable"));
   1.640 +  if (state & states::PROTECTED)
   1.641 +    stringStates->Add(NS_LITERAL_STRING("protected"));
   1.642 +  if (state & states::HASPOPUP)
   1.643 +    stringStates->Add(NS_LITERAL_STRING("haspopup"));
   1.644 +  if (state & states::REQUIRED)
   1.645 +    stringStates->Add(NS_LITERAL_STRING("required"));
   1.646 +  if (state & states::ALERT)
   1.647 +    stringStates->Add(NS_LITERAL_STRING("alert"));
   1.648 +  if (state & states::INVALID)
   1.649 +    stringStates->Add(NS_LITERAL_STRING("invalid"));
   1.650 +  if (state & states::CHECKABLE)
   1.651 +    stringStates->Add(NS_LITERAL_STRING("checkable"));
   1.652 +
   1.653 +  // extraStates
   1.654 +  if (state & states::SUPPORTS_AUTOCOMPLETION)
   1.655 +    stringStates->Add(NS_LITERAL_STRING("autocompletion"));
   1.656 +  if (state & states::DEFUNCT)
   1.657 +    stringStates->Add(NS_LITERAL_STRING("defunct"));
   1.658 +  if (state & states::SELECTABLE_TEXT)
   1.659 +    stringStates->Add(NS_LITERAL_STRING("selectable text"));
   1.660 +  if (state & states::EDITABLE)
   1.661 +    stringStates->Add(NS_LITERAL_STRING("editable"));
   1.662 +  if (state & states::ACTIVE)
   1.663 +    stringStates->Add(NS_LITERAL_STRING("active"));
   1.664 +  if (state & states::MODAL)
   1.665 +    stringStates->Add(NS_LITERAL_STRING("modal"));
   1.666 +  if (state & states::MULTI_LINE)
   1.667 +    stringStates->Add(NS_LITERAL_STRING("multi line"));
   1.668 +  if (state & states::HORIZONTAL)
   1.669 +    stringStates->Add(NS_LITERAL_STRING("horizontal"));
   1.670 +  if (state & states::OPAQUE1)
   1.671 +    stringStates->Add(NS_LITERAL_STRING("opaque"));
   1.672 +  if (state & states::SINGLE_LINE)
   1.673 +    stringStates->Add(NS_LITERAL_STRING("single line"));
   1.674 +  if (state & states::TRANSIENT)
   1.675 +    stringStates->Add(NS_LITERAL_STRING("transient"));
   1.676 +  if (state & states::VERTICAL)
   1.677 +    stringStates->Add(NS_LITERAL_STRING("vertical"));
   1.678 +  if (state & states::STALE)
   1.679 +    stringStates->Add(NS_LITERAL_STRING("stale"));
   1.680 +  if (state & states::ENABLED)
   1.681 +    stringStates->Add(NS_LITERAL_STRING("enabled"));
   1.682 +  if (state & states::SENSITIVE)
   1.683 +    stringStates->Add(NS_LITERAL_STRING("sensitive"));
   1.684 +  if (state & states::EXPANDABLE)
   1.685 +    stringStates->Add(NS_LITERAL_STRING("expandable"));
   1.686 +
   1.687 +  //unknown states
   1.688 +  if (!stringStates->Length())
   1.689 +    stringStates->Add(NS_LITERAL_STRING("unknown"));
   1.690 +
   1.691 +  stringStates.forget(aStringStates);
   1.692 +  return NS_OK;
   1.693 +}
   1.694 +
   1.695 +// nsIAccessibleRetrieval::getStringEventType()
   1.696 +NS_IMETHODIMP
   1.697 +nsAccessibilityService::GetStringEventType(uint32_t aEventType,
   1.698 +                                           nsAString& aString)
   1.699 +{
   1.700 +  NS_ASSERTION(nsIAccessibleEvent::EVENT_LAST_ENTRY == ArrayLength(kEventTypeNames),
   1.701 +               "nsIAccessibleEvent constants are out of sync to kEventTypeNames");
   1.702 +
   1.703 +  if (aEventType >= ArrayLength(kEventTypeNames)) {
   1.704 +    aString.AssignLiteral("unknown");
   1.705 +    return NS_OK;
   1.706 +  }
   1.707 +
   1.708 +  CopyUTF8toUTF16(kEventTypeNames[aEventType], aString);
   1.709 +  return NS_OK;
   1.710 +}
   1.711 +
   1.712 +// nsIAccessibleRetrieval::getStringRelationType()
   1.713 +NS_IMETHODIMP
   1.714 +nsAccessibilityService::GetStringRelationType(uint32_t aRelationType,
   1.715 +                                              nsAString& aString)
   1.716 +{
   1.717 +  NS_ENSURE_ARG(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
   1.718 +
   1.719 +#define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
   1.720 +  case RelationType::geckoType: \
   1.721 +    aString.AssignLiteral(geckoTypeName); \
   1.722 +    return NS_OK;
   1.723 +
   1.724 +  RelationType relationType = static_cast<RelationType>(aRelationType);
   1.725 +  switch (relationType) {
   1.726 +#include "RelationTypeMap.h"
   1.727 +    default:
   1.728 +      aString.AssignLiteral("unknown");
   1.729 +      return NS_OK;
   1.730 +  }
   1.731 +
   1.732 +#undef RELATIONTYPE
   1.733 +}
   1.734 +
   1.735 +NS_IMETHODIMP
   1.736 +nsAccessibilityService::GetAccessibleFromCache(nsIDOMNode* aNode,
   1.737 +                                               nsIAccessible** aAccessible)
   1.738 +{
   1.739 +  NS_ENSURE_ARG_POINTER(aAccessible);
   1.740 +  *aAccessible = nullptr;
   1.741 +  if (!aNode)
   1.742 +    return NS_OK;
   1.743 +
   1.744 +  nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
   1.745 +  if (!node)
   1.746 +    return NS_ERROR_INVALID_ARG;
   1.747 +
   1.748 +  // Search for an accessible in each of our per document accessible object
   1.749 +  // caches. If we don't find it, and the given node is itself a document, check
   1.750 +  // our cache of document accessibles (document cache). Note usually shutdown
   1.751 +  // document accessibles are not stored in the document cache, however an
   1.752 +  // "unofficially" shutdown document (i.e. not from DocManager) can still
   1.753 +  // exist in the document cache.
   1.754 +  Accessible* accessible = FindAccessibleInCache(node);
   1.755 +  if (!accessible) {
   1.756 +    nsCOMPtr<nsIDocument> document(do_QueryInterface(node));
   1.757 +    if (document)
   1.758 +      accessible = GetExistingDocAccessible(document);
   1.759 +  }
   1.760 +
   1.761 +  NS_IF_ADDREF(*aAccessible = accessible);
   1.762 +  return NS_OK;
   1.763 +}
   1.764 +
   1.765 +NS_IMETHODIMP
   1.766 +nsAccessibilityService::CreateAccessiblePivot(nsIAccessible* aRoot,
   1.767 +                                              nsIAccessiblePivot** aPivot)
   1.768 +{
   1.769 +  NS_ENSURE_ARG_POINTER(aPivot);
   1.770 +  NS_ENSURE_ARG(aRoot);
   1.771 +  *aPivot = nullptr;
   1.772 +
   1.773 +  nsRefPtr<Accessible> accessibleRoot(do_QueryObject(aRoot));
   1.774 +  NS_ENSURE_TRUE(accessibleRoot, NS_ERROR_INVALID_ARG);
   1.775 +
   1.776 +  nsAccessiblePivot* pivot = new nsAccessiblePivot(accessibleRoot);
   1.777 +  NS_ADDREF(*aPivot = pivot);
   1.778 +
   1.779 +  return NS_OK;
   1.780 +}
   1.781 +
   1.782 +NS_IMETHODIMP
   1.783 +nsAccessibilityService::SetLogging(const nsACString& aModules)
   1.784 +{
   1.785 +#ifdef A11Y_LOG
   1.786 +  logging::Enable(PromiseFlatCString(aModules));
   1.787 +#endif
   1.788 +  return NS_OK;
   1.789 +}
   1.790 +
   1.791 +NS_IMETHODIMP
   1.792 +nsAccessibilityService::IsLogged(const nsAString& aModule, bool* aIsLogged)
   1.793 +{
   1.794 +  NS_ENSURE_ARG_POINTER(aIsLogged);
   1.795 +  *aIsLogged = false;
   1.796 +
   1.797 +#ifdef A11Y_LOG
   1.798 +  *aIsLogged = logging::IsEnabled(aModule);
   1.799 +#endif
   1.800 +
   1.801 +  return NS_OK;
   1.802 +}
   1.803 +
   1.804 +////////////////////////////////////////////////////////////////////////////////
   1.805 +// nsAccessibilityService public
   1.806 +
   1.807 +Accessible*
   1.808 +nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
   1.809 +                                              Accessible* aContext,
   1.810 +                                              bool* aIsSubtreeHidden)
   1.811 +{
   1.812 +  NS_PRECONDITION(aContext && aNode && !gIsShutdown,
   1.813 +                  "Maybe let'd do a crash? Oh, yes, baby!");
   1.814 +
   1.815 +  if (aIsSubtreeHidden)
   1.816 +    *aIsSubtreeHidden = false;
   1.817 +
   1.818 +  DocAccessible* document = aContext->Document();
   1.819 +
   1.820 +  // Check to see if we already have an accessible for this node in the cache.
   1.821 +  // XXX: we don't have context check here. It doesn't really necessary until
   1.822 +  // we have in-law children adoption.
   1.823 +  Accessible* cachedAccessible = document->GetAccessible(aNode);
   1.824 +  if (cachedAccessible)
   1.825 +    return cachedAccessible;
   1.826 +
   1.827 +  // No cache entry, so we must create the accessible.
   1.828 +
   1.829 +  if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
   1.830 +    // If it's document node then ask accessible document loader for
   1.831 +    // document accessible, otherwise return null.
   1.832 +    nsCOMPtr<nsIDocument> document(do_QueryInterface(aNode));
   1.833 +    return GetDocAccessible(document);
   1.834 +  }
   1.835 +
   1.836 +  // We have a content node.
   1.837 +  if (!aNode->IsInDoc()) {
   1.838 +    NS_WARNING("Creating accessible for node with no document");
   1.839 +    return nullptr;
   1.840 +  }
   1.841 +
   1.842 +  if (aNode->OwnerDoc() != document->DocumentNode()) {
   1.843 +    NS_ERROR("Creating accessible for wrong document");
   1.844 +    return nullptr;
   1.845 +  }
   1.846 +
   1.847 +  if (!aNode->IsContent())
   1.848 +    return nullptr;
   1.849 +
   1.850 +  nsIContent* content = aNode->AsContent();
   1.851 +  nsIFrame* frame = content->GetPrimaryFrame();
   1.852 +
   1.853 +  // Check frame and its visibility. Note, hidden frame allows visible
   1.854 +  // elements in subtree.
   1.855 +  if (!frame || !frame->StyleVisibility()->IsVisible()) {
   1.856 +    if (aIsSubtreeHidden && !frame)
   1.857 +      *aIsSubtreeHidden = true;
   1.858 +
   1.859 +    return nullptr;
   1.860 +  }
   1.861 +
   1.862 +  if (frame->GetContent() != content) {
   1.863 +    // Not the main content for this frame. This happens because <area>
   1.864 +    // elements return the image frame as their primary frame. The main content
   1.865 +    // for the image frame is the image content. If the frame is not an image
   1.866 +    // frame or the node is not an area element then null is returned.
   1.867 +    // This setup will change when bug 135040 is fixed. Make sure we don't
   1.868 +    // create area accessible here. Hopefully assertion below will handle that.
   1.869 +
   1.870 +#ifdef DEBUG
   1.871 +  nsImageFrame* imageFrame = do_QueryFrame(frame);
   1.872 +  NS_ASSERTION(imageFrame && content->IsHTML() && content->Tag() == nsGkAtoms::area,
   1.873 +               "Unknown case of not main content for the frame!");
   1.874 +#endif
   1.875 +    return nullptr;
   1.876 +  }
   1.877 +
   1.878 +#ifdef DEBUG
   1.879 +  nsImageFrame* imageFrame = do_QueryFrame(frame);
   1.880 +  NS_ASSERTION(!imageFrame || !content->IsHTML() || content->Tag() != nsGkAtoms::area,
   1.881 +               "Image map manages the area accessible creation!");
   1.882 +#endif
   1.883 +
   1.884 +  // Attempt to create an accessible based on what we know.
   1.885 +  nsRefPtr<Accessible> newAcc;
   1.886 +
   1.887 +  // Create accessible for visible text frames.
   1.888 +  if (content->IsNodeOfType(nsINode::eTEXT)) {
   1.889 +    nsAutoString text;
   1.890 +    frame->GetRenderedText(&text, nullptr, nullptr, 0, UINT32_MAX);
   1.891 +    // Ignore not rendered text nodes and whitespace text nodes between table
   1.892 +    // cells.
   1.893 +    if (text.IsEmpty() ||
   1.894 +        (aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text))) {
   1.895 +      if (aIsSubtreeHidden)
   1.896 +        *aIsSubtreeHidden = true;
   1.897 +
   1.898 +      return nullptr;
   1.899 +    }
   1.900 +
   1.901 +    newAcc = CreateAccessibleByFrameType(frame, content, aContext);
   1.902 +    if (!aContext->IsAcceptableChild(newAcc))
   1.903 +      return nullptr;
   1.904 +
   1.905 +    document->BindToDocument(newAcc, nullptr);
   1.906 +    newAcc->AsTextLeaf()->SetText(text);
   1.907 +    return newAcc;
   1.908 +  }
   1.909 +
   1.910 +  bool isHTML = content->IsHTML();
   1.911 +  if (isHTML && content->Tag() == nsGkAtoms::map) {
   1.912 +    // Create hyper text accessible for HTML map if it is used to group links
   1.913 +    // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
   1.914 +    // map rect is empty then it is used for links grouping. Otherwise it should
   1.915 +    // be used in conjunction with HTML image element and in this case we don't
   1.916 +    // create any accessible for it and don't walk into it. The accessibles for
   1.917 +    // HTML area (HTMLAreaAccessible) the map contains are attached as
   1.918 +    // children of the appropriate accessible for HTML image
   1.919 +    // (ImageAccessible).
   1.920 +    if (nsLayoutUtils::GetAllInFlowRectsUnion(frame,
   1.921 +                                              frame->GetParent()).IsEmpty()) {
   1.922 +      if (aIsSubtreeHidden)
   1.923 +        *aIsSubtreeHidden = true;
   1.924 +
   1.925 +      return nullptr;
   1.926 +    }
   1.927 +
   1.928 +    newAcc = new HyperTextAccessibleWrap(content, document);
   1.929 +    if (!aContext->IsAcceptableChild(newAcc))
   1.930 +      return nullptr;
   1.931 +
   1.932 +    document->BindToDocument(newAcc, aria::GetRoleMap(aNode));
   1.933 +    return newAcc;
   1.934 +  }
   1.935 +
   1.936 +  nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aNode);
   1.937 +
   1.938 +  // If the element is focusable or global ARIA attribute is applied to it or
   1.939 +  // it is referenced by ARIA relationship then treat role="presentation" on
   1.940 +  // the element as the role is not there.
   1.941 +  if (roleMapEntry && roleMapEntry->Is(nsGkAtoms::presentation)) {
   1.942 +    if (!MustBeAccessible(content, document))
   1.943 +      return nullptr;
   1.944 +
   1.945 +    roleMapEntry = nullptr;
   1.946 +  }
   1.947 +
   1.948 +  if (!newAcc && isHTML) {  // HTML accessibles
   1.949 +    if (roleMapEntry) {
   1.950 +      // Create pure ARIA grid/treegrid related accessibles if they weren't used
   1.951 +      // on accessible HTML table elements.
   1.952 +      if ((roleMapEntry->accTypes & eTableCell)) {
   1.953 +        if (aContext->IsTableRow() &&
   1.954 +            (frame->AccessibleType() != eHTMLTableCellType ||
   1.955 +             aContext->GetContent() != content->GetParent())) {
   1.956 +          newAcc = new ARIAGridCellAccessibleWrap(content, document);
   1.957 +        }
   1.958 +
   1.959 +      } else if ((roleMapEntry->IsOfType(eTable)) &&
   1.960 +                 frame->AccessibleType() != eHTMLTableType) {
   1.961 +        newAcc = new ARIAGridAccessibleWrap(content, document);
   1.962 +      }
   1.963 +    }
   1.964 +
   1.965 +    if (!newAcc) {
   1.966 +      // Prefer to use markup (mostly tag name, perhaps attributes) to decide if
   1.967 +      // and what kind of accessible to create.
   1.968 +      newAcc = CreateHTMLAccessibleByMarkup(frame, content, aContext);
   1.969 +
   1.970 +      // Try using frame to do it.
   1.971 +      if (!newAcc)
   1.972 +        newAcc = CreateAccessibleByFrameType(frame, content, aContext);
   1.973 +
   1.974 +      // If table has strong ARIA role then all table descendants shouldn't
   1.975 +      // expose their native roles.
   1.976 +      if (!roleMapEntry && newAcc) {
   1.977 +        if (frame->AccessibleType() == eHTMLTableRowType) {
   1.978 +          nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
   1.979 +          if (contextRoleMap && !(contextRoleMap->IsOfType(eTable)))
   1.980 +            roleMapEntry = &aria::gEmptyRoleMap;
   1.981 +
   1.982 +        } else if (frame->AccessibleType() == eHTMLTableCellType &&
   1.983 +                   aContext->ARIARoleMap() == &aria::gEmptyRoleMap) {
   1.984 +          roleMapEntry = &aria::gEmptyRoleMap;
   1.985 +
   1.986 +        } else if (content->Tag() == nsGkAtoms::dt ||
   1.987 +                   content->Tag() == nsGkAtoms::li ||
   1.988 +                   content->Tag() == nsGkAtoms::dd ||
   1.989 +                   frame->AccessibleType() == eHTMLLiType) {
   1.990 +          nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
   1.991 +          if (contextRoleMap && !(contextRoleMap->IsOfType(eList)))
   1.992 +            roleMapEntry = &aria::gEmptyRoleMap;
   1.993 +        }
   1.994 +      }
   1.995 +    }
   1.996 +  }
   1.997 +
   1.998 +  // Accessible XBL types and deck stuff are used in XUL only currently.
   1.999 +  if (!newAcc && content->IsXUL()) {
  1.1000 +    // No accessible for not selected deck panel and its children.
  1.1001 +    if (!aContext->IsXULTabpanels()) {
  1.1002 +      nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
  1.1003 +      if (deckFrame && deckFrame->GetSelectedBox() != frame) {
  1.1004 +        if (aIsSubtreeHidden)
  1.1005 +          *aIsSubtreeHidden = true;
  1.1006 +
  1.1007 +        return nullptr;
  1.1008 +      }
  1.1009 +    }
  1.1010 +
  1.1011 +    // XBL bindings may use @role attribute to point the accessible type
  1.1012 +    // they belong to.
  1.1013 +    newAcc = CreateAccessibleByType(content, document);
  1.1014 +
  1.1015 +    // Any XUL box can be used as tabpanel, make sure we create a proper
  1.1016 +    // accessible for it.
  1.1017 +    if (!newAcc && aContext->IsXULTabpanels() &&
  1.1018 +        content->GetParent() == aContext->GetContent()) {
  1.1019 +      nsIAtom* frameType = frame->GetType();
  1.1020 +      if (frameType == nsGkAtoms::boxFrame ||
  1.1021 +          frameType == nsGkAtoms::scrollFrame) {
  1.1022 +        newAcc = new XULTabpanelAccessible(content, document);
  1.1023 +      }
  1.1024 +    }
  1.1025 +  }
  1.1026 +
  1.1027 +  if (!newAcc) {
  1.1028 +    if (content->IsSVG()) {
  1.1029 +      nsSVGPathGeometryFrame* pathGeometryFrame = do_QueryFrame(frame);
  1.1030 +      if (pathGeometryFrame) {
  1.1031 +        // A graphic elements: rect, circle, ellipse, line, path, polygon,
  1.1032 +        // polyline and image. A 'use' and 'text' graphic elements require
  1.1033 +        // special support.
  1.1034 +        newAcc = new EnumRoleAccessible(content, document, roles::GRAPHIC);
  1.1035 +      } else if (content->Tag() == nsGkAtoms::svg) {
  1.1036 +        newAcc = new EnumRoleAccessible(content, document, roles::DIAGRAM);
  1.1037 +      }
  1.1038 +    } else if (content->IsMathML()){
  1.1039 +      if (content->Tag() == nsGkAtoms::math)
  1.1040 +        newAcc = new EnumRoleAccessible(content, document, roles::EQUATION);
  1.1041 +      else
  1.1042 +        newAcc = new HyperTextAccessible(content, document);
  1.1043 +    }
  1.1044 +  }
  1.1045 +
  1.1046 +  // If no accessible, see if we need to create a generic accessible because
  1.1047 +  // of some property that makes this object interesting
  1.1048 +  // We don't do this for <body>, <html>, <window>, <dialog> etc. which
  1.1049 +  // correspond to the doc accessible and will be created in any case
  1.1050 +  if (!newAcc && content->Tag() != nsGkAtoms::body && content->GetParent() &&
  1.1051 +      (roleMapEntry || MustBeAccessible(content, document) ||
  1.1052 +       (isHTML && nsCoreUtils::HasClickListener(content)))) {
  1.1053 +    // This content is focusable or has an interesting dynamic content accessibility property.
  1.1054 +    // If it's interesting we need it in the accessibility hierarchy so that events or
  1.1055 +    // other accessibles can point to it, or so that it can hold a state, etc.
  1.1056 +    if (isHTML) {
  1.1057 +      // Interesting HTML container which may have selectable text and/or embedded objects
  1.1058 +      newAcc = new HyperTextAccessibleWrap(content, document);
  1.1059 +    } else {  // XUL, SVG, MathML etc.
  1.1060 +      // Interesting generic non-HTML container
  1.1061 +      newAcc = new AccessibleWrap(content, document);
  1.1062 +    }
  1.1063 +  }
  1.1064 +
  1.1065 +  if (!newAcc || !aContext->IsAcceptableChild(newAcc))
  1.1066 +    return nullptr;
  1.1067 +
  1.1068 +  document->BindToDocument(newAcc, roleMapEntry);
  1.1069 +  return newAcc;
  1.1070 +}
  1.1071 +
  1.1072 +////////////////////////////////////////////////////////////////////////////////
  1.1073 +// nsAccessibilityService private
  1.1074 +
  1.1075 +bool
  1.1076 +nsAccessibilityService::Init()
  1.1077 +{
  1.1078 +  // Initialize accessible document manager.
  1.1079 +  if (!DocManager::Init())
  1.1080 +    return false;
  1.1081 +
  1.1082 +  // Add observers.
  1.1083 +  nsCOMPtr<nsIObserverService> observerService =
  1.1084 +    mozilla::services::GetObserverService();
  1.1085 +  if (!observerService)
  1.1086 +    return false;
  1.1087 +
  1.1088 +  observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
  1.1089 +
  1.1090 +  static const char16_t kInitIndicator[] = { '1', 0 };
  1.1091 +  observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kInitIndicator);
  1.1092 +
  1.1093 +#ifdef A11Y_LOG
  1.1094 +  logging::CheckEnv();
  1.1095 +#endif
  1.1096 +
  1.1097 +  gApplicationAccessible = new ApplicationAccessibleWrap();
  1.1098 +  NS_ADDREF(gApplicationAccessible); // will release in Shutdown()
  1.1099 +
  1.1100 +#ifdef MOZ_CRASHREPORTER
  1.1101 +  CrashReporter::
  1.1102 +    AnnotateCrashReport(NS_LITERAL_CSTRING("Accessibility"),
  1.1103 +                        NS_LITERAL_CSTRING("Active"));
  1.1104 +#endif
  1.1105 +
  1.1106 +#ifdef XP_WIN
  1.1107 +  sPendingPlugins = new nsTArray<nsCOMPtr<nsIContent> >;
  1.1108 +  sPluginTimers = new nsTArray<nsCOMPtr<nsITimer> >;
  1.1109 +#endif
  1.1110 +
  1.1111 +  gIsShutdown = false;
  1.1112 +
  1.1113 +  // Now its safe to start platform accessibility.
  1.1114 +  PlatformInit();
  1.1115 +
  1.1116 +  return true;
  1.1117 +}
  1.1118 +
  1.1119 +void
  1.1120 +nsAccessibilityService::Shutdown()
  1.1121 +{
  1.1122 +  // Remove observers.
  1.1123 +  nsCOMPtr<nsIObserverService> observerService =
  1.1124 +      mozilla::services::GetObserverService();
  1.1125 +  if (observerService) {
  1.1126 +    observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
  1.1127 +
  1.1128 +    static const char16_t kShutdownIndicator[] = { '0', 0 };
  1.1129 +    observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kShutdownIndicator);
  1.1130 +  }
  1.1131 +
  1.1132 +  // Stop accessible document loader.
  1.1133 +  DocManager::Shutdown();
  1.1134 +
  1.1135 +  SelectionManager::Shutdown();
  1.1136 +
  1.1137 +#ifdef XP_WIN
  1.1138 +  sPendingPlugins = nullptr;
  1.1139 +
  1.1140 +  uint32_t timerCount = sPluginTimers->Length();
  1.1141 +  for (uint32_t i = 0; i < timerCount; i++)
  1.1142 +    sPluginTimers->ElementAt(i)->Cancel();
  1.1143 +
  1.1144 +  sPluginTimers = nullptr;
  1.1145 +#endif
  1.1146 +
  1.1147 +  // Application is going to be closed, shutdown accessibility and mark
  1.1148 +  // accessibility service as shutdown to prevent calls of its methods.
  1.1149 +  // Don't null accessibility service static member at this point to be safe
  1.1150 +  // if someone will try to operate with it.
  1.1151 +
  1.1152 +  NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already");
  1.1153 +
  1.1154 +  gIsShutdown = true;
  1.1155 +
  1.1156 +  PlatformShutdown();
  1.1157 +  gApplicationAccessible->Shutdown();
  1.1158 +  NS_RELEASE(gApplicationAccessible);
  1.1159 +  gApplicationAccessible = nullptr;
  1.1160 +}
  1.1161 +
  1.1162 +already_AddRefed<Accessible>
  1.1163 +nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
  1.1164 +                                               DocAccessible* aDoc)
  1.1165 +{
  1.1166 +  nsAutoString role;
  1.1167 +  for (const nsXBLBinding* binding = aContent->GetXBLBinding(); binding; binding = binding->GetBaseBinding()) {
  1.1168 +    nsIContent* bindingElm = binding->PrototypeBinding()->GetBindingElement();
  1.1169 +    bindingElm->GetAttr(kNameSpaceID_None, nsGkAtoms::role, role);
  1.1170 +    if (!role.IsEmpty())
  1.1171 +      break;
  1.1172 +  }
  1.1173 +
  1.1174 +  if (role.IsEmpty() || role.EqualsLiteral("none"))
  1.1175 +    return nullptr;
  1.1176 +
  1.1177 +  if (role.EqualsLiteral("outerdoc")) {
  1.1178 +    nsRefPtr<Accessible> accessible = new OuterDocAccessible(aContent, aDoc);
  1.1179 +    return accessible.forget();
  1.1180 +  }
  1.1181 + 
  1.1182 +  nsRefPtr<Accessible> accessible;
  1.1183 +#ifdef MOZ_XUL
  1.1184 +  // XUL controls
  1.1185 +  if (role.EqualsLiteral("xul:alert")) {
  1.1186 +    accessible = new XULAlertAccessible(aContent, aDoc);
  1.1187 +
  1.1188 +  } else if (role.EqualsLiteral("xul:button")) {
  1.1189 +    accessible = new XULButtonAccessible(aContent, aDoc);
  1.1190 +
  1.1191 +  } else if (role.EqualsLiteral("xul:checkbox")) {
  1.1192 +    accessible = new XULCheckboxAccessible(aContent, aDoc);
  1.1193 +
  1.1194 +  } else if (role.EqualsLiteral("xul:colorpicker")) {
  1.1195 +    accessible = new XULColorPickerAccessible(aContent, aDoc);
  1.1196 +
  1.1197 +  } else if (role.EqualsLiteral("xul:colorpickertile")) {
  1.1198 +    accessible = new XULColorPickerTileAccessible(aContent, aDoc);
  1.1199 +
  1.1200 +  } else if (role.EqualsLiteral("xul:combobox")) {
  1.1201 +    accessible = new XULComboboxAccessible(aContent, aDoc);
  1.1202 +
  1.1203 +  } else if (role.EqualsLiteral("xul:tabpanels")) {
  1.1204 +      accessible = new XULTabpanelsAccessible(aContent, aDoc);
  1.1205 +
  1.1206 +  } else if (role.EqualsLiteral("xul:dropmarker")) {
  1.1207 +      accessible = new XULDropmarkerAccessible(aContent, aDoc);
  1.1208 +
  1.1209 +  } else if (role.EqualsLiteral("xul:groupbox")) {
  1.1210 +      accessible = new XULGroupboxAccessible(aContent, aDoc);
  1.1211 +
  1.1212 +  } else if (role.EqualsLiteral("xul:image")) {
  1.1213 +    if (aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::onclick)) {
  1.1214 +      accessible = new XULToolbarButtonAccessible(aContent, aDoc);
  1.1215 +
  1.1216 +    } else {
  1.1217 +      // Don't include nameless images in accessible tree.
  1.1218 +      if (!aContent->HasAttr(kNameSpaceID_None,
  1.1219 +                             nsGkAtoms::tooltiptext))
  1.1220 +        return nullptr;
  1.1221 +
  1.1222 +      accessible = new ImageAccessibleWrap(aContent, aDoc);
  1.1223 +    }
  1.1224 +
  1.1225 +  } else if (role.EqualsLiteral("xul:link")) {
  1.1226 +    accessible = new XULLinkAccessible(aContent, aDoc);
  1.1227 +
  1.1228 +  } else if (role.EqualsLiteral("xul:listbox")) {
  1.1229 +      accessible = new XULListboxAccessibleWrap(aContent, aDoc);
  1.1230 +
  1.1231 +  } else if (role.EqualsLiteral("xul:listcell")) {
  1.1232 +    // Only create cells if there's more than one per row.
  1.1233 +    nsIContent* listItem = aContent->GetParent();
  1.1234 +    if (!listItem)
  1.1235 +      return nullptr;
  1.1236 +
  1.1237 +    for (nsIContent* child = listItem->GetFirstChild(); child;
  1.1238 +         child = child->GetNextSibling()) {
  1.1239 +      if (child->IsXUL(nsGkAtoms::listcell) && child != aContent) {
  1.1240 +        accessible = new XULListCellAccessibleWrap(aContent, aDoc);
  1.1241 +        break;
  1.1242 +      }
  1.1243 +    }
  1.1244 +
  1.1245 +  } else if (role.EqualsLiteral("xul:listhead")) {
  1.1246 +    accessible = new XULColumAccessible(aContent, aDoc);
  1.1247 +
  1.1248 +  } else if (role.EqualsLiteral("xul:listheader")) {
  1.1249 +    accessible = new XULColumnItemAccessible(aContent, aDoc);
  1.1250 +
  1.1251 +  } else if (role.EqualsLiteral("xul:listitem")) {
  1.1252 +    accessible = new XULListitemAccessible(aContent, aDoc);
  1.1253 +
  1.1254 +  } else if (role.EqualsLiteral("xul:menubar")) {
  1.1255 +    accessible = new XULMenubarAccessible(aContent, aDoc);
  1.1256 +
  1.1257 +  } else if (role.EqualsLiteral("xul:menulist")) {
  1.1258 +    accessible = new XULComboboxAccessible(aContent, aDoc);
  1.1259 +
  1.1260 +  } else if (role.EqualsLiteral("xul:menuitem")) {
  1.1261 +    accessible = new XULMenuitemAccessibleWrap(aContent, aDoc);
  1.1262 +
  1.1263 +  } else if (role.EqualsLiteral("xul:menupopup")) {
  1.1264 +#ifdef MOZ_ACCESSIBILITY_ATK
  1.1265 +    // ATK considers this node to be redundant when within menubars, and it makes menu
  1.1266 +    // navigation with assistive technologies more difficult
  1.1267 +    // XXX In the future we will should this for consistency across the nsIAccessible
  1.1268 +    // implementations on each platform for a consistent scripting environment, but
  1.1269 +    // then strip out redundant accessibles in the AccessibleWrap class for each platform.
  1.1270 +    nsIContent *parent = aContent->GetParent();
  1.1271 +    if (parent && parent->IsXUL() && parent->Tag() == nsGkAtoms::menu)
  1.1272 +      return nullptr;
  1.1273 +#endif
  1.1274 +
  1.1275 +    accessible = new XULMenupopupAccessible(aContent, aDoc);
  1.1276 +
  1.1277 +  } else if(role.EqualsLiteral("xul:menuseparator")) {
  1.1278 +    accessible = new XULMenuSeparatorAccessible(aContent, aDoc);
  1.1279 +
  1.1280 +  } else if(role.EqualsLiteral("xul:pane")) {
  1.1281 +    accessible = new EnumRoleAccessible(aContent, aDoc, roles::PANE);
  1.1282 +
  1.1283 +  } else if (role.EqualsLiteral("xul:panel")) {
  1.1284 +    if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautofocus,
  1.1285 +                              nsGkAtoms::_true, eCaseMatters))
  1.1286 +      accessible = new XULAlertAccessible(aContent, aDoc);
  1.1287 +    else
  1.1288 +      accessible = new EnumRoleAccessible(aContent, aDoc, roles::PANE);
  1.1289 +
  1.1290 +  } else if (role.EqualsLiteral("xul:progressmeter")) {
  1.1291 +    accessible = new XULProgressMeterAccessible(aContent, aDoc);
  1.1292 +
  1.1293 +  } else if (role.EqualsLiteral("xulstatusbar")) {
  1.1294 +    accessible = new XULStatusBarAccessible(aContent, aDoc);
  1.1295 +
  1.1296 +  } else if (role.EqualsLiteral("xul:scale")) {
  1.1297 +    accessible = new XULSliderAccessible(aContent, aDoc);
  1.1298 +
  1.1299 +  } else if (role.EqualsLiteral("xul:radiobutton")) {
  1.1300 +    accessible = new XULRadioButtonAccessible(aContent, aDoc);
  1.1301 +
  1.1302 +  } else if (role.EqualsLiteral("xul:radiogroup")) {
  1.1303 +    accessible = new XULRadioGroupAccessible(aContent, aDoc);
  1.1304 +
  1.1305 +  } else if (role.EqualsLiteral("xul:tab")) {
  1.1306 +    accessible = new XULTabAccessible(aContent, aDoc);
  1.1307 +
  1.1308 +  } else if (role.EqualsLiteral("xul:tabs")) {
  1.1309 +    accessible = new XULTabsAccessible(aContent, aDoc);
  1.1310 +
  1.1311 +  } else if (role.EqualsLiteral("xul:text")) {
  1.1312 +    accessible = new XULLabelAccessible(aContent, aDoc);
  1.1313 +
  1.1314 +  } else if (role.EqualsLiteral("xul:textbox")) {
  1.1315 +    accessible = new EnumRoleAccessible(aContent, aDoc, roles::SECTION);
  1.1316 +
  1.1317 +  } else if (role.EqualsLiteral("xul:thumb")) {
  1.1318 +    accessible = new XULThumbAccessible(aContent, aDoc);
  1.1319 +
  1.1320 +  } else if (role.EqualsLiteral("xul:tree")) {
  1.1321 +    accessible = CreateAccessibleForXULTree(aContent, aDoc);
  1.1322 +
  1.1323 +  } else if (role.EqualsLiteral("xul:treecolumns")) {
  1.1324 +    accessible = new XULTreeColumAccessible(aContent, aDoc);
  1.1325 +
  1.1326 +  } else if (role.EqualsLiteral("xul:treecolumnitem")) {
  1.1327 +    accessible = new XULColumnItemAccessible(aContent, aDoc);
  1.1328 +
  1.1329 +  } else if (role.EqualsLiteral("xul:toolbar")) {
  1.1330 +    accessible = new XULToolbarAccessible(aContent, aDoc);
  1.1331 +
  1.1332 +  } else if (role.EqualsLiteral("xul:toolbarseparator")) {
  1.1333 +    accessible = new XULToolbarSeparatorAccessible(aContent, aDoc);
  1.1334 +
  1.1335 +  } else if (role.EqualsLiteral("xul:tooltip")) {
  1.1336 +    accessible = new XULTooltipAccessible(aContent, aDoc);
  1.1337 +
  1.1338 +  } else if (role.EqualsLiteral("xul:toolbarbutton")) {
  1.1339 +    accessible = new XULToolbarButtonAccessible(aContent, aDoc);
  1.1340 +
  1.1341 +  }
  1.1342 +#endif // MOZ_XUL
  1.1343 +
  1.1344 +  return accessible.forget();
  1.1345 +}
  1.1346 +
  1.1347 +already_AddRefed<Accessible>
  1.1348 +nsAccessibilityService::CreateHTMLAccessibleByMarkup(nsIFrame* aFrame,
  1.1349 +                                                     nsIContent* aContent,
  1.1350 +                                                     Accessible* aContext)
  1.1351 +{
  1.1352 +  DocAccessible* document = aContext->Document();
  1.1353 +  if (aContext->IsTableRow()) {
  1.1354 +    if (nsCoreUtils::IsHTMLTableHeader(aContent) &&
  1.1355 +        aContext->GetContent() == aContent->GetParent()) {
  1.1356 +      nsRefPtr<Accessible> accessible =
  1.1357 +        new HTMLTableHeaderCellAccessibleWrap(aContent, document);
  1.1358 +      return accessible.forget();
  1.1359 +    }
  1.1360 +
  1.1361 +    return nullptr;
  1.1362 +  }
  1.1363 +
  1.1364 +  // This method assumes we're in an HTML namespace.
  1.1365 +  nsIAtom* tag = aContent->Tag();
  1.1366 +  if (tag == nsGkAtoms::figcaption) {
  1.1367 +    nsRefPtr<Accessible> accessible =
  1.1368 +      new HTMLFigcaptionAccessible(aContent, document);
  1.1369 +    return accessible.forget();
  1.1370 +  }
  1.1371 +
  1.1372 +  if (tag == nsGkAtoms::figure) {
  1.1373 +    nsRefPtr<Accessible> accessible =
  1.1374 +      new HTMLFigureAccessible(aContent, document);
  1.1375 +    return accessible.forget();
  1.1376 +  }
  1.1377 +
  1.1378 +  if (tag == nsGkAtoms::legend) {
  1.1379 +    nsRefPtr<Accessible> accessible =
  1.1380 +      new HTMLLegendAccessible(aContent, document);
  1.1381 +    return accessible.forget();
  1.1382 +  }
  1.1383 +
  1.1384 +  if (tag == nsGkAtoms::option) {
  1.1385 +    nsRefPtr<Accessible> accessible =
  1.1386 +      new HTMLSelectOptionAccessible(aContent, document);
  1.1387 +    return accessible.forget();
  1.1388 +  }
  1.1389 +
  1.1390 +  if (tag == nsGkAtoms::optgroup) {
  1.1391 +    nsRefPtr<Accessible> accessible =
  1.1392 +      new HTMLSelectOptGroupAccessible(aContent, document);
  1.1393 +    return accessible.forget();
  1.1394 +  }
  1.1395 +
  1.1396 +  if (tag == nsGkAtoms::ul || tag == nsGkAtoms::ol ||
  1.1397 +      tag == nsGkAtoms::dl) {
  1.1398 +    nsRefPtr<Accessible> accessible =
  1.1399 +      new HTMLListAccessible(aContent, document);
  1.1400 +    return accessible.forget();
  1.1401 +  }
  1.1402 +
  1.1403 +  if (tag == nsGkAtoms::a) {
  1.1404 +    // Only some roles truly enjoy life as HTMLLinkAccessibles, for details
  1.1405 +    // see closed bug 494807.
  1.1406 +    nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent);
  1.1407 +    if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
  1.1408 +        roleMapEntry->role != roles::LINK) {
  1.1409 +      nsRefPtr<Accessible> accessible =
  1.1410 +        new HyperTextAccessibleWrap(aContent, document);
  1.1411 +      return accessible.forget();
  1.1412 +    }
  1.1413 +
  1.1414 +    nsRefPtr<Accessible> accessible =
  1.1415 +      new HTMLLinkAccessible(aContent, document);
  1.1416 +    return accessible.forget();
  1.1417 +  }
  1.1418 +
  1.1419 +  if (aContext->IsList()) {
  1.1420 +    // If list item is a child of accessible list then create an accessible for
  1.1421 +    // it unconditionally by tag name. nsBlockFrame creates the list item
  1.1422 +    // accessible for other elements styled as list items.
  1.1423 +    if (aContext->GetContent() == aContent->GetParent()) {
  1.1424 +      if (tag == nsGkAtoms::dt || tag == nsGkAtoms::li) {
  1.1425 +        nsRefPtr<Accessible> accessible =
  1.1426 +          new HTMLLIAccessible(aContent, document);
  1.1427 +        return accessible.forget();
  1.1428 +      }
  1.1429 +
  1.1430 +      if (tag == nsGkAtoms::dd) {
  1.1431 +        nsRefPtr<Accessible> accessible =
  1.1432 +          new HyperTextAccessibleWrap(aContent, document);
  1.1433 +        return accessible.forget();
  1.1434 +      }
  1.1435 +    }
  1.1436 +
  1.1437 +    return nullptr;
  1.1438 +  }
  1.1439 +
  1.1440 +  if (tag == nsGkAtoms::abbr ||
  1.1441 +      tag == nsGkAtoms::acronym ||
  1.1442 +      tag == nsGkAtoms::article ||
  1.1443 +      tag == nsGkAtoms::aside ||
  1.1444 +      tag == nsGkAtoms::blockquote ||
  1.1445 +      tag == nsGkAtoms::form ||
  1.1446 +      tag == nsGkAtoms::footer ||
  1.1447 +      tag == nsGkAtoms::header ||
  1.1448 +      tag == nsGkAtoms::h1 ||
  1.1449 +      tag == nsGkAtoms::h2 ||
  1.1450 +      tag == nsGkAtoms::h3 ||
  1.1451 +      tag == nsGkAtoms::h4 ||
  1.1452 +      tag == nsGkAtoms::h5 ||
  1.1453 +      tag == nsGkAtoms::h6 ||
  1.1454 +      tag == nsGkAtoms::nav ||
  1.1455 +      tag == nsGkAtoms::q ||
  1.1456 +      tag == nsGkAtoms::section) {
  1.1457 +    nsRefPtr<Accessible> accessible =
  1.1458 +      new HyperTextAccessibleWrap(aContent, document);
  1.1459 +    return accessible.forget();
  1.1460 +  }
  1.1461 +
  1.1462 +  if (tag == nsGkAtoms::label) {
  1.1463 +    nsRefPtr<Accessible> accessible =
  1.1464 +      new HTMLLabelAccessible(aContent, document);
  1.1465 +    return accessible.forget();
  1.1466 +  }
  1.1467 +
  1.1468 +  if (tag == nsGkAtoms::output) {
  1.1469 +    nsRefPtr<Accessible> accessible =
  1.1470 +      new HTMLOutputAccessible(aContent, document);
  1.1471 +    return accessible.forget();
  1.1472 +  }
  1.1473 +
  1.1474 +  if (tag == nsGkAtoms::progress) {
  1.1475 +    nsRefPtr<Accessible> accessible =
  1.1476 +      new HTMLProgressMeterAccessible(aContent, document);
  1.1477 +    return accessible.forget();
  1.1478 +  }
  1.1479 +
  1.1480 +  return nullptr;
  1.1481 + }
  1.1482 +
  1.1483 +already_AddRefed<Accessible>
  1.1484 +nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
  1.1485 +                                                    nsIContent* aContent,
  1.1486 +                                                    Accessible* aContext)
  1.1487 +{
  1.1488 +  DocAccessible* document = aContext->Document();
  1.1489 +
  1.1490 +  nsRefPtr<Accessible> newAcc;
  1.1491 +  switch (aFrame->AccessibleType()) {
  1.1492 +    case eNoType:
  1.1493 +      return nullptr;
  1.1494 +    case eHTMLBRType:
  1.1495 +      newAcc = new HTMLBRAccessible(aContent, document);
  1.1496 +      break;
  1.1497 +    case eHTMLButtonType:
  1.1498 +      newAcc = new HTMLButtonAccessible(aContent, document);
  1.1499 +      break;
  1.1500 +    case eHTMLCanvasType:
  1.1501 +      newAcc = new HTMLCanvasAccessible(aContent, document);
  1.1502 +      break;
  1.1503 +    case eHTMLCaptionType:
  1.1504 +      if (aContext->IsTable() &&
  1.1505 +          aContext->GetContent() == aContent->GetParent()) {
  1.1506 +        newAcc = new HTMLCaptionAccessible(aContent, document);
  1.1507 +      }
  1.1508 +      break;
  1.1509 +    case eHTMLCheckboxType:
  1.1510 +      newAcc = new HTMLCheckboxAccessible(aContent, document);
  1.1511 +      break;
  1.1512 +    case eHTMLComboboxType:
  1.1513 +      newAcc = new HTMLComboboxAccessible(aContent, document);
  1.1514 +      break;
  1.1515 +    case eHTMLFileInputType:
  1.1516 +      newAcc = new HTMLFileInputAccessible(aContent, document);
  1.1517 +      break;
  1.1518 +    case eHTMLGroupboxType:
  1.1519 +      newAcc = new HTMLGroupboxAccessible(aContent, document);
  1.1520 +      break;
  1.1521 +    case eHTMLHRType:
  1.1522 +      newAcc = new HTMLHRAccessible(aContent, document);
  1.1523 +      break;
  1.1524 +    case eHTMLImageMapType:
  1.1525 +      newAcc = new HTMLImageMapAccessible(aContent, document);
  1.1526 +      break;
  1.1527 +    case eHTMLLiType:
  1.1528 +      if (aContext->IsList() &&
  1.1529 +          aContext->GetContent() == aContent->GetParent()) {
  1.1530 +        newAcc = new HTMLLIAccessible(aContent, document);
  1.1531 +      }
  1.1532 +      break;
  1.1533 +    case eHTMLSelectListType:
  1.1534 +      newAcc = new HTMLSelectListAccessible(aContent, document);
  1.1535 +      break;
  1.1536 +    case eHTMLMediaType:
  1.1537 +      newAcc = new EnumRoleAccessible(aContent, document, roles::GROUPING);
  1.1538 +      break;
  1.1539 +    case eHTMLRadioButtonType:
  1.1540 +      newAcc = new HTMLRadioButtonAccessible(aContent, document);
  1.1541 +      break;
  1.1542 +    case eHTMLRangeType:
  1.1543 +      newAcc = new HTMLRangeAccessible(aContent, document);
  1.1544 +      break;
  1.1545 +    case eHTMLSpinnerType:
  1.1546 +      newAcc = new HTMLSpinnerAccessible(aContent, document);
  1.1547 +      break;
  1.1548 +    case eHTMLTableType:
  1.1549 +      newAcc = new HTMLTableAccessibleWrap(aContent, document);
  1.1550 +      break;
  1.1551 +    case eHTMLTableCellType:
  1.1552 +      // Accessible HTML table cell should be a child of accessible HTML table
  1.1553 +      // or its row (CSS HTML tables are polite to the used markup at
  1.1554 +      // certain degree).
  1.1555 +      // Otherwise create a generic text accessible to avoid text jamming
  1.1556 +      // when reading by AT.
  1.1557 +      if (aContext->IsHTMLTableRow() || aContext->IsHTMLTable())
  1.1558 +        newAcc = new HTMLTableCellAccessibleWrap(aContent, document);
  1.1559 +      else
  1.1560 +        newAcc = new HyperTextAccessibleWrap(aContent, document);
  1.1561 +      break;
  1.1562 +
  1.1563 +    case eHTMLTableRowType: {
  1.1564 +      // Accessible HTML table row must be a child of tbody/tfoot/thead of
  1.1565 +      // accessible HTML table or must be a child of accessible of HTML table.
  1.1566 +      if (aContext->IsTable()) {
  1.1567 +        nsIContent* parentContent = aContent->GetParent();
  1.1568 +        nsIFrame* parentFrame = parentContent->GetPrimaryFrame();
  1.1569 +        if (parentFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
  1.1570 +          parentContent = parentContent->GetParent();
  1.1571 +          parentFrame = parentContent->GetPrimaryFrame();
  1.1572 +        }
  1.1573 +
  1.1574 +        if (parentFrame->GetType() == nsGkAtoms::tableOuterFrame &&
  1.1575 +            aContext->GetContent() == parentContent) {
  1.1576 +          newAcc = new HTMLTableRowAccessible(aContent, document);
  1.1577 +        }
  1.1578 +      }
  1.1579 +      break;
  1.1580 +    }
  1.1581 +    case eHTMLTextFieldType:
  1.1582 +      newAcc = new HTMLTextFieldAccessible(aContent, document);
  1.1583 +      break;
  1.1584 +    case eHyperTextType:
  1.1585 +      if (aContent->Tag() != nsGkAtoms::dt && aContent->Tag() != nsGkAtoms::dd)
  1.1586 +        newAcc = new HyperTextAccessibleWrap(aContent, document);
  1.1587 +      break;
  1.1588 +
  1.1589 +    case eImageType:
  1.1590 +      newAcc = new ImageAccessibleWrap(aContent, document);
  1.1591 +      break;
  1.1592 +    case eOuterDocType:
  1.1593 +      newAcc = new OuterDocAccessible(aContent, document);
  1.1594 +      break;
  1.1595 +    case ePluginType: {
  1.1596 +      nsObjectFrame* objectFrame = do_QueryFrame(aFrame);
  1.1597 +      newAcc = CreatePluginAccessible(objectFrame, aContent, aContext);
  1.1598 +      break;
  1.1599 +    }
  1.1600 +    case eTextLeafType:
  1.1601 +      newAcc = new TextLeafAccessibleWrap(aContent, document);
  1.1602 +      break;
  1.1603 +    default:
  1.1604 +      MOZ_ASSERT(false);
  1.1605 +      break;
  1.1606 +  }
  1.1607 +
  1.1608 +  return newAcc.forget();
  1.1609 +}
  1.1610 +
  1.1611 +////////////////////////////////////////////////////////////////////////////////
  1.1612 +// nsIAccessibilityService (DON'T put methods here)
  1.1613 +
  1.1614 +Accessible*
  1.1615 +nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
  1.1616 +{
  1.1617 +#ifdef MOZ_ACCESSIBILITY_ATK
  1.1618 +  ApplicationAccessible* applicationAcc = ApplicationAcc();
  1.1619 +  if (!applicationAcc)
  1.1620 +    return nullptr;
  1.1621 +
  1.1622 +  GtkWindowAccessible* nativeWnd =
  1.1623 +    new GtkWindowAccessible(static_cast<AtkObject*>(aAtkAccessible));
  1.1624 +
  1.1625 +  if (applicationAcc->AppendChild(nativeWnd))
  1.1626 +    return nativeWnd;
  1.1627 +#endif
  1.1628 +
  1.1629 +  return nullptr;
  1.1630 +}
  1.1631 +
  1.1632 +void
  1.1633 +nsAccessibilityService::RemoveNativeRootAccessible(Accessible* aAccessible)
  1.1634 +{
  1.1635 +#ifdef MOZ_ACCESSIBILITY_ATK
  1.1636 +  ApplicationAccessible* applicationAcc = ApplicationAcc();
  1.1637 +
  1.1638 +  if (applicationAcc)
  1.1639 +    applicationAcc->RemoveChild(aAccessible);
  1.1640 +#endif
  1.1641 +}
  1.1642 +
  1.1643 +////////////////////////////////////////////////////////////////////////////////
  1.1644 +// NS_GetAccessibilityService
  1.1645 +////////////////////////////////////////////////////////////////////////////////
  1.1646 +
  1.1647 +/**
  1.1648 + * Return accessibility service; creating one if necessary.
  1.1649 + */
  1.1650 +nsresult
  1.1651 +NS_GetAccessibilityService(nsIAccessibilityService** aResult)
  1.1652 +{
  1.1653 +  NS_ENSURE_TRUE(aResult, NS_ERROR_NULL_POINTER);
  1.1654 +  *aResult = nullptr;
  1.1655 + 
  1.1656 +  if (nsAccessibilityService::gAccessibilityService) {
  1.1657 +    NS_ADDREF(*aResult = nsAccessibilityService::gAccessibilityService);
  1.1658 +    return NS_OK;
  1.1659 +  }
  1.1660 +
  1.1661 +  nsRefPtr<nsAccessibilityService> service = new nsAccessibilityService();
  1.1662 +  NS_ENSURE_TRUE(service, NS_ERROR_OUT_OF_MEMORY);
  1.1663 +
  1.1664 +  if (!service->Init()) {
  1.1665 +    service->Shutdown();
  1.1666 +    return NS_ERROR_FAILURE;
  1.1667 +  }
  1.1668 +
  1.1669 +  statistics::A11yInitialized();
  1.1670 +
  1.1671 +  nsAccessibilityService::gAccessibilityService = service;
  1.1672 +  NS_ADDREF(*aResult = service);
  1.1673 +
  1.1674 +  return NS_OK;
  1.1675 +}
  1.1676 +
  1.1677 +////////////////////////////////////////////////////////////////////////////////
  1.1678 +// nsAccessibilityService private (DON'T put methods here)
  1.1679 +
  1.1680 +#ifdef MOZ_XUL
  1.1681 +already_AddRefed<Accessible>
  1.1682 +nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
  1.1683 +                                                   DocAccessible* aDoc)
  1.1684 +{
  1.1685 +  nsIContent* child = nsTreeUtils::GetDescendantChild(aContent,
  1.1686 +                                                      nsGkAtoms::treechildren);
  1.1687 +  if (!child)
  1.1688 +    return nullptr;
  1.1689 +
  1.1690 +  nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame());
  1.1691 +  if (!treeFrame)
  1.1692 +    return nullptr;
  1.1693 +
  1.1694 +  nsRefPtr<nsTreeColumns> treeCols = treeFrame->Columns();
  1.1695 +  int32_t count = 0;
  1.1696 +  treeCols->GetCount(&count);
  1.1697 +
  1.1698 +  // Outline of list accessible.
  1.1699 +  if (count == 1) {
  1.1700 +    nsRefPtr<Accessible> accessible =
  1.1701 +      new XULTreeAccessible(aContent, aDoc, treeFrame);
  1.1702 +    return accessible.forget();
  1.1703 +  }
  1.1704 +
  1.1705 +  // Table or tree table accessible.
  1.1706 +  nsRefPtr<Accessible> accessible =
  1.1707 +    new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame);
  1.1708 +  return accessible.forget();
  1.1709 +}
  1.1710 +#endif
  1.1711 +
  1.1712 +////////////////////////////////////////////////////////////////////////////////
  1.1713 +// Services
  1.1714 +////////////////////////////////////////////////////////////////////////////////
  1.1715 +
  1.1716 +namespace mozilla {
  1.1717 +namespace a11y {
  1.1718 +
  1.1719 +FocusManager*
  1.1720 +FocusMgr()
  1.1721 +{
  1.1722 +  return nsAccessibilityService::gAccessibilityService;
  1.1723 +}
  1.1724 +
  1.1725 +SelectionManager*
  1.1726 +SelectionMgr()
  1.1727 +{
  1.1728 +  return nsAccessibilityService::gAccessibilityService;
  1.1729 +}
  1.1730 +
  1.1731 +ApplicationAccessible*
  1.1732 +ApplicationAcc()
  1.1733 +{
  1.1734 +  return nsAccessibilityService::gApplicationAccessible;
  1.1735 +}
  1.1736 +
  1.1737 +EPlatformDisabledState
  1.1738 +PlatformDisabledState()
  1.1739 +{
  1.1740 +  static int disabledState = 0xff;
  1.1741 +
  1.1742 +  if (disabledState == 0xff) {
  1.1743 +    disabledState = Preferences::GetInt("accessibility.force_disabled", 0);
  1.1744 +    if (disabledState < ePlatformIsForceEnabled)
  1.1745 +      disabledState = ePlatformIsForceEnabled;
  1.1746 +    else if (disabledState > ePlatformIsDisabled)
  1.1747 +      disabledState = ePlatformIsDisabled;
  1.1748 +  }
  1.1749 +
  1.1750 +  return (EPlatformDisabledState)disabledState;
  1.1751 +}
  1.1752 +
  1.1753 +}
  1.1754 +}

mercurial