OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ui/views/accessibility/native_view_accessibility_win.h" | 5 #include "ui/views/accessibility/native_view_accessibility_win.h" |
6 | 6 |
7 #include <UIAutomationClient.h> | 7 #include <UIAutomationClient.h> |
8 #include <oleacc.h> | 8 #include <oleacc.h> |
9 | 9 |
10 #include <set> | 10 #include <set> |
11 #include <vector> | 11 #include <vector> |
12 | 12 |
13 #include "base/memory/singleton.h" | 13 #include "base/memory/singleton.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/win/scoped_comptr.h" |
15 #include "base/win/windows_version.h" | 16 #include "base/win/windows_version.h" |
16 #include "third_party/iaccessible2/ia2_api_all.h" | 17 #include "third_party/iaccessible2/ia2_api_all.h" |
17 #include "ui/base/accessibility/accessible_text_utils.h" | 18 #include "ui/base/accessibility/accessible_text_utils.h" |
18 #include "ui/base/accessibility/accessible_view_state.h" | 19 #include "ui/base/accessibility/accessible_view_state.h" |
19 #include "ui/base/win/accessibility_ids_win.h" | 20 #include "ui/base/win/accessibility_ids_win.h" |
20 #include "ui/base/win/accessibility_misc_utils.h" | 21 #include "ui/base/win/accessibility_misc_utils.h" |
21 #include "ui/base/win/atl_module.h" | 22 #include "ui/base/win/atl_module.h" |
22 #include "ui/views/controls/button/custom_button.h" | 23 #include "ui/views/controls/button/custom_button.h" |
23 #include "ui/views/focus/focus_manager.h" | 24 #include "ui/views/focus/focus_manager.h" |
24 #include "ui/views/focus/view_storage.h" | 25 #include "ui/views/focus/view_storage.h" |
(...skipping 12 matching lines...) Expand all Loading... |
37 void RegisterWebView(View* web_view); | 38 void RegisterWebView(View* web_view); |
38 | 39 |
39 void UnregisterWebView(View* web_view); | 40 void UnregisterWebView(View* web_view); |
40 | 41 |
41 // Given the view that received the request for the accessible | 42 // Given the view that received the request for the accessible |
42 // id in |top_view|, and the child id requested, return the native | 43 // id in |top_view|, and the child id requested, return the native |
43 // accessible object with that child id from one of the WebViews in | 44 // accessible object with that child id from one of the WebViews in |
44 // |top_view|'s view hierarchy, if any. | 45 // |top_view|'s view hierarchy, if any. |
45 IAccessible* GetAccessibleFromWebView(View* top_view, long child_id); | 46 IAccessible* GetAccessibleFromWebView(View* top_view, long child_id); |
46 | 47 |
| 48 // The system uses IAccessible APIs for many purposes, but only |
| 49 // assistive technology like screen readers uses IAccessible2. |
| 50 // Call this method to note that the IAccessible2 interface was queried and |
| 51 // that WebViews should be proactively notified that this interface will be |
| 52 // used. If this is enabled for the first time, this will explicitly call |
| 53 // QueryService with an argument of IAccessible2 on all WebViews, otherwise |
| 54 // it will just do it from now on. |
| 55 void EnableIAccessible2Support(); |
| 56 |
47 private: | 57 private: |
48 friend struct DefaultSingletonTraits<AccessibleWebViewRegistry>; | 58 friend struct DefaultSingletonTraits<AccessibleWebViewRegistry>; |
49 AccessibleWebViewRegistry(); | 59 AccessibleWebViewRegistry(); |
50 ~AccessibleWebViewRegistry() {} | 60 ~AccessibleWebViewRegistry() {} |
51 | 61 |
52 IAccessible* AccessibleObjectFromChildId(View* web_view, long child_id); | 62 IAccessible* AccessibleObjectFromChildId(View* web_view, long child_id); |
53 | 63 |
| 64 void QueryIAccessible2Interface(View* web_view); |
| 65 |
54 // Set of all web views. We check whether each one is contained in a | 66 // Set of all web views. We check whether each one is contained in a |
55 // top view dynamically rather than keeping track of a map. | 67 // top view dynamically rather than keeping track of a map. |
56 std::set<View*> web_views_; | 68 std::set<View*> web_views_; |
57 | 69 |
58 // The most recent top view used in a call to GetAccessibleFromWebView. | 70 // The most recent top view used in a call to GetAccessibleFromWebView. |
59 View* last_top_view_; | 71 View* last_top_view_; |
60 | 72 |
61 // The most recent web view where an accessible object was found, | 73 // The most recent web view where an accessible object was found, |
62 // corresponding to |last_top_view_|. | 74 // corresponding to |last_top_view_|. |
63 View* last_web_view_; | 75 View* last_web_view_; |
64 | 76 |
| 77 // If IAccessible2 support is enabled, we query the IAccessible2 interface |
| 78 // of WebViews proactively when they're registered, so that they are |
| 79 // aware that they need to support this interface. |
| 80 bool iaccessible2_support_enabled_; |
| 81 |
65 DISALLOW_COPY_AND_ASSIGN(AccessibleWebViewRegistry); | 82 DISALLOW_COPY_AND_ASSIGN(AccessibleWebViewRegistry); |
66 }; | 83 }; |
67 | 84 |
68 AccessibleWebViewRegistry::AccessibleWebViewRegistry() | 85 AccessibleWebViewRegistry::AccessibleWebViewRegistry() |
69 : last_top_view_(NULL), | 86 : last_top_view_(NULL), |
70 last_web_view_(NULL) { | 87 last_web_view_(NULL), |
| 88 iaccessible2_support_enabled_(false) { |
71 } | 89 } |
72 | 90 |
73 AccessibleWebViewRegistry* AccessibleWebViewRegistry::GetInstance() { | 91 AccessibleWebViewRegistry* AccessibleWebViewRegistry::GetInstance() { |
74 return Singleton<AccessibleWebViewRegistry>::get(); | 92 return Singleton<AccessibleWebViewRegistry>::get(); |
75 } | 93 } |
76 | 94 |
77 void AccessibleWebViewRegistry::RegisterWebView(View* web_view) { | 95 void AccessibleWebViewRegistry::RegisterWebView(View* web_view) { |
78 DCHECK(web_views_.find(web_view) == web_views_.end()); | 96 DCHECK(web_views_.find(web_view) == web_views_.end()); |
79 web_views_.insert(web_view); | 97 web_views_.insert(web_view); |
| 98 |
| 99 if (iaccessible2_support_enabled_) |
| 100 QueryIAccessible2Interface(web_view); |
80 } | 101 } |
81 | 102 |
82 void AccessibleWebViewRegistry::UnregisterWebView(View* web_view) { | 103 void AccessibleWebViewRegistry::UnregisterWebView(View* web_view) { |
83 DCHECK(web_views_.find(web_view) != web_views_.end()); | 104 DCHECK(web_views_.find(web_view) != web_views_.end()); |
84 web_views_.erase(web_view); | 105 web_views_.erase(web_view); |
85 if (last_web_view_ == web_view) { | 106 if (last_web_view_ == web_view) { |
86 last_top_view_ = NULL; | 107 last_top_view_ = NULL; |
87 last_web_view_ = NULL; | 108 last_web_view_ = NULL; |
88 } | 109 } |
89 } | 110 } |
(...skipping 23 matching lines...) Expand all Loading... |
113 if (accessible) { | 134 if (accessible) { |
114 last_top_view_ = top_view; | 135 last_top_view_ = top_view; |
115 last_web_view_ = web_view; | 136 last_web_view_ = web_view; |
116 return accessible; | 137 return accessible; |
117 } | 138 } |
118 } | 139 } |
119 | 140 |
120 return NULL; | 141 return NULL; |
121 } | 142 } |
122 | 143 |
| 144 void AccessibleWebViewRegistry::EnableIAccessible2Support() { |
| 145 if (iaccessible2_support_enabled_) |
| 146 return; |
| 147 iaccessible2_support_enabled_ = true; |
| 148 for (std::set<View*>::iterator iter = web_views_.begin(); |
| 149 iter != web_views_.end(); ++iter) { |
| 150 QueryIAccessible2Interface(*iter); |
| 151 } |
| 152 } |
| 153 |
123 IAccessible* AccessibleWebViewRegistry::AccessibleObjectFromChildId( | 154 IAccessible* AccessibleWebViewRegistry::AccessibleObjectFromChildId( |
124 View* web_view, | 155 View* web_view, |
125 long child_id) { | 156 long child_id) { |
126 IAccessible* web_view_accessible = web_view->GetNativeViewAccessible(); | 157 IAccessible* web_view_accessible = web_view->GetNativeViewAccessible(); |
127 if (web_view_accessible == NULL) | 158 if (web_view_accessible == NULL) |
128 return NULL; | 159 return NULL; |
129 | 160 |
130 VARIANT var_child; | 161 VARIANT var_child; |
131 var_child.vt = VT_I4; | 162 var_child.vt = VT_I4; |
132 var_child.lVal = child_id; | 163 var_child.lVal = child_id; |
133 IAccessible* result = NULL; | 164 IAccessible* result = NULL; |
134 if (S_OK == web_view_accessible->get_accChild( | 165 if (S_OK == web_view_accessible->get_accChild( |
135 var_child, reinterpret_cast<IDispatch**>(&result))) { | 166 var_child, reinterpret_cast<IDispatch**>(&result))) { |
136 return result; | 167 return result; |
137 } | 168 } |
138 | 169 |
139 return NULL; | 170 return NULL; |
140 } | 171 } |
141 | 172 |
| 173 void AccessibleWebViewRegistry::QueryIAccessible2Interface(View* web_view) { |
| 174 IAccessible* web_view_accessible = web_view->GetNativeViewAccessible(); |
| 175 if (!web_view_accessible) |
| 176 return; |
| 177 |
| 178 base::win::ScopedComPtr<IServiceProvider> service_provider; |
| 179 if (S_OK != web_view_accessible->QueryInterface(service_provider.Receive())) |
| 180 return; |
| 181 base::win::ScopedComPtr<IAccessible2> iaccessible2; |
| 182 service_provider->QueryService( |
| 183 IID_IAccessible, IID_IAccessible2, |
| 184 reinterpret_cast<void**>(iaccessible2.Receive())); |
| 185 } |
| 186 |
142 } // anonymous namespace | 187 } // anonymous namespace |
143 | 188 |
144 // static | 189 // static |
145 long NativeViewAccessibilityWin::next_unique_id_ = 1; | 190 long NativeViewAccessibilityWin::next_unique_id_ = 1; |
146 int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0}; | 191 int NativeViewAccessibilityWin::view_storage_ids_[kMaxViewStorageIds] = {0}; |
147 int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0; | 192 int NativeViewAccessibilityWin::next_view_storage_id_index_ = 0; |
148 | 193 |
149 // static | 194 // static |
150 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { | 195 NativeViewAccessibility* NativeViewAccessibility::Create(View* view) { |
151 // Make sure ATL is initialized in this module. | 196 // Make sure ATL is initialized in this module. |
(...skipping 867 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1019 | 1064 |
1020 // | 1065 // |
1021 // IServiceProvider methods. | 1066 // IServiceProvider methods. |
1022 // | 1067 // |
1023 | 1068 |
1024 STDMETHODIMP NativeViewAccessibilityWin::QueryService( | 1069 STDMETHODIMP NativeViewAccessibilityWin::QueryService( |
1025 REFGUID guidService, REFIID riid, void** object) { | 1070 REFGUID guidService, REFIID riid, void** object) { |
1026 if (!view_) | 1071 if (!view_) |
1027 return E_FAIL; | 1072 return E_FAIL; |
1028 | 1073 |
| 1074 if (riid == IID_IAccessible2) |
| 1075 AccessibleWebViewRegistry::GetInstance()->EnableIAccessible2Support(); |
| 1076 |
1029 if (guidService == IID_IAccessible || | 1077 if (guidService == IID_IAccessible || |
1030 guidService == IID_IAccessible2 || | 1078 guidService == IID_IAccessible2 || |
1031 guidService == IID_IAccessibleText) { | 1079 guidService == IID_IAccessibleText) { |
1032 return QueryInterface(riid, object); | 1080 return QueryInterface(riid, object); |
1033 } | 1081 } |
1034 | 1082 |
1035 // We only support the IAccessibleEx interface on Windows 8 and above. This | 1083 // We only support the IAccessibleEx interface on Windows 8 and above. This |
1036 // is needed for the On screen Keyboard to show up in metro mode, when the | 1084 // is needed for the On screen Keyboard to show up in metro mode, when the |
1037 // user taps an editable region in the window. | 1085 // user taps an editable region in the window. |
1038 // All methods in the IAccessibleEx interface are unimplemented. | 1086 // All methods in the IAccessibleEx interface are unimplemented. |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1357 continue; | 1405 continue; |
1358 | 1406 |
1359 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) | 1407 if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey)) |
1360 continue; | 1408 continue; |
1361 | 1409 |
1362 result_child_widgets->push_back(child_widget); | 1410 result_child_widgets->push_back(child_widget); |
1363 } | 1411 } |
1364 } | 1412 } |
1365 | 1413 |
1366 } // namespace views | 1414 } // namespace views |
OLD | NEW |