Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: content/browser/accessibility/dump_accessibility_browsertest_base.cc

Issue 1552683002: Enable DumpAccessibilityTree tests to use cross-process iframes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Get rid of lambdas due to MSVC bug Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/dump_accessibility_browsertest_base.h" 5 #include "content/browser/accessibility/dump_accessibility_browsertest_base.h"
6 6
7 #include <set> 7 #include <set>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/path_service.h" 12 #include "base/path_service.h"
13 #include "base/strings/string16.h" 13 #include "base/strings/string16.h"
14 #include "base/strings/string_split.h" 14 #include "base/strings/string_split.h"
15 #include "base/strings/string_util.h" 15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h" 16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h" 17 #include "base/strings/utf_string_conversions.h"
18 #include "build/build_config.h" 18 #include "build/build_config.h"
19 #include "content/browser/accessibility/accessibility_tree_formatter.h" 19 #include "content/browser/accessibility/accessibility_tree_formatter.h"
20 #include "content/browser/accessibility/accessibility_tree_formatter_blink.h" 20 #include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
21 #include "content/browser/accessibility/browser_accessibility.h" 21 #include "content/browser/accessibility/browser_accessibility.h"
22 #include "content/browser/accessibility/browser_accessibility_manager.h" 22 #include "content/browser/accessibility/browser_accessibility_manager.h"
23 #include "content/browser/accessibility/browser_accessibility_state_impl.h" 23 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
24 #include "content/browser/web_contents/web_contents_impl.h" 24 #include "content/browser/web_contents/web_contents_impl.h"
25 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
26 #include "content/public/common/content_paths.h" 26 #include "content/public/common/content_paths.h"
27 #include "content/public/common/content_switches.h" 27 #include "content/public/common/content_switches.h"
28 #include "content/public/common/url_constants.h" 28 #include "content/public/common/url_constants.h"
29 #include "content/public/test/browser_test_utils.h"
29 #include "content/public/test/content_browser_test.h" 30 #include "content/public/test/content_browser_test.h"
30 #include "content/public/test/content_browser_test_utils.h" 31 #include "content/public/test/content_browser_test_utils.h"
32 #include "content/public/test/test_utils.h"
31 #include "content/shell/browser/shell.h" 33 #include "content/shell/browser/shell.h"
32 #include "content/test/accessibility_browser_test_utils.h" 34 #include "content/test/accessibility_browser_test_utils.h"
35 #include "content/test/content_browser_test_utils_internal.h"
36 #include "net/dns/mock_host_resolver.h"
37 #include "net/test/embedded_test_server/embedded_test_server.h"
33 38
34 namespace content { 39 namespace content {
35 40
36 namespace { 41 namespace {
37 42
38 const char kCommentToken = '#'; 43 const char kCommentToken = '#';
39 const char kMarkSkipFile[] = "#<skip"; 44 const char kMarkSkipFile[] = "#<skip";
40 const char kMarkEndOfFile[] = "<-- End-of-file -->"; 45 const char kMarkEndOfFile[] = "<-- End-of-file -->";
41 const char kSignalDiff[] = "*"; 46 const char kSignalDiff[] = "*";
42 47
48 // Helper function to be used with FrameTree::ForEach, so that
49 // AccessibilityNotificationWaiter can listen for accessibility
50 // events in all frames.
51 bool ListenToFrame(AccessibilityNotificationWaiter* waiter,
52 FrameTreeNode* frame_tree_node) {
53 waiter->ListenToAdditionalFrame(frame_tree_node->current_frame_host());
54 return true;
55 }
56
57 // Helper function to be used with FrameTree::ForEach, to get the
58 // url of all frames.
59 bool GetFrameUrl(std::vector<std::string>* all_frame_urls,
60 FrameTreeNode* frame_tree_node) {
61 all_frame_urls->push_back(frame_tree_node->current_url().spec());
62 return true;
63 }
64
65 // Searches recursively and returns true if an accessibility node is found
66 // that represents a fully loaded web document with the given url.
67 bool AccessibilityTreeContainsLoadedDocWithUrl(BrowserAccessibility* node,
68 const std::string& url) {
69 if ((node->GetRole() == ui::AX_ROLE_WEB_AREA ||
70 node->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) &&
71 node->GetStringAttribute(ui::AX_ATTR_URL) == url) {
72 // If possible, ensure the doc has finished loading. That's currently
73 // not possible with same-process iframes until http://crbug.com/532249
nasko 2016/01/08 22:57:45 nit: httpS ;)
dmazzoni 2016/01/11 19:04:41 Done.
74 // is fixed.
75 return (node->manager()->GetTreeData().url != url ||
76 node->manager()->GetTreeData().loaded);
77 }
78
79 for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
80 if (AccessibilityTreeContainsLoadedDocWithUrl(
81 node->PlatformGetChild(i), url)) {
82 return true;
83 }
84 }
85 return false;
86 }
87
43 } // namespace 88 } // namespace
44 89
45 typedef AccessibilityTreeFormatter::Filter Filter; 90 typedef AccessibilityTreeFormatter::Filter Filter;
46 91
47 DumpAccessibilityTestBase::DumpAccessibilityTestBase() { 92 DumpAccessibilityTestBase::DumpAccessibilityTestBase() {
48 } 93 }
49 94
50 DumpAccessibilityTestBase::~DumpAccessibilityTestBase() { 95 DumpAccessibilityTestBase::~DumpAccessibilityTestBase() {
51 } 96 }
52 97
98 void DumpAccessibilityTestBase::SetUpCommandLine(
99 base::CommandLine* command_line) {
100 IsolateAllSitesForTesting(command_line);
101 }
102
103 void DumpAccessibilityTestBase::SetUpOnMainThread() {
104 host_resolver()->AddRule("*", "127.0.0.1");
105 ASSERT_TRUE(embedded_test_server()->Start());
106 SetupCrossSiteRedirector(embedded_test_server());
107 }
108
53 base::string16 109 base::string16
54 DumpAccessibilityTestBase::DumpUnfilteredAccessibilityTreeAsString() { 110 DumpAccessibilityTestBase::DumpUnfilteredAccessibilityTreeAsString() {
55 scoped_ptr<AccessibilityTreeFormatter> formatter( 111 scoped_ptr<AccessibilityTreeFormatter> formatter(
56 CreateAccessibilityTreeFormatter()); 112 CreateAccessibilityTreeFormatter());
57 std::vector<Filter> filters; 113 std::vector<Filter> filters;
58 filters.push_back(Filter(base::ASCIIToUTF16("*"), Filter::ALLOW)); 114 filters.push_back(Filter(base::ASCIIToUTF16("*"), Filter::ALLOW));
59 formatter->SetFilters(filters); 115 formatter->SetFilters(filters);
60 formatter->set_show_ids(true); 116 formatter->set_show_ids(true);
61 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( 117 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
62 shell()->web_contents()); 118 shell()->web_contents());
(...skipping 25 matching lines...) Expand all
88 ++j; 144 ++j;
89 } 145 }
90 146
91 // Actual file has been fully checked. 147 // Actual file has been fully checked.
92 return diff_lines; 148 return diff_lines;
93 } 149 }
94 150
95 void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives( 151 void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
96 const std::string& test_html, 152 const std::string& test_html,
97 std::vector<Filter>* filters, 153 std::vector<Filter>* filters,
98 std::string* wait_for) { 154 std::vector<std::string>* wait_for) {
99 for (const std::string& line : 155 for (const std::string& line :
100 base::SplitString(test_html, "\n", base::TRIM_WHITESPACE, 156 base::SplitString(test_html, "\n", base::TRIM_WHITESPACE,
101 base::SPLIT_WANT_ALL)) { 157 base::SPLIT_WANT_ALL)) {
102 const std::string& allow_empty_str = formatter_->GetAllowEmptyString(); 158 const std::string& allow_empty_str = formatter_->GetAllowEmptyString();
103 const std::string& allow_str = formatter_->GetAllowString(); 159 const std::string& allow_str = formatter_->GetAllowString();
104 const std::string& deny_str = formatter_->GetDenyString(); 160 const std::string& deny_str = formatter_->GetDenyString();
105 const std::string& wait_str = "@WAIT-FOR:"; 161 const std::string& wait_str = "@WAIT-FOR:";
106 if (base::StartsWith(line, allow_empty_str, 162 if (base::StartsWith(line, allow_empty_str,
107 base::CompareCase::SENSITIVE)) { 163 base::CompareCase::SENSITIVE)) {
108 filters->push_back( 164 filters->push_back(
109 Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())), 165 Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
110 Filter::ALLOW_EMPTY)); 166 Filter::ALLOW_EMPTY));
111 } else if (base::StartsWith(line, allow_str, 167 } else if (base::StartsWith(line, allow_str,
112 base::CompareCase::SENSITIVE)) { 168 base::CompareCase::SENSITIVE)) {
113 filters->push_back(Filter(base::UTF8ToUTF16( 169 filters->push_back(Filter(base::UTF8ToUTF16(
114 line.substr(allow_str.size())), 170 line.substr(allow_str.size())),
115 Filter::ALLOW)); 171 Filter::ALLOW));
116 } else if (base::StartsWith(line, deny_str, 172 } else if (base::StartsWith(line, deny_str,
117 base::CompareCase::SENSITIVE)) { 173 base::CompareCase::SENSITIVE)) {
118 filters->push_back(Filter(base::UTF8ToUTF16( 174 filters->push_back(Filter(base::UTF8ToUTF16(
119 line.substr(deny_str.size())), 175 line.substr(deny_str.size())),
120 Filter::DENY)); 176 Filter::DENY));
121 } else if (base::StartsWith(line, wait_str, 177 } else if (base::StartsWith(line, wait_str,
122 base::CompareCase::SENSITIVE)) { 178 base::CompareCase::SENSITIVE)) {
123 *wait_for = line.substr(wait_str.size()); 179 wait_for->push_back(line.substr(wait_str.size()));
124 } 180 }
125 } 181 }
126 } 182 }
127 183
128 AccessibilityTreeFormatter* 184 AccessibilityTreeFormatter*
129 DumpAccessibilityTestBase::CreateAccessibilityTreeFormatter() { 185 DumpAccessibilityTestBase::CreateAccessibilityTreeFormatter() {
130 if (is_blink_pass_) 186 if (is_blink_pass_)
131 return new AccessibilityTreeFormatterBlink(); 187 return new AccessibilityTreeFormatterBlink();
132 else 188 else
133 return AccessibilityTreeFormatter::Create(); 189 return AccessibilityTreeFormatter::Create();
134 } 190 }
135 191
136 void DumpAccessibilityTestBase::RunTest( 192 void DumpAccessibilityTestBase::RunTest(
137 const base::FilePath file_path, const char* file_dir) { 193 const base::FilePath file_path, const char* file_dir) {
138 #if !defined(OS_ANDROID) 194 #if !defined(OS_ANDROID)
139 // The blink tree is different on Android because we exclude inline 195 // The blink tree is different on Android because we exclude inline
140 // text boxes, for performance. 196 // text boxes, for performance.
141 is_blink_pass_ = true; 197 is_blink_pass_ = true;
142 RunTestForPlatform(file_path, file_dir); 198 RunTestForPlatform(file_path, file_dir);
143 #endif 199 #endif
144 is_blink_pass_ = false; 200 is_blink_pass_ = false;
145 RunTestForPlatform(file_path, file_dir); 201 RunTestForPlatform(file_path, file_dir);
146 } 202 }
147 203
148 void DumpAccessibilityTestBase::RunTestForPlatform( 204 void DumpAccessibilityTestBase::RunTestForPlatform(
149 const base::FilePath file_path, const char* file_dir) { 205 const base::FilePath file_path, const char* file_dir) {
206 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
207 shell()->web_contents());
208 web_contents->AddAccessibilityMode(AccessibilityModeComplete);
209
150 formatter_.reset(CreateAccessibilityTreeFormatter()); 210 formatter_.reset(CreateAccessibilityTreeFormatter());
151 211
152 // Disable the "hot tracked" state (set when the mouse is hovering over 212 // Disable the "hot tracked" state (set when the mouse is hovering over
153 // an object) because it makes test output change based on the mouse position. 213 // an object) because it makes test output change based on the mouse position.
154 BrowserAccessibilityStateImpl::GetInstance()-> 214 BrowserAccessibilityStateImpl::GetInstance()->
155 set_disable_hot_tracking_for_testing(true); 215 set_disable_hot_tracking_for_testing(true);
156 216
157 NavigateToURL(shell(), GURL(url::kAboutBlankURL)); 217 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
158 218
159 // Output the test path to help anyone who encounters a failure and needs 219 // Output the test path to help anyone who encounters a failure and needs
(...skipping 26 matching lines...) Expand all
186 // normalize by deleting all \r from the file (if any) to leave only \n. 246 // normalize by deleting all \r from the file (if any) to leave only \n.
187 std::string expected_contents; 247 std::string expected_contents;
188 base::RemoveChars(expected_contents_raw, "\r", &expected_contents); 248 base::RemoveChars(expected_contents_raw, "\r", &expected_contents);
189 249
190 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) { 250 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) {
191 LOG(INFO) << "Skipping this test on this platform."; 251 LOG(INFO) << "Skipping this test on this platform.";
192 return; 252 return;
193 } 253 }
194 254
195 // Parse filters and other directives in the test file. 255 // Parse filters and other directives in the test file.
196 std::string wait_for; 256 std::vector<std::string> wait_for;
197 AddDefaultFilters(&filters_); 257 AddDefaultFilters(&filters_);
198 ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for); 258 ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for);
199 259
200 // Load the page. 260 // Load the page.
201 base::string16 html_contents16; 261 GURL url(embedded_test_server()->GetURL(
202 html_contents16 = base::UTF8ToUTF16(html_contents); 262 "/" + std::string(file_dir) + "/" + file_path.BaseName().MaybeAsASCII()));
203 GURL url = GetTestUrl(file_dir, file_path.BaseName().MaybeAsASCII().c_str());
204
205 // If there's a @WAIT-FOR directive, set up an accessibility notification
206 // waiter that returns on any event; we'll stop when we get the text we're
207 // waiting for, or time out. Otherwise just wait specifically for
208 // the "load complete" event.
209 scoped_ptr<AccessibilityNotificationWaiter> waiter;
210 if (!wait_for.empty()) {
211 waiter.reset(new AccessibilityNotificationWaiter(
212 shell(), AccessibilityModeComplete, ui::AX_EVENT_NONE));
213 } else {
214 waiter.reset(new AccessibilityNotificationWaiter(
215 shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE));
216 }
217 263
218 // Load the test html. 264 // Load the test html.
219 NavigateToURL(shell(), url); 265 NavigateToURL(shell(), url);
220 266
221 // Wait for notifications. If there's a @WAIT-FOR directive, break when 267 // Get the url of every frame in the frame tree.
222 // the text we're waiting for appears in the dump, otherwise break after 268 FrameTree* frame_tree = web_contents->GetFrameTree();
223 // the first notification, which will be a load complete. 269 std::vector<std::string> all_frame_urls;
224 do { 270 frame_tree->ForEach(base::Bind(GetFrameUrl, &all_frame_urls));
225 waiter->WaitForNotification(); 271
226 if (!wait_for.empty()) { 272 // Wait for the accessibility tree to fully load for all frames,
227 base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString(); 273 // by searching for the WEB_AREA node in the accessibility tree
228 if (base::UTF16ToUTF8(tree_dump).find(wait_for) != std::string::npos) 274 // with the url of each frame in our frame tree. Note that this
229 wait_for.clear(); 275 // doesn't support cases where there are two iframes with the
276 // exact same url. If all frames haven't loaded yet, set up a
277 // listener for accessibility events on any frame and block
278 // until the next one is received.
279 //
280 // If the original page has a @WAIT-FOR directive, don't break until
281 // the text we're waiting for appears in the full text dump of the
282 // accessibility tree, either.
283 for (;;) {
284 VLOG(1) << "Top of loop";
285 RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
286 web_contents->GetMainFrame());
287 BrowserAccessibility* accessibility_root =
288 main_frame->browser_accessibility_manager()->GetRoot();
289
290 // Check to see if all frames have loaded.
291 bool all_frames_loaded = true;
292 for (const auto& url : all_frame_urls) {
293 if (!AccessibilityTreeContainsLoadedDocWithUrl(accessibility_root, url)) {
294 VLOG(1) << "Still waiting on this frame to load: " << url;
295 all_frames_loaded = false;
296 break;
297 }
230 } 298 }
231 } while (!wait_for.empty()); 299
300 // Check to see if the @WAIT-FOR text has appeared yet.
301 bool all_wait_for_strings_found = true;
302 base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString();
303 for (const auto& str : wait_for) {
304 if (base::UTF16ToUTF8(tree_dump).find(str) == std::string::npos) {
305 VLOG(1) << "Still waiting on this text to be found: " << str;
306 all_wait_for_strings_found = false;
307 break;
308 }
309 }
310
311 // If all frames have loaded and the @WAIT-FOR text has appeared,
312 // we're done.
313 if (all_frames_loaded && all_wait_for_strings_found)
314 break;
315
316 // Block until the next accessibility notification in any frame.
317 VLOG(1) << "Waiting until the next accessibility event";
318 AccessibilityNotificationWaiter accessibility_waiter(main_frame,
319 ui::AX_EVENT_NONE);
320 frame_tree->ForEach(base::Bind(ListenToFrame, &accessibility_waiter));
321 accessibility_waiter.WaitForNotification();
322 }
232 323
233 // Call the subclass to dump the output. 324 // Call the subclass to dump the output.
234 std::vector<std::string> actual_lines = Dump(); 325 std::vector<std::string> actual_lines = Dump();
235 326
236 // Perform a diff (or write the initial baseline). 327 // Perform a diff (or write the initial baseline).
237 std::vector<std::string> expected_lines = base::SplitString( 328 std::vector<std::string> expected_lines = base::SplitString(
238 expected_contents, "\n", base::KEEP_WHITESPACE, 329 expected_contents, "\n", base::KEEP_WHITESPACE,
239 base::SPLIT_WANT_NONEMPTY); 330 base::SPLIT_WANT_NONEMPTY);
240 // Marking the end of the file with a line of text ensures that 331 // Marking the end of the file with a line of text ensures that
241 // file length differences are found. 332 // file length differences are found.
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
278 expected_file, actual_contents.c_str(), actual_contents.size())); 369 expected_file, actual_contents.c_str(), actual_contents.size()));
279 LOG(INFO) << "Wrote expectations to: " 370 LOG(INFO) << "Wrote expectations to: "
280 << expected_file.LossyDisplayName(); 371 << expected_file.LossyDisplayName();
281 } 372 }
282 } else { 373 } else {
283 LOG(INFO) << "Test output matches expectations."; 374 LOG(INFO) << "Test output matches expectations.";
284 } 375 }
285 } 376 }
286 377
287 } // namespace content 378 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698