Commit 40d1f8a3 authored by Saho Kobayashi's avatar Saho Kobayashi Committed by Commit Bot

Send kValue changed triggered by state description.

Send kValue changed event when state description change event of range
widget is sent.
CL to set kValue when state description of range widget is sent:
CL:2224487

      AXTreeSourceArcTest.StateDescriptionChangedEvent

Bug: b:154433831
Test: ArcAccessibilityUtilTest.FromContentChangeTypesToAXEvent
Change-Id: Iea60accbc90a6aa04bdb1b9644ab623c9a8acc28
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2251518
Commit-Queue: Saho Kobayashi <sahok@chromium.org>
Reviewed-by: default avatarSara Kato <sarakato@chromium.org>
Reviewed-by: default avatarHiroki Sato <hirokisato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#781239}
parent f3789aa9
...@@ -2873,6 +2873,7 @@ source_set("unit_tests") { ...@@ -2873,6 +2873,7 @@ source_set("unit_tests") {
"apps/intent_helper/chromeos_apps_navigation_throttle_unittest.cc", "apps/intent_helper/chromeos_apps_navigation_throttle_unittest.cc",
"apps/metrics/intent_handling_metrics_unittest.cc", "apps/metrics/intent_handling_metrics_unittest.cc",
"arc/accessibility/arc_accessibility_helper_bridge_unittest.cc", "arc/accessibility/arc_accessibility_helper_bridge_unittest.cc",
"arc/accessibility/arc_accessibility_util_unittest.cc",
"arc/accessibility/ax_tree_source_arc_unittest.cc", "arc/accessibility/ax_tree_source_arc_unittest.cc",
"arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc", "arc/app_shortcuts/arc_app_shortcuts_menu_builder_unittest.cc",
"arc/app_shortcuts/arc_app_shortcuts_request_unittest.cc", "arc/app_shortcuts/arc_app_shortcuts_request_unittest.cc",
......
...@@ -5,14 +5,39 @@ ...@@ -5,14 +5,39 @@
#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h" #include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h"
#include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h" #include "chrome/browser/chromeos/arc/accessibility/accessibility_info_data_wrapper.h"
#include "base/optional.h"
#include "components/arc/mojom/accessibility_helper.mojom.h" #include "components/arc/mojom/accessibility_helper.mojom.h"
#include "ui/accessibility/ax_enums.mojom.h" #include "ui/accessibility/ax_enums.mojom.h"
namespace arc { namespace arc {
ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type, using AXActionType = mojom::AccessibilityActionType;
AccessibilityInfoDataWrapper* source_node, using AXBooleanProperty = mojom::AccessibilityBooleanProperty;
AccessibilityInfoDataWrapper* focused_node) { using AXIntListProperty = mojom::AccessibilityIntListProperty;
using AXNodeInfoData = mojom::AccessibilityNodeInfoData;
using AXStringProperty = mojom::AccessibilityStringProperty;
base::Optional<ax::mojom::Event> FromContentChangeTypesToAXEvent(
const std::vector<int32_t>& arc_content_change_types,
const AccessibilityInfoDataWrapper& source_node) {
if (!base::Contains(
arc_content_change_types,
static_cast<int32_t>(mojom::ContentChangeType::STATE_DESCRIPTION))) {
return base::nullopt;
}
const AXNodeInfoData* node_ptr = source_node.GetNode();
if (node_ptr && node_ptr->range_info) {
return ax::mojom::Event::kValueChanged;
} else {
return base::nullopt;
}
}
ax::mojom::Event ToAXEvent(
mojom::AccessibilityEventType arc_event_type,
const base::Optional<std::vector<int>>& arc_content_change_types,
AccessibilityInfoDataWrapper* source_node,
AccessibilityInfoDataWrapper* focused_node) {
switch (arc_event_type) { switch (arc_event_type) {
case mojom::AccessibilityEventType::VIEW_FOCUSED: case mojom::AccessibilityEventType::VIEW_FOCUSED:
case mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED: case mojom::AccessibilityEventType::VIEW_ACCESSIBILITY_FOCUSED:
...@@ -25,13 +50,35 @@ ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type, ...@@ -25,13 +50,35 @@ ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type,
case mojom::AccessibilityEventType::VIEW_TEXT_SELECTION_CHANGED: case mojom::AccessibilityEventType::VIEW_TEXT_SELECTION_CHANGED:
return ax::mojom::Event::kTextSelectionChanged; return ax::mojom::Event::kTextSelectionChanged;
case mojom::AccessibilityEventType::WINDOW_STATE_CHANGED: { case mojom::AccessibilityEventType::WINDOW_STATE_CHANGED: {
if (arc_content_change_types.has_value()) {
DCHECK(source_node); // Should be not null because it's dropped in
// Android side.
const base::Optional<ax::mojom::Event> event_or_null =
FromContentChangeTypesToAXEvent(arc_content_change_types.value(),
*source_node);
if (event_or_null.has_value()) {
return event_or_null.value();
}
}
if (focused_node) if (focused_node)
return ax::mojom::Event::kFocus; return ax::mojom::Event::kFocus;
else else
return ax::mojom::Event::kLayoutComplete; return ax::mojom::Event::kLayoutComplete;
} }
case mojom::AccessibilityEventType::NOTIFICATION_STATE_CHANGED: case mojom::AccessibilityEventType::NOTIFICATION_STATE_CHANGED:
return ax::mojom::Event::kLayoutComplete;
case mojom::AccessibilityEventType::WINDOW_CONTENT_CHANGED: case mojom::AccessibilityEventType::WINDOW_CONTENT_CHANGED:
if (arc_content_change_types.has_value()) {
DCHECK(source_node); // Should be not null because it's dropped in
// Android side.
const base::Optional<ax::mojom::Event> event_or_null =
FromContentChangeTypesToAXEvent(arc_content_change_types.value(),
*source_node);
if (event_or_null.has_value()) {
return event_or_null.value();
}
}
return ax::mojom::Event::kLayoutComplete;
case mojom::AccessibilityEventType::WINDOWS_CHANGED: case mojom::AccessibilityEventType::WINDOWS_CHANGED:
return ax::mojom::Event::kLayoutComplete; return ax::mojom::Event::kLayoutComplete;
case mojom::AccessibilityEventType::VIEW_HOVER_ENTER: case mojom::AccessibilityEventType::VIEW_HOVER_ENTER:
......
...@@ -9,16 +9,22 @@ ...@@ -9,16 +9,22 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/containers/flat_map.h"
#include "base/optional.h" #include "base/optional.h"
#include "components/arc/mojom/accessibility_helper.mojom-forward.h" #include "components/arc/mojom/accessibility_helper.mojom-forward.h"
#include "ui/accessibility/ax_enum_util.h" #include "ui/accessibility/ax_enum_util.h"
namespace arc { namespace arc {
class AccessibilityInfoDataWrapper; class AccessibilityInfoDataWrapper;
base::Optional<ax::mojom::Event> FromContentChangeTypesToAXEvent(
const std::vector<int>& arc_content_change_types,
const AccessibilityInfoDataWrapper& source_node);
ax::mojom::Event ToAXEvent(mojom::AccessibilityEventType arc_event_type, ax::mojom::Event ToAXEvent(
AccessibilityInfoDataWrapper* source_node, mojom::AccessibilityEventType arc_event_type,
AccessibilityInfoDataWrapper* focused_node); const base::Optional<std::vector<int>>& arc_content_change_types,
AccessibilityInfoDataWrapper* source_node,
AccessibilityInfoDataWrapper* focused_node);
base::Optional<mojom::AccessibilityActionType> ConvertToAndroidAction( base::Optional<mojom::AccessibilityActionType> ConvertToAndroidAction(
ax::mojom::Action action); ax::mojom::Action action);
...@@ -38,7 +44,7 @@ bool GetBooleanProperty(DataType* node, PropType prop) { ...@@ -38,7 +44,7 @@ bool GetBooleanProperty(DataType* node, PropType prop) {
} }
template <class PropMTypeMap, class PropType> template <class PropMTypeMap, class PropType>
bool HasProperty(PropMTypeMap properties, PropType prop) { bool HasProperty(const PropMTypeMap& properties, const PropType prop) {
if (!properties) if (!properties)
return false; return false;
...@@ -46,7 +52,9 @@ bool HasProperty(PropMTypeMap properties, PropType prop) { ...@@ -46,7 +52,9 @@ bool HasProperty(PropMTypeMap properties, PropType prop) {
} }
template <class PropMTypeMap, class PropType, class OutType> template <class PropMTypeMap, class PropType, class OutType>
bool GetProperty(PropMTypeMap properties, PropType prop, OutType* out_value) { bool GetProperty(const PropMTypeMap& properties,
const PropType prop,
OutType* out_value) {
if (!properties) if (!properties)
return false; return false;
...@@ -58,6 +66,16 @@ bool GetProperty(PropMTypeMap properties, PropType prop, OutType* out_value) { ...@@ -58,6 +66,16 @@ bool GetProperty(PropMTypeMap properties, PropType prop, OutType* out_value) {
return true; return true;
} }
template <class PropType, class OutType>
base::Optional<OutType> GetPropertyOrNull(
const base::Optional<base::flat_map<PropType, OutType>>& properties,
const PropType prop) {
OutType out_value;
if (GetProperty(properties, prop, &out_value))
return out_value;
return base::nullopt;
}
template <class InfoDataType, class PropType> template <class InfoDataType, class PropType>
bool HasNonEmptyStringProperty(InfoDataType* node, PropType prop) { bool HasNonEmptyStringProperty(InfoDataType* node, PropType prop) {
if (!node || !node->string_properties) if (!node || !node->string_properties)
......
// Copyright 2020 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 <memory>
#include "base/optional.h"
#include "chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h"
#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h"
#include "components/arc/mojom/accessibility_helper.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_enums.mojom.h"
namespace arc {
using AXEventType = mojom::AccessibilityEventType;
using AXNodeInfoData = mojom::AccessibilityNodeInfoData;
using AXRangeInfoData = mojom::AccessibilityRangeInfoData;
TEST(ArcAccessibilityUtilTest, FromContentChangeTypesToAXEvent) {
auto range_widget = AXNodeInfoData::New();
range_widget->range_info = AXRangeInfoData::New();
AccessibilityNodeInfoDataWrapper source_node_range(nullptr,
range_widget.get());
auto not_range_widget = AXNodeInfoData::New();
AccessibilityNodeInfoDataWrapper source_node_not_range(
nullptr, not_range_widget.get());
std::vector<int32_t> empty_list = {};
EXPECT_EQ(base::nullopt,
FromContentChangeTypesToAXEvent(empty_list, source_node_range));
EXPECT_EQ(base::nullopt,
FromContentChangeTypesToAXEvent(empty_list, source_node_not_range));
std::vector<int32_t> state_description = {
static_cast<int32_t>(mojom::ContentChangeType::STATE_DESCRIPTION)};
// TODO(sahok): add test when source_node is not a range widget.
EXPECT_EQ(
ax::mojom::Event::kValueChanged,
FromContentChangeTypesToAXEvent(state_description, source_node_range));
EXPECT_EQ(ax::mojom::Event::kValueChanged,
ToAXEvent(AXEventType::WINDOW_STATE_CHANGED, state_description,
&source_node_range, &source_node_range));
EXPECT_EQ(ax::mojom::Event::kValueChanged,
ToAXEvent(AXEventType::WINDOW_CONTENT_CHANGED, state_description,
&source_node_range, &source_node_range));
std::vector<int32_t> without_state_description = {
static_cast<int32_t>(mojom::ContentChangeType::TEXT)};
EXPECT_EQ(base::nullopt, FromContentChangeTypesToAXEvent(
without_state_description, source_node_range));
EXPECT_EQ(base::nullopt,
FromContentChangeTypesToAXEvent(without_state_description,
source_node_not_range));
std::vector<int32_t> include_state_description = {
static_cast<int32_t>(mojom::ContentChangeType::TEXT),
static_cast<int32_t>(mojom::ContentChangeType::STATE_DESCRIPTION)};
// TODO(sahok): add test when source_node is not a range widget.
EXPECT_EQ(ax::mojom::Event::kValueChanged,
FromContentChangeTypesToAXEvent(include_state_description,
source_node_range));
EXPECT_EQ(
ax::mojom::Event::kValueChanged,
ToAXEvent(AXEventType::WINDOW_STATE_CHANGED, include_state_description,
&source_node_range, &source_node_range));
EXPECT_EQ(
ax::mojom::Event::kValueChanged,
ToAXEvent(AXEventType::WINDOW_CONTENT_CHANGED, include_state_description,
&source_node_range, &source_node_range));
std::vector<int32_t> not_enum_value = {111};
EXPECT_EQ(base::nullopt,
FromContentChangeTypesToAXEvent(not_enum_value, source_node_range));
EXPECT_EQ(base::nullopt, FromContentChangeTypesToAXEvent(
not_enum_value, source_node_not_range));
}
} // namespace arc
...@@ -23,6 +23,7 @@ namespace arc { ...@@ -23,6 +23,7 @@ namespace arc {
using AXBooleanProperty = mojom::AccessibilityBooleanProperty; using AXBooleanProperty = mojom::AccessibilityBooleanProperty;
using AXEventData = mojom::AccessibilityEventData; using AXEventData = mojom::AccessibilityEventData;
using AXEventIntListProperty = mojom::AccessibilityEventIntListProperty;
using AXEventIntProperty = mojom::AccessibilityEventIntProperty; using AXEventIntProperty = mojom::AccessibilityEventIntProperty;
using AXEventType = mojom::AccessibilityEventType; using AXEventType = mojom::AccessibilityEventType;
using AXIntProperty = mojom::AccessibilityIntProperty; using AXIntProperty = mojom::AccessibilityIntProperty;
...@@ -136,8 +137,12 @@ void AXTreeSourceArc::NotifyAccessibilityEvent(AXEventData* event_data) { ...@@ -136,8 +137,12 @@ void AXTreeSourceArc::NotifyAccessibilityEvent(AXEventData* event_data) {
: nullptr; : nullptr;
event_bundle.events.emplace_back(); event_bundle.events.emplace_back();
ui::AXEvent& event = event_bundle.events.back(); ui::AXEvent& event = event_bundle.events.back();
event.event_type = ToAXEvent(event_data->event_type, event.event_type = ToAXEvent(
GetFromId(event_data->source_id), focused_node); event_data->event_type,
GetPropertyOrNull(
event_data->int_list_properties,
arc::mojom::AccessibilityEventIntListProperty::CONTENT_CHANGE_TYPES),
GetFromId(event_data->source_id), focused_node);
event.id = event_data->source_id; event.id = event_data->source_id;
if (HasProperty(event_data->int_properties, if (HasProperty(event_data->int_properties,
......
...@@ -6,9 +6,11 @@ ...@@ -6,9 +6,11 @@
#include <utility> #include <utility>
#include "base/optional.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h" #include "chrome/browser/chromeos/arc/accessibility/accessibility_node_info_data_wrapper.h"
#include "chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h" #include "chrome/browser/chromeos/arc/accessibility/accessibility_window_info_data_wrapper.h"
#include "chrome/browser/chromeos/arc/accessibility/arc_accessibility_util.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "components/arc/mojom/accessibility_helper.mojom.h" #include "components/arc/mojom/accessibility_helper.mojom.h"
#include "extensions/browser/api/automation_internal/automation_event_router.h" #include "extensions/browser/api/automation_internal/automation_event_router.h"
...@@ -27,6 +29,7 @@ using AXBooleanProperty = mojom::AccessibilityBooleanProperty; ...@@ -27,6 +29,7 @@ using AXBooleanProperty = mojom::AccessibilityBooleanProperty;
using AXCollectionInfoData = mojom::AccessibilityCollectionInfoData; using AXCollectionInfoData = mojom::AccessibilityCollectionInfoData;
using AXCollectionItemInfoData = mojom::AccessibilityCollectionItemInfoData; using AXCollectionItemInfoData = mojom::AccessibilityCollectionItemInfoData;
using AXEventData = mojom::AccessibilityEventData; using AXEventData = mojom::AccessibilityEventData;
using AXEventIntListProperty = mojom::AccessibilityEventIntListProperty;
using AXEventIntProperty = mojom::AccessibilityEventIntProperty; using AXEventIntProperty = mojom::AccessibilityEventIntProperty;
using AXEventType = mojom::AccessibilityEventType; using AXEventType = mojom::AccessibilityEventType;
using AXIntListProperty = mojom::AccessibilityIntListProperty; using AXIntListProperty = mojom::AccessibilityIntListProperty;
...@@ -113,6 +116,18 @@ void SetProperty(AXEventData* event, AXEventIntProperty prop, int32_t value) { ...@@ -113,6 +116,18 @@ void SetProperty(AXEventData* event, AXEventIntProperty prop, int32_t value) {
prop_map.insert(std::make_pair(prop, value)); prop_map.insert(std::make_pair(prop, value));
} }
void SetProperty(AXEventData* event,
AXEventIntListProperty prop,
const std::vector<int>& value) {
if (!event->int_list_properties) {
event->int_list_properties =
base::flat_map<AXEventIntListProperty, std::vector<int>>();
}
auto& prop_map = event->int_list_properties.value();
base::EraseIf(prop_map, [prop](auto it) { return it.first == prop; });
prop_map.insert(std::make_pair(prop, value));
}
class MockAutomationEventRouter class MockAutomationEventRouter
: public extensions::AutomationEventRouterInterface { : public extensions::AutomationEventRouterInterface {
public: public:
...@@ -123,8 +138,10 @@ class MockAutomationEventRouter ...@@ -123,8 +138,10 @@ class MockAutomationEventRouter
void DispatchAccessibilityEvents( void DispatchAccessibilityEvents(
const ExtensionMsg_AccessibilityEventBundleParams& events) override { const ExtensionMsg_AccessibilityEventBundleParams& events) override {
for (auto&& event : events.events) for (auto&& event : events.events) {
event_count_[event.event_type]++; event_count_[event.event_type]++;
last_event_type_ = event.event_type;
}
for (const auto& update : events.updates) for (const auto& update : events.updates)
tree_.Unserialize(update); tree_.Unserialize(update);
...@@ -146,8 +163,13 @@ class MockAutomationEventRouter ...@@ -146,8 +163,13 @@ class MockAutomationEventRouter
const ui::AXActionData& data, const ui::AXActionData& data,
const base::Optional<gfx::Rect>& rect) override {} const base::Optional<gfx::Rect>& rect) override {}
ax::mojom::Event last_event_type() const { return last_event_type_; }
std::map<ax::mojom::Event, int> event_count_; std::map<ax::mojom::Event, int> event_count_;
ui::AXTree tree_; ui::AXTree tree_;
private:
ax::mojom::Event last_event_type_;
}; };
class AXTreeSourceArcTest : public testing::Test, class AXTreeSourceArcTest : public testing::Test,
...@@ -202,6 +224,10 @@ class AXTreeSourceArcTest : public testing::Test, ...@@ -202,6 +224,10 @@ class AXTreeSourceArcTest : public testing::Test,
return router_->event_count_[type]; return router_->event_count_[type];
} }
ax::mojom::Event last_dispatched_event_type() const {
return router_->last_event_type();
}
ui::AXTree* tree() { return router_->tree(); } ui::AXTree* tree() { return router_->tree(); }
void ExpectTree(const std::string& expected) { void ExpectTree(const std::string& expected) {
...@@ -1712,4 +1738,35 @@ TEST_F(AXTreeSourceArcTest, StateDescriptionWithRange) { ...@@ -1712,4 +1738,35 @@ TEST_F(AXTreeSourceArcTest, StateDescriptionWithRange) {
EXPECT_EQ("state description", value); EXPECT_EQ("state description", value);
} }
TEST_F(AXTreeSourceArcTest, StateDescriptionChangedEvent) {
auto event = AXEventData::New();
event->source_id = 10;
event->task_id = 1;
event->event_type = AXEventType::WINDOW_STATE_CHANGED;
event->window_data = std::vector<mojom::AccessibilityWindowInfoDataPtr>();
event->window_data->push_back(AXWindowInfoData::New());
AXWindowInfoData* root_window = event->window_data->back().get();
root_window->window_id = 100;
root_window->root_node_id = 10;
event->node_data.push_back(AXNodeInfoData::New());
AXNodeInfoData* range_widget = event->node_data.back().get();
range_widget->range_info = AXRangeInfoData::New();
range_widget->id = 10;
std::vector<int> content_change_types = {
static_cast<int>(mojom::ContentChangeType::TEXT),
static_cast<int>(mojom::ContentChangeType::STATE_DESCRIPTION)};
SetProperty(event.get(), AXEventIntListProperty::CONTENT_CHANGE_TYPES,
content_change_types);
CallNotifyAccessibilityEvent(event.get());
EXPECT_EQ(ax::mojom::Event::kValueChanged, last_dispatched_event_type());
event->event_type = AXEventType::WINDOW_CONTENT_CHANGED;
CallNotifyAccessibilityEvent(event.get());
EXPECT_EQ(ax::mojom::Event::kValueChanged, last_dispatched_event_type());
// TODO(sahok): add test when source_node is not a range widget.
}
} // namespace arc } // namespace arc
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment