| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "chrome/browser/ui/views/accessibility_event_router_views.h" | 5 #include "chrome/browser/ui/views/accessibility_event_router_views.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 if (!ExtensionAccessibilityEventRouter::GetInstance()-> | 84 if (!ExtensionAccessibilityEventRouter::GetInstance()-> |
| 85 IsAccessibilityEnabled()) { | 85 IsAccessibilityEnabled()) { |
| 86 return; | 86 return; |
| 87 } | 87 } |
| 88 | 88 |
| 89 if (!most_recent_profile_) | 89 if (!most_recent_profile_) |
| 90 return; | 90 return; |
| 91 | 91 |
| 92 AccessibilityMenuItemInfo info(most_recent_profile_, | 92 AccessibilityMenuItemInfo info(most_recent_profile_, |
| 93 UTF16ToUTF8(menu_item_name), | 93 UTF16ToUTF8(menu_item_name), |
| 94 UTF16ToUTF8(menu_name), |
| 94 has_submenu, | 95 has_submenu, |
| 95 item_index, | 96 item_index, |
| 96 item_count); | 97 item_count); |
| 97 SendAccessibilityNotification( | 98 SendAccessibilityNotification( |
| 98 chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, &info); | 99 chrome::NOTIFICATION_ACCESSIBILITY_CONTROL_FOCUSED, &info); |
| 99 } | 100 } |
| 100 | 101 |
| 101 // | 102 // |
| 102 // Private methods | 103 // Private methods |
| 103 // | 104 // |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 163 break; | 164 break; |
| 164 case ui::AccessibilityTypes::ROLE_RADIOBUTTON: | 165 case ui::AccessibilityTypes::ROLE_RADIOBUTTON: |
| 165 // Not used anymore? | 166 // Not used anymore? |
| 166 default: | 167 default: |
| 167 // If this is encountered, please file a bug with the role that wasn't | 168 // If this is encountered, please file a bug with the role that wasn't |
| 168 // caught so we can add accessibility extension API support. | 169 // caught so we can add accessibility extension API support. |
| 169 NOTREACHED(); | 170 NOTREACHED(); |
| 170 } | 171 } |
| 171 } | 172 } |
| 172 | 173 |
| 174 // static |
| 173 void AccessibilityEventRouterViews::SendButtonNotification( | 175 void AccessibilityEventRouterViews::SendButtonNotification( |
| 174 views::View* view, | 176 views::View* view, |
| 175 int type, | 177 int type, |
| 176 Profile* profile) { | 178 Profile* profile) { |
| 177 AccessibilityButtonInfo info(profile, GetViewName(view)); | 179 AccessibilityButtonInfo info( |
| 180 profile, GetViewName(view), GetViewContext(view)); |
| 178 SendAccessibilityNotification(type, &info); | 181 SendAccessibilityNotification(type, &info); |
| 179 } | 182 } |
| 180 | 183 |
| 184 // static |
| 181 void AccessibilityEventRouterViews::SendLinkNotification( | 185 void AccessibilityEventRouterViews::SendLinkNotification( |
| 182 views::View* view, | 186 views::View* view, |
| 183 int type, | 187 int type, |
| 184 Profile* profile) { | 188 Profile* profile) { |
| 185 AccessibilityLinkInfo info(profile, GetViewName(view)); | 189 AccessibilityLinkInfo info(profile, GetViewName(view), GetViewContext(view)); |
| 186 SendAccessibilityNotification(type, &info); | 190 SendAccessibilityNotification(type, &info); |
| 187 } | 191 } |
| 188 | 192 |
| 193 // static |
| 189 void AccessibilityEventRouterViews::SendMenuNotification( | 194 void AccessibilityEventRouterViews::SendMenuNotification( |
| 190 views::View* view, | 195 views::View* view, |
| 191 int type, | 196 int type, |
| 192 Profile* profile) { | 197 Profile* profile) { |
| 193 AccessibilityMenuInfo info(profile, GetViewName(view)); | 198 AccessibilityMenuInfo info(profile, GetViewName(view)); |
| 194 SendAccessibilityNotification(type, &info); | 199 SendAccessibilityNotification(type, &info); |
| 195 } | 200 } |
| 196 | 201 |
| 202 // static |
| 197 void AccessibilityEventRouterViews::SendMenuItemNotification( | 203 void AccessibilityEventRouterViews::SendMenuItemNotification( |
| 198 views::View* view, | 204 views::View* view, |
| 199 int type, | 205 int type, |
| 200 Profile* profile) { | 206 Profile* profile) { |
| 201 std::string name = GetViewName(view); | 207 std::string name = GetViewName(view); |
| 208 std::string context = GetViewContext(view); |
| 202 | 209 |
| 203 bool has_submenu = false; | 210 bool has_submenu = false; |
| 204 int index = -1; | 211 int index = -1; |
| 205 int count = -1; | 212 int count = -1; |
| 206 | 213 |
| 207 if (view->GetClassName() == views::MenuItemView::kViewClassName) | 214 if (view->GetClassName() == views::MenuItemView::kViewClassName) |
| 208 has_submenu = static_cast<views::MenuItemView*>(view)->HasSubmenu(); | 215 has_submenu = static_cast<views::MenuItemView*>(view)->HasSubmenu(); |
| 209 | 216 |
| 210 views::View* parent_menu = view->parent(); | 217 views::View* parent_menu = view->parent(); |
| 211 while (parent_menu != NULL && parent_menu->GetClassName() != | 218 while (parent_menu != NULL && parent_menu->GetClassName() != |
| 212 views::SubmenuView::kViewClassName) { | 219 views::SubmenuView::kViewClassName) { |
| 213 parent_menu = parent_menu->parent(); | 220 parent_menu = parent_menu->parent(); |
| 214 } | 221 } |
| 215 if (parent_menu) { | 222 if (parent_menu) { |
| 216 count = 0; | 223 count = 0; |
| 217 RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count); | 224 RecursiveGetMenuItemIndexAndCount(parent_menu, view, &index, &count); |
| 218 } | 225 } |
| 219 | 226 |
| 220 AccessibilityMenuItemInfo info(profile, name, has_submenu, index, count); | 227 AccessibilityMenuItemInfo info( |
| 228 profile, name, context, has_submenu, index, count); |
| 221 SendAccessibilityNotification(type, &info); | 229 SendAccessibilityNotification(type, &info); |
| 222 } | 230 } |
| 223 | 231 |
| 232 // static |
| 224 void AccessibilityEventRouterViews::SendTextfieldNotification( | 233 void AccessibilityEventRouterViews::SendTextfieldNotification( |
| 225 views::View* view, | 234 views::View* view, |
| 226 int type, | 235 int type, |
| 227 Profile* profile) { | 236 Profile* profile) { |
| 228 ui::AccessibleViewState state; | 237 ui::AccessibleViewState state; |
| 229 view->GetAccessibleState(&state); | 238 view->GetAccessibleState(&state); |
| 230 std::string name = UTF16ToUTF8(state.name); | 239 std::string name = UTF16ToUTF8(state.name); |
| 240 std::string context = GetViewContext(view); |
| 231 bool password = | 241 bool password = |
| 232 (state.state & ui::AccessibilityTypes::STATE_PROTECTED) != 0; | 242 (state.state & ui::AccessibilityTypes::STATE_PROTECTED) != 0; |
| 233 AccessibilityTextBoxInfo info(profile, name, password); | 243 AccessibilityTextBoxInfo info(profile, name, context, password); |
| 234 std::string value = UTF16ToUTF8(state.value); | 244 std::string value = UTF16ToUTF8(state.value); |
| 235 info.SetValue(value, state.selection_start, state.selection_end); | 245 info.SetValue(value, state.selection_start, state.selection_end); |
| 236 SendAccessibilityNotification(type, &info); | 246 SendAccessibilityNotification(type, &info); |
| 237 } | 247 } |
| 238 | 248 |
| 249 // static |
| 239 void AccessibilityEventRouterViews::SendComboboxNotification( | 250 void AccessibilityEventRouterViews::SendComboboxNotification( |
| 240 views::View* view, | 251 views::View* view, |
| 241 int type, | 252 int type, |
| 242 Profile* profile) { | 253 Profile* profile) { |
| 243 ui::AccessibleViewState state; | 254 ui::AccessibleViewState state; |
| 244 view->GetAccessibleState(&state); | 255 view->GetAccessibleState(&state); |
| 245 std::string name = UTF16ToUTF8(state.name); | 256 std::string name = UTF16ToUTF8(state.name); |
| 246 std::string value = UTF16ToUTF8(state.value); | 257 std::string value = UTF16ToUTF8(state.value); |
| 258 std::string context = GetViewContext(view); |
| 247 AccessibilityComboBoxInfo info( | 259 AccessibilityComboBoxInfo info( |
| 248 profile, name, value, state.index, state.count); | 260 profile, name, context, value, state.index, state.count); |
| 249 SendAccessibilityNotification(type, &info); | 261 SendAccessibilityNotification(type, &info); |
| 250 } | 262 } |
| 251 | 263 |
| 264 // static |
| 252 void AccessibilityEventRouterViews::SendCheckboxNotification( | 265 void AccessibilityEventRouterViews::SendCheckboxNotification( |
| 253 views::View* view, | 266 views::View* view, |
| 254 int type, | 267 int type, |
| 255 Profile* profile) { | 268 Profile* profile) { |
| 256 ui::AccessibleViewState state; | 269 ui::AccessibleViewState state; |
| 257 view->GetAccessibleState(&state); | 270 view->GetAccessibleState(&state); |
| 258 std::string name = UTF16ToUTF8(state.name); | 271 std::string name = UTF16ToUTF8(state.name); |
| 259 std::string value = UTF16ToUTF8(state.value); | 272 std::string value = UTF16ToUTF8(state.value); |
| 273 std::string context = GetViewContext(view); |
| 260 AccessibilityCheckboxInfo info( | 274 AccessibilityCheckboxInfo info( |
| 261 profile, name, state.state == ui::AccessibilityTypes::STATE_CHECKED); | 275 profile, |
| 276 name, |
| 277 context, |
| 278 state.state == ui::AccessibilityTypes::STATE_CHECKED); |
| 262 SendAccessibilityNotification(type, &info); | 279 SendAccessibilityNotification(type, &info); |
| 263 } | 280 } |
| 264 | 281 |
| 282 // static |
| 265 void AccessibilityEventRouterViews::SendWindowNotification( | 283 void AccessibilityEventRouterViews::SendWindowNotification( |
| 266 views::View* view, | 284 views::View* view, |
| 267 int type, | 285 int type, |
| 268 Profile* profile) { | 286 Profile* profile) { |
| 269 ui::AccessibleViewState state; | 287 ui::AccessibleViewState state; |
| 270 view->GetAccessibleState(&state); | 288 view->GetAccessibleState(&state); |
| 271 std::string window_text; | 289 std::string window_text; |
| 272 | 290 |
| 273 // If it's an alert, try to get the text from the contents of the | 291 // If it's an alert, try to get the text from the contents of the |
| 274 // static text, not the window title. | 292 // static text, not the window title. |
| 275 if (state.role == ui::AccessibilityTypes::ROLE_ALERT) | 293 if (state.role == ui::AccessibilityTypes::ROLE_ALERT) |
| 276 window_text = RecursiveGetStaticText(view); | 294 window_text = RecursiveGetStaticText(view); |
| 277 | 295 |
| 278 // Otherwise get it from the window's accessible name. | 296 // Otherwise get it from the window's accessible name. |
| 279 if (window_text.empty()) | 297 if (window_text.empty()) |
| 280 window_text = UTF16ToUTF8(state.name); | 298 window_text = UTF16ToUTF8(state.name); |
| 281 | 299 |
| 282 AccessibilityWindowInfo info(profile, window_text); | 300 AccessibilityWindowInfo info(profile, window_text); |
| 283 SendAccessibilityNotification(type, &info); | 301 SendAccessibilityNotification(type, &info); |
| 284 } | 302 } |
| 285 | 303 |
| 304 // static |
| 286 std::string AccessibilityEventRouterViews::GetViewName(views::View* view) { | 305 std::string AccessibilityEventRouterViews::GetViewName(views::View* view) { |
| 287 ui::AccessibleViewState state; | 306 ui::AccessibleViewState state; |
| 288 view->GetAccessibleState(&state); | 307 view->GetAccessibleState(&state); |
| 289 return UTF16ToUTF8(state.name); | 308 return UTF16ToUTF8(state.name); |
| 290 } | 309 } |
| 291 | 310 |
| 311 // static |
| 312 std::string AccessibilityEventRouterViews::GetViewContext(views::View* view) { |
| 313 for (views::View* parent = view->parent(); |
| 314 parent; |
| 315 parent = parent->parent()) { |
| 316 ui::AccessibleViewState state; |
| 317 parent->GetAccessibleState(&state); |
| 318 |
| 319 // Two cases are handled right now. More could be added in the future |
| 320 // depending on how the UI evolves. |
| 321 |
| 322 // A control in a toolbar should use the toolbar's accessible name |
| 323 // as the context. |
| 324 if (state.role == ui::AccessibilityTypes::ROLE_TOOLBAR && |
| 325 !state.name.empty()) { |
| 326 return UTF16ToUTF8(state.name); |
| 327 } |
| 328 |
| 329 // A control inside of an alert (like an infobar) should grab the |
| 330 // first static text descendant as the context; that's the prompt. |
| 331 if (state.role == ui::AccessibilityTypes::ROLE_ALERT) { |
| 332 views::View* static_text_child = FindDescendantWithAccessibleRole( |
| 333 parent, ui::AccessibilityTypes::ROLE_STATICTEXT); |
| 334 if (static_text_child) { |
| 335 ui::AccessibleViewState state; |
| 336 static_text_child->GetAccessibleState(&state); |
| 337 if (!state.name.empty()) |
| 338 return UTF16ToUTF8(state.name); |
| 339 } |
| 340 return std::string(); |
| 341 } |
| 342 } |
| 343 |
| 344 return std::string(); |
| 345 } |
| 346 |
| 347 // static |
| 348 views::View* AccessibilityEventRouterViews::FindDescendantWithAccessibleRole( |
| 349 views::View* view, ui::AccessibilityTypes::Role role) { |
| 350 ui::AccessibleViewState state; |
| 351 view->GetAccessibleState(&state); |
| 352 if (state.role == role) |
| 353 return view; |
| 354 |
| 355 for (int i = 0; i < view->child_count(); i++) { |
| 356 views::View* child = view->child_at(i); |
| 357 views::View* result = FindDescendantWithAccessibleRole(child, role); |
| 358 if (result) |
| 359 return result; |
| 360 } |
| 361 |
| 362 return NULL; |
| 363 } |
| 364 |
| 365 // static |
| 292 bool AccessibilityEventRouterViews::IsMenuEvent( | 366 bool AccessibilityEventRouterViews::IsMenuEvent( |
| 293 views::View* view, | 367 views::View* view, |
| 294 int type) { | 368 int type) { |
| 295 if (type == chrome::NOTIFICATION_ACCESSIBILITY_MENU_OPENED || | 369 if (type == chrome::NOTIFICATION_ACCESSIBILITY_MENU_OPENED || |
| 296 type == chrome::NOTIFICATION_ACCESSIBILITY_MENU_CLOSED) | 370 type == chrome::NOTIFICATION_ACCESSIBILITY_MENU_CLOSED) |
| 297 return true; | 371 return true; |
| 298 | 372 |
| 299 while (view) { | 373 while (view) { |
| 300 ui::AccessibleViewState state; | 374 ui::AccessibleViewState state; |
| 301 view->GetAccessibleState(&state); | 375 view->GetAccessibleState(&state); |
| 302 ui::AccessibilityTypes::Role role = state.role; | 376 ui::AccessibilityTypes::Role role = state.role; |
| 303 if (role == ui::AccessibilityTypes::ROLE_MENUITEM || | 377 if (role == ui::AccessibilityTypes::ROLE_MENUITEM || |
| 304 role == ui::AccessibilityTypes::ROLE_MENUPOPUP) { | 378 role == ui::AccessibilityTypes::ROLE_MENUPOPUP) { |
| 305 return true; | 379 return true; |
| 306 } | 380 } |
| 307 view = view->parent(); | 381 view = view->parent(); |
| 308 } | 382 } |
| 309 | 383 |
| 310 return false; | 384 return false; |
| 311 } | 385 } |
| 312 | 386 |
| 387 // static |
| 313 void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount( | 388 void AccessibilityEventRouterViews::RecursiveGetMenuItemIndexAndCount( |
| 314 views::View* menu, | 389 views::View* menu, |
| 315 views::View* item, | 390 views::View* item, |
| 316 int* index, | 391 int* index, |
| 317 int* count) { | 392 int* count) { |
| 318 for (int i = 0; i < menu->child_count(); ++i) { | 393 for (int i = 0; i < menu->child_count(); ++i) { |
| 319 views::View* child = menu->child_at(i); | 394 views::View* child = menu->child_at(i); |
| 320 int previous_count = *count; | 395 int previous_count = *count; |
| 321 RecursiveGetMenuItemIndexAndCount(child, item, index, count); | 396 RecursiveGetMenuItemIndexAndCount(child, item, index, count); |
| 322 if (child->GetClassName() == views::MenuItemView::kViewClassName && | 397 if (child->GetClassName() == views::MenuItemView::kViewClassName && |
| 323 *count == previous_count) { | 398 *count == previous_count) { |
| 324 if (item == child) | 399 if (item == child) |
| 325 *index = *count; | 400 *index = *count; |
| 326 (*count)++; | 401 (*count)++; |
| 327 } else if (child->GetClassName() == views::TextButton::kViewClassName) { | 402 } else if (child->GetClassName() == views::TextButton::kViewClassName) { |
| 328 if (item == child) | 403 if (item == child) |
| 329 *index = *count; | 404 *index = *count; |
| 330 (*count)++; | 405 (*count)++; |
| 331 } | 406 } |
| 332 } | 407 } |
| 333 } | 408 } |
| 334 | 409 |
| 410 // static |
| 335 std::string AccessibilityEventRouterViews::RecursiveGetStaticText( | 411 std::string AccessibilityEventRouterViews::RecursiveGetStaticText( |
| 336 views::View* view) { | 412 views::View* view) { |
| 337 ui::AccessibleViewState state; | 413 ui::AccessibleViewState state; |
| 338 view->GetAccessibleState(&state); | 414 view->GetAccessibleState(&state); |
| 339 if (state.role == ui::AccessibilityTypes::ROLE_STATICTEXT) | 415 if (state.role == ui::AccessibilityTypes::ROLE_STATICTEXT) |
| 340 return UTF16ToUTF8(state.name); | 416 return UTF16ToUTF8(state.name); |
| 341 | 417 |
| 342 for (int i = 0; i < view->child_count(); ++i) { | 418 for (int i = 0; i < view->child_count(); ++i) { |
| 343 views::View* child = view->child_at(i); | 419 views::View* child = view->child_at(i); |
| 344 std::string result = RecursiveGetStaticText(child); | 420 std::string result = RecursiveGetStaticText(child); |
| 345 if (!result.empty()) | 421 if (!result.empty()) |
| 346 return result; | 422 return result; |
| 347 } | 423 } |
| 348 return std::string(); | 424 return std::string(); |
| 349 } | 425 } |
| OLD | NEW |