diff options
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.cc | 11 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 18 | ||||
-rw-r--r-- | chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc | 109 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 3 | ||||
-rw-r--r-- | chrome/common/render_messages.cc | 4 | ||||
-rw-r--r-- | chrome/common/render_messages_unittest.cc | 13 | ||||
-rw-r--r-- | webkit/glue/webaccessibility.cc | 34 | ||||
-rw-r--r-- | webkit/glue/webaccessibility.h | 12 |
8 files changed, 196 insertions, 8 deletions
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc index 0af74c3..10b3ce0 100644 --- a/chrome/browser/renderer_host/render_view_host.cc +++ b/chrome/browser/renderer_host/render_view_host.cc @@ -52,11 +52,6 @@ #include "webkit/glue/webaccessibility.h" #include "webkit/glue/webdropdata.h" -#if defined(OS_WIN) -// TODO(port): accessibility not yet implemented. See http://crbug.com/8288. -#include "chrome/browser/browser_accessibility_manager_win.h" -#endif - using base::TimeDelta; using webkit_glue::FormData; using webkit_glue::PasswordForm; @@ -134,7 +129,8 @@ RenderViewHost::RenderViewHost(SiteInstance* instance, sudden_termination_allowed_(false), session_storage_namespace_id_(session_storage_namespace_id), is_extension_process_(false), - autofill_query_id_(0) { + autofill_query_id_(0), + save_accessibility_tree_for_testing_(false) { DCHECK(instance_); DCHECK(delegate_); } @@ -1970,6 +1966,9 @@ void RenderViewHost::OnAccessibilityTree( if (view()) view()->UpdateAccessibilityTree(tree); + if (save_accessibility_tree_for_testing_) + accessibility_tree_ = tree; + NotificationService::current()->Notify( NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED, Source<RenderViewHost>(this), diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 6dad785..a2b4783 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -22,6 +22,7 @@ #include "third_party/WebKit/WebKit/chromium/public/WebDragOperation.h" #include "third_party/WebKit/WebKit/chromium/public/WebPopupType.h" #include "third_party/WebKit/WebKit/chromium/public/WebTextDirection.h" +#include "webkit/glue/webaccessibility.h" #include "webkit/glue/window_open_disposition.h" class FilePath; @@ -475,7 +476,16 @@ class RenderViewHost : public RenderWidgetHost { void EnablePreferredSizeChangedMode(int flags); #if defined(UNIT_TEST) - // This shouldn't be necessary outside of testing. + // These functions shouldn't be necessary outside of testing. + + void set_save_accessibility_tree_for_testing(bool save) { + save_accessibility_tree_for_testing_ = save; + } + + const webkit_glue::WebAccessibility& accessibility_tree() { + return accessibility_tree_; + } + bool is_waiting_for_unload_ack() { return is_waiting_for_unload_ack_; } #endif @@ -744,6 +754,12 @@ class RenderViewHost : public RenderWidgetHost { std::vector<string16> autofill_icons_; std::vector<int> autofill_unique_ids_; + // Whether the accessibility tree should be saved, for unit testing. + bool save_accessibility_tree_for_testing_; + + // The most recently received accessibility tree - for unit testing only. + webkit_glue::WebAccessibility accessibility_tree_; + DISALLOW_COPY_AND_ASSIGN(RenderViewHost); }; diff --git a/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc new file mode 100644 index 0000000..4f8fb5d --- /dev/null +++ b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc @@ -0,0 +1,109 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> +#include <vector> + +#include "base/utf_string_conversions.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_window.h" +#include "chrome/browser/renderer_host/render_view_host.h" +#include "chrome/browser/renderer_host/render_widget_host.h" +#include "chrome/browser/renderer_host/render_widget_host_view.h" +#include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/render_messages.h" +#include "chrome/common/notification_type.h" +#include "chrome/test/in_process_browser_test.h" +#include "chrome/test/ui_test_utils.h" + +using webkit_glue::WebAccessibility; + +namespace { + +class RendererAccessibilityBrowserTest : public InProcessBrowserTest { + public: + RendererAccessibilityBrowserTest() {} + + protected: + const char *GetAttr(const WebAccessibility& node, + const WebAccessibility::Attribute attr); +}; + +// Convenience method to get the value of a particular WebAccessibility +// node attribute as a UTF-8 const char*. +const char *RendererAccessibilityBrowserTest::GetAttr( + const WebAccessibility& node, const WebAccessibility::Attribute attr) { + std::map<int32, string16>::const_iterator iter = node.attributes.find(attr); + if (iter != node.attributes.end()) + return UTF16ToUTF8(iter->second).c_str(); + else + return ""; +} + +IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest, + TestCrossPlatformAccessibilityTree) { + // Create a data url and load it. + const char url_str[] = + "data:text/html," + "<!doctype html>" + "<html><head><title>Accessibility Test</title></head>" + "<body><input type='button' value='push' /><input type='checkbox' />" + "</body></html>"; + GURL url(url_str); + browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED); + + // Tell the renderer to send an accessibility tree, then wait for the + // notification that it's been received. + RenderWidgetHostView* host_view = + browser()->GetSelectedTabContents()->GetRenderWidgetHostView(); + RenderWidgetHost* host = host_view->GetRenderWidgetHost(); + RenderViewHost* view_host = static_cast<RenderViewHost*>(host); + view_host->set_save_accessibility_tree_for_testing(true); + host->Send(new ViewMsg_GetAccessibilityTree(host->routing_id())); + ui_test_utils::WaitForNotification( + NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); + + // Check properties of the root element of the tree. + const WebAccessibility& tree = view_host->accessibility_tree(); + EXPECT_STREQ(url_str, GetAttr(tree, WebAccessibility::ATTR_DOC_URL)); + EXPECT_STREQ("Accessibility Test", + GetAttr(tree, WebAccessibility::ATTR_DOC_TITLE)); + EXPECT_STREQ("html", GetAttr(tree, WebAccessibility::ATTR_DOC_DOCTYPE)); + EXPECT_STREQ("text/html", GetAttr(tree, WebAccessibility::ATTR_DOC_MIMETYPE)); + EXPECT_EQ(WebAccessibility::ROLE_WEB_AREA, tree.role); + + // Check properites of the BODY element. + ASSERT_EQ(1U, tree.children.size()); + const WebAccessibility& body = tree.children[0]; + EXPECT_EQ(WebAccessibility::ROLE_GROUP, body.role); + EXPECT_STREQ("BODY", GetAttr(body, WebAccessibility::ATTR_HTML_TAG)); + EXPECT_STREQ("block", GetAttr(body, WebAccessibility::ATTR_DISPLAY)); + + // Check properties of the two children of the BODY element. + ASSERT_EQ(2U, body.children.size()); + + const WebAccessibility& button = body.children[0]; + EXPECT_EQ(WebAccessibility::ROLE_BUTTON, button.role); + EXPECT_STREQ("INPUT", GetAttr(button, WebAccessibility::ATTR_HTML_TAG)); + EXPECT_STREQ("push", UTF16ToUTF8(button.name).c_str()); + EXPECT_STREQ("inline-block", GetAttr(button, WebAccessibility::ATTR_DISPLAY)); + ASSERT_EQ(2U, button.html_attributes.size()); + EXPECT_STREQ("type", UTF16ToUTF8(button.html_attributes[0].first).c_str()); + EXPECT_STREQ("button", UTF16ToUTF8(button.html_attributes[0].second).c_str()); + EXPECT_STREQ("value", UTF16ToUTF8(button.html_attributes[1].first).c_str()); + EXPECT_STREQ("push", UTF16ToUTF8(button.html_attributes[1].second).c_str()); + + const WebAccessibility& checkbox = body.children[1]; + EXPECT_EQ(WebAccessibility::ROLE_CHECKBOX, checkbox.role); + EXPECT_STREQ("INPUT", GetAttr(checkbox, WebAccessibility::ATTR_HTML_TAG)); + EXPECT_STREQ("inline-block", + GetAttr(checkbox, WebAccessibility::ATTR_DISPLAY)); + ASSERT_EQ(1U, checkbox.html_attributes.size()); + EXPECT_STREQ("type", + UTF16ToUTF8(checkbox.html_attributes[0].first).c_str()); + EXPECT_STREQ("checkbox", + UTF16ToUTF8(checkbox.html_attributes[0].second).c_str()); +} + +} // namespace diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index f672664..19aed38 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1754,9 +1754,10 @@ 'browser/net/cookie_policy_browsertest.cc', 'browser/net/ftp_browsertest.cc', 'browser/printing/print_dialog_cloud_uitest.cc', - 'browser/renderer_host/test/web_cache_manager_browsertest.cc', 'browser/renderer_host/test/render_process_host_browsertest.cc', 'browser/renderer_host/test/render_view_host_manager_browsertest.cc', + 'browser/renderer_host/test/renderer_accessibility_browsertest.cc', + 'browser/renderer_host/test/web_cache_manager_browsertest.cc', 'browser/safe_browsing/safe_browsing_browsertest.cc', 'browser/service/service_process_control_browsertest.cc', 'browser/sessions/session_restore_browsertest.cc', diff --git a/chrome/common/render_messages.cc b/chrome/common/render_messages.cc index 1c60413..011a979 100644 --- a/chrome/common/render_messages.cc +++ b/chrome/common/render_messages.cc @@ -794,6 +794,7 @@ void ParamTraits<webkit_glue::WebAccessibility>::Write(Message* m, WriteParam(m, p.location); WriteParam(m, p.attributes); WriteParam(m, p.children); + WriteParam(m, p.html_attributes); } bool ParamTraits<webkit_glue::WebAccessibility>::Read( @@ -815,6 +816,7 @@ bool ParamTraits<webkit_glue::WebAccessibility>::Read( ret = ret && ReadParam(m, iter, &p->location); ret = ret && ReadParam(m, iter, &p->attributes); ret = ret && ReadParam(m, iter, &p->children); + ret = ret && ReadParam(m, iter, &p->html_attributes); return ret; } @@ -836,6 +838,8 @@ void ParamTraits<webkit_glue::WebAccessibility>::Log(const param_type& p, LogParam(p.attributes, l); l->append(", "); LogParam(p.children, l); + l->append(", "); + LogParam(p.html_attributes, l); l->append(")"); } diff --git a/chrome/common/render_messages_unittest.cc b/chrome/common/render_messages_unittest.cc index 4fc0aab..d45d5df 100644 --- a/chrome/common/render_messages_unittest.cc +++ b/chrome/common/render_messages_unittest.cc @@ -23,6 +23,10 @@ TEST(RenderMessagesUnittest, WebAccessibility) { (1 << webkit_glue::WebAccessibility::STATE_CHECKED) | (1 << webkit_glue::WebAccessibility::STATE_FOCUSED); input.location = WebKit::WebRect(11, 22, 333, 444); + input.html_attributes.push_back( + std::pair<string16, string16>(ASCIIToUTF16("id"), ASCIIToUTF16("a"))); + input.html_attributes.push_back( + std::pair<string16, string16>(ASCIIToUTF16("class"), ASCIIToUTF16("b"))); IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL); IPC::WriteParam(&msg, input); @@ -39,6 +43,15 @@ TEST(RenderMessagesUnittest, WebAccessibility) { EXPECT_EQ(input.state, output.state); EXPECT_EQ(input.location, output.location); EXPECT_EQ(input.children.size(), output.children.size()); + EXPECT_EQ(input.html_attributes.size(), output.html_attributes.size()); + EXPECT_EQ(input.html_attributes[0].first, + output.html_attributes[0].first); + EXPECT_EQ(input.html_attributes[0].second, + output.html_attributes[0].second); + EXPECT_EQ(input.html_attributes[1].first, + output.html_attributes[1].first); + EXPECT_EQ(input.html_attributes[1].second, + output.html_attributes[1].second); // Test a corrupt case. IPC::Message bad_msg(1, 2, IPC::Message::PRIORITY_NORMAL); diff --git a/webkit/glue/webaccessibility.cc b/webkit/glue/webaccessibility.cc index b6e0d5e..8b007d3 100644 --- a/webkit/glue/webaccessibility.cc +++ b/webkit/glue/webaccessibility.cc @@ -7,6 +7,13 @@ #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityCache.h" #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityObject.h" #include "third_party/WebKit/WebKit/chromium/public/WebAccessibilityRole.h" +#include "third_party/WebKit/WebKit/chromium/public/WebAttribute.h" +#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h" +#include "third_party/WebKit/WebKit/chromium/public/WebDocumentType.h" +#include "third_party/WebKit/WebKit/chromium/public/WebElement.h" +#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h" +#include "third_party/WebKit/WebKit/chromium/public/WebNamedNodeMap.h" +#include "third_party/WebKit/WebKit/chromium/public/WebNode.h" #include "third_party/WebKit/WebKit/chromium/public/WebString.h" using WebKit::WebAccessibilityCache; @@ -285,6 +292,33 @@ void WebAccessibility::Init(const WebKit::WebAccessibilityObject& src, attributes[ATTR_HELP] = src.helpText(); if (src.keyboardShortcut().length()) attributes[ATTR_SHORTCUT] = src.keyboardShortcut(); + if (src.hasComputedStyle()) + attributes[ATTR_DISPLAY] = src.computedStyleDisplay(); + + WebKit::WebNode node = src.node(); + + if (!node.isNull() && node.isElementNode()) { + WebKit::WebElement element = node.to<WebKit::WebElement>(); + attributes[ATTR_HTML_TAG] = element.tagName(); + for (unsigned i = 0; i < element.attributes().length(); i++) { + html_attributes.push_back( + std::pair<string16, string16>( + element.attributes().attributeItem(i).localName(), + element.attributes().attributeItem(i).value())); + } + } + + if (role == WebAccessibility::ROLE_DOCUMENT || + role == WebAccessibility::ROLE_WEB_AREA) { + WebKit::WebDocument document = src.document(); + attributes[ATTR_DOC_TITLE] = document.title(); + attributes[ATTR_DOC_URL] = document.frame()->url().spec().utf16(); + if (document.isXHTMLDocument()) + attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/xhtml"); + else + attributes[ATTR_DOC_MIMETYPE] = WebKit::WebString("text/html"); + attributes[ATTR_DOC_DOCTYPE] = document.doctype().name(); + } // Add the source object to the cache and store its id. id = cache->addOrGetId(src); diff --git a/webkit/glue/webaccessibility.h b/webkit/glue/webaccessibility.h index 305bc0ca..1836948 100644 --- a/webkit/glue/webaccessibility.h +++ b/webkit/glue/webaccessibility.h @@ -147,9 +147,20 @@ struct WebAccessibility { STATE_UNAVAILABLE }; + // Additional optional attributes that can be optionally attached to + // a node. enum Attribute { + // Doc attributes: only make sense when applied to the top-level + // Document node. + ATTR_DOC_URL, + ATTR_DOC_TITLE, + ATTR_DOC_MIMETYPE, + ATTR_DOC_DOCTYPE, + + // Attributes that could apply to any node. ATTR_ACTION, ATTR_DESCRIPTION, + ATTR_DISPLAY, ATTR_HELP, ATTR_HTML_TAG, ATTR_LINK_TARGET, @@ -180,6 +191,7 @@ struct WebAccessibility { WebKit::WebRect location; std::map<int32, string16> attributes; std::vector<WebAccessibility> children; + std::vector<std::pair<string16, string16> > html_attributes; }; } // namespace webkit_glue |