| 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 "content/browser/accessibility/browser_accessibility_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_win.h" |
| 6 | 6 |
| 7 #include <UIAutomationClient.h> | 7 #include <UIAutomationClient.h> |
| 8 #include <UIAutomationCoreApi.h> | 8 #include <UIAutomationCoreApi.h> |
| 9 | 9 |
| 10 #include <algorithm> | 10 #include <algorithm> |
| 11 | 11 |
| 12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_split.h" | 13 #include "base/strings/string_split.h" |
| 14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
| 15 #include "base/strings/utf_string_conversions.h" | 15 #include "base/strings/utf_string_conversions.h" |
| 16 #include "base/win/enum_variant.h" | 16 #include "base/win/enum_variant.h" |
| 17 #include "base/win/scoped_comptr.h" | 17 #include "base/win/scoped_comptr.h" |
| 18 #include "base/win/windows_version.h" | 18 #include "base/win/windows_version.h" |
| 19 #include "content/browser/accessibility/browser_accessibility_event_win.h" |
| 19 #include "content/browser/accessibility/browser_accessibility_manager_win.h" | 20 #include "content/browser/accessibility/browser_accessibility_manager_win.h" |
| 20 #include "content/browser/accessibility/browser_accessibility_state_impl.h" | 21 #include "content/browser/accessibility/browser_accessibility_state_impl.h" |
| 21 #include "content/common/accessibility_messages.h" | 22 #include "content/common/accessibility_messages.h" |
| 22 #include "content/public/common/content_client.h" | 23 #include "content/public/common/content_client.h" |
| 23 #include "third_party/skia/include/core/SkColor.h" | 24 #include "third_party/skia/include/core/SkColor.h" |
| 24 #include "ui/accessibility/ax_text_utils.h" | 25 #include "ui/accessibility/ax_text_utils.h" |
| 25 #include "ui/base/win/accessibility_ids_win.h" | 26 #include "ui/base/win/accessibility_ids_win.h" |
| 26 #include "ui/base/win/accessibility_misc_utils.h" | 27 #include "ui/base/win/accessibility_misc_utils.h" |
| 27 #include "ui/base/win/atl_module.h" | 28 #include "ui/base/win/atl_module.h" |
| 28 | 29 |
| (...skipping 3457 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3486 int32_t child_id = child->GetId(); | 3487 int32_t child_id = child->GetId(); |
| 3487 int32_t index = hyperlinks().size(); | 3488 int32_t index = hyperlinks().size(); |
| 3488 win_attributes_->hyperlink_offset_to_index[char_offset] = index; | 3489 win_attributes_->hyperlink_offset_to_index[char_offset] = index; |
| 3489 win_attributes_->hyperlinks.push_back(child_id); | 3490 win_attributes_->hyperlinks.push_back(child_id); |
| 3490 win_attributes_->hypertext += kEmbeddedCharacter; | 3491 win_attributes_->hypertext += kEmbeddedCharacter; |
| 3491 } | 3492 } |
| 3492 } | 3493 } |
| 3493 } | 3494 } |
| 3494 | 3495 |
| 3495 void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) { | 3496 void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) { |
| 3496 BrowserAccessibilityManagerWin* manager = | |
| 3497 this->manager()->ToBrowserAccessibilityManagerWin(); | |
| 3498 | |
| 3499 // Fire an event when an alert first appears. | 3497 // Fire an event when an alert first appears. |
| 3500 if (ia_role() == ROLE_SYSTEM_ALERT && | 3498 if (ia_role() == ROLE_SYSTEM_ALERT && |
| 3501 old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { | 3499 old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { |
| 3502 manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); | 3500 BrowserAccessibilityEvent::Create( |
| 3501 BrowserAccessibilityEvent::FromTreeChange, |
| 3502 ui::AX_EVENT_ALERT, |
| 3503 this)->Fire(); |
| 3503 } | 3504 } |
| 3504 | 3505 |
| 3505 // Fire an event when a new subtree is created. | 3506 // Fire an event when a new subtree is created. |
| 3506 if (is_subtree_creation) | 3507 if (is_subtree_creation) |
| 3507 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SHOW, this); | 3508 FireNativeEvent(EVENT_OBJECT_SHOW); |
| 3508 | 3509 |
| 3509 // The rest of the events only fire on changes, not on new objects. | 3510 // The rest of the events only fire on changes, not on new objects. |
| 3510 if (old_win_attributes_->ia_role != 0 || | 3511 if (old_win_attributes_->ia_role != 0 || |
| 3511 !old_win_attributes_->role_name.empty()) { | 3512 !old_win_attributes_->role_name.empty()) { |
| 3512 // Fire an event if the name, description, help, or value changes. | 3513 // Fire an event if the name, description, help, or value changes. |
| 3513 if (name() != old_win_attributes_->name) | 3514 if (name() != old_win_attributes_->name) |
| 3514 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); | 3515 FireNativeEvent(EVENT_OBJECT_NAMECHANGE); |
| 3515 if (description() != old_win_attributes_->description) | 3516 if (description() != old_win_attributes_->description) |
| 3516 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); | 3517 FireNativeEvent(EVENT_OBJECT_DESCRIPTIONCHANGE); |
| 3517 if (value() != old_win_attributes_->value) | 3518 if (value() != old_win_attributes_->value) |
| 3518 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); | 3519 FireNativeEvent(EVENT_OBJECT_VALUECHANGE); |
| 3519 if (ia_state() != old_win_attributes_->ia_state) | 3520 if (ia_state() != old_win_attributes_->ia_state) |
| 3520 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); | 3521 FireNativeEvent(EVENT_OBJECT_STATECHANGE); |
| 3521 | 3522 |
| 3522 // Normally focus events are handled elsewhere, however | 3523 // Normally focus events are handled elsewhere, however |
| 3523 // focus for managed descendants is platform-specific. | 3524 // focus for managed descendants is platform-specific. |
| 3524 // Fire a focus event if the focused descendant in a multi-select | 3525 // Fire a focus event if the focused descendant in a multi-select |
| 3525 // list box changes. | 3526 // list box changes. |
| 3526 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && | 3527 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && |
| 3527 (ia_state() & STATE_SYSTEM_FOCUSABLE) && | 3528 (ia_state() & STATE_SYSTEM_FOCUSABLE) && |
| 3528 (ia_state() & STATE_SYSTEM_SELECTABLE) && | 3529 (ia_state() & STATE_SYSTEM_SELECTABLE) && |
| 3529 (ia_state() & STATE_SYSTEM_FOCUSED) && | 3530 (ia_state() & STATE_SYSTEM_FOCUSED) && |
| 3530 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { | 3531 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { |
| 3531 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this); | 3532 FireNativeEvent(EVENT_OBJECT_FOCUS); |
| 3532 } | 3533 } |
| 3533 | 3534 |
| 3534 // Handle selection being added or removed. | 3535 // Handle selection being added or removed. |
| 3535 bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; | 3536 bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; |
| 3536 bool was_selected_before = | 3537 bool was_selected_before = |
| 3537 (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; | 3538 (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; |
| 3538 if (is_selected_now || was_selected_before) { | 3539 if (is_selected_now || was_selected_before) { |
| 3539 bool multiselect = false; | 3540 bool multiselect = false; |
| 3540 if (GetParent() && GetParent()->HasState(ui::AX_STATE_MULTISELECTABLE)) | 3541 if (GetParent() && GetParent()->HasState(ui::AX_STATE_MULTISELECTABLE)) |
| 3541 multiselect = true; | 3542 multiselect = true; |
| 3542 | 3543 |
| 3543 if (multiselect) { | 3544 if (multiselect) { |
| 3544 // In a multi-select box, fire SELECTIONADD and SELECTIONREMOVE events. | 3545 // In a multi-select box, fire SELECTIONADD and SELECTIONREMOVE events. |
| 3545 if (is_selected_now && !was_selected_before) { | 3546 if (is_selected_now && !was_selected_before) { |
| 3546 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); | 3547 FireNativeEvent(EVENT_OBJECT_SELECTIONADD); |
| 3547 } else if (!is_selected_now && was_selected_before) { | 3548 } else if (!is_selected_now && was_selected_before) { |
| 3548 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); | 3549 FireNativeEvent(EVENT_OBJECT_SELECTIONREMOVE); |
| 3549 } | 3550 } |
| 3550 } else if (is_selected_now && !was_selected_before) { | 3551 } else if (is_selected_now && !was_selected_before) { |
| 3551 // In a single-select box, only fire SELECTION events. | 3552 // In a single-select box, only fire SELECTION events. |
| 3552 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTION, this); | 3553 FireNativeEvent(EVENT_OBJECT_SELECTION); |
| 3553 } | 3554 } |
| 3554 } | 3555 } |
| 3555 | 3556 |
| 3556 // Fire an event if this container object has scrolled. | 3557 // Fire an event if this container object has scrolled. |
| 3557 int sx = 0; | 3558 int sx = 0; |
| 3558 int sy = 0; | 3559 int sy = 0; |
| 3559 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && | 3560 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && |
| 3560 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { | 3561 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { |
| 3561 if (sx != previous_scroll_x_ || sy != previous_scroll_y_) | 3562 if (sx != previous_scroll_x_ || sy != previous_scroll_y_) |
| 3562 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); | 3563 FireNativeEvent(EVENT_SYSTEM_SCROLLINGEND); |
| 3563 previous_scroll_x_ = sx; | 3564 previous_scroll_x_ = sx; |
| 3564 previous_scroll_y_ = sy; | 3565 previous_scroll_y_ = sy; |
| 3565 } | 3566 } |
| 3566 | 3567 |
| 3567 // Fire hypertext-related events. | 3568 // Fire hypertext-related events. |
| 3568 int start, old_len, new_len; | 3569 int start, old_len, new_len; |
| 3569 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | 3570 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); |
| 3570 if (old_len > 0) { | 3571 if (old_len > 0) { |
| 3571 // In-process screen readers may call IAccessibleText::get_oldText | 3572 // In-process screen readers may call IAccessibleText::get_oldText |
| 3572 // in reaction to this event to retrieve the text that was removed. | 3573 // in reaction to this event to retrieve the text that was removed. |
| 3573 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); | 3574 FireNativeEvent(IA2_EVENT_TEXT_REMOVED); |
| 3574 } | 3575 } |
| 3575 if (new_len > 0) { | 3576 if (new_len > 0) { |
| 3576 // In-process screen readers may call IAccessibleText::get_newText | 3577 // In-process screen readers may call IAccessibleText::get_newText |
| 3577 // in reaction to this event to retrieve the text that was inserted. | 3578 // in reaction to this event to retrieve the text that was inserted. |
| 3578 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); | 3579 FireNativeEvent(IA2_EVENT_TEXT_INSERTED); |
| 3579 } | 3580 } |
| 3580 | 3581 |
| 3581 // Changing a static text node can affect the IAccessibleText hypertext | 3582 // Changing a static text node can affect the IAccessibleText hypertext |
| 3582 // of the parent node, so force an update on the parent. | 3583 // of the parent node, so force an update on the parent. |
| 3583 BrowserAccessibilityWin* parent = ToBrowserAccessibilityWin(GetParent()); | 3584 BrowserAccessibilityWin* parent = ToBrowserAccessibilityWin(GetParent()); |
| 3584 if (parent && IsTextOnlyObject() && | 3585 if (parent && IsTextOnlyObject() && |
| 3585 name() != old_win_attributes_->name) { | 3586 name() != old_win_attributes_->name) { |
| 3586 parent->UpdatePlatformAttributes(); | 3587 parent->UpdatePlatformAttributes(); |
| 3587 } | 3588 } |
| 3588 } | 3589 } |
| 3589 | 3590 |
| 3590 old_win_attributes_.reset(nullptr); | 3591 old_win_attributes_.reset(nullptr); |
| 3591 } | 3592 } |
| 3592 | 3593 |
| 3593 void BrowserAccessibilityWin::UpdatePlatformAttributes() { | 3594 void BrowserAccessibilityWin::UpdatePlatformAttributes() { |
| 3594 UpdateStep1ComputeWinAttributes(); | 3595 UpdateStep1ComputeWinAttributes(); |
| 3595 UpdateStep2ComputeHypertext(); | 3596 UpdateStep2ComputeHypertext(); |
| 3596 UpdateStep3FireEvents(false); | 3597 UpdateStep3FireEvents(false); |
| 3597 } | 3598 } |
| 3598 | 3599 |
| 3599 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { | 3600 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { |
| 3600 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( | 3601 FireNativeEvent(EVENT_OBJECT_HIDE); |
| 3601 EVENT_OBJECT_HIDE, this); | |
| 3602 } | 3602 } |
| 3603 | 3603 |
| 3604 void BrowserAccessibilityWin::NativeAddReference() { | 3604 void BrowserAccessibilityWin::NativeAddReference() { |
| 3605 AddRef(); | 3605 AddRef(); |
| 3606 } | 3606 } |
| 3607 | 3607 |
| 3608 void BrowserAccessibilityWin::NativeReleaseReference() { | 3608 void BrowserAccessibilityWin::NativeReleaseReference() { |
| 3609 Release(); | 3609 Release(); |
| 3610 } | 3610 } |
| 3611 | 3611 |
| 3612 bool BrowserAccessibilityWin::IsNative() const { | 3612 bool BrowserAccessibilityWin::IsNative() const { |
| 3613 return true; | 3613 return true; |
| 3614 } | 3614 } |
| 3615 | 3615 |
| 3616 void BrowserAccessibilityWin::OnLocationChanged() { | 3616 void BrowserAccessibilityWin::OnLocationChanged() { |
| 3617 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( | 3617 FireNativeEvent(EVENT_OBJECT_LOCATIONCHANGE); |
| 3618 EVENT_OBJECT_LOCATIONCHANGE, this); | |
| 3619 } | 3618 } |
| 3620 | 3619 |
| 3621 std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes() | 3620 std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes() |
| 3622 const { | 3621 const { |
| 3623 std::vector<base::string16> attributes; | 3622 std::vector<base::string16> attributes; |
| 3624 | 3623 |
| 3625 // We include list markers for now, but there might be other objects that are | 3624 // We include list markers for now, but there might be other objects that are |
| 3626 // auto generated. | 3625 // auto generated. |
| 3627 // TODO(nektar): Compute what objects are auto-generated in Blink. | 3626 // TODO(nektar): Compute what objects are auto-generated in Blink. |
| 3628 if (GetRole() == ui::AX_ROLE_LIST_MARKER) | 3627 if (GetRole() == ui::AX_ROLE_LIST_MARKER) |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4387 // Expose input-text type attribute. | 4386 // Expose input-text type attribute. |
| 4388 base::string16 type; | 4387 base::string16 type; |
| 4389 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG); | 4388 base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG); |
| 4390 if (IsSimpleTextControl() && html_tag == L"input" && | 4389 if (IsSimpleTextControl() && html_tag == L"input" && |
| 4391 GetHtmlAttribute("type", &type)) { | 4390 GetHtmlAttribute("type", &type)) { |
| 4392 SanitizeStringAttributeForIA2(type, &type); | 4391 SanitizeStringAttributeForIA2(type, &type); |
| 4393 win_attributes_->ia2_attributes.push_back(L"text-input-type:" + type); | 4392 win_attributes_->ia2_attributes.push_back(L"text-input-type:" + type); |
| 4394 } | 4393 } |
| 4395 } | 4394 } |
| 4396 | 4395 |
| 4396 void BrowserAccessibilityWin::FireNativeEvent(LONG win_event_type) const { |
| 4397 (new BrowserAccessibilityEventWin( |
| 4398 BrowserAccessibilityEvent::FromTreeChange, |
| 4399 ui::AX_EVENT_NONE, |
| 4400 win_event_type, |
| 4401 this))->Fire(); |
| 4402 } |
| 4403 |
| 4397 void BrowserAccessibilityWin::InitRoleAndState() { | 4404 void BrowserAccessibilityWin::InitRoleAndState() { |
| 4398 int32_t ia_role = 0; | 4405 int32_t ia_role = 0; |
| 4399 int32_t ia_state = 0; | 4406 int32_t ia_state = 0; |
| 4400 base::string16 role_name; | 4407 base::string16 role_name; |
| 4401 int32_t ia2_role = 0; | 4408 int32_t ia2_role = 0; |
| 4402 int32_t ia2_state = IA2_STATE_OPAQUE; | 4409 int32_t ia2_state = IA2_STATE_OPAQUE; |
| 4403 | 4410 |
| 4404 if (HasState(ui::AX_STATE_BUSY)) | 4411 if (HasState(ui::AX_STATE_BUSY)) |
| 4405 ia_state |= STATE_SYSTEM_BUSY; | 4412 ia_state |= STATE_SYSTEM_BUSY; |
| 4406 if (HasState(ui::AX_STATE_CHECKED)) | 4413 if (HasState(ui::AX_STATE_CHECKED)) |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4956 return static_cast<BrowserAccessibilityWin*>(obj); | 4963 return static_cast<BrowserAccessibilityWin*>(obj); |
| 4957 } | 4964 } |
| 4958 | 4965 |
| 4959 const BrowserAccessibilityWin* | 4966 const BrowserAccessibilityWin* |
| 4960 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { | 4967 ToBrowserAccessibilityWin(const BrowserAccessibility* obj) { |
| 4961 DCHECK(!obj || obj->IsNative()); | 4968 DCHECK(!obj || obj->IsNative()); |
| 4962 return static_cast<const BrowserAccessibilityWin*>(obj); | 4969 return static_cast<const BrowserAccessibilityWin*>(obj); |
| 4963 } | 4970 } |
| 4964 | 4971 |
| 4965 } // namespace content | 4972 } // namespace content |
| OLD | NEW |