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

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: Rebaseline last win tests 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
(...skipping 12 matching lines...) Expand all
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/content_browser_test.h" 29 #include "content/public/test/content_browser_test.h"
30 #include "content/public/test/content_browser_test_utils.h" 30 #include "content/public/test/content_browser_test_utils.h"
31 #include "content/shell/browser/shell.h" 31 #include "content/shell/browser/shell.h"
32 #include "content/test/accessibility_browser_test_utils.h" 32 #include "content/test/accessibility_browser_test_utils.h"
33 #include "content/test/content_browser_test_utils_internal.h"
33 34
34 namespace content { 35 namespace content {
35 36
36 namespace { 37 namespace {
37 38
38 const char kCommentToken = '#'; 39 const char kCommentToken = '#';
39 const char kMarkSkipFile[] = "#<skip"; 40 const char kMarkSkipFile[] = "#<skip";
40 const char kMarkEndOfFile[] = "<-- End-of-file -->"; 41 const char kMarkEndOfFile[] = "<-- End-of-file -->";
41 const char kSignalDiff[] = "*"; 42 const char kSignalDiff[] = "*";
42 43
44 // Helper function to be used with FrameTree::ForEach, so that
45 // AccessibilityNotificationWaiter can listen for accessibility
46 // events in all frames.
47 bool ListenToFrame(AccessibilityNotificationWaiter* waiter,
48 FrameTreeNode* frame_tree_node) {
49 waiter->ListenToAdditionalFrame(frame_tree_node->current_frame_host());
50 return true;
nasko 2016/01/07 00:07:37 nit: This is a small enough function that it can b
dmazzoni 2016/01/07 19:19:08 Done, though unfortunately it doesn't seem to pass
51 }
52
53 // Helper function to be used with FrameTree::ForEach, to get the
54 // url of all frames.
55 bool GetFrameUrl(std::vector<std::string>* all_frame_urls,
56 FrameTreeNode* frame_tree_node) {
57 std::string url = frame_tree_node->current_url().spec();
58 if (url != url::kAboutBlankURL)
dcheng 2016/01/07 00:07:11 Just curious: any particular reason to filter out
dmazzoni 2016/01/07 19:19:08 Removed. I added this while debugging but it shoul
dmazzoni 2016/01/11 19:40:53 Turns out this was needed for one test. Consider
59 all_frame_urls->push_back(url);
60 return true;
61 }
62
63 // Searches recursively and returns true if an accessibility node
David Tseng 2016/01/07 00:02:29 nit: lines can fit more characters.
dmazzoni 2016/01/07 19:19:08 Done.
64 // is found that represents a fully loaded web document with the
65 // given url.
66 bool AccessibilityTreeContainsLoadedDocWithUrl(BrowserAccessibility* node,
67 const std::string& url) {
68 if ((node->GetRole() == ui::AX_ROLE_WEB_AREA ||
69 node->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) &&
70 node->GetStringAttribute(ui::AX_ATTR_URL) == url) {
71 // If possible, ensure the doc has finished loading. That's currently
72 // not possible with same-process iframes until bug 532249 is
nasko 2016/01/07 00:07:37 nit: https://crbug.com/532249 as it will likify an
dmazzoni 2016/01/07 19:19:08 Done.
73 // fixed.
74 if (node->manager()->GetTreeData().url == url &&
75 !node->manager()->GetTreeData().loaded) {
76 return false;
77 }
78
79 return true;
David Tseng 2016/01/07 00:02:29 You could negate the above if clauses and return t
dmazzoni 2016/01/07 19:19:08 Done.
80 }
81
82 for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
83 if (AccessibilityTreeContainsLoadedDocWithUrl(
84 node->PlatformGetChild(i), url)) {
85 return true;
86 }
87 }
88 return false;
89 }
90
43 } // namespace 91 } // namespace
44 92
45 typedef AccessibilityTreeFormatter::Filter Filter; 93 typedef AccessibilityTreeFormatter::Filter Filter;
46 94
47 DumpAccessibilityTestBase::DumpAccessibilityTestBase() { 95 DumpAccessibilityTestBase::DumpAccessibilityTestBase() {
48 } 96 }
49 97
50 DumpAccessibilityTestBase::~DumpAccessibilityTestBase() { 98 DumpAccessibilityTestBase::~DumpAccessibilityTestBase() {
51 } 99 }
52 100
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 ++j; 136 ++j;
89 } 137 }
90 138
91 // Actual file has been fully checked. 139 // Actual file has been fully checked.
92 return diff_lines; 140 return diff_lines;
93 } 141 }
94 142
95 void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives( 143 void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
96 const std::string& test_html, 144 const std::string& test_html,
97 std::vector<Filter>* filters, 145 std::vector<Filter>* filters,
98 std::string* wait_for) { 146 std::vector<std::string>* wait_for) {
99 for (const std::string& line : 147 for (const std::string& line :
100 base::SplitString(test_html, "\n", base::TRIM_WHITESPACE, 148 base::SplitString(test_html, "\n", base::TRIM_WHITESPACE,
101 base::SPLIT_WANT_ALL)) { 149 base::SPLIT_WANT_ALL)) {
102 const std::string& allow_empty_str = formatter_->GetAllowEmptyString(); 150 const std::string& allow_empty_str = formatter_->GetAllowEmptyString();
103 const std::string& allow_str = formatter_->GetAllowString(); 151 const std::string& allow_str = formatter_->GetAllowString();
104 const std::string& deny_str = formatter_->GetDenyString(); 152 const std::string& deny_str = formatter_->GetDenyString();
105 const std::string& wait_str = "@WAIT-FOR:"; 153 const std::string& wait_str = "@WAIT-FOR:";
106 if (base::StartsWith(line, allow_empty_str, 154 if (base::StartsWith(line, allow_empty_str,
107 base::CompareCase::SENSITIVE)) { 155 base::CompareCase::SENSITIVE)) {
108 filters->push_back( 156 filters->push_back(
109 Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())), 157 Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
110 Filter::ALLOW_EMPTY)); 158 Filter::ALLOW_EMPTY));
111 } else if (base::StartsWith(line, allow_str, 159 } else if (base::StartsWith(line, allow_str,
112 base::CompareCase::SENSITIVE)) { 160 base::CompareCase::SENSITIVE)) {
113 filters->push_back(Filter(base::UTF8ToUTF16( 161 filters->push_back(Filter(base::UTF8ToUTF16(
114 line.substr(allow_str.size())), 162 line.substr(allow_str.size())),
115 Filter::ALLOW)); 163 Filter::ALLOW));
116 } else if (base::StartsWith(line, deny_str, 164 } else if (base::StartsWith(line, deny_str,
117 base::CompareCase::SENSITIVE)) { 165 base::CompareCase::SENSITIVE)) {
118 filters->push_back(Filter(base::UTF8ToUTF16( 166 filters->push_back(Filter(base::UTF8ToUTF16(
119 line.substr(deny_str.size())), 167 line.substr(deny_str.size())),
120 Filter::DENY)); 168 Filter::DENY));
121 } else if (base::StartsWith(line, wait_str, 169 } else if (base::StartsWith(line, wait_str,
122 base::CompareCase::SENSITIVE)) { 170 base::CompareCase::SENSITIVE)) {
123 *wait_for = line.substr(wait_str.size()); 171 wait_for->push_back(line.substr(wait_str.size()));
124 } 172 }
125 } 173 }
126 } 174 }
127 175
128 AccessibilityTreeFormatter* 176 AccessibilityTreeFormatter*
129 DumpAccessibilityTestBase::CreateAccessibilityTreeFormatter() { 177 DumpAccessibilityTestBase::CreateAccessibilityTreeFormatter() {
130 if (is_blink_pass_) 178 if (is_blink_pass_)
131 return new AccessibilityTreeFormatterBlink(); 179 return new AccessibilityTreeFormatterBlink();
132 else 180 else
133 return AccessibilityTreeFormatter::Create(); 181 return AccessibilityTreeFormatter::Create();
134 } 182 }
135 183
136 void DumpAccessibilityTestBase::RunTest( 184 void DumpAccessibilityTestBase::RunTest(
137 const base::FilePath file_path, const char* file_dir) { 185 const base::FilePath file_path, const char* file_dir) {
138 #if !defined(OS_ANDROID) 186 #if !defined(OS_ANDROID)
139 // The blink tree is different on Android because we exclude inline 187 // The blink tree is different on Android because we exclude inline
140 // text boxes, for performance. 188 // text boxes, for performance.
141 is_blink_pass_ = true; 189 is_blink_pass_ = true;
142 RunTestForPlatform(file_path, file_dir); 190 RunTestForPlatform(file_path, file_dir);
143 #endif 191 #endif
144 is_blink_pass_ = false; 192 is_blink_pass_ = false;
145 RunTestForPlatform(file_path, file_dir); 193 RunTestForPlatform(file_path, file_dir);
146 } 194 }
147 195
148 void DumpAccessibilityTestBase::RunTestForPlatform( 196 void DumpAccessibilityTestBase::RunTestForPlatform(
149 const base::FilePath file_path, const char* file_dir) { 197 const base::FilePath file_path, const char* file_dir) {
198 WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
199 shell()->web_contents());
200 web_contents->AddAccessibilityMode(AccessibilityModeComplete);
201
150 formatter_.reset(CreateAccessibilityTreeFormatter()); 202 formatter_.reset(CreateAccessibilityTreeFormatter());
151 203
152 // Disable the "hot tracked" state (set when the mouse is hovering over 204 // 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. 205 // an object) because it makes test output change based on the mouse position.
154 BrowserAccessibilityStateImpl::GetInstance()-> 206 BrowserAccessibilityStateImpl::GetInstance()->
155 set_disable_hot_tracking_for_testing(true); 207 set_disable_hot_tracking_for_testing(true);
156 208
157 NavigateToURL(shell(), GURL(url::kAboutBlankURL)); 209 NavigateToURL(shell(), GURL(url::kAboutBlankURL));
158 210
159 // Output the test path to help anyone who encounters a failure and needs 211 // 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. 238 // normalize by deleting all \r from the file (if any) to leave only \n.
187 std::string expected_contents; 239 std::string expected_contents;
188 base::RemoveChars(expected_contents_raw, "\r", &expected_contents); 240 base::RemoveChars(expected_contents_raw, "\r", &expected_contents);
189 241
190 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) { 242 if (!expected_contents.compare(0, strlen(kMarkSkipFile), kMarkSkipFile)) {
191 LOG(INFO) << "Skipping this test on this platform."; 243 LOG(INFO) << "Skipping this test on this platform.";
192 return; 244 return;
193 } 245 }
194 246
195 // Parse filters and other directives in the test file. 247 // Parse filters and other directives in the test file.
196 std::string wait_for; 248 std::vector<std::string> wait_for;
197 AddDefaultFilters(&filters_); 249 AddDefaultFilters(&filters_);
198 ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for); 250 ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for);
199 251
200 // Load the page. 252 // Load the page.
201 base::string16 html_contents16; 253 GURL url(embedded_test_server()->GetURL(
202 html_contents16 = base::UTF8ToUTF16(html_contents); 254 "/" + 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 255
218 // Load the test html. 256 // Load the test html.
219 NavigateToURL(shell(), url); 257 NavigateToURL(shell(), url);
220 258
221 // Wait for notifications. If there's a @WAIT-FOR directive, break when 259 // Navigate frames with the @CROSS-SITE: directive to a cross-site url.
222 // the text we're waiting for appears in the dump, otherwise break after 260 const std::string& cross_site_str = "@CROSS-SITE:";
223 // the first notification, which will be a load complete. 261 FrameTree* frame_tree = web_contents->GetFrameTree();
224 do { 262 FrameTreeNode* root = frame_tree->root();
225 waiter->WaitForNotification(); 263 for (size_t i = 0; i < root->child_count(); ++i) {
226 if (!wait_for.empty()) { 264 FrameTreeNode* child_frame_tree_node = root->child_at(i);
227 base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString(); 265 GURL url = child_frame_tree_node->current_url();
228 if (base::UTF16ToUTF8(tree_dump).find(wait_for) != std::string::npos) 266 std::string path = url.path();
229 wait_for.clear(); 267 auto pos = path.find(cross_site_str);
268 if (pos != std::string::npos) {
269 std::string host = base::StringPrintf("site%d.com", static_cast<int>(i));
dcheng 2016/01/07 00:07:11 Per http://google.github.io/styleguide/cppguide.ht
dmazzoni 2016/01/07 19:19:08 Moot due to comment below.
270 GURL cross_site_url(embedded_test_server()->GetURL(
271 host, path.replace(pos, cross_site_str.size(), "")));
272 NavigateFrameToURL(child_frame_tree_node, cross_site_url);
273
274 SiteInstance* site_instance =
275 child_frame_tree_node->current_frame_host()->GetSiteInstance();
276 EXPECT_NE(web_contents->GetSiteInstance(), site_instance);
230 } 277 }
231 } while (!wait_for.empty()); 278 }
nasko 2016/01/07 00:07:37 This loop is unnecessary as we have enough facilit
dmazzoni 2016/01/07 19:19:08 Great idea! For some reason I didn't think I could
279
280 // Get the url of every frame in the frame tree.
281 std::vector<std::string> all_frame_urls;
282 frame_tree->ForEach(base::Bind(GetFrameUrl, &all_frame_urls));
283
284 // Wait for the accessibility tree to fully load for all frames,
285 // by searching for the WEB_AREA node in the accessibility tree
286 // with the url of each frame in our frame tree. Note that this
287 // doesn't support cases where there are two iframes with the
288 // exact same url. If all frames haven't loaded yet, set up a
289 // listener for accessibility events on any frame and block
290 // until the next one is received.
291 //
292 // If the original page has a @WAIT-FOR directive, don't break until
293 // the text we're waiting for appears in the full text dump of the
294 // accessibility tree, either.
295 for (;;) {
296 VLOG(1) << "Top of loop";
297 RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
298 web_contents->GetMainFrame());
299 BrowserAccessibility* accessibility_root =
300 main_frame->browser_accessibility_manager()->GetRoot();
301
302 // Check to see if all frames have loaded.
303 bool all_frames_loaded = true;
304 for (auto& url : all_frame_urls) {
dcheng 2016/01/07 00:07:11 const auto&, since mutability isn't required
dmazzoni 2016/01/07 19:19:08 Done.
305 if (!AccessibilityTreeContainsLoadedDocWithUrl(accessibility_root, url)) {
306 VLOG(1) << "Still waiting on this frame to load: " << url;
307 all_frames_loaded = false;
308 break;
309 }
310 }
311
312 // Check to see if the @WAIT-FOR text has appeared yet.
313 bool all_wait_for_strings_found = true;
314 base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString();
315 for (auto& str : wait_for) {
dcheng 2016/01/07 00:07:11 const auto&
dmazzoni 2016/01/07 19:19:08 Done.
316 if (base::UTF16ToUTF8(tree_dump).find(str) == std::string::npos) {
317 VLOG(1) << "Still waiting on this text to be found: " << str;
318 all_wait_for_strings_found = false;
319 break;
320 }
321 }
322
323 // If all frames have loaded and the @WAIT-FOR text has appeared,
324 // we're done.
325 if (all_frames_loaded && all_wait_for_strings_found)
326 break;
327
328 // Block until the next accessibility notification in any frame.
329 VLOG(1) << "Waiting until the next accessibility event";
330 AccessibilityNotificationWaiter accessibility_waiter(main_frame,
331 ui::AX_EVENT_NONE);
332 frame_tree->ForEach(base::Bind(ListenToFrame, &accessibility_waiter));
333 accessibility_waiter.WaitForNotification();
334 }
232 335
233 // Call the subclass to dump the output. 336 // Call the subclass to dump the output.
234 std::vector<std::string> actual_lines = Dump(); 337 std::vector<std::string> actual_lines = Dump();
235 338
236 // Perform a diff (or write the initial baseline). 339 // Perform a diff (or write the initial baseline).
237 std::vector<std::string> expected_lines = base::SplitString( 340 std::vector<std::string> expected_lines = base::SplitString(
238 expected_contents, "\n", base::KEEP_WHITESPACE, 341 expected_contents, "\n", base::KEEP_WHITESPACE,
239 base::SPLIT_WANT_NONEMPTY); 342 base::SPLIT_WANT_NONEMPTY);
240 // Marking the end of the file with a line of text ensures that 343 // Marking the end of the file with a line of text ensures that
241 // file length differences are found. 344 // 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())); 381 expected_file, actual_contents.c_str(), actual_contents.size()));
279 LOG(INFO) << "Wrote expectations to: " 382 LOG(INFO) << "Wrote expectations to: "
280 << expected_file.LossyDisplayName(); 383 << expected_file.LossyDisplayName();
281 } 384 }
282 } else { 385 } else {
283 LOG(INFO) << "Test output matches expectations."; 386 LOG(INFO) << "Test output matches expectations.";
284 } 387 }
285 } 388 }
286 389
287 } // namespace content 390 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698