123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "HTMLFormControlAccessible.h"
- #include "Accessible-inl.h"
- #include "nsAccUtils.h"
- #include "nsEventShell.h"
- #include "nsTextEquivUtils.h"
- #include "Relation.h"
- #include "Role.h"
- #include "States.h"
- #include "nsContentList.h"
- #include "mozilla/dom/HTMLInputElement.h"
- #include "nsIDOMNSEditableElement.h"
- #include "nsIDOMHTMLTextAreaElement.h"
- #include "nsIEditor.h"
- #include "nsIFormControl.h"
- #include "nsIPersistentProperties2.h"
- #include "nsISelectionController.h"
- #include "nsIServiceManager.h"
- #include "nsITextControlFrame.h"
- #include "nsNameSpaceManager.h"
- #include "mozilla/dom/ScriptSettings.h"
- #include "mozilla/EventStates.h"
- #include "mozilla/FloatingPoint.h"
- #include "mozilla/Preferences.h"
- using namespace mozilla;
- using namespace mozilla::dom;
- using namespace mozilla::a11y;
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLCheckboxAccessible
- ////////////////////////////////////////////////////////////////////////////////
- role
- HTMLCheckboxAccessible::NativeRole()
- {
- return roles::CHECKBUTTON;
- }
- uint8_t
- HTMLCheckboxAccessible::ActionCount()
- {
- return 1;
- }
- void
- HTMLCheckboxAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
- {
- if (aIndex == eAction_Click) { // 0 is the magic value for default action
- uint64_t state = NativeState();
- if (state & states::CHECKED)
- aName.AssignLiteral("uncheck");
- else if (state & states::MIXED)
- aName.AssignLiteral("cycle");
- else
- aName.AssignLiteral("check");
- }
- }
- bool
- HTMLCheckboxAccessible::DoAction(uint8_t aIndex)
- {
- if (aIndex != 0)
- return false;
- DoCommand();
- return true;
- }
- uint64_t
- HTMLCheckboxAccessible::NativeState()
- {
- uint64_t state = LeafAccessible::NativeState();
- state |= states::CHECKABLE;
- HTMLInputElement* input = HTMLInputElement::FromContent(mContent);
- if (!input)
- return state;
- if (input->Indeterminate())
- return state | states::MIXED;
- if (input->Checked())
- return state | states::CHECKED;
-
- return state;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLCheckboxAccessible: Widgets
- bool
- HTMLCheckboxAccessible::IsWidget() const
- {
- return true;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLRadioButtonAccessible
- ////////////////////////////////////////////////////////////////////////////////
- uint64_t
- HTMLRadioButtonAccessible::NativeState()
- {
- uint64_t state = AccessibleWrap::NativeState();
- state |= states::CHECKABLE;
- HTMLInputElement* input = HTMLInputElement::FromContent(mContent);
- if (input && input->Checked())
- state |= states::CHECKED;
- return state;
- }
- void
- HTMLRadioButtonAccessible::GetPositionAndSizeInternal(int32_t* aPosInSet,
- int32_t* aSetSize)
- {
- int32_t namespaceId = mContent->NodeInfo()->NamespaceID();
- nsAutoString tagName;
- mContent->NodeInfo()->GetName(tagName);
- nsAutoString type;
- mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type);
- nsAutoString name;
- mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name);
- RefPtr<nsContentList> inputElms;
- nsCOMPtr<nsIFormControl> formControlNode(do_QueryInterface(mContent));
- dom::Element* formElm = formControlNode->GetFormElement();
- if (formElm)
- inputElms = NS_GetContentList(formElm, namespaceId, tagName);
- else
- inputElms = NS_GetContentList(mContent->OwnerDoc(), namespaceId, tagName);
- NS_ENSURE_TRUE_VOID(inputElms);
- uint32_t inputCount = inputElms->Length(false);
- // Compute posinset and setsize.
- int32_t indexOf = 0;
- int32_t count = 0;
- for (uint32_t index = 0; index < inputCount; index++) {
- nsIContent* inputElm = inputElms->Item(index, false);
- if (inputElm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- type, eCaseMatters) &&
- inputElm->AttrValueIs(kNameSpaceID_None, nsGkAtoms::name,
- name, eCaseMatters) && mDoc->HasAccessible(inputElm)) {
- count++;
- if (inputElm == mContent)
- indexOf = count;
- }
- }
- *aPosInSet = indexOf;
- *aSetSize = count;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLButtonAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLButtonAccessible::
- HTMLButtonAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- mGenericTypes |= eButton;
- }
- uint8_t
- HTMLButtonAccessible::ActionCount()
- {
- return 1;
- }
- void
- HTMLButtonAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
- {
- if (aIndex == eAction_Click)
- aName.AssignLiteral("press");
- }
- bool
- HTMLButtonAccessible::DoAction(uint8_t aIndex)
- {
- if (aIndex != eAction_Click)
- return false;
- DoCommand();
- return true;
- }
- uint64_t
- HTMLButtonAccessible::State()
- {
- uint64_t state = HyperTextAccessibleWrap::State();
- if (state == states::DEFUNCT)
- return state;
- // Inherit states from input@type="file" suitable for the button. Note,
- // no special processing for unavailable state since inheritance is supplied
- // other code paths.
- if (mParent && mParent->IsHTMLFileInput()) {
- uint64_t parentState = mParent->State();
- state |= parentState & (states::BUSY | states::REQUIRED |
- states::HASPOPUP | states::INVALID);
- }
- return state;
- }
- uint64_t
- HTMLButtonAccessible::NativeState()
- {
- uint64_t state = HyperTextAccessibleWrap::NativeState();
- EventStates elmState = mContent->AsElement()->State();
- if (elmState.HasState(NS_EVENT_STATE_DEFAULT))
- state |= states::DEFAULT;
- return state;
- }
- role
- HTMLButtonAccessible::NativeRole()
- {
- return roles::PUSHBUTTON;
- }
- ENameValueFlag
- HTMLButtonAccessible::NativeName(nsString& aName)
- {
- // No need to check @value attribute for buttons since this attribute results
- // in native anonymous text node and the name is calculated from subtree.
- // The same magic works for @alt and @value attributes in case of type="image"
- // element that has no valid @src (note if input@type="image" has an image
- // then neither @alt nor @value attributes are used to generate a visual label
- // and thus we need to obtain the accessible name directly from attribute
- // value). Also the same algorithm works in case of default labels for
- // type="submit"/"reset"/"image" elements.
- ENameValueFlag nameFlag = Accessible::NativeName(aName);
- if (!aName.IsEmpty() || !mContent->IsHTMLElement(nsGkAtoms::input) ||
- !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- nsGkAtoms::image, eCaseMatters))
- return nameFlag;
- if (!mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::alt, aName))
- mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::value, aName);
- aName.CompressWhitespace();
- return eNameOK;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLButtonAccessible: Widgets
- bool
- HTMLButtonAccessible::IsWidget() const
- {
- return true;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLTextFieldAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLTextFieldAccessible::
- HTMLTextFieldAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- mType = eHTMLTextFieldType;
- }
- NS_IMPL_ISUPPORTS_INHERITED0(HTMLTextFieldAccessible,
- HyperTextAccessible)
- role
- HTMLTextFieldAccessible::NativeRole()
- {
- if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- nsGkAtoms::password, eIgnoreCase)) {
- return roles::PASSWORD_TEXT;
- }
- return roles::ENTRY;
- }
- already_AddRefed<nsIPersistentProperties>
- HTMLTextFieldAccessible::NativeAttributes()
- {
- nsCOMPtr<nsIPersistentProperties> attributes =
- HyperTextAccessibleWrap::NativeAttributes();
- // Expose type for text input elements as it gives some useful context,
- // especially for mobile.
- nsAutoString type;
- if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::type, type)) {
- nsAccUtils::SetAccAttr(attributes, nsGkAtoms::textInputType, type);
- if (!ARIARoleMap() && type.EqualsLiteral("search")) {
- nsAccUtils::SetAccAttr(attributes, nsGkAtoms::xmlroles,
- NS_LITERAL_STRING("searchbox"));
- }
- }
- return attributes.forget();
- }
- ENameValueFlag
- HTMLTextFieldAccessible::NativeName(nsString& aName)
- {
- ENameValueFlag nameFlag = Accessible::NativeName(aName);
- if (!aName.IsEmpty())
- return nameFlag;
- // If part of compound of XUL widget then grab a name from XUL widget element.
- nsIContent* widgetElm = XULWidgetElm();
- if (widgetElm)
- XULElmName(mDoc, widgetElm, aName);
- if (!aName.IsEmpty())
- return eNameOK;
- // text inputs and textareas might have useful placeholder text
- mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::placeholder, aName);
- return eNameOK;
- }
- void
- HTMLTextFieldAccessible::Value(nsString& aValue)
- {
- aValue.Truncate();
- if (NativeState() & states::PROTECTED) // Don't return password text!
- return;
- nsCOMPtr<nsIDOMHTMLTextAreaElement> textArea(do_QueryInterface(mContent));
- if (textArea) {
- textArea->GetValue(aValue);
- return;
- }
- HTMLInputElement* input = HTMLInputElement::FromContent(mContent);
- if (input)
- input->GetValue(aValue);
- }
- void
- HTMLTextFieldAccessible::ApplyARIAState(uint64_t* aState) const
- {
- HyperTextAccessibleWrap::ApplyARIAState(aState);
- aria::MapToState(aria::eARIAAutoComplete, mContent->AsElement(), aState);
- // If part of compound of XUL widget then pick up ARIA stuff from XUL widget
- // element.
- nsIContent* widgetElm = XULWidgetElm();
- if (widgetElm)
- aria::MapToState(aria::eARIAAutoComplete, widgetElm->AsElement(), aState);
- }
- uint64_t
- HTMLTextFieldAccessible::NativeState()
- {
- uint64_t state = HyperTextAccessibleWrap::NativeState();
- // Text fields are always editable, even if they are also read only or
- // disabled.
- state |= states::EDITABLE;
- // can be focusable, focused, protected. readonly, unavailable, selected
- if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
- nsGkAtoms::password, eIgnoreCase)) {
- state |= states::PROTECTED;
- }
- if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::readonly)) {
- state |= states::READONLY;
- }
- // Is it an <input> or a <textarea> ?
- HTMLInputElement* input = HTMLInputElement::FromContent(mContent);
- state |= input && input->IsSingleLineTextControl() ?
- states::SINGLE_LINE : states::MULTI_LINE;
- if (state & (states::PROTECTED | states::MULTI_LINE | states::READONLY |
- states::UNAVAILABLE))
- return state;
- // Expose autocomplete states if this input is part of autocomplete widget.
- Accessible* widget = ContainerWidget();
- if (widget && widget-IsAutoComplete()) {
- state |= states::HASPOPUP | states::SUPPORTS_AUTOCOMPLETION;
- return state;
- }
- // Expose autocomplete state if it has associated autocomplete list.
- if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::list))
- return state | states::SUPPORTS_AUTOCOMPLETION | states::HASPOPUP;
- // Ordinal XUL textboxes don't support autocomplete.
- if (!XULWidgetElm() && Preferences::GetBool("browser.formfill.enable")) {
- // Check to see if autocompletion is allowed on this input. We don't expose
- // it for password fields even though the entire password can be remembered
- // for a page if the user asks it to be. However, the kind of autocomplete
- // we're talking here is based on what the user types, where a popup of
- // possible choices comes up.
- nsAutoString autocomplete;
- mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::autocomplete,
- autocomplete);
- if (!autocomplete.LowerCaseEqualsLiteral("off")) {
- nsIContent* formContent = input->GetFormElement();
- if (formContent) {
- formContent->GetAttr(kNameSpaceID_None,
- nsGkAtoms::autocomplete, autocomplete);
- }
- if (!formContent || !autocomplete.LowerCaseEqualsLiteral("off"))
- state |= states::SUPPORTS_AUTOCOMPLETION;
- }
- }
- return state;
- }
- uint8_t
- HTMLTextFieldAccessible::ActionCount()
- {
- return 1;
- }
- void
- HTMLTextFieldAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName)
- {
- if (aIndex == eAction_Click)
- aName.AssignLiteral("activate");
- }
- bool
- HTMLTextFieldAccessible::DoAction(uint8_t aIndex)
- {
- if (aIndex != 0)
- return false;
- TakeFocus();
- return true;
- }
- already_AddRefed<nsIEditor>
- HTMLTextFieldAccessible::GetEditor() const
- {
- nsCOMPtr<nsIDOMNSEditableElement> editableElt(do_QueryInterface(mContent));
- if (!editableElt)
- return nullptr;
- // nsGenericHTMLElement::GetEditor has a security check.
- // Make sure we're not restricted by the permissions of
- // whatever script is currently running.
- mozilla::dom::AutoNoJSAPI nojsapi;
- nsCOMPtr<nsIEditor> editor;
- editableElt->GetEditor(getter_AddRefs(editor));
- return editor.forget();
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLTextFieldAccessible: Widgets
- bool
- HTMLTextFieldAccessible::IsWidget() const
- {
- return true;
- }
- Accessible*
- HTMLTextFieldAccessible::ContainerWidget() const
- {
- if (!mParent || mParent->Role() != roles::AUTOCOMPLETE) {
- return nullptr;
- }
- return mParent;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLFileInputAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLFileInputAccessible::
- HTMLFileInputAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- mType = eHTMLFileInputType;
- }
- role
- HTMLFileInputAccessible::NativeRole()
- {
- // JAWS wants a text container, others don't mind. No specific role in
- // AT APIs.
- return roles::TEXT_CONTAINER;
- }
- nsresult
- HTMLFileInputAccessible::HandleAccEvent(AccEvent* aEvent)
- {
- nsresult rv = HyperTextAccessibleWrap::HandleAccEvent(aEvent);
- NS_ENSURE_SUCCESS(rv, rv);
- // Redirect state change events for inherited states to child controls. Note,
- // unavailable state is not redirected. That's a standard for unavailable
- // state handling.
- AccStateChangeEvent* event = downcast_accEvent(aEvent);
- if (event &&
- (event->GetState() == states::BUSY ||
- event->GetState() == states::REQUIRED ||
- event->GetState() == states::HASPOPUP ||
- event->GetState() == states::INVALID)) {
- Accessible* button = GetChildAt(0);
- if (button && button->Role() == roles::PUSHBUTTON) {
- RefPtr<AccStateChangeEvent> childEvent =
- new AccStateChangeEvent(button, event->GetState(),
- event->IsStateEnabled(), event->FromUserInput());
- nsEventShell::FireEvent(childEvent);
- }
- }
- return NS_OK;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLSpinnerAccessible
- ////////////////////////////////////////////////////////////////////////////////
- role
- HTMLSpinnerAccessible::NativeRole()
- {
- return roles::SPINBUTTON;
- }
- void
- HTMLSpinnerAccessible::Value(nsString& aValue)
- {
- AccessibleWrap::Value(aValue);
- if (!aValue.IsEmpty())
- return;
- HTMLInputElement::FromContent(mContent)->GetValue(aValue);
- }
- double
- HTMLSpinnerAccessible::MaxValue() const
- {
- double value = AccessibleWrap::MaxValue();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetMaximum().toDouble();
- }
- double
- HTMLSpinnerAccessible::MinValue() const
- {
- double value = AccessibleWrap::MinValue();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetMinimum().toDouble();
- }
- double
- HTMLSpinnerAccessible::Step() const
- {
- double value = AccessibleWrap::Step();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetStep().toDouble();
- }
- double
- HTMLSpinnerAccessible::CurValue() const
- {
- double value = AccessibleWrap::CurValue();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetValueAsDecimal().toDouble();
- }
- bool
- HTMLSpinnerAccessible::SetCurValue(double aValue)
- {
- ErrorResult er;
- HTMLInputElement::FromContent(mContent)->SetValueAsNumber(aValue, er);
- return !er.Failed();
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLRangeAccessible
- ////////////////////////////////////////////////////////////////////////////////
- role
- HTMLRangeAccessible::NativeRole()
- {
- return roles::SLIDER;
- }
- bool
- HTMLRangeAccessible::IsWidget() const
- {
- return true;
- }
- void
- HTMLRangeAccessible::Value(nsString& aValue)
- {
- LeafAccessible::Value(aValue);
- if (!aValue.IsEmpty())
- return;
- HTMLInputElement::FromContent(mContent)->GetValue(aValue);
- }
- double
- HTMLRangeAccessible::MaxValue() const
- {
- double value = LeafAccessible::MaxValue();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetMaximum().toDouble();
- }
- double
- HTMLRangeAccessible::MinValue() const
- {
- double value = LeafAccessible::MinValue();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetMinimum().toDouble();
- }
- double
- HTMLRangeAccessible::Step() const
- {
- double value = LeafAccessible::Step();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetStep().toDouble();
- }
- double
- HTMLRangeAccessible::CurValue() const
- {
- double value = LeafAccessible::CurValue();
- if (!IsNaN(value))
- return value;
- return HTMLInputElement::FromContent(mContent)->GetValueAsDecimal().toDouble();
- }
- bool
- HTMLRangeAccessible::SetCurValue(double aValue)
- {
- ErrorResult er;
- HTMLInputElement::FromContent(mContent)->SetValueAsNumber(aValue, er);
- return !er.Failed();
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLGroupboxAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLGroupboxAccessible::
- HTMLGroupboxAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- }
- role
- HTMLGroupboxAccessible::NativeRole()
- {
- return roles::GROUPING;
- }
- nsIContent*
- HTMLGroupboxAccessible::GetLegend() const
- {
- for (nsIContent* legendContent = mContent->GetFirstChild(); legendContent;
- legendContent = legendContent->GetNextSibling()) {
- if (legendContent->NodeInfo()->Equals(nsGkAtoms::legend,
- mContent->GetNameSpaceID())) {
- // Either XHTML namespace or no namespace
- return legendContent;
- }
- }
- return nullptr;
- }
- ENameValueFlag
- HTMLGroupboxAccessible::NativeName(nsString& aName)
- {
- ENameValueFlag nameFlag = Accessible::NativeName(aName);
- if (!aName.IsEmpty())
- return nameFlag;
- nsIContent* legendContent = GetLegend();
- if (legendContent)
- nsTextEquivUtils::AppendTextEquivFromContent(this, legendContent, &aName);
- return eNameOK;
- }
- Relation
- HTMLGroupboxAccessible::RelationByType(RelationType aType)
- {
- Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
- // No override for label, so use <legend> for this <fieldset>
- if (aType == RelationType::LABELLED_BY)
- rel.AppendTarget(mDoc, GetLegend());
- return rel;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLLegendAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLLegendAccessible::
- HTMLLegendAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- }
- Relation
- HTMLLegendAccessible::RelationByType(RelationType aType)
- {
- Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
- if (aType != RelationType::LABEL_FOR)
- return rel;
- Accessible* groupbox = Parent();
- if (groupbox && groupbox->Role() == roles::GROUPING)
- rel.AppendTarget(groupbox);
- return rel;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLFigureAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLFigureAccessible::
- HTMLFigureAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- }
- ENameValueFlag
- HTMLFigureAccessible::NativeName(nsString& aName)
- {
- ENameValueFlag nameFlag = HyperTextAccessibleWrap::NativeName(aName);
- if (!aName.IsEmpty())
- return nameFlag;
- nsIContent* captionContent = Caption();
- if (captionContent)
- nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
- return eNameOK;
- }
- Relation
- HTMLFigureAccessible::RelationByType(RelationType aType)
- {
- Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
- if (aType == RelationType::LABELLED_BY)
- rel.AppendTarget(mDoc, Caption());
- return rel;
- }
- nsIContent*
- HTMLFigureAccessible::Caption() const
- {
- for (nsIContent* childContent = mContent->GetFirstChild(); childContent;
- childContent = childContent->GetNextSibling()) {
- if (childContent->NodeInfo()->Equals(nsGkAtoms::figcaption,
- mContent->GetNameSpaceID())) {
- return childContent;
- }
- }
- return nullptr;
- }
- ////////////////////////////////////////////////////////////////////////////////
- // HTMLFigcaptionAccessible
- ////////////////////////////////////////////////////////////////////////////////
- HTMLFigcaptionAccessible::
- HTMLFigcaptionAccessible(nsIContent* aContent, DocAccessible* aDoc) :
- HyperTextAccessibleWrap(aContent, aDoc)
- {
- }
- Relation
- HTMLFigcaptionAccessible::RelationByType(RelationType aType)
- {
- Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
- if (aType != RelationType::LABEL_FOR)
- return rel;
- Accessible* figure = Parent();
- if (figure &&
- figure->GetContent()->NodeInfo()->Equals(nsGkAtoms::figure,
- mContent->GetNameSpaceID())) {
- rel.AppendTarget(figure);
- }
- return rel;
- }
|