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 13 matching lines...) Expand all Loading... | |
24 #include "content/test/accessibility_browser_test_utils.h" | 24 #include "content/test/accessibility_browser_test_utils.h" |
25 #include "third_party/iaccessible2/ia2_api_all.h" | 25 #include "third_party/iaccessible2/ia2_api_all.h" |
26 #include "third_party/isimpledom/ISimpleDOMNode.h" | 26 #include "third_party/isimpledom/ISimpleDOMNode.h" |
27 #include "ui/aura/window.h" | 27 #include "ui/aura/window.h" |
28 #include "ui/aura/window_tree_host.h" | 28 #include "ui/aura/window_tree_host.h" |
29 | 29 |
30 namespace content { | 30 namespace content { |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
34 // Helpers -------------------------------------------------------------------- | 34 // AccessibilityWinBrowserTest ------------------------------------------------ |
35 | 35 |
36 base::win::ScopedComPtr<IAccessible> GetAccessibleFromResultVariant( | 36 class AccessibilityWinBrowserTest : public ContentBrowserTest { |
37 IAccessible* parent, | 37 public: |
38 VARIANT* var) { | 38 AccessibilityWinBrowserTest(); |
39 virtual ~AccessibilityWinBrowserTest(); | |
40 | |
41 protected: | |
42 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | |
43 IAccessible* GetRendererAccessible(); | |
44 void ExecuteScript(const std::wstring& script); | |
45 | |
46 static base::win::ScopedComPtr<IAccessible> | |
47 AccessibilityWinBrowserTest::GetAccessibleFromResultVariant( | |
48 IAccessible* parent, VARIANT* var); | |
49 static HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** acces sible2); | |
dmazzoni
2014/11/03 16:26:49
nit: wrap to 80 chars
| |
50 static void RecursiveFindNodeInAccessibilityTree(IAccessible* node, | |
51 int32 expected_role, const std::wstring& expected_name, | |
52 int32 depth, bool* found); | |
53 static void CheckTextAtOffset(IAccessible2 element, | |
54 LONG offset, IA2TextBoundaryType boundary_type, | |
55 LONG expected_start_offset, LONG expected_end_offset, | |
56 std::wstring& expected_text); | |
57 | |
58 private: | |
59 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); | |
60 }; | |
61 | |
62 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { | |
63 } | |
64 | |
65 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | |
66 } | |
67 | |
68 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | |
69 const std::string& html) { | |
70 AccessibilityNotificationWaiter waiter( | |
71 shell(), AccessibilityModeComplete, | |
72 ui::AX_EVENT_LOAD_COMPLETE); | |
73 GURL html_data_url("data:text/html," + html); | |
74 NavigateToURL(shell(), html_data_url); | |
75 waiter.WaitForNotification(); | |
76 } | |
77 | |
78 // Retrieve the MSAA client accessibility object for the Render Widget Host View | |
79 // of the selected tab. | |
80 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | |
81 content::WebContents* web_contents = shell()->web_contents(); | |
82 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); | |
83 } | |
84 | |
85 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { | |
86 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); | |
87 } | |
88 | |
89 // Static helpers ------------------------------------------------ | |
90 | |
91 base::win::ScopedComPtr<IAccessible> | |
92 AccessibilityWinBrowserTest::GetAccessibleFromResultVariant( | |
93 IAccessible* parent, VARIANT* var) { | |
39 base::win::ScopedComPtr<IAccessible> ptr; | 94 base::win::ScopedComPtr<IAccessible> ptr; |
40 switch (V_VT(var)) { | 95 switch (V_VT(var)) { |
41 case VT_DISPATCH: { | 96 case VT_DISPATCH: { |
42 IDispatch* dispatch = V_DISPATCH(var); | 97 IDispatch* dispatch = V_DISPATCH(var); |
43 if (dispatch) | 98 if (dispatch) |
44 ptr.QueryFrom(dispatch); | 99 ptr.QueryFrom(dispatch); |
45 break; | 100 break; |
46 } | 101 } |
47 | 102 |
48 case VT_I4: { | 103 case VT_I4: { |
49 base::win::ScopedComPtr<IDispatch> dispatch; | 104 base::win::ScopedComPtr<IDispatch> dispatch; |
50 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); | 105 HRESULT hr = parent->get_accChild(*var, dispatch.Receive()); |
51 EXPECT_TRUE(SUCCEEDED(hr)); | 106 EXPECT_TRUE(SUCCEEDED(hr)); |
52 if (dispatch) | 107 if (dispatch) |
53 dispatch.QueryInterface(ptr.Receive()); | 108 dispatch.QueryInterface(ptr.Receive()); |
54 break; | 109 break; |
55 } | 110 } |
56 } | 111 } |
57 return ptr; | 112 return ptr; |
58 } | 113 } |
59 | 114 |
60 HRESULT QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) { | 115 HRESULT AccessibilityWinBrowserTest::QueryIAccessible2(IAccessible* accessible, IAccessible2** accessible2) { |
61 // TODO(ctguil): For some reason querying the IAccessible2 interface from | 116 // IA2 Spec dictates that IServiceProvider should be used instead of |
62 // IAccessible fails. | 117 // QueryInterface when retrieving IAccessible2. |
63 base::win::ScopedComPtr<IServiceProvider> service_provider; | 118 base::win::ScopedComPtr<IServiceProvider> service_provider; |
64 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); | 119 HRESULT hr = accessible->QueryInterface(service_provider.Receive()); |
65 return SUCCEEDED(hr) ? | 120 return SUCCEEDED(hr) ? |
66 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; | 121 service_provider->QueryService(IID_IAccessible2, accessible2) : hr; |
67 } | 122 } |
68 | 123 |
69 // Recursively search through all of the descendants reachable from an | 124 // Recursively search through all of the descendants reachable from an |
70 // IAccessible node and return true if we find one with the given role | 125 // IAccessible node and return true if we find one with the given role |
71 // and name. | 126 // and name. |
72 void RecursiveFindNodeInAccessibilityTree(IAccessible* node, | 127 void AccessibilityWinBrowserTest::RecursiveFindNodeInAccessibilityTree( |
73 int32 expected_role, | 128 IAccessible* node, int32 expected_role, const std::wstring& expected_name, |
74 const std::wstring& expected_name, | 129 int32 depth, bool* found) { |
75 int32 depth, | |
76 bool* found) { | |
77 base::win::ScopedBstr name_bstr; | 130 base::win::ScopedBstr name_bstr; |
78 base::win::ScopedVariant childid_self(CHILDID_SELF); | 131 base::win::ScopedVariant childid_self(CHILDID_SELF); |
79 node->get_accName(childid_self, name_bstr.Receive()); | 132 node->get_accName(childid_self, name_bstr.Receive()); |
80 std::wstring name(name_bstr, name_bstr.Length()); | 133 std::wstring name(name_bstr, name_bstr.Length()); |
81 base::win::ScopedVariant role; | 134 base::win::ScopedVariant role; |
82 node->get_accRole(childid_self, role.Receive()); | 135 node->get_accRole(childid_self, role.Receive()); |
83 ASSERT_EQ(VT_I4, role.type()); | 136 ASSERT_EQ(VT_I4, role.type()); |
84 | 137 |
85 // Print the accessibility tree as we go, because if this test fails | 138 // Print the accessibility tree as we go, because if this test fails |
86 // on the bots, this is really helpful in figuring out why. | 139 // on the bots, this is really helpful in figuring out why. |
(...skipping 25 matching lines...) Expand all Loading... | |
112 if (child_accessible) { | 165 if (child_accessible) { |
113 RecursiveFindNodeInAccessibilityTree( | 166 RecursiveFindNodeInAccessibilityTree( |
114 child_accessible.get(), expected_role, expected_name, depth + 1, | 167 child_accessible.get(), expected_role, expected_name, depth + 1, |
115 found); | 168 found); |
116 if (*found) | 169 if (*found) |
117 return; | 170 return; |
118 } | 171 } |
119 } | 172 } |
120 } | 173 } |
121 | 174 |
175 // Ensures that the text, the start and end offsets retrieved using | |
176 // get_textAtOffset match the expected values. | |
177 void AccessibilityWinBrowserTest::CheckTextAtOffset(IAccessible2 element, | |
178 LONG offset, IA2TextBoundaryType boundary_type, | |
179 LONG expected_start_offset, LONG expected_end_offset, | |
180 std::wstring& expected_text) { | |
181 const std::wstring message = L"while checking for " + expected_text + | |
182 L" at " + expected_start_offset + L'-' + expected_end_offset; | |
dmazzoni
2014/11/03 16:26:49
I don't think you can append integers to strings i
| |
183 SCOPED_TRACE(message); | |
122 | 184 |
123 // AccessibilityWinBrowserTest ------------------------------------------------ | 185 LONG start_offset = 0; |
124 | 186 LONG end_offset = 0; |
125 class AccessibilityWinBrowserTest : public ContentBrowserTest { | 187 base::win::ScopedBstr text; |
126 public: | 188 HRESULT hr = element->get_textAtOffset( |
127 AccessibilityWinBrowserTest(); | 189 offset, boundary_type, |
128 virtual ~AccessibilityWinBrowserTest(); | 190 &start_offset, &end_offset, text.Receive()); |
129 | 191 EXPECT_EQ(S_OK, hr); |
130 protected: | 192 EXPECT_EQ(expected_start_offset, start_offset); |
131 void LoadInitialAccessibilityTreeFromHtml(const std::string& html); | 193 EXPECT_EQ(expected_end_offset, end_offset); |
132 IAccessible* GetRendererAccessible(); | 194 EXPECT_EQ(expected_text, std:wstring(text, text.Length())); |
133 void ExecuteScript(const std::wstring& script); | |
134 | |
135 private: | |
136 DISALLOW_COPY_AND_ASSIGN(AccessibilityWinBrowserTest); | |
137 }; | |
138 | |
139 AccessibilityWinBrowserTest::AccessibilityWinBrowserTest() { | |
140 } | |
141 | |
142 AccessibilityWinBrowserTest::~AccessibilityWinBrowserTest() { | |
143 } | |
144 | |
145 void AccessibilityWinBrowserTest::LoadInitialAccessibilityTreeFromHtml( | |
146 const std::string& html) { | |
147 AccessibilityNotificationWaiter waiter( | |
148 shell(), AccessibilityModeComplete, | |
149 ui::AX_EVENT_LOAD_COMPLETE); | |
150 GURL html_data_url("data:text/html," + html); | |
151 NavigateToURL(shell(), html_data_url); | |
152 waiter.WaitForNotification(); | |
153 } | |
154 | |
155 // Retrieve the MSAA client accessibility object for the Render Widget Host View | |
156 // of the selected tab. | |
157 IAccessible* AccessibilityWinBrowserTest::GetRendererAccessible() { | |
158 content::WebContents* web_contents = shell()->web_contents(); | |
159 return web_contents->GetRenderWidgetHostView()->GetNativeViewAccessible(); | |
160 } | |
161 | |
162 void AccessibilityWinBrowserTest::ExecuteScript(const std::wstring& script) { | |
163 shell()->web_contents()->GetMainFrame()->ExecuteJavaScript(script); | |
164 } | 195 } |
165 | 196 |
166 | 197 |
167 // AccessibleChecker ---------------------------------------------------------- | 198 // AccessibleChecker ---------------------------------------------------------- |
168 | 199 |
169 class AccessibleChecker { | 200 class AccessibleChecker { |
170 public: | 201 public: |
171 // This constructor can be used if the IA2 role will be the same as the MSAA | 202 // This constructor can be used if the IA2 role will be the same as the MSAA |
172 // role. | 203 // role. |
173 AccessibleChecker(const std::wstring& expected_name, | 204 AccessibleChecker(const std::wstring& expected_name, |
(...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 std::wstring()); | 777 std::wstring()); |
747 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, | 778 AccessibleChecker grouping2_checker(std::wstring(), ROLE_SYSTEM_GROUPING, |
748 std::wstring()); | 779 std::wstring()); |
749 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, | 780 AccessibleChecker document_checker(std::wstring(), ROLE_SYSTEM_DOCUMENT, |
750 std::wstring()); | 781 std::wstring()); |
751 document_checker.AppendExpectedChild(&grouping1_checker); | 782 document_checker.AppendExpectedChild(&grouping1_checker); |
752 document_checker.AppendExpectedChild(&grouping2_checker); | 783 document_checker.AppendExpectedChild(&grouping2_checker); |
753 document_checker.CheckAccessible(GetRendererAccessible()); | 784 document_checker.CheckAccessible(GetRendererAccessible()); |
754 } | 785 } |
755 | 786 |
787 IN_PROC_BROWSER_TEST_F(AccessibilityWinBrowserTest, TestTextAtOffset) { | |
788 const char input_contents[] = "Mozilla/5.0 (NT 6.x; WOW64) " | |
789 "WebKit (KHTML, like)."; | |
790 const char textarea_contents[] = "Mozilla/5.0 (NT 6.x; WOW64)\n" | |
791 "WebKit \n(KHTML, like)."; | |
792 LONG contents_length = sizeof(input_contents) / sizeof(char); | |
793 LoadInitialAccessibilityTreeFromHtml("<!DOCTYPE html>" | |
794 "<html><body><form>" | |
795 "<label for='name'>Browser name:</label>" | |
796 "<input type='text' id='name' name='name' value='" | |
797 "Mozilla/5.0 (NT 6.x; WOW64) WebKit " | |
798 "(KHTML, like).'>" | |
799 "</form><textarea rows='3' cols='60'>" | |
800 "Mozilla/5.0 (NT 6.x; WOW64)<br>" | |
801 "WebKit <br>(KHTML, like)." | |
802 "</textarea></body></html>"); | |
803 | |
804 // Retrieve the IAccessible interface for the web page. | |
805 base::win::ScopedComPtr<IAccessible> document = GetRendererAccessible(); | |
806 LONG child_count = 0; | |
807 HRESULT hr = document->get_accChildCount(&child_count); | |
808 ASSERT_EQ(S_OK, hr); | |
809 ASSERT_EQ(2, child_count); | |
810 // Get all the document's children. | |
811 scoped_ptr<VARIANT[]> children(new VARIANT[child_count]); | |
812 LONG obtained_count = 0; | |
813 hr = AccessibleChildren( | |
814 document, 0, child_count, children.get(), &obtained_count); | |
815 ASSERT_EQ(S_OK, hr); | |
816 ASSERT_EQ(child_count, obtained_count); | |
817 | |
818 // Find the two edit fields (simple and text area). | |
819 base::win::ScopedComPtr<IAccessible2> input; | |
820 hr = QueryIAccessible2(GetAccessibleFromResultVariant( | |
821 document, children.get()[0]), input.Receive()); | |
822 ASSERT_EQ(S_OK, hr); | |
823 base::win::ScopedComPtr<IAccessible2> textarea; | |
824 hr = QueryIAccessible2(GetAccessibleFromResultVariant( | |
825 document, children.get()[1]), textarea.Receive()); | |
826 ASSERT_EQ(S_OK, hr); | |
827 | |
828 // Retrieve the IAccessibleText interface for both of the fields. | |
829 base::win::ScopedComPtr<IAccessibleText> input_text; | |
830 hr = input->QueryInterface(input_text.Receive()); | |
831 ASSERT_EQ(S_OK, hr); | |
832 base::win::ScopedComPtr<IAccessibleText> textarea_text; | |
833 hr = textarea->QueryInterface(textarea_text.Receive()); | |
834 ASSERT_EQ(S_OK, hr); | |
835 | |
836 // Test invalid arguments. | |
837 hr = input_text->get_textAtOffset( | |
838 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
839 EXPECT_EQ(E_INVALIDARG, hr); | |
840 hr = textarea_text->get_textAtOffset( | |
841 0, IA2_TEXT_BOUNDARY_CHAR, NULL, NULL, NULL); | |
842 EXPECT_EQ(E_INVALIDARG, hr); | |
843 | |
844 // Test invalid offset. | |
845 LONG invalid_offset = -5; | |
846 LONG start_offset = 0; | |
847 LONG end_offset = 0; | |
848 base::win::ScopedBstr text; | |
849 hr = input_text->get_textAtOffset( | |
850 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
851 &start_offset, &end_offset, text.Receive()); | |
852 EXPECT_EQ(E_FAIL, hr); | |
853 hr = textarea_text->get_textAtOffset( | |
854 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
855 &start_offset, &end_offset, text.Receive()); | |
856 EXPECT_EQ(E_FAIL, hr); | |
857 invalid_offset = contents_length; | |
858 hr = input_text->get_textAtOffset( | |
859 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
860 &start_offset, &end_offset, text.Receive()); | |
861 EXPECT_EQ(E_FAIL, hr); | |
862 hr = textarea_text->get_textAtOffset( | |
863 invalid_offset, IA2_TEXT_BOUNDARY_CHAR, | |
864 &start_offset, &end_offset, text.Receive()); | |
865 EXPECT_EQ(E_FAIL, hr); | |
866 | |
867 // Test character navigation. | |
868 for (LONG offset = 0; offset < contents_length; ++offset) { | |
869 std::wstring expected_text(input_contents[offset], 1); | |
870 LONG expected_start_offset = offset; | |
871 LONG expected_end_offset = offset + 1; | |
872 CheckTextAtOffset(input_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
873 expected_start_offset, expected_end_offset, expected_text); | |
874 } | |
875 for (LONG offset = contents_length - 1; offset >= 0; --offset) { | |
876 std::wstring expected_text(textarea_contents[offset], 1); | |
877 LONG expected_start_offset = offset; | |
878 LONG expected_end_offset = offset + 1; | |
879 CheckTextAtOffset(textarea_text, offset, IA2_TEXT_BOUNDARY_CHAR, | |
880 expected_start_offset, expected_end_offset, expected_text); | |
881 } | |
882 | |
883 // Test word navigation. | |
dmazzoni
2014/11/03 16:26:49
Please add tests for passing IA2_TEXT_OFFSET_LENGT
| |
884 // (Imitate Firefox behavior.) | |
885 // Trailing punctuation should be included as part of the previous word. | |
886 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_WORD, | |
887 0, 8, L"Mozilla/"); | |
888 CheckTextAtOffset(textarea_text, 6, IA2_TEXT_BOUNDARY_WORD, | |
889 0, 8, L"Mozilla/"); | |
890 // If the offset is at the punctuation, it should return | |
891 // the previous word. | |
892 CheckTextAtOffset(textarea_text, 7, IA2_TEXT_BOUNDARY_WORD, | |
893 0, 8, L"Mozilla/"); | |
894 // Numbers with a decimal point (U.S), should be treated as two words. | |
895 CheckTextAtOffset(input_text, 8, IA2_TEXT_BOUNDARY_WORD, | |
896 8, 10, L"5."); | |
897 CheckTextAtOffset(textarea_text, 9, IA2_TEXT_BOUNDARY_WORD, | |
898 8, 10, L"5."); | |
899 // Also, trailing punctuation that occurs after empty space should not be | |
900 // part of the word. ("0 " and not "0 (".) | |
901 CheckTextAtOffset(input_text, 10, IA2_TEXT_BOUNDARY_WORD, | |
902 10, 12, L"0 "); | |
903 CheckTextAtOffset(textarea_text, 11, IA2_TEXT_BOUNDARY_WORD, | |
904 10, 12, L"0 "); | |
905 // Leading punctuation should be included with the word after it. | |
906 CheckTextAtOffset(input_text, 12, IA2_TEXT_BOUNDARY_WORD, | |
907 12, 16, L"(NT "); | |
908 CheckTextAtOffset(textarea_text, 15, IA2_TEXT_BOUNDARY_WORD, | |
909 12, 16, L"(NT "); | |
910 // Numbers separated from letters with trailing punctuation should | |
911 // behave like decimal numbers above. | |
912 CheckTextAtOffset(input_text, 16, IA2_TEXT_BOUNDARY_WORD, | |
913 16, 18, L"6."); | |
914 CheckTextAtOffset(textarea_text, 19, IA2_TEXT_BOUNDARY_WORD, | |
915 18, 21, L"x; "); | |
916 // Words with numbers should be treated like ordinary words. | |
917 CheckTextAtOffset(input_text, 24, IA2_TEXT_BOUNDARY_WORD, | |
918 21, 28, L"WOW64) "); | |
919 CheckTextAtOffset(textarea_text, 26, IA2_TEXT_BOUNDARY_WORD, | |
920 21, 28, L"WOW64)\n"); | |
921 // Multiple trailing empty spaces should be part of the word preceding it. | |
922 CheckTextAtOffset(input_text, 30, IA2_TEXT_BOUNDARY_WORD, | |
923 28, 36, L"WebKit "); | |
924 CheckTextAtOffset(textarea_text, 35, IA2_TEXT_BOUNDARY_WORD, | |
925 28, 36, L"WebKit \n"); | |
926 | |
927 // Test sentence navigation (not currently implemented). | |
928 hr = input_text->get_textAtOffset( | |
929 5, IA2_TEXT_BOUNDARY_SENTENCE, | |
930 &start_offset, &end_offset, text.Receive()); | |
931 EXPECT_EQ(S_FALSE, hr); | |
932 hr = textarea_text->get_textAtOffset( | |
933 25, IA2_TEXT_BOUNDARY_CHAR, | |
934 &start_offset, &end_offset, text.Receive()); | |
935 EXPECT_EQ(S_FALSE, hr); | |
936 | |
937 // Test line navigation. | |
938 CheckTextAtOffset(textarea_text, 0, IA2_TEXT_BOUNDARY_LINE, | |
939 0, 28, L"Mozilla/5.0 (NT 6.x; WOW64)\n"); | |
940 // If the offset is at the newline, return the line preceding it. | |
941 CheckTextAtOffset(textarea_text, 35, IA2_TEXT_BOUNDARY_LINE, | |
942 28, 36, L"WebKit \n"); | |
943 // Last line does not have a trailing newline. | |
944 CheckTextAtOffset(textarea_text, 36, IA2_TEXT_BOUNDARY_LINE, | |
945 36, contents_length, L"(KHTML, like)."); | |
946 | |
947 // Return the whole of the text. | |
948 CheckTextAtOffset(input_text, 0, IA2_TEXT_BOUNDARY_ALL, | |
949 0, contents_length, std::string(input_contents, contents_length)); | |
950 CheckTextAtOffset(textarea_text, contents_length - 1, IA2_TEXT_BOUNDARY_ALL, | |
951 0, contents_length, std::string(textarea_contents, contents_length)); | |
952 } | |
953 | |
756 } // namespace content | 954 } // namespace content |
OLD | NEW |