LCOV - code coverage report
Current view: directory - accessible/src/base - nsAccessible.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 1638 2 0.1 %
Date: 2012-06-02 Functions: 150 2 1.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   John Gaunt (jgaunt@netscape.com)
      24                 :  *   Aaron Leventhal (aaronl@netscape.com)
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : #include "nsAccessible.h"
      41                 : 
      42                 : #include "nsIXBLAccessible.h"
      43                 : 
      44                 : #include "AccGroupInfo.h"
      45                 : #include "AccIterator.h"
      46                 : #include "nsAccUtils.h"
      47                 : #include "nsAccEvent.h"
      48                 : #include "nsAccessibleRelation.h"
      49                 : #include "nsAccessibilityService.h"
      50                 : #include "nsAccTreeWalker.h"
      51                 : #include "nsIAccessibleRelation.h"
      52                 : #include "nsEventShell.h"
      53                 : #include "nsRootAccessible.h"
      54                 : #include "nsTextEquivUtils.h"
      55                 : #include "Relation.h"
      56                 : #include "Role.h"
      57                 : #include "States.h"
      58                 : #include "StyleInfo.h"
      59                 : 
      60                 : #include "nsIDOMCSSValue.h"
      61                 : #include "nsIDOMCSSPrimitiveValue.h"
      62                 : #include "nsIDOMElement.h"
      63                 : #include "nsIDOMDocument.h"
      64                 : #include "nsIDOMDocumentXBL.h"
      65                 : #include "nsIDOMHTMLDocument.h"
      66                 : #include "nsIDOMHTMLFormElement.h"
      67                 : #include "nsIDOMNodeFilter.h"
      68                 : #include "nsIDOMHTMLElement.h"
      69                 : #include "nsIDOMTreeWalker.h"
      70                 : #include "nsIDOMXULButtonElement.h"
      71                 : #include "nsIDOMXULDocument.h"
      72                 : #include "nsIDOMXULElement.h"
      73                 : #include "nsIDOMXULLabelElement.h"
      74                 : #include "nsIDOMXULSelectCntrlEl.h"
      75                 : #include "nsIDOMXULSelectCntrlItemEl.h"
      76                 : #include "nsPIDOMWindow.h"
      77                 : 
      78                 : #include "nsIDocument.h"
      79                 : #include "nsIContent.h"
      80                 : #include "nsIForm.h"
      81                 : #include "nsIFormControl.h"
      82                 : 
      83                 : #include "nsLayoutUtils.h"
      84                 : #include "nsIPresShell.h"
      85                 : #include "nsPresContext.h"
      86                 : #include "nsIFrame.h"
      87                 : #include "nsIView.h"
      88                 : #include "nsIDocShellTreeItem.h"
      89                 : #include "nsIScrollableFrame.h"
      90                 : #include "nsFocusManager.h"
      91                 : 
      92                 : #include "nsXPIDLString.h"
      93                 : #include "nsUnicharUtils.h"
      94                 : #include "nsReadableUtils.h"
      95                 : #include "prdtoa.h"
      96                 : #include "nsIAtom.h"
      97                 : #include "nsIURI.h"
      98                 : #include "nsArrayUtils.h"
      99                 : #include "nsIMutableArray.h"
     100                 : #include "nsIObserverService.h"
     101                 : #include "nsIServiceManager.h"
     102                 : #include "nsWhitespaceTokenizer.h"
     103                 : #include "nsAttrName.h"
     104                 : #include "nsNetUtil.h"
     105                 : #include "nsEventStates.h"
     106                 : 
     107                 : #ifdef NS_DEBUG
     108                 : #include "nsIDOMCharacterData.h"
     109                 : #endif
     110                 : 
     111                 : #include "mozilla/unused.h"
     112                 : #include "mozilla/Preferences.h"
     113                 : #include "mozilla/dom/Element.h"
     114                 : 
     115                 : using namespace mozilla;
     116                 : using namespace mozilla::a11y;
     117                 : 
     118                 : 
     119                 : ////////////////////////////////////////////////////////////////////////////////
     120                 : // nsAccessible. nsISupports
     121                 : 
     122            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsAccessible)
     123                 : 
     124               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsAccessible, nsAccessNode)
     125               0 :   NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mParent");
     126               0 :   cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mParent.get()));
     127                 : 
     128               0 :   PRUint32 i, length = tmp->mChildren.Length();
     129               0 :   for (i = 0; i < length; ++i) {
     130               0 :     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
     131               0 :     cb.NoteXPCOMChild(static_cast<nsIAccessible*>(tmp->mChildren[i].get()));
     132                 :   }
     133               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     134                 : 
     135               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsAccessible, nsAccessNode)
     136               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParent)
     137               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSTARRAY(mChildren)
     138               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     139                 : 
     140               0 : NS_IMPL_ADDREF_INHERITED(nsAccessible, nsAccessNode)
     141               0 : NS_IMPL_RELEASE_INHERITED(nsAccessible, nsAccessNode)
     142                 : 
     143               0 : nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
     144                 : {
     145                 :   // Custom-built QueryInterface() knows when we support nsIAccessibleSelectable
     146                 :   // based on role attribute and aria-multiselectable
     147               0 :   *aInstancePtr = nsnull;
     148                 : 
     149               0 :   if (aIID.Equals(NS_GET_IID(nsXPCOMCycleCollectionParticipant))) {
     150               0 :     *aInstancePtr = &NS_CYCLE_COLLECTION_NAME(nsAccessible);
     151               0 :     return NS_OK;
     152                 :   }
     153                 : 
     154               0 :   if (aIID.Equals(NS_GET_IID(nsIAccessible))) {
     155               0 :     *aInstancePtr = static_cast<nsIAccessible*>(this);
     156               0 :     NS_ADDREF_THIS();
     157               0 :     return NS_OK;
     158                 :   }
     159                 : 
     160               0 :   if (aIID.Equals(NS_GET_IID(nsAccessible))) {
     161               0 :     *aInstancePtr = static_cast<nsAccessible*>(this);
     162               0 :     NS_ADDREF_THIS();
     163               0 :     return NS_OK;
     164                 :   }
     165                 : 
     166               0 :   if (aIID.Equals(NS_GET_IID(nsIAccessibleSelectable))) {
     167               0 :     if (IsSelect()) {
     168               0 :       *aInstancePtr = static_cast<nsIAccessibleSelectable*>(this);
     169               0 :       NS_ADDREF_THIS();
     170               0 :       return NS_OK;
     171                 :     }
     172               0 :     return NS_ERROR_NO_INTERFACE;
     173                 :   }
     174                 : 
     175               0 :   if (aIID.Equals(NS_GET_IID(nsIAccessibleValue))) {
     176               0 :     if (mRoleMapEntry && mRoleMapEntry->valueRule != eNoValue) {
     177               0 :       *aInstancePtr = static_cast<nsIAccessibleValue*>(this);
     178               0 :       NS_ADDREF_THIS();
     179               0 :       return NS_OK;
     180                 :     }
     181                 :   }                       
     182                 : 
     183               0 :   if (aIID.Equals(NS_GET_IID(nsIAccessibleHyperLink))) {
     184               0 :     if (IsLink()) {
     185               0 :       *aInstancePtr = static_cast<nsIAccessibleHyperLink*>(this);
     186               0 :       NS_ADDREF_THIS();
     187               0 :       return NS_OK;
     188                 :     }
     189               0 :     return NS_ERROR_NO_INTERFACE;
     190                 :   }
     191                 : 
     192               0 :   return nsAccessNodeWrap::QueryInterface(aIID, aInstancePtr);
     193                 : }
     194                 : 
     195               0 : nsAccessible::nsAccessible(nsIContent* aContent, nsDocAccessible* aDoc) :
     196                 :   nsAccessNodeWrap(aContent, aDoc),
     197                 :   mParent(nsnull), mIndexInParent(-1), mFlags(eChildrenUninitialized),
     198               0 :   mIndexOfEmbeddedChild(-1), mRoleMapEntry(nsnull)
     199                 : {
     200                 : #ifdef NS_DEBUG_X
     201                 :    {
     202                 :      nsCOMPtr<nsIPresShell> shell(do_QueryReferent(aShell));
     203                 :      printf(">>> %p Created Acc - DOM: %p  PS: %p", 
     204                 :             (void*)static_cast<nsIAccessible*>(this), (void*)aNode,
     205                 :             (void*)shell.get());
     206                 :     nsCOMPtr<nsIContent> content = do_QueryInterface(aNode);
     207                 :     if (content) {
     208                 :       printf(" Con: %s@%p",
     209                 :              NS_ConvertUTF16toUTF8(content->NodeInfo()->QualifiedName()).get(),
     210                 :              (void *)content.get());
     211                 :       nsAutoString buf;
     212                 :       if (NS_SUCCEEDED(GetName(buf))) {
     213                 :         printf(" Name:[%s]", NS_ConvertUTF16toUTF8(buf).get());
     214                 :        }
     215                 :      }
     216                 :      printf("\n");
     217                 :    }
     218                 : #endif
     219               0 : }
     220                 : 
     221                 : //-----------------------------------------------------
     222                 : // destruction
     223                 : //-----------------------------------------------------
     224               0 : nsAccessible::~nsAccessible()
     225                 : {
     226               0 : }
     227                 : 
     228                 : void
     229               0 : nsAccessible::SetRoleMapEntry(nsRoleMapEntry* aRoleMapEntry)
     230                 : {
     231               0 :   mRoleMapEntry = aRoleMapEntry;
     232               0 : }
     233                 : 
     234                 : NS_IMETHODIMP
     235               0 : nsAccessible::GetDocument(nsIAccessibleDocument **aDocument)
     236                 : {
     237               0 :   NS_ENSURE_ARG_POINTER(aDocument);
     238                 : 
     239               0 :   NS_IF_ADDREF(*aDocument = Document());
     240               0 :   return NS_OK;
     241                 : }
     242                 : 
     243                 : NS_IMETHODIMP
     244               0 : nsAccessible::GetDOMNode(nsIDOMNode **aDOMNode)
     245                 : {
     246               0 :   NS_ENSURE_ARG_POINTER(aDOMNode);
     247               0 :   *aDOMNode = nsnull;
     248                 : 
     249               0 :   nsINode *node = GetNode();
     250               0 :   if (node)
     251               0 :     CallQueryInterface(node, aDOMNode);
     252                 : 
     253               0 :   return NS_OK;
     254                 : }
     255                 : 
     256                 : NS_IMETHODIMP
     257               0 : nsAccessible::GetRootDocument(nsIAccessibleDocument **aRootDocument)
     258                 : {
     259               0 :   NS_ENSURE_ARG_POINTER(aRootDocument);
     260                 : 
     261               0 :   nsRootAccessible* rootDocument = RootAccessible();
     262               0 :   NS_IF_ADDREF(*aRootDocument = rootDocument);
     263               0 :   return NS_OK;
     264                 : }
     265                 : 
     266                 : NS_IMETHODIMP
     267               0 : nsAccessible::GetInnerHTML(nsAString& aInnerHTML)
     268                 : {
     269               0 :   aInnerHTML.Truncate();
     270                 : 
     271               0 :   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent);
     272               0 :   NS_ENSURE_TRUE(htmlElement, NS_ERROR_NULL_POINTER);
     273                 : 
     274               0 :   return htmlElement->GetInnerHTML(aInnerHTML);
     275                 : }
     276                 : 
     277                 : NS_IMETHODIMP
     278               0 : nsAccessible::GetLanguage(nsAString& aLanguage)
     279                 : {
     280               0 :   Language(aLanguage);
     281               0 :   return NS_OK;
     282                 : }
     283                 : 
     284                 : NS_IMETHODIMP
     285               0 : nsAccessible::GetName(nsAString& aName)
     286                 : {
     287               0 :   aName.Truncate();
     288                 : 
     289               0 :   if (IsDefunct())
     290               0 :     return NS_ERROR_FAILURE;
     291                 : 
     292               0 :   GetARIAName(aName);
     293               0 :   if (!aName.IsEmpty())
     294               0 :     return NS_OK;
     295                 : 
     296               0 :   nsCOMPtr<nsIXBLAccessible> xblAccessible(do_QueryInterface(mContent));
     297               0 :   if (xblAccessible) {
     298               0 :     xblAccessible->GetAccessibleName(aName);
     299               0 :     if (!aName.IsEmpty())
     300               0 :       return NS_OK;
     301                 :   }
     302                 : 
     303               0 :   nsresult rv = GetNameInternal(aName);
     304               0 :   NS_ENSURE_SUCCESS(rv, rv);
     305                 : 
     306               0 :   if (!aName.IsEmpty())
     307               0 :     return NS_OK;
     308                 : 
     309                 :   // In the end get the name from tooltip.
     310               0 :   nsIAtom *tooltipAttr = nsnull;
     311                 : 
     312               0 :   if (mContent->IsHTML())
     313               0 :     tooltipAttr = nsGkAtoms::title;
     314               0 :   else if (mContent->IsXUL())
     315               0 :     tooltipAttr = nsGkAtoms::tooltiptext;
     316                 :   else
     317               0 :     return NS_OK;
     318                 : 
     319                 :   // XXX: if CompressWhiteSpace worked on nsAString we could avoid a copy.
     320               0 :   nsAutoString name;
     321               0 :   if (mContent->GetAttr(kNameSpaceID_None, tooltipAttr, name)) {
     322               0 :     name.CompressWhitespace();
     323               0 :     aName = name;
     324               0 :     return NS_OK_NAME_FROM_TOOLTIP;
     325                 :   }
     326                 : 
     327               0 :   if (rv != NS_OK_EMPTY_NAME)
     328               0 :     aName.SetIsVoid(true);
     329                 : 
     330               0 :   return NS_OK;
     331                 : }
     332                 : 
     333                 : NS_IMETHODIMP
     334               0 : nsAccessible::GetDescription(nsAString& aDescription)
     335                 : {
     336               0 :   if (IsDefunct())
     337               0 :     return NS_ERROR_FAILURE;
     338                 : 
     339               0 :   nsAutoString desc;
     340               0 :   Description(desc);
     341               0 :   aDescription.Assign(desc);
     342                 : 
     343               0 :   return NS_OK;
     344                 : }
     345                 : 
     346                 : void
     347               0 : nsAccessible::Description(nsString& aDescription)
     348                 : {
     349                 :   // There are 4 conditions that make an accessible have no accDescription:
     350                 :   // 1. it's a text node; or
     351                 :   // 2. It has no DHTML describedby property
     352                 :   // 3. it doesn't have an accName; or
     353                 :   // 4. its title attribute already equals to its accName nsAutoString name; 
     354                 : 
     355               0 :   if (mContent->IsNodeOfType(nsINode::eTEXT))
     356               0 :     return;
     357                 : 
     358                 :   nsTextEquivUtils::
     359                 :     GetTextEquivFromIDRefs(this, nsGkAtoms::aria_describedby,
     360               0 :                            aDescription);
     361                 : 
     362               0 :   if (aDescription.IsEmpty()) {
     363               0 :     bool isXUL = mContent->IsXUL();
     364               0 :     if (isXUL) {
     365                 :       // Try XUL <description control="[id]">description text</description>
     366               0 :       XULDescriptionIterator iter(Document(), mContent);
     367               0 :       nsAccessible* descr = nsnull;
     368               0 :       while ((descr = iter.Next()))
     369                 :         nsTextEquivUtils::AppendTextEquivFromContent(this, descr->GetContent(),
     370               0 :                                                      &aDescription);
     371                 :       }
     372                 : 
     373               0 :       if (aDescription.IsEmpty()) {
     374                 :         nsIAtom *descAtom = isXUL ? nsGkAtoms::tooltiptext :
     375               0 :                                     nsGkAtoms::title;
     376               0 :         if (mContent->GetAttr(kNameSpaceID_None, descAtom, aDescription)) {
     377               0 :           nsAutoString name;
     378               0 :           GetName(name);
     379               0 :           if (name.IsEmpty() || aDescription == name)
     380                 :             // Don't use tooltip for a description if this object
     381                 :             // has no name or the tooltip is the same as the name
     382               0 :             aDescription.Truncate();
     383                 :         }
     384                 :       }
     385                 :     }
     386               0 :     aDescription.CompressWhitespace();
     387                 : }
     388                 : 
     389                 : NS_IMETHODIMP
     390               0 : nsAccessible::GetKeyboardShortcut(nsAString& aAccessKey)
     391                 : {
     392               0 :   aAccessKey.Truncate();
     393                 : 
     394               0 :   if (IsDefunct())
     395               0 :     return NS_ERROR_FAILURE;
     396                 : 
     397               0 :   AccessKey().ToString(aAccessKey);
     398               0 :   return NS_OK;
     399                 : }
     400                 : 
     401                 : KeyBinding
     402               0 : nsAccessible::AccessKey() const
     403                 : {
     404               0 :   PRUint32 key = nsCoreUtils::GetAccessKeyFor(mContent);
     405               0 :   if (!key && mContent->IsElement()) {
     406               0 :     nsAccessible* label = nsnull;
     407                 : 
     408                 :     // Copy access key from label node.
     409               0 :     if (mContent->IsHTML()) {
     410                 :       // Unless it is labeled via an ancestor <label>, in which case that would
     411                 :       // be redundant.
     412                 :       HTMLLabelIterator iter(Document(), this,
     413               0 :                              HTMLLabelIterator::eSkipAncestorLabel);
     414               0 :       label = iter.Next();
     415                 : 
     416               0 :     } else if (mContent->IsXUL()) {
     417               0 :       XULLabelIterator iter(Document(), mContent);
     418               0 :       label = iter.Next();
     419                 :     }
     420                 : 
     421               0 :     if (label)
     422               0 :       key = nsCoreUtils::GetAccessKeyFor(label->GetContent());
     423                 :   }
     424                 : 
     425               0 :   if (!key)
     426               0 :     return KeyBinding();
     427                 : 
     428                 :   // Get modifier mask. Use ui.key.generalAccessKey (unless it is -1).
     429               0 :   switch (Preferences::GetInt("ui.key.generalAccessKey", -1)) {
     430                 :   case -1:
     431                 :     break;
     432                 :   case nsIDOMKeyEvent::DOM_VK_SHIFT:
     433               0 :     return KeyBinding(key, KeyBinding::kShift);
     434                 :   case nsIDOMKeyEvent::DOM_VK_CONTROL:
     435               0 :     return KeyBinding(key, KeyBinding::kControl);
     436                 :   case nsIDOMKeyEvent::DOM_VK_ALT:
     437               0 :     return KeyBinding(key, KeyBinding::kAlt);
     438                 :   case nsIDOMKeyEvent::DOM_VK_META:
     439               0 :     return KeyBinding(key, KeyBinding::kMeta);
     440                 :   default:
     441               0 :     return KeyBinding();
     442                 :   }
     443                 : 
     444                 :   // Determine the access modifier used in this context.
     445               0 :   nsIDocument* document = mContent->GetCurrentDoc();
     446               0 :   if (!document)
     447               0 :     return KeyBinding();
     448               0 :   nsCOMPtr<nsISupports> container = document->GetContainer();
     449               0 :   if (!container)
     450               0 :     return KeyBinding();
     451               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(container));
     452               0 :   if (!treeItem)
     453               0 :     return KeyBinding();
     454                 : 
     455               0 :   nsresult rv = NS_ERROR_FAILURE;
     456               0 :   PRInt32 itemType = 0, modifierMask = 0;
     457               0 :   treeItem->GetItemType(&itemType);
     458               0 :   switch (itemType) {
     459                 :     case nsIDocShellTreeItem::typeChrome:
     460               0 :       rv = Preferences::GetInt("ui.key.chromeAccess", &modifierMask);
     461               0 :       break;
     462                 :     case nsIDocShellTreeItem::typeContent:
     463               0 :       rv = Preferences::GetInt("ui.key.contentAccess", &modifierMask);
     464               0 :       break;
     465                 :   }
     466                 : 
     467               0 :   return NS_SUCCEEDED(rv) ? KeyBinding(key, modifierMask) : KeyBinding();
     468                 : }
     469                 : 
     470                 : KeyBinding
     471               0 : nsAccessible::KeyboardShortcut() const
     472                 : {
     473               0 :   return KeyBinding();
     474                 : }
     475                 : 
     476                 : NS_IMETHODIMP
     477               0 : nsAccessible::GetParent(nsIAccessible **aParent)
     478                 : {
     479               0 :   NS_ENSURE_ARG_POINTER(aParent);
     480               0 :   if (IsDefunct())
     481               0 :     return NS_ERROR_FAILURE;
     482                 : 
     483               0 :   NS_IF_ADDREF(*aParent = Parent());
     484               0 :   return *aParent ? NS_OK : NS_ERROR_FAILURE;
     485                 : }
     486                 : 
     487                 :   /* readonly attribute nsIAccessible nextSibling; */
     488                 : NS_IMETHODIMP
     489               0 : nsAccessible::GetNextSibling(nsIAccessible **aNextSibling) 
     490                 : {
     491               0 :   NS_ENSURE_ARG_POINTER(aNextSibling);
     492               0 :   *aNextSibling = nsnull;
     493                 : 
     494               0 :   if (IsDefunct())
     495               0 :     return NS_ERROR_FAILURE;
     496                 : 
     497               0 :   nsresult rv = NS_OK;
     498               0 :   NS_IF_ADDREF(*aNextSibling = GetSiblingAtOffset(1, &rv));
     499               0 :   return rv;
     500                 : }
     501                 : 
     502                 :   /* readonly attribute nsIAccessible previousSibling; */
     503                 : NS_IMETHODIMP
     504               0 : nsAccessible::GetPreviousSibling(nsIAccessible * *aPreviousSibling) 
     505                 : {
     506               0 :   NS_ENSURE_ARG_POINTER(aPreviousSibling);
     507               0 :   *aPreviousSibling = nsnull;
     508                 : 
     509               0 :   if (IsDefunct())
     510               0 :     return NS_ERROR_FAILURE;
     511                 : 
     512               0 :   nsresult rv = NS_OK;
     513               0 :   NS_IF_ADDREF(*aPreviousSibling = GetSiblingAtOffset(-1, &rv));
     514               0 :   return rv;
     515                 : }
     516                 : 
     517                 :   /* readonly attribute nsIAccessible firstChild; */
     518                 : NS_IMETHODIMP
     519               0 : nsAccessible::GetFirstChild(nsIAccessible **aFirstChild) 
     520                 : {
     521               0 :   NS_ENSURE_ARG_POINTER(aFirstChild);
     522               0 :   *aFirstChild = nsnull;
     523                 : 
     524               0 :   if (IsDefunct())
     525               0 :     return NS_ERROR_FAILURE;
     526                 : 
     527               0 :   PRInt32 childCount = GetChildCount();
     528               0 :   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
     529                 : 
     530               0 :   if (childCount > 0)
     531               0 :     NS_ADDREF(*aFirstChild = GetChildAt(0));
     532                 : 
     533               0 :   return NS_OK;
     534                 : }
     535                 : 
     536                 :   /* readonly attribute nsIAccessible lastChild; */
     537                 : NS_IMETHODIMP
     538               0 : nsAccessible::GetLastChild(nsIAccessible **aLastChild)
     539                 : {
     540               0 :   NS_ENSURE_ARG_POINTER(aLastChild);
     541               0 :   *aLastChild = nsnull;
     542                 : 
     543               0 :   if (IsDefunct())
     544               0 :     return NS_ERROR_FAILURE;
     545                 : 
     546               0 :   PRInt32 childCount = GetChildCount();
     547               0 :   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
     548                 : 
     549               0 :   NS_IF_ADDREF(*aLastChild = GetChildAt(childCount - 1));
     550               0 :   return NS_OK;
     551                 : }
     552                 : 
     553                 : NS_IMETHODIMP
     554               0 : nsAccessible::GetChildAt(PRInt32 aChildIndex, nsIAccessible **aChild)
     555                 : {
     556               0 :   NS_ENSURE_ARG_POINTER(aChild);
     557               0 :   *aChild = nsnull;
     558                 : 
     559               0 :   if (IsDefunct())
     560               0 :     return NS_ERROR_FAILURE;
     561                 : 
     562               0 :   PRInt32 childCount = GetChildCount();
     563               0 :   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
     564                 : 
     565                 :   // If child index is negative, then return last child.
     566                 :   // XXX: do we really need this?
     567               0 :   if (aChildIndex < 0)
     568               0 :     aChildIndex = childCount - 1;
     569                 : 
     570               0 :   nsAccessible* child = GetChildAt(aChildIndex);
     571               0 :   if (!child)
     572               0 :     return NS_ERROR_INVALID_ARG;
     573                 : 
     574               0 :   NS_ADDREF(*aChild = child);
     575               0 :   return NS_OK;
     576                 : }
     577                 : 
     578                 : // readonly attribute nsIArray children;
     579                 : NS_IMETHODIMP
     580               0 : nsAccessible::GetChildren(nsIArray **aOutChildren)
     581                 : {
     582               0 :   NS_ENSURE_ARG_POINTER(aOutChildren);
     583               0 :   *aOutChildren = nsnull;
     584                 : 
     585               0 :   if (IsDefunct())
     586               0 :     return NS_ERROR_FAILURE;
     587                 : 
     588               0 :   PRInt32 childCount = GetChildCount();
     589               0 :   NS_ENSURE_TRUE(childCount != -1, NS_ERROR_FAILURE);
     590                 : 
     591               0 :   nsresult rv = NS_OK;
     592                 :   nsCOMPtr<nsIMutableArray> children =
     593               0 :     do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     594               0 :   NS_ENSURE_SUCCESS(rv, rv);
     595                 : 
     596               0 :   for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
     597               0 :     nsIAccessible* child = GetChildAt(childIdx);
     598               0 :     children->AppendElement(child, false);
     599                 :   }
     600                 : 
     601               0 :   NS_ADDREF(*aOutChildren = children);
     602               0 :   return NS_OK;
     603                 : }
     604                 : 
     605                 : bool
     606               0 : nsAccessible::CanHaveAnonChildren()
     607                 : {
     608               0 :   return true;
     609                 : }
     610                 : 
     611                 : /* readonly attribute long childCount; */
     612                 : NS_IMETHODIMP
     613               0 : nsAccessible::GetChildCount(PRInt32 *aChildCount) 
     614                 : {
     615               0 :   NS_ENSURE_ARG_POINTER(aChildCount);
     616                 : 
     617               0 :   if (IsDefunct())
     618               0 :     return NS_ERROR_FAILURE;
     619                 : 
     620               0 :   *aChildCount = GetChildCount();
     621               0 :   return *aChildCount != -1 ? NS_OK : NS_ERROR_FAILURE;  
     622                 : }
     623                 : 
     624                 : /* readonly attribute long indexInParent; */
     625                 : NS_IMETHODIMP
     626               0 : nsAccessible::GetIndexInParent(PRInt32 *aIndexInParent)
     627                 : {
     628               0 :   NS_ENSURE_ARG_POINTER(aIndexInParent);
     629                 : 
     630               0 :   *aIndexInParent = IndexInParent();
     631               0 :   return *aIndexInParent != -1 ? NS_OK : NS_ERROR_FAILURE;
     632                 : }
     633                 : 
     634                 : void 
     635               0 : nsAccessible::TranslateString(const nsAString& aKey, nsAString& aStringOut)
     636                 : {
     637               0 :   nsXPIDLString xsValue;
     638                 : 
     639               0 :   gStringBundle->GetStringFromName(PromiseFlatString(aKey).get(), getter_Copies(xsValue));
     640               0 :   aStringOut.Assign(xsValue);
     641               0 : }
     642                 : 
     643                 : PRUint64
     644               0 : nsAccessible::VisibilityState()
     645                 : {
     646               0 :   PRUint64 vstates = states::INVISIBLE | states::OFFSCREEN;
     647                 : 
     648               0 :   nsIFrame* frame = GetFrame();
     649               0 :   if (!frame)
     650               0 :     return vstates;
     651                 : 
     652               0 :   nsIPresShell* shell(mDoc->PresShell());
     653               0 :   if (!shell)
     654               0 :     return vstates;
     655                 : 
     656                 :   // We need to know if at least a kMinPixels around the object is visible,
     657                 :   // otherwise it will be marked states::OFFSCREEN.
     658               0 :   const PRUint16 kMinPixels  = 12;
     659               0 :   const nsSize frameSize = frame->GetSize();
     660                 :   const nsRectVisibility rectVisibility =
     661               0 :     shell->GetRectVisibility(frame, nsRect(nsPoint(0,0), frameSize),
     662               0 :                              nsPresContext::CSSPixelsToAppUnits(kMinPixels));
     663                 : 
     664               0 :   if (rectVisibility == nsRectVisibility_kVisible)
     665               0 :     vstates &= ~states::OFFSCREEN;
     666                 : 
     667                 :   // Zero area rects can occur in the first frame of a multi-frame text flow,
     668                 :   // in which case the rendered text is not empty and the frame should not be
     669                 :   // marked invisible.
     670                 :   // XXX Can we just remove this check? Why do we need to mark empty
     671                 :   // text invisible?
     672               0 :   if (frame->GetType() == nsGkAtoms::textFrame &&
     673               0 :       !(frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
     674               0 :       frame->GetRect().IsEmpty()) {
     675               0 :     nsAutoString renderedText;
     676               0 :     frame->GetRenderedText(&renderedText, nsnull, nsnull, 0, 1);
     677               0 :     if (renderedText.IsEmpty())
     678               0 :       return vstates;
     679                 : 
     680                 :   }
     681                 : 
     682                 :   // XXX Do we really need to cross from content to chrome ancestor?
     683               0 :   if (!frame->IsVisibleConsideringAncestors(nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY))
     684               0 :     return vstates;
     685                 : 
     686                 :   // Assume we are visible enough.
     687               0 :   return vstates &= ~states::INVISIBLE;
     688                 : }
     689                 : 
     690                 : PRUint64
     691               0 : nsAccessible::NativeState()
     692                 : {
     693               0 :   PRUint64 state = 0;
     694                 : 
     695               0 :   nsDocAccessible* document = Document();
     696               0 :   if (!document || !document->IsInDocument(this))
     697               0 :     state |= states::STALE;
     698                 : 
     699               0 :   bool disabled = false;
     700               0 :   if (mContent->IsElement()) {
     701               0 :     nsEventStates elementState = mContent->AsElement()->State();
     702                 : 
     703               0 :     if (elementState.HasState(NS_EVENT_STATE_INVALID))
     704               0 :       state |= states::INVALID;
     705                 : 
     706               0 :     if (elementState.HasState(NS_EVENT_STATE_REQUIRED))
     707               0 :       state |= states::REQUIRED;
     708                 : 
     709               0 :     disabled = mContent->IsHTML() ? 
     710               0 :       (elementState.HasState(NS_EVENT_STATE_DISABLED)) :
     711               0 :       (mContent->AttrValueIs(kNameSpaceID_None,
     712                 :                              nsGkAtoms::disabled,
     713                 :                              nsGkAtoms::_true,
     714               0 :                              eCaseMatters));
     715                 :   }
     716                 : 
     717                 :   // Set unavailable state based on disabled state, otherwise set focus states
     718               0 :   if (disabled) {
     719               0 :     state |= states::UNAVAILABLE;
     720                 :   }
     721               0 :   else if (mContent->IsElement()) {
     722               0 :     nsIFrame* frame = GetFrame();
     723               0 :     if (frame && frame->IsFocusable())
     724               0 :       state |= states::FOCUSABLE;
     725                 : 
     726               0 :     if (FocusMgr()->IsFocused(this))
     727               0 :       state |= states::FOCUSED;
     728                 :   }
     729                 : 
     730                 :   // Gather states::INVISIBLE and states::OFFSCREEN flags for this object.
     731               0 :   state |= VisibilityState();
     732                 : 
     733               0 :   nsIFrame *frame = GetFrame();
     734               0 :   if (frame && (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW))
     735               0 :     state |= states::FLOATING;
     736                 : 
     737                 :   // Check if a XUL element has the popup attribute (an attached popup menu).
     738               0 :   if (mContent->IsXUL())
     739               0 :     if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::popup))
     740               0 :       state |= states::HASPOPUP;
     741                 : 
     742                 :   // Add 'linked' state for simple xlink.
     743               0 :   if (nsCoreUtils::IsXLink(mContent))
     744               0 :     state |= states::LINKED;
     745                 : 
     746               0 :   return state;
     747                 : }
     748                 : 
     749                 :   /* readonly attribute boolean focusedChild; */
     750                 : NS_IMETHODIMP
     751               0 : nsAccessible::GetFocusedChild(nsIAccessible** aChild)
     752                 : {
     753               0 :   NS_ENSURE_ARG_POINTER(aChild);
     754               0 :   *aChild = nsnull;
     755                 : 
     756               0 :   if (IsDefunct())
     757               0 :     return NS_ERROR_FAILURE;
     758                 : 
     759               0 :   NS_IF_ADDREF(*aChild = FocusedChild());
     760               0 :   return NS_OK;
     761                 : }
     762                 : 
     763                 : nsAccessible*
     764               0 : nsAccessible::FocusedChild()
     765                 : {
     766               0 :   nsAccessible* focus = FocusMgr()->FocusedAccessible();
     767               0 :   if (focus && (focus == this || focus->Parent() == this))
     768               0 :     return focus;
     769                 : 
     770               0 :   return nsnull;
     771                 : }
     772                 : 
     773                 : // nsAccessible::ChildAtPoint()
     774                 : nsAccessible*
     775               0 : nsAccessible::ChildAtPoint(PRInt32 aX, PRInt32 aY,
     776                 :                            EWhichChildAtPoint aWhichChild)
     777                 : {
     778                 :   // If we can't find the point in a child, we will return the fallback answer:
     779                 :   // we return |this| if the point is within it, otherwise nsnull.
     780               0 :   PRInt32 x = 0, y = 0, width = 0, height = 0;
     781               0 :   nsresult rv = GetBounds(&x, &y, &width, &height);
     782               0 :   NS_ENSURE_SUCCESS(rv, nsnull);
     783                 : 
     784               0 :   nsAccessible* fallbackAnswer = nsnull;
     785               0 :   if (aX >= x && aX < x + width && aY >= y && aY < y + height)
     786               0 :     fallbackAnswer = this;
     787                 : 
     788               0 :   if (nsAccUtils::MustPrune(this))  // Do not dig any further
     789               0 :     return fallbackAnswer;
     790                 : 
     791                 :   // Search an accessible at the given point starting from accessible document
     792                 :   // because containing block (see CSS2) for out of flow element (for example,
     793                 :   // absolutely positioned element) may be different from its DOM parent and
     794                 :   // therefore accessible for containing block may be different from accessible
     795                 :   // for DOM parent but GetFrameForPoint() should be called for containing block
     796                 :   // to get an out of flow element.
     797               0 :   nsDocAccessible* accDocument = Document();
     798               0 :   NS_ENSURE_TRUE(accDocument, nsnull);
     799                 : 
     800               0 :   nsIFrame *frame = accDocument->GetFrame();
     801               0 :   NS_ENSURE_TRUE(frame, nsnull);
     802                 : 
     803               0 :   nsPresContext *presContext = frame->PresContext();
     804                 : 
     805               0 :   nsRect screenRect = frame->GetScreenRectInAppUnits();
     806               0 :   nsPoint offset(presContext->DevPixelsToAppUnits(aX) - screenRect.x,
     807               0 :                  presContext->DevPixelsToAppUnits(aY) - screenRect.y);
     808                 : 
     809               0 :   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
     810               0 :   nsIFrame *foundFrame = presShell->GetFrameForPoint(frame, offset);
     811                 : 
     812               0 :   nsIContent* content = nsnull;
     813               0 :   if (!foundFrame || !(content = foundFrame->GetContent()))
     814               0 :     return fallbackAnswer;
     815                 : 
     816                 :   // Get accessible for the node with the point or the first accessible in
     817                 :   // the DOM parent chain.
     818               0 :   nsDocAccessible* contentDocAcc = GetAccService()->
     819               0 :     GetDocAccessible(content->OwnerDoc());
     820                 : 
     821                 :   // contentDocAcc in some circumstances can be NULL. See bug 729861
     822               0 :   NS_ASSERTION(contentDocAcc, "could not get the document accessible");
     823               0 :   if (!contentDocAcc)
     824               0 :     return fallbackAnswer;
     825                 : 
     826               0 :   nsAccessible* accessible = contentDocAcc->GetAccessibleOrContainer(content);
     827               0 :   if (!accessible)
     828               0 :     return fallbackAnswer;
     829                 : 
     830               0 :   if (accessible == this) {
     831                 :     // Manually walk through accessible children and see if the are within this
     832                 :     // point. Skip offscreen or invisible accessibles. This takes care of cases
     833                 :     // where layout won't walk into things for us, such as image map areas and
     834                 :     // sub documents (XXX: subdocuments should be handled by methods of
     835                 :     // nsOuterDocAccessibles).
     836               0 :     PRInt32 childCount = GetChildCount();
     837               0 :     for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
     838               0 :       nsAccessible *child = GetChildAt(childIdx);
     839                 : 
     840                 :       PRInt32 childX, childY, childWidth, childHeight;
     841               0 :       child->GetBounds(&childX, &childY, &childWidth, &childHeight);
     842               0 :       if (aX >= childX && aX < childX + childWidth &&
     843                 :           aY >= childY && aY < childY + childHeight &&
     844               0 :           (child->State() & states::INVISIBLE) == 0) {
     845                 : 
     846               0 :         if (aWhichChild == eDeepestChild)
     847               0 :           return child->ChildAtPoint(aX, aY, eDeepestChild);
     848                 : 
     849               0 :         return child;
     850                 :       }
     851                 :     }
     852                 : 
     853                 :     // The point is in this accessible but not in a child. We are allowed to
     854                 :     // return |this| as the answer.
     855               0 :     return accessible;
     856                 :   }
     857                 : 
     858                 :   // Since DOM node of obtained accessible may be out of flow then we should
     859                 :   // ensure obtained accessible is a child of this accessible.
     860               0 :   nsAccessible* child = accessible;
     861               0 :   while (true) {
     862               0 :     nsAccessible* parent = child->Parent();
     863               0 :     if (!parent) {
     864                 :       // Reached the top of the hierarchy. These bounds were inside an
     865                 :       // accessible that is not a descendant of this one.
     866               0 :       return fallbackAnswer;
     867                 :     }
     868                 : 
     869               0 :     if (parent == this)
     870               0 :       return aWhichChild == eDeepestChild ? accessible : child;
     871                 : 
     872               0 :     child = parent;
     873                 :   }
     874                 : 
     875                 :   return nsnull;
     876                 : }
     877                 : 
     878                 : // nsIAccessible getChildAtPoint(in long x, in long y)
     879                 : NS_IMETHODIMP
     880               0 : nsAccessible::GetChildAtPoint(PRInt32 aX, PRInt32 aY,
     881                 :                               nsIAccessible **aAccessible)
     882                 : {
     883               0 :   NS_ENSURE_ARG_POINTER(aAccessible);
     884               0 :   *aAccessible = nsnull;
     885                 : 
     886               0 :   if (IsDefunct())
     887               0 :     return NS_ERROR_FAILURE;
     888                 : 
     889               0 :   NS_IF_ADDREF(*aAccessible = ChildAtPoint(aX, aY, eDirectChild));
     890               0 :   return NS_OK;
     891                 : }
     892                 : 
     893                 : // nsIAccessible getDeepestChildAtPoint(in long x, in long y)
     894                 : NS_IMETHODIMP
     895               0 : nsAccessible::GetDeepestChildAtPoint(PRInt32 aX, PRInt32 aY,
     896                 :                                      nsIAccessible **aAccessible)
     897                 : {
     898               0 :   NS_ENSURE_ARG_POINTER(aAccessible);
     899               0 :   *aAccessible = nsnull;
     900                 : 
     901               0 :   if (IsDefunct())
     902               0 :     return NS_ERROR_FAILURE;
     903                 : 
     904               0 :   NS_IF_ADDREF(*aAccessible = ChildAtPoint(aX, aY, eDeepestChild));
     905               0 :   return NS_OK;
     906                 : }
     907                 : 
     908               0 : void nsAccessible::GetBoundsRect(nsRect& aTotalBounds, nsIFrame** aBoundingFrame)
     909                 : {
     910                 : /*
     911                 :  * This method is used to determine the bounds of a content node.
     912                 :  * Because HTML wraps and links are not always rectangular, this
     913                 :  * method uses the following algorithm:
     914                 :  *
     915                 :  * 1) Start with an empty rectangle
     916                 :  * 2) Add the rect for the primary frame from for the DOM node.
     917                 :  * 3) For each next frame at the same depth with the same DOM node, add that rect to total
     918                 :  * 4) If that frame is an inline frame, search deeper at that point in the tree, adding all rects
     919                 :  */
     920                 : 
     921                 :   // Initialization area
     922               0 :   *aBoundingFrame = nsnull;
     923               0 :   nsIFrame *firstFrame = GetBoundsFrame();
     924               0 :   if (!firstFrame)
     925               0 :     return;
     926                 : 
     927                 :   // Find common relative parent
     928                 :   // This is an ancestor frame that will incompass all frames for this content node.
     929                 :   // We need the relative parent so we can get absolute screen coordinates
     930               0 :   nsIFrame *ancestorFrame = firstFrame;
     931                 : 
     932               0 :   while (ancestorFrame) {  
     933               0 :     *aBoundingFrame = ancestorFrame;
     934                 :     // If any other frame type, we only need to deal with the primary frame
     935                 :     // Otherwise, there may be more frames attached to the same content node
     936               0 :     if (ancestorFrame->GetType() != nsGkAtoms::inlineFrame &&
     937               0 :         ancestorFrame->GetType() != nsGkAtoms::textFrame)
     938               0 :       break;
     939               0 :     ancestorFrame = ancestorFrame->GetParent();
     940                 :   }
     941                 : 
     942               0 :   nsIFrame *iterFrame = firstFrame;
     943               0 :   nsCOMPtr<nsIContent> firstContent(mContent);
     944               0 :   nsIContent* iterContent = firstContent;
     945               0 :   PRInt32 depth = 0;
     946                 : 
     947                 :   // Look only at frames below this depth, or at this depth (if we're still on the content node we started with)
     948               0 :   while (iterContent == firstContent || depth > 0) {
     949                 :     // Coordinates will come back relative to parent frame
     950               0 :     nsRect currFrameBounds = iterFrame->GetRect();
     951                 :     
     952                 :     // Make this frame's bounds relative to common parent frame
     953                 :     currFrameBounds +=
     954               0 :       iterFrame->GetParent()->GetOffsetToExternal(*aBoundingFrame);
     955                 : 
     956                 :     // Add this frame's bounds to total
     957               0 :     aTotalBounds.UnionRect(aTotalBounds, currFrameBounds);
     958                 : 
     959               0 :     nsIFrame *iterNextFrame = nsnull;
     960                 : 
     961               0 :     if (iterFrame->GetType() == nsGkAtoms::inlineFrame) {
     962                 :       // Only do deeper bounds search if we're on an inline frame
     963                 :       // Inline frames can contain larger frames inside of them
     964               0 :       iterNextFrame = iterFrame->GetFirstPrincipalChild();
     965                 :     }
     966                 : 
     967               0 :     if (iterNextFrame) 
     968               0 :       ++depth;  // Child was found in code above this: We are going deeper in this iteration of the loop
     969                 :     else {  
     970                 :       // Use next sibling if it exists, or go back up the tree to get the first next-in-flow or next-sibling 
     971                 :       // within our search
     972               0 :       while (iterFrame) {
     973               0 :         iterNextFrame = iterFrame->GetNextContinuation();
     974               0 :         if (!iterNextFrame)
     975               0 :           iterNextFrame = iterFrame->GetNextSibling();
     976               0 :         if (iterNextFrame || --depth < 0) 
     977               0 :           break;
     978               0 :         iterFrame = iterFrame->GetParent();
     979                 :       }
     980                 :     }
     981                 : 
     982                 :     // Get ready for the next round of our loop
     983               0 :     iterFrame = iterNextFrame;
     984               0 :     if (iterFrame == nsnull)
     985                 :       break;
     986               0 :     iterContent = nsnull;
     987               0 :     if (depth == 0)
     988               0 :       iterContent = iterFrame->GetContent();
     989                 :   }
     990                 : }
     991                 : 
     992                 : 
     993                 : /* void getBounds (out long x, out long y, out long width, out long height); */
     994                 : NS_IMETHODIMP
     995               0 : nsAccessible::GetBounds(PRInt32* aX, PRInt32* aY,
     996                 :                         PRInt32* aWidth, PRInt32* aHeight)
     997                 : {
     998               0 :   NS_ENSURE_ARG_POINTER(aX);
     999               0 :   *aX = 0;
    1000               0 :   NS_ENSURE_ARG_POINTER(aY);
    1001               0 :   *aY = 0;
    1002               0 :   NS_ENSURE_ARG_POINTER(aWidth);
    1003               0 :   *aWidth = 0;
    1004               0 :   NS_ENSURE_ARG_POINTER(aHeight);
    1005               0 :   *aHeight = 0;
    1006                 : 
    1007               0 :   if (IsDefunct())
    1008               0 :     return NS_ERROR_FAILURE;
    1009                 : 
    1010               0 :   nsIPresShell* presShell = mDoc->PresShell();
    1011                 : 
    1012                 :   // This routine will get the entire rectangle for all the frames in this node.
    1013                 :   // -------------------------------------------------------------------------
    1014                 :   //      Primary Frame for node
    1015                 :   //  Another frame, same node                <- Example
    1016                 :   //  Another frame, same node
    1017                 : 
    1018               0 :   nsRect unionRectTwips;
    1019               0 :   nsIFrame* boundingFrame = nsnull;
    1020               0 :   GetBoundsRect(unionRectTwips, &boundingFrame);   // Unions up all primary frames for this node and all siblings after it
    1021               0 :   NS_ENSURE_STATE(boundingFrame);
    1022                 : 
    1023               0 :   nsPresContext* presContext = presShell->GetPresContext();
    1024               0 :   *aX = presContext->AppUnitsToDevPixels(unionRectTwips.x);
    1025               0 :   *aY = presContext->AppUnitsToDevPixels(unionRectTwips.y);
    1026               0 :   *aWidth = presContext->AppUnitsToDevPixels(unionRectTwips.width);
    1027               0 :   *aHeight = presContext->AppUnitsToDevPixels(unionRectTwips.height);
    1028                 : 
    1029                 :   // We have the union of the rectangle, now we need to put it in absolute screen coords
    1030               0 :   nsIntRect orgRectPixels = boundingFrame->GetScreenRectInAppUnits().
    1031               0 :     ToNearestPixels(presContext->AppUnitsPerDevPixel());
    1032               0 :   *aX += orgRectPixels.x;
    1033               0 :   *aY += orgRectPixels.y;
    1034                 : 
    1035               0 :   return NS_OK;
    1036                 : }
    1037                 : 
    1038                 : // helpers
    1039                 : 
    1040               0 : nsIFrame* nsAccessible::GetBoundsFrame()
    1041                 : {
    1042               0 :   return GetFrame();
    1043                 : }
    1044                 : 
    1045                 : /* void removeSelection (); */
    1046               0 : NS_IMETHODIMP nsAccessible::SetSelected(bool aSelect)
    1047                 : {
    1048                 :   // Add or remove selection
    1049               0 :   if (IsDefunct())
    1050               0 :     return NS_ERROR_FAILURE;
    1051                 : 
    1052               0 :   if (State() & states::SELECTABLE) {
    1053                 :     nsAccessible* multiSelect =
    1054               0 :       nsAccUtils::GetMultiSelectableContainer(mContent);
    1055               0 :     if (!multiSelect) {
    1056               0 :       return aSelect ? TakeFocus() : NS_ERROR_FAILURE;
    1057                 :     }
    1058                 : 
    1059               0 :     if (mRoleMapEntry) {
    1060               0 :       if (aSelect) {
    1061                 :         return mContent->SetAttr(kNameSpaceID_None,
    1062                 :                                  nsGkAtoms::aria_selected,
    1063               0 :                                  NS_LITERAL_STRING("true"), true);
    1064                 :       }
    1065               0 :       return mContent->UnsetAttr(kNameSpaceID_None,
    1066               0 :                                  nsGkAtoms::aria_selected, true);
    1067                 :     }
    1068                 :   }
    1069                 : 
    1070               0 :   return NS_OK;
    1071                 : }
    1072                 : 
    1073                 : /* void takeSelection (); */
    1074               0 : NS_IMETHODIMP nsAccessible::TakeSelection()
    1075                 : {
    1076                 :   // Select only this item
    1077               0 :   if (IsDefunct())
    1078               0 :     return NS_ERROR_FAILURE;
    1079                 : 
    1080               0 :   if (State() & states::SELECTABLE) {
    1081                 :     nsAccessible* multiSelect =
    1082               0 :       nsAccUtils::GetMultiSelectableContainer(mContent);
    1083               0 :     if (multiSelect)
    1084               0 :       multiSelect->ClearSelection();
    1085                 : 
    1086               0 :     return SetSelected(true);
    1087                 :   }
    1088                 : 
    1089               0 :   return NS_ERROR_FAILURE;
    1090                 : }
    1091                 : 
    1092                 : NS_IMETHODIMP
    1093               0 : nsAccessible::TakeFocus()
    1094                 : {
    1095               0 :   if (IsDefunct())
    1096               0 :     return NS_ERROR_FAILURE;
    1097                 : 
    1098               0 :   nsIFrame *frame = GetFrame();
    1099               0 :   NS_ENSURE_STATE(frame);
    1100                 : 
    1101               0 :   nsIContent* focusContent = mContent;
    1102                 : 
    1103                 :   // If the accessible focus is managed by container widget then focus the
    1104                 :   // widget and set the accessible as its current item.
    1105               0 :   if (!frame->IsFocusable()) {
    1106               0 :     nsAccessible* widget = ContainerWidget();
    1107               0 :     if (widget && widget->AreItemsOperable()) {
    1108               0 :       nsIContent* widgetElm = widget->GetContent();
    1109               0 :       nsIFrame* widgetFrame = widgetElm->GetPrimaryFrame();
    1110               0 :       if (widgetFrame && widgetFrame->IsFocusable()) {
    1111               0 :         focusContent = widgetElm;
    1112               0 :         widget->SetCurrentItem(this);
    1113                 :       }
    1114                 :     }
    1115                 :   }
    1116                 : 
    1117               0 :   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(focusContent));
    1118               0 :   nsFocusManager* fm = nsFocusManager::GetFocusManager();
    1119               0 :   if (fm)
    1120               0 :     fm->SetFocus(element, 0);
    1121                 : 
    1122               0 :   return NS_OK;
    1123                 : }
    1124                 : 
    1125                 : nsresult
    1126               0 : nsAccessible::GetHTMLName(nsAString& aLabel)
    1127                 : {
    1128               0 :   nsAutoString label;
    1129                 : 
    1130               0 :   nsAccessible* labelAcc = nsnull;
    1131               0 :   HTMLLabelIterator iter(Document(), this);
    1132               0 :   while ((labelAcc = iter.Next())) {
    1133                 :     nsresult rv = nsTextEquivUtils::
    1134               0 :       AppendTextEquivFromContent(this, labelAcc->GetContent(), &label);
    1135               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1136                 : 
    1137               0 :     label.CompressWhitespace();
    1138                 :   }
    1139                 : 
    1140               0 :   if (label.IsEmpty())
    1141               0 :     return nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
    1142                 : 
    1143               0 :   aLabel = label;
    1144               0 :   return NS_OK;
    1145                 : }
    1146                 : 
    1147                 : /**
    1148                 :   * 3 main cases for XUL Controls to be labeled
    1149                 :   *   1 - control contains label="foo"
    1150                 :   *   2 - control has, as a child, a label element
    1151                 :   *        - label has either value="foo" or children
    1152                 :   *   3 - non-child label contains control="controlID"
    1153                 :   *        - label has either value="foo" or children
    1154                 :   * Once a label is found, the search is discontinued, so a control
    1155                 :   *  that has a label child as well as having a label external to
    1156                 :   *  the control that uses the control="controlID" syntax will use
    1157                 :   *  the child label for its Name.
    1158                 :   */
    1159                 : nsresult
    1160               0 : nsAccessible::GetXULName(nsAString& aLabel)
    1161                 : {
    1162                 :   // CASE #1 (via label attribute) -- great majority of the cases
    1163               0 :   nsresult rv = NS_OK;
    1164                 : 
    1165               0 :   nsAutoString label;
    1166               0 :   nsCOMPtr<nsIDOMXULLabeledControlElement> labeledEl(do_QueryInterface(mContent));
    1167               0 :   if (labeledEl) {
    1168               0 :     rv = labeledEl->GetLabel(label);
    1169                 :   }
    1170                 :   else {
    1171               0 :     nsCOMPtr<nsIDOMXULSelectControlItemElement> itemEl(do_QueryInterface(mContent));
    1172               0 :     if (itemEl) {
    1173               0 :       rv = itemEl->GetLabel(label);
    1174                 :     }
    1175                 :     else {
    1176               0 :       nsCOMPtr<nsIDOMXULSelectControlElement> select(do_QueryInterface(mContent));
    1177                 :       // Use label if this is not a select control element which 
    1178                 :       // uses label attribute to indicate which option is selected
    1179               0 :       if (!select) {
    1180               0 :         nsCOMPtr<nsIDOMXULElement> xulEl(do_QueryInterface(mContent));
    1181               0 :         if (xulEl) {
    1182               0 :           rv = xulEl->GetAttribute(NS_LITERAL_STRING("label"), label);
    1183                 :         }
    1184                 :       }
    1185                 :     }
    1186                 :   }
    1187                 : 
    1188                 :   // CASES #2 and #3 ------ label as a child or <label control="id" ... > </label>
    1189               0 :   if (NS_FAILED(rv) || label.IsEmpty()) {
    1190               0 :     label.Truncate();
    1191                 : 
    1192               0 :     nsAccessible* labelAcc = nsnull;
    1193               0 :     XULLabelIterator iter(Document(), mContent);
    1194               0 :     while ((labelAcc = iter.Next())) {
    1195                 :       nsCOMPtr<nsIDOMXULLabelElement> xulLabel =
    1196               0 :         do_QueryInterface(labelAcc->GetContent());
    1197                 :       // Check if label's value attribute is used
    1198               0 :       if (xulLabel && NS_SUCCEEDED(xulLabel->GetValue(label)) && label.IsEmpty()) {
    1199                 :         // If no value attribute, a non-empty label must contain
    1200                 :         // children that define its text -- possibly using HTML
    1201                 :         nsTextEquivUtils::
    1202               0 :           AppendTextEquivFromContent(this, labelAcc->GetContent(), &label);
    1203                 :       }
    1204                 :     }
    1205                 :   }
    1206                 : 
    1207                 :   // XXX If CompressWhiteSpace worked on nsAString we could avoid a copy
    1208               0 :   label.CompressWhitespace();
    1209               0 :   if (!label.IsEmpty()) {
    1210               0 :     aLabel = label;
    1211               0 :     return NS_OK;
    1212                 :   }
    1213                 : 
    1214                 :   // Can get text from title of <toolbaritem> if we're a child of a <toolbaritem>
    1215               0 :   nsIContent *bindingParent = mContent->GetBindingParent();
    1216               0 :   nsIContent *parent = bindingParent? bindingParent->GetParent() :
    1217               0 :                                       mContent->GetParent();
    1218               0 :   while (parent) {
    1219               0 :     if (parent->Tag() == nsGkAtoms::toolbaritem &&
    1220               0 :         parent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, label)) {
    1221               0 :       label.CompressWhitespace();
    1222               0 :       aLabel = label;
    1223               0 :       return NS_OK;
    1224                 :     }
    1225               0 :     parent = parent->GetParent();
    1226                 :   }
    1227                 : 
    1228               0 :   return nsTextEquivUtils::GetNameFromSubtree(this, aLabel);
    1229                 : }
    1230                 : 
    1231                 : nsresult
    1232               0 : nsAccessible::HandleAccEvent(AccEvent* aEvent)
    1233                 : {
    1234               0 :   NS_ENSURE_ARG_POINTER(aEvent);
    1235                 : 
    1236                 :   nsCOMPtr<nsIObserverService> obsService =
    1237               0 :     mozilla::services::GetObserverService();
    1238               0 :   NS_ENSURE_TRUE(obsService, NS_ERROR_FAILURE);
    1239                 : 
    1240               0 :   nsCOMPtr<nsISimpleEnumerator> observers;
    1241               0 :   obsService->EnumerateObservers(NS_ACCESSIBLE_EVENT_TOPIC,
    1242               0 :                                  getter_AddRefs(observers));
    1243                 : 
    1244               0 :   NS_ENSURE_STATE(observers);
    1245                 : 
    1246               0 :   bool hasObservers = false;
    1247               0 :   observers->HasMoreElements(&hasObservers);
    1248               0 :   if (hasObservers) {
    1249               0 :     nsRefPtr<nsAccEvent> evnt(aEvent->CreateXPCOMObject());
    1250               0 :     return obsService->NotifyObservers(evnt, NS_ACCESSIBLE_EVENT_TOPIC, nsnull);
    1251                 :   }
    1252                 : 
    1253               0 :   return NS_OK;
    1254                 : }
    1255                 : 
    1256                 : NS_IMETHODIMP
    1257               0 : nsAccessible::GetRole(PRUint32 *aRole)
    1258                 : {
    1259               0 :   NS_ENSURE_ARG_POINTER(aRole);
    1260               0 :   *aRole = nsIAccessibleRole::ROLE_NOTHING;
    1261                 : 
    1262               0 :   if (IsDefunct())
    1263               0 :     return NS_ERROR_FAILURE;
    1264                 : 
    1265               0 :   *aRole = Role();
    1266               0 :   return NS_OK;
    1267                 : }
    1268                 : 
    1269                 : NS_IMETHODIMP
    1270               0 : nsAccessible::GetAttributes(nsIPersistentProperties **aAttributes)
    1271                 : {
    1272               0 :   NS_ENSURE_ARG_POINTER(aAttributes);  // In/out param. Created if necessary.
    1273                 :   
    1274               0 :   if (IsDefunct())
    1275               0 :     return NS_ERROR_FAILURE;
    1276                 : 
    1277               0 :   nsCOMPtr<nsIPersistentProperties> attributes = *aAttributes;
    1278               0 :   if (!attributes) {
    1279                 :     // Create only if an array wasn't already passed in
    1280               0 :     attributes = do_CreateInstance(NS_PERSISTENTPROPERTIES_CONTRACTID);
    1281               0 :     NS_ENSURE_TRUE(attributes, NS_ERROR_OUT_OF_MEMORY);
    1282               0 :     NS_ADDREF(*aAttributes = attributes);
    1283                 :   }
    1284                 :  
    1285               0 :   nsresult rv = GetAttributesInternal(attributes);
    1286               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1287                 : 
    1288               0 :   nsAutoString id;
    1289               0 :   nsAutoString oldValueUnused;
    1290               0 :   if (nsCoreUtils::GetID(mContent, id)) {
    1291                 :     // Expose ID. If an <iframe id> exists override the one on the <body> of the source doc,
    1292                 :     // because the specific instance is what makes the ID useful for scripts
    1293               0 :     attributes->SetStringProperty(NS_LITERAL_CSTRING("id"), id, oldValueUnused);
    1294                 :   }
    1295                 :   
    1296               0 :   nsAutoString xmlRoles;
    1297               0 :   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::role, xmlRoles)) {
    1298               0 :     attributes->SetStringProperty(NS_LITERAL_CSTRING("xml-roles"),  xmlRoles, oldValueUnused);          
    1299                 :   }
    1300                 : 
    1301               0 :   nsCOMPtr<nsIAccessibleValue> supportsValue = do_QueryInterface(static_cast<nsIAccessible*>(this));
    1302               0 :   if (supportsValue) {
    1303                 :     // We support values, so expose the string value as well, via the valuetext object attribute
    1304                 :     // We test for the value interface because we don't want to expose traditional get_accValue()
    1305                 :     // information such as URL's on links and documents, or text in an input
    1306               0 :     nsAutoString valuetext;
    1307               0 :     GetValue(valuetext);
    1308               0 :     attributes->SetStringProperty(NS_LITERAL_CSTRING("valuetext"), valuetext, oldValueUnused);
    1309                 :   }
    1310                 : 
    1311                 :   // Expose checkable object attribute if the accessible has checkable state
    1312               0 :   if (State() & states::CHECKABLE)
    1313               0 :     nsAccUtils::SetAccAttr(attributes, nsGkAtoms::checkable, NS_LITERAL_STRING("true"));
    1314                 : 
    1315                 :   // Group attributes (level/setsize/posinset)
    1316               0 :   PRInt32 level = 0, posInSet = 0, setSize = 0;
    1317               0 :   rv = GroupPosition(&level, &setSize, &posInSet);
    1318               0 :   if (NS_SUCCEEDED(rv))
    1319               0 :     nsAccUtils::SetAccGroupAttrs(attributes, level, setSize, posInSet);
    1320                 : 
    1321                 :   // Expose object attributes from ARIA attributes.
    1322               0 :   PRUint32 numAttrs = mContent->GetAttrCount();
    1323               0 :   for (PRUint32 count = 0; count < numAttrs; count ++) {
    1324               0 :     const nsAttrName *attr = mContent->GetAttrNameAt(count);
    1325               0 :     if (attr && attr->NamespaceEquals(kNameSpaceID_None)) {
    1326               0 :       nsIAtom *attrAtom = attr->Atom();
    1327               0 :       nsDependentAtomString attrStr(attrAtom);
    1328               0 :       if (!StringBeginsWith(attrStr, NS_LITERAL_STRING("aria-"))) 
    1329               0 :         continue; // Not ARIA
    1330               0 :       PRUint8 attrFlags = nsAccUtils::GetAttributeCharacteristics(attrAtom);
    1331               0 :       if (attrFlags & ATTR_BYPASSOBJ)
    1332               0 :         continue; // No need to handle exposing as obj attribute here
    1333               0 :       if ((attrFlags & ATTR_VALTOKEN) &&
    1334               0 :           !nsAccUtils::HasDefinedARIAToken(mContent, attrAtom))
    1335               0 :         continue; // only expose token based attributes if they are defined
    1336               0 :       nsAutoString value;
    1337               0 :       if (mContent->GetAttr(kNameSpaceID_None, attrAtom, value)) {
    1338               0 :         attributes->SetStringProperty(NS_ConvertUTF16toUTF8(Substring(attrStr, 5)), value, oldValueUnused);
    1339                 :       }
    1340                 :     }
    1341                 :   }
    1342                 : 
    1343                 :   // If there is no aria-live attribute then expose default value of 'live'
    1344                 :   // object attribute used for ARIA role of this accessible.
    1345               0 :   if (mRoleMapEntry) {
    1346               0 :     nsAutoString live;
    1347               0 :     nsAccUtils::GetAccAttr(attributes, nsGkAtoms::live, live);
    1348               0 :     if (live.IsEmpty()) {
    1349               0 :       if (nsAccUtils::GetLiveAttrValue(mRoleMapEntry->liveAttRule, live))
    1350               0 :         nsAccUtils::SetAccAttr(attributes, nsGkAtoms::live, live);
    1351                 :     }
    1352                 :   }
    1353                 : 
    1354               0 :   return NS_OK;
    1355                 : }
    1356                 : 
    1357                 : nsresult
    1358               0 : nsAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
    1359                 : {
    1360                 :   // Attributes set by this method will not be used to override attributes on a sub-document accessible
    1361                 :   // when there is a <frame>/<iframe> element that spawned the sub-document
    1362               0 :   nsCOMPtr<nsIDOMElement> element(do_QueryInterface(mContent));
    1363                 : 
    1364               0 :   nsAutoString tagName;
    1365               0 :   element->GetTagName(tagName);
    1366               0 :   if (!tagName.IsEmpty()) {
    1367               0 :     nsAutoString oldValueUnused;
    1368               0 :     aAttributes->SetStringProperty(NS_LITERAL_CSTRING("tag"), tagName,
    1369               0 :                                    oldValueUnused);
    1370                 :   }
    1371                 : 
    1372               0 :   nsEventShell::GetEventAttributes(GetNode(), aAttributes);
    1373                 :  
    1374                 :   // Expose class because it may have useful microformat information
    1375                 :   // Let the class from an iframe's document be exposed, don't override from <iframe class>
    1376               0 :   nsAutoString _class;
    1377               0 :   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::_class, _class))
    1378               0 :     nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::_class, _class);
    1379                 : 
    1380                 :   // Get container-foo computed live region properties based on the closest container with
    1381                 :   // the live region attribute. 
    1382                 :   // Inner nodes override outer nodes within the same document --
    1383                 :   //   The inner nodes can be used to override live region behavior on more general outer nodes
    1384                 :   // However, nodes in outer documents override nodes in inner documents:
    1385                 :   //   Outer doc author may want to override properties on a widget they used in an iframe
    1386               0 :   nsIContent *startContent = mContent;
    1387               0 :   while (true) {
    1388               0 :     NS_ENSURE_STATE(startContent);
    1389               0 :     nsIDocument *doc = startContent->GetDocument();
    1390               0 :     nsIContent* rootContent = nsCoreUtils::GetRoleContent(doc);
    1391               0 :     NS_ENSURE_STATE(rootContent);
    1392                 :     nsAccUtils::SetLiveContainerAttributes(aAttributes, startContent,
    1393               0 :                                            rootContent);
    1394                 : 
    1395                 :     // Allow ARIA live region markup from outer documents to override
    1396               0 :     nsCOMPtr<nsISupports> container = doc->GetContainer(); 
    1397                 :     nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
    1398               0 :       do_QueryInterface(container);
    1399               0 :     if (!docShellTreeItem)
    1400                 :       break;
    1401                 : 
    1402               0 :     nsCOMPtr<nsIDocShellTreeItem> sameTypeParent;
    1403               0 :     docShellTreeItem->GetSameTypeParent(getter_AddRefs(sameTypeParent));
    1404               0 :     if (!sameTypeParent || sameTypeParent == docShellTreeItem)
    1405                 :       break;
    1406                 : 
    1407               0 :     nsIDocument *parentDoc = doc->GetParentDocument();
    1408               0 :     if (!parentDoc)
    1409                 :       break;
    1410                 : 
    1411               0 :     startContent = parentDoc->FindContentForSubDocument(doc);      
    1412                 :   }
    1413                 : 
    1414               0 :   if (!mContent->IsElement())
    1415               0 :     return NS_OK;
    1416                 : 
    1417                 :   // Expose draggable object attribute?
    1418               0 :   nsCOMPtr<nsIDOMHTMLElement> htmlElement = do_QueryInterface(mContent);
    1419               0 :   if (htmlElement) {
    1420               0 :     bool draggable = false;
    1421               0 :     htmlElement->GetDraggable(&draggable);
    1422               0 :     if (draggable) {
    1423                 :       nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::draggable,
    1424               0 :                              NS_LITERAL_STRING("true"));
    1425                 :     }
    1426                 :   }
    1427                 : 
    1428                 :   // Don't calculate CSS-based object attributes when no frame (i.e.
    1429                 :   // the accessible is not unattached form three) or when the accessible is not
    1430                 :   // primary for node (like list bullet or XUL tree items).
    1431               0 :   if (!mContent->GetPrimaryFrame() || !IsPrimaryForNode())
    1432               0 :     return NS_OK;
    1433                 : 
    1434                 :   // CSS style based object attributes.
    1435               0 :   nsAutoString value;
    1436               0 :   StyleInfo styleInfo(mContent->AsElement(), mDoc->PresShell());
    1437                 : 
    1438                 :   // Expose 'display' attribute.
    1439               0 :   styleInfo.Display(value);
    1440               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::display, value);
    1441                 : 
    1442                 :   // Expose 'text-align' attribute.
    1443               0 :   styleInfo.TextAlign(value);
    1444               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textAlign, value);
    1445                 : 
    1446                 :   // Expose 'text-indent' attribute.
    1447               0 :   styleInfo.TextIndent(value);
    1448               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::textIndent, value);
    1449                 : 
    1450                 :   // Expose 'margin-left' attribute.
    1451               0 :   styleInfo.MarginLeft(value);
    1452               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginLeft, value);
    1453                 : 
    1454                 :   // Expose 'margin-right' attribute.
    1455               0 :   styleInfo.MarginRight(value);
    1456               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginRight, value);
    1457                 : 
    1458                 :   // Expose 'margin-top' attribute.
    1459               0 :   styleInfo.MarginTop(value);
    1460               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginTop, value);
    1461                 : 
    1462                 :   // Expose 'margin-bottom' attribute.
    1463               0 :   styleInfo.MarginBottom(value);
    1464               0 :   nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::marginBottom, value);
    1465                 : 
    1466               0 :   return NS_OK;
    1467                 : }
    1468                 : 
    1469                 : NS_IMETHODIMP
    1470               0 : nsAccessible::GroupPosition(PRInt32 *aGroupLevel,
    1471                 :                             PRInt32 *aSimilarItemsInGroup,
    1472                 :                             PRInt32 *aPositionInGroup)
    1473                 : {
    1474               0 :   NS_ENSURE_ARG_POINTER(aGroupLevel);
    1475               0 :   *aGroupLevel = 0;
    1476                 : 
    1477               0 :   NS_ENSURE_ARG_POINTER(aSimilarItemsInGroup);
    1478               0 :   *aSimilarItemsInGroup = 0;
    1479                 : 
    1480               0 :   NS_ENSURE_ARG_POINTER(aPositionInGroup);
    1481               0 :   *aPositionInGroup = 0;
    1482                 : 
    1483               0 :   if (IsDefunct())
    1484               0 :     return NS_ERROR_FAILURE;
    1485                 : 
    1486                 :   // Get group position from ARIA attributes.
    1487                 :   nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_level,
    1488               0 :                            aGroupLevel);
    1489                 :   nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_posinset,
    1490               0 :                            aPositionInGroup);
    1491                 :   nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_setsize,
    1492               0 :                            aSimilarItemsInGroup);
    1493                 : 
    1494                 :   // If ARIA is missed and the accessible is visible then calculate group
    1495                 :   // position from hierarchy.
    1496               0 :   if (State() & states::INVISIBLE)
    1497               0 :     return NS_OK;
    1498                 : 
    1499                 :   // Calculate group level if ARIA is missed.
    1500               0 :   if (*aGroupLevel == 0) {
    1501               0 :     PRInt32 level = GetLevelInternal();
    1502               0 :     if (level != 0)
    1503               0 :       *aGroupLevel = level;
    1504                 :   }
    1505                 : 
    1506                 :   // Calculate position in group and group size if ARIA is missed.
    1507               0 :   if (*aSimilarItemsInGroup == 0 || *aPositionInGroup == 0) {
    1508               0 :     PRInt32 posInSet = 0, setSize = 0;
    1509               0 :     GetPositionAndSizeInternal(&posInSet, &setSize);
    1510               0 :     if (posInSet != 0 && setSize != 0) {
    1511               0 :       if (*aPositionInGroup == 0)
    1512               0 :         *aPositionInGroup = posInSet;
    1513                 : 
    1514               0 :       if (*aSimilarItemsInGroup == 0)
    1515               0 :         *aSimilarItemsInGroup = setSize;
    1516                 :     }
    1517                 :   }
    1518                 : 
    1519               0 :   return NS_OK;
    1520                 : }
    1521                 : 
    1522                 : NS_IMETHODIMP
    1523               0 : nsAccessible::GetState(PRUint32* aState, PRUint32* aExtraState)
    1524                 : {
    1525               0 :   NS_ENSURE_ARG_POINTER(aState);
    1526                 : 
    1527               0 :   nsAccUtils::To32States(State(), aState, aExtraState);
    1528               0 :   return NS_OK;
    1529                 : }
    1530                 : 
    1531                 : PRUint64
    1532               0 : nsAccessible::State()
    1533                 : {
    1534               0 :   if (IsDefunct())
    1535               0 :     return states::DEFUNCT;
    1536                 : 
    1537               0 :   PRUint64 state = NativeState();
    1538                 :   // Apply ARIA states to be sure accessible states will be overridden.
    1539               0 :   ApplyARIAState(&state);
    1540                 : 
    1541                 :   // If this is an ARIA item of the selectable widget and if it's focused and
    1542                 :   // not marked unselected explicitly (i.e. aria-selected="false") then expose
    1543                 :   // it as selected to make ARIA widget authors life easier.
    1544               0 :   if (mRoleMapEntry && !(state & states::SELECTED) &&
    1545               0 :       !mContent->AttrValueIs(kNameSpaceID_None,
    1546                 :                              nsGkAtoms::aria_selected,
    1547               0 :                              nsGkAtoms::_false, eCaseMatters)) {
    1548                 :     // Special case for tabs: focused tab or focus inside related tab panel
    1549                 :     // implies selected state.
    1550               0 :     if (mRoleMapEntry->role == roles::PAGETAB) {
    1551               0 :       if (state & states::FOCUSED) {
    1552               0 :         state |= states::SELECTED;
    1553                 :       } else {
    1554                 :         // If focus is in a child of the tab panel surely the tab is selected!
    1555               0 :         Relation rel = RelationByType(nsIAccessibleRelation::RELATION_LABEL_FOR);
    1556               0 :         nsAccessible* relTarget = nsnull;
    1557               0 :         while ((relTarget = rel.Next())) {
    1558               0 :           if (relTarget->Role() == roles::PROPERTYPAGE &&
    1559               0 :               FocusMgr()->IsFocusWithin(relTarget))
    1560               0 :             state |= states::SELECTED;
    1561                 :         }
    1562                 :       }
    1563               0 :     } else if (state & states::FOCUSED) {
    1564               0 :       nsAccessible* container = nsAccUtils::GetSelectableContainer(this, state);
    1565               0 :       if (container &&
    1566                 :           !nsAccUtils::HasDefinedARIAToken(container->GetContent(),
    1567               0 :                                            nsGkAtoms::aria_multiselectable)) {
    1568               0 :         state |= states::SELECTED;
    1569                 :       }
    1570                 :     }
    1571                 :   }
    1572                 : 
    1573               0 :   const PRUint32 kExpandCollapseStates = states::COLLAPSED | states::EXPANDED;
    1574               0 :   if ((state & kExpandCollapseStates) == kExpandCollapseStates) {
    1575                 :     // Cannot be both expanded and collapsed -- this happens in ARIA expanded
    1576                 :     // combobox because of limitation of nsARIAMap.
    1577                 :     // XXX: Perhaps we will be able to make this less hacky if we support
    1578                 :     // extended states in nsARIAMap, e.g. derive COLLAPSED from
    1579                 :     // EXPANDABLE && !EXPANDED.
    1580               0 :     state &= ~states::COLLAPSED;
    1581                 :   }
    1582                 : 
    1583               0 :   if (!(state & states::UNAVAILABLE)) {
    1584               0 :     state |= states::ENABLED | states::SENSITIVE;
    1585                 : 
    1586                 :     // If the object is a current item of container widget then mark it as
    1587                 :     // ACTIVE. This allows screen reader virtual buffer modes to know which
    1588                 :     // descendant is the current one that would get focus if the user navigates
    1589                 :     // to the container widget.
    1590               0 :     nsAccessible* widget = ContainerWidget();
    1591               0 :     if (widget && widget->CurrentItem() == this)
    1592               0 :       state |= states::ACTIVE;
    1593                 :   }
    1594                 : 
    1595               0 :   if ((state & states::COLLAPSED) || (state & states::EXPANDED))
    1596               0 :     state |= states::EXPANDABLE;
    1597                 : 
    1598                 :   // For some reasons DOM node may have not a frame. We tract such accessibles
    1599                 :   // as invisible.
    1600               0 :   nsIFrame *frame = GetFrame();
    1601               0 :   if (!frame)
    1602               0 :     return state;
    1603                 : 
    1604               0 :   const nsStyleDisplay* display = frame->GetStyleDisplay();
    1605               0 :   if (display && display->mOpacity == 1.0f &&
    1606               0 :       !(state & states::INVISIBLE)) {
    1607               0 :     state |= states::OPAQUE1;
    1608                 :   }
    1609                 : 
    1610               0 :   const nsStyleXUL *xulStyle = frame->GetStyleXUL();
    1611               0 :   if (xulStyle) {
    1612                 :     // In XUL all boxes are either vertical or horizontal
    1613               0 :     if (xulStyle->mBoxOrient == NS_STYLE_BOX_ORIENT_VERTICAL) {
    1614               0 :       state |= states::VERTICAL;
    1615                 :     }
    1616                 :     else {
    1617               0 :       state |= states::HORIZONTAL;
    1618                 :     }
    1619                 :   }
    1620                 :   
    1621                 :   // If we are editable, force readonly bit off
    1622               0 :   if (state & states::EDITABLE)
    1623               0 :     state &= ~states::READONLY;
    1624                 :  
    1625               0 :   return state;
    1626                 : }
    1627                 : 
    1628                 : void
    1629               0 : nsAccessible::ApplyARIAState(PRUint64* aState)
    1630                 : {
    1631                 :   // Test for universal states first
    1632               0 :   *aState |= nsARIAMap::UniversalStatesFor(mContent);
    1633                 : 
    1634               0 :   if (mRoleMapEntry) {
    1635                 : 
    1636                 :     // We only force the readonly bit off if we have a real mapping for the aria
    1637                 :     // role. This preserves the ability for screen readers to use readonly
    1638                 :     // (primarily on the document) as the hint for creating a virtual buffer.
    1639               0 :     if (mRoleMapEntry->role != roles::NOTHING)
    1640               0 :       *aState &= ~states::READONLY;
    1641                 : 
    1642               0 :     if (mContent->HasAttr(kNameSpaceID_None, mContent->GetIDAttributeName())) {
    1643                 :       // If has a role & ID and aria-activedescendant on the container, assume focusable
    1644               0 :       nsIContent *ancestorContent = mContent;
    1645               0 :       while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {
    1646               0 :         if (ancestorContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant)) {
    1647                 :             // ancestor has activedescendant property, this content could be active
    1648               0 :           *aState |= states::FOCUSABLE;
    1649               0 :           break;
    1650                 :         }
    1651                 :       }
    1652                 :     }
    1653                 :   }
    1654                 : 
    1655               0 :   if (*aState & states::FOCUSABLE) {
    1656                 :     // Special case: aria-disabled propagates from ancestors down to any focusable descendant
    1657               0 :     nsIContent *ancestorContent = mContent;
    1658               0 :     while ((ancestorContent = ancestorContent->GetParent()) != nsnull) {
    1659               0 :       if (ancestorContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::aria_disabled,
    1660               0 :                                        nsGkAtoms::_true, eCaseMatters)) {
    1661                 :           // ancestor has aria-disabled property, this is disabled
    1662               0 :         *aState |= states::UNAVAILABLE;
    1663               0 :         break;
    1664                 :       }
    1665                 :     }    
    1666                 :   }
    1667                 : 
    1668               0 :   if (!mRoleMapEntry)
    1669               0 :     return;
    1670                 : 
    1671                 :   // Note: the readonly bitflag will be overridden later if content is editable
    1672               0 :   *aState |= mRoleMapEntry->state;
    1673               0 :   if (nsStateMapEntry::MapToStates(mContent, aState,
    1674               0 :                                    mRoleMapEntry->attributeMap1) &&
    1675                 :       nsStateMapEntry::MapToStates(mContent, aState,
    1676               0 :                                    mRoleMapEntry->attributeMap2)) {
    1677                 :     nsStateMapEntry::MapToStates(mContent, aState,
    1678               0 :                                  mRoleMapEntry->attributeMap3);
    1679                 :   }
    1680                 : 
    1681                 : }
    1682                 : 
    1683                 : // Not implemented by this class
    1684                 : 
    1685                 : /* DOMString getValue (); */
    1686                 : NS_IMETHODIMP
    1687               0 : nsAccessible::GetValue(nsAString& aValue)
    1688                 : {
    1689               0 :   if (IsDefunct())
    1690               0 :     return NS_ERROR_FAILURE;
    1691                 : 
    1692               0 :   if (mRoleMapEntry) {
    1693               0 :     if (mRoleMapEntry->valueRule == eNoValue) {
    1694               0 :       return NS_OK;
    1695                 :     }
    1696                 : 
    1697                 :     // aria-valuenow is a number, and aria-valuetext is the optional text equivalent
    1698                 :     // For the string value, we will try the optional text equivalent first
    1699               0 :     if (!mContent->GetAttr(kNameSpaceID_None,
    1700               0 :                            nsGkAtoms::aria_valuetext, aValue)) {
    1701               0 :       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow,
    1702               0 :                         aValue);
    1703                 :     }
    1704                 :   }
    1705                 : 
    1706               0 :   if (!aValue.IsEmpty())
    1707               0 :     return NS_OK;
    1708                 : 
    1709                 :   // Check if it's a simple xlink.
    1710               0 :   if (nsCoreUtils::IsXLink(mContent)) {
    1711               0 :     nsIPresShell* presShell = mDoc->PresShell();
    1712               0 :     if (presShell) {
    1713               0 :       nsCOMPtr<nsIDOMNode> DOMNode(do_QueryInterface(mContent));
    1714               0 :       return presShell->GetLinkLocation(DOMNode, aValue);
    1715                 :     }
    1716                 :   }
    1717                 : 
    1718               0 :   return NS_OK;
    1719                 : }
    1720                 : 
    1721                 : // nsIAccessibleValue
    1722                 : NS_IMETHODIMP
    1723               0 : nsAccessible::GetMaximumValue(double *aMaximumValue)
    1724                 : {
    1725               0 :   return GetAttrValue(nsGkAtoms::aria_valuemax, aMaximumValue);
    1726                 : }
    1727                 : 
    1728                 : NS_IMETHODIMP
    1729               0 : nsAccessible::GetMinimumValue(double *aMinimumValue)
    1730                 : {
    1731               0 :   return GetAttrValue(nsGkAtoms::aria_valuemin, aMinimumValue);
    1732                 : }
    1733                 : 
    1734                 : NS_IMETHODIMP
    1735               0 : nsAccessible::GetMinimumIncrement(double *aMinIncrement)
    1736                 : {
    1737               0 :   NS_ENSURE_ARG_POINTER(aMinIncrement);
    1738               0 :   *aMinIncrement = 0;
    1739                 : 
    1740                 :   // No mimimum increment in dynamic content spec right now
    1741               0 :   return NS_OK_NO_ARIA_VALUE;
    1742                 : }
    1743                 : 
    1744                 : NS_IMETHODIMP
    1745               0 : nsAccessible::GetCurrentValue(double *aValue)
    1746                 : {
    1747               0 :   return GetAttrValue(nsGkAtoms::aria_valuenow, aValue);
    1748                 : }
    1749                 : 
    1750                 : NS_IMETHODIMP
    1751               0 : nsAccessible::SetCurrentValue(double aValue)
    1752                 : {
    1753               0 :   if (IsDefunct())
    1754               0 :     return NS_ERROR_FAILURE;
    1755                 : 
    1756               0 :   if (!mRoleMapEntry || mRoleMapEntry->valueRule == eNoValue)
    1757               0 :     return NS_OK_NO_ARIA_VALUE;
    1758                 : 
    1759               0 :   const PRUint32 kValueCannotChange = states::READONLY | states::UNAVAILABLE;
    1760                 : 
    1761               0 :   if (State() & kValueCannotChange)
    1762               0 :     return NS_ERROR_FAILURE;
    1763                 : 
    1764               0 :   double minValue = 0;
    1765               0 :   if (NS_SUCCEEDED(GetMinimumValue(&minValue)) && aValue < minValue)
    1766               0 :     return NS_ERROR_INVALID_ARG;
    1767                 : 
    1768               0 :   double maxValue = 0;
    1769               0 :   if (NS_SUCCEEDED(GetMaximumValue(&maxValue)) && aValue > maxValue)
    1770               0 :     return NS_ERROR_INVALID_ARG;
    1771                 : 
    1772               0 :   nsAutoString newValue;
    1773               0 :   newValue.AppendFloat(aValue);
    1774                 :   return mContent->SetAttr(kNameSpaceID_None,
    1775               0 :                            nsGkAtoms::aria_valuenow, newValue, true);
    1776                 : }
    1777                 : 
    1778                 : /* void setName (in DOMString name); */
    1779               0 : NS_IMETHODIMP nsAccessible::SetName(const nsAString& name)
    1780                 : {
    1781               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1782                 : }
    1783                 : 
    1784                 : NS_IMETHODIMP
    1785               0 : nsAccessible::GetDefaultKeyBinding(nsAString& aKeyBinding)
    1786                 : {
    1787               0 :   aKeyBinding.Truncate();
    1788               0 :   if (IsDefunct())
    1789               0 :     return NS_ERROR_FAILURE;
    1790                 : 
    1791               0 :   KeyboardShortcut().ToString(aKeyBinding);
    1792               0 :   return NS_OK;
    1793                 : }
    1794                 : 
    1795                 : NS_IMETHODIMP
    1796               0 : nsAccessible::GetKeyBindings(PRUint8 aActionIndex,
    1797                 :                              nsIDOMDOMStringList **aKeyBindings)
    1798                 : {
    1799                 :   // Currently we support only unique key binding on element for default action.
    1800               0 :   NS_ENSURE_TRUE(aActionIndex == 0, NS_ERROR_INVALID_ARG);
    1801                 : 
    1802               0 :   nsAccessibleDOMStringList *keyBindings = new nsAccessibleDOMStringList();
    1803               0 :   NS_ENSURE_TRUE(keyBindings, NS_ERROR_OUT_OF_MEMORY);
    1804                 : 
    1805               0 :   nsAutoString defaultKey;
    1806               0 :   nsresult rv = GetDefaultKeyBinding(defaultKey);
    1807               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1808                 : 
    1809               0 :   if (!defaultKey.IsEmpty())
    1810               0 :     keyBindings->Add(defaultKey);
    1811                 : 
    1812               0 :   NS_ADDREF(*aKeyBindings = keyBindings);
    1813               0 :   return NS_OK;
    1814                 : }
    1815                 : 
    1816                 : role
    1817               0 : nsAccessible::ARIARoleInternal()
    1818                 : {
    1819               0 :   NS_PRECONDITION(mRoleMapEntry && mRoleMapEntry->roleRule == kUseMapRole,
    1820                 :                   "ARIARoleInternal should only be called when ARIA role overrides!");
    1821                 : 
    1822                 :   // XXX: these unfortunate exceptions don't fit into the ARIA table. This is
    1823                 :   // where the accessible role depends on both the role and ARIA state.
    1824               0 :   if (mRoleMapEntry->role == roles::PUSHBUTTON) {
    1825               0 :     if (nsAccUtils::HasDefinedARIAToken(mContent, nsGkAtoms::aria_pressed)) {
    1826                 :       // For simplicity, any existing pressed attribute except "" or "undefined"
    1827                 :       // indicates a toggle.
    1828               0 :       return roles::TOGGLE_BUTTON;
    1829                 :     }
    1830                 : 
    1831               0 :     if (mContent->AttrValueIs(kNameSpaceID_None,
    1832                 :                               nsGkAtoms::aria_haspopup,
    1833                 :                               nsGkAtoms::_true,
    1834               0 :                               eCaseMatters)) {
    1835                 :       // For button with aria-haspopup="true".
    1836               0 :       return roles::BUTTONMENU;
    1837                 :     }
    1838                 : 
    1839               0 :   } else if (mRoleMapEntry->role == roles::LISTBOX) {
    1840                 :     // A listbox inside of a combobox needs a special role because of ATK
    1841                 :     // mapping to menu.
    1842               0 :     if (mParent && mParent->Role() == roles::COMBOBOX) {
    1843               0 :       return roles::COMBOBOX_LIST;
    1844                 : 
    1845                 :       Relation rel = RelationByType(nsIAccessibleRelation::RELATION_NODE_CHILD_OF);
    1846                 :       nsAccessible* targetAcc = nsnull;
    1847                 :       while ((targetAcc = rel.Next()))
    1848                 :         if (targetAcc->Role() == roles::COMBOBOX)
    1849                 :           return roles::COMBOBOX_LIST;
    1850                 :     }
    1851                 : 
    1852               0 :   } else if (mRoleMapEntry->role == roles::OPTION) {
    1853               0 :     if (mParent && mParent->Role() == roles::COMBOBOX_LIST)
    1854               0 :       return roles::COMBOBOX_OPTION;
    1855                 :   }
    1856                 : 
    1857               0 :   return mRoleMapEntry->role;
    1858                 : }
    1859                 : 
    1860                 : role
    1861               0 : nsAccessible::NativeRole()
    1862                 : {
    1863               0 :   return nsCoreUtils::IsXLink(mContent) ? roles::LINK : roles::NOTHING;
    1864                 : }
    1865                 : 
    1866                 : // readonly attribute PRUint8 numActions
    1867                 : NS_IMETHODIMP
    1868               0 : nsAccessible::GetNumActions(PRUint8* aActionCount)
    1869                 : {
    1870               0 :   NS_ENSURE_ARG_POINTER(aActionCount);
    1871               0 :   *aActionCount = 0;
    1872               0 :   if (IsDefunct())
    1873               0 :     return NS_ERROR_FAILURE;
    1874                 : 
    1875               0 :   *aActionCount = ActionCount();
    1876               0 :   return NS_OK;
    1877                 : }
    1878                 : 
    1879                 : PRUint8
    1880               0 : nsAccessible::ActionCount()
    1881                 : {
    1882               0 :   return GetActionRule(State()) == eNoAction ? 0 : 1;
    1883                 : }
    1884                 : 
    1885                 : /* DOMString getAccActionName (in PRUint8 index); */
    1886                 : NS_IMETHODIMP
    1887               0 : nsAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
    1888                 : {
    1889               0 :   aName.Truncate();
    1890                 : 
    1891               0 :   if (aIndex != 0)
    1892               0 :     return NS_ERROR_INVALID_ARG;
    1893                 : 
    1894               0 :   if (IsDefunct())
    1895               0 :     return NS_ERROR_FAILURE;
    1896                 : 
    1897               0 :   PRUint64 states = State();
    1898               0 :   PRUint32 actionRule = GetActionRule(states);
    1899                 : 
    1900               0 :  switch (actionRule) {
    1901                 :    case eActivateAction:
    1902               0 :      aName.AssignLiteral("activate");
    1903               0 :      return NS_OK;
    1904                 : 
    1905                 :    case eClickAction:
    1906               0 :      aName.AssignLiteral("click");
    1907               0 :      return NS_OK;
    1908                 : 
    1909                 :    case ePressAction:
    1910               0 :      aName.AssignLiteral("press");
    1911               0 :      return NS_OK;
    1912                 : 
    1913                 :    case eCheckUncheckAction:
    1914               0 :      if (states & states::CHECKED)
    1915               0 :        aName.AssignLiteral("uncheck");
    1916               0 :      else if (states & states::MIXED)
    1917               0 :        aName.AssignLiteral("cycle");
    1918                 :      else
    1919               0 :        aName.AssignLiteral("check");
    1920               0 :      return NS_OK;
    1921                 : 
    1922                 :    case eJumpAction:
    1923               0 :      aName.AssignLiteral("jump");
    1924               0 :      return NS_OK;
    1925                 : 
    1926                 :    case eOpenCloseAction:
    1927               0 :      if (states & states::COLLAPSED)
    1928               0 :        aName.AssignLiteral("open");
    1929                 :      else
    1930               0 :        aName.AssignLiteral("close");
    1931               0 :      return NS_OK;
    1932                 : 
    1933                 :    case eSelectAction:
    1934               0 :      aName.AssignLiteral("select");
    1935               0 :      return NS_OK;
    1936                 : 
    1937                 :    case eSwitchAction:
    1938               0 :      aName.AssignLiteral("switch");
    1939               0 :      return NS_OK;
    1940                 :      
    1941                 :    case eSortAction:
    1942               0 :      aName.AssignLiteral("sort");
    1943               0 :      return NS_OK;
    1944                 :    
    1945                 :    case eExpandAction:
    1946               0 :      if (states & states::COLLAPSED)
    1947               0 :        aName.AssignLiteral("expand");
    1948                 :      else
    1949               0 :        aName.AssignLiteral("collapse");
    1950               0 :      return NS_OK;
    1951                 :   }
    1952                 : 
    1953               0 :   return NS_ERROR_INVALID_ARG;
    1954                 : }
    1955                 : 
    1956                 : // AString getActionDescription(in PRUint8 index)
    1957                 : NS_IMETHODIMP
    1958               0 : nsAccessible::GetActionDescription(PRUint8 aIndex, nsAString& aDescription)
    1959                 : {
    1960                 :   // default to localized action name.
    1961               0 :   nsAutoString name;
    1962               0 :   nsresult rv = GetActionName(aIndex, name);
    1963               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1964                 : 
    1965               0 :   TranslateString(name, aDescription);
    1966               0 :   return NS_OK;
    1967                 : }
    1968                 : 
    1969                 : // void doAction(in PRUint8 index)
    1970                 : NS_IMETHODIMP
    1971               0 : nsAccessible::DoAction(PRUint8 aIndex)
    1972                 : {
    1973               0 :   if (aIndex != 0)
    1974               0 :     return NS_ERROR_INVALID_ARG;
    1975                 : 
    1976               0 :   if (IsDefunct())
    1977               0 :     return NS_ERROR_FAILURE;
    1978                 : 
    1979               0 :   if (GetActionRule(State()) != eNoAction) {
    1980               0 :     DoCommand();
    1981               0 :     return NS_OK;
    1982                 :   }
    1983                 : 
    1984               0 :   return NS_ERROR_INVALID_ARG;
    1985                 : }
    1986                 : 
    1987                 : /* DOMString getHelp (); */
    1988               0 : NS_IMETHODIMP nsAccessible::GetHelp(nsAString& _retval)
    1989                 : {
    1990               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    1991                 : }
    1992                 : 
    1993                 : nsIContent*
    1994               0 : nsAccessible::GetAtomicRegion() const
    1995                 : {
    1996               0 :   nsIContent *loopContent = mContent;
    1997               0 :   nsAutoString atomic;
    1998               0 :   while (loopContent && !loopContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_atomic, atomic))
    1999               0 :     loopContent = loopContent->GetParent();
    2000                 : 
    2001               0 :   return atomic.EqualsLiteral("true") ? loopContent : nsnull;
    2002                 : }
    2003                 : 
    2004                 : // nsIAccessible getRelationByType()
    2005                 : NS_IMETHODIMP
    2006               0 : nsAccessible::GetRelationByType(PRUint32 aType,
    2007                 :                                 nsIAccessibleRelation** aRelation)
    2008                 : {
    2009               0 :   NS_ENSURE_ARG_POINTER(aRelation);
    2010               0 :   *aRelation = nsnull;
    2011               0 :   if (IsDefunct())
    2012               0 :     return NS_ERROR_FAILURE;
    2013                 : 
    2014               0 :   Relation rel = RelationByType(aType);
    2015               0 :   NS_ADDREF(*aRelation = new nsAccessibleRelation(aType, &rel));
    2016               0 :   return *aRelation ? NS_OK : NS_ERROR_FAILURE;
    2017                 : }
    2018                 : 
    2019                 : Relation
    2020               0 : nsAccessible::RelationByType(PRUint32 aType)
    2021                 : {
    2022                 :   // Relationships are defined on the same content node that the role would be
    2023                 :   // defined on.
    2024               0 :   switch (aType) {
    2025                 :     case nsIAccessibleRelation::RELATION_LABEL_FOR: {
    2026               0 :       Relation rel(new RelatedAccIterator(Document(), mContent,
    2027               0 :                                           nsGkAtoms::aria_labelledby));
    2028               0 :       if (mContent->Tag() == nsGkAtoms::label)
    2029               0 :         rel.AppendIter(new IDRefsIterator(mContent, mContent->IsHTML() ?
    2030                 :                                           nsGkAtoms::_for :
    2031               0 :                                           nsGkAtoms::control));
    2032                 : 
    2033               0 :       return rel;
    2034                 :     }
    2035                 :     case nsIAccessibleRelation::RELATION_LABELLED_BY: {
    2036                 :       Relation rel(new IDRefsIterator(mContent,
    2037               0 :                                       nsGkAtoms::aria_labelledby));
    2038               0 :       if (mContent->IsHTML()) {
    2039               0 :         rel.AppendIter(new HTMLLabelIterator(Document(), this));
    2040               0 :       } else if (mContent->IsXUL()) {
    2041               0 :         rel.AppendIter(new XULLabelIterator(Document(), mContent));
    2042                 :       }
    2043                 : 
    2044               0 :       return rel;
    2045                 :     }
    2046                 :     case nsIAccessibleRelation::RELATION_DESCRIBED_BY: {
    2047                 :       Relation rel(new IDRefsIterator(mContent,
    2048               0 :                                         nsGkAtoms::aria_describedby));
    2049               0 :       if (mContent->IsXUL())
    2050               0 :         rel.AppendIter(new XULDescriptionIterator(Document(), mContent));
    2051                 : 
    2052               0 :       return rel;
    2053                 :     }
    2054                 :     case nsIAccessibleRelation::RELATION_DESCRIPTION_FOR: {
    2055               0 :       Relation rel(new RelatedAccIterator(Document(), mContent,
    2056               0 :                                           nsGkAtoms::aria_describedby));
    2057                 : 
    2058                 :       // This affectively adds an optional control attribute to xul:description,
    2059                 :       // which only affects accessibility, by allowing the description to be
    2060                 :       // tied to a control.
    2061               0 :       if (mContent->Tag() == nsGkAtoms::description &&
    2062               0 :           mContent->IsXUL())
    2063                 :         rel.AppendIter(new IDRefsIterator(mContent,
    2064               0 :                                           nsGkAtoms::control));
    2065                 : 
    2066               0 :       return rel;
    2067                 :     }
    2068                 :     case nsIAccessibleRelation::RELATION_NODE_CHILD_OF: {
    2069               0 :       Relation rel(new RelatedAccIterator(Document(), mContent,
    2070               0 :                                           nsGkAtoms::aria_owns));
    2071                 :       
    2072                 :       // This is an ARIA tree or treegrid that doesn't use owns, so we need to
    2073                 :       // get the parent the hard way.
    2074               0 :       if (mRoleMapEntry && (mRoleMapEntry->role == roles::OUTLINEITEM || 
    2075                 :                             mRoleMapEntry->role == roles::ROW)) {
    2076               0 :         AccGroupInfo* groupInfo = GetGroupInfo();
    2077               0 :         if (!groupInfo)
    2078               0 :           return rel;
    2079                 : 
    2080               0 :         rel.AppendTarget(groupInfo->ConceptualParent());
    2081                 :       }
    2082                 : 
    2083                 :       // If accessible is in its own Window, or is the root of a document,
    2084                 :       // then we should provide NODE_CHILD_OF relation so that MSAA clients
    2085                 :       // can easily get to true parent instead of getting to oleacc's
    2086                 :       // ROLE_WINDOW accessible which will prevent us from going up further
    2087                 :       // (because it is system generated and has no idea about the hierarchy
    2088                 :       // above it).
    2089               0 :       nsIFrame *frame = GetFrame();
    2090               0 :       if (frame) {
    2091               0 :         nsIView *view = frame->GetViewExternal();
    2092               0 :         if (view) {
    2093               0 :           nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
    2094               0 :           if (scrollFrame || view->GetWidget() || !frame->GetParent())
    2095               0 :             rel.AppendTarget(Parent());
    2096                 :         }
    2097                 :       }
    2098                 : 
    2099               0 :       return rel;
    2100                 :     }
    2101                 :     case nsIAccessibleRelation::RELATION_CONTROLLED_BY:
    2102               0 :       return Relation(new RelatedAccIterator(Document(), mContent,
    2103               0 :                                              nsGkAtoms::aria_controls));
    2104                 :     case nsIAccessibleRelation::RELATION_CONTROLLER_FOR: {
    2105                 :       Relation rel(new IDRefsIterator(mContent,
    2106               0 :                                       nsGkAtoms::aria_controls));
    2107               0 :       rel.AppendIter(new HTMLOutputIterator(Document(), mContent));
    2108               0 :       return rel;
    2109                 :     }
    2110                 :     case nsIAccessibleRelation::RELATION_FLOWS_TO:
    2111                 :       return Relation(new IDRefsIterator(mContent,
    2112               0 :                                          nsGkAtoms::aria_flowto));
    2113                 :     case nsIAccessibleRelation::RELATION_FLOWS_FROM:
    2114               0 :       return Relation(new RelatedAccIterator(Document(), mContent,
    2115               0 :                                              nsGkAtoms::aria_flowto));
    2116                 :     case nsIAccessibleRelation::RELATION_DEFAULT_BUTTON: {
    2117               0 :       if (mContent->IsHTML()) {
    2118                 :         // HTML form controls implements nsIFormControl interface.
    2119               0 :         nsCOMPtr<nsIFormControl> control(do_QueryInterface(mContent));
    2120               0 :         if (control) {
    2121               0 :           nsCOMPtr<nsIForm> form(do_QueryInterface(control->GetFormElement()));
    2122               0 :           if (form) {
    2123                 :             nsCOMPtr<nsIContent> formContent =
    2124               0 :               do_QueryInterface(form->GetDefaultSubmitElement());
    2125               0 :             return Relation(formContent);
    2126                 :           }
    2127                 :         }
    2128                 :       } else {
    2129                 :         // In XUL, use first <button default="true" .../> in the document
    2130                 :         nsCOMPtr<nsIDOMXULDocument> xulDoc =
    2131               0 :           do_QueryInterface(mContent->OwnerDoc());
    2132               0 :         nsCOMPtr<nsIDOMXULButtonElement> buttonEl;
    2133               0 :         if (xulDoc) {
    2134               0 :           nsCOMPtr<nsIDOMNodeList> possibleDefaultButtons;
    2135               0 :           xulDoc->GetElementsByAttribute(NS_LITERAL_STRING("default"),
    2136               0 :                                          NS_LITERAL_STRING("true"),
    2137               0 :                                          getter_AddRefs(possibleDefaultButtons));
    2138               0 :           if (possibleDefaultButtons) {
    2139                 :             PRUint32 length;
    2140               0 :             possibleDefaultButtons->GetLength(&length);
    2141               0 :             nsCOMPtr<nsIDOMNode> possibleButton;
    2142                 :             // Check for button in list of default="true" elements
    2143               0 :             for (PRUint32 count = 0; count < length && !buttonEl; count ++) {
    2144               0 :               possibleDefaultButtons->Item(count, getter_AddRefs(possibleButton));
    2145               0 :               buttonEl = do_QueryInterface(possibleButton);
    2146                 :             }
    2147                 :           }
    2148               0 :           if (!buttonEl) { // Check for anonymous accept button in <dialog>
    2149               0 :             nsCOMPtr<nsIDOMDocumentXBL> xblDoc(do_QueryInterface(xulDoc));
    2150               0 :             if (xblDoc) {
    2151               0 :               nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(xulDoc);
    2152               0 :               NS_ASSERTION(domDoc, "No DOM document");
    2153               0 :               nsCOMPtr<nsIDOMElement> rootEl;
    2154               0 :               domDoc->GetDocumentElement(getter_AddRefs(rootEl));
    2155               0 :               if (rootEl) {
    2156               0 :                 nsCOMPtr<nsIDOMElement> possibleButtonEl;
    2157               0 :                 xblDoc->GetAnonymousElementByAttribute(rootEl,
    2158               0 :                                                       NS_LITERAL_STRING("default"),
    2159               0 :                                                       NS_LITERAL_STRING("true"),
    2160               0 :                                                       getter_AddRefs(possibleButtonEl));
    2161               0 :                 buttonEl = do_QueryInterface(possibleButtonEl);
    2162                 :               }
    2163                 :             }
    2164                 :           }
    2165               0 :           nsCOMPtr<nsIContent> relatedContent(do_QueryInterface(buttonEl));
    2166               0 :           return Relation(relatedContent);
    2167                 :         }
    2168                 :       }
    2169               0 :       return Relation();
    2170                 :     }
    2171                 :     case nsIAccessibleRelation::RELATION_MEMBER_OF:
    2172               0 :       return Relation(GetAtomicRegion());
    2173                 :     case nsIAccessibleRelation::RELATION_SUBWINDOW_OF:
    2174                 :     case nsIAccessibleRelation::RELATION_EMBEDS:
    2175                 :     case nsIAccessibleRelation::RELATION_EMBEDDED_BY:
    2176                 :     case nsIAccessibleRelation::RELATION_POPUP_FOR:
    2177                 :     case nsIAccessibleRelation::RELATION_PARENT_WINDOW_OF:
    2178                 :     default:
    2179               0 :     return Relation();
    2180                 :   }
    2181                 : }
    2182                 : 
    2183                 : NS_IMETHODIMP
    2184               0 : nsAccessible::GetRelations(nsIArray **aRelations)
    2185                 : {
    2186               0 :   NS_ENSURE_ARG_POINTER(aRelations);
    2187               0 :   *aRelations = nsnull;
    2188                 : 
    2189               0 :   if (IsDefunct())
    2190               0 :     return NS_ERROR_FAILURE;
    2191                 : 
    2192               0 :   nsCOMPtr<nsIMutableArray> relations = do_CreateInstance(NS_ARRAY_CONTRACTID);
    2193               0 :   NS_ENSURE_TRUE(relations, NS_ERROR_OUT_OF_MEMORY);
    2194                 : 
    2195               0 :   for (PRUint32 relType = nsIAccessibleRelation::RELATION_FIRST;
    2196                 :        relType < nsIAccessibleRelation::RELATION_LAST;
    2197                 :        ++relType) {
    2198                 : 
    2199               0 :     nsCOMPtr<nsIAccessibleRelation> relation;
    2200               0 :     nsresult rv = GetRelationByType(relType, getter_AddRefs(relation));
    2201                 : 
    2202               0 :     if (NS_SUCCEEDED(rv) && relation) {
    2203               0 :       PRUint32 targets = 0;
    2204               0 :       relation->GetTargetsCount(&targets);
    2205               0 :       if (targets)
    2206               0 :         relations->AppendElement(relation, false);
    2207                 :     }
    2208                 :   }
    2209                 : 
    2210               0 :   NS_ADDREF(*aRelations = relations);
    2211               0 :   return NS_OK;
    2212                 : }
    2213                 : 
    2214                 : /* void extendSelection (); */
    2215               0 : NS_IMETHODIMP nsAccessible::ExtendSelection()
    2216                 : {
    2217                 :   // XXX Should be implemented, but not high priority
    2218               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    2219                 : }
    2220                 : 
    2221                 : /* [noscript] void getNativeInterface(out voidPtr aOutAccessible); */
    2222               0 : NS_IMETHODIMP nsAccessible::GetNativeInterface(void **aOutAccessible)
    2223                 : {
    2224               0 :   return NS_ERROR_NOT_IMPLEMENTED;
    2225                 : }
    2226                 : 
    2227                 : void
    2228               0 : nsAccessible::DoCommand(nsIContent *aContent, PRUint32 aActionIndex)
    2229                 : {
    2230               0 :   nsIContent* content = aContent ? aContent : mContent.get();
    2231               0 :   NS_DISPATCH_RUNNABLEMETHOD_ARG2(DispatchClickEvent, this, content,
    2232                 :                                   aActionIndex);
    2233               0 : }
    2234                 : 
    2235                 : void
    2236               0 : nsAccessible::DispatchClickEvent(nsIContent *aContent, PRUint32 aActionIndex)
    2237                 : {
    2238               0 :   if (IsDefunct())
    2239               0 :     return;
    2240                 : 
    2241               0 :   nsIPresShell* presShell = mDoc->PresShell();
    2242                 : 
    2243                 :   // Scroll into view.
    2244                 :   presShell->ScrollContentIntoView(aContent, NS_PRESSHELL_SCROLL_ANYWHERE,
    2245                 :                                    NS_PRESSHELL_SCROLL_ANYWHERE,
    2246               0 :                                    nsIPresShell::SCROLL_OVERFLOW_HIDDEN);
    2247                 : 
    2248                 :   // Fire mouse down and mouse up events.
    2249                 :   bool res = nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, presShell,
    2250               0 :                                                aContent);
    2251               0 :   if (!res)
    2252               0 :     return;
    2253                 : 
    2254               0 :   nsCoreUtils::DispatchMouseEvent(NS_MOUSE_BUTTON_UP, presShell, aContent);
    2255                 : }
    2256                 : 
    2257                 : NS_IMETHODIMP
    2258               0 : nsAccessible::ScrollTo(PRUint32 aHow)
    2259                 : {
    2260               0 :   nsAccessNode::ScrollTo(aHow);
    2261               0 :   return NS_OK;
    2262                 : }
    2263                 : 
    2264                 : NS_IMETHODIMP
    2265               0 : nsAccessible::ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY)
    2266                 : {
    2267               0 :   nsIFrame *frame = GetFrame();
    2268               0 :   if (!frame)
    2269               0 :     return NS_ERROR_FAILURE;
    2270                 : 
    2271               0 :   nsIntPoint coords;
    2272                 :   nsresult rv = nsAccUtils::ConvertToScreenCoords(aX, aY, aCoordinateType,
    2273               0 :                                                   this, &coords);
    2274               0 :   NS_ENSURE_SUCCESS(rv, rv);
    2275                 : 
    2276               0 :   nsIFrame *parentFrame = frame;
    2277               0 :   while ((parentFrame = parentFrame->GetParent()))
    2278               0 :     nsCoreUtils::ScrollFrameToPoint(parentFrame, frame, coords);
    2279                 : 
    2280               0 :   return NS_OK;
    2281                 : }
    2282                 : 
    2283                 : // nsIAccessibleSelectable
    2284               0 : NS_IMETHODIMP nsAccessible::GetSelectedChildren(nsIArray **aSelectedAccessibles)
    2285                 : {
    2286               0 :   NS_ENSURE_ARG_POINTER(aSelectedAccessibles);
    2287               0 :   *aSelectedAccessibles = nsnull;
    2288                 : 
    2289               0 :   if (IsDefunct() || !IsSelect())
    2290               0 :     return NS_ERROR_FAILURE;
    2291                 : 
    2292               0 :   nsCOMPtr<nsIArray> items = SelectedItems();
    2293               0 :   if (items) {
    2294               0 :     PRUint32 length = 0;
    2295               0 :     items->GetLength(&length);
    2296               0 :     if (length)
    2297               0 :       items.swap(*aSelectedAccessibles);
    2298                 :   }
    2299                 : 
    2300               0 :   return NS_OK;
    2301                 : }
    2302                 : 
    2303                 : // return the nth selected descendant nsIAccessible object
    2304               0 : NS_IMETHODIMP nsAccessible::RefSelection(PRInt32 aIndex, nsIAccessible **aSelected)
    2305                 : {
    2306               0 :   NS_ENSURE_ARG_POINTER(aSelected);
    2307               0 :   *aSelected = nsnull;
    2308                 : 
    2309               0 :   if (IsDefunct() || !IsSelect())
    2310               0 :     return NS_ERROR_FAILURE;
    2311                 : 
    2312               0 :   if (aIndex < 0) {
    2313               0 :     return NS_ERROR_INVALID_ARG;
    2314                 :   }
    2315                 : 
    2316               0 :   *aSelected = GetSelectedItem(aIndex);
    2317               0 :   if (*aSelected) {
    2318               0 :     NS_ADDREF(*aSelected);
    2319               0 :     return NS_OK;
    2320                 :   }
    2321                 : 
    2322               0 :   return NS_ERROR_INVALID_ARG;
    2323                 : }
    2324                 : 
    2325               0 : NS_IMETHODIMP nsAccessible::GetSelectionCount(PRInt32 *aSelectionCount)
    2326                 : {
    2327               0 :   NS_ENSURE_ARG_POINTER(aSelectionCount);
    2328               0 :   *aSelectionCount = 0;
    2329                 : 
    2330               0 :   if (IsDefunct() || !IsSelect())
    2331               0 :     return NS_ERROR_FAILURE;
    2332                 : 
    2333               0 :   *aSelectionCount = SelectedItemCount();
    2334               0 :   return NS_OK;
    2335                 : }
    2336                 : 
    2337               0 : NS_IMETHODIMP nsAccessible::AddChildToSelection(PRInt32 aIndex)
    2338                 : {
    2339               0 :   if (IsDefunct() || !IsSelect())
    2340               0 :     return NS_ERROR_FAILURE;
    2341                 : 
    2342               0 :   return aIndex >= 0 && AddItemToSelection(aIndex) ?
    2343               0 :     NS_OK : NS_ERROR_INVALID_ARG;
    2344                 : }
    2345                 : 
    2346               0 : NS_IMETHODIMP nsAccessible::RemoveChildFromSelection(PRInt32 aIndex)
    2347                 : {
    2348               0 :   if (IsDefunct() || !IsSelect())
    2349               0 :     return NS_ERROR_FAILURE;
    2350                 : 
    2351               0 :   return aIndex >=0 && RemoveItemFromSelection(aIndex) ?
    2352               0 :     NS_OK : NS_ERROR_INVALID_ARG;
    2353                 : }
    2354                 : 
    2355               0 : NS_IMETHODIMP nsAccessible::IsChildSelected(PRInt32 aIndex, bool *aIsSelected)
    2356                 : {
    2357               0 :   NS_ENSURE_ARG_POINTER(aIsSelected);
    2358               0 :   *aIsSelected = false;
    2359                 : 
    2360               0 :   if (IsDefunct() || !IsSelect())
    2361               0 :     return NS_ERROR_FAILURE;
    2362                 : 
    2363               0 :   NS_ENSURE_TRUE(aIndex >= 0, NS_ERROR_FAILURE);
    2364                 : 
    2365               0 :   *aIsSelected = IsItemSelected(aIndex);
    2366               0 :   return NS_OK;
    2367                 : }
    2368                 : 
    2369                 : NS_IMETHODIMP
    2370               0 : nsAccessible::ClearSelection()
    2371                 : {
    2372               0 :   if (IsDefunct() || !IsSelect())
    2373               0 :     return NS_ERROR_FAILURE;
    2374                 : 
    2375               0 :   UnselectAll();
    2376               0 :   return NS_OK;
    2377                 : }
    2378                 : 
    2379                 : NS_IMETHODIMP
    2380               0 : nsAccessible::SelectAllSelection(bool* aIsMultiSelect)
    2381                 : {
    2382               0 :   NS_ENSURE_ARG_POINTER(aIsMultiSelect);
    2383               0 :   *aIsMultiSelect = false;
    2384                 : 
    2385               0 :   if (IsDefunct() || !IsSelect())
    2386               0 :     return NS_ERROR_FAILURE;
    2387                 : 
    2388               0 :   *aIsMultiSelect = SelectAll();
    2389               0 :   return NS_OK;
    2390                 : }
    2391                 : 
    2392                 : // nsIAccessibleHyperLink
    2393                 : // Because of new-atk design, any embedded object in text can implement
    2394                 : // nsIAccessibleHyperLink, which helps determine where it is located
    2395                 : // within containing text
    2396                 : 
    2397                 : // readonly attribute long nsIAccessibleHyperLink::anchorCount
    2398                 : NS_IMETHODIMP
    2399               0 : nsAccessible::GetAnchorCount(PRInt32 *aAnchorCount)
    2400                 : {
    2401               0 :   NS_ENSURE_ARG_POINTER(aAnchorCount);
    2402               0 :   *aAnchorCount = 0;
    2403                 : 
    2404               0 :   if (IsDefunct())
    2405               0 :     return NS_ERROR_FAILURE;
    2406                 : 
    2407               0 :   *aAnchorCount = AnchorCount();
    2408               0 :   return NS_OK;
    2409                 : }
    2410                 : 
    2411                 : // readonly attribute long nsIAccessibleHyperLink::startIndex
    2412                 : NS_IMETHODIMP
    2413               0 : nsAccessible::GetStartIndex(PRInt32 *aStartIndex)
    2414                 : {
    2415               0 :   NS_ENSURE_ARG_POINTER(aStartIndex);
    2416               0 :   *aStartIndex = 0;
    2417                 : 
    2418               0 :   if (IsDefunct())
    2419               0 :     return NS_ERROR_FAILURE;
    2420                 : 
    2421               0 :   *aStartIndex = StartOffset();
    2422               0 :   return NS_OK;
    2423                 : }
    2424                 : 
    2425                 : // readonly attribute long nsIAccessibleHyperLink::endIndex
    2426                 : NS_IMETHODIMP
    2427               0 : nsAccessible::GetEndIndex(PRInt32 *aEndIndex)
    2428                 : {
    2429               0 :   NS_ENSURE_ARG_POINTER(aEndIndex);
    2430               0 :   *aEndIndex = 0;
    2431                 : 
    2432               0 :   if (IsDefunct())
    2433               0 :     return NS_ERROR_FAILURE;
    2434                 : 
    2435               0 :   *aEndIndex = EndOffset();
    2436               0 :   return NS_OK;
    2437                 : }
    2438                 : 
    2439                 : NS_IMETHODIMP
    2440               0 : nsAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
    2441                 : {
    2442               0 :   NS_ENSURE_ARG_POINTER(aURI);
    2443                 : 
    2444               0 :   if (IsDefunct())
    2445               0 :     return NS_ERROR_FAILURE;
    2446                 : 
    2447               0 :   if (aIndex < 0 || aIndex >= static_cast<PRInt32>(AnchorCount()))
    2448               0 :     return NS_ERROR_INVALID_ARG;
    2449                 : 
    2450               0 :   nsRefPtr<nsIURI>(AnchorURIAt(aIndex)).forget(aURI);
    2451               0 :   return NS_OK;
    2452                 : }
    2453                 : 
    2454                 : 
    2455                 : NS_IMETHODIMP
    2456               0 : nsAccessible::GetAnchor(PRInt32 aIndex, nsIAccessible** aAccessible)
    2457                 : {
    2458               0 :   NS_ENSURE_ARG_POINTER(aAccessible);
    2459               0 :   *aAccessible = nsnull;
    2460                 : 
    2461               0 :   if (IsDefunct())
    2462               0 :     return NS_ERROR_FAILURE;
    2463                 : 
    2464               0 :   if (aIndex < 0 || aIndex >= static_cast<PRInt32>(AnchorCount()))
    2465               0 :     return NS_ERROR_INVALID_ARG;
    2466                 : 
    2467               0 :   NS_IF_ADDREF(*aAccessible = AnchorAt(aIndex));
    2468               0 :   return NS_OK;
    2469                 : }
    2470                 : 
    2471                 : // readonly attribute boolean nsIAccessibleHyperLink::valid
    2472                 : NS_IMETHODIMP
    2473               0 : nsAccessible::GetValid(bool *aValid)
    2474                 : {
    2475               0 :   NS_ENSURE_ARG_POINTER(aValid);
    2476               0 :   *aValid = false;
    2477                 : 
    2478               0 :   if (IsDefunct())
    2479               0 :     return NS_ERROR_FAILURE;
    2480                 : 
    2481               0 :   *aValid = IsLinkValid();
    2482               0 :   return NS_OK;
    2483                 : }
    2484                 : 
    2485                 : // readonly attribute boolean nsIAccessibleHyperLink::selected
    2486                 : NS_IMETHODIMP
    2487               0 : nsAccessible::GetSelected(bool *aSelected)
    2488                 : {
    2489               0 :   NS_ENSURE_ARG_POINTER(aSelected);
    2490               0 :   *aSelected = false;
    2491                 : 
    2492               0 :   if (IsDefunct())
    2493               0 :     return NS_ERROR_FAILURE;
    2494                 : 
    2495               0 :   *aSelected = IsLinkSelected();
    2496               0 :   return NS_OK;
    2497                 : 
    2498                 : }
    2499                 : 
    2500                 : void
    2501               0 : nsAccessible::AppendTextTo(nsAString& aText, PRUint32 aStartOffset,
    2502                 :                            PRUint32 aLength)
    2503                 : {
    2504                 :   // Return text representation of non-text accessible within hypertext
    2505                 :   // accessible. Text accessible overrides this method to return enclosed text.
    2506               0 :   if (aStartOffset != 0 || aLength == 0)
    2507               0 :     return;
    2508                 : 
    2509               0 :   nsIFrame *frame = GetFrame();
    2510               0 :   if (!frame)
    2511               0 :     return;
    2512                 : 
    2513               0 :   if (frame->GetType() == nsGkAtoms::brFrame) {
    2514               0 :     aText += kForcedNewLineChar;
    2515               0 :   } else if (nsAccUtils::MustPrune(Parent())) {
    2516                 :     // Expose the embedded object accessible as imaginary embedded object
    2517                 :     // character if its parent hypertext accessible doesn't expose children to
    2518                 :     // AT.
    2519               0 :     aText += kImaginaryEmbeddedObjectChar;
    2520                 :   } else {
    2521               0 :     aText += kEmbeddedObjectChar;
    2522                 :   }
    2523                 : }
    2524                 : 
    2525                 : ////////////////////////////////////////////////////////////////////////////////
    2526                 : // nsAccessNode public methods
    2527                 : 
    2528                 : void
    2529               0 : nsAccessible::Shutdown()
    2530                 : {
    2531                 :   // Invalidate the child count and pointers to other accessibles, also make
    2532                 :   // sure none of its children point to this parent
    2533               0 :   InvalidateChildren();
    2534               0 :   if (mParent)
    2535               0 :     mParent->RemoveChild(this);
    2536                 : 
    2537               0 :   nsAccessNodeWrap::Shutdown();
    2538               0 : }
    2539                 : 
    2540                 : ////////////////////////////////////////////////////////////////////////////////
    2541                 : // nsAccessible public methods
    2542                 : 
    2543                 : nsresult
    2544               0 : nsAccessible::GetARIAName(nsAString& aName)
    2545                 : {
    2546               0 :   nsAutoString label;
    2547                 : 
    2548                 :   // aria-labelledby now takes precedence over aria-label
    2549                 :   nsresult rv = nsTextEquivUtils::
    2550               0 :     GetTextEquivFromIDRefs(this, nsGkAtoms::aria_labelledby, label);
    2551               0 :   if (NS_SUCCEEDED(rv)) {
    2552               0 :     label.CompressWhitespace();
    2553               0 :     aName = label;
    2554                 :   }
    2555                 : 
    2556               0 :   if (label.IsEmpty() &&
    2557               0 :       mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::aria_label,
    2558               0 :                         label)) {
    2559               0 :     label.CompressWhitespace();
    2560               0 :     aName = label;
    2561                 :   }
    2562                 :   
    2563               0 :   return NS_OK;
    2564                 : }
    2565                 : 
    2566                 : nsresult
    2567               0 : nsAccessible::GetNameInternal(nsAString& aName)
    2568                 : {
    2569               0 :   if (mContent->IsHTML())
    2570               0 :     return GetHTMLName(aName);
    2571                 : 
    2572               0 :   if (mContent->IsXUL())
    2573               0 :     return GetXULName(aName);
    2574                 : 
    2575               0 :   return NS_OK;
    2576                 : }
    2577                 : 
    2578                 : // nsAccessible protected
    2579                 : void
    2580               0 : nsAccessible::BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent)
    2581                 : {
    2582               0 :   NS_PRECONDITION(aParent, "This method isn't used to set null parent!");
    2583                 : 
    2584               0 :   if (mParent) {
    2585               0 :     if (mParent != aParent) {
    2586               0 :       NS_ERROR("Adopting child!");
    2587               0 :       mParent->RemoveChild(this);
    2588                 :     } else {
    2589               0 :       NS_ERROR("Binding to the same parent!");
    2590               0 :       return;
    2591                 :     }
    2592                 :   }
    2593                 : 
    2594               0 :   mParent = aParent;
    2595               0 :   mIndexInParent = aIndexInParent;
    2596                 : }
    2597                 : 
    2598                 : void
    2599               0 : nsAccessible::UnbindFromParent()
    2600                 : {
    2601               0 :   mParent = nsnull;
    2602               0 :   mIndexInParent = -1;
    2603               0 :   mIndexOfEmbeddedChild = -1;
    2604               0 :   mGroupInfo = nsnull;
    2605               0 : }
    2606                 : 
    2607                 : void
    2608               0 : nsAccessible::InvalidateChildren()
    2609                 : {
    2610               0 :   PRInt32 childCount = mChildren.Length();
    2611               0 :   for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
    2612               0 :     nsAccessible* child = mChildren.ElementAt(childIdx);
    2613               0 :     child->UnbindFromParent();
    2614                 :   }
    2615                 : 
    2616               0 :   mEmbeddedObjCollector = nsnull;
    2617               0 :   mChildren.Clear();
    2618               0 :   SetChildrenFlag(eChildrenUninitialized);
    2619               0 : }
    2620                 : 
    2621                 : bool
    2622               0 : nsAccessible::AppendChild(nsAccessible* aChild)
    2623                 : {
    2624               0 :   if (!aChild)
    2625               0 :     return false;
    2626                 : 
    2627               0 :   if (!mChildren.AppendElement(aChild))
    2628               0 :     return false;
    2629                 : 
    2630               0 :   if (!nsAccUtils::IsEmbeddedObject(aChild))
    2631               0 :     SetChildrenFlag(eMixedChildren);
    2632                 : 
    2633               0 :   aChild->BindToParent(this, mChildren.Length() - 1);
    2634               0 :   return true;
    2635                 : }
    2636                 : 
    2637                 : bool
    2638               0 : nsAccessible::InsertChildAt(PRUint32 aIndex, nsAccessible* aChild)
    2639                 : {
    2640               0 :   if (!aChild)
    2641               0 :     return false;
    2642                 : 
    2643               0 :   if (!mChildren.InsertElementAt(aIndex, aChild))
    2644               0 :     return false;
    2645                 : 
    2646               0 :   for (PRUint32 idx = aIndex + 1; idx < mChildren.Length(); idx++) {
    2647               0 :     NS_ASSERTION(mChildren[idx]->mIndexInParent == idx - 1, "Accessible child index doesn't match");
    2648               0 :     mChildren[idx]->mIndexInParent = idx;
    2649                 :   }
    2650                 : 
    2651               0 :   if (nsAccUtils::IsText(aChild))
    2652               0 :     SetChildrenFlag(eMixedChildren);
    2653                 : 
    2654               0 :   mEmbeddedObjCollector = nsnull;
    2655                 : 
    2656               0 :   aChild->BindToParent(this, aIndex);
    2657               0 :   return true;
    2658                 : }
    2659                 : 
    2660                 : bool
    2661               0 : nsAccessible::RemoveChild(nsAccessible* aChild)
    2662                 : {
    2663               0 :   if (!aChild)
    2664               0 :     return false;
    2665                 : 
    2666               0 :   if (aChild->mParent != this || aChild->mIndexInParent == -1)
    2667               0 :     return false;
    2668                 : 
    2669               0 :   PRUint32 index = static_cast<PRUint32>(aChild->mIndexInParent);
    2670               0 :   if (index >= mChildren.Length() || mChildren[index] != aChild) {
    2671               0 :     NS_ERROR("Child is bound to parent but parent hasn't this child at its index!");
    2672               0 :     aChild->UnbindFromParent();
    2673               0 :     return false;
    2674                 :   }
    2675                 : 
    2676               0 :   for (PRUint32 idx = index + 1; idx < mChildren.Length(); idx++) {
    2677               0 :     NS_ASSERTION(mChildren[idx]->mIndexInParent == idx, "Accessible child index doesn't match");
    2678               0 :     mChildren[idx]->mIndexInParent = idx - 1;
    2679                 :   }
    2680                 : 
    2681               0 :   aChild->UnbindFromParent();
    2682               0 :   mChildren.RemoveElementAt(index);
    2683               0 :   mEmbeddedObjCollector = nsnull;
    2684                 : 
    2685               0 :   return true;
    2686                 : }
    2687                 : 
    2688                 : nsAccessible*
    2689               0 : nsAccessible::GetChildAt(PRUint32 aIndex)
    2690                 : {
    2691               0 :   nsAccessible *child = mChildren.SafeElementAt(aIndex, nsnull);
    2692               0 :   if (!child)
    2693               0 :     return nsnull;
    2694                 : 
    2695                 : #ifdef DEBUG
    2696               0 :   nsAccessible* realParent = child->mParent;
    2697               0 :   NS_ASSERTION(!realParent || realParent == this,
    2698                 :                "Two accessibles have the same first child accessible!");
    2699                 : #endif
    2700                 : 
    2701               0 :   return child;
    2702                 : }
    2703                 : 
    2704                 : PRInt32
    2705               0 : nsAccessible::GetChildCount()
    2706                 : {
    2707               0 :   return mChildren.Length();
    2708                 : }
    2709                 : 
    2710                 : PRInt32
    2711               0 : nsAccessible::GetIndexOf(nsAccessible* aChild)
    2712                 : {
    2713               0 :   return (aChild->mParent != this) ? -1 : aChild->IndexInParent();
    2714                 : }
    2715                 : 
    2716                 : PRInt32
    2717               0 : nsAccessible::IndexInParent() const
    2718                 : {
    2719               0 :   return mIndexInParent;
    2720                 : }
    2721                 : 
    2722                 : PRInt32
    2723               0 : nsAccessible::GetEmbeddedChildCount()
    2724                 : {
    2725               0 :   if (IsChildrenFlag(eMixedChildren)) {
    2726               0 :     if (!mEmbeddedObjCollector)
    2727               0 :       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
    2728               0 :     return mEmbeddedObjCollector ? mEmbeddedObjCollector->Count() : -1;
    2729                 :   }
    2730                 : 
    2731               0 :   return GetChildCount();
    2732                 : }
    2733                 : 
    2734                 : nsAccessible*
    2735               0 : nsAccessible::GetEmbeddedChildAt(PRUint32 aIndex)
    2736                 : {
    2737               0 :   if (IsChildrenFlag(eMixedChildren)) {
    2738               0 :     if (!mEmbeddedObjCollector)
    2739               0 :       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
    2740                 :     return mEmbeddedObjCollector ?
    2741               0 :       mEmbeddedObjCollector->GetAccessibleAt(aIndex) : nsnull;
    2742                 :   }
    2743                 : 
    2744               0 :   return GetChildAt(aIndex);
    2745                 : }
    2746                 : 
    2747                 : PRInt32
    2748               0 : nsAccessible::GetIndexOfEmbeddedChild(nsAccessible* aChild)
    2749                 : {
    2750               0 :   if (IsChildrenFlag(eMixedChildren)) {
    2751               0 :     if (!mEmbeddedObjCollector)
    2752               0 :       mEmbeddedObjCollector = new EmbeddedObjCollector(this);
    2753                 :     return mEmbeddedObjCollector ?
    2754               0 :       mEmbeddedObjCollector->GetIndexAt(aChild) : -1;
    2755                 :   }
    2756                 : 
    2757               0 :   return GetIndexOf(aChild);
    2758                 : }
    2759                 : 
    2760                 : ////////////////////////////////////////////////////////////////////////////////
    2761                 : // HyperLinkAccessible methods
    2762                 : 
    2763                 : bool
    2764               0 : nsAccessible::IsLink()
    2765                 : {
    2766                 :   // Every embedded accessible within hypertext accessible implements
    2767                 :   // hyperlink interface.
    2768               0 :   return mParent && mParent->IsHyperText() && nsAccUtils::IsEmbeddedObject(this);
    2769                 : }
    2770                 : 
    2771                 : PRUint32
    2772               0 : nsAccessible::StartOffset()
    2773                 : {
    2774               0 :   NS_PRECONDITION(IsLink(), "StartOffset is called not on hyper link!");
    2775                 : 
    2776               0 :   nsHyperTextAccessible* hyperText = mParent ? mParent->AsHyperText() : nsnull;
    2777               0 :   return hyperText ? hyperText->GetChildOffset(this) : 0;
    2778                 : }
    2779                 : 
    2780                 : PRUint32
    2781               0 : nsAccessible::EndOffset()
    2782                 : {
    2783               0 :   NS_PRECONDITION(IsLink(), "EndOffset is called on not hyper link!");
    2784                 : 
    2785               0 :   nsHyperTextAccessible* hyperText = mParent ? mParent->AsHyperText() : nsnull;
    2786               0 :   return hyperText ? (hyperText->GetChildOffset(this) + 1) : 0;
    2787                 : }
    2788                 : 
    2789                 : bool
    2790               0 : nsAccessible::IsLinkSelected()
    2791                 : {
    2792               0 :   NS_PRECONDITION(IsLink(),
    2793                 :                   "IsLinkSelected() called on something that is not a hyper link!");
    2794               0 :   return FocusMgr()->IsFocused(this);
    2795                 : }
    2796                 : 
    2797                 : PRUint32
    2798               0 : nsAccessible::AnchorCount()
    2799                 : {
    2800               0 :   NS_PRECONDITION(IsLink(), "AnchorCount is called on not hyper link!");
    2801               0 :   return 1;
    2802                 : }
    2803                 : 
    2804                 : nsAccessible*
    2805               0 : nsAccessible::AnchorAt(PRUint32 aAnchorIndex)
    2806                 : {
    2807               0 :   NS_PRECONDITION(IsLink(), "GetAnchor is called on not hyper link!");
    2808               0 :   return aAnchorIndex == 0 ? this : nsnull;
    2809                 : }
    2810                 : 
    2811                 : already_AddRefed<nsIURI>
    2812               0 : nsAccessible::AnchorURIAt(PRUint32 aAnchorIndex)
    2813                 : {
    2814               0 :   NS_PRECONDITION(IsLink(), "AnchorURIAt is called on not hyper link!");
    2815                 : 
    2816               0 :   if (aAnchorIndex != 0)
    2817               0 :     return nsnull;
    2818                 : 
    2819                 :   // Check if it's a simple xlink.
    2820               0 :   if (nsCoreUtils::IsXLink(mContent)) {
    2821               0 :     nsAutoString href;
    2822               0 :     mContent->GetAttr(kNameSpaceID_XLink, nsGkAtoms::href, href);
    2823                 : 
    2824               0 :     nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
    2825               0 :     nsCOMPtr<nsIDocument> document = mContent->OwnerDoc();
    2826               0 :     nsIURI* anchorURI = nsnull;
    2827                 :     NS_NewURI(&anchorURI, href,
    2828               0 :               document ? document->GetDocumentCharacterSet().get() : nsnull,
    2829               0 :               baseURI);
    2830               0 :     return anchorURI;
    2831                 :   }
    2832                 : 
    2833               0 :   return nsnull;
    2834                 : }
    2835                 : 
    2836                 : 
    2837                 : ////////////////////////////////////////////////////////////////////////////////
    2838                 : // SelectAccessible
    2839                 : 
    2840                 : bool
    2841               0 : nsAccessible::IsSelect()
    2842                 : {
    2843                 :   // If we have an ARIA role attribute present and the role allows multi
    2844                 :   // selectable state, then we need to support SelectAccessible interface. If
    2845                 :   // either attribute (role or multiselectable) change, then we'll destroy this
    2846                 :   // accessible so that we can follow COM identity rules.
    2847                 : 
    2848                 :   return mRoleMapEntry &&
    2849                 :     (mRoleMapEntry->attributeMap1 == eARIAMultiSelectable ||
    2850                 :      mRoleMapEntry->attributeMap2 == eARIAMultiSelectable ||
    2851               0 :      mRoleMapEntry->attributeMap3 == eARIAMultiSelectable);
    2852                 : }
    2853                 : 
    2854                 : already_AddRefed<nsIArray>
    2855               0 : nsAccessible::SelectedItems()
    2856                 : {
    2857               0 :   nsCOMPtr<nsIMutableArray> selectedItems = do_CreateInstance(NS_ARRAY_CONTRACTID);
    2858               0 :   if (!selectedItems)
    2859               0 :     return nsnull;
    2860                 : 
    2861               0 :   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
    2862               0 :   nsIAccessible* selected = nsnull;
    2863               0 :   while ((selected = iter.Next()))
    2864               0 :     selectedItems->AppendElement(selected, false);
    2865                 : 
    2866               0 :   nsIMutableArray* items = nsnull;
    2867               0 :   selectedItems.forget(&items);
    2868               0 :   return items;
    2869                 : }
    2870                 : 
    2871                 : PRUint32
    2872               0 : nsAccessible::SelectedItemCount()
    2873                 : {
    2874               0 :   PRUint32 count = 0;
    2875               0 :   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
    2876               0 :   nsAccessible* selected = nsnull;
    2877               0 :   while ((selected = iter.Next()))
    2878               0 :     ++count;
    2879                 : 
    2880               0 :   return count;
    2881                 : }
    2882                 : 
    2883                 : nsAccessible*
    2884               0 : nsAccessible::GetSelectedItem(PRUint32 aIndex)
    2885                 : {
    2886               0 :   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
    2887               0 :   nsAccessible* selected = nsnull;
    2888                 : 
    2889               0 :   PRUint32 index = 0;
    2890               0 :   while ((selected = iter.Next()) && index < aIndex)
    2891               0 :     index++;
    2892                 : 
    2893               0 :   return selected;
    2894                 : }
    2895                 : 
    2896                 : bool
    2897               0 : nsAccessible::IsItemSelected(PRUint32 aIndex)
    2898                 : {
    2899               0 :   PRUint32 index = 0;
    2900               0 :   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
    2901               0 :   nsAccessible* selected = nsnull;
    2902               0 :   while ((selected = iter.Next()) && index < aIndex)
    2903               0 :     index++;
    2904                 : 
    2905                 :   return selected &&
    2906               0 :     selected->State() & states::SELECTED;
    2907                 : }
    2908                 : 
    2909                 : bool
    2910               0 : nsAccessible::AddItemToSelection(PRUint32 aIndex)
    2911                 : {
    2912               0 :   PRUint32 index = 0;
    2913               0 :   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
    2914               0 :   nsAccessible* selected = nsnull;
    2915               0 :   while ((selected = iter.Next()) && index < aIndex)
    2916               0 :     index++;
    2917                 : 
    2918               0 :   if (selected)
    2919               0 :     selected->SetSelected(true);
    2920                 : 
    2921               0 :   return static_cast<bool>(selected);
    2922                 : }
    2923                 : 
    2924                 : bool
    2925               0 : nsAccessible::RemoveItemFromSelection(PRUint32 aIndex)
    2926                 : {
    2927               0 :   PRUint32 index = 0;
    2928               0 :   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
    2929               0 :   nsAccessible* selected = nsnull;
    2930               0 :   while ((selected = iter.Next()) && index < aIndex)
    2931               0 :     index++;
    2932                 : 
    2933               0 :   if (selected)
    2934               0 :     selected->SetSelected(false);
    2935                 : 
    2936               0 :   return static_cast<bool>(selected);
    2937                 : }
    2938                 : 
    2939                 : bool
    2940               0 : nsAccessible::SelectAll()
    2941                 : {
    2942               0 :   bool success = false;
    2943               0 :   nsAccessible* selectable = nsnull;
    2944                 : 
    2945               0 :   AccIterator iter(this, filters::GetSelectable, AccIterator::eTreeNav);
    2946               0 :   while((selectable = iter.Next())) {
    2947               0 :     success = true;
    2948               0 :     selectable->SetSelected(true);
    2949                 :   }
    2950               0 :   return success;
    2951                 : }
    2952                 : 
    2953                 : bool
    2954               0 : nsAccessible::UnselectAll()
    2955                 : {
    2956               0 :   bool success = false;
    2957               0 :   nsAccessible* selected = nsnull;
    2958                 : 
    2959               0 :   AccIterator iter(this, filters::GetSelected, AccIterator::eTreeNav);
    2960               0 :   while ((selected = iter.Next())) {
    2961               0 :     success = true;
    2962               0 :     selected->SetSelected(false);
    2963                 :   }
    2964               0 :   return success;
    2965                 : }
    2966                 : 
    2967                 : ////////////////////////////////////////////////////////////////////////////////
    2968                 : // Widgets
    2969                 : 
    2970                 : bool
    2971               0 : nsAccessible::IsWidget() const
    2972                 : {
    2973               0 :   return false;
    2974                 : }
    2975                 : 
    2976                 : bool
    2977               0 : nsAccessible::IsActiveWidget() const
    2978                 : {
    2979               0 :   return FocusMgr()->IsFocused(this);
    2980                 : }
    2981                 : 
    2982                 : bool
    2983               0 : nsAccessible::AreItemsOperable() const
    2984                 : {
    2985               0 :   return mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::aria_activedescendant);
    2986                 : }
    2987                 : 
    2988                 : nsAccessible*
    2989               0 : nsAccessible::CurrentItem()
    2990                 : {
    2991                 :   // Check for aria-activedescendant, which changes which element has focus.
    2992                 :   // For activedescendant, the ARIA spec does not require that the user agent
    2993                 :   // checks whether pointed node is actually a DOM descendant of the element
    2994                 :   // with the aria-activedescendant attribute.
    2995               0 :   nsAutoString id;
    2996               0 :   if (mContent->GetAttr(kNameSpaceID_None,
    2997               0 :                         nsGkAtoms::aria_activedescendant, id)) {
    2998               0 :     nsIDocument* DOMDoc = mContent->OwnerDoc();
    2999               0 :     dom::Element* activeDescendantElm = DOMDoc->GetElementById(id);
    3000               0 :     if (activeDescendantElm) {
    3001               0 :       nsDocAccessible* document = Document();
    3002               0 :       if (document)
    3003               0 :         return document->GetAccessible(activeDescendantElm);
    3004                 :     }
    3005                 :   }
    3006               0 :   return nsnull;
    3007                 : }
    3008                 : 
    3009                 : void
    3010               0 : nsAccessible::SetCurrentItem(nsAccessible* aItem)
    3011                 : {
    3012               0 :   nsIAtom* id = aItem->GetContent()->GetID();
    3013               0 :   if (id) {
    3014               0 :     nsAutoString idStr;
    3015               0 :     id->ToString(idStr);
    3016                 :     mContent->SetAttr(kNameSpaceID_None,
    3017               0 :                       nsGkAtoms::aria_activedescendant, idStr, true);
    3018                 :   }
    3019               0 : }
    3020                 : 
    3021                 : nsAccessible*
    3022               0 : nsAccessible::ContainerWidget() const
    3023                 : {
    3024               0 :   if (HasARIARole() && mContent->HasID()) {
    3025               0 :     for (nsAccessible* parent = Parent(); parent; parent = parent->Parent()) {
    3026               0 :       nsIContent* parentContent = parent->GetContent();
    3027               0 :       if (parentContent &&
    3028                 :         parentContent->HasAttr(kNameSpaceID_None,
    3029               0 :                                nsGkAtoms::aria_activedescendant)) {
    3030               0 :         return parent;
    3031                 :       }
    3032                 : 
    3033                 :       // Don't cross DOM document boundaries.
    3034               0 :       if (parent->IsDocumentNode())
    3035               0 :         break;
    3036                 :     }
    3037                 :   }
    3038               0 :   return nsnull;
    3039                 : }
    3040                 : 
    3041                 : ////////////////////////////////////////////////////////////////////////////////
    3042                 : // nsAccessible protected methods
    3043                 : 
    3044                 : void
    3045               0 : nsAccessible::CacheChildren()
    3046                 : {
    3047               0 :   nsDocAccessible* doc = Document();
    3048               0 :   NS_ENSURE_TRUE(doc,);
    3049                 : 
    3050               0 :   nsAccTreeWalker walker(doc, mContent, CanHaveAnonChildren());
    3051                 : 
    3052               0 :   nsAccessible* child = nsnull;
    3053               0 :   while ((child = walker.NextChild()) && AppendChild(child));
    3054                 : }
    3055                 : 
    3056                 : void
    3057               0 : nsAccessible::TestChildCache(nsAccessible* aCachedChild) const
    3058                 : {
    3059                 : #ifdef DEBUG
    3060               0 :   PRInt32 childCount = mChildren.Length();
    3061               0 :   if (childCount == 0) {
    3062               0 :     NS_ASSERTION(IsChildrenFlag(eChildrenUninitialized),
    3063                 :                  "No children but initialized!");
    3064               0 :     return;
    3065                 :   }
    3066                 : 
    3067               0 :   nsAccessible *child = nsnull;
    3068               0 :   for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
    3069               0 :     child = mChildren[childIdx];
    3070               0 :     if (child == aCachedChild)
    3071               0 :       break;
    3072                 :   }
    3073                 : 
    3074               0 :   NS_ASSERTION(child == aCachedChild,
    3075                 :                "[TestChildCache] cached accessible wasn't found. Wrong accessible tree!");  
    3076                 : #endif
    3077                 : }
    3078                 : 
    3079                 : // nsAccessible public
    3080                 : bool
    3081               0 : nsAccessible::EnsureChildren()
    3082                 : {
    3083               0 :   if (IsDefunct()) {
    3084               0 :     SetChildrenFlag(eChildrenUninitialized);
    3085               0 :     return true;
    3086                 :   }
    3087                 : 
    3088               0 :   if (!IsChildrenFlag(eChildrenUninitialized))
    3089               0 :     return false;
    3090                 : 
    3091                 :   // State is embedded children until text leaf accessible is appended.
    3092               0 :   SetChildrenFlag(eEmbeddedChildren); // Prevent reentry
    3093                 : 
    3094               0 :   CacheChildren();
    3095               0 :   return false;
    3096                 : }
    3097                 : 
    3098                 : nsAccessible*
    3099               0 : nsAccessible::GetSiblingAtOffset(PRInt32 aOffset, nsresult* aError) const
    3100                 : {
    3101               0 :   if (!mParent || mIndexInParent == -1) {
    3102               0 :     if (aError)
    3103               0 :       *aError = NS_ERROR_UNEXPECTED;
    3104                 : 
    3105               0 :     return nsnull;
    3106                 :   }
    3107                 : 
    3108               0 :   if (aError && mIndexInParent + aOffset >= mParent->GetChildCount()) {
    3109               0 :     *aError = NS_OK; // fail peacefully
    3110               0 :     return nsnull;
    3111                 :   }
    3112                 : 
    3113               0 :   nsAccessible* child = mParent->GetChildAt(mIndexInParent + aOffset);
    3114               0 :   if (aError && !child)
    3115               0 :     *aError = NS_ERROR_UNEXPECTED;
    3116                 : 
    3117               0 :   return child;
    3118                 : }
    3119                 : 
    3120                 : nsAccessible *
    3121               0 : nsAccessible::GetFirstAvailableAccessible(nsINode *aStartNode) const
    3122                 : {
    3123               0 :   nsAccessible* accessible = mDoc->GetAccessible(aStartNode);
    3124               0 :   if (accessible)
    3125               0 :     return accessible;
    3126                 : 
    3127               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(aStartNode->OwnerDoc());
    3128               0 :   NS_ENSURE_TRUE(domDoc, nsnull);
    3129                 : 
    3130               0 :   nsCOMPtr<nsIDOMNode> currentNode = do_QueryInterface(aStartNode);
    3131               0 :   nsCOMPtr<nsIDOMNode> rootNode = do_QueryInterface(GetNode());
    3132               0 :   nsCOMPtr<nsIDOMTreeWalker> walker;
    3133               0 :   domDoc->CreateTreeWalker(rootNode,
    3134                 :                            nsIDOMNodeFilter::SHOW_ELEMENT | nsIDOMNodeFilter::SHOW_TEXT,
    3135               0 :                            nsnull, false, getter_AddRefs(walker));
    3136               0 :   NS_ENSURE_TRUE(walker, nsnull);
    3137                 : 
    3138               0 :   walker->SetCurrentNode(currentNode);
    3139               0 :   while (true) {
    3140               0 :     walker->NextNode(getter_AddRefs(currentNode));
    3141               0 :     if (!currentNode)
    3142               0 :       return nsnull;
    3143                 : 
    3144               0 :     nsCOMPtr<nsINode> node(do_QueryInterface(currentNode));
    3145               0 :     nsAccessible* accessible = mDoc->GetAccessible(node);
    3146               0 :     if (accessible)
    3147               0 :       return accessible;
    3148                 :   }
    3149                 : 
    3150                 :   return nsnull;
    3151                 : }
    3152                 : 
    3153                 : nsresult
    3154               0 : nsAccessible::GetAttrValue(nsIAtom *aProperty, double *aValue)
    3155                 : {
    3156               0 :   NS_ENSURE_ARG_POINTER(aValue);
    3157               0 :   *aValue = 0;
    3158                 : 
    3159               0 :   if (IsDefunct())
    3160               0 :     return NS_ERROR_FAILURE;  // Node already shut down
    3161                 : 
    3162               0 :  if (!mRoleMapEntry || mRoleMapEntry->valueRule == eNoValue)
    3163               0 :     return NS_OK_NO_ARIA_VALUE;
    3164                 : 
    3165               0 :   nsAutoString attrValue;
    3166               0 :   mContent->GetAttr(kNameSpaceID_None, aProperty, attrValue);
    3167                 : 
    3168                 :   // Return zero value if there is no attribute or its value is empty.
    3169               0 :   if (attrValue.IsEmpty())
    3170               0 :     return NS_OK;
    3171                 : 
    3172               0 :   PRInt32 error = NS_OK;
    3173               0 :   double value = attrValue.ToDouble(&error);
    3174               0 :   if (NS_SUCCEEDED(error))
    3175               0 :     *aValue = value;
    3176                 : 
    3177               0 :   return NS_OK;
    3178                 : }
    3179                 : 
    3180                 : PRUint32
    3181               0 : nsAccessible::GetActionRule(PRUint64 aStates)
    3182                 : {
    3183               0 :   if (aStates & states::UNAVAILABLE)
    3184               0 :     return eNoAction;
    3185                 :   
    3186                 :   // Check if it's simple xlink.
    3187               0 :   if (nsCoreUtils::IsXLink(mContent))
    3188               0 :     return eJumpAction;
    3189                 : 
    3190                 :   // Return "click" action on elements that have an attached popup menu.
    3191               0 :   if (mContent->IsXUL())
    3192               0 :     if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::popup))
    3193               0 :       return eClickAction;
    3194                 : 
    3195                 :   // Has registered 'click' event handler.
    3196               0 :   bool isOnclick = nsCoreUtils::HasClickListener(mContent);
    3197                 : 
    3198               0 :   if (isOnclick)
    3199               0 :     return eClickAction;
    3200                 :   
    3201                 :   // Get an action based on ARIA role.
    3202               0 :   if (mRoleMapEntry &&
    3203                 :       mRoleMapEntry->actionRule != eNoAction)
    3204               0 :     return mRoleMapEntry->actionRule;
    3205                 : 
    3206                 :   // Get an action based on ARIA attribute.
    3207               0 :   if (nsAccUtils::HasDefinedARIAToken(mContent,
    3208               0 :                                       nsGkAtoms::aria_expanded))
    3209               0 :     return eExpandAction;
    3210                 : 
    3211               0 :   return eNoAction;
    3212                 : }
    3213                 : 
    3214                 : AccGroupInfo*
    3215               0 : nsAccessible::GetGroupInfo()
    3216                 : {
    3217               0 :   if (mGroupInfo)
    3218               0 :     return mGroupInfo;
    3219                 : 
    3220               0 :   mGroupInfo = AccGroupInfo::CreateGroupInfo(this);
    3221               0 :   return mGroupInfo;
    3222                 : }
    3223                 : 
    3224                 : void
    3225               0 : nsAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet, PRInt32 *aSetSize)
    3226                 : {
    3227               0 :   AccGroupInfo* groupInfo = GetGroupInfo();
    3228               0 :   if (groupInfo) {
    3229               0 :     *aPosInSet = groupInfo->PosInSet();
    3230               0 :     *aSetSize = groupInfo->SetSize();
    3231                 :   }
    3232               0 : }
    3233                 : 
    3234                 : PRInt32
    3235               0 : nsAccessible::GetLevelInternal()
    3236                 : {
    3237               0 :   PRInt32 level = nsAccUtils::GetDefaultLevel(this);
    3238                 : 
    3239               0 :   if (!IsBoundToParent())
    3240               0 :     return level;
    3241                 : 
    3242               0 :   roles::Role role = Role();
    3243               0 :   if (role == roles::OUTLINEITEM) {
    3244                 :     // Always expose 'level' attribute for 'outlineitem' accessible. The number
    3245                 :     // of nested 'grouping' accessibles containing 'outlineitem' accessible is
    3246                 :     // its level.
    3247               0 :     level = 1;
    3248                 : 
    3249               0 :     nsAccessible* parent = this;
    3250               0 :     while ((parent = parent->Parent())) {
    3251               0 :       roles::Role parentRole = parent->Role();
    3252                 : 
    3253               0 :       if (parentRole == roles::OUTLINE)
    3254               0 :         break;
    3255               0 :       if (parentRole == roles::GROUPING)
    3256               0 :         ++ level;
    3257                 : 
    3258                 :     }
    3259                 : 
    3260               0 :   } else if (role == roles::LISTITEM) {
    3261                 :     // Expose 'level' attribute on nested lists. We assume nested list is a last
    3262                 :     // child of listitem of parent list. We don't handle the case when nested
    3263                 :     // lists have more complex structure, for example when there are accessibles
    3264                 :     // between parent listitem and nested list.
    3265                 : 
    3266                 :     // Calculate 'level' attribute based on number of parent listitems.
    3267               0 :     level = 0;
    3268               0 :     nsAccessible* parent = this;
    3269               0 :     while ((parent = parent->Parent())) {
    3270               0 :       roles::Role parentRole = parent->Role();
    3271                 : 
    3272               0 :       if (parentRole == roles::LISTITEM)
    3273               0 :         ++ level;
    3274               0 :       else if (parentRole != roles::LIST)
    3275               0 :         break;
    3276                 : 
    3277                 :     }
    3278                 : 
    3279               0 :     if (level == 0) {
    3280                 :       // If this listitem is on top of nested lists then expose 'level'
    3281                 :       // attribute.
    3282               0 :       parent = Parent();
    3283               0 :       PRInt32 siblingCount = parent->GetChildCount();
    3284               0 :       for (PRInt32 siblingIdx = 0; siblingIdx < siblingCount; siblingIdx++) {
    3285               0 :         nsAccessible* sibling = parent->GetChildAt(siblingIdx);
    3286                 : 
    3287               0 :         nsAccessible* siblingChild = sibling->LastChild();
    3288               0 :         if (siblingChild && siblingChild->Role() == roles::LIST)
    3289               0 :           return 1;
    3290                 :       }
    3291                 :     } else {
    3292               0 :       ++ level; // level is 1-index based
    3293                 :     }
    3294                 :   }
    3295                 : 
    3296               0 :   return level;
    3297                 : }
    3298                 : 
    3299                 : 
    3300                 : ////////////////////////////////////////////////////////////////////////////////
    3301                 : // KeyBinding class
    3302                 : 
    3303                 : void
    3304               0 : KeyBinding::ToPlatformFormat(nsAString& aValue) const
    3305                 : {
    3306               0 :   nsCOMPtr<nsIStringBundle> keyStringBundle;
    3307                 :   nsCOMPtr<nsIStringBundleService> stringBundleService =
    3308               0 :       mozilla::services::GetStringBundleService();
    3309               0 :   if (stringBundleService)
    3310               0 :     stringBundleService->CreateBundle(PLATFORM_KEYS_BUNDLE_URL,
    3311               0 :                                       getter_AddRefs(keyStringBundle));
    3312                 : 
    3313               0 :   if (!keyStringBundle)
    3314                 :     return;
    3315                 : 
    3316               0 :   nsAutoString separator;
    3317               0 :   keyStringBundle->GetStringFromName(NS_LITERAL_STRING("MODIFIER_SEPARATOR").get(),
    3318               0 :                                      getter_Copies(separator));
    3319                 : 
    3320               0 :   nsAutoString modifierName;
    3321               0 :   if (mModifierMask & kControl) {
    3322               0 :     keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_CONTROL").get(),
    3323               0 :                                        getter_Copies(modifierName));
    3324                 : 
    3325               0 :     aValue.Append(modifierName);
    3326               0 :     aValue.Append(separator);
    3327                 :   }
    3328                 : 
    3329               0 :   if (mModifierMask & kAlt) {
    3330               0 :     keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_ALT").get(),
    3331               0 :                                        getter_Copies(modifierName));
    3332                 : 
    3333               0 :     aValue.Append(modifierName);
    3334               0 :     aValue.Append(separator);
    3335                 :   }
    3336                 : 
    3337               0 :   if (mModifierMask & kShift) {
    3338               0 :     keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_SHIFT").get(),
    3339               0 :                                        getter_Copies(modifierName));
    3340                 : 
    3341               0 :     aValue.Append(modifierName);
    3342               0 :     aValue.Append(separator);
    3343                 :   }
    3344                 : 
    3345               0 :   if (mModifierMask & kMeta) {
    3346               0 :     keyStringBundle->GetStringFromName(NS_LITERAL_STRING("VK_META").get(),
    3347               0 :                                        getter_Copies(modifierName));
    3348                 : 
    3349               0 :     aValue.Append(modifierName);
    3350               0 :     aValue.Append(separator);
    3351                 :   }
    3352                 : 
    3353               0 :   aValue.Append(mKey);
    3354                 : }
    3355                 : 
    3356                 : void
    3357               0 : KeyBinding::ToAtkFormat(nsAString& aValue) const
    3358                 : {
    3359               0 :   nsAutoString modifierName;
    3360               0 :   if (mModifierMask & kControl)
    3361               0 :     aValue.Append(NS_LITERAL_STRING("<Control>"));
    3362                 : 
    3363               0 :   if (mModifierMask & kAlt)
    3364               0 :     aValue.Append(NS_LITERAL_STRING("<Alt>"));
    3365                 : 
    3366               0 :   if (mModifierMask & kShift)
    3367               0 :     aValue.Append(NS_LITERAL_STRING("<Shift>"));
    3368                 : 
    3369               0 :   if (mModifierMask & kMeta)
    3370               0 :       aValue.Append(NS_LITERAL_STRING("<Meta>"));
    3371                 : 
    3372               0 :   aValue.Append(mKey);
    3373            4392 : }

Generated by: LCOV version 1.7