OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/memory/ptr_util.h" | 5 #include "base/memory/ptr_util.h" |
6 #include "base/strings/utf_string_conversions.h" | 6 #include "base/strings/utf_string_conversions.h" |
7 #include "ui/accessibility/ax_node_data.h" | 7 #include "ui/accessibility/ax_node_data.h" |
8 #include "ui/gfx/geometry/rect_conversions.h" | 8 #include "ui/gfx/geometry/rect_conversions.h" |
9 #include "ui/views/accessibility/ax_aura_obj_cache.h" | 9 #include "ui/views/accessibility/ax_aura_obj_cache.h" |
10 #include "ui/views/accessibility/ax_aura_obj_wrapper.h" | 10 #include "ui/views/accessibility/ax_aura_obj_wrapper.h" |
11 #include "ui/views/accessibility/ax_widget_obj_wrapper.h" | 11 #include "ui/views/accessibility/ax_widget_obj_wrapper.h" |
12 #include "ui/views/accessibility/native_view_accessibility_base.h" | 12 #include "ui/views/accessibility/native_view_accessibility_base.h" |
13 #include "ui/views/controls/button/button.h" | 13 #include "ui/views/controls/button/button.h" |
14 #include "ui/views/controls/label.h" | 14 #include "ui/views/controls/label.h" |
15 #include "ui/views/test/views_test_base.h" | 15 #include "ui/views/test/views_test_base.h" |
| 16 #include "ui/views/widget/widget.h" |
16 | 17 |
17 namespace views { | 18 namespace views { |
18 namespace test { | 19 namespace test { |
19 | 20 |
20 class NativeViewAccessibilityTest; | 21 class NativeViewAccessibilityTest; |
21 | 22 |
22 namespace { | 23 namespace { |
23 | 24 |
24 class TestButton : public Button { | 25 class TestButton : public Button { |
25 public: | 26 public: |
26 TestButton() : Button(NULL) {} | 27 TestButton() : Button(NULL) {} |
27 }; | 28 }; |
28 | 29 |
29 } // namespace | 30 } // namespace |
30 | 31 |
31 class NativeViewAccessibilityTest : public ViewsTestBase { | 32 class NativeViewAccessibilityTest : public ViewsTestBase { |
32 public: | 33 public: |
33 NativeViewAccessibilityTest() {} | 34 NativeViewAccessibilityTest() {} |
34 ~NativeViewAccessibilityTest() override {} | 35 ~NativeViewAccessibilityTest() override {} |
35 | 36 |
36 void SetUp() override { | 37 void SetUp() override { |
37 ViewsTestBase::SetUp(); | 38 ViewsTestBase::SetUp(); |
38 | 39 |
39 widget_ = new views::Widget; | 40 widget_ = new Widget; |
40 views::Widget::InitParams params = | 41 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW); |
41 CreateParams(views::Widget::InitParams::TYPE_WINDOW); | |
42 params.bounds = gfx::Rect(0, 0, 200, 200); | 42 params.bounds = gfx::Rect(0, 0, 200, 200); |
43 widget_->Init(params); | 43 widget_->Init(params); |
44 | 44 |
45 button_ = new TestButton(); | 45 button_ = new TestButton(); |
46 button_->SetSize(gfx::Size(20, 20)); | 46 button_->SetSize(gfx::Size(20, 20)); |
47 button_accessibility_ = NativeViewAccessibility::Create(button_); | 47 button_accessibility_ = NativeViewAccessibility::Create(button_); |
48 | 48 |
49 label_ = new Label(); | 49 label_ = new Label(); |
50 button_->AddChildView(label_); | 50 button_->AddChildView(label_); |
51 label_accessibility_ = NativeViewAccessibility::Create(label_); | 51 label_accessibility_ = NativeViewAccessibility::Create(label_); |
(...skipping 19 matching lines...) Expand all Loading... |
71 } | 71 } |
72 | 72 |
73 bool SetFocused(NativeViewAccessibilityBase* view_accessibility, | 73 bool SetFocused(NativeViewAccessibilityBase* view_accessibility, |
74 bool focused) { | 74 bool focused) { |
75 ui::AXActionData data; | 75 ui::AXActionData data; |
76 data.action = focused ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; | 76 data.action = focused ? ui::AX_ACTION_FOCUS : ui::AX_ACTION_BLUR; |
77 return view_accessibility->AccessibilityPerformAction(data); | 77 return view_accessibility->AccessibilityPerformAction(data); |
78 } | 78 } |
79 | 79 |
80 protected: | 80 protected: |
81 views::Widget* widget_; | 81 Widget* widget_; |
82 TestButton* button_; | 82 TestButton* button_; |
83 std::unique_ptr<NativeViewAccessibility> button_accessibility_; | 83 std::unique_ptr<NativeViewAccessibility> button_accessibility_; |
84 Label* label_; | 84 Label* label_; |
85 std::unique_ptr<NativeViewAccessibility> label_accessibility_; | 85 std::unique_ptr<NativeViewAccessibility> label_accessibility_; |
| 86 |
| 87 DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityTest); |
86 }; | 88 }; |
87 | 89 |
88 TEST_F(NativeViewAccessibilityTest, RoleShouldMatch) { | 90 TEST_F(NativeViewAccessibilityTest, RoleShouldMatch) { |
89 EXPECT_EQ(ui::AX_ROLE_BUTTON, button_accessibility()->GetData().role); | 91 EXPECT_EQ(ui::AX_ROLE_BUTTON, button_accessibility()->GetData().role); |
| 92 // Since the label is a subview of |button_|, and the button is keyboard |
| 93 // focusable, the label is assumed to form part of the button and not have a |
| 94 // role of its own. |
| 95 EXPECT_EQ(ui::AX_ROLE_IGNORED, label_accessibility()->GetData().role); |
| 96 // This will happen for all potentially keyboard-focusable Views with |
| 97 // non-keyboard-focusable children, so if we make the button unfocusable, the |
| 98 // label will be allowed to have its own role again. |
| 99 button_->SetFocusBehavior(View::FocusBehavior::NEVER); |
90 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, label_accessibility()->GetData().role); | 100 EXPECT_EQ(ui::AX_ROLE_STATIC_TEXT, label_accessibility()->GetData().role); |
91 } | 101 } |
92 | 102 |
93 TEST_F(NativeViewAccessibilityTest, BoundsShouldMatch) { | 103 TEST_F(NativeViewAccessibilityTest, BoundsShouldMatch) { |
94 gfx::Rect bounds = | 104 gfx::Rect bounds = |
95 gfx::ToEnclosingRect(button_accessibility()->GetData().location); | 105 gfx::ToEnclosingRect(button_accessibility()->GetData().location); |
96 gfx::Rect screen_bounds = button_accessibility()->GetScreenBoundsRect(); | 106 gfx::Rect screen_bounds = button_accessibility()->GetScreenBoundsRect(); |
97 | 107 |
98 EXPECT_EQ(button_->GetBoundsInScreen(), bounds); | 108 EXPECT_EQ(button_->GetBoundsInScreen(), bounds); |
99 EXPECT_EQ(screen_bounds, bounds); | 109 EXPECT_EQ(screen_bounds, bounds); |
100 } | 110 } |
101 | 111 |
102 TEST_F(NativeViewAccessibilityTest, LabelIsChildOfButton) { | 112 TEST_F(NativeViewAccessibilityTest, LabelIsChildOfButton) { |
| 113 // |button_| is focusable, so |label_| (as its child) should be ignored. |
| 114 EXPECT_EQ(View::FocusBehavior::ACCESSIBLE_ONLY, button_->focus_behavior()); |
| 115 EXPECT_EQ(1, button_accessibility()->GetChildCount()); |
| 116 EXPECT_EQ(button_->GetNativeViewAccessible(), |
| 117 label_accessibility()->GetParent()); |
| 118 EXPECT_EQ(ui::AX_ROLE_IGNORED, label_accessibility()->GetData().role); |
| 119 |
| 120 // If |button_| is no longer focusable, |label_| should show up again. |
| 121 button_->SetFocusBehavior(View::FocusBehavior::NEVER); |
103 EXPECT_EQ(1, button_accessibility()->GetChildCount()); | 122 EXPECT_EQ(1, button_accessibility()->GetChildCount()); |
104 EXPECT_EQ(label_->GetNativeViewAccessible(), | 123 EXPECT_EQ(label_->GetNativeViewAccessible(), |
105 button_accessibility()->ChildAtIndex(0)); | 124 button_accessibility()->ChildAtIndex(0)); |
106 EXPECT_EQ(button_->GetNativeViewAccessible(), | 125 EXPECT_EQ(button_->GetNativeViewAccessible(), |
107 label_accessibility()->GetParent()); | 126 label_accessibility()->GetParent()); |
| 127 EXPECT_NE(ui::AX_ROLE_IGNORED, label_accessibility()->GetData().role); |
108 } | 128 } |
109 | 129 |
110 // Verify Views with invisible ancestors have AX_STATE_INVISIBLE. | 130 // Verify Views with invisible ancestors have AX_STATE_INVISIBLE. |
111 TEST_F(NativeViewAccessibilityTest, InvisibleViews) { | 131 TEST_F(NativeViewAccessibilityTest, InvisibleViews) { |
112 EXPECT_TRUE(widget_->IsVisible()); | 132 EXPECT_TRUE(widget_->IsVisible()); |
113 EXPECT_FALSE( | 133 EXPECT_FALSE( |
114 button_accessibility()->GetData().HasState(ui::AX_STATE_INVISIBLE)); | 134 button_accessibility()->GetData().HasState(ui::AX_STATE_INVISIBLE)); |
115 EXPECT_FALSE( | 135 EXPECT_FALSE( |
116 label_accessibility()->GetData().HasState(ui::AX_STATE_INVISIBLE)); | 136 label_accessibility()->GetData().HasState(ui::AX_STATE_INVISIBLE)); |
117 button_->SetVisible(false); | 137 button_->SetVisible(false); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
151 bool is_destroying_parent_widget = (parent_widget_ == widget); | 171 bool is_destroying_parent_widget = (parent_widget_ == widget); |
152 NativeViewAccessibilityBase::OnWidgetDestroying(widget); | 172 NativeViewAccessibilityBase::OnWidgetDestroying(widget); |
153 if (is_destroying_parent_widget) | 173 if (is_destroying_parent_widget) |
154 delete this; | 174 delete this; |
155 } | 175 } |
156 }; | 176 }; |
157 | 177 |
158 TEST_F(NativeViewAccessibilityTest, CrashOnWidgetDestroyed) { | 178 TEST_F(NativeViewAccessibilityTest, CrashOnWidgetDestroyed) { |
159 std::unique_ptr<Widget> parent_widget(new Widget); | 179 std::unique_ptr<Widget> parent_widget(new Widget); |
160 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 180 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
161 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 181 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
162 params.bounds = gfx::Rect(50, 50, 650, 650); | 182 params.bounds = gfx::Rect(50, 50, 650, 650); |
163 parent_widget->Init(params); | 183 parent_widget->Init(params); |
164 | 184 |
165 std::unique_ptr<Widget> child_widget(new Widget); | 185 std::unique_ptr<Widget> child_widget(new Widget); |
166 child_widget->Init(params); | 186 child_widget->Init(params); |
167 | 187 |
168 // Make sure that deleting the parent widget can't cause a crash | 188 // Make sure that deleting the parent widget can't cause a crash |
169 // due to NativeViewAccessibility not unregistering itself as a | 189 // due to NativeViewAccessibility not unregistering itself as a |
170 // WidgetObserver. Note that TestNativeViewAccessibility is a subclass | 190 // WidgetObserver. Note that TestNativeViewAccessibility is a subclass |
171 // defined above that destroys itself when its parent widget is destroyed. | 191 // defined above that destroys itself when its parent widget is destroyed. |
(...skipping 10 matching lines...) Expand all Loading... |
182 ~DerivedTestView() override {} | 202 ~DerivedTestView() override {} |
183 | 203 |
184 void OnBlur() override { SetVisible(false); } | 204 void OnBlur() override { SetVisible(false); } |
185 }; | 205 }; |
186 | 206 |
187 class AxTestViewsDelegate : public TestViewsDelegate { | 207 class AxTestViewsDelegate : public TestViewsDelegate { |
188 public: | 208 public: |
189 AxTestViewsDelegate() {} | 209 AxTestViewsDelegate() {} |
190 ~AxTestViewsDelegate() override {} | 210 ~AxTestViewsDelegate() override {} |
191 | 211 |
192 void NotifyAccessibilityEvent(views::View* view, | 212 void NotifyAccessibilityEvent(View* view, ui::AXEvent event_type) override { |
193 ui::AXEvent event_type) override { | |
194 AXAuraObjCache* ax = AXAuraObjCache::GetInstance(); | 213 AXAuraObjCache* ax = AXAuraObjCache::GetInstance(); |
195 std::vector<AXAuraObjWrapper*> out_children; | 214 std::vector<AXAuraObjWrapper*> out_children; |
196 AXAuraObjWrapper* ax_obj = ax->GetOrCreate(view->GetWidget()); | 215 AXAuraObjWrapper* ax_obj = ax->GetOrCreate(view->GetWidget()); |
197 ax_obj->GetChildren(&out_children); | 216 ax_obj->GetChildren(&out_children); |
198 } | 217 } |
199 | 218 |
200 private: | 219 private: |
201 DISALLOW_COPY_AND_ASSIGN(AxTestViewsDelegate); | 220 DISALLOW_COPY_AND_ASSIGN(AxTestViewsDelegate); |
202 }; | 221 }; |
203 | 222 |
204 class AXViewTest : public ViewsTestBase { | 223 class AXViewTest : public ViewsTestBase { |
205 public: | 224 public: |
206 AXViewTest() {} | 225 AXViewTest() {} |
207 ~AXViewTest() override {} | 226 ~AXViewTest() override {} |
208 void SetUp() override { | 227 void SetUp() override { |
209 std::unique_ptr<TestViewsDelegate> views_delegate( | 228 std::unique_ptr<TestViewsDelegate> views_delegate( |
210 new AxTestViewsDelegate()); | 229 new AxTestViewsDelegate()); |
211 set_views_delegate(std::move(views_delegate)); | 230 set_views_delegate(std::move(views_delegate)); |
212 views::ViewsTestBase::SetUp(); | 231 ViewsTestBase::SetUp(); |
213 } | 232 } |
214 }; | 233 }; |
215 | 234 |
216 // Check if the destruction of the widget ends successfully if |view|'s | 235 // Check if the destruction of the widget ends successfully if |view|'s |
217 // visibility changed during destruction. | 236 // visibility changed during destruction. |
218 TEST_F(AXViewTest, LayoutCalledInvalidateRootView) { | 237 TEST_F(AXViewTest, LayoutCalledInvalidateRootView) { |
219 std::unique_ptr<Widget> widget(new Widget); | 238 std::unique_ptr<Widget> widget(new Widget); |
220 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); | 239 Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP); |
221 params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 240 params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
222 widget->Init(params); | 241 widget->Init(params); |
223 widget->Show(); | 242 widget->Show(); |
224 | 243 |
225 View* root = widget->GetRootView(); | 244 View* root = widget->GetRootView(); |
226 DerivedTestView* parent = new DerivedTestView(); | 245 DerivedTestView* parent = new DerivedTestView(); |
227 DerivedTestView* child = new DerivedTestView(); | 246 DerivedTestView* child = new DerivedTestView(); |
228 root->AddChildView(parent); | 247 root->AddChildView(parent); |
229 parent->AddChildView(child); | 248 parent->AddChildView(child); |
230 child->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); | 249 child->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); |
231 parent->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); | 250 parent->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); |
232 root->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); | 251 root->SetFocusBehavior(DerivedTestView::FocusBehavior::ALWAYS); |
233 parent->RequestFocus(); | 252 parent->RequestFocus(); |
234 // During the destruction of parent, OnBlur will be called and change the | 253 // During the destruction of parent, OnBlur will be called and change the |
235 // visibility to false. | 254 // visibility to false. |
236 parent->SetVisible(true); | 255 parent->SetVisible(true); |
237 AXAuraObjCache* ax = AXAuraObjCache::GetInstance(); | 256 AXAuraObjCache* ax = AXAuraObjCache::GetInstance(); |
238 ax->GetOrCreate(widget.get()); | 257 ax->GetOrCreate(widget.get()); |
239 } | 258 } |
240 #endif | 259 #endif |
241 | 260 |
242 } // namespace test | 261 } // namespace test |
243 } // namespace views | 262 } // namespace views |
OLD | NEW |