diff options
author | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-01 19:52:04 +0000 |
---|---|---|
committer | dmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-10-01 19:52:04 +0000 |
commit | bd554c644039736cf4eb3944f63b7a8e87c449d9 (patch) | |
tree | c10f024ecd6f3a5665c4eacf6a9c0c81f866a9b1 /chrome | |
parent | 017091110712afd7f2bdba2ab9c97f51d06c87b5 (diff) | |
download | chromium_src-bd554c644039736cf4eb3944f63b7a8e87c449d9.zip chromium_src-bd554c644039736cf4eb3944f63b7a8e87c449d9.tar.gz chromium_src-bd554c644039736cf4eb3944f63b7a8e87c449d9.tar.bz2 |
Make the selection start and end attributes of an html input control
accessible, implement IAccessibleText methods to retrieve this info,
and post a notification when the cursor moves within a text field.
BUG=none
TEST=Added new test to renderer_accessibility_browsertest
Review URL: http://codereview.chromium.org/3389037
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@61216 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/browser_accessibility_manager_win.cc | 95 | ||||
-rw-r--r-- | chrome/browser/browser_accessibility_manager_win.h | 20 | ||||
-rw-r--r-- | chrome/browser/browser_accessibility_win.cc | 134 | ||||
-rw-r--r-- | chrome/browser/browser_accessibility_win.h | 89 | ||||
-rw-r--r-- | chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc | 88 | ||||
-rw-r--r-- | chrome/common/render_messages_params.cc | 2 | ||||
-rw-r--r-- | chrome/common/render_messages_params.h | 3 | ||||
-rw-r--r-- | chrome/renderer/render_view.cc | 5 |
8 files changed, 335 insertions, 101 deletions
diff --git a/chrome/browser/browser_accessibility_manager_win.cc b/chrome/browser/browser_accessibility_manager_win.cc index 7f8b268..653ac20 100644 --- a/chrome/browser/browser_accessibility_manager_win.cc +++ b/chrome/browser/browser_accessibility_manager_win.cc @@ -126,6 +126,10 @@ void BrowserAccessibilityManager::OnAccessibilityNotifications( NOTIFICATION_TYPE_VALUE_CHANGED: OnAccessibilityObjectValueChange(param.acc_obj); break; + case ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED: + OnAccessibilityObjectTextChange(param.acc_obj); + break; default: DCHECK(0); break; @@ -133,6 +137,37 @@ void BrowserAccessibilityManager::OnAccessibilityNotifications( } } +bool BrowserAccessibilityManager::CanModifyTreeInPlace( + BrowserAccessibility* current_root, + const webkit_glue::WebAccessibility& new_root) { + if (current_root->renderer_id() != new_root.id) + return false; + if (current_root->GetChildCount() != new_root.children.size()) + return false; + for (unsigned int i = 0; i < current_root->GetChildCount(); i++) { + if (!CanModifyTreeInPlace(current_root->GetChild(i), + new_root.children[i])) { + return false; + } + } + return true; +} + +void BrowserAccessibilityManager::ModifyTreeInPlace( + BrowserAccessibility* current_root, + const webkit_glue::WebAccessibility& new_root) { + DCHECK_EQ(current_root->renderer_id(), new_root.id); + DCHECK_EQ(current_root->GetChildCount(), new_root.children.size()); + for (unsigned int i = 0; i < current_root->GetChildCount(); i++) + ModifyTreeInPlace(current_root->GetChild(i), new_root.children[i]); + current_root->Initialize( + this, + current_root->GetParent(), + current_root->child_id(), + current_root->index_in_parent(), + new_root); +} + BrowserAccessibility* BrowserAccessibilityManager::UpdateTree( const webkit_glue::WebAccessibility& acc_obj) { base::hash_map<int, LONG>::iterator iter = @@ -145,37 +180,30 @@ BrowserAccessibility* BrowserAccessibilityManager::UpdateTree( if (!old_browser_acc) return NULL; - if (old_browser_acc->GetChildCount() == 0 && acc_obj.children.size() == 0) { - // Reinitialize the BrowserAccessibility if there are no children to update. - old_browser_acc->Initialize( - this, - old_browser_acc->GetParent(), - child_id, - old_browser_acc->index_in_parent(), - acc_obj); - + if (CanModifyTreeInPlace(old_browser_acc, acc_obj)) { + ModifyTreeInPlace(old_browser_acc, acc_obj); return old_browser_acc; - } else { - BrowserAccessibility* new_browser_acc = CreateAccessibilityTree( - old_browser_acc->GetParent(), - child_id, - acc_obj, - old_browser_acc->index_in_parent()); - - if (old_browser_acc->GetParent()) { - old_browser_acc->GetParent()->ReplaceChild( - old_browser_acc, - new_browser_acc); - } else { - DCHECK_EQ(old_browser_acc, root_); - root_ = new_browser_acc; - } - old_browser_acc->InactivateTree(); - old_browser_acc->Release(); - child_id_map_[child_id] = new_browser_acc; + } - return new_browser_acc; + BrowserAccessibility* new_browser_acc = CreateAccessibilityTree( + old_browser_acc->GetParent(), + child_id, + acc_obj, + old_browser_acc->index_in_parent()); + + if (old_browser_acc->GetParent()) { + old_browser_acc->GetParent()->ReplaceChild( + old_browser_acc, + new_browser_acc); + } else { + DCHECK_EQ(old_browser_acc, root_); + root_ = new_browser_acc; } + old_browser_acc->InactivateTree(); + old_browser_acc->Release(); + child_id_map_[child_id] = new_browser_acc; + + return new_browser_acc; } void BrowserAccessibilityManager::OnAccessibilityObjectStateChange( @@ -243,6 +271,17 @@ void BrowserAccessibilityManager::OnAccessibilityObjectValueChange( EVENT_OBJECT_VALUECHANGE, parent_hwnd_, OBJID_CLIENT, child_id); } +void BrowserAccessibilityManager::OnAccessibilityObjectTextChange( + const webkit_glue::WebAccessibility& acc_obj) { + BrowserAccessibility* new_browser_acc = UpdateTree(acc_obj); + if (!new_browser_acc) + return; + + LONG child_id = new_browser_acc->child_id(); + NotifyWinEvent( + IA2_EVENT_TEXT_CARET_MOVED, parent_hwnd_, OBJID_CLIENT, child_id); +} + LONG BrowserAccessibilityManager::GetNextChildID() { // Get the next child ID, and wrap around when we get near the end // of a 32-bit integer range. It's okay to wrap around; we just want diff --git a/chrome/browser/browser_accessibility_manager_win.h b/chrome/browser/browser_accessibility_manager_win.h index 429c66f..76cc2b6 100644 --- a/chrome/browser/browser_accessibility_manager_win.h +++ b/chrome/browser/browser_accessibility_manager_win.h @@ -82,9 +82,23 @@ class BrowserAccessibilityManager { const std::vector<ViewHostMsg_AccessibilityNotification_Params>& params); private: + // Recursively compare the IDs of our subtree to a new subtree received + // from the renderer and return true if their IDs match exactly. + bool CanModifyTreeInPlace( + BrowserAccessibility* current_root, + const webkit_glue::WebAccessibility& new_root); + + // Recursively modify a subtree (by reinitializing) to match a new + // subtree received from the renderer process. Should only be called + // if CanModifyTreeInPlace returned true. + void ModifyTreeInPlace( + BrowserAccessibility* current_root, + const webkit_glue::WebAccessibility& new_root); + // Update the accessibility tree with an updated WebAccessibility tree or - // subtree received from the renderer process. Returns the updated node or - // NULL if no node was updated. + // subtree received from the renderer process. First attempts to modify + // the tree in place, and if that fails, replaces the entire subtree. + // Returns the updated node or NULL if no node was updated. BrowserAccessibility* UpdateTree( const webkit_glue::WebAccessibility& acc_obj); @@ -98,6 +112,8 @@ class BrowserAccessibilityManager { const webkit_glue::WebAccessibility& acc_obj); void OnAccessibilityObjectValueChange( const webkit_glue::WebAccessibility& acc_obj); + void OnAccessibilityObjectTextChange( + const webkit_glue::WebAccessibility& acc_obj); // Returns the next MSAA child id. static LONG GetNextChildID(); diff --git a/chrome/browser/browser_accessibility_win.cc b/chrome/browser/browser_accessibility_win.cc index 61fe5cf..2517bef 100644 --- a/chrome/browser/browser_accessibility_win.cc +++ b/chrome/browser/browser_accessibility_win.cc @@ -5,6 +5,7 @@ #include "chrome/browser/browser_accessibility_win.h" #include "base/logging.h" +#include "base/string_number_conversions.h" #include "base/string_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_accessibility_manager_win.h" @@ -31,8 +32,6 @@ void BrowserAccessibility::Initialize( LONG child_id, LONG index_in_parent, const webkit_glue::WebAccessibility& src) { - DCHECK_EQ(children_.size(), 0U); - manager_ = manager; parent_ = parent; child_id_ = child_id; @@ -44,6 +43,7 @@ void BrowserAccessibility::Initialize( attributes_ = src.attributes; html_attributes_ = src.html_attributes; location_ = src.location; + src_role_ = src.role; InitRoleAndState(src.role, src.state); // Expose headings levels to NVDA with the "level" object attribute. @@ -106,6 +106,11 @@ uint32 BrowserAccessibility::GetChildCount() { return children_.size(); } +BrowserAccessibility* BrowserAccessibility::GetChild(uint32 child_index) { + DCHECK(child_index >= 0 && child_index < children_.size()); + return children_[child_index]; +} + BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() { if (parent_ && index_in_parent_ > 0) return parent_->children_[index_in_parent_ - 1]; @@ -575,7 +580,7 @@ STDMETHODIMP BrowserAccessibility::get_description(BSTR* desc) { } STDMETHODIMP BrowserAccessibility::get_imagePosition( - enum IA2CoordinateType coordinate_type, long* x, long* y) { + enum IA2CoordinateType coordinate_type, LONG* x, LONG* y) { if (!instance_active_) return E_FAIL; @@ -602,7 +607,7 @@ STDMETHODIMP BrowserAccessibility::get_imagePosition( return S_OK; } -STDMETHODIMP BrowserAccessibility::get_imageSize(long* height, long* width) { +STDMETHODIMP BrowserAccessibility::get_imageSize(LONG* height, LONG* width) { if (!instance_active_) return E_FAIL; @@ -618,32 +623,53 @@ STDMETHODIMP BrowserAccessibility::get_imageSize(long* height, long* width) { // IAccessibleText methods. // -STDMETHODIMP BrowserAccessibility::get_nCharacters(long* n_characters) { +STDMETHODIMP BrowserAccessibility::get_nCharacters(LONG* n_characters) { if (!instance_active_) return E_FAIL; if (!n_characters) return E_INVALIDARG; - *n_characters = name_.length(); + if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { + *n_characters = value_.length(); + } else { + *n_characters = name_.length(); + } + return S_OK; } STDMETHODIMP BrowserAccessibility::get_text( - long start_offset, long end_offset, BSTR* text) { + LONG start_offset, LONG end_offset, BSTR* text) { if (!instance_active_) return E_FAIL; if (!text) return E_INVALIDARG; - long len = name_.length(); + string16 text_str; + if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { + text_str = value_; + } else { + text_str = name_; + } + + // The spec allows the arguments to be reversed. + if (start_offset > end_offset) { + LONG tmp = start_offset; + start_offset = end_offset; + end_offset = tmp; + } + + // The spec does not allow the start or end offsets to be out or range; + // we must return an error if so. + LONG len = text_str.length(); if (start_offset < 0) - start_offset = 0; + return E_INVALIDARG; if (end_offset > len) - end_offset = len; + return E_INVALIDARG; - string16 substr = name_.substr(start_offset, end_offset - start_offset); + string16 substr = text_str.substr(start_offset, end_offset - start_offset); if (substr.empty()) return S_FALSE; @@ -652,14 +678,76 @@ STDMETHODIMP BrowserAccessibility::get_text( return S_OK; } -STDMETHODIMP BrowserAccessibility::get_caretOffset(long* offset) { +STDMETHODIMP BrowserAccessibility::get_caretOffset(LONG* offset) { if (!instance_active_) return E_FAIL; if (!offset) return E_INVALIDARG; - *offset = 0; + if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { + int sel_start = 0; + if (GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_START, &sel_start)) { + *offset = sel_start; + } else { + *offset = 0; + } + } else { + *offset = 0; + } + + return S_OK; +} + +STDMETHODIMP BrowserAccessibility::get_nSelections(LONG* n_selections) { + if (!instance_active_) + return E_FAIL; + + if (!n_selections) + return E_INVALIDARG; + + if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { + int sel_start = 0; + int sel_end = 0; + if (GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_START, &sel_start) && + GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_END, &sel_end) && + sel_start != sel_end) { + *n_selections = 1; + } else { + *n_selections = 0; + } + } else { + *n_selections = 0; + } + + return S_OK; +} + +STDMETHODIMP BrowserAccessibility::get_selection(LONG selection_index, + LONG* start_offset, + LONG* end_offset) { + if (!instance_active_) + return E_FAIL; + + if (!start_offset || !end_offset || selection_index != 0) + return E_INVALIDARG; + + if (src_role_ == WebAccessibility::ROLE_TEXT_FIELD) { + int sel_start = 0; + int sel_end = 0; + if (GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_START, &sel_start) && + GetAttributeAsInt(WebAccessibility::ATTR_TEXT_SEL_END, &sel_end)) { + *start_offset = sel_start; + *end_offset = sel_end; + } else { + *start_offset = 0; + *end_offset = 0; + } + } else { + *start_offset = 0; + *end_offset = 0; + } + return S_OK; } @@ -1011,7 +1099,7 @@ HRESULT WINAPI BrowserAccessibility::InternalQueryInterface( REFIID iid, void** object) { if (iid == IID_IAccessibleText) { - if (role_ != ROLE_SYSTEM_LINK) { + if (role_ != ROLE_SYSTEM_LINK && role_ != ROLE_SYSTEM_TEXT) { *object = NULL; return E_NOINTERFACE; } @@ -1081,12 +1169,24 @@ HRESULT BrowserAccessibility::GetAttributeAsBstr( return S_OK; } +bool BrowserAccessibility::GetAttributeAsInt( + WebAccessibility::Attribute attribute, int* value_int) { + string16 value_str; + + if (!GetAttribute(attribute, &value_str)) + return false; + + if (!base::StringToInt(value_str, value_int)) + return false; + + return true; +} + string16 BrowserAccessibility::Escape(string16 str) { - return UTF8ToUTF16(EscapeNonASCII(UTF16ToUTF8(str))); + return EscapeQueryParamValueUTF8(str, false); } -void BrowserAccessibility::InitRoleAndState(LONG web_role, - LONG web_state) { +void BrowserAccessibility::InitRoleAndState(LONG web_role, LONG web_state) { state_ = 0; ia2_state_ = IA2_STATE_OPAQUE; diff --git a/chrome/browser/browser_accessibility_win.h b/chrome/browser/browser_accessibility_win.h index 76cb59d..a981c3a 100644 --- a/chrome/browser/browser_accessibility_win.h +++ b/chrome/browser/browser_accessibility_win.h @@ -83,6 +83,9 @@ class ATL_NO_VTABLE BrowserAccessibility // Returns the number of children of this BrowserAccessibility object. uint32 GetChildCount(); + // Return a pointer to the child with the given index. + BrowserAccessibility* GetChild(uint32 child_index); + // Return the previous sibling of this object, or NULL if it's the first // child of its parent. BrowserAccessibility* GetPreviousSibling(); @@ -259,84 +262,82 @@ class ATL_NO_VTABLE BrowserAccessibility STDMETHODIMP get_description(BSTR* description); STDMETHODIMP get_imagePosition(enum IA2CoordinateType coordinate_type, - long* x, long* y); + LONG* x, LONG* y); - STDMETHODIMP get_imageSize(long* height, long* width); + STDMETHODIMP get_imageSize(LONG* height, LONG* width); // // IAccessibleText methods. // - STDMETHODIMP get_nCharacters(long* n_characters); + STDMETHODIMP get_nCharacters(LONG* n_characters); + + STDMETHODIMP get_text(LONG start_offset, LONG end_offset, BSTR* text); - STDMETHODIMP get_text(long start_offset, long end_offset, BSTR* text); + STDMETHODIMP get_caretOffset(LONG* offset); - STDMETHODIMP get_caretOffset(long* offset); + STDMETHODIMP get_nSelections(LONG* n_selections); + + STDMETHODIMP get_selection(LONG selection_index, + LONG* start_offset, + LONG* end_offset); // IAccessibleText methods not implemented. - STDMETHODIMP addSelection(long start_offset, long end_offset) { + STDMETHODIMP addSelection(LONG start_offset, LONG end_offset) { return E_NOTIMPL; } - STDMETHODIMP get_attributes(long offset, long* start_offset, long* end_offset, + STDMETHODIMP get_attributes(LONG offset, LONG* start_offset, LONG* end_offset, BSTR* text_attributes) { return E_NOTIMPL; } - STDMETHODIMP get_characterExtents(long offset, + STDMETHODIMP get_characterExtents(LONG offset, enum IA2CoordinateType coord_type, - long* x, long* y, - long* width, long* height) { + LONG* x, LONG* y, + LONG* width, LONG* height) { return E_NOTIMPL; } - STDMETHODIMP get_nSelections(long* n_selections) { + STDMETHODIMP get_offsetAtPoint(LONG x, LONG y, + enum IA2CoordinateType coord_type, + LONG* offset) { return E_NOTIMPL; } - STDMETHODIMP get_offsetAtPoint(long x, long y, - enum IA2CoordinateType coord_type, - long* offset) { + STDMETHODIMP get_textBeforeOffset(LONG offset, + enum IA2TextBoundaryType boundary_type, + LONG* start_offset, LONG* end_offset, + BSTR* text) { return E_NOTIMPL; } - STDMETHODIMP get_selection(long selection_index, - long* start_offset, - long* end_offset) { + STDMETHODIMP get_textAfterOffset(LONG offset, + enum IA2TextBoundaryType boundary_type, + LONG* start_offset, LONG* end_offset, + BSTR* text) { return E_NOTIMPL; } - STDMETHODIMP get_textBeforeOffset(long offset, + STDMETHODIMP get_textAtOffset(LONG offset, enum IA2TextBoundaryType boundary_type, - long* start_offset, long* end_offset, + LONG* start_offset, LONG* end_offset, BSTR* text) { return E_NOTIMPL; } - STDMETHODIMP get_textAfterOffset(long offset, - enum IA2TextBoundaryType boundary_type, - long* start_offset, long* end_offset, - BSTR* text) { - return E_NOTIMPL; - } - STDMETHODIMP get_textAtOffset(long offset, - enum IA2TextBoundaryType boundary_type, - long* start_offset, long* end_offset, - BSTR* text) { - return E_NOTIMPL; - } - STDMETHODIMP removeSelection(long selection_index) { + STDMETHODIMP removeSelection(LONG selection_index) { return E_NOTIMPL; } - STDMETHODIMP setCaretOffset(long offset) { + STDMETHODIMP setCaretOffset(LONG offset) { return E_NOTIMPL; } - STDMETHODIMP setSelection(long selection_index, - long start_offset, - long end_offset) { + STDMETHODIMP setSelection(LONG selection_index, + LONG start_offset, + LONG end_offset) { return E_NOTIMPL; } - STDMETHODIMP scrollSubstringTo(long start_index, - long end_index, + STDMETHODIMP scrollSubstringTo(LONG start_index, + LONG end_index, enum IA2ScrollType scroll_type) { return E_NOTIMPL; } - STDMETHODIMP scrollSubstringToPoint(long start_index, long end_index, + STDMETHODIMP scrollSubstringToPoint(LONG start_index, LONG end_index, enum IA2CoordinateType coordinate_type, - long x, long y) { + LONG x, LONG y) { return E_NOTIMPL; } STDMETHODIMP get_newText(IA2TextSegment* new_text) { @@ -510,6 +511,13 @@ class ATL_NO_VTABLE BrowserAccessibility HRESULT GetAttributeAsBstr( WebAccessibility::Attribute attribute, BSTR* value_bstr); + // Retrieve the value of an attribute from the attribute map and + // if found and nonempty, try to convert it to an integer. + // Returns true only if both the attribute was found and it was successfully + // converted to an integer. + bool GetAttributeAsInt( + WebAccessibility::Attribute attribute, int* value_int); + // Escape a string like it would be escaped for a URL or HTML form. string16 Escape(string16 str); @@ -535,6 +543,7 @@ class ATL_NO_VTABLE BrowserAccessibility std::map<int32, string16> attributes_; std::vector<std::pair<string16, string16> > html_attributes_; + int src_role_; LONG role_; LONG state_; string16 role_name_; diff --git a/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc index b12c6a7..ff93b3d 100644 --- a/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc +++ b/chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc @@ -30,6 +30,20 @@ class RendererAccessibilityBrowserTest : public InProcessBrowserTest { public: RendererAccessibilityBrowserTest() {} + // Tell the renderer to send an accessibility tree, then wait for the + // notification that it's been received. + const WebAccessibility& GetWebAccessibilityTree() { + 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); + view_host->EnableRendererAccessibility(); + ui_test_utils::WaitForNotification( + NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); + return view_host->accessibility_tree(); + } + // InProcessBrowserTest void SetUpInProcessBrowserTestFixture(); void TearDownInProcessBrowserTestFixture(); @@ -55,6 +69,7 @@ void RendererAccessibilityBrowserTest::TearDownInProcessBrowserTestFixture() { ::CoUninitialize(); #endif } + // Convenience method to get the value of a particular WebAccessibility // node attribute as a UTF-8 const char*. std::string RendererAccessibilityBrowserTest::GetAttr( @@ -67,7 +82,7 @@ std::string RendererAccessibilityBrowserTest::GetAttr( } IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest, - TestCrossPlatformAccessibilityTree) { + CrossPlatformWebpageAccessibility) { // Create a data url and load it. const char url_str[] = "data:text/html," @@ -77,20 +92,9 @@ IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest, "</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); - view_host->EnableRendererAccessibility(); - ui_test_utils::WaitForNotification( - NotificationType::RENDER_VIEW_HOST_ACCESSIBILITY_TREE_UPDATED); + const WebAccessibility& tree = GetWebAccessibilityTree(); // 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).c_str()); EXPECT_STREQ( "Accessibility Test", @@ -139,4 +143,62 @@ IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest, "checkbox", UTF16ToUTF8(checkbox.html_attributes[0].second).c_str()); } +IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest, + CrossPlatformUnselectedEditableTextAccessibility) { + // Create a data url and load it. + const char url_str[] = + "data:text/html," + "<!doctype html>" + "<body>" + "<input value=\"Hello, world.\"/>" + "</body></html>"; + GURL url(url_str); + browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED); + + const WebAccessibility& tree = GetWebAccessibilityTree(); + ASSERT_EQ(1U, tree.children.size()); + const WebAccessibility& body = tree.children[0]; + ASSERT_EQ(1U, body.children.size()); + const WebAccessibility& text = body.children[0]; + EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text.role); + EXPECT_STREQ( + "input", GetAttr(text, WebAccessibility::ATTR_HTML_TAG).c_str()); + EXPECT_STREQ( + "0", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_START).c_str()); + EXPECT_STREQ( + "0", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_END).c_str()); + EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str()); + + // TODO(dmazzoni): as soon as more accessibility code is cross-platform, + // this code should test that the accessible info is dynamically updated + // if the selection or value changes. +} + +IN_PROC_BROWSER_TEST_F(RendererAccessibilityBrowserTest, + CrossPlatformSelectedEditableTextAccessibility) { + // Create a data url and load it. + const char url_str[] = + "data:text/html," + "<!doctype html>" + "<body onload=\"document.body.children[0].select();\">" + "<input value=\"Hello, world.\"/>" + "</body></html>"; + GURL url(url_str); + browser()->OpenURL(url, GURL(), CURRENT_TAB, PageTransition::TYPED); + + const WebAccessibility& tree = GetWebAccessibilityTree(); + ASSERT_EQ(1U, tree.children.size()); + const WebAccessibility& body = tree.children[0]; + ASSERT_EQ(1U, body.children.size()); + const WebAccessibility& text = body.children[0]; + EXPECT_EQ(WebAccessibility::ROLE_TEXT_FIELD, text.role); + EXPECT_STREQ( + "input", GetAttr(text, WebAccessibility::ATTR_HTML_TAG).c_str()); + EXPECT_STREQ( + "0", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_START).c_str()); + EXPECT_STREQ( + "13", GetAttr(text, WebAccessibility::ATTR_TEXT_SEL_END).c_str()); + EXPECT_STREQ("Hello, world.", UTF16ToUTF8(text.value).c_str()); +} + } // namespace diff --git a/chrome/common/render_messages_params.cc b/chrome/common/render_messages_params.cc index 4b28b3d..8bd3eb8 100644 --- a/chrome/common/render_messages_params.cc +++ b/chrome/common/render_messages_params.cc @@ -505,7 +505,7 @@ struct ParamTraits int val = 0; if (!ReadParam(m, iter, &val) || val < params::NOTIFICATION_TYPE_CHECK_STATE_CHANGED || - val > params::NOTIFICATION_TYPE_VALUE_CHANGED) { + val > params::NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED) { return false; } *p = static_cast<param_type>(val); diff --git a/chrome/common/render_messages_params.h b/chrome/common/render_messages_params.h index 5c2b0d1..dfb78b8 100644 --- a/chrome/common/render_messages_params.h +++ b/chrome/common/render_messages_params.h @@ -984,6 +984,9 @@ struct ViewHostMsg_AccessibilityNotification_Params { // The node value has changed. NOTIFICATION_TYPE_VALUE_CHANGED, + + // The text cursor or selection changed. + NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED, }; // Type of notification. diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc index 8076c06..ae4b476 100644 --- a/chrome/renderer/render_view.cc +++ b/chrome/renderer/render_view.cc @@ -5595,6 +5595,11 @@ void RenderView::postAccessibilityNotification( ViewHostMsg_AccessibilityNotification_Params:: NOTIFICATION_TYPE_VALUE_CHANGED; break; + case WebKit::WebAccessibilityNotificationSelectedTextChanged: + param.notification_type = + ViewHostMsg_AccessibilityNotification_Params:: + NOTIFICATION_TYPE_SELECTED_TEXT_CHANGED; + break; default: return; } |