summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-01 19:52:04 +0000
committerdmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-01 19:52:04 +0000
commitbd554c644039736cf4eb3944f63b7a8e87c449d9 (patch)
treec10f024ecd6f3a5665c4eacf6a9c0c81f866a9b1 /chrome
parent017091110712afd7f2bdba2ab9c97f51d06c87b5 (diff)
downloadchromium_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.cc95
-rw-r--r--chrome/browser/browser_accessibility_manager_win.h20
-rw-r--r--chrome/browser/browser_accessibility_win.cc134
-rw-r--r--chrome/browser/browser_accessibility_win.h89
-rw-r--r--chrome/browser/renderer_host/test/renderer_accessibility_browsertest.cc88
-rw-r--r--chrome/common/render_messages_params.cc2
-rw-r--r--chrome/common/render_messages_params.h3
-rw-r--r--chrome/renderer/render_view.cc5
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;
}