Chromium Code Reviews| Index: content/browser/accessibility/dump_accessibility_browsertest_base.cc |
| diff --git a/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/content/browser/accessibility/dump_accessibility_browsertest_base.cc |
| index b5dd3296ef3106a32025b15a1a7cf93b335578a6..0deee310cb662f36c4acfb4c03bf0864052c0acb 100644 |
| --- a/content/browser/accessibility/dump_accessibility_browsertest_base.cc |
| +++ b/content/browser/accessibility/dump_accessibility_browsertest_base.cc |
| @@ -30,6 +30,7 @@ |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/shell/browser/shell.h" |
| #include "content/test/accessibility_browser_test_utils.h" |
| +#include "content/test/content_browser_test_utils_internal.h" |
| namespace content { |
| @@ -40,6 +41,53 @@ const char kMarkSkipFile[] = "#<skip"; |
| const char kMarkEndOfFile[] = "<-- End-of-file -->"; |
| const char kSignalDiff[] = "*"; |
| +// Helper function to be used with FrameTree::ForEach, so that |
| +// AccessibilityNotificationWaiter can listen for accessibility |
| +// events in all frames. |
| +bool ListenToFrame(AccessibilityNotificationWaiter* waiter, |
| + FrameTreeNode* frame_tree_node) { |
| + waiter->ListenToAdditionalFrame(frame_tree_node->current_frame_host()); |
| + 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
|
| +} |
| + |
| +// Helper function to be used with FrameTree::ForEach, to get the |
| +// url of all frames. |
| +bool GetFrameUrl(std::vector<std::string>* all_frame_urls, |
| + FrameTreeNode* frame_tree_node) { |
| + std::string url = frame_tree_node->current_url().spec(); |
| + 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
|
| + all_frame_urls->push_back(url); |
| + return true; |
| +} |
| + |
| +// 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.
|
| +// is found that represents a fully loaded web document with the |
| +// given url. |
| +bool AccessibilityTreeContainsLoadedDocWithUrl(BrowserAccessibility* node, |
| + const std::string& url) { |
| + if ((node->GetRole() == ui::AX_ROLE_WEB_AREA || |
| + node->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) && |
| + node->GetStringAttribute(ui::AX_ATTR_URL) == url) { |
| + // If possible, ensure the doc has finished loading. That's currently |
| + // 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.
|
| + // fixed. |
| + if (node->manager()->GetTreeData().url == url && |
| + !node->manager()->GetTreeData().loaded) { |
| + return false; |
| + } |
| + |
| + 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.
|
| + } |
| + |
| + for (unsigned i = 0; i < node->PlatformChildCount(); i++) { |
| + if (AccessibilityTreeContainsLoadedDocWithUrl( |
| + node->PlatformGetChild(i), url)) { |
| + return true; |
| + } |
| + } |
| + return false; |
| +} |
| + |
| } // namespace |
| typedef AccessibilityTreeFormatter::Filter Filter; |
| @@ -95,7 +143,7 @@ std::vector<int> DumpAccessibilityTestBase::DiffLines( |
| void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives( |
| const std::string& test_html, |
| std::vector<Filter>* filters, |
| - std::string* wait_for) { |
| + std::vector<std::string>* wait_for) { |
| for (const std::string& line : |
| base::SplitString(test_html, "\n", base::TRIM_WHITESPACE, |
| base::SPLIT_WANT_ALL)) { |
| @@ -120,7 +168,7 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives( |
| Filter::DENY)); |
| } else if (base::StartsWith(line, wait_str, |
| base::CompareCase::SENSITIVE)) { |
| - *wait_for = line.substr(wait_str.size()); |
| + wait_for->push_back(line.substr(wait_str.size())); |
| } |
| } |
| } |
| @@ -147,6 +195,10 @@ void DumpAccessibilityTestBase::RunTest( |
| void DumpAccessibilityTestBase::RunTestForPlatform( |
| const base::FilePath file_path, const char* file_dir) { |
| + WebContentsImpl* web_contents = static_cast<WebContentsImpl*>( |
| + shell()->web_contents()); |
| + web_contents->AddAccessibilityMode(AccessibilityModeComplete); |
| + |
| formatter_.reset(CreateAccessibilityTreeFormatter()); |
| // Disable the "hot tracked" state (set when the mouse is hovering over |
| @@ -193,42 +245,93 @@ void DumpAccessibilityTestBase::RunTestForPlatform( |
| } |
| // Parse filters and other directives in the test file. |
| - std::string wait_for; |
| + std::vector<std::string> wait_for; |
| AddDefaultFilters(&filters_); |
| ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for); |
| // Load the page. |
| - base::string16 html_contents16; |
| - html_contents16 = base::UTF8ToUTF16(html_contents); |
| - GURL url = GetTestUrl(file_dir, file_path.BaseName().MaybeAsASCII().c_str()); |
| - |
| - // If there's a @WAIT-FOR directive, set up an accessibility notification |
| - // waiter that returns on any event; we'll stop when we get the text we're |
| - // waiting for, or time out. Otherwise just wait specifically for |
| - // the "load complete" event. |
| - scoped_ptr<AccessibilityNotificationWaiter> waiter; |
| - if (!wait_for.empty()) { |
| - waiter.reset(new AccessibilityNotificationWaiter( |
| - shell(), AccessibilityModeComplete, ui::AX_EVENT_NONE)); |
| - } else { |
| - waiter.reset(new AccessibilityNotificationWaiter( |
| - shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE)); |
| - } |
| + GURL url(embedded_test_server()->GetURL( |
| + "/" + std::string(file_dir) + "/" + file_path.BaseName().MaybeAsASCII())); |
| // Load the test html. |
| NavigateToURL(shell(), url); |
| - // Wait for notifications. If there's a @WAIT-FOR directive, break when |
| - // the text we're waiting for appears in the dump, otherwise break after |
| - // the first notification, which will be a load complete. |
| - do { |
| - waiter->WaitForNotification(); |
| - if (!wait_for.empty()) { |
| - base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString(); |
| - if (base::UTF16ToUTF8(tree_dump).find(wait_for) != std::string::npos) |
| - wait_for.clear(); |
| + // Navigate frames with the @CROSS-SITE: directive to a cross-site url. |
| + const std::string& cross_site_str = "@CROSS-SITE:"; |
| + FrameTree* frame_tree = web_contents->GetFrameTree(); |
| + FrameTreeNode* root = frame_tree->root(); |
| + for (size_t i = 0; i < root->child_count(); ++i) { |
| + FrameTreeNode* child_frame_tree_node = root->child_at(i); |
| + GURL url = child_frame_tree_node->current_url(); |
| + std::string path = url.path(); |
| + auto pos = path.find(cross_site_str); |
| + if (pos != std::string::npos) { |
| + 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.
|
| + GURL cross_site_url(embedded_test_server()->GetURL( |
| + host, path.replace(pos, cross_site_str.size(), ""))); |
| + NavigateFrameToURL(child_frame_tree_node, cross_site_url); |
| + |
| + SiteInstance* site_instance = |
| + child_frame_tree_node->current_frame_host()->GetSiteInstance(); |
| + EXPECT_NE(web_contents->GetSiteInstance(), site_instance); |
| } |
| - } while (!wait_for.empty()); |
| + } |
|
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
|
| + |
| + // Get the url of every frame in the frame tree. |
| + std::vector<std::string> all_frame_urls; |
| + frame_tree->ForEach(base::Bind(GetFrameUrl, &all_frame_urls)); |
| + |
| + // Wait for the accessibility tree to fully load for all frames, |
| + // by searching for the WEB_AREA node in the accessibility tree |
| + // with the url of each frame in our frame tree. Note that this |
| + // doesn't support cases where there are two iframes with the |
| + // exact same url. If all frames haven't loaded yet, set up a |
| + // listener for accessibility events on any frame and block |
| + // until the next one is received. |
| + // |
| + // If the original page has a @WAIT-FOR directive, don't break until |
| + // the text we're waiting for appears in the full text dump of the |
| + // accessibility tree, either. |
| + for (;;) { |
| + VLOG(1) << "Top of loop"; |
| + RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>( |
| + web_contents->GetMainFrame()); |
| + BrowserAccessibility* accessibility_root = |
| + main_frame->browser_accessibility_manager()->GetRoot(); |
| + |
| + // Check to see if all frames have loaded. |
| + bool all_frames_loaded = true; |
| + 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.
|
| + if (!AccessibilityTreeContainsLoadedDocWithUrl(accessibility_root, url)) { |
| + VLOG(1) << "Still waiting on this frame to load: " << url; |
| + all_frames_loaded = false; |
| + break; |
| + } |
| + } |
| + |
| + // Check to see if the @WAIT-FOR text has appeared yet. |
| + bool all_wait_for_strings_found = true; |
| + base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString(); |
| + for (auto& str : wait_for) { |
|
dcheng
2016/01/07 00:07:11
const auto&
dmazzoni
2016/01/07 19:19:08
Done.
|
| + if (base::UTF16ToUTF8(tree_dump).find(str) == std::string::npos) { |
| + VLOG(1) << "Still waiting on this text to be found: " << str; |
| + all_wait_for_strings_found = false; |
| + break; |
| + } |
| + } |
| + |
| + // If all frames have loaded and the @WAIT-FOR text has appeared, |
| + // we're done. |
| + if (all_frames_loaded && all_wait_for_strings_found) |
| + break; |
| + |
| + // Block until the next accessibility notification in any frame. |
| + VLOG(1) << "Waiting until the next accessibility event"; |
| + AccessibilityNotificationWaiter accessibility_waiter(main_frame, |
| + ui::AX_EVENT_NONE); |
| + frame_tree->ForEach(base::Bind(ListenToFrame, &accessibility_waiter)); |
| + accessibility_waiter.WaitForNotification(); |
| + } |
| // Call the subclass to dump the output. |
| std::vector<std::string> actual_lines = Dump(); |