123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854 |
- // Copyright 2013 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/accessibility/ax_node_data.h"
- #include <stddef.h>
- #include <algorithm>
- #include <set>
- #include <type_traits>
- #include <utility>
- #include "base/containers/cxx20_erase.h"
- #include "base/no_destructor.h"
- #include "base/strings/string_number_conversions.h"
- #include "base/strings/string_util.h"
- #include "base/strings/stringprintf.h"
- #include "base/strings/utf_string_conversions.h"
- #include "ui/accessibility/ax_enum_util.h"
- #include "ui/accessibility/ax_enums.mojom.h"
- #include "ui/accessibility/ax_role_properties.h"
- #include "ui/accessibility/ax_tree_id.h"
- #include "ui/gfx/geometry/transform.h"
- namespace ui {
- namespace {
- bool IsFlagSet(uint32_t bitfield, uint32_t flag) {
- return (bitfield & (1U << flag)) != 0;
- }
- bool IsFlagSet(uint64_t bitfield, uint32_t flag) {
- return (bitfield & (1ULL << flag)) != 0;
- }
- uint32_t ModifyFlag(uint32_t bitfield, uint32_t flag, bool set) {
- return set ? (bitfield |= (1U << flag)) : (bitfield &= ~(1U << flag));
- }
- uint64_t ModifyFlag(uint64_t bitfield, uint32_t flag, bool set) {
- return set ? (bitfield |= (1ULL << flag)) : (bitfield &= ~(1ULL << flag));
- }
- std::string StateBitfieldToString(uint32_t state_enum) {
- std::string str;
- for (uint32_t i = static_cast<uint32_t>(ax::mojom::State::kNone) + 1;
- i <= static_cast<uint32_t>(ax::mojom::State::kMaxValue); ++i) {
- if (IsFlagSet(state_enum, i))
- str += " " +
- base::ToUpperASCII(ui::ToString(static_cast<ax::mojom::State>(i)));
- }
- return str;
- }
- std::string ActionsBitfieldToString(uint64_t actions) {
- std::string str;
- for (uint32_t i = static_cast<uint32_t>(ax::mojom::Action::kNone) + 1;
- i <= static_cast<uint32_t>(ax::mojom::Action::kMaxValue); ++i) {
- if (IsFlagSet(actions, i)) {
- str += ui::ToString(static_cast<ax::mojom::Action>(i));
- actions = ModifyFlag(actions, i, false);
- str += actions ? "," : "";
- }
- }
- return str;
- }
- template <typename ItemType, typename ItemToStringFunction>
- std::string VectorToString(const std::vector<ItemType>& items,
- ItemToStringFunction itemToStringFunction) {
- std::string str;
- for (size_t i = 0; i < items.size(); ++i) {
- std::string item_str = itemToStringFunction(items[i]);
- if (item_str.empty())
- continue;
- if (i > 0)
- str += ",";
- str += itemToStringFunction(items[i]);
- }
- return str;
- }
- std::string IntVectorToString(const std::vector<int32_t>& items) {
- return VectorToString(
- items, [](const int32_t item) { return base::NumberToString(item); });
- }
- // Predicate that returns true if the first value of a pair is |first|.
- template <typename FirstType, typename SecondType>
- struct FirstIs {
- explicit FirstIs(FirstType first) : first_(first) {}
- bool operator()(std::pair<FirstType, SecondType> const& p) {
- return p.first == first_;
- }
- FirstType first_;
- };
- // Helper function that finds a key in a vector of pairs by matching on the
- // first value, and returns an iterator.
- template <typename FirstType, typename SecondType>
- typename std::vector<std::pair<FirstType, SecondType>>::const_iterator
- FindInVectorOfPairs(
- FirstType first,
- const std::vector<std::pair<FirstType, SecondType>>& vector) {
- return std::find_if(vector.begin(), vector.end(),
- FirstIs<FirstType, SecondType>(first));
- }
- } // namespace
- // Return true if |attr| is a node ID that would need to be mapped when
- // renumbering the ids in a combined tree.
- bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr) {
- switch (attr) {
- case ax::mojom::IntAttribute::kActivedescendantId:
- case ax::mojom::IntAttribute::kErrormessageId:
- case ax::mojom::IntAttribute::kInPageLinkTargetId:
- case ax::mojom::IntAttribute::kMemberOfId:
- case ax::mojom::IntAttribute::kNextOnLineId:
- case ax::mojom::IntAttribute::kPopupForId:
- case ax::mojom::IntAttribute::kPreviousOnLineId:
- case ax::mojom::IntAttribute::kTableHeaderId:
- case ax::mojom::IntAttribute::kTableColumnHeaderId:
- case ax::mojom::IntAttribute::kTableRowHeaderId:
- case ax::mojom::IntAttribute::kNextFocusId:
- case ax::mojom::IntAttribute::kPreviousFocusId:
- return true;
- // Note: all of the attributes are included here explicitly,
- // rather than using "default:", so that it's a compiler error to
- // add a new attribute without explicitly considering whether it's
- // a node id attribute or not.
- case ax::mojom::IntAttribute::kNone:
- case ax::mojom::IntAttribute::kDefaultActionVerb:
- case ax::mojom::IntAttribute::kScrollX:
- case ax::mojom::IntAttribute::kScrollXMin:
- case ax::mojom::IntAttribute::kScrollXMax:
- case ax::mojom::IntAttribute::kScrollY:
- case ax::mojom::IntAttribute::kScrollYMin:
- case ax::mojom::IntAttribute::kScrollYMax:
- case ax::mojom::IntAttribute::kTextSelStart:
- case ax::mojom::IntAttribute::kTextSelEnd:
- case ax::mojom::IntAttribute::kTableRowCount:
- case ax::mojom::IntAttribute::kTableColumnCount:
- case ax::mojom::IntAttribute::kTableRowIndex:
- case ax::mojom::IntAttribute::kTableColumnIndex:
- case ax::mojom::IntAttribute::kTableCellColumnIndex:
- case ax::mojom::IntAttribute::kTableCellColumnSpan:
- case ax::mojom::IntAttribute::kTableCellRowIndex:
- case ax::mojom::IntAttribute::kTableCellRowSpan:
- case ax::mojom::IntAttribute::kSortDirection:
- case ax::mojom::IntAttribute::kHierarchicalLevel:
- case ax::mojom::IntAttribute::kNameFrom:
- case ax::mojom::IntAttribute::kDescriptionFrom:
- case ax::mojom::IntAttribute::kSetSize:
- case ax::mojom::IntAttribute::kPosInSet:
- case ax::mojom::IntAttribute::kColorValue:
- case ax::mojom::IntAttribute::kAriaCurrentState:
- case ax::mojom::IntAttribute::kHasPopup:
- case ax::mojom::IntAttribute::kBackgroundColor:
- case ax::mojom::IntAttribute::kColor:
- case ax::mojom::IntAttribute::kInvalidState:
- case ax::mojom::IntAttribute::kCheckedState:
- case ax::mojom::IntAttribute::kRestriction:
- case ax::mojom::IntAttribute::kListStyle:
- case ax::mojom::IntAttribute::kTextAlign:
- case ax::mojom::IntAttribute::kTextDirection:
- case ax::mojom::IntAttribute::kTextPosition:
- case ax::mojom::IntAttribute::kTextStyle:
- case ax::mojom::IntAttribute::kTextOverlineStyle:
- case ax::mojom::IntAttribute::kTextStrikethroughStyle:
- case ax::mojom::IntAttribute::kTextUnderlineStyle:
- case ax::mojom::IntAttribute::kAriaColumnCount:
- case ax::mojom::IntAttribute::kAriaCellColumnIndex:
- case ax::mojom::IntAttribute::kAriaCellColumnSpan:
- case ax::mojom::IntAttribute::kAriaRowCount:
- case ax::mojom::IntAttribute::kAriaCellRowIndex:
- case ax::mojom::IntAttribute::kAriaCellRowSpan:
- case ax::mojom::IntAttribute::kImageAnnotationStatus:
- case ax::mojom::IntAttribute::kDropeffect:
- case ax::mojom::IntAttribute::kDOMNodeId:
- return false;
- }
- NOTREACHED();
- return false;
- }
- // Returns true if |attr| contains a vector of node ids that would need
- // to be mapped when renumbering the ids in a combined tree.
- bool IsNodeIdIntListAttribute(ax::mojom::IntListAttribute attr) {
- switch (attr) {
- case ax::mojom::IntListAttribute::kIndirectChildIds:
- case ax::mojom::IntListAttribute::kControlsIds:
- case ax::mojom::IntListAttribute::kDetailsIds:
- case ax::mojom::IntListAttribute::kDescribedbyIds:
- case ax::mojom::IntListAttribute::kFlowtoIds:
- case ax::mojom::IntListAttribute::kLabelledbyIds:
- case ax::mojom::IntListAttribute::kRadioGroupIds:
- return true;
- // Note: all of the attributes are included here explicitly,
- // rather than using "default:", so that it's a compiler error to
- // add a new attribute without explicitly considering whether it's
- // a node id attribute or not.
- case ax::mojom::IntListAttribute::kNone:
- case ax::mojom::IntListAttribute::kMarkerTypes:
- case ax::mojom::IntListAttribute::kMarkerStarts:
- case ax::mojom::IntListAttribute::kMarkerEnds:
- case ax::mojom::IntListAttribute::kHighlightTypes:
- case ax::mojom::IntListAttribute::kCaretBounds:
- case ax::mojom::IntListAttribute::kCharacterOffsets:
- case ax::mojom::IntListAttribute::kLineStarts:
- case ax::mojom::IntListAttribute::kLineEnds:
- case ax::mojom::IntListAttribute::kSentenceStarts:
- case ax::mojom::IntListAttribute::kSentenceEnds:
- case ax::mojom::IntListAttribute::kWordStarts:
- case ax::mojom::IntListAttribute::kWordEnds:
- case ax::mojom::IntListAttribute::kCustomActionIds:
- return false;
- }
- }
- AXNodeData::AXNodeData() : role(ax::mojom::Role::kUnknown) {}
- AXNodeData::~AXNodeData() = default;
- AXNodeData::AXNodeData(const AXNodeData& other) {
- id = other.id;
- role = other.role;
- state = other.state;
- actions = other.actions;
- string_attributes = other.string_attributes;
- int_attributes = other.int_attributes;
- float_attributes = other.float_attributes;
- bool_attributes = other.bool_attributes;
- intlist_attributes = other.intlist_attributes;
- stringlist_attributes = other.stringlist_attributes;
- html_attributes = other.html_attributes;
- child_ids = other.child_ids;
- relative_bounds = other.relative_bounds;
- }
- AXNodeData::AXNodeData(AXNodeData&& other) {
- id = other.id;
- role = other.role;
- state = other.state;
- actions = other.actions;
- string_attributes.swap(other.string_attributes);
- int_attributes.swap(other.int_attributes);
- float_attributes.swap(other.float_attributes);
- bool_attributes.swap(other.bool_attributes);
- intlist_attributes.swap(other.intlist_attributes);
- stringlist_attributes.swap(other.stringlist_attributes);
- html_attributes.swap(other.html_attributes);
- child_ids.swap(other.child_ids);
- relative_bounds = other.relative_bounds;
- other.id = kInvalidAXNodeID;
- other.role = ax::mojom::Role::kUnknown;
- other.state = 0U;
- other.actions = 0ULL;
- }
- AXNodeData& AXNodeData::operator=(const AXNodeData& other) {
- id = other.id;
- role = other.role;
- state = other.state;
- actions = other.actions;
- string_attributes = other.string_attributes;
- int_attributes = other.int_attributes;
- float_attributes = other.float_attributes;
- bool_attributes = other.bool_attributes;
- intlist_attributes = other.intlist_attributes;
- stringlist_attributes = other.stringlist_attributes;
- html_attributes = other.html_attributes;
- child_ids = other.child_ids;
- relative_bounds = other.relative_bounds;
- return *this;
- }
- bool AXNodeData::HasBoolAttribute(ax::mojom::BoolAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, bool_attributes);
- return iter != bool_attributes.end();
- }
- bool AXNodeData::GetBoolAttribute(ax::mojom::BoolAttribute attribute) const {
- bool result;
- if (GetBoolAttribute(attribute, &result))
- return result;
- return false;
- }
- bool AXNodeData::GetBoolAttribute(ax::mojom::BoolAttribute attribute,
- bool* value) const {
- auto iter = FindInVectorOfPairs(attribute, bool_attributes);
- if (iter != bool_attributes.end()) {
- *value = iter->second;
- return true;
- }
- return false;
- }
- bool AXNodeData::HasFloatAttribute(ax::mojom::FloatAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, float_attributes);
- return iter != float_attributes.end();
- }
- float AXNodeData::GetFloatAttribute(ax::mojom::FloatAttribute attribute) const {
- float result;
- if (GetFloatAttribute(attribute, &result))
- return result;
- return 0.0;
- }
- bool AXNodeData::GetFloatAttribute(ax::mojom::FloatAttribute attribute,
- float* value) const {
- auto iter = FindInVectorOfPairs(attribute, float_attributes);
- if (iter != float_attributes.end()) {
- *value = iter->second;
- return true;
- }
- return false;
- }
- bool AXNodeData::HasIntAttribute(ax::mojom::IntAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, int_attributes);
- return iter != int_attributes.end();
- }
- int AXNodeData::GetIntAttribute(ax::mojom::IntAttribute attribute) const {
- int result;
- if (GetIntAttribute(attribute, &result))
- return result;
- return 0;
- }
- bool AXNodeData::GetIntAttribute(ax::mojom::IntAttribute attribute,
- int* value) const {
- auto iter = FindInVectorOfPairs(attribute, int_attributes);
- if (iter != int_attributes.end()) {
- *value = int{iter->second};
- return true;
- }
- return false;
- }
- bool AXNodeData::HasStringAttribute(
- ax::mojom::StringAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, string_attributes);
- return iter != string_attributes.end();
- }
- const std::string& AXNodeData::GetStringAttribute(
- ax::mojom::StringAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, string_attributes);
- return iter != string_attributes.end() ? iter->second : base::EmptyString();
- }
- bool AXNodeData::GetStringAttribute(ax::mojom::StringAttribute attribute,
- std::string* value) const {
- auto iter = FindInVectorOfPairs(attribute, string_attributes);
- if (iter != string_attributes.end()) {
- *value = iter->second;
- return true;
- }
- return false;
- }
- std::u16string AXNodeData::GetString16Attribute(
- ax::mojom::StringAttribute attribute) const {
- std::string value_utf8;
- if (!GetStringAttribute(attribute, &value_utf8))
- return std::u16string();
- return base::UTF8ToUTF16(value_utf8);
- }
- bool AXNodeData::GetString16Attribute(ax::mojom::StringAttribute attribute,
- std::u16string* value) const {
- std::string value_utf8;
- if (!GetStringAttribute(attribute, &value_utf8))
- return false;
- *value = base::UTF8ToUTF16(value_utf8);
- return true;
- }
- bool AXNodeData::HasIntListAttribute(
- ax::mojom::IntListAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
- return iter != intlist_attributes.end();
- }
- const std::vector<int32_t>& AXNodeData::GetIntListAttribute(
- ax::mojom::IntListAttribute attribute) const {
- static const base::NoDestructor<std::vector<int32_t>> empty_vector;
- auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
- if (iter != intlist_attributes.end())
- return iter->second;
- return *empty_vector;
- }
- bool AXNodeData::GetIntListAttribute(ax::mojom::IntListAttribute attribute,
- std::vector<int32_t>* value) const {
- auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
- if (iter != intlist_attributes.end()) {
- *value = iter->second;
- return true;
- }
- return false;
- }
- bool AXNodeData::HasStringListAttribute(
- ax::mojom::StringListAttribute attribute) const {
- auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
- return iter != stringlist_attributes.end();
- }
- const std::vector<std::string>& AXNodeData::GetStringListAttribute(
- ax::mojom::StringListAttribute attribute) const {
- static const base::NoDestructor<std::vector<std::string>> empty_vector;
- auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
- if (iter != stringlist_attributes.end())
- return iter->second;
- return *empty_vector;
- }
- bool AXNodeData::GetStringListAttribute(
- ax::mojom::StringListAttribute attribute,
- std::vector<std::string>* value) const {
- auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
- if (iter != stringlist_attributes.end()) {
- *value = iter->second;
- return true;
- }
- return false;
- }
- bool AXNodeData::HasHtmlAttribute(const char* attribute) const {
- std::string value;
- if (!GetHtmlAttribute(attribute, &value))
- return false;
- return true;
- }
- bool AXNodeData::GetHtmlAttribute(const char* attribute,
- std::string* value) const {
- for (const std::pair<std::string, std::string>& html_attribute :
- html_attributes) {
- const std::string& attr = html_attribute.first;
- if (base::EqualsCaseInsensitiveASCII(attr, attribute)) {
- *value = html_attribute.second;
- return true;
- }
- }
- return false;
- }
- std::u16string AXNodeData::GetHtmlAttribute(const char* attribute) const {
- std::u16string value_utf16;
- GetHtmlAttribute(attribute, &value_utf16);
- return value_utf16;
- }
- bool AXNodeData::GetHtmlAttribute(const char* attribute,
- std::u16string* value) const {
- std::string value_utf8;
- if (!GetHtmlAttribute(attribute, &value_utf8))
- return false;
- *value = base::UTF8ToUTF16(value_utf8);
- return true;
- }
- void AXNodeData::AddChildTreeId(const AXTreeID& tree_id) {
- ax::mojom::StringAttribute attribute =
- ax::mojom::StringAttribute::kChildTreeId;
- if (HasStringAttribute(attribute))
- RemoveStringAttribute(attribute);
- string_attributes.emplace_back(attribute, tree_id.ToString());
- }
- void AXNodeData::AddBoolAttribute(ax::mojom::BoolAttribute attribute,
- bool value) {
- DCHECK_NE(attribute, ax::mojom::BoolAttribute::kNone);
- if (HasBoolAttribute(attribute))
- RemoveBoolAttribute(attribute);
- bool_attributes.emplace_back(attribute, value);
- }
- void AXNodeData::AddIntAttribute(ax::mojom::IntAttribute attribute, int value) {
- DCHECK_NE(attribute, ax::mojom::IntAttribute::kNone);
- if (HasIntAttribute(attribute))
- RemoveIntAttribute(attribute);
- int_attributes.emplace_back(attribute, value);
- }
- void AXNodeData::AddFloatAttribute(ax::mojom::FloatAttribute attribute,
- float value) {
- DCHECK_NE(attribute, ax::mojom::FloatAttribute::kNone);
- if (HasFloatAttribute(attribute))
- RemoveFloatAttribute(attribute);
- float_attributes.emplace_back(attribute, value);
- }
- void AXNodeData::AddStringAttribute(ax::mojom::StringAttribute attribute,
- const std::string& value) {
- DCHECK_NE(attribute, ax::mojom::StringAttribute::kNone);
- DCHECK_NE(attribute, ax::mojom::StringAttribute::kChildTreeId)
- << "Use AddChildTreeId.";
- if (HasStringAttribute(attribute))
- RemoveStringAttribute(attribute);
- string_attributes.emplace_back(attribute, value);
- }
- void AXNodeData::AddIntListAttribute(ax::mojom::IntListAttribute attribute,
- const std::vector<int32_t>& value) {
- DCHECK_NE(attribute, ax::mojom::IntListAttribute::kNone);
- if (HasIntListAttribute(attribute))
- RemoveIntListAttribute(attribute);
- intlist_attributes.emplace_back(attribute, value);
- }
- void AXNodeData::AddStringListAttribute(
- ax::mojom::StringListAttribute attribute,
- const std::vector<std::string>& value) {
- DCHECK_NE(attribute, ax::mojom::StringListAttribute::kNone);
- if (HasStringListAttribute(attribute))
- RemoveStringListAttribute(attribute);
- stringlist_attributes.emplace_back(attribute, value);
- }
- void AXNodeData::RemoveBoolAttribute(ax::mojom::BoolAttribute attribute) {
- DCHECK_NE(attribute, ax::mojom::BoolAttribute::kNone);
- base::EraseIf(bool_attributes, [attribute](const auto& bool_attribute) {
- return bool_attribute.first == attribute;
- });
- }
- void AXNodeData::RemoveIntAttribute(ax::mojom::IntAttribute attribute) {
- DCHECK_NE(attribute, ax::mojom::IntAttribute::kNone);
- base::EraseIf(int_attributes, [attribute](const auto& int_attribute) {
- return int_attribute.first == attribute;
- });
- }
- void AXNodeData::RemoveFloatAttribute(ax::mojom::FloatAttribute attribute) {
- DCHECK_NE(attribute, ax::mojom::FloatAttribute::kNone);
- base::EraseIf(float_attributes, [attribute](const auto& float_attribute) {
- return float_attribute.first == attribute;
- });
- }
- void AXNodeData::RemoveStringAttribute(ax::mojom::StringAttribute attribute) {
- DCHECK_NE(attribute, ax::mojom::StringAttribute::kNone);
- base::EraseIf(string_attributes, [attribute](const auto& string_attribute) {
- return string_attribute.first == attribute;
- });
- }
- void AXNodeData::RemoveIntListAttribute(ax::mojom::IntListAttribute attribute) {
- DCHECK_NE(attribute, ax::mojom::IntListAttribute::kNone);
- base::EraseIf(intlist_attributes, [attribute](const auto& intlist_attribute) {
- return intlist_attribute.first == attribute;
- });
- }
- void AXNodeData::RemoveStringListAttribute(
- ax::mojom::StringListAttribute attribute) {
- DCHECK_NE(attribute, ax::mojom::StringListAttribute::kNone);
- base::EraseIf(stringlist_attributes,
- [attribute](const auto& stringlist_attribute) {
- return stringlist_attribute.first == attribute;
- });
- }
- AXTextAttributes AXNodeData::GetTextAttributes() const {
- AXTextAttributes text_attributes;
- // This overload of `GetIntAttribute` does not set the return value to 0 if
- // the attribute is not present, hence maintaining the corresponding member in
- // `AXTextAttributes` as `AXTextAttributes::kUnsetValue`.
- GetIntAttribute(ax::mojom::IntAttribute::kBackgroundColor,
- &text_attributes.background_color);
- GetIntAttribute(ax::mojom::IntAttribute::kColor, &text_attributes.color);
- GetIntAttribute(ax::mojom::IntAttribute::kInvalidState,
- &text_attributes.invalid_state);
- GetIntAttribute(ax::mojom::IntAttribute::kTextOverlineStyle,
- &text_attributes.overline_style);
- GetIntAttribute(ax::mojom::IntAttribute::kTextDirection,
- &text_attributes.text_direction);
- GetIntAttribute(ax::mojom::IntAttribute::kTextPosition,
- &text_attributes.text_position);
- GetIntAttribute(ax::mojom::IntAttribute::kTextStrikethroughStyle,
- &text_attributes.strikethrough_style);
- GetIntAttribute(ax::mojom::IntAttribute::kTextStyle,
- &text_attributes.text_style);
- GetIntAttribute(ax::mojom::IntAttribute::kTextUnderlineStyle,
- &text_attributes.underline_style);
- GetFloatAttribute(ax::mojom::FloatAttribute::kFontSize,
- &text_attributes.font_size);
- GetFloatAttribute(ax::mojom::FloatAttribute::kFontWeight,
- &text_attributes.font_weight);
- GetStringAttribute(ax::mojom::StringAttribute::kFontFamily,
- &text_attributes.font_family);
- GetIntListAttribute(ax::mojom::IntListAttribute::kMarkerTypes,
- &text_attributes.marker_types);
- GetIntListAttribute(ax::mojom::IntListAttribute::kHighlightTypes,
- &text_attributes.highlight_types);
- return text_attributes;
- }
- void AXNodeData::SetName(const std::string& name) {
- // Elements with role='presentation' have Role::kNone. They should not be
- // named. This check is only relevant if the name is not empty.
- // TODO(accessibility): It would be nice to have a means to set the name
- // and role at the same time to avoid this ordering requirement.
- DCHECK(role != ax::mojom::Role::kNone || name.empty())
- << "Cannot set name to '" << name << "' on class: '"
- << GetStringAttribute(ax::mojom::StringAttribute::kClassName)
- << "' because a valid role is needed to set the default NameFrom "
- "attribute. Set the role first.";
- auto iter = std::find_if(string_attributes.begin(), string_attributes.end(),
- [](const auto& string_attribute) {
- return string_attribute.first ==
- ax::mojom::StringAttribute::kName;
- });
- if (iter == string_attributes.end()) {
- string_attributes.emplace_back(ax::mojom::StringAttribute::kName, name);
- } else {
- iter->second = name;
- }
- // It is possible for SetName to be called after
- // SetNameExplicitlyEmpty.
- if (!name.empty() &&
- GetNameFrom() == ax::mojom::NameFrom::kAttributeExplicitlyEmpty) {
- RemoveIntAttribute(ax::mojom::IntAttribute::kNameFrom);
- }
- if (HasIntAttribute(ax::mojom::IntAttribute::kNameFrom))
- return;
- // Since this method is mostly used by tests which don't always set the
- // "NameFrom" attribute, we need to set it here to the most likely value if
- // not set, otherwise code that tries to calculate the node's inner text, its
- // hypertext, or even its value, might not know whether to include the name in
- // the result or not.
- //
- // For example, if there is a text field, but it is empty, i.e. it has no
- // value, its value could be its name if "NameFrom" is set to "kPlaceholder"
- // or to "kContents" but not if it's set to "kAttribute". Similarly, if there
- // is a button without any unignored children, it's name can only be
- // equivalent to its inner text if "NameFrom" is set to "kContents" or to
- // "kValue", but not if it is set to "kAttribute".
- if (IsText(role)) {
- SetNameFrom(ax::mojom::NameFrom::kContents);
- } else {
- SetNameFrom(ax::mojom::NameFrom::kAttribute);
- }
- }
- void AXNodeData::SetName(const std::u16string& name) {
- SetName(base::UTF16ToUTF8(name));
- }
- void AXNodeData::SetNameExplicitlyEmpty() {
- SetNameFrom(ax::mojom::NameFrom::kAttributeExplicitlyEmpty);
- SetName(std::string());
- }
- void AXNodeData::SetDescription(const std::string& description) {
- AddStringAttribute(ax::mojom::StringAttribute::kDescription, description);
- }
- void AXNodeData::SetDescription(const std::u16string& description) {
- SetDescription(base::UTF16ToUTF8(description));
- }
- void AXNodeData::SetValue(const std::string& value) {
- AddStringAttribute(ax::mojom::StringAttribute::kValue, value);
- }
- void AXNodeData::SetValue(const std::u16string& value) {
- SetValue(base::UTF16ToUTF8(value));
- }
- bool AXNodeData::HasState(ax::mojom::State state_enum) const {
- return IsFlagSet(state, static_cast<uint32_t>(state_enum));
- }
- bool AXNodeData::HasAction(ax::mojom::Action action) const {
- return IsFlagSet(actions, static_cast<uint32_t>(action));
- }
- bool AXNodeData::HasTextStyle(ax::mojom::TextStyle text_style_enum) const {
- int32_t style = GetIntAttribute(ax::mojom::IntAttribute::kTextStyle);
- return IsFlagSet(static_cast<uint32_t>(style),
- static_cast<uint32_t>(text_style_enum));
- }
- bool AXNodeData::HasDropeffect(ax::mojom::Dropeffect dropeffect_enum) const {
- int32_t dropeffect = GetIntAttribute(ax::mojom::IntAttribute::kDropeffect);
- return IsFlagSet(static_cast<uint32_t>(dropeffect),
- static_cast<uint32_t>(dropeffect_enum));
- }
- void AXNodeData::AddState(ax::mojom::State state_enum) {
- DCHECK_GT(static_cast<int>(state_enum),
- static_cast<int>(ax::mojom::State::kNone));
- DCHECK_LE(static_cast<int>(state_enum),
- static_cast<int>(ax::mojom::State::kMaxValue));
- state = ModifyFlag(state, static_cast<uint32_t>(state_enum), true);
- }
- void AXNodeData::RemoveState(ax::mojom::State state_enum) {
- DCHECK_GT(static_cast<int>(state_enum),
- static_cast<int>(ax::mojom::State::kNone));
- DCHECK_LE(static_cast<int>(state_enum),
- static_cast<int>(ax::mojom::State::kMaxValue));
- state = ModifyFlag(state, static_cast<uint32_t>(state_enum), false);
- }
- void AXNodeData::AddAction(ax::mojom::Action action_enum) {
- switch (action_enum) {
- case ax::mojom::Action::kNone:
- NOTREACHED();
- break;
- // Note: all of the attributes are included here explicitly, rather than
- // using "default:", so that it's a compiler error to add a new action
- // without explicitly considering whether there are mutually exclusive
- // actions that can be performed on a UI control at the same time.
- case ax::mojom::Action::kBlur:
- case ax::mojom::Action::kFocus: {
- ax::mojom::Action excluded_action =
- (action_enum == ax::mojom::Action::kBlur) ? ax::mojom::Action::kFocus
- : ax::mojom::Action::kBlur;
- DCHECK(!HasAction(excluded_action)) << excluded_action;
- break;
- }
- case ax::mojom::Action::kClearAccessibilityFocus:
- case ax::mojom::Action::kCollapse:
- case ax::mojom::Action::kCustomAction:
- case ax::mojom::Action::kDecrement:
- case ax::mojom::Action::kDoDefault:
- case ax::mojom::Action::kExpand:
- case ax::mojom::Action::kGetImageData:
- case ax::mojom::Action::kHitTest:
- case ax::mojom::Action::kIncrement:
- case ax::mojom::Action::kInternalInvalidateTree:
- case ax::mojom::Action::kLoadInlineTextBoxes:
- case ax::mojom::Action::kReplaceSelectedText:
- case ax::mojom::Action::kScrollToMakeVisible:
- case ax::mojom::Action::kScrollToPoint:
- case ax::mojom::Action::kSetAccessibilityFocus:
- case ax::mojom::Action::kSetScrollOffset:
- case ax::mojom::Action::kSetSelection:
- case ax::mojom::Action::kSetSequentialFocusNavigationStartingPoint:
- case ax::mojom::Action::kSetValue:
- case ax::mojom::Action::kShowContextMenu:
- case ax::mojom::Action::kScrollBackward:
- case ax::mojom::Action::kScrollForward:
- case ax::mojom::Action::kScrollUp:
- case ax::mojom::Action::kScrollDown:
- case ax::mojom::Action::kScrollLeft:
- case ax::mojom::Action::kScrollRight:
- case ax::mojom::Action::kGetTextLocation:
- case ax::mojom::Action::kAnnotatePageImages:
- case ax::mojom::Action::kSignalEndOfTest:
- case ax::mojom::Action::kHideTooltip:
- case ax::mojom::Action::kShowTooltip:
- case ax::mojom::Action::kResumeMedia:
- case ax::mojom::Action::kStartDuckingMedia:
- case ax::mojom::Action::kStopDuckingMedia:
- case ax::mojom::Action::kSuspendMedia:
- break;
- }
- actions = ModifyFlag(actions, static_cast<uint32_t>(action_enum), true);
- }
- void AXNodeData::AddTextStyle(ax::mojom::TextStyle text_style_enum) {
- DCHECK_GE(static_cast<int>(text_style_enum),
- static_cast<int>(ax::mojom::TextStyle::kMinValue));
- DCHECK_LE(static_cast<int>(text_style_enum),
- static_cast<int>(ax::mojom::TextStyle::kMaxValue));
- int32_t style = GetIntAttribute(ax::mojom::IntAttribute::kTextStyle);
- style = ModifyFlag(static_cast<uint32_t>(style),
- static_cast<uint32_t>(text_style_enum), true);
- RemoveIntAttribute(ax::mojom::IntAttribute::kTextStyle);
- AddIntAttribute(ax::mojom::IntAttribute::kTextStyle, style);
- }
- void AXNodeData::AddDropeffect(ax::mojom::Dropeffect dropeffect_enum) {
- DCHECK_GE(static_cast<int>(dropeffect_enum),
- static_cast<int>(ax::mojom::Dropeffect::kMinValue));
- DCHECK_LE(static_cast<int>(dropeffect_enum),
- static_cast<int>(ax::mojom::Dropeffect::kMaxValue));
- int32_t dropeffect = GetIntAttribute(ax::mojom::IntAttribute::kDropeffect);
- dropeffect = ModifyFlag(static_cast<uint32_t>(dropeffect),
- static_cast<uint32_t>(dropeffect_enum), true);
- RemoveIntAttribute(ax::mojom::IntAttribute::kDropeffect);
- AddIntAttribute(ax::mojom::IntAttribute::kDropeffect, dropeffect);
- }
- ax::mojom::CheckedState AXNodeData::GetCheckedState() const {
- return static_cast<ax::mojom::CheckedState>(
- GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
- }
- void AXNodeData::SetCheckedState(ax::mojom::CheckedState checked_state) {
- if (HasCheckedState())
- RemoveIntAttribute(ax::mojom::IntAttribute::kCheckedState);
- if (checked_state != ax::mojom::CheckedState::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kCheckedState,
- static_cast<int32_t>(checked_state));
- }
- }
- bool AXNodeData::HasCheckedState() const {
- return HasIntAttribute(ax::mojom::IntAttribute::kCheckedState);
- }
- ax::mojom::DefaultActionVerb AXNodeData::GetDefaultActionVerb() const {
- return static_cast<ax::mojom::DefaultActionVerb>(
- GetIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb));
- }
- void AXNodeData::SetDefaultActionVerb(
- ax::mojom::DefaultActionVerb default_action_verb) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb))
- RemoveIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb);
- if (default_action_verb != ax::mojom::DefaultActionVerb::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb,
- static_cast<int32_t>(default_action_verb));
- }
- }
- ax::mojom::HasPopup AXNodeData::GetHasPopup() const {
- return static_cast<ax::mojom::HasPopup>(
- GetIntAttribute(ax::mojom::IntAttribute::kHasPopup));
- }
- void AXNodeData::SetHasPopup(ax::mojom::HasPopup has_popup) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kHasPopup))
- RemoveIntAttribute(ax::mojom::IntAttribute::kHasPopup);
- if (has_popup != ax::mojom::HasPopup::kFalse) {
- AddIntAttribute(ax::mojom::IntAttribute::kHasPopup,
- static_cast<int32_t>(has_popup));
- }
- }
- ax::mojom::InvalidState AXNodeData::GetInvalidState() const {
- return static_cast<ax::mojom::InvalidState>(
- GetIntAttribute(ax::mojom::IntAttribute::kInvalidState));
- }
- void AXNodeData::SetInvalidState(ax::mojom::InvalidState invalid_state) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kInvalidState))
- RemoveIntAttribute(ax::mojom::IntAttribute::kInvalidState);
- if (invalid_state != ax::mojom::InvalidState::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kInvalidState,
- static_cast<int32_t>(invalid_state));
- }
- }
- ax::mojom::NameFrom AXNodeData::GetNameFrom() const {
- return static_cast<ax::mojom::NameFrom>(
- GetIntAttribute(ax::mojom::IntAttribute::kNameFrom));
- }
- void AXNodeData::SetNameFrom(ax::mojom::NameFrom name_from) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kNameFrom))
- RemoveIntAttribute(ax::mojom::IntAttribute::kNameFrom);
- if (name_from != ax::mojom::NameFrom::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kNameFrom,
- static_cast<int32_t>(name_from));
- }
- }
- ax::mojom::DescriptionFrom AXNodeData::GetDescriptionFrom() const {
- return static_cast<ax::mojom::DescriptionFrom>(
- GetIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom));
- }
- void AXNodeData::SetDescriptionFrom(
- ax::mojom::DescriptionFrom description_from) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom))
- RemoveIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom);
- if (description_from != ax::mojom::DescriptionFrom::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kDescriptionFrom,
- static_cast<int32_t>(description_from));
- }
- }
- ax::mojom::TextPosition AXNodeData::GetTextPosition() const {
- return static_cast<ax::mojom::TextPosition>(
- GetIntAttribute(ax::mojom::IntAttribute::kTextPosition));
- }
- void AXNodeData::SetTextPosition(ax::mojom::TextPosition text_position) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kTextPosition))
- RemoveIntAttribute(ax::mojom::IntAttribute::kTextPosition);
- if (text_position != ax::mojom::TextPosition::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kTextPosition,
- static_cast<int32_t>(text_position));
- }
- }
- ax::mojom::ImageAnnotationStatus AXNodeData::GetImageAnnotationStatus() const {
- return static_cast<ax::mojom::ImageAnnotationStatus>(
- GetIntAttribute(ax::mojom::IntAttribute::kImageAnnotationStatus));
- }
- void AXNodeData::SetImageAnnotationStatus(
- ax::mojom::ImageAnnotationStatus status) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kImageAnnotationStatus))
- RemoveIntAttribute(ax::mojom::IntAttribute::kImageAnnotationStatus);
- if (status != ax::mojom::ImageAnnotationStatus::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kImageAnnotationStatus,
- static_cast<int32_t>(status));
- }
- }
- ax::mojom::Restriction AXNodeData::GetRestriction() const {
- return static_cast<ax::mojom::Restriction>(
- GetIntAttribute(ax::mojom::IntAttribute::kRestriction));
- }
- void AXNodeData::SetRestriction(ax::mojom::Restriction restriction) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kRestriction))
- RemoveIntAttribute(ax::mojom::IntAttribute::kRestriction);
- if (restriction != ax::mojom::Restriction::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kRestriction,
- static_cast<int32_t>(restriction));
- }
- }
- ax::mojom::ListStyle AXNodeData::GetListStyle() const {
- return static_cast<ax::mojom::ListStyle>(
- GetIntAttribute(ax::mojom::IntAttribute::kListStyle));
- }
- void AXNodeData::SetListStyle(ax::mojom::ListStyle list_style) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kListStyle))
- RemoveIntAttribute(ax::mojom::IntAttribute::kListStyle);
- if (list_style != ax::mojom::ListStyle::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kListStyle,
- static_cast<int32_t>(list_style));
- }
- }
- ax::mojom::TextAlign AXNodeData::GetTextAlign() const {
- return static_cast<ax::mojom::TextAlign>(
- GetIntAttribute(ax::mojom::IntAttribute::kTextAlign));
- }
- void AXNodeData::SetTextAlign(ax::mojom::TextAlign text_align) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kTextAlign))
- RemoveIntAttribute(ax::mojom::IntAttribute::kTextAlign);
- AddIntAttribute(ax::mojom::IntAttribute::kTextAlign,
- static_cast<int32_t>(text_align));
- }
- ax::mojom::WritingDirection AXNodeData::GetTextDirection() const {
- return static_cast<ax::mojom::WritingDirection>(
- GetIntAttribute(ax::mojom::IntAttribute::kTextDirection));
- }
- void AXNodeData::SetTextDirection(ax::mojom::WritingDirection text_direction) {
- if (HasIntAttribute(ax::mojom::IntAttribute::kTextDirection))
- RemoveIntAttribute(ax::mojom::IntAttribute::kTextDirection);
- if (text_direction != ax::mojom::WritingDirection::kNone) {
- AddIntAttribute(ax::mojom::IntAttribute::kTextDirection,
- static_cast<int32_t>(text_direction));
- }
- }
- bool AXNodeData::IsActivatable() const {
- return IsTextField() || role == ax::mojom::Role::kListBox;
- }
- bool AXNodeData::IsActiveLiveRegionRoot() const {
- std::string aria_live_status;
- if (GetStringAttribute(ax::mojom::StringAttribute::kLiveStatus,
- &aria_live_status)) {
- return aria_live_status != "off";
- }
- return false;
- }
- bool AXNodeData::IsButtonPressed() const {
- // Currently there is no internal representation for |aria-pressed|, and
- // we map |aria-pressed="true"| to ax::mojom::CheckedState::kTrue for a native
- // button or role="button".
- // https://www.w3.org/TR/wai-aria-1.1/#aria-pressed
- if (IsButton(role) && GetCheckedState() == ax::mojom::CheckedState::kTrue)
- return true;
- return false;
- }
- bool AXNodeData::IsClickable() const {
- // If it has a custom default action verb except for
- // ax::mojom::DefaultActionVerb::kClickAncestor, it's definitely clickable.
- // ax::mojom::DefaultActionVerb::kClickAncestor is used when an element with a
- // click listener is present in its ancestry chain.
- if (HasIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb) &&
- (GetDefaultActionVerb() != ax::mojom::DefaultActionVerb::kClickAncestor))
- return true;
- return ui::IsClickable(role);
- }
- bool AXNodeData::IsContainedInActiveLiveRegion() const {
- std::string aria_container_live_status;
- if (GetStringAttribute(ax::mojom::StringAttribute::kContainerLiveStatus,
- &aria_container_live_status)) {
- return aria_container_live_status != "off" &&
- HasStringAttribute(ax::mojom::StringAttribute::kName);
- }
- return false;
- }
- bool AXNodeData::IsSelectable() const {
- // It's selectable if it has the attribute, whether it's true or false.
- return HasBoolAttribute(ax::mojom::BoolAttribute::kSelected) &&
- GetRestriction() != ax::mojom::Restriction::kDisabled;
- }
- bool AXNodeData::IsIgnored() const {
- return HasState(ax::mojom::State::kIgnored) || role == ax::mojom::Role::kNone;
- }
- bool AXNodeData::IsInvisible() const {
- return HasState(ax::mojom::State::kInvisible);
- }
- bool AXNodeData::IsInvisibleOrIgnored() const {
- return IsIgnored() || IsInvisible();
- }
- bool AXNodeData::IsInvocable() const {
- // A control is "invocable" if it initiates an action when activated but
- // does not maintain any state. A control that maintains state when activated
- // would be considered a toggle or expand-collapse element - these elements
- // are "clickable" but not "invocable". Similarly, if the action only involves
- // activating the control, such as when clicking a text field, the control is
- // not considered "invocable". However, all links are always invocable.
- return IsLink(role) || (IsClickable() && !IsActivatable() &&
- !SupportsExpandCollapse() && !SupportsToggle(role));
- }
- bool AXNodeData::IsMenuButton() const {
- // According to the WAI-ARIA spec, a menu button is a native button or an ARIA
- // role="button" that opens a menu. Although ARIA does not include a role
- // specifically for menu buttons, screen readers identify buttons that have
- // aria-haspopup="true" or aria-haspopup="menu" as menu buttons, and Blink
- // maps both to HasPopup::kMenu.
- // https://www.w3.org/TR/wai-aria-practices/#menubutton
- // https://www.w3.org/TR/wai-aria-1.1/#aria-haspopup
- if (IsButton(role) && GetHasPopup() == ax::mojom::HasPopup::kMenu)
- return true;
- return false;
- }
- bool AXNodeData::IsTextField() const {
- return IsAtomicTextField() || IsNonAtomicTextField() || IsSpinnerTextField();
- }
- bool AXNodeData::IsPasswordField() const {
- return IsTextField() && HasState(ax::mojom::State::kProtected);
- }
- bool AXNodeData::IsAtomicTextField() const {
- // The ARIA spec suggests a textbox or a searchbox is a simple text field,
- // like an <input> or <textarea> depending on aria-multiline. However there is
- // nothing to stop an author from adding the textbox role to a
- // non-contenteditable element, or from adding or removing non-plain-text
- // nodes. If we treat the textbox role as atomic when contenteditable is not
- // set, it can break accessibility by pruning interactive elements from the
- // accessibility tree. Therefore, until we have a reliable means to identify
- // truly atomic ARIA textboxes, we treat them as non-atomic in Blink.
- return (ui::IsTextField(role) || IsSpinnerTextField()) &&
- !GetBoolAttribute(ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot);
- }
- bool AXNodeData::IsNonAtomicTextField() const {
- return GetBoolAttribute(ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot);
- }
- bool AXNodeData::IsSpinnerTextField() const {
- // TODO(accessibility) Should an editable spin button be it's own role?
- // This would allow this method to go away, by instead adding the editable
- // spinbutton role to AXRoleProperties::IsTextField().
- return role == ax::mojom::Role::kSpinButton &&
- GetStringAttribute(ax::mojom::StringAttribute::kInputType) == "number";
- }
- bool AXNodeData::IsRangeValueSupported() const {
- if (role == ax::mojom::Role::kSplitter) {
- // According to the ARIA spec, role="separator" acts as a splitter only
- // when focusable, and supports a range only in that case.
- return HasState(ax::mojom::State::kFocusable);
- }
- return ui::IsRangeValueSupported(role);
- }
- bool AXNodeData::SupportsExpandCollapse() const {
- if (GetHasPopup() != ax::mojom::HasPopup::kFalse ||
- HasState(ax::mojom::State::kExpanded) ||
- HasState(ax::mojom::State::kCollapsed))
- return true;
- return ui::SupportsExpandCollapse(role);
- }
- std::string AXNodeData::ToString() const {
- std::string result;
- result += "id=" + base::NumberToString(id);
- result += " ";
- result += ui::ToString(role);
- result += StateBitfieldToString(state);
- result += " " + relative_bounds.ToString();
- for (const std::pair<ax::mojom::IntAttribute, int32_t>& int_attribute :
- int_attributes) {
- std::string value = base::NumberToString(int_attribute.second);
- switch (int_attribute.first) {
- case ax::mojom::IntAttribute::kDefaultActionVerb:
- result += std::string(" action=") +
- ui::ToString(static_cast<ax::mojom::DefaultActionVerb>(
- int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kScrollX:
- result += " scroll_x=" + value;
- break;
- case ax::mojom::IntAttribute::kScrollXMin:
- result += " scroll_x_min=" + value;
- break;
- case ax::mojom::IntAttribute::kScrollXMax:
- result += " scroll_x_max=" + value;
- break;
- case ax::mojom::IntAttribute::kScrollY:
- result += " scroll_y=" + value;
- break;
- case ax::mojom::IntAttribute::kScrollYMin:
- result += " scroll_y_min=" + value;
- break;
- case ax::mojom::IntAttribute::kScrollYMax:
- result += " scroll_y_max=" + value;
- break;
- case ax::mojom::IntAttribute::kHierarchicalLevel:
- result += " level=" + value;
- break;
- case ax::mojom::IntAttribute::kTextSelStart:
- result += " sel_start=" + value;
- break;
- case ax::mojom::IntAttribute::kTextSelEnd:
- result += " sel_end=" + value;
- break;
- case ax::mojom::IntAttribute::kAriaColumnCount:
- result += " aria_column_count=" + value;
- break;
- case ax::mojom::IntAttribute::kAriaCellColumnIndex:
- result += " aria_cell_column_index=" + value;
- break;
- case ax::mojom::IntAttribute::kAriaCellColumnSpan:
- result += " aria_cell_column_span=" + value;
- break;
- case ax::mojom::IntAttribute::kAriaRowCount:
- result += " aria_row_count=" + value;
- break;
- case ax::mojom::IntAttribute::kAriaCellRowIndex:
- result += " aria_cell_row_index=" + value;
- break;
- case ax::mojom::IntAttribute::kAriaCellRowSpan:
- result += " aria_cell_row_span=" + value;
- break;
- case ax::mojom::IntAttribute::kTableRowCount:
- result += " rows=" + value;
- break;
- case ax::mojom::IntAttribute::kTableColumnCount:
- result += " cols=" + value;
- break;
- case ax::mojom::IntAttribute::kTableCellColumnIndex:
- result += " col=" + value;
- break;
- case ax::mojom::IntAttribute::kTableCellRowIndex:
- result += " row=" + value;
- break;
- case ax::mojom::IntAttribute::kTableCellColumnSpan:
- result += " colspan=" + value;
- break;
- case ax::mojom::IntAttribute::kTableCellRowSpan:
- result += " rowspan=" + value;
- break;
- case ax::mojom::IntAttribute::kTableColumnHeaderId:
- result += " column_header_id=" + value;
- break;
- case ax::mojom::IntAttribute::kTableColumnIndex:
- result += " column_index=" + value;
- break;
- case ax::mojom::IntAttribute::kTableHeaderId:
- result += " header_id=" + value;
- break;
- case ax::mojom::IntAttribute::kTableRowHeaderId:
- result += " row_header_id=" + value;
- break;
- case ax::mojom::IntAttribute::kTableRowIndex:
- result += " row_index=" + value;
- break;
- case ax::mojom::IntAttribute::kSortDirection:
- switch (static_cast<ax::mojom::SortDirection>(int_attribute.second)) {
- case ax::mojom::SortDirection::kUnsorted:
- result += " sort_direction=none";
- break;
- case ax::mojom::SortDirection::kAscending:
- result += " sort_direction=ascending";
- break;
- case ax::mojom::SortDirection::kDescending:
- result += " sort_direction=descending";
- break;
- case ax::mojom::SortDirection::kOther:
- result += " sort_direction=other";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kNameFrom:
- result += " name_from=";
- result += ui::ToString(
- static_cast<ax::mojom::NameFrom>(int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kDescriptionFrom:
- result += " description_from=";
- result += ui::ToString(
- static_cast<ax::mojom::DescriptionFrom>(int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kActivedescendantId:
- result += " activedescendant=" + value;
- break;
- case ax::mojom::IntAttribute::kErrormessageId:
- result += " errormessage=" + value;
- break;
- case ax::mojom::IntAttribute::kInPageLinkTargetId:
- result += " in_page_link_target_id=" + value;
- break;
- case ax::mojom::IntAttribute::kMemberOfId:
- result += " member_of_id=" + value;
- break;
- case ax::mojom::IntAttribute::kNextOnLineId:
- result += " next_on_line_id=" + value;
- break;
- case ax::mojom::IntAttribute::kPopupForId:
- result += " popup_for_id=" + value;
- break;
- case ax::mojom::IntAttribute::kPreviousOnLineId:
- result += " previous_on_line_id=" + value;
- break;
- case ax::mojom::IntAttribute::kColorValue:
- result += base::StringPrintf(" color_value=&%X", int_attribute.second);
- break;
- case ax::mojom::IntAttribute::kAriaCurrentState:
- switch (
- static_cast<ax::mojom::AriaCurrentState>(int_attribute.second)) {
- case ax::mojom::AriaCurrentState::kFalse:
- result += " aria_current_state=false";
- break;
- case ax::mojom::AriaCurrentState::kTrue:
- result += " aria_current_state=true";
- break;
- case ax::mojom::AriaCurrentState::kPage:
- result += " aria_current_state=page";
- break;
- case ax::mojom::AriaCurrentState::kStep:
- result += " aria_current_state=step";
- break;
- case ax::mojom::AriaCurrentState::kLocation:
- result += " aria_current_state=location";
- break;
- case ax::mojom::AriaCurrentState::kDate:
- result += " aria_current_state=date";
- break;
- case ax::mojom::AriaCurrentState::kTime:
- result += " aria_current_state=time";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kBackgroundColor:
- result +=
- base::StringPrintf(" background_color=&%X", int_attribute.second);
- break;
- case ax::mojom::IntAttribute::kColor:
- result += base::StringPrintf(" color=&%X", int_attribute.second);
- break;
- case ax::mojom::IntAttribute::kListStyle:
- switch (static_cast<ax::mojom::ListStyle>(int_attribute.second)) {
- case ax::mojom::ListStyle::kCircle:
- result += " list_style=circle";
- break;
- case ax::mojom::ListStyle::kDisc:
- result += " list_style=disc";
- break;
- case ax::mojom::ListStyle::kImage:
- result += " list_style=image";
- break;
- case ax::mojom::ListStyle::kNumeric:
- result += " list_style=numeric";
- break;
- case ax::mojom::ListStyle::kOther:
- result += " list_style=other";
- break;
- case ax::mojom::ListStyle::kSquare:
- result += " list_style=square";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kTextAlign:
- result += " text_align=";
- result += ui::ToString(
- static_cast<ax::mojom::TextAlign>(int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kTextDirection:
- switch (
- static_cast<ax::mojom::WritingDirection>(int_attribute.second)) {
- case ax::mojom::WritingDirection::kLtr:
- result += " text_direction=ltr";
- break;
- case ax::mojom::WritingDirection::kRtl:
- result += " text_direction=rtl";
- break;
- case ax::mojom::WritingDirection::kTtb:
- result += " text_direction=ttb";
- break;
- case ax::mojom::WritingDirection::kBtt:
- result += " text_direction=btt";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kTextPosition:
- switch (static_cast<ax::mojom::TextPosition>(int_attribute.second)) {
- case ax::mojom::TextPosition::kNone:
- result += " text_position=none";
- break;
- case ax::mojom::TextPosition::kSubscript:
- result += " text_position=subscript";
- break;
- case ax::mojom::TextPosition::kSuperscript:
- result += " text_position=superscript";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kTextStyle: {
- std::string text_style_value;
- if (HasTextStyle(ax::mojom::TextStyle::kBold))
- text_style_value += "bold,";
- if (HasTextStyle(ax::mojom::TextStyle::kItalic))
- text_style_value += "italic,";
- if (HasTextStyle(ax::mojom::TextStyle::kUnderline))
- text_style_value += "underline,";
- if (HasTextStyle(ax::mojom::TextStyle::kLineThrough))
- text_style_value += "line-through,";
- if (HasTextStyle(ax::mojom::TextStyle::kOverline))
- text_style_value += "overline,";
- result += text_style_value.substr(0, text_style_value.size() - 1);
- break;
- }
- case ax::mojom::IntAttribute::kTextOverlineStyle:
- result += std::string(" text_overline_style=") +
- ui::ToString(static_cast<ax::mojom::TextDecorationStyle>(
- int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kTextStrikethroughStyle:
- result += std::string(" text_strikethrough_style=") +
- ui::ToString(static_cast<ax::mojom::TextDecorationStyle>(
- int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kTextUnderlineStyle:
- result += std::string(" text_underline_style=") +
- ui::ToString(static_cast<ax::mojom::TextDecorationStyle>(
- int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kSetSize:
- result += " setsize=" + value;
- break;
- case ax::mojom::IntAttribute::kPosInSet:
- result += " posinset=" + value;
- break;
- case ax::mojom::IntAttribute::kHasPopup:
- switch (static_cast<ax::mojom::HasPopup>(int_attribute.second)) {
- case ax::mojom::HasPopup::kTrue:
- result += " haspopup=true";
- break;
- case ax::mojom::HasPopup::kMenu:
- result += " haspopup=menu";
- break;
- case ax::mojom::HasPopup::kListbox:
- result += " haspopup=listbox";
- break;
- case ax::mojom::HasPopup::kTree:
- result += " haspopup=tree";
- break;
- case ax::mojom::HasPopup::kGrid:
- result += " haspopup=grid";
- break;
- case ax::mojom::HasPopup::kDialog:
- result += " haspopup=dialog";
- break;
- case ax::mojom::HasPopup::kFalse:
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kInvalidState:
- switch (static_cast<ax::mojom::InvalidState>(int_attribute.second)) {
- case ax::mojom::InvalidState::kFalse:
- result += " invalid_state=false";
- break;
- case ax::mojom::InvalidState::kTrue:
- result += " invalid_state=true";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kCheckedState:
- switch (static_cast<ax::mojom::CheckedState>(int_attribute.second)) {
- case ax::mojom::CheckedState::kFalse:
- result += " checked_state=false";
- break;
- case ax::mojom::CheckedState::kTrue:
- result += " checked_state=true";
- break;
- case ax::mojom::CheckedState::kMixed:
- result += " checked_state=mixed";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kRestriction:
- switch (static_cast<ax::mojom::Restriction>(int_attribute.second)) {
- case ax::mojom::Restriction::kReadOnly:
- result += " restriction=readonly";
- break;
- case ax::mojom::Restriction::kDisabled:
- result += " restriction=disabled";
- break;
- default:
- break;
- }
- break;
- case ax::mojom::IntAttribute::kNextFocusId:
- result += " next_focus_id=" + value;
- break;
- case ax::mojom::IntAttribute::kPreviousFocusId:
- result += " previous_focus_id=" + value;
- break;
- case ax::mojom::IntAttribute::kImageAnnotationStatus:
- result += std::string(" image_annotation_status=") +
- ui::ToString(static_cast<ax::mojom::ImageAnnotationStatus>(
- int_attribute.second));
- break;
- case ax::mojom::IntAttribute::kDropeffect:
- result += " dropeffect=" + value;
- break;
- case ax::mojom::IntAttribute::kDOMNodeId:
- result += " dom_node_id=" + value;
- break;
- case ax::mojom::IntAttribute::kNone:
- break;
- }
- }
- for (const std::pair<ax::mojom::StringAttribute, std::string>&
- string_attribute : string_attributes) {
- std::string value = string_attribute.second;
- switch (string_attribute.first) {
- case ax::mojom::StringAttribute::kAccessKey:
- result += " access_key=" + value;
- break;
- case ax::mojom::StringAttribute::kAriaInvalidValue:
- result += " aria_invalid_value=" + value;
- break;
- case ax::mojom::StringAttribute::kCheckedStateDescription:
- result += " checked_state_description=" + value;
- break;
- case ax::mojom::StringAttribute::kAutoComplete:
- result += " autocomplete=" + value;
- break;
- case ax::mojom::StringAttribute::kChildTreeId:
- result += " child_tree_id=" + value.substr(0, 8);
- break;
- case ax::mojom::StringAttribute::kChildTreeNodeAppId:
- result += " child_tree_node_app_id=" + value.substr(0, 8);
- break;
- case ax::mojom::StringAttribute::kClassName:
- result += " class_name=" + value;
- break;
- case ax::mojom::StringAttribute::kDescription:
- result += " description=" + value;
- break;
- case ax::mojom::StringAttribute::kDisplay:
- result += " display=" + value;
- break;
- case ax::mojom::StringAttribute::kFontFamily:
- result += " font-family=" + value;
- break;
- case ax::mojom::StringAttribute::kHtmlTag:
- result += " html_tag=" + value;
- break;
- case ax::mojom::StringAttribute::kImageAnnotation:
- result += " image_annotation=" + value;
- break;
- case ax::mojom::StringAttribute::kImageDataUrl:
- result += " image_data_url=(" +
- base::NumberToString(static_cast<int>(value.size())) +
- " bytes)";
- break;
- case ax::mojom::StringAttribute::kInnerHtml:
- result += " inner_html=" + value;
- break;
- case ax::mojom::StringAttribute::kInputType:
- result += " input_type=" + value;
- break;
- case ax::mojom::StringAttribute::kKeyShortcuts:
- result += " key_shortcuts=" + value;
- break;
- case ax::mojom::StringAttribute::kLanguage:
- result += " language=" + value;
- break;
- case ax::mojom::StringAttribute::kLiveRelevant:
- result += " relevant=" + value;
- break;
- case ax::mojom::StringAttribute::kLiveStatus:
- result += " live=" + value;
- break;
- case ax::mojom::StringAttribute::kContainerLiveRelevant:
- result += " container_relevant=" + value;
- break;
- case ax::mojom::StringAttribute::kContainerLiveStatus:
- result += " container_live=" + value;
- break;
- case ax::mojom::StringAttribute::kAppId:
- result += " app_id=" + value.substr(0, 8);
- break;
- case ax::mojom::StringAttribute::kPlaceholder:
- result += " placeholder=" + value;
- break;
- case ax::mojom::StringAttribute::kRole:
- result += " role=" + value;
- break;
- case ax::mojom::StringAttribute::kRoleDescription:
- result += " role_description=" + value;
- break;
- case ax::mojom::StringAttribute::kTooltip:
- result += " tooltip=" + value;
- break;
- case ax::mojom::StringAttribute::kUrl:
- result += " url=" + value;
- break;
- case ax::mojom::StringAttribute::kName:
- result += " name=" + value;
- break;
- case ax::mojom::StringAttribute::kValue:
- result += " value=" + value;
- break;
- case ax::mojom::StringAttribute::kVirtualContent:
- result += " virtual_content=" + value;
- break;
- case ax::mojom::StringAttribute::kNone:
- break;
- }
- }
- for (const std::pair<ax::mojom::FloatAttribute, float>& float_attribute :
- float_attributes) {
- std::string value = base::NumberToString(float_attribute.second);
- switch (float_attribute.first) {
- case ax::mojom::FloatAttribute::kValueForRange:
- result += " value_for_range=" + value;
- break;
- case ax::mojom::FloatAttribute::kMaxValueForRange:
- result += " max_value=" + value;
- break;
- case ax::mojom::FloatAttribute::kMinValueForRange:
- result += " min_value=" + value;
- break;
- case ax::mojom::FloatAttribute::kStepValueForRange:
- result += " step_value=" + value;
- break;
- case ax::mojom::FloatAttribute::kFontSize:
- result += " font_size=" + value;
- break;
- case ax::mojom::FloatAttribute::kFontWeight:
- result += " font_weight=" + value;
- break;
- case ax::mojom::FloatAttribute::kTextIndent:
- result += " text_indent=" + value;
- break;
- case ax::mojom::FloatAttribute::kChildTreeScale:
- result += " child_tree_scale=" + value;
- break;
- case ax::mojom::FloatAttribute::kNone:
- break;
- }
- }
- for (const std::pair<ax::mojom::BoolAttribute, bool>& bool_attribute :
- bool_attributes) {
- std::string value = bool_attribute.second ? "true" : "false";
- switch (bool_attribute.first) {
- case ax::mojom::BoolAttribute::kNonAtomicTextFieldRoot:
- result += " non_atomic_text_field_root=" + value;
- break;
- case ax::mojom::BoolAttribute::kLiveAtomic:
- result += " atomic=" + value;
- break;
- case ax::mojom::BoolAttribute::kBusy:
- result += " busy=" + value;
- break;
- case ax::mojom::BoolAttribute::kContainerLiveAtomic:
- result += " container_atomic=" + value;
- break;
- case ax::mojom::BoolAttribute::kContainerLiveBusy:
- result += " container_busy=" + value;
- break;
- case ax::mojom::BoolAttribute::kUpdateLocationOnly:
- result += " update_location_only=" + value;
- break;
- case ax::mojom::BoolAttribute::kCanvasHasFallback:
- result += " has_fallback=" + value;
- break;
- case ax::mojom::BoolAttribute::kModal:
- result += " modal=" + value;
- break;
- case ax::mojom::BoolAttribute::kScrollable:
- result += " scrollable=" + value;
- break;
- case ax::mojom::BoolAttribute::kClickable:
- result += " clickable=" + value;
- break;
- case ax::mojom::BoolAttribute::kClipsChildren:
- result += " clips_children=" + value;
- break;
- case ax::mojom::BoolAttribute::kNotUserSelectableStyle:
- result += " not_user_selectable=" + value;
- break;
- case ax::mojom::BoolAttribute::kSelected:
- result += " selected=" + value;
- break;
- case ax::mojom::BoolAttribute::kSelectedFromFocus:
- result += " selected_from_focus=" + value;
- break;
- case ax::mojom::BoolAttribute::kSupportsTextLocation:
- result += " supports_text_location=" + value;
- break;
- case ax::mojom::BoolAttribute::kGrabbed:
- result += " grabbed=" + value;
- break;
- case ax::mojom::BoolAttribute::kIsLineBreakingObject:
- result += " is_line_breaking_object=" + value;
- break;
- case ax::mojom::BoolAttribute::kIsPageBreakingObject:
- result += " is_page_breaking_object=" + value;
- break;
- case ax::mojom::BoolAttribute::kHasAriaAttribute:
- result += " has_aria_attribute=" + value;
- break;
- case ax::mojom::BoolAttribute::kTouchPassthrough:
- result += " touch_passthrough=" + value;
- break;
- case ax::mojom::BoolAttribute::kNone:
- break;
- }
- }
- for (const std::pair<ax::mojom::IntListAttribute, std::vector<int32_t>>&
- intlist_attribute : intlist_attributes) {
- const std::vector<int32_t>& values = intlist_attribute.second;
- switch (intlist_attribute.first) {
- case ax::mojom::IntListAttribute::kNone:
- break;
- case ax::mojom::IntListAttribute::kIndirectChildIds:
- result += " indirect_child_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kControlsIds:
- result += " controls_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kDetailsIds:
- result += " details_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kDescribedbyIds:
- result += " describedby_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kFlowtoIds:
- result += " flowto_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kLabelledbyIds:
- result += " labelledby_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kRadioGroupIds:
- result += " radio_group_ids=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kMarkerTypes: {
- std::string types_str = VectorToString(values, [](const int32_t type) {
- std::string type_str;
- if (type == static_cast<int32_t>(ax::mojom::MarkerType::kNone))
- return type_str;
- if (type & static_cast<int32_t>(ax::mojom::MarkerType::kSpelling))
- type_str += "spelling&";
- if (type & static_cast<int32_t>(ax::mojom::MarkerType::kGrammar))
- type_str += "grammar&";
- if (type & static_cast<int32_t>(ax::mojom::MarkerType::kHighlight))
- type_str += "highlight&";
- if (type & static_cast<int32_t>(ax::mojom::MarkerType::kTextMatch))
- type_str += "text_match&";
- if (type &
- static_cast<int32_t>(ax::mojom::MarkerType::kActiveSuggestion))
- type_str += "active_suggestion&";
- if (type & static_cast<int32_t>(ax::mojom::MarkerType::kSuggestion))
- type_str += "suggestion&";
- return type_str;
- });
- if (!types_str.empty()) {
- types_str = types_str.substr(0, types_str.size() - 1);
- result += " marker_types=" + types_str;
- }
- break;
- }
- case ax::mojom::IntListAttribute::kMarkerStarts:
- result += " marker_starts=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kMarkerEnds:
- result += " marker_ends=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kHighlightTypes: {
- std::string highlight_types_str =
- VectorToString(values, [](const int32_t highlight_type) {
- if (static_cast<ax::mojom::HighlightType>(highlight_type) ==
- ax::mojom::HighlightType::kNone)
- return "";
- return ui::ToString(
- static_cast<ax::mojom::HighlightType>(highlight_type));
- });
- if (!highlight_types_str.empty())
- result += " highlight_types=" + highlight_types_str;
- break;
- }
- case ax::mojom::IntListAttribute::kCaretBounds:
- result += " caret_bounds=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kCharacterOffsets:
- result += " character_offsets=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kLineStarts:
- result += " line_start_offsets=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kLineEnds:
- result += " line_end_offsets=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kSentenceStarts:
- result += " sentence_start_offsets=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kSentenceEnds:
- result += " sentence_end_offsets=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kWordStarts:
- result += " word_starts=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kWordEnds:
- result += " word_ends=" + IntVectorToString(values);
- break;
- case ax::mojom::IntListAttribute::kCustomActionIds:
- result += " custom_action_ids=" + IntVectorToString(values);
- break;
- }
- }
- for (const std::pair<ax::mojom::StringListAttribute,
- std::vector<std::string>>& stringlist_attribute :
- stringlist_attributes) {
- const std::vector<std::string>& values = stringlist_attribute.second;
- switch (stringlist_attribute.first) {
- case ax::mojom::StringListAttribute::kCustomActionDescriptions:
- result +=
- " custom_action_descriptions: " + base::JoinString(values, ",");
- break;
- case ax::mojom::StringListAttribute::kNone:
- break;
- }
- }
- for (const std::pair<std::string, std::string>& string_pair :
- html_attributes) {
- result += " " + string_pair.first + "=" + string_pair.second;
- }
- if (actions)
- result += " actions=" + ActionsBitfieldToString(actions);
- if (!child_ids.empty())
- result += " child_ids=" + IntVectorToString(child_ids);
- return result;
- }
- std::string AXNodeData::DropeffectBitfieldToString() const {
- if (!HasIntAttribute(ax::mojom::IntAttribute::kDropeffect))
- return "";
- std::string str;
- for (int dropeffect_idx = static_cast<int>(ax::mojom::Dropeffect::kMinValue);
- dropeffect_idx <= static_cast<int>(ax::mojom::Dropeffect::kMaxValue);
- ++dropeffect_idx) {
- ax::mojom::Dropeffect dropeffect_enum =
- static_cast<ax::mojom::Dropeffect>(dropeffect_idx);
- if (HasDropeffect(dropeffect_enum))
- str += " " + std::string(ui::ToString(dropeffect_enum));
- }
- // Removing leading space in final string.
- return str.substr(1);
- }
- } // namespace ui
|