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 <vector> | 5 #include <vector> |
6 | 6 |
7 #include "base/memory/scoped_ptr.h" | 7 #include "base/memory/scoped_ptr.h" |
8 #include "base/strings/utf_string_conversions.h" | 8 #include "base/strings/utf_string_conversions.h" |
9 #include "base/win/scoped_bstr.h" | 9 #include "base/win/scoped_bstr.h" |
10 #include "base/win/scoped_comptr.h" | 10 #include "base/win/scoped_comptr.h" |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
112 if (child_accessible) { | 112 if (child_accessible) { |
113 RecursiveFindNodeInAccessibilityTree( | 113 RecursiveFindNodeInAccessibilityTree( |
114 child_accessible.get(), expected_role, expected_name, depth + 1, | 114 child_accessible.get(), expected_role, expected_name, depth + 1, |
115 found); | 115 found); |
116 if (*found) | 116 if (*found) |
117 return; | 117 return; |
118 } | 118 } |
119 } | 119 } |
120 } | 120 } |
121 | 121 |
122 // Ensures that the text, the start and end offsets retrieved using | |
123 // get_textAtOffset match the expected values. | |
124 void CheckTextAtOffset(IAccessible2 element, | |
125 LONG offset, IA2TextBoundaryType boundary_type, | |
126 LONG expected_start_offset, LONG expected_end_offset, | |
127 std::wstring expected_text) { | |
128 LONG start_offset = 0; | |
dmazzoni
2014/10/29 21:49:43
Consider adding a SCOPED_TRACE here to aid in debu
| |
129 LONG end_offset = 0; | |
130 base::win::ScopedBstr text; | |
131 HRESULT hr = element->get_textAtOffset( | |
132 offset, boundary_type, | |
133 &start_offset, &end_offset, text.Receive()); | |
134 EXPECT_EQ(S_OK, hr); | |
135 EXPECT_EQ(expected_start_offset, start_offset); | |
136 EXPECT_EQ(expected_end_offset, end_offset); | |
137 EXPECT_EQ(expected_text, std:wstring(text, text.Length())); | |
138 } | |
139 | |
122 | 140 |
123 // AccessibilityWinBrowserTest ------------------------------------------------ | 141 // AccessibilityWinBrowserTest ------------------------------------------------ |
124 | 142 |
125 class AccessibilityWinBrowserTest : public ContentBrowserTest { | 143 class AccessibilityWinBrowserTest : public ContentBrowserTest { |
126 public: | 144 public: |
127 AccessibilityWinBrowserTest(); | 145 AccessibilityWinBrowserTest(); |
128 virtual ~AccessibilityWinBrowserTest(); | 146 virtual ~AccessibilityWinBrowserTest(); |
129 | 147 |
130 protected: | 148 protected: |
131 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | 149 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 std::wstring()); | 764 std::wstring()); |
747 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, | 765 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, |
748 std::wstring()); | 766 std::wstring()); |
749 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, | 767 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, |
750 std::wstring()); | 768 std::wstring()); |
751 document_checker.AppendExpectedChild(&grouping1_checker); | 769 document_checker.AppendExpectedChild(&grouping1_checker); |
752 document_checker.AppendExpectedChild(&grouping2_checker); | 770 document_checker.AppendExpectedChild(&grouping2_checker); |
753 document_checker.CheckAccessible(GetRendererAccessible()); | 771 document_checker.CheckAccessible(GetRendererAccessible()); |
754 } | 772 } |
755 | 773 |
774 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestTextAtOffset) { | |
775 const char input_contents[] = "Mozilla/5.0 (NT 6.x; WOW64) " | |
776 "WebKit (KHTML, like)."; | |
777 const char textarea_contents[] = "Mozilla/5.0 (NT 6.x; WOW64)\n" | |
778 "WebKit \n(KHTML, like)."; | |
779 LONG contents_length = sizeof(input_contents) / sizeof(char); | |
780 LoadInitialAccessibilityTreeFromHtml("<!DOCTYPE html>" | |
781 "<html><body><form>" | |
782 "<label for='name'>Browser name:</label>" | |
783 "<input type='text' id='name' name='name' value='" | |
784 "Mozilla/5.0 (NT 6.x; WOW64) WebKit " | |
785 "(KHTML, like).'>" | |
786 "</form><textarea rows='3' cols='60'>" | |
787 "Mozilla/5.0 (NT 6.x; WOW64)<br>" | |
788 "WebKit <br>(KHTML, like)." | |
789 "</textarea></body></html>"); | |
790 | |
791 // Retrieve the IAccessible interface for the web page. | |
792 base::win::ScopedComPtr<IAccessible> document = GetRendererAccessible(); | |
793 LONG child_count = 0; | |
794 HRESULT hr = document->get_accChildCount(&child_count); | |
795 ASSERT_EQ(S_OK, hr); | |
796 ASSERT_EQ(2, child_count); | |
797 // Get all the document's children. | |
798 scoped_ptr<VARIANT[]> children(new VARIANT[child_count]); | |
799 LONG obtained_count = 0; | |
800 hr = AccessibleChildren( | |
801 document, 0, child_count, children.get(), &obtained_count); | |
802 ASSERT_EQ(S_OK, hr); | |
803 ASSERT_EQ(child_count, obtained_count); | |
804 | |
805 // Find the two edit fields (simple and text area). | |
806 base::win::ScopedComPtr<IAccessible2> input; | |
807 hr = QueryIAccessible2(GetAccessibleFromResultVariant( | |
808 document, children.get()[0]), input.Receive()); | |
809 ASSERT_EQ(S_OK, hr); | |
810 base::win::ScopedComPtr<IAccessible2> textarea; | |
811 hr = QueryIAccessible2(GetAccessibleFromResultVariant( | |
812 document, children.get()[1]), textarea.Receive()); | |
813 ASSERT_EQ(S_OK, hr); | |
814 | |
815 // Retrieve the IAccessibleText interface for both of the fields. | |
816 base::win::ScopedComPtr<IAccessibleText> input_text; | |
817 hr = input->QueryInterface(input_text.Receive()); | |
818 ASSERT_EQ(S_OK, hr); | |
819 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
820 hr = textarea->QueryInterface(textarea_text.Receive()); | |
821 ASSERT_EQ(S_OK, hr); | |
822 | |
823 // Test invalid arguments. | |
824 hr = input_text->get_textAtOffset( | |
825 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
826 EXPECT_EQ(E_INVALIDARG, hr); | |
827 hr = textarea_text->get_textAtOffset( | |
828 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
829 EXPECT_EQ(E_INVALIDARG, hr); | |
830 | |
831 // Test invalid offset. | |
832 LONG invalid_offset = -5; | |
833 LONG start_offset = 0; | |
834 LONG end_offset = 0; | |
835 base::win::ScopedBstr text; | |
836 hr = input_text->get_textAtOffset( | |
837 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
838 &start_offset, &end_offset, text.Receive()); | |
839 EXPECT_EQ(E_FAIL, hr); | |
840 hr = textarea_text->get_textAtOffset( | |
841 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
842 &start_offset, &end_offset, text.Receive()); | |
843 EXPECT_EQ(E_FAIL, hr); | |
844 invalid_offset = contents_length; | |
845 hr = input_text->get_textAtOffset( | |
846 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
847 &start_offset, &end_offset, text.Receive()); | |
848 EXPECT_EQ(E_FAIL, hr); | |
849 hr = textarea_text->get_textAtOffset( | |
850 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
851 &start_offset, &end_offset, text.Receive()); | |
852 EXPECT_EQ(E_FAIL, hr); | |
853 | |
854 // Test character navigation. | |
855 for (LONG offset = 0; offset < contents_length; ++offset) { | |
dmazzoni
2014/10/29 21:49:43
Consider a SCOPED_TRACE inside each loop - that wa
| |
856 std::wstring expected_text(input_contents[offset], 1); | |
857 LONG expected_start_offset = offset; | |
858 LONG expected_end_offset = offset + 1; | |
859 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
860 expected_start_offset, expected_end_offset, expected_text); | |
861 } | |
862 for (LONG offset = contents_length - 1; offset >= 0; --offset) { | |
863 std::wstring expected_text(textarea_contents[offset], 1); | |
864 LONG expected_start_offset = offset; | |
865 LONG expected_end_offset = offset + 1; | |
866 CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
867 expected_start_offset, expected_end_offset, expected_text); | |
868 } | |
869 | |
870 // Test word navigation. | |
871 // (Imitate Firefox behavior.) | |
872 // Trailing punctuation should be included as part of the previous word. | |
873 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, | |
874 0, 8, L"Mozilla/"); | |
875 CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, | |
876 0, 8, L"Mozilla/"); | |
877 // If the offset is at the punctuation, it should return | |
878 // the previous word. | |
879 CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, | |
880 0, 8, L"Mozilla/"); | |
881 // Numbers with a decimal point (U.S), should be treated as two words. | |
882 CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, | |
883 8, 10, L"5."); | |
884 CheckTextAtOffset(textarea_text, 9, IA2_TEXT_BOUNDARY_WORD, | |
885 8, 10, L"5."); | |
886 // Also, trailing punctuation that occurs after empty space should not be | |
887 // part of the word. ("0 " and not "0 (".) | |
888 CheckTextAtOffset(input_text, 10, IA2_TEXT_BOUNDARY_WORD, | |
889 10, 12, L"0 "); | |
890 CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, | |
891 10, 12, L"0 "); | |
892 // Leading punctuation should be included with the word after it. | |
893 CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, | |
894 12, 16, L"(NT "); | |
895 CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, | |
896 12, 16, L"(NT "); | |
897 // Numbers separated from letters with trailing punctuation should | |
898 // behave like decimal numbers above. | |
899 CheckTextAtOffset(input_text, 16, IA2_TEXT_BOUNDARY_WORD, | |
900 16, 18, L"6."); | |
901 CheckTextAtOffset(textarea_text, 19, IA2_TEXT_BOUNDARY_WORD, | |
902 18, 21, L"x; "); | |
903 // Words with numbers should be treated like ordinary words. | |
904 CheckTextAtOffset(input_text, 24, IA2_TEXT_BOUNDARY_WORD, | |
905 21, 28, L"WOW64) "); | |
906 CheckTextAtOffset(textarea_text, 26, IA2_TEXT_BOUNDARY_WORD, | |
907 21, 28, L"WOW64)\n"); | |
908 // Multiple trailing empty spaces should be part of the word preceding it. | |
909 CheckTextAtOffset(input_text, 30, IA2_TEXT_BOUNDARY_WORD, | |
910 28, 36, L"WebKit "); | |
911 CheckTextAtOffset(textarea_text, 35, IA2_TEXT_BOUNDARY_WORD, | |
912 28, 36, L"WebKit \n"); | |
913 | |
914 // Test sentense navigation (not currently implemented). | |
dmazzoni
2014/10/29 21:49:43
nit: sentense -> sentence
| |
915 hr = input_text->get_textAtOffset( | |
916 5, IA2_TEXT_BOUNDARY_SENTENSE, | |
917 &start_offset, &end_offset, text.Receive()); | |
918 EXPECT_EQ(S_FALSE, hr); | |
919 hr = textarea_text->get_textAtOffset( | |
920 25, IA2_TEXT_BOUNDARY_CHAR, | |
921 &start_offset, &end_offset, text.Receive()); | |
922 EXPECT_EQ(S_FALSE, hr); | |
923 | |
924 // Test line navigation. | |
925 CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE, | |
926 0, 28, L"Mozilla/5.0 (NT 6.x; WOW64)\n"); | |
927 // If the offset is at the newline, return the line preceding it. | |
928 CheckTextAtOffset(textarea_text, 35, IA2_TEXT_BOUNDARY_LINE, | |
929 28, 36, L"WebKit \n"); | |
930 // Last line does not have a trailing newline. | |
931 CheckTextAtOffset(textarea_text, 36, IA2_TEXT_BOUNDARY_LINE, | |
932 36, contents_length, L"(KHTML, like)."); | |
933 | |
934 // Return the whole of the text. | |
935 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, | |
936 0, contents_length, std::string(input_contents, contents_length)); | |
937 CheckTextAtOffset(textarea_text, contents_length - 1, IA2_TEXT_BOUNDARY_ALL, | |
938 0, contents_length, std::string(textarea_contents, contents_length)); | |
939 } | |
940 | |
756 } // namespace content | 941 } // namespace content |
OLD | NEW |