OLD | NEW |
---|---|
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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/browser_accessibility_win.h" | 5 #include "chrome/browser/browser_accessibility_win.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/string_number_conversions.h" | |
8 #include "base/string_util.h" | 9 #include "base/string_util.h" |
9 #include "base/utf_string_conversions.h" | 10 #include "base/utf_string_conversions.h" |
10 #include "chrome/browser/browser_accessibility_manager_win.h" | 11 #include "chrome/browser/browser_accessibility_manager_win.h" |
11 #include "net/base/escape.h" | 12 #include "net/base/escape.h" |
12 | 13 |
13 using webkit_glue::WebAccessibility; | 14 using webkit_glue::WebAccessibility; |
14 | 15 |
15 BrowserAccessibility::BrowserAccessibility() | 16 BrowserAccessibility::BrowserAccessibility() |
16 : manager_(NULL), | 17 : manager_(NULL), |
17 parent_(NULL), | 18 parent_(NULL), |
18 child_id_(-1), | 19 child_id_(-1), |
19 index_in_parent_(-1), | 20 index_in_parent_(-1), |
20 renderer_id_(-1), | 21 renderer_id_(-1), |
21 instance_active_(false) { | 22 instance_active_(false) { |
22 } | 23 } |
23 | 24 |
24 BrowserAccessibility::~BrowserAccessibility() { | 25 BrowserAccessibility::~BrowserAccessibility() { |
25 InactivateTree(); | 26 InactivateTree(); |
26 } | 27 } |
27 | 28 |
28 void BrowserAccessibility::Initialize( | 29 void BrowserAccessibility::Initialize( |
29 BrowserAccessibilityManager* manager, | 30 BrowserAccessibilityManager* manager, |
30 BrowserAccessibility* parent, | 31 BrowserAccessibility* parent, |
31 LONG child_id, | 32 LONG child_id, |
32 LONG index_in_parent, | 33 LONG index_in_parent, |
33 const webkit_glue::WebAccessibility& src) { | 34 const webkit_glue::WebAccessibility& src) { |
34 DCHECK_EQ(children_.size(), 0U); | |
35 | |
36 manager_ = manager; | 35 manager_ = manager; |
37 parent_ = parent; | 36 parent_ = parent; |
38 child_id_ = child_id; | 37 child_id_ = child_id; |
39 index_in_parent_ = index_in_parent; | 38 index_in_parent_ = index_in_parent; |
40 | 39 |
41 renderer_id_ = src.id; | 40 renderer_id_ = src.id; |
42 name_ = src.name; | 41 name_ = src.name; |
43 value_ = src.value; | 42 value_ = src.value; |
44 attributes_ = src.attributes; | 43 attributes_ = src.attributes; |
45 html_attributes_ = src.html_attributes; | 44 html_attributes_ = src.html_attributes; |
46 location_ = src.location; | 45 location_ = src.location; |
46 src_role_ = src.role; | |
47 InitRoleAndState(src.role, src.state); | 47 InitRoleAndState(src.role, src.state); |
48 | 48 |
49 // Expose headings levels to NVDA with the "level" object attribute. | 49 // Expose headings levels to NVDA with the "level" object attribute. |
50 if (src.role == WebAccessibility::ROLE_HEADING && role_name_.size() == 2 && | 50 if (src.role == WebAccessibility::ROLE_HEADING && role_name_.size() == 2 && |
51 IsAsciiDigit(role_name_[1])) { | 51 IsAsciiDigit(role_name_[1])) { |
52 html_attributes_.push_back(std::make_pair(L"level", role_name_.substr(1))); | 52 html_attributes_.push_back(std::make_pair(L"level", role_name_.substr(1))); |
53 } | 53 } |
54 | 54 |
55 // If this object doesn't have a name but it does have a description, | 55 // If this object doesn't have a name but it does have a description, |
56 // use the description as its name - because some screen readers only | 56 // use the description as its name - because some screen readers only |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 } | 99 } |
100 | 100 |
101 BrowserAccessibility* BrowserAccessibility::GetParent() { | 101 BrowserAccessibility* BrowserAccessibility::GetParent() { |
102 return parent_; | 102 return parent_; |
103 } | 103 } |
104 | 104 |
105 uint32 BrowserAccessibility::GetChildCount() { | 105 uint32 BrowserAccessibility::GetChildCount() { |
106 return children_.size(); | 106 return children_.size(); |
107 } | 107 } |
108 | 108 |
109 BrowserAccessibility* BrowserAccessibility::GetChild(uint32 child_index) { | |
110 DCHECK(child_index >= 0 && child_index < children_.size()); | |
111 return children_[child_index]; | |
112 } | |
113 | |
109 BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() { | 114 BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() { |
110 if (parent_ && index_in_parent_ > 0) | 115 if (parent_ && index_in_parent_ > 0) |
111 return parent_->children_[index_in_parent_ - 1]; | 116 return parent_->children_[index_in_parent_ - 1]; |
112 | 117 |
113 return NULL; | 118 return NULL; |
114 } | 119 } |
115 | 120 |
116 BrowserAccessibility* BrowserAccessibility::GetNextSibling() { | 121 BrowserAccessibility* BrowserAccessibility::GetNextSibling() { |
117 if (parent_ && | 122 if (parent_ && |
118 index_in_parent_ >= 0 && | 123 index_in_parent_ >= 0 && |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
568 if (!instance_active_) | 573 if (!instance_active_) |
569 return E_FAIL; | 574 return E_FAIL; |
570 | 575 |
571 if (!desc) | 576 if (!desc) |
572 return E_INVALIDARG; | 577 return E_INVALIDARG; |
573 | 578 |
574 return GetAttributeAsBstr(WebAccessibility::ATTR_DESCRIPTION, desc); | 579 return GetAttributeAsBstr(WebAccessibility::ATTR_DESCRIPTION, desc); |
575 } | 580 } |
576 | 581 |
577 STDMETHODIMP BrowserAccessibility::get_imagePosition( | 582 STDMETHODIMP BrowserAccessibility::get_imagePosition( |
578 enum IA2CoordinateType coordinate_type, long* x, long* y) { | 583 enum IA2CoordinateType coordinate_type, LONG* x, LONG* y) { |
579 if (!instance_active_) | 584 if (!instance_active_) |
580 return E_FAIL; | 585 return E_FAIL; |
581 | 586 |
582 if (!x || !y) | 587 if (!x || !y) |
583 return E_INVALIDARG; | 588 return E_INVALIDARG; |
584 | 589 |
585 if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) { | 590 if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) { |
586 HWND parent_hwnd = manager_->GetParentHWND(); | 591 HWND parent_hwnd = manager_->GetParentHWND(); |
587 POINT top_left = {0, 0}; | 592 POINT top_left = {0, 0}; |
588 ::ClientToScreen(parent_hwnd, &top_left); | 593 ::ClientToScreen(parent_hwnd, &top_left); |
589 *x = location_.x + top_left.x; | 594 *x = location_.x + top_left.x; |
590 *y = location_.y + top_left.y; | 595 *y = location_.y + top_left.y; |
591 } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) { | 596 } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) { |
592 *x = location_.x; | 597 *x = location_.x; |
593 *y = location_.y; | 598 *y = location_.y; |
594 if (parent_) { | 599 if (parent_) { |
595 *x -= parent_->location_.x; | 600 *x -= parent_->location_.x; |
596 *y -= parent_->location_.y; | 601 *y -= parent_->location_.y; |
597 } | 602 } |
598 } else { | 603 } else { |
599 return E_INVALIDARG; | 604 return E_INVALIDARG; |
600 } | 605 } |
601 | 606 |
602 return S_OK; | 607 return S_OK; |
603 } | 608 } |
604 | 609 |
605 STDMETHODIMP BrowserAccessibility::get_imageSize(long* height, long* width) { | 610 STDMETHODIMP BrowserAccessibility::get_imageSize(LONG* height, LONG* width) { |
606 if (!instance_active_) | 611 if (!instance_active_) |
607 return E_FAIL; | 612 return E_FAIL; |
608 | 613 |
609 if (!height || !width) | 614 if (!height || !width) |
610 return E_INVALIDARG; | 615 return E_INVALIDARG; |
611 | 616 |
612 *height = location_.height; | 617 *height = location_.height; |
613 *width = location_.width; | 618 *width = location_.width; |
614 return S_OK; | 619 return S_OK; |
615 } | 620 } |
616 | 621 |
617 // | 622 // |
618 // IAccessibleText methods. | 623 // IAccessibleText methods. |
619 // | 624 // |
620 | 625 |
621 STDMETHODIMP BrowserAccessibility::get_nCharacters(long* n_characters) { | 626 STDMETHODIMP BrowserAccessibility::get_nCharacters(LONG* n_characters) { |
622 if (!instance_active_) | 627 if (!instance_active_) |
623 return E_FAIL; | 628 return E_FAIL; |
624 | 629 |
625 if (!n_characters) | 630 if (!n_characters) |
626 return E_INVALIDARG; | 631 return E_INVALIDARG; |
627 | 632 |
628 *n_characters = name_.length(); | 633 if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { |
634 *n_characters = value_.length(); | |
635 } else { | |
636 *n_characters = name_.length(); | |
637 } | |
638 | |
629 return S_OK; | 639 return S_OK; |
630 } | 640 } |
631 | 641 |
632 STDMETHODIMP BrowserAccessibility::get_text( | 642 STDMETHODIMP BrowserAccessibility::get_text( |
633 long start_offset, long end_offset, BSTR* text) { | 643 LONG start_offset, LONG end_offset, BSTR* text) { |
634 if (!instance_active_) | 644 if (!instance_active_) |
635 return E_FAIL; | 645 return E_FAIL; |
636 | 646 |
637 if (!text) | 647 if (!text) |
638 return E_INVALIDARG; | 648 return E_INVALIDARG; |
639 | 649 |
640 long len = name_.length(); | 650 string16 text_str; |
Chris Guillory
2010/10/01 18:06:43
Can we use a reference here.
| |
651 if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { | |
652 text_str = value_; | |
653 } else { | |
654 text_str = name_; | |
655 } | |
656 | |
657 // The spec allows the arguments to be reversed. | |
658 if (start_offset > end_offset) { | |
659 LONG tmp = start_offset; | |
660 start_offset = end_offset; | |
661 end_offset = tmp; | |
662 } | |
663 | |
664 // The spec does not allow the start or end offsets to be out or range; | |
665 // we must return an error if so. | |
666 LONG len = text_str.length(); | |
641 if (start_offset < 0) | 667 if (start_offset < 0) |
642 start_offset = 0; | 668 return E_INVALIDARG; |
643 if (end_offset > len) | 669 if (end_offset > len) |
644 end_offset = len; | 670 return E_INVALIDARG; |
645 | 671 |
646 string16 substr = name_.substr(start_offset, end_offset - start_offset); | 672 string16 substr = text_str.substr(start_offset, end_offset - start_offset); |
647 if (substr.empty()) | 673 if (substr.empty()) |
648 return S_FALSE; | 674 return S_FALSE; |
649 | 675 |
650 *text = SysAllocString(substr.c_str()); | 676 *text = SysAllocString(substr.c_str()); |
651 DCHECK(*text); | 677 DCHECK(*text); |
652 return S_OK; | 678 return S_OK; |
653 } | 679 } |
654 | 680 |
655 STDMETHODIMP BrowserAccessibility::get_caretOffset(long* offset) { | 681 STDMETHODIMP BrowserAccessibility::get_caretOffset(LONG* offset) { |
656 if (!instance_active_) | 682 if (!instance_active_) |
657 return E_FAIL; | 683 return E_FAIL; |
658 | 684 |
659 if (!offset) | 685 if (!offset) |
660 return E_INVALIDARG; | 686 return E_INVALIDARG; |
661 | 687 |
662 *offset = 0; | 688 if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { |
689 int sel_start = 0; | |
690 if (GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_START, &sel_start)) { | |
691 *offset = sel_start; | |
692 } else { | |
693 *offset = 0; | |
694 } | |
695 } else { | |
696 *offset = 0; | |
697 } | |
698 | |
699 return S_OK; | |
700 } | |
701 | |
702 STDMETHODIMP BrowserAccessibility::get_nSelections(LONG* n_selections) { | |
703 if (!instance_active_) | |
704 return E_FAIL; | |
705 | |
706 if (!n_selections) | |
707 return E_INVALIDARG; | |
708 | |
709 if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { | |
710 int sel_start = 0; | |
711 int sel_end = 0; | |
712 if (GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_START, &sel_start) && | |
713 GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_END, &sel_end) && | |
714 sel_start != sel_end) { | |
715 *n_selections = 1; | |
716 } else { | |
717 *n_selections = 0; | |
718 } | |
719 } else { | |
720 *n_selections = 0; | |
721 } | |
722 | |
723 return S_OK; | |
724 } | |
725 | |
726 STDMETHODIMP BrowserAccessibility::get_selection(LONG selection_index, | |
727 LONG* start_offset, | |
728 LONG* end_offset) { | |
729 if (!instance_active_) | |
730 return E_FAIL; | |
731 | |
732 if (!start_offset || !end_offset || selection_index != 0) | |
733 return E_INVALIDARG; | |
734 | |
735 if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { | |
736 int sel_start = 0; | |
737 int sel_end = 0; | |
738 if (GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_START, &sel_start) && | |
739 GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_END, &sel_end)) { | |
740 *start_offset = sel_start; | |
741 *end_offset = sel_end; | |
742 } else { | |
743 *start_offset = 0; | |
744 *end_offset = 0; | |
745 } | |
746 } else { | |
747 *start_offset = 0; | |
748 *end_offset = 0; | |
749 } | |
750 | |
663 return S_OK; | 751 return S_OK; |
664 } | 752 } |
665 | 753 |
666 // | 754 // |
667 // ISimpleDOMDocument methods. | 755 // ISimpleDOMDocument methods. |
668 // | 756 // |
669 | 757 |
670 STDMETHODIMP BrowserAccessibility::get_URL(BSTR* url) { | 758 STDMETHODIMP BrowserAccessibility::get_URL(BSTR* url) { |
671 if (!instance_active_) | 759 if (!instance_active_) |
672 return E_FAIL; | 760 return E_FAIL; |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1004 // | 1092 // |
1005 // CComObjectRootEx methods. | 1093 // CComObjectRootEx methods. |
1006 // | 1094 // |
1007 | 1095 |
1008 HRESULT WINAPI BrowserAccessibility::InternalQueryInterface( | 1096 HRESULT WINAPI BrowserAccessibility::InternalQueryInterface( |
1009 void* this_ptr, | 1097 void* this_ptr, |
1010 const _ATL_INTMAP_ENTRY* entries, | 1098 const _ATL_INTMAP_ENTRY* entries, |
1011 REFIID iid, | 1099 REFIID iid, |
1012 void** object) { | 1100 void** object) { |
1013 if (iid == IID_IAccessibleText) { | 1101 if (iid == IID_IAccessibleText) { |
1014 if (role_ != ROLE_SYSTEM_LINK) { | 1102 if (role_ != ROLE_SYSTEM_LINK && role_ != ROLE_SYSTEM_TEXT) { |
1015 *object = NULL; | 1103 *object = NULL; |
1016 return E_NOINTERFACE; | 1104 return E_NOINTERFACE; |
1017 } | 1105 } |
1018 } else if (iid == IID_IAccessibleImage) { | 1106 } else if (iid == IID_IAccessibleImage) { |
1019 if (role_ != ROLE_SYSTEM_GRAPHIC) { | 1107 if (role_ != ROLE_SYSTEM_GRAPHIC) { |
1020 *object = NULL; | 1108 *object = NULL; |
1021 return E_NOINTERFACE; | 1109 return E_NOINTERFACE; |
1022 } | 1110 } |
1023 } else if (iid == IID_ISimpleDOMDocument) { | 1111 } else if (iid == IID_ISimpleDOMDocument) { |
1024 if (role_ != ROLE_SYSTEM_DOCUMENT) { | 1112 if (role_ != ROLE_SYSTEM_DOCUMENT) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1074 | 1162 |
1075 if (str.empty()) | 1163 if (str.empty()) |
1076 return S_FALSE; | 1164 return S_FALSE; |
1077 | 1165 |
1078 *value_bstr = SysAllocString(str.c_str()); | 1166 *value_bstr = SysAllocString(str.c_str()); |
1079 DCHECK(*value_bstr); | 1167 DCHECK(*value_bstr); |
1080 | 1168 |
1081 return S_OK; | 1169 return S_OK; |
1082 } | 1170 } |
1083 | 1171 |
1084 string16 BrowserAccessibility::Escape(string16 str) { | 1172 bool BrowserAccessibility::GetAttributeAsInt( |
1085 return UTF8ToUTF16(EscapeNonASCII(UTF16ToUTF8(str))); | 1173 WebAccessibility::Attribute attribute, int* value_int) { |
1174 string16 value_str; | |
1175 | |
1176 if (!GetAttribute(attribute, &value_str)) | |
1177 return false; | |
1178 | |
1179 if (!base::StringToInt(value_str, value_int)) | |
1180 return false; | |
1181 | |
1182 return true; | |
1086 } | 1183 } |
1087 | 1184 |
1088 void BrowserAccessibility::InitRoleAndState(LONG web_role, | 1185 string16 BrowserAccessibility::Escape(string16 str) { |
1089 LONG web_state) { | 1186 return EscapeQueryParamValueUTF8(str, false); |
1187 } | |
1188 | |
1189 void BrowserAccessibility::InitRoleAndState(LONG web_role, LONG web_state) { | |
1090 state_ = 0; | 1190 state_ = 0; |
1091 ia2_state_ = IA2_STATE_OPAQUE; | 1191 ia2_state_ = IA2_STATE_OPAQUE; |
1092 | 1192 |
1093 if ((web_state >> WebAccessibility::STATE_CHECKED) & 1) | 1193 if ((web_state >> WebAccessibility::STATE_CHECKED) & 1) |
1094 state_ |= STATE_SYSTEM_CHECKED; | 1194 state_ |= STATE_SYSTEM_CHECKED; |
1095 if ((web_state >> WebAccessibility::STATE_COLLAPSED) & 1) | 1195 if ((web_state >> WebAccessibility::STATE_COLLAPSED) & 1) |
1096 state_ |= STATE_SYSTEM_COLLAPSED; | 1196 state_ |= STATE_SYSTEM_COLLAPSED; |
1097 if ((web_state >> WebAccessibility::STATE_EXPANDED) & 1) | 1197 if ((web_state >> WebAccessibility::STATE_EXPANDED) & 1) |
1098 state_ |= STATE_SYSTEM_EXPANDED; | 1198 state_ |= STATE_SYSTEM_EXPANDED; |
1099 if ((web_state >> WebAccessibility::STATE_FOCUSABLE) & 1) | 1199 if ((web_state >> WebAccessibility::STATE_FOCUSABLE) & 1) |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1377 } | 1477 } |
1378 | 1478 |
1379 // The role should always be set. | 1479 // The role should always be set. |
1380 DCHECK(!role_name_.empty() || role_); | 1480 DCHECK(!role_name_.empty() || role_); |
1381 | 1481 |
1382 // If we didn't explicitly set the IAccessible2 role, make it the same | 1482 // If we didn't explicitly set the IAccessible2 role, make it the same |
1383 // as the MSAA role. | 1483 // as the MSAA role. |
1384 if (!ia2_role_) | 1484 if (!ia2_role_) |
1385 ia2_role_ = role_; | 1485 ia2_role_ = role_; |
1386 } | 1486 } |
OLD | NEW |