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
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/
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
15 * The Original Code is mozilla.org code.
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.
23 * Author: Eric Vaughan (evaughan@netscape.com)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 // NOTE: alphabetically ordered
40 #include "nsAccessibleTreeWalker.h"
41 #include "nsAccessibilityAtoms.h"
42 #include "nsHTMLFormControlAccessible.h"
43 #include "nsIDOMDocument.h"
44 #include "nsIDOMHTMLInputElement.h"
45 #include "nsIDOMNSHTMLElement.h"
46 #include "nsIDOMNSEditableElement.h"
47 #include "nsIDOMNSHTMLButtonElement.h"
48 #include "nsIDOMHTMLFormElement.h"
49 #include "nsIDOMHTMLLegendElement.h"
50 #include "nsIDOMHTMLTextAreaElement.h"
51 #include "nsIEditor.h"
53 #include "nsINameSpaceManager.h"
54 #include "nsISelectionController.h"
56 #include "nsIJSContextStack.h"
57 #include "nsIServiceManager.h"
58 #include "nsITextControlFrame.h"
62 nsHTMLCheckboxAccessible::nsHTMLCheckboxAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
63 nsFormControlAccessible(aNode
, aShell
)
67 NS_IMETHODIMP
nsHTMLCheckboxAccessible::GetRole(PRUint32
*_retval
)
69 *_retval
= nsIAccessibleRole::ROLE_CHECKBUTTON
;
73 NS_IMETHODIMP
nsHTMLCheckboxAccessible::GetNumActions(PRUint8
*_retval
)
79 NS_IMETHODIMP
nsHTMLCheckboxAccessible::GetActionName(PRUint8 aIndex
, nsAString
& aName
)
81 if (aIndex
== eAction_Click
) { // 0 is the magic value for default action
84 nsresult rv
= GetStateInternal(&state
, nsnull
);
85 NS_ENSURE_SUCCESS(rv
, rv
);
87 if (state
& nsIAccessibleStates::STATE_CHECKED
)
88 aName
.AssignLiteral("uncheck");
90 aName
.AssignLiteral("check");
94 return NS_ERROR_INVALID_ARG
;
97 NS_IMETHODIMP
nsHTMLCheckboxAccessible::DoAction(PRUint8 index
)
99 if (index
== 0) { // 0 is the magic value for default action
102 return NS_ERROR_INVALID_ARG
;
106 nsHTMLCheckboxAccessible::GetStateInternal(PRUint32
*aState
,
107 PRUint32
*aExtraState
)
109 nsresult rv
= nsFormControlAccessible::GetStateInternal(aState
, aExtraState
);
110 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
112 *aState
|= nsIAccessibleStates::STATE_CHECKABLE
;
114 PRBool checked
= PR_FALSE
; // Radio buttons and check boxes can be checked
116 nsCOMPtr
<nsIDOMHTMLInputElement
> htmlCheckboxElement(do_QueryInterface(mDOMNode
));
117 if (htmlCheckboxElement
)
118 htmlCheckboxElement
->GetChecked(&checked
);
121 *aState
|= nsIAccessibleStates::STATE_CHECKED
;
126 //------ Radio button -------
128 nsHTMLRadioButtonAccessible::nsHTMLRadioButtonAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
129 nsRadioButtonAccessible(aNode
, aShell
)
134 nsHTMLRadioButtonAccessible::GetStateInternal(PRUint32
*aState
,
135 PRUint32
*aExtraState
)
137 nsresult rv
= nsAccessibleWrap::GetStateInternal(aState
, aExtraState
);
138 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
140 *aState
|= nsIAccessibleStates::STATE_CHECKABLE
;
142 PRBool checked
= PR_FALSE
; // Radio buttons and check boxes can be checked
144 nsCOMPtr
<nsIDOMHTMLInputElement
> htmlRadioElement(do_QueryInterface(mDOMNode
));
145 if (htmlRadioElement
)
146 htmlRadioElement
->GetChecked(&checked
);
149 *aState
|= nsIAccessibleStates::STATE_CHECKED
;
155 nsHTMLRadioButtonAccessible::GetAttributesInternal(nsIPersistentProperties
*aAttributes
)
157 NS_ENSURE_ARG_POINTER(aAttributes
);
158 NS_ENSURE_TRUE(mDOMNode
, NS_ERROR_FAILURE
);
160 nsresult rv
= nsRadioButtonAccessible::GetAttributesInternal(aAttributes
);
161 NS_ENSURE_SUCCESS(rv
, rv
);
164 mDOMNode
->GetNamespaceURI(nsURI
);
165 nsAutoString tagName
;
166 mDOMNode
->GetLocalName(tagName
);
168 nsCOMPtr
<nsIContent
> content(do_QueryInterface(mDOMNode
));
169 NS_ENSURE_STATE(content
);
172 content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::type
, type
);
174 content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::name
, name
);
176 nsCOMPtr
<nsIDOMNodeList
> inputs
;
178 nsCOMPtr
<nsIDOMHTMLInputElement
> radio(do_QueryInterface(mDOMNode
));
179 nsCOMPtr
<nsIDOMHTMLFormElement
> form
;
180 radio
->GetForm(getter_AddRefs(form
));
182 form
->GetElementsByTagNameNS(nsURI
, tagName
, getter_AddRefs(inputs
));
184 nsCOMPtr
<nsIDOMDocument
> document
;
185 mDOMNode
->GetOwnerDocument(getter_AddRefs(document
));
187 document
->GetElementsByTagNameNS(nsURI
, tagName
, getter_AddRefs(inputs
));
190 NS_ENSURE_TRUE(inputs
, NS_OK
);
192 PRUint32 inputsCount
= 0;
193 inputs
->GetLength(&inputsCount
);
195 // Get posinset and setsize.
199 for (PRUint32 index
= 0; index
< inputsCount
; index
++) {
200 nsCOMPtr
<nsIDOMNode
> itemNode
;
201 inputs
->Item(index
, getter_AddRefs(itemNode
));
203 nsCOMPtr
<nsIContent
> item(do_QueryInterface(itemNode
));
205 item
->AttrValueIs(kNameSpaceID_None
, nsAccessibilityAtoms::type
,
206 type
, eCaseMatters
) &&
207 item
->AttrValueIs(kNameSpaceID_None
, nsAccessibilityAtoms::name
,
208 name
, eCaseMatters
)) {
212 if (itemNode
== mDOMNode
)
217 nsAccUtils::SetAccGroupAttrs(aAttributes
, 0, indexOf
, count
);
222 // ----- Button -----
224 nsHTMLButtonAccessible::nsHTMLButtonAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
225 nsHyperTextAccessibleWrap(aNode
, aShell
)
229 NS_IMETHODIMP
nsHTMLButtonAccessible::GetNumActions(PRUint8
*_retval
)
235 NS_IMETHODIMP
nsHTMLButtonAccessible::GetActionName(PRUint8 aIndex
, nsAString
& aName
)
237 if (aIndex
== eAction_Click
) {
238 aName
.AssignLiteral("press");
241 return NS_ERROR_INVALID_ARG
;
244 NS_IMETHODIMP
nsHTMLButtonAccessible::DoAction(PRUint8 index
)
246 if (index
== eAction_Click
) {
249 return NS_ERROR_INVALID_ARG
;
253 nsHTMLButtonAccessible::GetStateInternal(PRUint32
*aState
,
254 PRUint32
*aExtraState
)
256 nsresult rv
= nsHyperTextAccessibleWrap::GetStateInternal(aState
,
258 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
260 nsCOMPtr
<nsIDOMElement
> element(do_QueryInterface(mDOMNode
));
261 NS_ENSURE_TRUE(element
, NS_ERROR_FAILURE
);
263 nsAutoString buttonType
;
264 element
->GetAttribute(NS_LITERAL_STRING("type"), buttonType
);
265 if (buttonType
.LowerCaseEqualsLiteral("submit"))
266 *aState
|= nsIAccessibleStates::STATE_DEFAULT
;
271 NS_IMETHODIMP
nsHTMLButtonAccessible::GetRole(PRUint32
*_retval
)
273 *_retval
= nsIAccessibleRole::ROLE_PUSHBUTTON
;
278 nsHTMLButtonAccessible::GetNameInternal(nsAString
& aName
)
280 nsresult rv
= nsAccessible::GetNameInternal(aName
);
281 if (!aName
.IsEmpty())
284 nsCOMPtr
<nsIContent
> content(do_QueryInterface(mDOMNode
));
286 // No name from HTML or ARIA
288 if (!content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::value
,
290 !content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::alt
,
292 // Use the button's (default) label if nothing else works
293 nsIFrame
* frame
= GetFrame();
295 nsIFormControlFrame
* fcFrame
= nsnull
;
296 CallQueryInterface(frame
, &fcFrame
);
298 fcFrame
->GetFormProperty(nsAccessibilityAtoms::defaultLabel
, name
);
302 if (name
.IsEmpty() &&
303 !content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::src
,
305 content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::data
, name
);
308 name
.CompressWhitespace();
315 // ----- HTML 4 Button: can contain arbitrary HTML content -----
317 nsHTML4ButtonAccessible::nsHTML4ButtonAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
318 nsHyperTextAccessibleWrap(aNode
, aShell
)
322 NS_IMETHODIMP
nsHTML4ButtonAccessible::GetNumActions(PRUint8
*_retval
)
328 NS_IMETHODIMP
nsHTML4ButtonAccessible::GetActionName(PRUint8 aIndex
, nsAString
& aName
)
330 if (aIndex
== eAction_Click
) {
331 aName
.AssignLiteral("press");
334 return NS_ERROR_INVALID_ARG
;
337 NS_IMETHODIMP
nsHTML4ButtonAccessible::DoAction(PRUint8 index
)
342 return NS_ERROR_INVALID_ARG
;
345 NS_IMETHODIMP
nsHTML4ButtonAccessible::GetRole(PRUint32
*_retval
)
347 *_retval
= nsIAccessibleRole::ROLE_PUSHBUTTON
;
352 nsHTML4ButtonAccessible::GetStateInternal(PRUint32
*aState
,
353 PRUint32
*aExtraState
)
355 nsresult rv
= nsHyperTextAccessibleWrap::GetStateInternal(aState
,
357 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
359 nsCOMPtr
<nsIDOMElement
> element(do_QueryInterface(mDOMNode
));
360 NS_ASSERTION(element
, "No element for button's dom node!");
362 *aState
|= nsIAccessibleStates::STATE_FOCUSABLE
;
364 nsAutoString buttonType
;
365 element
->GetAttribute(NS_LITERAL_STRING("type"), buttonType
);
366 if (buttonType
.LowerCaseEqualsLiteral("submit"))
367 *aState
|= nsIAccessibleStates::STATE_DEFAULT
;
372 // --- textfield -----
374 nsHTMLTextFieldAccessible::nsHTMLTextFieldAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
375 nsHyperTextAccessibleWrap(aNode
, aShell
)
379 NS_IMPL_ISUPPORTS_INHERITED3(nsHTMLTextFieldAccessible
, nsAccessible
, nsHyperTextAccessible
, nsIAccessibleText
, nsIAccessibleEditableText
)
381 NS_IMETHODIMP
nsHTMLTextFieldAccessible::GetRole(PRUint32
*aRole
)
383 *aRole
= nsIAccessibleRole::ROLE_ENTRY
;
384 nsCOMPtr
<nsIContent
> content(do_QueryInterface(mDOMNode
));
386 content
->AttrValueIs(kNameSpaceID_None
, nsAccessibilityAtoms::type
,
387 nsAccessibilityAtoms::password
, eIgnoreCase
)) {
388 *aRole
= nsIAccessibleRole::ROLE_PASSWORD_TEXT
;
394 nsHTMLTextFieldAccessible::GetNameInternal(nsAString
& aName
)
396 nsresult rv
= nsAccessible::GetNameInternal(aName
);
397 NS_ENSURE_SUCCESS(rv
, rv
);
399 if (!aName
.IsEmpty())
402 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(mDOMNode
);
403 if (!content
->GetBindingParent())
407 // There's a binding parent.
408 // This means we're part of another control, so use parent accessible for name.
409 // This ensures that a textbox inside of a XUL widget gets
410 // an accessible name.
411 nsCOMPtr
<nsIAccessible
> parent
;
412 rv
= GetParent(getter_AddRefs(parent
));
413 return parent
? parent
->GetName(aName
) : rv
;
416 NS_IMETHODIMP
nsHTMLTextFieldAccessible::GetValue(nsAString
& _retval
)
419 nsresult rv
= GetStateInternal(&state
, nsnull
);
420 NS_ENSURE_SUCCESS(rv
, rv
);
422 if (state
& nsIAccessibleStates::STATE_PROTECTED
) // Don't return password text!
423 return NS_ERROR_FAILURE
;
425 nsCOMPtr
<nsIDOMHTMLTextAreaElement
> textArea(do_QueryInterface(mDOMNode
));
427 return textArea
->GetValue(_retval
);
430 nsCOMPtr
<nsIDOMHTMLInputElement
> inputElement(do_QueryInterface(mDOMNode
));
432 return inputElement
->GetValue(_retval
);
435 return NS_ERROR_FAILURE
;
439 nsHTMLTextFieldAccessible::GetStateInternal(PRUint32
*aState
,
440 PRUint32
*aExtraState
)
442 nsresult rv
= nsHyperTextAccessibleWrap::GetStateInternal(aState
,
444 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
446 // can be focusable, focused, protected. readonly, unavailable, selected
447 nsCOMPtr
<nsIContent
> content(do_QueryInterface(mDOMNode
));
448 NS_ASSERTION(content
, "Should not have gotten here if upcalled GetExtState() succeeded");
450 if (content
->AttrValueIs(kNameSpaceID_None
, nsAccessibilityAtoms::type
,
451 nsAccessibilityAtoms::password
, eIgnoreCase
)) {
452 *aState
|= nsIAccessibleStates::STATE_PROTECTED
;
455 nsCOMPtr
<nsIAccessible
> parent
;
456 GetParent(getter_AddRefs(parent
));
457 if (nsAccUtils::Role(parent
) == nsIAccessibleRole::ROLE_AUTOCOMPLETE
)
458 *aState
|= nsIAccessibleStates::STATE_HASPOPUP
;
461 if (content
->HasAttr(kNameSpaceID_None
, nsAccessibilityAtoms::readonly
)) {
462 *aState
|= nsIAccessibleStates::STATE_READONLY
;
468 nsCOMPtr
<nsIDOMHTMLInputElement
> htmlInput(do_QueryInterface(mDOMNode
));
469 // Is it an <input> or a <textarea> ?
471 *aExtraState
|= nsIAccessibleStates::EXT_STATE_SINGLE_LINE
;
474 *aExtraState
|= nsIAccessibleStates::EXT_STATE_MULTI_LINE
;
477 if (!(*aExtraState
& nsIAccessibleStates::EXT_STATE_EDITABLE
))
480 nsCOMPtr
<nsIContent
> bindingContent
= content
->GetBindingParent();
481 if (bindingContent
&&
482 bindingContent
->NodeInfo()->Equals(nsAccessibilityAtoms::textbox
,
484 bindingContent
->AttrValueIs(kNameSpaceID_None
, nsAccessibilityAtoms::type
,
485 nsAccessibilityAtoms::autocomplete
,
487 // If parent is XUL textbox and value of @type attribute is "autocomplete",
488 // then this accessible supports autocompletion.
489 *aExtraState
|= nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION
;
490 } else if (gIsFormFillEnabled
&& htmlInput
&&
491 !(*aState
& nsIAccessibleStates::STATE_PROTECTED
)) {
492 // Check to see if autocompletion is allowed on this input. We don't expose
493 // it for password fields even though the entire password can be remembered
494 // for a page if the user asks it to be. However, the kind of autocomplete
495 // we're talking here is based on what the user types, where a popup of
496 // possible choices comes up.
497 nsAutoString autocomplete
;
498 content
->GetAttr(kNameSpaceID_None
, nsAccessibilityAtoms::autocomplete
,
501 if (!autocomplete
.LowerCaseEqualsLiteral("off")) {
502 nsCOMPtr
<nsIDOMHTMLFormElement
> form
;
503 htmlInput
->GetForm(getter_AddRefs(form
));
504 nsCOMPtr
<nsIContent
> formContent(do_QueryInterface(form
));
506 formContent
->GetAttr(kNameSpaceID_None
,
507 nsAccessibilityAtoms::autocomplete
, autocomplete
);
510 if (!formContent
|| !autocomplete
.LowerCaseEqualsLiteral("off"))
511 *aExtraState
|= nsIAccessibleStates::EXT_STATE_SUPPORTS_AUTOCOMPLETION
;
518 NS_IMETHODIMP
nsHTMLTextFieldAccessible::GetNumActions(PRUint8
*_retval
)
524 NS_IMETHODIMP
nsHTMLTextFieldAccessible::GetActionName(PRUint8 aIndex
, nsAString
& aName
)
526 if (aIndex
== eAction_Click
) {
527 aName
.AssignLiteral("activate");
530 return NS_ERROR_INVALID_ARG
;
533 NS_IMETHODIMP
nsHTMLTextFieldAccessible::DoAction(PRUint8 index
)
536 nsCOMPtr
<nsIDOMNSHTMLElement
> element(do_QueryInterface(mDOMNode
));
538 return element
->Focus();
540 return NS_ERROR_FAILURE
;
542 return NS_ERROR_INVALID_ARG
;
545 NS_IMETHODIMP
nsHTMLTextFieldAccessible::GetAssociatedEditor(nsIEditor
**aEditor
)
548 nsCOMPtr
<nsIDOMNSEditableElement
> editableElt(do_QueryInterface(mDOMNode
));
549 NS_ENSURE_TRUE(editableElt
, NS_ERROR_FAILURE
);
551 // nsGenericHTMLElement::GetEditor has a security check.
552 // Make sure we're not restricted by the permissions of
553 // whatever script is currently running.
554 nsCOMPtr
<nsIJSContextStack
> stack
=
555 do_GetService("@mozilla.org/js/xpc/ContextStack;1");
556 PRBool pushed
= stack
&& NS_SUCCEEDED(stack
->Push(nsnull
));
558 nsCOMPtr
<nsIEditor
> editor
;
559 nsresult rv
= editableElt
->GetEditor(aEditor
);
564 NS_ASSERTION(!cx
, "context should be null");
570 // --- groupbox -----
573 * The HTML for this is <fieldset> <legend>box-title</legend> form elements </fieldset>
576 nsHTMLGroupboxAccessible::nsHTMLGroupboxAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
577 nsHyperTextAccessibleWrap(aNode
, aShell
)
581 NS_IMETHODIMP
nsHTMLGroupboxAccessible::GetRole(PRUint32
*_retval
)
583 *_retval
= nsIAccessibleRole::ROLE_GROUPING
;
587 nsIContent
* nsHTMLGroupboxAccessible::GetLegend()
589 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(mDOMNode
);
590 NS_ENSURE_TRUE(content
, nsnull
);
593 nsIContent
*testLegendContent
;
594 while ((testLegendContent
= content
->GetChildAt(count
++ )) != nsnull
) {
595 if (testLegendContent
->NodeInfo()->Equals(nsAccessibilityAtoms::legend
,
596 content
->GetNameSpaceID())) {
597 // Either XHTML namespace or no namespace
598 return testLegendContent
;
606 nsHTMLGroupboxAccessible::GetNameInternal(nsAString
& aName
)
608 nsresult rv
= nsAccessible::GetNameInternal(aName
);
609 NS_ENSURE_SUCCESS(rv
, rv
);
611 if (!aName
.IsEmpty())
614 nsIContent
*legendContent
= GetLegend();
616 return AppendFlatStringFromSubtree(legendContent
, &aName
);
623 nsHTMLGroupboxAccessible::GetAccessibleRelated(PRUint32 aRelationType
,
624 nsIAccessible
**aRelated
)
627 return NS_ERROR_FAILURE
;
629 NS_ENSURE_ARG_POINTER(aRelated
);
633 nsresult rv
= nsHyperTextAccessibleWrap::GetAccessibleRelated(aRelationType
, aRelated
);
634 if (NS_FAILED(rv
) || *aRelated
) {
635 // Either the node is shut down, or another relation mechanism has been used
639 if (aRelationType
== nsIAccessibleRelation::RELATION_LABELLED_BY
) {
640 // No override for label, so use <legend> for this <fieldset>
641 nsCOMPtr
<nsIDOMNode
> legendNode
= do_QueryInterface(GetLegend());
643 GetAccService()->GetAccessibleInWeakShell(legendNode
, mWeakShell
, aRelated
);
650 nsHTMLLegendAccessible::nsHTMLLegendAccessible(nsIDOMNode
* aNode
, nsIWeakReference
* aShell
):
651 nsHyperTextAccessibleWrap(aNode
, aShell
)
656 nsHTMLLegendAccessible::GetAccessibleRelated(PRUint32 aRelationType
,
657 nsIAccessible
**aRelated
)
661 nsresult rv
= nsHyperTextAccessibleWrap::GetAccessibleRelated(aRelationType
, aRelated
);
662 if (NS_FAILED(rv
) || *aRelated
) {
663 // Either the node is shut down, or another relation mechanism has been used
667 if (aRelationType
== nsIAccessibleRelation::RELATION_LABEL_FOR
) {
668 // Look for groupbox parent
669 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(mDOMNode
);
671 return NS_ERROR_FAILURE
; // Node already shut down
673 nsCOMPtr
<nsIAccessible
> groupboxAccessible
= GetParent();
674 if (nsAccUtils::Role(groupboxAccessible
) == nsIAccessibleRole::ROLE_GROUPING
) {
675 nsCOMPtr
<nsIAccessible
> testLabelAccessible
;
676 groupboxAccessible
->GetAccessibleRelated(nsIAccessibleRelation::RELATION_LABELLED_BY
,
677 getter_AddRefs(testLabelAccessible
));
678 if (testLabelAccessible
== this) {
679 // We're the first child of the parent groupbox
680 NS_ADDREF(*aRelated
= groupboxAccessible
);