summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content/browser/accessibility/dump_accessibility_tree_browsertest.cc80
-rw-r--r--content/renderer/accessibility/renderer_accessibility_complete.cc29
-rw-r--r--content/test/accessibility_browser_test_utils.cc6
-rw-r--r--content/test/accessibility_browser_test_utils.h1
-rw-r--r--content/test/data/accessibility/transition-expected-android.txt5
-rw-r--r--content/test/data/accessibility/transition-expected-mac.txt4
-rw-r--r--content/test/data/accessibility/transition-expected-win.txt4
-rw-r--r--content/test/data/accessibility/transition.html58
8 files changed, 163 insertions, 24 deletions
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 543b06c..de73995 100644
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -93,8 +93,27 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
filters->push_back(Filter(base::ASCIIToUTF16("*=''"), Filter::DENY));
}
- void ParseFilters(const std::string& test_html,
- std::vector<Filter>* filters) {
+ // Parse the test html file and parse special directives, usually
+ // beginning with an '@' and inside an HTML comment, that control how the
+ // test is run and how the results are interpreted.
+ //
+ // When the accessibility tree is dumped as text, each attribute is
+ // run through filters before being appended to the string. An "allow"
+ // filter specifies attribute strings that should be dumped, and a "deny"
+ // filter specifies strings that should be suppressed. As an example,
+ // @MAC-ALLOW:AXSubrole=* means that the AXSubrole attribute should be
+ // printed, while @MAC-ALLOW:AXSubrole=AXList* means that any subrole
+ // beginning with the text "AXList" should be printed.
+ //
+ // The @WAIT-FOR:text directive allows the test to specify that the document
+ // may dynamically change after initial load, and the test is to wait
+ // until the given string (e.g., "text") appears in the resulting dump.
+ // A test can make some changes to the document, then append a magic string
+ // indicating that the test is done, and this framework will wait for that
+ // string to appear before comparing the results.
+ void ParseHtmlForExtraDirectives(const std::string& test_html,
+ std::vector<Filter>* filters,
+ std::string* wait_for) {
std::vector<std::string> lines;
base::SplitString(test_html, '\n', &lines);
for (std::vector<std::string>::const_iterator iter = lines.begin();
@@ -107,6 +126,7 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
AccessibilityTreeFormatter::GetAllowString();
const std::string& deny_str =
AccessibilityTreeFormatter::GetDenyString();
+ const std::string& wait_str = "@WAIT-FOR:";
if (StartsWithASCII(line, allow_empty_str, true)) {
filters->push_back(
Filter(base::UTF8ToUTF16(line.substr(allow_empty_str.size())),
@@ -119,6 +139,8 @@ class DumpAccessibilityTreeTest : public ContentBrowserTest {
filters->push_back(Filter(base::UTF8ToUTF16(
line.substr(deny_str.size())),
Filter::DENY));
+ } else if (StartsWithASCII(line, wait_str, true)) {
+ *wait_for = line.substr(wait_str.size());
}
}
}
@@ -170,32 +192,52 @@ void DumpAccessibilityTreeTest::RunTest(
return;
}
+ // Parse filters and other directives in the test file.
+ std::vector<Filter> filters;
+ 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("accessibility",
html_file.BaseName().MaybeAsASCII().c_str());
- AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
+
+ // 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));
+ }
+
+ // Load the test html.
NavigateToURL(shell(), url);
- waiter.WaitForNotification();
+ // 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.
RenderWidgetHostViewBase* host_view = static_cast<RenderWidgetHostViewBase*>(
shell()->web_contents()->GetRenderWidgetHostView());
- AccessibilityTreeFormatter formatter(
- host_view->GetBrowserAccessibilityManager()->GetRoot());
-
- // Parse filters in the test file.
- std::vector<Filter> filters;
- AddDefaultFilters(&filters);
- ParseFilters(html_contents, &filters);
- formatter.SetFilters(filters);
+ std::string actual_contents;
+ do {
+ waiter->WaitForNotification();
+ base::string16 actual_contents_utf16;
+ AccessibilityTreeFormatter formatter(
+ host_view->GetBrowserAccessibilityManager()->GetRoot());
+ formatter.SetFilters(filters);
+ formatter.FormatAccessibilityTree(&actual_contents_utf16);
+ actual_contents = base::UTF16ToUTF8(actual_contents_utf16);
+ } while (!wait_for.empty() &&
+ actual_contents.find(wait_for) == std::string::npos);
// Perform a diff (or write the initial baseline).
- base::string16 actual_contents_utf16;
- formatter.FormatAccessibilityTree(&actual_contents_utf16);
- std::string actual_contents = base::UTF16ToUTF8(actual_contents_utf16);
std::vector<std::string> actual_lines, expected_lines;
Tokenize(actual_contents, "\n", &actual_lines);
Tokenize(expected_contents, "\n", &expected_lines);
@@ -530,6 +572,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTableSpans) {
RunTest(FILE_PATH_LITERAL("table-spans.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTransition) {
+ RunTest(FILE_PATH_LITERAL("transition.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityToggleButton) {
RunTest(FILE_PATH_LITERAL("togglebutton.html"));
diff --git a/content/renderer/accessibility/renderer_accessibility_complete.cc b/content/renderer/accessibility/renderer_accessibility_complete.cc
index 2e72dde..e7765d4 100644
--- a/content/renderer/accessibility/renderer_accessibility_complete.cc
+++ b/content/renderer/accessibility/renderer_accessibility_complete.cc
@@ -177,16 +177,21 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
// Generate an event message from each Blink event.
std::vector<AccessibilityHostMsg_EventParams> event_msgs;
+ // If there's a layout complete message, we need to send location changes.
+ bool had_layout_complete_messages = false;
+
// Loop over each event and generate an updated event message.
for (size_t i = 0; i < src_events.size(); ++i) {
- AccessibilityHostMsg_EventParams& event =
- src_events[i];
+ AccessibilityHostMsg_EventParams& event = src_events[i];
+ if (event.event_type == ui::AX_EVENT_LAYOUT_COMPLETE)
+ had_layout_complete_messages = true;
+
+ WebAXObject obj = document.accessibilityObjectFromID(event.id);
- WebAXObject obj = document.accessibilityObjectFromID(
- event.id);
// Make sure the object still exists.
if (!obj.updateBackingStoreAndCheckValidity())
continue;
+
// Make sure it's a descendant of our root node - exceptions include the
// scroll area that's the parent of the main document (we ignore it), and
// possibly nodes attached to a different document.
@@ -207,6 +212,13 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
serializer_.SerializeChanges(obj, &event_msg.update);
event_msgs.push_back(event_msg);
+ // For each node in the update, set the location in our map from
+ // ids to locations.
+ for (size_t i = 0; i < event_msg.update.nodes.size(); ++i) {
+ locations_[event_msg.update.nodes[i].id] =
+ event_msg.update.nodes[i].location;
+ }
+
VLOG(0) << "Accessibility event: " << ui::ToString(event.event_type)
<< " on node id " << event_msg.id
<< "\n" << event_msg.update.ToString();
@@ -214,7 +226,8 @@ void RendererAccessibilityComplete::SendPendingAccessibilityEvents() {
Send(new AccessibilityHostMsg_Events(routing_id(), event_msgs));
- SendLocationChanges();
+ if (had_layout_complete_messages)
+ SendLocationChanges();
}
void RendererAccessibilityComplete::SendLocationChanges() {
@@ -246,6 +259,12 @@ void RendererAccessibilityComplete::SendLocationChanges() {
// Save the new location.
new_locations[id] = new_location;
+
+ // Explore children of this object.
+ std::vector<blink::WebAXObject> children;
+ tree_source_.GetChildren(obj, &children);
+ for (size_t i = 0; i < children.size(); ++i)
+ objs_to_explore.push(children[i]);
}
locations_.swap(new_locations);
diff --git a/content/test/accessibility_browser_test_utils.cc b/content/test/accessibility_browser_test_utils.cc
index ba0331c..deb3deb 100644
--- a/content/test/accessibility_browser_test_utils.cc
+++ b/content/test/accessibility_browser_test_utils.cc
@@ -56,6 +56,10 @@ AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() {
void AccessibilityNotificationWaiter::WaitForNotification() {
loop_runner_->Run();
+
+ // Each loop runner can only be called once. Create a new one in case
+ // the caller wants to call this again to wait for the next notification.
+ loop_runner_ = new MessageLoopRunner();
}
const ui::AXTree& AccessibilityNotificationWaiter::GetAXTree() const {
@@ -64,7 +68,7 @@ const ui::AXTree& AccessibilityNotificationWaiter::GetAXTree() const {
void AccessibilityNotificationWaiter::OnAccessibilityEvent(
ui::AXEvent event_type, int event_target_id) {
- if (!IsAboutBlank() && (event_to_wait_for_ == ui::AX_EVENT_NONE ||
+ if (!IsAboutBlank() && (event_to_wait_for_ == ui::AX_EVENT_NONE ||
event_to_wait_for_ == event_type)) {
event_target_id_ = event_target_id;
loop_runner_->Quit();
diff --git a/content/test/accessibility_browser_test_utils.h b/content/test/accessibility_browser_test_utils.h
index 5111e3c..3c134ea 100644
--- a/content/test/accessibility_browser_test_utils.h
+++ b/content/test/accessibility_browser_test_utils.h
@@ -24,7 +24,6 @@ class Shell;
class AccessibilityNotificationWaiter {
public:
explicit AccessibilityNotificationWaiter(Shell* shell);
-
AccessibilityNotificationWaiter(
Shell* shell,
AccessibilityMode accessibility_mode,
diff --git a/content/test/data/accessibility/transition-expected-android.txt b/content/test/data/accessibility/transition-expected-android.txt
new file mode 100644
index 0000000..37ef40e
--- /dev/null
+++ b/content/test/data/accessibility/transition-expected-android.txt
@@ -0,0 +1,5 @@
+#<skip - Android doesn't output the location and size of objects.>
+android.webkit.WebView focusable scrollable
+ android.view.View
+ android.widget.Button clickable focusable focused name='GrowButton'
+ android.view.View clickable name='Done'
diff --git a/content/test/data/accessibility/transition-expected-mac.txt b/content/test/data/accessibility/transition-expected-mac.txt
new file mode 100644
index 0000000..f2043b1
--- /dev/null
+++ b/content/test/data/accessibility/transition-expected-mac.txt
@@ -0,0 +1,4 @@
+AXWebArea
+ AXGroup
+ AXButton AXTitle='GrowButton' size=(600, 300)
+ AXStaticText AXValue='Done'
diff --git a/content/test/data/accessibility/transition-expected-win.txt b/content/test/data/accessibility/transition-expected-win.txt
new file mode 100644
index 0000000..743cb39
--- /dev/null
+++ b/content/test/data/accessibility/transition-expected-win.txt
@@ -0,0 +1,4 @@
+ROLE_SYSTEM_DOCUMENT READONLY FOCUSABLE
+ IA2_ROLE_SECTION READONLY
+ ROLE_SYSTEM_PUSHBUTTON name='GrowButton' FOCUSABLE size=(600, 300)
+ ROLE_SYSTEM_STATICTEXT name='Done'
diff --git a/content/test/data/accessibility/transition.html b/content/test/data/accessibility/transition.html
new file mode 100644
index 0000000..df42c6a
--- /dev/null
+++ b/content/test/data/accessibility/transition.html
@@ -0,0 +1,58 @@
+<!doctype html>
+<!--
+This tests that location changes are sent when an element animates
+using CSS transitions. The test animates the size of a button when
+focused, then adds the magic text "Done" to the document when
+the transition finishes. The WAIT-FOR directive below instructs
+the test framework to keep waiting for accessibility events and
+not diff the dump against the expectations until the text "Done"
+appears in the dump.
+
+@MAC-ALLOW:size=(400, 200)
+@MAC-ALLOW:size=(600, 300)
+@WIN-ALLOW:size=(400, 200)
+@WIN-ALLOW:size=(600, 300)
+@WAIT-FOR:Done
+-->
+<html>
+<head>
+<style>
+body {
+ width: 800px;
+ height: 600px;
+ margin: 0;
+ padding: 0;
+ border: 0;
+ overflow: hidden;
+}
+#growbutton {
+ width: 400px;
+ height: 200px;
+ margin: 0;
+ padding: 0;
+}
+#growbutton:focus {
+ width: 600px;
+ height: 300px;
+ transition: all 0.1s ease-in-out;
+}
+</style>
+</head>
+<body>
+
+<button id="growbutton">GrowButton</button>
+
+<script>
+ var growButton = document.getElementById('growbutton');
+ var done = false;
+ growButton.addEventListener('webkitTransitionEnd', function() {
+ if (!done) {
+ document.body.appendChild(document.createTextNode('Done'));
+ done = true;
+ }
+ }, false);
+ growButton.focus();
+</script>
+
+</body>
+</html>