Index: third_party/WebKit/Source/modules/accessibility/AXObject.cpp |
diff --git a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp |
index caf768238d37c02b1abc06aa43b4ef737e0959de..13e814bcc798bc1125474a1f3ea876939e50aea9 100644 |
--- a/third_party/WebKit/Source/modules/accessibility/AXObject.cpp |
+++ b/third_party/WebKit/Source/modules/accessibility/AXObject.cpp |
@@ -38,7 +38,9 @@ |
#include "core/frame/Settings.h" |
#include "core/html/HTMLDialogElement.h" |
#include "core/html/HTMLFrameOwnerElement.h" |
+#include "core/html/HTMLInputElement.h" |
#include "core/html/parser/HTMLParserIdioms.h" |
+#include "core/InputTypeNames.h" |
#include "core/layout/LayoutBoxModelObject.h" |
#include "modules/accessibility/AXObjectCacheImpl.h" |
#include "platform/UserGestureIndicator.h" |
@@ -391,6 +393,67 @@ bool AXObject::isButton() const { |
role == ToggleButtonRole; |
} |
+bool AXObject::isCheckable() const { |
+ switch (roleValue()) { |
+ case CheckBoxRole: |
+ case MenuItemCheckBoxRole: |
+ case MenuItemRadioRole: |
+ case RadioButtonRole: |
+ case SwitchRole: |
+ return true; |
+ default: |
+ return false; |
+ } |
+} |
+ |
+// Why this is here instead of AXNodeObject: |
+// Because an AXMenuListOption (<option>) can |
+// have an ARIA role of menuitemcheckbox/menuitemradio |
+// yet does not inherit from AXNodeObject |
+AccessibilityButtonState AXObject::checkedState() const { |
+ if (isCheckable() && hasAttribute(aria_checkedAttr)) { |
+ const AtomicString& checkedAttribute = getAttribute(aria_checkedAttr); |
+ if (equalIgnoringCase(checkedAttribute, "true")) |
+ return ButtonStateOn; |
+ |
+ if (equalIgnoringCase(checkedAttribute, "mixed")) { |
+ // Only checkboxes and radios should support the mixed state. |
+ const AccessibilityRole role = roleValue(); |
+ if (role == CheckBoxRole || role == MenuItemCheckBoxRole || |
+ role == RadioButtonRole || role == MenuItemRadioRole) |
+ return ButtonStateMixed; |
+ } |
+ |
+ return ButtonStateOff; |
+ } |
+ |
+ const Node* node = this->getNode(); |
+ if (!node) |
+ return ButtonStateOff; |
+ |
+ if (isNativeInputInMixedState(node)) |
+ return ButtonStateMixed; |
+ |
+ if (isHTMLInputElement(*node) && |
+ toHTMLInputElement(*node).shouldAppearChecked()) { |
+ return ButtonStateOn; |
+ } |
+ |
+ return ButtonStateOff; |
+} |
+ |
+bool AXObject::isNativeInputInMixedState(const Node* node) { |
+ if (!isHTMLInputElement(node)) |
+ return false; |
+ |
+ const HTMLInputElement* input = toHTMLInputElement(node); |
+ const auto inputType = input->type(); |
+ if (inputType != InputTypeNames::checkbox && |
+ inputType != InputTypeNames::radio) |
+ return false; |
+ return input->shouldAppearIndeterminate(); |
+} |
+ |
bool AXObject::isLandmarkRelated() const { |
switch (roleValue()) { |
case ApplicationRole: |
@@ -929,8 +992,9 @@ AXSupportedAction AXObject::action() const { |
return AXSupportedAction::Select; |
case CheckBoxRole: |
case SwitchRole: |
- return isChecked() ? AXSupportedAction::Check |
- : AXSupportedAction::Uncheck; |
+ return checkedState() == ButtonStateOff |
+ ? AXSupportedAction::Check |
+ : AXSupportedAction::Uncheck; |
case LinkRole: |
return AXSupportedAction::Jump; |
case PopUpButtonRole: |
@@ -940,21 +1004,6 @@ AXSupportedAction AXObject::action() const { |
} |
} |
-AccessibilityButtonState AXObject::checkboxOrRadioValue() const { |
- const AtomicString& checkedAttribute = getAttribute(aria_checkedAttr); |
- if (equalIgnoringCase(checkedAttribute, "true")) |
- return ButtonStateOn; |
- |
- if (equalIgnoringCase(checkedAttribute, "mixed")) { |
- // Only checkboxes should support the mixed state. |
- AccessibilityRole role = ariaRoleAttribute(); |
- if (role == CheckBoxRole || role == MenuItemCheckBoxRole) |
- return ButtonStateMixed; |
- } |
- |
- return ButtonStateOff; |
-} |
- |
bool AXObject::isMultiline() const { |
Node* node = this->getNode(); |
if (!node) |