LCOV - code coverage report
Current view: top level - accessible/base - nsAccessibilityService.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 6 847 0.7 %
Date: 2017-07-14 16:53:18 Functions: 1 66 1.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "nsAccessibilityService.h"
       7             : 
       8             : // NOTE: alphabetically ordered
       9             : #include "ApplicationAccessibleWrap.h"
      10             : #include "ARIAGridAccessibleWrap.h"
      11             : #include "ARIAMap.h"
      12             : #include "DocAccessible-inl.h"
      13             : #include "FocusManager.h"
      14             : #include "HTMLCanvasAccessible.h"
      15             : #include "HTMLElementAccessibles.h"
      16             : #include "HTMLImageMapAccessible.h"
      17             : #include "HTMLLinkAccessible.h"
      18             : #include "HTMLListAccessible.h"
      19             : #include "HTMLSelectAccessible.h"
      20             : #include "HTMLTableAccessibleWrap.h"
      21             : #include "HyperTextAccessibleWrap.h"
      22             : #include "RootAccessible.h"
      23             : #include "nsAccUtils.h"
      24             : #include "nsArrayUtils.h"
      25             : #include "nsAttrName.h"
      26             : #include "nsEventShell.h"
      27             : #include "nsIURI.h"
      28             : #include "OuterDocAccessible.h"
      29             : #include "Platform.h"
      30             : #include "Role.h"
      31             : #ifdef MOZ_ACCESSIBILITY_ATK
      32             : #include "RootAccessibleWrap.h"
      33             : #endif
      34             : #include "States.h"
      35             : #include "Statistics.h"
      36             : #include "TextLeafAccessibleWrap.h"
      37             : #include "TreeWalker.h"
      38             : #include "xpcAccessibleApplication.h"
      39             : #include "xpcAccessibleDocument.h"
      40             : 
      41             : #ifdef MOZ_ACCESSIBILITY_ATK
      42             : #include "AtkSocketAccessible.h"
      43             : #endif
      44             : 
      45             : #ifdef XP_WIN
      46             : #include "mozilla/a11y/Compatibility.h"
      47             : #include "mozilla/dom/ContentChild.h"
      48             : #include "HTMLWin32ObjectAccessible.h"
      49             : #include "mozilla/StaticPtr.h"
      50             : #endif
      51             : 
      52             : #ifdef A11Y_LOG
      53             : #include "Logging.h"
      54             : #endif
      55             : 
      56             : #ifdef MOZ_CRASHREPORTER
      57             : #include "nsExceptionHandler.h"
      58             : #endif
      59             : 
      60             : #include "nsImageFrame.h"
      61             : #include "nsIObserverService.h"
      62             : #include "nsLayoutUtils.h"
      63             : #include "nsPluginFrame.h"
      64             : #include "SVGGeometryFrame.h"
      65             : #include "nsTreeBodyFrame.h"
      66             : #include "nsTreeColumns.h"
      67             : #include "nsTreeUtils.h"
      68             : #include "nsXBLPrototypeBinding.h"
      69             : #include "nsXBLBinding.h"
      70             : #include "mozilla/ArrayUtils.h"
      71             : #include "mozilla/dom/DOMStringList.h"
      72             : #include "mozilla/Preferences.h"
      73             : #include "mozilla/Services.h"
      74             : #include "nsDeckFrame.h"
      75             : 
      76             : #ifdef MOZ_XUL
      77             : #include "XULAlertAccessible.h"
      78             : #include "XULColorPickerAccessible.h"
      79             : #include "XULComboboxAccessible.h"
      80             : #include "XULElementAccessibles.h"
      81             : #include "XULFormControlAccessible.h"
      82             : #include "XULListboxAccessibleWrap.h"
      83             : #include "XULMenuAccessibleWrap.h"
      84             : #include "XULSliderAccessible.h"
      85             : #include "XULTabAccessible.h"
      86             : #include "XULTreeGridAccessibleWrap.h"
      87             : #endif
      88             : 
      89             : #if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
      90             : #include "nsNPAPIPluginInstance.h"
      91             : #endif
      92             : 
      93             : using namespace mozilla;
      94             : using namespace mozilla::a11y;
      95             : using namespace mozilla::dom;
      96             : 
      97             : ////////////////////////////////////////////////////////////////////////////////
      98             : // Statics
      99             : ////////////////////////////////////////////////////////////////////////////////
     100             : 
     101             : /**
     102             :  * Return true if the element must be accessible.
     103             :  */
     104             : static bool
     105           0 : MustBeAccessible(nsIContent* aContent, DocAccessible* aDocument)
     106             : {
     107           0 :   if (aContent->GetPrimaryFrame()->IsFocusable())
     108           0 :     return true;
     109             : 
     110           0 :   uint32_t attrCount = aContent->GetAttrCount();
     111           0 :   for (uint32_t attrIdx = 0; attrIdx < attrCount; attrIdx++) {
     112           0 :     const nsAttrName* attr = aContent->GetAttrNameAt(attrIdx);
     113           0 :     if (attr->NamespaceEquals(kNameSpaceID_None)) {
     114           0 :       nsIAtom* attrAtom = attr->Atom();
     115           0 :       nsDependentAtomString attrStr(attrAtom);
     116           0 :       if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-")))
     117           0 :         continue; // not ARIA
     118             : 
     119             :       // A global state or a property and in case of token defined.
     120           0 :       uint8_t attrFlags = aria::AttrCharacteristicsFor(attrAtom);
     121           0 :       if ((attrFlags & ATTR_GLOBAL) && (!(attrFlags & ATTR_VALTOKEN) ||
     122           0 :            nsAccUtils::HasDefinedARIAToken(aContent, attrAtom))) {
     123           0 :         return true;
     124             :       }
     125             :     }
     126             :   }
     127             : 
     128             :   // If the given ID is referred by relation attribute then create an accessible
     129             :   // for it.
     130           0 :   nsAutoString id;
     131           0 :   if (nsCoreUtils::GetID(aContent, id) && !id.IsEmpty())
     132           0 :     return aDocument->IsDependentID(id);
     133             : 
     134           0 :   return false;
     135             : }
     136             : 
     137             : ////////////////////////////////////////////////////////////////////////////////
     138             : // Accessible constructors
     139             : 
     140             : static Accessible*
     141           0 : New_HTMLLink(nsIContent* aContent, Accessible* aContext)
     142             : {
     143             :   // Only some roles truly enjoy life as HTMLLinkAccessibles, for details
     144             :   // see closed bug 494807.
     145           0 :   const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(aContent->AsElement());
     146           0 :   if (roleMapEntry && roleMapEntry->role != roles::NOTHING &&
     147           0 :       roleMapEntry->role != roles::LINK) {
     148           0 :     return new HyperTextAccessibleWrap(aContent, aContext->Document());
     149             :   }
     150             : 
     151           0 :   return new HTMLLinkAccessible(aContent, aContext->Document());
     152             : }
     153             : 
     154           0 : static Accessible* New_HyperText(nsIContent* aContent, Accessible* aContext)
     155           0 :   { return new HyperTextAccessibleWrap(aContent, aContext->Document()); }
     156             : 
     157           0 : static Accessible* New_HTMLFigcaption(nsIContent* aContent, Accessible* aContext)
     158           0 :   { return new HTMLFigcaptionAccessible(aContent, aContext->Document()); }
     159             : 
     160           0 : static Accessible* New_HTMLFigure(nsIContent* aContent, Accessible* aContext)
     161           0 :   { return new HTMLFigureAccessible(aContent, aContext->Document()); }
     162             : 
     163           0 : static Accessible* New_HTMLLegend(nsIContent* aContent, Accessible* aContext)
     164           0 :   { return new HTMLLegendAccessible(aContent, aContext->Document()); }
     165             : 
     166           0 : static Accessible* New_HTMLOption(nsIContent* aContent, Accessible* aContext)
     167           0 :   { return new HTMLSelectOptionAccessible(aContent, aContext->Document()); }
     168             : 
     169           0 : static Accessible* New_HTMLOptgroup(nsIContent* aContent, Accessible* aContext)
     170           0 :   { return new HTMLSelectOptGroupAccessible(aContent, aContext->Document()); }
     171             : 
     172           0 : static Accessible* New_HTMLList(nsIContent* aContent, Accessible* aContext)
     173           0 :   { return new HTMLListAccessible(aContent, aContext->Document()); }
     174             : 
     175             : static Accessible*
     176           0 : New_HTMLListitem(nsIContent* aContent, Accessible* aContext)
     177             : {
     178             :   // If list item is a child of accessible list then create an accessible for
     179             :   // it unconditionally by tag name. nsBlockFrame creates the list item
     180             :   // accessible for other elements styled as list items.
     181           0 :   if (aContext->IsList() && aContext->GetContent() == aContent->GetParent())
     182           0 :     return new HTMLLIAccessible(aContent, aContext->Document());
     183             : 
     184           0 :   return nullptr;
     185             : }
     186             : 
     187             : static Accessible*
     188           0 : New_HTMLDefinition(nsIContent* aContent, Accessible* aContext)
     189             : {
     190           0 :   if (aContext->IsList())
     191           0 :     return new HyperTextAccessibleWrap(aContent, aContext->Document());
     192           0 :   return nullptr;
     193             : }
     194             : 
     195           0 : static Accessible* New_HTMLLabel(nsIContent* aContent, Accessible* aContext)
     196           0 :   { return new HTMLLabelAccessible(aContent, aContext->Document()); }
     197             : 
     198           0 : static Accessible* New_HTMLInput(nsIContent* aContent, Accessible* aContext)
     199             : {
     200           0 :   if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
     201             :                             nsGkAtoms::checkbox, eIgnoreCase)) {
     202           0 :     return new HTMLCheckboxAccessible(aContent, aContext->Document());
     203             :   }
     204           0 :   if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
     205             :                             nsGkAtoms::radio, eIgnoreCase)) {
     206           0 :     return new HTMLRadioButtonAccessible(aContent, aContext->Document());
     207             :   }
     208           0 :   return nullptr;
     209             : }
     210             : 
     211           0 : static Accessible* New_HTMLOutput(nsIContent* aContent, Accessible* aContext)
     212           0 :   { return new HTMLOutputAccessible(aContent, aContext->Document()); }
     213             : 
     214           0 : static Accessible* New_HTMLProgress(nsIContent* aContent, Accessible* aContext)
     215           0 :   { return new HTMLProgressMeterAccessible(aContent, aContext->Document()); }
     216             : 
     217           0 : static Accessible* New_HTMLSummary(nsIContent* aContent, Accessible* aContext)
     218           0 :   { return new HTMLSummaryAccessible(aContent, aContext->Document()); }
     219             : 
     220             : static Accessible*
     221           0 : New_HTMLTableAccessible(nsIContent* aContent, Accessible* aContext)
     222           0 :   { return new HTMLTableAccessible(aContent, aContext->Document()); }
     223             : 
     224             : static Accessible*
     225           0 : New_HTMLTableRowAccessible(nsIContent* aContent, Accessible* aContext)
     226           0 :   { return new HTMLTableRowAccessible(aContent, aContext->Document()); }
     227             : 
     228             : static Accessible*
     229           0 : New_HTMLTableCellAccessible(nsIContent* aContent, Accessible* aContext)
     230           0 :   { return new HTMLTableCellAccessible(aContent, aContext->Document()); }
     231             : 
     232             : static Accessible*
     233           0 : New_HTMLTableHeaderCell(nsIContent* aContent, Accessible* aContext)
     234             : {
     235           0 :   if (aContext->IsTableRow() && aContext->GetContent() == aContent->GetParent())
     236           0 :     return new HTMLTableHeaderCellAccessibleWrap(aContent, aContext->Document());
     237           0 :   return nullptr;
     238             : }
     239             : 
     240             : static Accessible*
     241           0 : New_HTMLTableHeaderCellIfScope(nsIContent* aContent, Accessible* aContext)
     242             : {
     243           0 :   if (aContext->IsTableRow() && aContext->GetContent() == aContent->GetParent() &&
     244           0 :       aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::scope))
     245           0 :     return new HTMLTableHeaderCellAccessibleWrap(aContent, aContext->Document());
     246           0 :   return nullptr;
     247             : }
     248             : 
     249             : ////////////////////////////////////////////////////////////////////////////////
     250             : // Markup maps array.
     251             : 
     252             : #define Attr(name, value) \
     253             :   { &nsGkAtoms::name, &nsGkAtoms::value }
     254             : 
     255             : #define AttrFromDOM(name, DOMAttrName) \
     256             :   { &nsGkAtoms::name, nullptr, &nsGkAtoms::DOMAttrName }
     257             : 
     258             : #define AttrFromDOMIf(name, DOMAttrName, DOMAttrValue) \
     259             :   { &nsGkAtoms::name, nullptr,  &nsGkAtoms::DOMAttrName, &nsGkAtoms::DOMAttrValue }
     260             : 
     261             : #define MARKUPMAP(atom, new_func, r, ... ) \
     262             :   { &nsGkAtoms::atom, new_func, static_cast<a11y::role>(r), { __VA_ARGS__ } },
     263             : 
     264             : static const MarkupMapInfo sMarkupMapList[] = {
     265             :   #include "MarkupMap.h"
     266             : };
     267             : 
     268             : #undef Attr
     269             : #undef AttrFromDOM
     270             : #undef AttrFromDOMIf
     271             : #undef MARKUPMAP
     272             : 
     273             : ////////////////////////////////////////////////////////////////////////////////
     274             : // nsAccessibilityService
     275             : ////////////////////////////////////////////////////////////////////////////////
     276             : 
     277             : nsAccessibilityService *nsAccessibilityService::gAccessibilityService = nullptr;
     278             : ApplicationAccessible* nsAccessibilityService::gApplicationAccessible = nullptr;
     279             : xpcAccessibleApplication* nsAccessibilityService::gXPCApplicationAccessible = nullptr;
     280             : uint32_t nsAccessibilityService::gConsumers = 0;
     281             : 
     282           0 : nsAccessibilityService::nsAccessibilityService() :
     283           0 :   DocManager(), FocusManager(), mMarkupMaps(ArrayLength(sMarkupMapList))
     284             : {
     285           0 : }
     286             : 
     287           0 : nsAccessibilityService::~nsAccessibilityService()
     288             : {
     289           0 :   NS_ASSERTION(IsShutdown(), "Accessibility wasn't shutdown!");
     290           0 :   gAccessibilityService = nullptr;
     291           0 : }
     292             : 
     293             : ////////////////////////////////////////////////////////////////////////////////
     294             : // nsIListenerChangeListener
     295             : 
     296             : NS_IMETHODIMP
     297           0 : nsAccessibilityService::ListenersChanged(nsIArray* aEventChanges)
     298             : {
     299             :   uint32_t targetCount;
     300           0 :   nsresult rv = aEventChanges->GetLength(&targetCount);
     301           0 :   NS_ENSURE_SUCCESS(rv, rv);
     302             : 
     303           0 :   for (uint32_t i = 0 ; i < targetCount ; i++) {
     304           0 :     nsCOMPtr<nsIEventListenerChange> change = do_QueryElementAt(aEventChanges, i);
     305             : 
     306           0 :     nsCOMPtr<nsIDOMEventTarget> target;
     307           0 :     change->GetTarget(getter_AddRefs(target));
     308           0 :     nsCOMPtr<nsIContent> node(do_QueryInterface(target));
     309           0 :     if (!node || !node->IsHTMLElement()) {
     310           0 :       continue;
     311             :     }
     312           0 :     nsCOMPtr<nsIArray> listenerNames;
     313           0 :     change->GetChangedListenerNames(getter_AddRefs(listenerNames));
     314             : 
     315             :     uint32_t changeCount;
     316           0 :     rv = listenerNames->GetLength(&changeCount);
     317           0 :     NS_ENSURE_SUCCESS(rv, rv);
     318             : 
     319           0 :     for (uint32_t i = 0 ; i < changeCount ; i++) {
     320           0 :       nsCOMPtr<nsIAtom> listenerName = do_QueryElementAt(listenerNames, i);
     321             : 
     322             :       // We are only interested in event listener changes which may
     323             :       // make an element accessible or inaccessible.
     324           0 :       if (listenerName != nsGkAtoms::onclick &&
     325           0 :           listenerName != nsGkAtoms::onmousedown &&
     326           0 :           listenerName != nsGkAtoms::onmouseup) {
     327           0 :         continue;
     328             :       }
     329             : 
     330           0 :       nsIDocument* ownerDoc = node->OwnerDoc();
     331           0 :       DocAccessible* document = GetExistingDocAccessible(ownerDoc);
     332             : 
     333             :       // Create an accessible for a inaccessible element having click event
     334             :       // handler.
     335           0 :       if (document && !document->HasAccessible(node) &&
     336           0 :           nsCoreUtils::HasClickListener(node)) {
     337           0 :         nsIContent* parentEl = node->GetFlattenedTreeParent();
     338           0 :         if (parentEl) {
     339           0 :           document->ContentInserted(parentEl, node, node->GetNextSibling());
     340             :         }
     341           0 :         break;
     342             :       }
     343             :     }
     344             :   }
     345           0 :   return NS_OK;
     346             : }
     347             : 
     348             : ////////////////////////////////////////////////////////////////////////////////
     349             : // nsISupports
     350             : 
     351           0 : NS_IMPL_ISUPPORTS_INHERITED(nsAccessibilityService,
     352             :                             DocManager,
     353             :                             nsIObserver,
     354             :                             nsIListenerChangeListener,
     355             :                             nsISelectionListener) // from SelectionManager
     356             : 
     357             : ////////////////////////////////////////////////////////////////////////////////
     358             : // nsIObserver
     359             : 
     360             : NS_IMETHODIMP
     361           0 : nsAccessibilityService::Observe(nsISupports *aSubject, const char *aTopic,
     362             :                          const char16_t *aData)
     363             : {
     364           0 :   if (!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID))
     365           0 :     Shutdown();
     366             : 
     367           0 :   return NS_OK;
     368             : }
     369             : 
     370             : void
     371           0 : nsAccessibilityService::NotifyOfAnchorJumpTo(nsIContent* aTargetNode)
     372             : {
     373           0 :   nsIDocument* documentNode = aTargetNode->GetUncomposedDoc();
     374           0 :   if (documentNode) {
     375           0 :     DocAccessible* document = GetDocAccessible(documentNode);
     376           0 :     if (document)
     377           0 :       document->SetAnchorJump(aTargetNode);
     378             :   }
     379           0 : }
     380             : 
     381             : void
     382           0 : nsAccessibilityService::FireAccessibleEvent(uint32_t aEvent,
     383             :                                             Accessible* aTarget)
     384             : {
     385           0 :   nsEventShell::FireEvent(aEvent, aTarget);
     386           0 : }
     387             : 
     388             : Accessible*
     389           0 : nsAccessibilityService::GetRootDocumentAccessible(nsIPresShell* aPresShell,
     390             :                                                   bool aCanCreate)
     391             : {
     392           0 :   nsIPresShell* ps = aPresShell;
     393           0 :   nsIDocument* documentNode = aPresShell->GetDocument();
     394           0 :   if (documentNode) {
     395           0 :     nsCOMPtr<nsIDocShellTreeItem> treeItem(documentNode->GetDocShell());
     396           0 :     if (treeItem) {
     397           0 :       nsCOMPtr<nsIDocShellTreeItem> rootTreeItem;
     398           0 :       treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem));
     399           0 :       if (treeItem != rootTreeItem) {
     400           0 :         nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(rootTreeItem));
     401           0 :         ps = docShell->GetPresShell();
     402             :       }
     403             : 
     404           0 :       return aCanCreate ? GetDocAccessible(ps) : ps->GetDocAccessible();
     405             :     }
     406             :   }
     407           0 :   return nullptr;
     408             : }
     409             : 
     410             : #ifdef XP_WIN
     411             : static StaticAutoPtr<nsTArray<nsCOMPtr<nsIContent> > > sPendingPlugins;
     412             : static StaticAutoPtr<nsTArray<nsCOMPtr<nsITimer> > > sPluginTimers;
     413             : 
     414             : class PluginTimerCallBack final : public nsITimerCallback
     415             : {
     416             :   ~PluginTimerCallBack() {}
     417             : 
     418             : public:
     419             :   explicit PluginTimerCallBack(nsIContent* aContent) : mContent(aContent) {}
     420             : 
     421             :   NS_DECL_ISUPPORTS
     422             : 
     423             :   NS_IMETHOD Notify(nsITimer* aTimer) final
     424             :   {
     425             :     if (!mContent->IsInUncomposedDoc())
     426             :       return NS_OK;
     427             : 
     428             :     nsIPresShell* ps = mContent->OwnerDoc()->GetShell();
     429             :     if (ps) {
     430             :       DocAccessible* doc = ps->GetDocAccessible();
     431             :       if (doc) {
     432             :         // Make sure that if we created an accessible for the plugin that wasn't
     433             :         // a plugin accessible we remove it before creating the right accessible.
     434             :         doc->RecreateAccessible(mContent);
     435             :         sPluginTimers->RemoveElement(aTimer);
     436             :         return NS_OK;
     437             :       }
     438             :     }
     439             : 
     440             :     // We couldn't get a doc accessible so presumably the document went away.
     441             :     // In this case don't leak our ref to the content or timer.
     442             :     sPendingPlugins->RemoveElement(mContent);
     443             :     sPluginTimers->RemoveElement(aTimer);
     444             :     return NS_OK;
     445             :   }
     446             : 
     447             : private:
     448             :   nsCOMPtr<nsIContent> mContent;
     449             : };
     450             : 
     451             : NS_IMPL_ISUPPORTS(PluginTimerCallBack, nsITimerCallback)
     452             : #endif
     453             : 
     454             : already_AddRefed<Accessible>
     455           0 : nsAccessibilityService::CreatePluginAccessible(nsPluginFrame* aFrame,
     456             :                                                nsIContent* aContent,
     457             :                                                Accessible* aContext)
     458             : {
     459             :   // nsPluginFrame means a plugin, so we need to use the accessibility support
     460             :   // of the plugin.
     461           0 :   if (aFrame->GetRect().IsEmpty())
     462           0 :     return nullptr;
     463             : 
     464             : #if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
     465           0 :   RefPtr<nsNPAPIPluginInstance> pluginInstance;
     466           0 :   if (NS_SUCCEEDED(aFrame->GetPluginInstance(getter_AddRefs(pluginInstance))) &&
     467           0 :       pluginInstance) {
     468             : #ifdef XP_WIN
     469             :     if (!sPendingPlugins->Contains(aContent) &&
     470             :         (Preferences::GetBool("accessibility.delay_plugins") ||
     471             :          Compatibility::IsJAWS() || Compatibility::IsWE())) {
     472             :       nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
     473             :       RefPtr<PluginTimerCallBack> cb = new PluginTimerCallBack(aContent);
     474             :       timer->InitWithCallback(cb, Preferences::GetUint("accessibility.delay_plugin_time"),
     475             :                               nsITimer::TYPE_ONE_SHOT);
     476             :       sPluginTimers->AppendElement(timer);
     477             :       sPendingPlugins->AppendElement(aContent);
     478             :       return nullptr;
     479             :     }
     480             : 
     481             :     // We need to remove aContent from the pending plugins here to avoid
     482             :     // reentrancy.  When the timer fires it calls
     483             :     // DocAccessible::ContentInserted() which does the work async.
     484             :     sPendingPlugins->RemoveElement(aContent);
     485             : 
     486             :     // Note: pluginPort will be null if windowless.
     487             :     HWND pluginPort = nullptr;
     488             :     aFrame->GetPluginPort(&pluginPort);
     489             : 
     490             :     RefPtr<Accessible> accessible =
     491             :       new HTMLWin32ObjectOwnerAccessible(aContent, aContext->Document(),
     492             :                                          pluginPort);
     493             :     return accessible.forget();
     494             : 
     495             : #elif MOZ_ACCESSIBILITY_ATK
     496           0 :     if (!AtkSocketAccessible::gCanEmbed)
     497           0 :       return nullptr;
     498             : 
     499             :     // Note this calls into the plugin, so crazy things may happen and aFrame
     500             :     // may go away.
     501           0 :     nsCString plugId;
     502           0 :     nsresult rv = pluginInstance->GetValueFromPlugin(
     503           0 :       NPPVpluginNativeAccessibleAtkPlugId, &plugId);
     504           0 :     if (NS_SUCCEEDED(rv) && !plugId.IsEmpty()) {
     505             :       RefPtr<AtkSocketAccessible> socketAccessible =
     506           0 :         new AtkSocketAccessible(aContent, aContext->Document(), plugId);
     507             : 
     508           0 :       return socketAccessible.forget();
     509             :     }
     510             : #endif
     511             :   }
     512             : #endif
     513             : 
     514           0 :   return nullptr;
     515             : }
     516             : 
     517             : void
     518           0 : nsAccessibilityService::DeckPanelSwitched(nsIPresShell* aPresShell,
     519             :                                           nsIContent* aDeckNode,
     520             :                                           nsIFrame* aPrevBoxFrame,
     521             :                                           nsIFrame* aCurrentBoxFrame)
     522             : {
     523             :   // Ignore tabpanels elements (a deck having an accessible) since their
     524             :   // children are accessible not depending on selected tab.
     525           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     526           0 :   if (!document || document->HasAccessible(aDeckNode))
     527           0 :     return;
     528             : 
     529           0 :   if (aPrevBoxFrame) {
     530           0 :     nsIContent* panelNode = aPrevBoxFrame->GetContent();
     531             : #ifdef A11Y_LOG
     532           0 :     if (logging::IsEnabled(logging::eTree)) {
     533           0 :       logging::MsgBegin("TREE", "deck panel unselected");
     534           0 :       logging::Node("container", panelNode);
     535           0 :       logging::Node("content", aDeckNode);
     536           0 :       logging::MsgEnd();
     537             :     }
     538             : #endif
     539             : 
     540           0 :     document->ContentRemoved(panelNode);
     541             :   }
     542             : 
     543           0 :   if (aCurrentBoxFrame) {
     544           0 :     nsIContent* panelNode = aCurrentBoxFrame->GetContent();
     545             : #ifdef A11Y_LOG
     546           0 :     if (logging::IsEnabled(logging::eTree)) {
     547           0 :       logging::MsgBegin("TREE", "deck panel selected");
     548           0 :       logging::Node("container", panelNode);
     549           0 :       logging::Node("content", aDeckNode);
     550           0 :       logging::MsgEnd();
     551             :     }
     552             : #endif
     553             : 
     554           0 :     document->ContentInserted(aDeckNode, panelNode, panelNode->GetNextSibling());
     555             :   }
     556             : }
     557             : 
     558             : void
     559           0 : nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
     560             :                                              nsIContent* aContainer,
     561             :                                              nsIContent* aStartChild,
     562             :                                              nsIContent* aEndChild)
     563             : {
     564           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     565             : #ifdef A11Y_LOG
     566           0 :   if (logging::IsEnabled(logging::eTree)) {
     567           0 :     logging::MsgBegin("TREE", "content inserted; doc: %p", document);
     568           0 :     logging::Node("container", aContainer);
     569           0 :     for (nsIContent* child = aStartChild; child != aEndChild;
     570           0 :          child = child->GetNextSibling()) {
     571           0 :       logging::Node("content", child);
     572             :     }
     573           0 :     logging::MsgEnd();
     574           0 :     logging::Stack();
     575             :   }
     576             : #endif
     577             : 
     578           0 :   if (document) {
     579           0 :     document->ContentInserted(aContainer, aStartChild, aEndChild);
     580             :   }
     581           0 : }
     582             : 
     583             : void
     584           0 : nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
     585             :                                        nsIContent* aChildNode)
     586             : {
     587           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     588             : #ifdef A11Y_LOG
     589           0 :   if (logging::IsEnabled(logging::eTree)) {
     590           0 :     logging::MsgBegin("TREE", "content removed; doc: %p", document);
     591           0 :     logging::Node("container node", aChildNode->GetFlattenedTreeParent());
     592           0 :     logging::Node("content node", aChildNode);
     593           0 :     logging::MsgEnd();
     594             :   }
     595             : #endif
     596             : 
     597           0 :   if (document) {
     598           0 :     document->ContentRemoved(aChildNode);
     599             :   }
     600             : 
     601             : #ifdef A11Y_LOG
     602           0 :   if (logging::IsEnabled(logging::eTree)) {
     603           0 :     logging::MsgEnd();
     604           0 :     logging::Stack();
     605             :   }
     606             : #endif
     607           0 : }
     608             : 
     609             : void
     610           0 : nsAccessibilityService::UpdateText(nsIPresShell* aPresShell,
     611             :                                    nsIContent* aContent)
     612             : {
     613           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     614           0 :   if (document)
     615           0 :     document->UpdateText(aContent);
     616           0 : }
     617             : 
     618             : void
     619           0 : nsAccessibilityService::TreeViewChanged(nsIPresShell* aPresShell,
     620             :                                         nsIContent* aContent,
     621             :                                         nsITreeView* aView)
     622             : {
     623           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     624           0 :   if (document) {
     625           0 :     Accessible* accessible = document->GetAccessible(aContent);
     626           0 :     if (accessible) {
     627           0 :       XULTreeAccessible* treeAcc = accessible->AsXULTree();
     628           0 :       if (treeAcc)
     629           0 :         treeAcc->TreeViewChanged(aView);
     630             :     }
     631             :   }
     632           0 : }
     633             : 
     634             : void
     635           0 : nsAccessibilityService::RangeValueChanged(nsIPresShell* aPresShell,
     636             :                                           nsIContent* aContent)
     637             : {
     638           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     639           0 :   if (document) {
     640           0 :     Accessible* accessible = document->GetAccessible(aContent);
     641           0 :     if (accessible) {
     642             :       document->FireDelayedEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE,
     643           0 :                                  accessible);
     644             :     }
     645             :   }
     646           0 : }
     647             : 
     648             : void
     649           0 : nsAccessibilityService::UpdateListBullet(nsIPresShell* aPresShell,
     650             :                                          nsIContent* aHTMLListItemContent,
     651             :                                          bool aHasBullet)
     652             : {
     653           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     654           0 :   if (document) {
     655           0 :     Accessible* accessible = document->GetAccessible(aHTMLListItemContent);
     656           0 :     if (accessible) {
     657           0 :       HTMLLIAccessible* listItem = accessible->AsHTMLListItem();
     658           0 :       if (listItem)
     659           0 :         listItem->UpdateBullet(aHasBullet);
     660             :     }
     661             :   }
     662           0 : }
     663             : 
     664             : void
     665           0 : nsAccessibilityService::UpdateImageMap(nsImageFrame* aImageFrame)
     666             : {
     667           0 :   nsIPresShell* presShell = aImageFrame->PresContext()->PresShell();
     668           0 :   DocAccessible* document = GetDocAccessible(presShell);
     669           0 :   if (document) {
     670             :     Accessible* accessible =
     671           0 :       document->GetAccessible(aImageFrame->GetContent());
     672           0 :     if (accessible) {
     673           0 :       HTMLImageMapAccessible* imageMap = accessible->AsImageMap();
     674           0 :       if (imageMap) {
     675           0 :         imageMap->UpdateChildAreas();
     676           0 :         return;
     677             :       }
     678             : 
     679             :       // If image map was initialized after we created an accessible (that'll
     680             :       // be an image accessible) then recreate it.
     681           0 :       RecreateAccessible(presShell, aImageFrame->GetContent());
     682             :     }
     683             :   }
     684             : }
     685             : 
     686             : void
     687           0 : nsAccessibilityService::UpdateLabelValue(nsIPresShell* aPresShell,
     688             :                                          nsIContent* aLabelElm,
     689             :                                          const nsString& aNewValue)
     690             : {
     691           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     692           0 :   if (document) {
     693           0 :     Accessible* accessible = document->GetAccessible(aLabelElm);
     694           0 :     if (accessible) {
     695           0 :       XULLabelAccessible* xulLabel = accessible->AsXULLabel();
     696           0 :       NS_ASSERTION(xulLabel,
     697             :                    "UpdateLabelValue was called for wrong accessible!");
     698           0 :       if (xulLabel)
     699           0 :         xulLabel->UpdateLabelValue(aNewValue);
     700             :     }
     701             :   }
     702           0 : }
     703             : 
     704             : void
     705           0 : nsAccessibilityService::PresShellActivated(nsIPresShell* aPresShell)
     706             : {
     707           0 :   DocAccessible* document = aPresShell->GetDocAccessible();
     708           0 :   if (document) {
     709           0 :     RootAccessible* rootDocument = document->RootAccessible();
     710           0 :     NS_ASSERTION(rootDocument, "Entirely broken tree: no root document!");
     711           0 :     if (rootDocument)
     712           0 :       rootDocument->DocumentActivated(document);
     713             :   }
     714           0 : }
     715             : 
     716             : void
     717           0 : nsAccessibilityService::RecreateAccessible(nsIPresShell* aPresShell,
     718             :                                            nsIContent* aContent)
     719             : {
     720           0 :   DocAccessible* document = GetDocAccessible(aPresShell);
     721           0 :   if (document)
     722           0 :     document->RecreateAccessible(aContent);
     723           0 : }
     724             : 
     725             : void
     726           0 : nsAccessibilityService::GetStringRole(uint32_t aRole, nsAString& aString)
     727             : {
     728             : #define ROLE(geckoRole, stringRole, atkRole, \
     729             :              macRole, msaaRole, ia2Role, nameRule) \
     730             :   case roles::geckoRole: \
     731             :     CopyUTF8toUTF16(stringRole, aString); \
     732             :     return;
     733             : 
     734           0 :   switch (aRole) {
     735             : #include "RoleMap.h"
     736             :     default:
     737           0 :       aString.AssignLiteral("unknown");
     738           0 :       return;
     739             :   }
     740             : 
     741             : #undef ROLE
     742             : }
     743             : 
     744             : void
     745           0 : nsAccessibilityService::GetStringStates(uint32_t aState, uint32_t aExtraState,
     746             :                                         nsISupports** aStringStates)
     747             : {
     748             :   RefPtr<DOMStringList> stringStates =
     749           0 :     GetStringStates(nsAccUtils::To64State(aState, aExtraState));
     750             : 
     751             :   // unknown state
     752           0 :   if (!stringStates->Length()) {
     753           0 :     stringStates->Add(NS_LITERAL_STRING("unknown"));
     754             :   }
     755             : 
     756           0 :   stringStates.forget(aStringStates);
     757           0 : }
     758             : 
     759             : already_AddRefed<DOMStringList>
     760           0 : nsAccessibilityService::GetStringStates(uint64_t aStates) const
     761             : {
     762           0 :   RefPtr<DOMStringList> stringStates = new DOMStringList();
     763             : 
     764           0 :   if (aStates & states::UNAVAILABLE) {
     765           0 :     stringStates->Add(NS_LITERAL_STRING("unavailable"));
     766             :   }
     767           0 :   if (aStates & states::SELECTED) {
     768           0 :     stringStates->Add(NS_LITERAL_STRING("selected"));
     769             :   }
     770           0 :   if (aStates & states::FOCUSED) {
     771           0 :     stringStates->Add(NS_LITERAL_STRING("focused"));
     772             :   }
     773           0 :   if (aStates & states::PRESSED) {
     774           0 :     stringStates->Add(NS_LITERAL_STRING("pressed"));
     775             :   }
     776           0 :   if (aStates & states::CHECKED) {
     777           0 :     stringStates->Add(NS_LITERAL_STRING("checked"));
     778             :   }
     779           0 :   if (aStates & states::MIXED) {
     780           0 :     stringStates->Add(NS_LITERAL_STRING("mixed"));
     781             :   }
     782           0 :   if (aStates & states::READONLY) {
     783           0 :     stringStates->Add(NS_LITERAL_STRING("readonly"));
     784             :   }
     785           0 :   if (aStates & states::HOTTRACKED) {
     786           0 :     stringStates->Add(NS_LITERAL_STRING("hottracked"));
     787             :   }
     788           0 :   if (aStates & states::DEFAULT) {
     789           0 :     stringStates->Add(NS_LITERAL_STRING("default"));
     790             :   }
     791           0 :   if (aStates & states::EXPANDED) {
     792           0 :     stringStates->Add(NS_LITERAL_STRING("expanded"));
     793             :   }
     794           0 :   if (aStates & states::COLLAPSED) {
     795           0 :     stringStates->Add(NS_LITERAL_STRING("collapsed"));
     796             :   }
     797           0 :   if (aStates & states::BUSY) {
     798           0 :     stringStates->Add(NS_LITERAL_STRING("busy"));
     799             :   }
     800           0 :   if (aStates & states::FLOATING) {
     801           0 :     stringStates->Add(NS_LITERAL_STRING("floating"));
     802             :   }
     803           0 :   if (aStates & states::ANIMATED) {
     804           0 :     stringStates->Add(NS_LITERAL_STRING("animated"));
     805             :   }
     806           0 :   if (aStates & states::INVISIBLE) {
     807           0 :     stringStates->Add(NS_LITERAL_STRING("invisible"));
     808             :   }
     809           0 :   if (aStates & states::OFFSCREEN) {
     810           0 :     stringStates->Add(NS_LITERAL_STRING("offscreen"));
     811             :   }
     812           0 :   if (aStates & states::SIZEABLE) {
     813           0 :     stringStates->Add(NS_LITERAL_STRING("sizeable"));
     814             :   }
     815           0 :   if (aStates & states::MOVEABLE) {
     816           0 :     stringStates->Add(NS_LITERAL_STRING("moveable"));
     817             :   }
     818           0 :   if (aStates & states::SELFVOICING) {
     819           0 :     stringStates->Add(NS_LITERAL_STRING("selfvoicing"));
     820             :   }
     821           0 :   if (aStates & states::FOCUSABLE) {
     822           0 :     stringStates->Add(NS_LITERAL_STRING("focusable"));
     823             :   }
     824           0 :   if (aStates & states::SELECTABLE) {
     825           0 :     stringStates->Add(NS_LITERAL_STRING("selectable"));
     826             :   }
     827           0 :   if (aStates & states::LINKED) {
     828           0 :     stringStates->Add(NS_LITERAL_STRING("linked"));
     829             :   }
     830           0 :   if (aStates & states::TRAVERSED) {
     831           0 :     stringStates->Add(NS_LITERAL_STRING("traversed"));
     832             :   }
     833           0 :   if (aStates & states::MULTISELECTABLE) {
     834           0 :     stringStates->Add(NS_LITERAL_STRING("multiselectable"));
     835             :   }
     836           0 :   if (aStates & states::EXTSELECTABLE) {
     837           0 :     stringStates->Add(NS_LITERAL_STRING("extselectable"));
     838             :   }
     839           0 :   if (aStates & states::PROTECTED) {
     840           0 :     stringStates->Add(NS_LITERAL_STRING("protected"));
     841             :   }
     842           0 :   if (aStates & states::HASPOPUP) {
     843           0 :     stringStates->Add(NS_LITERAL_STRING("haspopup"));
     844             :   }
     845           0 :   if (aStates & states::REQUIRED) {
     846           0 :     stringStates->Add(NS_LITERAL_STRING("required"));
     847             :   }
     848           0 :   if (aStates & states::ALERT) {
     849           0 :     stringStates->Add(NS_LITERAL_STRING("alert"));
     850             :   }
     851           0 :   if (aStates & states::INVALID) {
     852           0 :     stringStates->Add(NS_LITERAL_STRING("invalid"));
     853             :   }
     854           0 :   if (aStates & states::CHECKABLE) {
     855           0 :     stringStates->Add(NS_LITERAL_STRING("checkable"));
     856             :   }
     857           0 :   if (aStates & states::SUPPORTS_AUTOCOMPLETION) {
     858           0 :     stringStates->Add(NS_LITERAL_STRING("autocompletion"));
     859             :   }
     860           0 :   if (aStates & states::DEFUNCT) {
     861           0 :     stringStates->Add(NS_LITERAL_STRING("defunct"));
     862             :   }
     863           0 :   if (aStates & states::SELECTABLE_TEXT) {
     864           0 :     stringStates->Add(NS_LITERAL_STRING("selectable text"));
     865             :   }
     866           0 :   if (aStates & states::EDITABLE) {
     867           0 :     stringStates->Add(NS_LITERAL_STRING("editable"));
     868             :   }
     869           0 :   if (aStates & states::ACTIVE) {
     870           0 :     stringStates->Add(NS_LITERAL_STRING("active"));
     871             :   }
     872           0 :   if (aStates & states::MODAL) {
     873           0 :     stringStates->Add(NS_LITERAL_STRING("modal"));
     874             :   }
     875           0 :   if (aStates & states::MULTI_LINE) {
     876           0 :     stringStates->Add(NS_LITERAL_STRING("multi line"));
     877             :   }
     878           0 :   if (aStates & states::HORIZONTAL) {
     879           0 :     stringStates->Add(NS_LITERAL_STRING("horizontal"));
     880             :   }
     881           0 :   if (aStates & states::OPAQUE1) {
     882           0 :     stringStates->Add(NS_LITERAL_STRING("opaque"));
     883             :   }
     884           0 :   if (aStates & states::SINGLE_LINE) {
     885           0 :     stringStates->Add(NS_LITERAL_STRING("single line"));
     886             :   }
     887           0 :   if (aStates & states::TRANSIENT) {
     888           0 :     stringStates->Add(NS_LITERAL_STRING("transient"));
     889             :   }
     890           0 :   if (aStates & states::VERTICAL) {
     891           0 :     stringStates->Add(NS_LITERAL_STRING("vertical"));
     892             :   }
     893           0 :   if (aStates & states::STALE) {
     894           0 :     stringStates->Add(NS_LITERAL_STRING("stale"));
     895             :   }
     896           0 :   if (aStates & states::ENABLED) {
     897           0 :     stringStates->Add(NS_LITERAL_STRING("enabled"));
     898             :   }
     899           0 :   if (aStates & states::SENSITIVE) {
     900           0 :     stringStates->Add(NS_LITERAL_STRING("sensitive"));
     901             :   }
     902           0 :   if (aStates & states::EXPANDABLE) {
     903           0 :     stringStates->Add(NS_LITERAL_STRING("expandable"));
     904             :   }
     905             : 
     906           0 :   return stringStates.forget();
     907             : }
     908             : 
     909             : void
     910           0 : nsAccessibilityService::GetStringEventType(uint32_t aEventType,
     911             :                                            nsAString& aString)
     912             : {
     913           0 :   NS_ASSERTION(nsIAccessibleEvent::EVENT_LAST_ENTRY == ArrayLength(kEventTypeNames),
     914             :                "nsIAccessibleEvent constants are out of sync to kEventTypeNames");
     915             : 
     916           0 :   if (aEventType >= ArrayLength(kEventTypeNames)) {
     917           0 :     aString.AssignLiteral("unknown");
     918           0 :     return;
     919             :   }
     920             : 
     921           0 :   CopyUTF8toUTF16(kEventTypeNames[aEventType], aString);
     922             : }
     923             : 
     924             : void
     925           0 : nsAccessibilityService::GetStringRelationType(uint32_t aRelationType,
     926             :                                               nsAString& aString)
     927             : {
     928           0 :   NS_ENSURE_TRUE_VOID(aRelationType <= static_cast<uint32_t>(RelationType::LAST));
     929             : 
     930             : #define RELATIONTYPE(geckoType, geckoTypeName, atkType, msaaType, ia2Type) \
     931             :   case RelationType::geckoType: \
     932             :     aString.AssignLiteral(geckoTypeName); \
     933             :     return;
     934             : 
     935           0 :   RelationType relationType = static_cast<RelationType>(aRelationType);
     936           0 :   switch (relationType) {
     937             : #include "RelationTypeMap.h"
     938             :     default:
     939           0 :       aString.AssignLiteral("unknown");
     940           0 :       return;
     941             :   }
     942             : 
     943             : #undef RELATIONTYPE
     944             : }
     945             : 
     946             : ////////////////////////////////////////////////////////////////////////////////
     947             : // nsAccessibilityService public
     948             : 
     949             : Accessible*
     950           0 : nsAccessibilityService::CreateAccessible(nsINode* aNode,
     951             :                                          Accessible* aContext,
     952             :                                          bool* aIsSubtreeHidden)
     953             : {
     954           0 :   MOZ_ASSERT(aContext, "No context provided");
     955           0 :   MOZ_ASSERT(aNode, "No node to create an accessible for");
     956           0 :   MOZ_ASSERT(gConsumers, "No creation after shutdown");
     957             : 
     958           0 :   if (aIsSubtreeHidden)
     959           0 :     *aIsSubtreeHidden = false;
     960             : 
     961           0 :   DocAccessible* document = aContext->Document();
     962           0 :   MOZ_ASSERT(!document->GetAccessible(aNode),
     963             :              "We already have an accessible for this node.");
     964             : 
     965           0 :   if (aNode->IsNodeOfType(nsINode::eDOCUMENT)) {
     966             :     // If it's document node then ask accessible document loader for
     967             :     // document accessible, otherwise return null.
     968           0 :     nsCOMPtr<nsIDocument> document(do_QueryInterface(aNode));
     969           0 :     return GetDocAccessible(document);
     970             :   }
     971             : 
     972             :   // We have a content node.
     973           0 :   if (!aNode->GetComposedDoc()) {
     974           0 :     NS_WARNING("Creating accessible for node with no document");
     975           0 :     return nullptr;
     976             :   }
     977             : 
     978           0 :   if (aNode->OwnerDoc() != document->DocumentNode()) {
     979           0 :     NS_ERROR("Creating accessible for wrong document");
     980           0 :     return nullptr;
     981             :   }
     982             : 
     983           0 :   if (!aNode->IsContent())
     984           0 :     return nullptr;
     985             : 
     986           0 :   nsIContent* content = aNode->AsContent();
     987           0 :   nsIFrame* frame = content->GetPrimaryFrame();
     988             : 
     989             :   // Check frame and its visibility. Note, hidden frame allows visible
     990             :   // elements in subtree.
     991           0 :   if (!frame || !frame->StyleVisibility()->IsVisible()) {
     992           0 :     if (aIsSubtreeHidden && !frame)
     993           0 :       *aIsSubtreeHidden = true;
     994             : 
     995           0 :     return nullptr;
     996             :   }
     997             : 
     998           0 :   if (frame->GetContent() != content) {
     999             :     // Not the main content for this frame. This happens because <area>
    1000             :     // elements return the image frame as their primary frame. The main content
    1001             :     // for the image frame is the image content. If the frame is not an image
    1002             :     // frame or the node is not an area element then null is returned.
    1003             :     // This setup will change when bug 135040 is fixed. Make sure we don't
    1004             :     // create area accessible here. Hopefully assertion below will handle that.
    1005             : 
    1006             : #ifdef DEBUG
    1007           0 :   nsImageFrame* imageFrame = do_QueryFrame(frame);
    1008           0 :   NS_ASSERTION(imageFrame && content->IsHTMLElement(nsGkAtoms::area),
    1009             :                "Unknown case of not main content for the frame!");
    1010             : #endif
    1011           0 :     return nullptr;
    1012             :   }
    1013             : 
    1014             : #ifdef DEBUG
    1015           0 :   nsImageFrame* imageFrame = do_QueryFrame(frame);
    1016           0 :   NS_ASSERTION(!imageFrame || !content->IsHTMLElement(nsGkAtoms::area),
    1017             :                "Image map manages the area accessible creation!");
    1018             : #endif
    1019             : 
    1020             :   // Attempt to create an accessible based on what we know.
    1021           0 :   RefPtr<Accessible> newAcc;
    1022             : 
    1023             :   // Create accessible for visible text frames.
    1024           0 :   if (content->IsNodeOfType(nsINode::eTEXT)) {
    1025             :     nsIFrame::RenderedText text = frame->GetRenderedText(0,
    1026             :         UINT32_MAX, nsIFrame::TextOffsetType::OFFSETS_IN_CONTENT_TEXT,
    1027           0 :         nsIFrame::TrailingWhitespace::DONT_TRIM_TRAILING_WHITESPACE);
    1028             :     // Ignore not rendered text nodes and whitespace text nodes between table
    1029             :     // cells.
    1030           0 :     if (text.mString.IsEmpty() ||
    1031           0 :         (aContext->IsTableRow() && nsCoreUtils::IsWhitespaceString(text.mString))) {
    1032           0 :       if (aIsSubtreeHidden)
    1033           0 :         *aIsSubtreeHidden = true;
    1034             : 
    1035           0 :       return nullptr;
    1036             :     }
    1037             : 
    1038           0 :     newAcc = CreateAccessibleByFrameType(frame, content, aContext);
    1039           0 :     document->BindToDocument(newAcc, nullptr);
    1040           0 :     newAcc->AsTextLeaf()->SetText(text.mString);
    1041           0 :     return newAcc;
    1042             :   }
    1043             : 
    1044           0 :   if (content->IsHTMLElement(nsGkAtoms::map)) {
    1045             :     // Create hyper text accessible for HTML map if it is used to group links
    1046             :     // (see http://www.w3.org/TR/WCAG10-HTML-TECHS/#group-bypass). If the HTML
    1047             :     // map rect is empty then it is used for links grouping. Otherwise it should
    1048             :     // be used in conjunction with HTML image element and in this case we don't
    1049             :     // create any accessible for it and don't walk into it. The accessibles for
    1050             :     // HTML area (HTMLAreaAccessible) the map contains are attached as
    1051             :     // children of the appropriate accessible for HTML image
    1052             :     // (ImageAccessible).
    1053           0 :     if (nsLayoutUtils::GetAllInFlowRectsUnion(frame,
    1054           0 :                                               frame->GetParent()).IsEmpty()) {
    1055           0 :       if (aIsSubtreeHidden)
    1056           0 :         *aIsSubtreeHidden = true;
    1057             : 
    1058           0 :       return nullptr;
    1059             :     }
    1060             : 
    1061           0 :     newAcc = new HyperTextAccessibleWrap(content, document);
    1062           0 :     document->BindToDocument(newAcc, aria::GetRoleMap(content->AsElement()));
    1063           0 :     return newAcc;
    1064             :   }
    1065             : 
    1066           0 :   const nsRoleMapEntry* roleMapEntry = aria::GetRoleMap(content->AsElement());
    1067             : 
    1068             :   // If the element is focusable or global ARIA attribute is applied to it or
    1069             :   // it is referenced by ARIA relationship then treat role="presentation" on
    1070             :   // the element as the role is not there.
    1071           0 :   if (roleMapEntry &&
    1072           0 :       (roleMapEntry->Is(nsGkAtoms::presentation) ||
    1073           0 :        roleMapEntry->Is(nsGkAtoms::none))) {
    1074           0 :     if (!MustBeAccessible(content, document))
    1075           0 :       return nullptr;
    1076             : 
    1077           0 :     roleMapEntry = nullptr;
    1078             :   }
    1079             : 
    1080           0 :   if (!newAcc && content->IsHTMLElement()) {  // HTML accessibles
    1081           0 :     bool isARIATablePart = roleMapEntry &&
    1082           0 :       (roleMapEntry->accTypes & (eTableCell | eTableRow | eTable));
    1083             : 
    1084           0 :     if (!isARIATablePart ||
    1085           0 :         frame->AccessibleType() == eHTMLTableCellType ||
    1086           0 :         frame->AccessibleType() == eHTMLTableRowType ||
    1087           0 :         frame->AccessibleType() == eHTMLTableType) {
    1088             :       // Prefer to use markup to decide if and what kind of accessible to create,
    1089             :       const MarkupMapInfo* markupMap =
    1090           0 :         mMarkupMaps.Get(content->NodeInfo()->NameAtom());
    1091           0 :       if (markupMap && markupMap->new_func)
    1092           0 :         newAcc = markupMap->new_func(content, aContext);
    1093             : 
    1094           0 :       if (!newAcc) // try by frame accessible type.
    1095           0 :         newAcc = CreateAccessibleByFrameType(frame, content, aContext);
    1096             :     }
    1097             : 
    1098             :     // In case of ARIA grid or table use table-specific classes if it's not
    1099             :     // native table based.
    1100           0 :     if (isARIATablePart && (!newAcc || newAcc->IsGenericHyperText())) {
    1101           0 :       if ((roleMapEntry->accTypes & eTableCell)) {
    1102           0 :         if (aContext->IsTableRow())
    1103           0 :           newAcc = new ARIAGridCellAccessibleWrap(content, document);
    1104             : 
    1105           0 :       } else if (roleMapEntry->IsOfType(eTableRow)) {
    1106           0 :         if (aContext->IsTable())
    1107           0 :           newAcc = new ARIARowAccessible(content, document);
    1108             : 
    1109           0 :       } else if (roleMapEntry->IsOfType(eTable)) {
    1110           0 :         newAcc = new ARIAGridAccessibleWrap(content, document);
    1111             :       }
    1112             :     }
    1113             : 
    1114             :     // If table has strong ARIA role then all table descendants shouldn't
    1115             :     // expose their native roles.
    1116           0 :     if (!roleMapEntry && newAcc && aContext->HasStrongARIARole()) {
    1117           0 :       if (frame->AccessibleType() == eHTMLTableRowType) {
    1118           0 :         const nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
    1119           0 :         if (!contextRoleMap->IsOfType(eTable))
    1120           0 :           roleMapEntry = &aria::gEmptyRoleMap;
    1121             : 
    1122           0 :       } else if (frame->AccessibleType() == eHTMLTableCellType &&
    1123           0 :                  aContext->ARIARoleMap() == &aria::gEmptyRoleMap) {
    1124           0 :         roleMapEntry = &aria::gEmptyRoleMap;
    1125             : 
    1126           0 :       } else if (content->IsAnyOfHTMLElements(nsGkAtoms::dt,
    1127             :                                               nsGkAtoms::li,
    1128           0 :                                               nsGkAtoms::dd) ||
    1129           0 :                  frame->AccessibleType() == eHTMLLiType) {
    1130           0 :         const nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
    1131           0 :         if (!contextRoleMap->IsOfType(eList))
    1132           0 :           roleMapEntry = &aria::gEmptyRoleMap;
    1133             :       }
    1134             :     }
    1135             :   }
    1136             : 
    1137             :   // Accessible XBL types and deck stuff are used in XUL only currently.
    1138           0 :   if (!newAcc && content->IsXULElement()) {
    1139             :     // No accessible for not selected deck panel and its children.
    1140           0 :     if (!aContext->IsXULTabpanels()) {
    1141           0 :       nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
    1142           0 :       if (deckFrame && deckFrame->GetSelectedBox() != frame) {
    1143           0 :         if (aIsSubtreeHidden)
    1144           0 :           *aIsSubtreeHidden = true;
    1145             : 
    1146           0 :         return nullptr;
    1147             :       }
    1148             :     }
    1149             : 
    1150             :     // XBL bindings may use @role attribute to point the accessible type
    1151             :     // they belong to.
    1152           0 :     newAcc = CreateAccessibleByType(content, document);
    1153             : 
    1154             :     // Any XUL box can be used as tabpanel, make sure we create a proper
    1155             :     // accessible for it.
    1156           0 :     if (!newAcc && aContext->IsXULTabpanels() &&
    1157           0 :         content->GetParent() == aContext->GetContent()) {
    1158           0 :       LayoutFrameType frameType = frame->Type();
    1159           0 :       if (frameType == LayoutFrameType::Box ||
    1160             :           frameType == LayoutFrameType::Scroll) {
    1161           0 :         newAcc = new XULTabpanelAccessible(content, document);
    1162             :       }
    1163             :     }
    1164             :   }
    1165             : 
    1166           0 :   if (!newAcc) {
    1167           0 :     if (content->IsSVGElement()) {
    1168           0 :       SVGGeometryFrame* geometryFrame = do_QueryFrame(frame);
    1169           0 :       if (geometryFrame) {
    1170             :         // A graphic elements: rect, circle, ellipse, line, path, polygon,
    1171             :         // polyline and image. A 'use' and 'text' graphic elements require
    1172             :         // special support.
    1173           0 :         newAcc = new EnumRoleAccessible<roles::GRAPHIC>(content, document);
    1174           0 :       } else if (content->IsSVGElement(nsGkAtoms::svg)) {
    1175           0 :         newAcc = new EnumRoleAccessible<roles::DIAGRAM>(content, document);
    1176             :       }
    1177             : 
    1178           0 :     } else if (content->IsMathMLElement()) {
    1179             :       const MarkupMapInfo* markupMap =
    1180           0 :         mMarkupMaps.Get(content->NodeInfo()->NameAtom());
    1181           0 :       if (markupMap && markupMap->new_func)
    1182           0 :         newAcc = markupMap->new_func(content, aContext);
    1183             : 
    1184             :       // Fall back to text when encountering Content MathML.
    1185           0 :       if (!newAcc && !content->IsAnyOfMathMLElements(nsGkAtoms::annotation_,
    1186             :                                                      nsGkAtoms::annotation_xml_,
    1187             :                                                      nsGkAtoms::mpadded_,
    1188             :                                                      nsGkAtoms::mphantom_,
    1189             :                                                      nsGkAtoms::maligngroup_,
    1190             :                                                      nsGkAtoms::malignmark_,
    1191             :                                                      nsGkAtoms::mspace_,
    1192             :                                                      nsGkAtoms::semantics_)) {
    1193           0 :        newAcc = new HyperTextAccessible(content, document);
    1194             :       }
    1195             :     }
    1196             :   }
    1197             : 
    1198             :   // If no accessible, see if we need to create a generic accessible because
    1199             :   // of some property that makes this object interesting
    1200             :   // We don't do this for <body>, <html>, <window>, <dialog> etc. which
    1201             :   // correspond to the doc accessible and will be created in any case
    1202           0 :   if (!newAcc && !content->IsHTMLElement(nsGkAtoms::body) &&
    1203           0 :       content->GetParent() &&
    1204           0 :       (roleMapEntry || MustBeAccessible(content, document) ||
    1205           0 :        (content->IsHTMLElement() &&
    1206           0 :         nsCoreUtils::HasClickListener(content)))) {
    1207             :     // This content is focusable or has an interesting dynamic content accessibility property.
    1208             :     // If it's interesting we need it in the accessibility hierarchy so that events or
    1209             :     // other accessibles can point to it, or so that it can hold a state, etc.
    1210           0 :     if (content->IsHTMLElement()) {
    1211             :       // Interesting HTML container which may have selectable text and/or embedded objects
    1212           0 :       newAcc = new HyperTextAccessibleWrap(content, document);
    1213             :     } else {  // XUL, SVG, MathML etc.
    1214             :       // Interesting generic non-HTML container
    1215           0 :       newAcc = new AccessibleWrap(content, document);
    1216             :     }
    1217             :   }
    1218             : 
    1219           0 :   if (newAcc) {
    1220           0 :     document->BindToDocument(newAcc, roleMapEntry);
    1221             :   }
    1222           0 :   return newAcc;
    1223             : }
    1224             : 
    1225             : ////////////////////////////////////////////////////////////////////////////////
    1226             : // nsAccessibilityService private
    1227             : 
    1228             : bool
    1229           0 : nsAccessibilityService::Init()
    1230             : {
    1231             :   // Initialize accessible document manager.
    1232           0 :   if (!DocManager::Init())
    1233           0 :     return false;
    1234             : 
    1235             :   // Add observers.
    1236             :   nsCOMPtr<nsIObserverService> observerService =
    1237           0 :     mozilla::services::GetObserverService();
    1238           0 :   if (!observerService)
    1239           0 :     return false;
    1240             : 
    1241           0 :   observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
    1242             : 
    1243             :   static const char16_t kInitIndicator[] = { '1', 0 };
    1244           0 :   observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kInitIndicator);
    1245             : 
    1246             :   // Subscribe to EventListenerService.
    1247             :   nsCOMPtr<nsIEventListenerService> eventListenerService =
    1248           0 :     do_GetService("@mozilla.org/eventlistenerservice;1");
    1249           0 :   if (!eventListenerService)
    1250           0 :     return false;
    1251             : 
    1252           0 :   eventListenerService->AddListenerChangeListener(this);
    1253             : 
    1254           0 :   for (uint32_t i = 0; i < ArrayLength(sMarkupMapList); i++)
    1255           0 :     mMarkupMaps.Put(*sMarkupMapList[i].tag, &sMarkupMapList[i]);
    1256             : 
    1257             : #ifdef A11Y_LOG
    1258           0 :   logging::CheckEnv();
    1259             : #endif
    1260             : 
    1261           0 :   gAccessibilityService = this;
    1262           0 :   NS_ADDREF(gAccessibilityService); // will release in Shutdown()
    1263             : 
    1264           0 :   if (XRE_IsParentProcess()) {
    1265           0 :     gApplicationAccessible = new ApplicationAccessibleWrap();
    1266             :   } else {
    1267             : #if defined(XP_WIN)
    1268             :     dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
    1269             :     MOZ_ASSERT(contentChild);
    1270             :     // If we were instantiated by the chrome process, GetMsaaID() will return
    1271             :     // a non-zero value and we may safely continue with initialization.
    1272             :     if (!contentChild->GetMsaaID()) {
    1273             :       // Since we were not instantiated by chrome, we need to synchronously
    1274             :       // obtain a MSAA content process id.
    1275             :       contentChild->SendGetA11yContentId();
    1276             :     }
    1277             : #endif // defined(XP_WIN)
    1278             : 
    1279           0 :     gApplicationAccessible = new ApplicationAccessible();
    1280             :   }
    1281             : 
    1282           0 :   NS_ADDREF(gApplicationAccessible); // will release in Shutdown()
    1283           0 :   gApplicationAccessible->Init();
    1284             : 
    1285             : #ifdef MOZ_CRASHREPORTER
    1286             :   CrashReporter::
    1287           0 :     AnnotateCrashReport(NS_LITERAL_CSTRING("Accessibility"),
    1288           0 :                         NS_LITERAL_CSTRING("Active"));
    1289             : #endif
    1290             : 
    1291             : #ifdef XP_WIN
    1292             :   sPendingPlugins = new nsTArray<nsCOMPtr<nsIContent> >;
    1293             :   sPluginTimers = new nsTArray<nsCOMPtr<nsITimer> >;
    1294             : #endif
    1295             : 
    1296             :   // Now its safe to start platform accessibility.
    1297           0 :   if (XRE_IsParentProcess())
    1298           0 :     PlatformInit();
    1299             : 
    1300           0 :   statistics::A11yInitialized();
    1301             : 
    1302           0 :   return true;
    1303             : }
    1304             : 
    1305             : void
    1306           0 : nsAccessibilityService::Shutdown()
    1307             : {
    1308             :   // Application is going to be closed, shutdown accessibility and mark
    1309             :   // accessibility service as shutdown to prevent calls of its methods.
    1310             :   // Don't null accessibility service static member at this point to be safe
    1311             :   // if someone will try to operate with it.
    1312             : 
    1313           0 :   MOZ_ASSERT(gConsumers, "Accessibility was shutdown already");
    1314             : 
    1315           0 :   gConsumers = 0;
    1316             : 
    1317             :   // Remove observers.
    1318             :   nsCOMPtr<nsIObserverService> observerService =
    1319           0 :       mozilla::services::GetObserverService();
    1320           0 :   if (observerService) {
    1321           0 :     observerService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
    1322             : 
    1323             :     static const char16_t kShutdownIndicator[] = { '0', 0 };
    1324           0 :     observerService->NotifyObservers(nullptr, "a11y-init-or-shutdown", kShutdownIndicator);
    1325             :   }
    1326             : 
    1327             :   // Stop accessible document loader.
    1328           0 :   DocManager::Shutdown();
    1329             : 
    1330           0 :   SelectionManager::Shutdown();
    1331             : 
    1332             : #ifdef XP_WIN
    1333             :   sPendingPlugins = nullptr;
    1334             : 
    1335             :   uint32_t timerCount = sPluginTimers->Length();
    1336             :   for (uint32_t i = 0; i < timerCount; i++)
    1337             :     sPluginTimers->ElementAt(i)->Cancel();
    1338             : 
    1339             :   sPluginTimers = nullptr;
    1340             : #endif
    1341             : 
    1342           0 :   if (XRE_IsParentProcess())
    1343           0 :     PlatformShutdown();
    1344             : 
    1345           0 :   gApplicationAccessible->Shutdown();
    1346           0 :   NS_RELEASE(gApplicationAccessible);
    1347           0 :   gApplicationAccessible = nullptr;
    1348             : 
    1349           0 :   NS_IF_RELEASE(gXPCApplicationAccessible);
    1350           0 :   gXPCApplicationAccessible = nullptr;
    1351             : 
    1352           0 :   NS_RELEASE(gAccessibilityService);
    1353           0 :   gAccessibilityService = nullptr;
    1354           0 : }
    1355             : 
    1356             : already_AddRefed<Accessible>
    1357           0 : nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
    1358             :                                                DocAccessible* aDoc)
    1359             : {
    1360           0 :   nsAutoString role;
    1361           0 :   nsCoreUtils::XBLBindingRole(aContent, role);
    1362           0 :   if (role.IsEmpty() || role.EqualsLiteral("none"))
    1363           0 :     return nullptr;
    1364             : 
    1365           0 :   if (role.EqualsLiteral("outerdoc")) {
    1366           0 :     RefPtr<Accessible> accessible = new OuterDocAccessible(aContent, aDoc);
    1367           0 :     return accessible.forget();
    1368             :   }
    1369             : 
    1370           0 :   RefPtr<Accessible> accessible;
    1371             : #ifdef MOZ_XUL
    1372             :   // XUL controls
    1373           0 :   if (role.EqualsLiteral("xul:alert")) {
    1374           0 :     accessible = new XULAlertAccessible(aContent, aDoc);
    1375             : 
    1376           0 :   } else if (role.EqualsLiteral("xul:button")) {
    1377           0 :     accessible = new XULButtonAccessible(aContent, aDoc);
    1378             : 
    1379           0 :   } else if (role.EqualsLiteral("xul:checkbox")) {
    1380           0 :     accessible = new XULCheckboxAccessible(aContent, aDoc);
    1381             : 
    1382           0 :   } else if (role.EqualsLiteral("xul:colorpicker")) {
    1383           0 :     accessible = new XULColorPickerAccessible(aContent, aDoc);
    1384             : 
    1385           0 :   } else if (role.EqualsLiteral("xul:colorpickertile")) {
    1386           0 :     accessible = new XULColorPickerTileAccessible(aContent, aDoc);
    1387             : 
    1388           0 :   } else if (role.EqualsLiteral("xul:combobox")) {
    1389           0 :     accessible = new XULComboboxAccessible(aContent, aDoc);
    1390             : 
    1391           0 :   } else if (role.EqualsLiteral("xul:tabpanels")) {
    1392           0 :       accessible = new XULTabpanelsAccessible(aContent, aDoc);
    1393             : 
    1394           0 :   } else if (role.EqualsLiteral("xul:dropmarker")) {
    1395           0 :       accessible = new XULDropmarkerAccessible(aContent, aDoc);
    1396             : 
    1397           0 :   } else if (role.EqualsLiteral("xul:groupbox")) {
    1398           0 :       accessible = new XULGroupboxAccessible(aContent, aDoc);
    1399             : 
    1400           0 :   } else if (role.EqualsLiteral("xul:image")) {
    1401           0 :     if (aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::onclick)) {
    1402           0 :       accessible = new XULToolbarButtonAccessible(aContent, aDoc);
    1403             : 
    1404             :     } else {
    1405             :       // Don't include nameless images in accessible tree.
    1406           0 :       if (!aContent->HasAttr(kNameSpaceID_None,
    1407             :                              nsGkAtoms::tooltiptext))
    1408           0 :         return nullptr;
    1409             : 
    1410           0 :       accessible = new ImageAccessibleWrap(aContent, aDoc);
    1411             :     }
    1412             : 
    1413           0 :   } else if (role.EqualsLiteral("xul:link")) {
    1414           0 :     accessible = new XULLinkAccessible(aContent, aDoc);
    1415             : 
    1416           0 :   } else if (role.EqualsLiteral("xul:listbox")) {
    1417           0 :       accessible = new XULListboxAccessibleWrap(aContent, aDoc);
    1418             : 
    1419           0 :   } else if (role.EqualsLiteral("xul:listcell")) {
    1420             :     // Only create cells if there's more than one per row.
    1421           0 :     nsIContent* listItem = aContent->GetParent();
    1422           0 :     if (!listItem)
    1423           0 :       return nullptr;
    1424             : 
    1425           0 :     for (nsIContent* child = listItem->GetFirstChild(); child;
    1426           0 :          child = child->GetNextSibling()) {
    1427           0 :       if (child->IsXULElement(nsGkAtoms::listcell) && child != aContent) {
    1428           0 :         accessible = new XULListCellAccessibleWrap(aContent, aDoc);
    1429           0 :         break;
    1430             :       }
    1431             :     }
    1432             : 
    1433           0 :   } else if (role.EqualsLiteral("xul:listhead")) {
    1434           0 :     accessible = new XULColumAccessible(aContent, aDoc);
    1435             : 
    1436           0 :   } else if (role.EqualsLiteral("xul:listheader")) {
    1437           0 :     accessible = new XULColumnItemAccessible(aContent, aDoc);
    1438             : 
    1439           0 :   } else if (role.EqualsLiteral("xul:listitem")) {
    1440           0 :     accessible = new XULListitemAccessible(aContent, aDoc);
    1441             : 
    1442           0 :   } else if (role.EqualsLiteral("xul:menubar")) {
    1443           0 :     accessible = new XULMenubarAccessible(aContent, aDoc);
    1444             : 
    1445           0 :   } else if (role.EqualsLiteral("xul:menulist")) {
    1446           0 :     accessible = new XULComboboxAccessible(aContent, aDoc);
    1447             : 
    1448           0 :   } else if (role.EqualsLiteral("xul:menuitem")) {
    1449           0 :     accessible = new XULMenuitemAccessibleWrap(aContent, aDoc);
    1450             : 
    1451           0 :   } else if (role.EqualsLiteral("xul:menupopup")) {
    1452             : #ifdef MOZ_ACCESSIBILITY_ATK
    1453             :     // ATK considers this node to be redundant when within menubars, and it makes menu
    1454             :     // navigation with assistive technologies more difficult
    1455             :     // XXX In the future we will should this for consistency across the nsIAccessible
    1456             :     // implementations on each platform for a consistent scripting environment, but
    1457             :     // then strip out redundant accessibles in the AccessibleWrap class for each platform.
    1458           0 :     nsIContent *parent = aContent->GetParent();
    1459           0 :     if (parent && parent->IsXULElement(nsGkAtoms::menu))
    1460           0 :       return nullptr;
    1461             : #endif
    1462             : 
    1463           0 :     accessible = new XULMenupopupAccessible(aContent, aDoc);
    1464             : 
    1465           0 :   } else if(role.EqualsLiteral("xul:menuseparator")) {
    1466           0 :     accessible = new XULMenuSeparatorAccessible(aContent, aDoc);
    1467             : 
    1468           0 :   } else if(role.EqualsLiteral("xul:pane")) {
    1469           0 :     accessible = new EnumRoleAccessible<roles::PANE>(aContent, aDoc);
    1470             : 
    1471           0 :   } else if (role.EqualsLiteral("xul:panel")) {
    1472           0 :     if (aContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::noautofocus,
    1473             :                               nsGkAtoms::_true, eCaseMatters))
    1474           0 :       accessible = new XULAlertAccessible(aContent, aDoc);
    1475             :     else
    1476           0 :       accessible = new EnumRoleAccessible<roles::PANE>(aContent, aDoc);
    1477             : 
    1478           0 :   } else if (role.EqualsLiteral("xul:progressmeter")) {
    1479           0 :     accessible = new XULProgressMeterAccessible(aContent, aDoc);
    1480             : 
    1481           0 :   } else if (role.EqualsLiteral("xul:statusbar")) {
    1482           0 :     accessible = new XULStatusBarAccessible(aContent, aDoc);
    1483             : 
    1484           0 :   } else if (role.EqualsLiteral("xul:scale")) {
    1485           0 :     accessible = new XULSliderAccessible(aContent, aDoc);
    1486             : 
    1487           0 :   } else if (role.EqualsLiteral("xul:radiobutton")) {
    1488           0 :     accessible = new XULRadioButtonAccessible(aContent, aDoc);
    1489             : 
    1490           0 :   } else if (role.EqualsLiteral("xul:radiogroup")) {
    1491           0 :     accessible = new XULRadioGroupAccessible(aContent, aDoc);
    1492             : 
    1493           0 :   } else if (role.EqualsLiteral("xul:tab")) {
    1494           0 :     accessible = new XULTabAccessible(aContent, aDoc);
    1495             : 
    1496           0 :   } else if (role.EqualsLiteral("xul:tabs")) {
    1497           0 :     accessible = new XULTabsAccessible(aContent, aDoc);
    1498             : 
    1499           0 :   } else if (role.EqualsLiteral("xul:text")) {
    1500           0 :     accessible = new XULLabelAccessible(aContent, aDoc);
    1501             : 
    1502           0 :   } else if (role.EqualsLiteral("xul:textbox")) {
    1503           0 :     accessible = new EnumRoleAccessible<roles::SECTION>(aContent, aDoc);
    1504             : 
    1505           0 :   } else if (role.EqualsLiteral("xul:thumb")) {
    1506           0 :     accessible = new XULThumbAccessible(aContent, aDoc);
    1507             : 
    1508           0 :   } else if (role.EqualsLiteral("xul:tree")) {
    1509           0 :     accessible = CreateAccessibleForXULTree(aContent, aDoc);
    1510             : 
    1511           0 :   } else if (role.EqualsLiteral("xul:treecolumns")) {
    1512           0 :     accessible = new XULTreeColumAccessible(aContent, aDoc);
    1513             : 
    1514           0 :   } else if (role.EqualsLiteral("xul:treecolumnitem")) {
    1515           0 :     accessible = new XULColumnItemAccessible(aContent, aDoc);
    1516             : 
    1517           0 :   } else if (role.EqualsLiteral("xul:toolbar")) {
    1518           0 :     accessible = new XULToolbarAccessible(aContent, aDoc);
    1519             : 
    1520           0 :   } else if (role.EqualsLiteral("xul:toolbarseparator")) {
    1521           0 :     accessible = new XULToolbarSeparatorAccessible(aContent, aDoc);
    1522             : 
    1523           0 :   } else if (role.EqualsLiteral("xul:tooltip")) {
    1524           0 :     accessible = new XULTooltipAccessible(aContent, aDoc);
    1525             : 
    1526           0 :   } else if (role.EqualsLiteral("xul:toolbarbutton")) {
    1527           0 :     accessible = new XULToolbarButtonAccessible(aContent, aDoc);
    1528             : 
    1529             :   }
    1530             : #endif // MOZ_XUL
    1531             : 
    1532           0 :   return accessible.forget();
    1533             : }
    1534             : 
    1535             : already_AddRefed<Accessible>
    1536           0 : nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
    1537             :                                                     nsIContent* aContent,
    1538             :                                                     Accessible* aContext)
    1539             : {
    1540           0 :   DocAccessible* document = aContext->Document();
    1541             : 
    1542           0 :   RefPtr<Accessible> newAcc;
    1543           0 :   switch (aFrame->AccessibleType()) {
    1544             :     case eNoType:
    1545           0 :       return nullptr;
    1546             :     case eHTMLBRType:
    1547           0 :       newAcc = new HTMLBRAccessible(aContent, document);
    1548           0 :       break;
    1549             :     case eHTMLButtonType:
    1550           0 :       newAcc = new HTMLButtonAccessible(aContent, document);
    1551           0 :       break;
    1552             :     case eHTMLCanvasType:
    1553           0 :       newAcc = new HTMLCanvasAccessible(aContent, document);
    1554           0 :       break;
    1555             :     case eHTMLCaptionType:
    1556           0 :       if (aContext->IsTable() &&
    1557           0 :           aContext->GetContent() == aContent->GetParent()) {
    1558           0 :         newAcc = new HTMLCaptionAccessible(aContent, document);
    1559             :       }
    1560           0 :       break;
    1561             :     case eHTMLCheckboxType:
    1562           0 :       newAcc = new HTMLCheckboxAccessible(aContent, document);
    1563           0 :       break;
    1564             :     case eHTMLComboboxType:
    1565           0 :       newAcc = new HTMLComboboxAccessible(aContent, document);
    1566           0 :       break;
    1567             :     case eHTMLFileInputType:
    1568           0 :       newAcc = new HTMLFileInputAccessible(aContent, document);
    1569           0 :       break;
    1570             :     case eHTMLGroupboxType:
    1571           0 :       newAcc = new HTMLGroupboxAccessible(aContent, document);
    1572           0 :       break;
    1573             :     case eHTMLHRType:
    1574           0 :       newAcc = new HTMLHRAccessible(aContent, document);
    1575           0 :       break;
    1576             :     case eHTMLImageMapType:
    1577           0 :       newAcc = new HTMLImageMapAccessible(aContent, document);
    1578           0 :       break;
    1579             :     case eHTMLLiType:
    1580           0 :       if (aContext->IsList() &&
    1581           0 :           aContext->GetContent() == aContent->GetParent()) {
    1582           0 :         newAcc = new HTMLLIAccessible(aContent, document);
    1583             :       } else {
    1584             :         // Otherwise create a generic text accessible to avoid text jamming.
    1585           0 :         newAcc = new HyperTextAccessibleWrap(aContent, document);
    1586             :       }
    1587           0 :       break;
    1588             :     case eHTMLSelectListType:
    1589           0 :       newAcc = new HTMLSelectListAccessible(aContent, document);
    1590           0 :       break;
    1591             :     case eHTMLMediaType:
    1592           0 :       newAcc = new EnumRoleAccessible<roles::GROUPING>(aContent, document);
    1593           0 :       break;
    1594             :     case eHTMLRadioButtonType:
    1595           0 :       newAcc = new HTMLRadioButtonAccessible(aContent, document);
    1596           0 :       break;
    1597             :     case eHTMLRangeType:
    1598           0 :       newAcc = new HTMLRangeAccessible(aContent, document);
    1599           0 :       break;
    1600             :     case eHTMLSpinnerType:
    1601           0 :       newAcc = new HTMLSpinnerAccessible(aContent, document);
    1602           0 :       break;
    1603             :     case eHTMLTableType:
    1604           0 :       if (aContent->IsHTMLElement(nsGkAtoms::table))
    1605           0 :         newAcc = new HTMLTableAccessibleWrap(aContent, document);
    1606             :       else
    1607           0 :         newAcc = new HyperTextAccessibleWrap(aContent, document);
    1608           0 :       break;
    1609             :     case eHTMLTableCellType:
    1610             :       // Accessible HTML table cell should be a child of accessible HTML table
    1611             :       // or its row (CSS HTML tables are polite to the used markup at
    1612             :       // certain degree).
    1613             :       // Otherwise create a generic text accessible to avoid text jamming
    1614             :       // when reading by AT.
    1615           0 :       if (aContext->IsHTMLTableRow() || aContext->IsHTMLTable())
    1616           0 :         newAcc = new HTMLTableCellAccessibleWrap(aContent, document);
    1617             :       else
    1618           0 :         newAcc = new HyperTextAccessibleWrap(aContent, document);
    1619           0 :       break;
    1620             : 
    1621             :     case eHTMLTableRowType: {
    1622             :       // Accessible HTML table row may be a child of tbody/tfoot/thead of
    1623             :       // accessible HTML table or a direct child of accessible of HTML table.
    1624           0 :       Accessible* table = aContext->IsTable() ? aContext : nullptr;
    1625           0 :       if (!table && aContext->Parent() && aContext->Parent()->IsTable())
    1626           0 :         table = aContext->Parent();
    1627             : 
    1628           0 :       if (table) {
    1629           0 :         nsIContent* parentContent = aContent->GetParent();
    1630           0 :         nsIFrame* parentFrame = parentContent->GetPrimaryFrame();
    1631           0 :         if (!parentFrame->IsTableWrapperFrame()) {
    1632           0 :           parentContent = parentContent->GetParent();
    1633           0 :           parentFrame = parentContent->GetPrimaryFrame();
    1634             :         }
    1635             : 
    1636           0 :         if (parentFrame->IsTableWrapperFrame() &&
    1637           0 :             table->GetContent() == parentContent) {
    1638           0 :           newAcc = new HTMLTableRowAccessible(aContent, document);
    1639             :         }
    1640             :       }
    1641           0 :       break;
    1642             :     }
    1643             :     case eHTMLTextFieldType:
    1644           0 :       newAcc = new HTMLTextFieldAccessible(aContent, document);
    1645           0 :       break;
    1646             :     case eHyperTextType:
    1647           0 :       if (!aContent->IsAnyOfHTMLElements(nsGkAtoms::dt, nsGkAtoms::dd))
    1648           0 :         newAcc = new HyperTextAccessibleWrap(aContent, document);
    1649           0 :       break;
    1650             : 
    1651             :     case eImageType:
    1652           0 :       newAcc = new ImageAccessibleWrap(aContent, document);
    1653           0 :       break;
    1654             :     case eOuterDocType:
    1655           0 :       newAcc = new OuterDocAccessible(aContent, document);
    1656           0 :       break;
    1657             :     case ePluginType: {
    1658           0 :       nsPluginFrame* pluginFrame = do_QueryFrame(aFrame);
    1659           0 :       newAcc = CreatePluginAccessible(pluginFrame, aContent, aContext);
    1660           0 :       break;
    1661             :     }
    1662             :     case eTextLeafType:
    1663           0 :       newAcc = new TextLeafAccessibleWrap(aContent, document);
    1664           0 :       break;
    1665             :     default:
    1666           0 :       MOZ_ASSERT(false);
    1667             :       break;
    1668             :   }
    1669             : 
    1670           0 :   return newAcc.forget();
    1671             : }
    1672             : 
    1673             : void
    1674           0 : nsAccessibilityService::MarkupAttributes(const nsIContent* aContent,
    1675             :                                          nsIPersistentProperties* aAttributes) const
    1676             : {
    1677             :   const mozilla::a11y::MarkupMapInfo* markupMap =
    1678           0 :     mMarkupMaps.Get(aContent->NodeInfo()->NameAtom());
    1679           0 :   if (!markupMap)
    1680           0 :     return;
    1681             : 
    1682           0 :   for (uint32_t i = 0; i < ArrayLength(markupMap->attrs); i++) {
    1683           0 :     const MarkupAttrInfo* info = markupMap->attrs + i;
    1684           0 :     if (!info->name)
    1685           0 :       break;
    1686             : 
    1687           0 :     if (info->DOMAttrName) {
    1688           0 :       if (info->DOMAttrValue) {
    1689           0 :         if (aContent->AttrValueIs(kNameSpaceID_None, *info->DOMAttrName,
    1690           0 :                                   *info->DOMAttrValue, eCaseMatters)) {
    1691           0 :           nsAccUtils::SetAccAttr(aAttributes, *info->name, *info->DOMAttrValue);
    1692             :         }
    1693           0 :         continue;
    1694             :       }
    1695             : 
    1696           0 :       nsAutoString value;
    1697           0 :       aContent->GetAttr(kNameSpaceID_None, *info->DOMAttrName, value);
    1698           0 :       if (!value.IsEmpty())
    1699           0 :         nsAccUtils::SetAccAttr(aAttributes, *info->name, value);
    1700             : 
    1701           0 :       continue;
    1702             :     }
    1703             : 
    1704           0 :     nsAccUtils::SetAccAttr(aAttributes, *info->name, *info->value);
    1705             :   }
    1706             : }
    1707             : 
    1708             : Accessible*
    1709           0 : nsAccessibilityService::AddNativeRootAccessible(void* aAtkAccessible)
    1710             : {
    1711             : #ifdef MOZ_ACCESSIBILITY_ATK
    1712           0 :   ApplicationAccessible* applicationAcc = ApplicationAcc();
    1713           0 :   if (!applicationAcc)
    1714           0 :     return nullptr;
    1715             : 
    1716             :   GtkWindowAccessible* nativeWnd =
    1717           0 :     new GtkWindowAccessible(static_cast<AtkObject*>(aAtkAccessible));
    1718             : 
    1719           0 :   if (applicationAcc->AppendChild(nativeWnd))
    1720           0 :     return nativeWnd;
    1721             : #endif
    1722             : 
    1723           0 :   return nullptr;
    1724             : }
    1725             : 
    1726             : void
    1727           0 : nsAccessibilityService::RemoveNativeRootAccessible(Accessible* aAccessible)
    1728             : {
    1729             : #ifdef MOZ_ACCESSIBILITY_ATK
    1730           0 :   ApplicationAccessible* applicationAcc = ApplicationAcc();
    1731             : 
    1732           0 :   if (applicationAcc)
    1733           0 :     applicationAcc->RemoveChild(aAccessible);
    1734             : #endif
    1735           0 : }
    1736             : 
    1737             : bool
    1738           0 : nsAccessibilityService::HasAccessible(nsIDOMNode* aDOMNode)
    1739             : {
    1740           0 :   nsCOMPtr<nsINode> node(do_QueryInterface(aDOMNode));
    1741           0 :   if (!node)
    1742           0 :     return false;
    1743             : 
    1744           0 :   DocAccessible* document = GetDocAccessible(node->OwnerDoc());
    1745           0 :   if (!document)
    1746           0 :     return false;
    1747             : 
    1748           0 :   return document->HasAccessible(node);
    1749             : }
    1750             : 
    1751             : ////////////////////////////////////////////////////////////////////////////////
    1752             : // nsAccessibilityService private (DON'T put methods here)
    1753             : 
    1754             : #ifdef MOZ_XUL
    1755             : already_AddRefed<Accessible>
    1756           0 : nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
    1757             :                                                    DocAccessible* aDoc)
    1758             : {
    1759           0 :   nsIContent* child = nsTreeUtils::GetDescendantChild(aContent,
    1760           0 :                                                       nsGkAtoms::treechildren);
    1761           0 :   if (!child)
    1762           0 :     return nullptr;
    1763             : 
    1764           0 :   nsTreeBodyFrame* treeFrame = do_QueryFrame(child->GetPrimaryFrame());
    1765           0 :   if (!treeFrame)
    1766           0 :     return nullptr;
    1767             : 
    1768           0 :   RefPtr<nsTreeColumns> treeCols = treeFrame->Columns();
    1769           0 :   int32_t count = 0;
    1770           0 :   treeCols->GetCount(&count);
    1771             : 
    1772             :   // Outline of list accessible.
    1773           0 :   if (count == 1) {
    1774             :     RefPtr<Accessible> accessible =
    1775           0 :       new XULTreeAccessible(aContent, aDoc, treeFrame);
    1776           0 :     return accessible.forget();
    1777             :   }
    1778             : 
    1779             :   // Table or tree table accessible.
    1780             :   RefPtr<Accessible> accessible =
    1781           0 :     new XULTreeGridAccessibleWrap(aContent, aDoc, treeFrame);
    1782           0 :   return accessible.forget();
    1783             : }
    1784             : #endif
    1785             : 
    1786             : nsAccessibilityService*
    1787           0 : GetOrCreateAccService(uint32_t aNewConsumer)
    1788             : {
    1789           0 :   if (!nsAccessibilityService::gAccessibilityService) {
    1790           0 :     RefPtr<nsAccessibilityService> service = new nsAccessibilityService();
    1791           0 :     if (!service->Init()) {
    1792           0 :       service->Shutdown();
    1793           0 :       return nullptr;
    1794             :     }
    1795             :   }
    1796             : 
    1797           0 :   MOZ_ASSERT(nsAccessibilityService::gAccessibilityService,
    1798             :              "Accessible service is not initialized.");
    1799           0 :   nsAccessibilityService::gConsumers |= aNewConsumer;
    1800           0 :   return nsAccessibilityService::gAccessibilityService;
    1801             : }
    1802             : 
    1803             : void
    1804           0 : MaybeShutdownAccService(uint32_t aFormerConsumer)
    1805             : {
    1806             :   nsAccessibilityService* accService =
    1807           0 :     nsAccessibilityService::gAccessibilityService;
    1808             : 
    1809           0 :   if (!accService || accService->IsShutdown()) {
    1810           0 :     return;
    1811             :   }
    1812             : 
    1813           0 :   if (nsCoreUtils::AccEventObserversExist() ||
    1814           0 :       xpcAccessibilityService::IsInUse() ||
    1815           0 :       accService->HasXPCDocuments()) {
    1816             :     // Still used by XPCOM
    1817           0 :     nsAccessibilityService::gConsumers =
    1818           0 :       (nsAccessibilityService::gConsumers & ~aFormerConsumer) |
    1819             :       nsAccessibilityService::eXPCOM;
    1820           0 :     return;
    1821             :   }
    1822             : 
    1823           0 :   if (nsAccessibilityService::gConsumers & ~aFormerConsumer) {
    1824           0 :     nsAccessibilityService::gConsumers &= ~aFormerConsumer;
    1825             :   } else {
    1826           0 :     accService->Shutdown(); // Will unset all nsAccessibilityService::gConsumers
    1827             :   }
    1828             : }
    1829             : 
    1830             : ////////////////////////////////////////////////////////////////////////////////
    1831             : // Services
    1832             : ////////////////////////////////////////////////////////////////////////////////
    1833             : 
    1834             : namespace mozilla {
    1835             : namespace a11y {
    1836             : 
    1837             : FocusManager*
    1838           0 : FocusMgr()
    1839             : {
    1840           0 :   return nsAccessibilityService::gAccessibilityService;
    1841             : }
    1842             : 
    1843             : SelectionManager*
    1844           0 : SelectionMgr()
    1845             : {
    1846           0 :   return nsAccessibilityService::gAccessibilityService;
    1847             : }
    1848             : 
    1849             : ApplicationAccessible*
    1850           0 : ApplicationAcc()
    1851             : {
    1852           0 :   return nsAccessibilityService::gApplicationAccessible;
    1853             : }
    1854             : 
    1855             : xpcAccessibleApplication*
    1856           0 : XPCApplicationAcc()
    1857             : {
    1858           0 :   if (!nsAccessibilityService::gXPCApplicationAccessible &&
    1859           0 :       nsAccessibilityService::gApplicationAccessible) {
    1860           0 :     nsAccessibilityService::gXPCApplicationAccessible =
    1861           0 :       new xpcAccessibleApplication(nsAccessibilityService::gApplicationAccessible);
    1862           0 :     NS_ADDREF(nsAccessibilityService::gXPCApplicationAccessible);
    1863             :   }
    1864             : 
    1865           0 :   return nsAccessibilityService::gXPCApplicationAccessible;
    1866             : }
    1867             : 
    1868             : EPlatformDisabledState
    1869           1 : PlatformDisabledState()
    1870             : {
    1871             :   static int disabledState = 0xff;
    1872             : 
    1873           1 :   if (disabledState == 0xff) {
    1874           1 :     disabledState = Preferences::GetInt("accessibility.force_disabled", 0);
    1875           1 :     if (disabledState < ePlatformIsForceEnabled)
    1876           0 :       disabledState = ePlatformIsForceEnabled;
    1877           1 :     else if (disabledState > ePlatformIsDisabled)
    1878           0 :       disabledState = ePlatformIsDisabled;
    1879             :   }
    1880             : 
    1881           1 :   return (EPlatformDisabledState)disabledState;
    1882             : }
    1883             : 
    1884             : }
    1885             : }

Generated by: LCOV version 1.13