1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
7 #include "base/win/scoped_bstr.h"
8 #include "base/win/scoped_comptr.h"
9 #include "base/win/scoped_variant.h"
10 #include "third_party/iaccessible2/ia2_api_all.h"
11 #include "ui/views/accessibility/native_view_accessibility.h"
12 #include "ui/views/controls/textfield/textfield.h"
13 #include "ui/views/test/views_test_base.h"
15 using base::win::ScopedBstr
;
16 using base::win::ScopedComPtr
;
17 using base::win::ScopedVariant
;
22 class NativeViewAcccessibilityWinTest
: public ViewsTestBase
{
24 NativeViewAcccessibilityWinTest() {}
25 ~NativeViewAcccessibilityWinTest() override
{}
28 void GetIAccessible2InterfaceForView(View
* view
, IAccessible2_2
** result
) {
29 ScopedComPtr
<IAccessible
> view_accessible(
30 view
->GetNativeViewAccessible());
31 ScopedComPtr
<IServiceProvider
> service_provider
;
32 ASSERT_EQ(S_OK
, view_accessible
.QueryInterface(service_provider
.Receive()));
34 service_provider
->QueryService(IID_IAccessible2_2
, result
));
38 TEST_F(NativeViewAcccessibilityWinTest
, TextfieldAccessibility
) {
40 Widget::InitParams init_params
=
41 CreateParams(Widget::InitParams::TYPE_POPUP
);
42 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
43 widget
.Init(init_params
);
45 View
* content
= new View
;
46 widget
.SetContentsView(content
);
48 Textfield
* textfield
= new Textfield
;
49 textfield
->SetAccessibleName(L
"Name");
50 textfield
->SetText(L
"Value");
51 content
->AddChildView(textfield
);
53 ScopedComPtr
<IAccessible
> content_accessible(
54 content
->GetNativeViewAccessible());
56 ASSERT_EQ(S_OK
, content_accessible
->get_accChildCount(&child_count
));
57 ASSERT_EQ(1L, child_count
);
59 ScopedComPtr
<IDispatch
> textfield_dispatch
;
60 ScopedComPtr
<IAccessible
> textfield_accessible
;
61 ScopedVariant
child_index(1);
62 ASSERT_EQ(S_OK
, content_accessible
->get_accChild(
63 child_index
, textfield_dispatch
.Receive()));
64 ASSERT_EQ(S_OK
, textfield_dispatch
.QueryInterface(
65 textfield_accessible
.Receive()));
68 ScopedVariant
childid_self(CHILDID_SELF
);
69 ASSERT_EQ(S_OK
, textfield_accessible
->get_accName(
70 childid_self
, name
.Receive()));
71 ASSERT_STREQ(L
"Name", name
);
74 ASSERT_EQ(S_OK
, textfield_accessible
->get_accValue(
75 childid_self
, value
.Receive()));
76 ASSERT_STREQ(L
"Value", value
);
78 ScopedBstr
new_value(L
"New value");
79 ASSERT_EQ(S_OK
, textfield_accessible
->put_accValue(childid_self
, new_value
));
81 ASSERT_STREQ(L
"New value", textfield
->text().c_str());
84 TEST_F(NativeViewAcccessibilityWinTest
, AuraOwnedWidgets
) {
86 Widget::InitParams init_params
=
87 CreateParams(Widget::InitParams::TYPE_WINDOW
);
88 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
89 widget
.Init(init_params
);
91 ScopedComPtr
<IAccessible
> root_view_accessible(
92 widget
.GetRootView()->GetNativeViewAccessible());
95 ASSERT_EQ(S_OK
, root_view_accessible
->get_accChildCount(&child_count
));
96 ASSERT_EQ(1L, child_count
);
98 ScopedComPtr
<IDispatch
> child_view_dispatch
;
99 ScopedComPtr
<IAccessible
> child_view_accessible
;
100 ScopedVariant
child_index_1(1);
101 ASSERT_EQ(S_OK
, root_view_accessible
->get_accChild(
102 child_index_1
, child_view_dispatch
.Receive()));
103 ASSERT_EQ(S_OK
, child_view_dispatch
.QueryInterface(
104 child_view_accessible
.Receive()));
107 Widget::InitParams owned_init_params
=
108 CreateParams(Widget::InitParams::TYPE_POPUP
);
109 owned_init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
110 owned_init_params
.parent
= widget
.GetNativeView();
111 owned_widget
.Init(owned_init_params
);
114 ASSERT_EQ(S_OK
, root_view_accessible
->get_accChildCount(&child_count
));
115 ASSERT_EQ(2L, child_count
);
117 ScopedComPtr
<IDispatch
> child_widget_dispatch
;
118 ScopedComPtr
<IAccessible
> child_widget_accessible
;
119 ScopedVariant
child_index_2(2);
120 ASSERT_EQ(S_OK
, root_view_accessible
->get_accChild(
121 child_index_2
, child_widget_dispatch
.Receive()));
122 ASSERT_EQ(S_OK
, child_widget_dispatch
.QueryInterface(
123 child_widget_accessible
.Receive()));
125 ScopedComPtr
<IDispatch
> child_widget_sibling_dispatch
;
126 ScopedComPtr
<IAccessible
> child_widget_sibling_accessible
;
127 ScopedVariant
childid_self(CHILDID_SELF
);
128 ScopedVariant result
;
129 ASSERT_EQ(S_OK
, child_widget_accessible
->accNavigate(
130 NAVDIR_PREVIOUS
, childid_self
, result
.Receive()));
131 ASSERT_EQ(VT_DISPATCH
, V_VT(result
.ptr()));
132 child_widget_sibling_dispatch
= V_DISPATCH(result
.ptr());
133 ASSERT_EQ(S_OK
, child_widget_sibling_dispatch
.QueryInterface(
134 child_widget_sibling_accessible
.Receive()));
135 ASSERT_EQ(child_view_accessible
.get(), child_widget_sibling_accessible
.get());
137 ScopedComPtr
<IDispatch
> child_widget_parent_dispatch
;
138 ScopedComPtr
<IAccessible
> child_widget_parent_accessible
;
139 ASSERT_EQ(S_OK
, child_widget_accessible
->get_accParent(
140 child_widget_parent_dispatch
.Receive()));
141 ASSERT_EQ(S_OK
, child_widget_parent_dispatch
.QueryInterface(
142 child_widget_parent_accessible
.Receive()));
143 ASSERT_EQ(root_view_accessible
.get(), child_widget_parent_accessible
.get());
146 // Flaky on Windows: https://crbug.com/461837.
147 TEST_F(NativeViewAcccessibilityWinTest
, DISABLED_RetrieveAllAlerts
) {
149 Widget::InitParams init_params
=
150 CreateParams(Widget::InitParams::TYPE_POPUP
);
151 init_params
.ownership
= Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET
;
152 widget
.Init(init_params
);
154 View
* content
= new View
;
155 widget
.SetContentsView(content
);
157 View
* infobar
= new View
;
158 content
->AddChildView(infobar
);
160 View
* infobar2
= new View
;
161 content
->AddChildView(infobar2
);
163 View
* root_view
= content
->parent();
164 ASSERT_EQ(NULL
, root_view
->parent());
166 ScopedComPtr
<IAccessible2_2
> root_view_accessible
;
167 GetIAccessible2InterfaceForView(root_view
, root_view_accessible
.Receive());
169 ScopedComPtr
<IAccessible2_2
> infobar_accessible
;
170 GetIAccessible2InterfaceForView(infobar
, infobar_accessible
.Receive());
172 ScopedComPtr
<IAccessible2_2
> infobar2_accessible
;
173 GetIAccessible2InterfaceForView(infobar2
, infobar2_accessible
.Receive());
175 // Initially, there are no alerts
176 ScopedBstr
alerts_bstr(L
"alerts");
179 ASSERT_EQ(S_FALSE
, root_view_accessible
->get_relationTargetsOfType(
180 alerts_bstr
, 0, &targets
, &n_targets
));
181 ASSERT_EQ(0, n_targets
);
183 // Fire alert events on the infobars.
184 infobar
->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT
, true);
185 infobar2
->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT
, true);
187 // Now calling get_relationTargetsOfType should retrieve the alerts.
188 ASSERT_EQ(S_OK
, root_view_accessible
->get_relationTargetsOfType(
189 alerts_bstr
, 0, &targets
, &n_targets
));
190 ASSERT_EQ(2, n_targets
);
191 ASSERT_TRUE(infobar_accessible
.IsSameObject(targets
[0]));
192 ASSERT_TRUE(infobar2_accessible
.IsSameObject(targets
[1]));
193 CoTaskMemFree(targets
);
195 // If we set max_targets to 1, we should only get the first one.
196 ASSERT_EQ(S_OK
, root_view_accessible
->get_relationTargetsOfType(
197 alerts_bstr
, 1, &targets
, &n_targets
));
198 ASSERT_EQ(1, n_targets
);
199 ASSERT_TRUE(infobar_accessible
.IsSameObject(targets
[0]));
200 CoTaskMemFree(targets
);
202 // If we delete the first view, we should only get the second one now.
204 ASSERT_EQ(S_OK
, root_view_accessible
->get_relationTargetsOfType(
205 alerts_bstr
, 0, &targets
, &n_targets
));
206 ASSERT_EQ(1, n_targets
);
207 ASSERT_TRUE(infobar2_accessible
.IsSameObject(targets
[0]));
208 CoTaskMemFree(targets
);