summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authordmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-21 16:54:36 +0000
committerdmazzoni@chromium.org <dmazzoni@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-05-21 16:54:36 +0000
commitaef9284447e6e63d30448481e8cdf01ba1ecdf22 (patch)
tree994a27fd137aac90b92c81cc77880387be52dbd0 /chrome/browser
parent8ddbd66ab581984c87b8b52465c96e349ebcfb5f (diff)
downloadchromium_src-aef9284447e6e63d30448481e8cdf01ba1ecdf22.zip
chromium_src-aef9284447e6e63d30448481e8cdf01ba1ecdf22.tar.gz
chromium_src-aef9284447e6e63d30448481e8cdf01ba1ecdf22.tar.bz2
Windows accessibility improvements: 1. All WebKit roles are now passed to the
browser and then converted to MSAA roles - this is both because the logic needs to be more complicated, and so we can support Mac accessibility, too. 2. The serializable object used to pass accessibility info from the renderer to the browser now uses a map for uncommon attributes, rather than having a bunch of fields that are almost always empty. 3. Handles the accSelect method with TAKE_FOCUS, allowing assistive technology to set focus to a particular control. 4. Implements several other IAccessible2 interfaces. BUG=25564 BUG=13291 TEST=None Review URL: http://codereview.chromium.org/2121004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@47922 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser_accessibility.cc729
-rw-r--r--chrome/browser/browser_accessibility.h140
-rw-r--r--chrome/browser/browser_accessibility_manager.cc16
-rw-r--r--chrome/browser/browser_accessibility_manager.h18
-rw-r--r--chrome/browser/browser_accessibility_unittest.cc10
-rw-r--r--chrome/browser/renderer_host/render_view_host.cc4
-rw-r--r--chrome/browser/renderer_host/render_view_host.h3
-rw-r--r--chrome/browser/renderer_host/render_widget_host.cc12
-rw-r--r--chrome/browser/renderer_host/render_widget_host.h11
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.cc24
-rw-r--r--chrome/browser/renderer_host/render_widget_host_view_win.h7
11 files changed, 735 insertions, 239 deletions
diff --git a/chrome/browser/browser_accessibility.cc b/chrome/browser/browser_accessibility.cc
index e282263..6471faf 100644
--- a/chrome/browser/browser_accessibility.cc
+++ b/chrome/browser/browser_accessibility.cc
@@ -36,18 +36,18 @@ void BrowserAccessibility::Initialize(
renderer_id_ = src.id;
name_ = src.name;
value_ = src.value;
- action_ = src.action;
- description_ = src.description;
- help_ = src.help;
- shortcut_ = src.shortcut;
- role_ = MSAARole(src.role);
- state_ = MSAAState(src.state);
+ attributes_ = src.attributes;
location_ = src.location;
+ InitRoleAndState(src.role, src.state);
- instance_active_ = true;
+ // If this object doesn't have a name but it does have a description,
+ // use the description as its name - because some screen readers only
+ // announce the name.
+ if (name_.empty() && HasAttribute(WebAccessibility::ATTR_DESCRIPTION)) {
+ GetAttribute(WebAccessibility::ATTR_DESCRIPTION, &name_);
+ }
- // Focused is a dynamic state, only one node will be focused at a time.
- state_ &= ~STATE_SYSTEM_FOCUSED;
+ instance_active_ = true;
}
void BrowserAccessibility::AddChild(BrowserAccessibility* child) {
@@ -106,22 +106,28 @@ BrowserAccessibility* BrowserAccessibility::NewReference() {
//
// IAccessible methods.
//
+// Conventions:
+// * Always test for instance_active_ first and return E_FAIL if it's false.
+// * Always check for invalid arguments first, even if they're unused.
+// * Return S_FALSE if the only output is a string argument and it's empty.
+//
HRESULT BrowserAccessibility::accDoDefaultAction(VARIANT var_id) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
- return E_NOTIMPL;
+ BrowserAccessibility* target = GetTargetFromChildID(var_id);
+ if (!target)
+ return E_INVALIDARG;
+
+ manager_->DoDefaultAction(*target);
+ return S_OK;
}
STDMETHODIMP BrowserAccessibility::accHitTest(LONG x_left, LONG y_top,
VARIANT* child) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!child)
return E_INVALIDARG;
@@ -132,10 +138,8 @@ STDMETHODIMP BrowserAccessibility::accHitTest(LONG x_left, LONG y_top,
STDMETHODIMP BrowserAccessibility::accLocation(LONG* x_left, LONG* y_top,
LONG* width, LONG* height,
VARIANT var_id) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!x_left || !y_top || !width || !height)
return E_INVALIDARG;
@@ -170,28 +174,28 @@ STDMETHODIMP BrowserAccessibility::accNavigate(
return E_INVALIDARG;
}
- BrowserAccessibility* result;
+ BrowserAccessibility* result = NULL;
switch (nav_dir) {
case NAVDIR_DOWN:
case NAVDIR_UP:
case NAVDIR_LEFT:
case NAVDIR_RIGHT:
- // These directions are not implemented, matching Mozilla and IE.
- return E_NOTIMPL;
- case NAVDIR_FIRSTCHILD:
- if (target->children_.size() > 0)
- result = target->children_[0];
- break;
- case NAVDIR_LASTCHILD:
- if (target->children_.size() > 0)
- result = target->children_[target->children_.size() - 1];
- break;
- case NAVDIR_NEXT:
- result = target->GetNextSibling();
- break;
- case NAVDIR_PREVIOUS:
- result = target->GetPreviousSibling();
- break;
+ // These directions are not implemented, matching Mozilla and IE.
+ return E_NOTIMPL;
+ case NAVDIR_FIRSTCHILD:
+ if (target->children_.size() > 0)
+ result = target->children_[0];
+ break;
+ case NAVDIR_LASTCHILD:
+ if (target->children_.size() > 0)
+ result = target->children_[target->children_.size() - 1];
+ break;
+ case NAVDIR_NEXT:
+ result = target->GetNextSibling();
+ break;
+ case NAVDIR_PREVIOUS:
+ result = target->GetPreviousSibling();
+ break;
}
if (!result) {
@@ -206,10 +210,8 @@ STDMETHODIMP BrowserAccessibility::accNavigate(
STDMETHODIMP BrowserAccessibility::get_accChild(VARIANT var_child,
IDispatch** disp_child) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!disp_child)
return E_INVALIDARG;
@@ -225,10 +227,8 @@ STDMETHODIMP BrowserAccessibility::get_accChild(VARIANT var_child,
}
STDMETHODIMP BrowserAccessibility::get_accChildCount(LONG* child_count) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!child_count)
return E_INVALIDARG;
@@ -239,10 +239,8 @@ STDMETHODIMP BrowserAccessibility::get_accChildCount(LONG* child_count) {
STDMETHODIMP BrowserAccessibility::get_accDefaultAction(VARIANT var_id,
BSTR* def_action) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!def_action)
return E_INVALIDARG;
@@ -251,11 +249,14 @@ STDMETHODIMP BrowserAccessibility::get_accDefaultAction(VARIANT var_id,
if (!target)
return E_INVALIDARG;
- // Return false if the string is empty.
- if (target->action_.size() == 0)
+ string16 action;
+ if (!target->GetAttribute(WebAccessibility::ATTR_SHORTCUT, &action))
+ return S_FALSE;
+
+ if (action.empty())
return S_FALSE;
- *def_action = SysAllocString(target->action_.c_str());
+ *def_action = SysAllocString(action.c_str());
DCHECK(*def_action);
return S_OK;
@@ -263,10 +264,8 @@ STDMETHODIMP BrowserAccessibility::get_accDefaultAction(VARIANT var_id,
STDMETHODIMP BrowserAccessibility::get_accDescription(VARIANT var_id,
BSTR* desc) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!desc)
return E_INVALIDARG;
@@ -275,21 +274,22 @@ STDMETHODIMP BrowserAccessibility::get_accDescription(VARIANT var_id,
if (!target)
return E_INVALIDARG;
- // Return false if the string is empty.
- if (target->description_.size() == 0)
+ string16 description;
+ if (!target->GetAttribute(WebAccessibility::ATTR_DESCRIPTION, &description))
+ return S_FALSE;
+
+ if (description.empty())
return S_FALSE;
- *desc = SysAllocString(target->description_.c_str());
+ *desc = SysAllocString(description.c_str());
DCHECK(*desc);
return S_OK;
}
STDMETHODIMP BrowserAccessibility::get_accFocus(VARIANT* focus_child) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!focus_child)
return E_INVALIDARG;
@@ -309,10 +309,8 @@ STDMETHODIMP BrowserAccessibility::get_accFocus(VARIANT* focus_child) {
}
STDMETHODIMP BrowserAccessibility::get_accHelp(VARIANT var_id, BSTR* help) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!help)
return E_INVALIDARG;
@@ -321,11 +319,14 @@ STDMETHODIMP BrowserAccessibility::get_accHelp(VARIANT var_id, BSTR* help) {
if (!target)
return E_INVALIDARG;
- // Return false if the string is empty.
- if (target->help_.size() == 0)
+ string16 help_str;
+ if (!target->GetAttribute(WebAccessibility::ATTR_HELP, &help_str))
return S_FALSE;
- *help = SysAllocString(target->help_.c_str());
+ if (help_str.empty())
+ return S_FALSE;
+
+ *help = SysAllocString(help_str.c_str());
DCHECK(*help);
return S_OK;
@@ -333,10 +334,8 @@ STDMETHODIMP BrowserAccessibility::get_accHelp(VARIANT var_id, BSTR* help) {
STDMETHODIMP BrowserAccessibility::get_accKeyboardShortcut(VARIANT var_id,
BSTR* acc_key) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!acc_key)
return E_INVALIDARG;
@@ -345,21 +344,22 @@ STDMETHODIMP BrowserAccessibility::get_accKeyboardShortcut(VARIANT var_id,
if (!target)
return E_INVALIDARG;
- // Return false if the string is empty.
- if (target->shortcut_.size() == 0)
+ string16 shortcut;
+ if (!target->GetAttribute(WebAccessibility::ATTR_SHORTCUT, &shortcut))
return S_FALSE;
- *acc_key = SysAllocString(target->shortcut_.c_str());
+ if (shortcut.empty())
+ return S_FALSE;
+
+ *acc_key = SysAllocString(shortcut.c_str());
DCHECK(*acc_key);
return S_OK;
}
STDMETHODIMP BrowserAccessibility::get_accName(VARIANT var_id, BSTR* name) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!name)
return E_INVALIDARG;
@@ -368,8 +368,7 @@ STDMETHODIMP BrowserAccessibility::get_accName(VARIANT var_id, BSTR* name) {
if (!target)
return E_INVALIDARG;
- // Return false if the string is empty.
- if (target->name_.size() == 0)
+ if (target->name_.empty())
return S_FALSE;
*name = SysAllocString(target->name_.c_str());
@@ -379,10 +378,8 @@ STDMETHODIMP BrowserAccessibility::get_accName(VARIANT var_id, BSTR* name) {
}
STDMETHODIMP BrowserAccessibility::get_accParent(IDispatch** disp_parent) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!disp_parent)
return E_INVALIDARG;
@@ -400,10 +397,8 @@ STDMETHODIMP BrowserAccessibility::get_accParent(IDispatch** disp_parent) {
}
STDMETHODIMP BrowserAccessibility::get_accRole(VARIANT var_id, VARIANT* role) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!role)
return E_INVALIDARG;
@@ -412,17 +407,20 @@ STDMETHODIMP BrowserAccessibility::get_accRole(VARIANT var_id, VARIANT* role) {
if (!target)
return E_INVALIDARG;
- role->vt = VT_I4;
- role->lVal = target->role_;
+ if (!target->role_name_.empty()) {
+ role->vt = VT_BSTR;
+ role->bstrVal = SysAllocString(target->role_name_.c_str());
+ } else {
+ role->vt = VT_I4;
+ role->lVal = target->role_;
+ }
return S_OK;
}
STDMETHODIMP BrowserAccessibility::get_accState(VARIANT var_id,
VARIANT* state) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!state)
return E_INVALIDARG;
@@ -440,10 +438,8 @@ STDMETHODIMP BrowserAccessibility::get_accState(VARIANT var_id,
}
STDMETHODIMP BrowserAccessibility::get_accValue(VARIANT var_id, BSTR* value) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!value)
return E_INVALIDARG;
@@ -465,21 +461,22 @@ STDMETHODIMP BrowserAccessibility::get_accHelpTopic(BSTR* help_file,
}
STDMETHODIMP BrowserAccessibility::get_accSelection(VARIANT* selected) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
return E_NOTIMPL;
}
STDMETHODIMP BrowserAccessibility::accSelect(LONG flags_sel, VARIANT var_id) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
+
+ if (flags_sel & SELFLAG_TAKEFOCUS) {
+ manager_->SetFocus(*this);
+ return S_OK;
}
- return E_NOTIMPL;
+ return S_FALSE;
}
//
@@ -487,38 +484,42 @@ STDMETHODIMP BrowserAccessibility::accSelect(LONG flags_sel, VARIANT var_id) {
//
STDMETHODIMP BrowserAccessibility::role(LONG* role) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!role)
return E_INVALIDARG;
- *role = role_;
+ *role = ia2_role_;
return S_OK;
}
+STDMETHODIMP BrowserAccessibility::get_attributes(BSTR* attributes) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (!attributes)
+ return E_INVALIDARG;
+
+ return S_FALSE;
+}
+
STDMETHODIMP BrowserAccessibility::get_states(AccessibleStates* states) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!states)
return E_INVALIDARG;
- *states = state_;
+ *states = ia2_state_;
return S_OK;
}
STDMETHODIMP BrowserAccessibility::get_uniqueID(LONG* unique_id) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!unique_id)
return E_INVALIDARG;
@@ -528,10 +529,8 @@ STDMETHODIMP BrowserAccessibility::get_uniqueID(LONG* unique_id) {
}
STDMETHODIMP BrowserAccessibility::get_windowHandle(HWND* window_handle) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!window_handle)
return E_INVALIDARG;
@@ -541,10 +540,8 @@ STDMETHODIMP BrowserAccessibility::get_windowHandle(HWND* window_handle) {
}
STDMETHODIMP BrowserAccessibility::get_indexInParent(LONG* index_in_parent) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (!index_in_parent)
return E_INVALIDARG;
@@ -554,15 +551,116 @@ STDMETHODIMP BrowserAccessibility::get_indexInParent(LONG* index_in_parent) {
}
//
+// IAccessibleImage methods.
+//
+
+STDMETHODIMP BrowserAccessibility::get_description(BSTR* desc) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (!desc)
+ return E_INVALIDARG;
+
+ string16 description;
+ if (!GetAttribute(WebAccessibility::ATTR_DESCRIPTION, &description))
+ return S_FALSE;
+
+ if (description.empty())
+ return S_FALSE;
+
+ *desc = SysAllocString(description.c_str());
+
+ DCHECK(*desc);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_imagePosition(
+ enum IA2CoordinateType coordinate_type, long* x, long* y) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (!x || !y)
+ return E_INVALIDARG;
+
+ if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
+ HWND parent_hwnd = manager_->GetParentHWND();
+ POINT top_left = {0, 0};
+ ::ClientToScreen(parent_hwnd, &top_left);
+ *x = location_.x + top_left.x;
+ *y = location_.y + top_left.y;
+ } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
+ *x = location_.x;
+ *y = location_.y;
+ if (parent_) {
+ *x -= parent_->location_.x;
+ *y -= parent_->location_.y;
+ }
+ } else {
+ return E_INVALIDARG;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_imageSize(long* height, long* width) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (!height || !width)
+ return E_INVALIDARG;
+
+ *height = location_.height;
+ *width = location_.width;
+ return S_OK;
+}
+
+//
+// IAccessibleText methods.
+//
+
+STDMETHODIMP BrowserAccessibility::get_nCharacters(long* n_characters) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (!n_characters)
+ return E_INVALIDARG;
+
+ *n_characters = name_.length();
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_text(
+ long start_offset, long end_offset, BSTR* text) {
+ if (!instance_active_)
+ return E_FAIL;
+
+ if (!text)
+ return E_INVALIDARG;
+
+ long len = name_.length();
+ if (start_offset < 0)
+ start_offset = 0;
+ if (end_offset > len)
+ end_offset = len;
+
+ *text = SysAllocString(
+ name_.substr(start_offset, end_offset - start_offset).c_str());
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_caretOffset(long* offset) {
+ *offset = 0;
+ return S_OK;
+}
+
+//
// IServiceProvider methods.
//
STDMETHODIMP BrowserAccessibility::QueryService(
REFGUID guidService, REFIID riid, void** object) {
- if (!instance_active_) {
- // Instance no longer active, fail gracefully.
+ if (!instance_active_)
return E_FAIL;
- }
if (guidService == IID_IAccessible || guidService == IID_IAccessible2)
return QueryInterface(riid, object);
@@ -572,6 +670,31 @@ STDMETHODIMP BrowserAccessibility::QueryService(
}
//
+// CComObjectRootEx methods.
+//
+
+HRESULT WINAPI BrowserAccessibility::InternalQueryInterface(
+ void* this_ptr,
+ const _ATL_INTMAP_ENTRY* entries,
+ REFIID iid,
+ void** object) {
+ if (iid == IID_IAccessibleText) {
+ if (role_ != ROLE_SYSTEM_LINK) {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ } else if (iid == IID_IAccessibleImage) {
+ if (role_ != ROLE_SYSTEM_GRAPHIC) {
+ *object = NULL;
+ return E_NOINTERFACE;
+ }
+ }
+
+ return CComObjectRootBase::InternalQueryInterface(
+ this_ptr, entries, iid, object);
+}
+
+//
// Private methods.
//
@@ -590,119 +713,301 @@ BrowserAccessibility* BrowserAccessibility::GetTargetFromChildID(
return manager_->GetFromChildID(child_id);
}
-LONG BrowserAccessibility::MSAARole(LONG browser_accessibility_role) {
- switch (browser_accessibility_role) {
+bool BrowserAccessibility::HasAttribute(WebAccessibility::Attribute attribute) {
+ return (attributes_.find(attribute) != attributes_.end());
+}
+
+bool BrowserAccessibility::GetAttribute(
+ WebAccessibility::Attribute attribute, string16* value) {
+ std::map<int32, string16>::iterator iter = attributes_.find(attribute);
+ if (iter != attributes_.end()) {
+ *value = iter->second;
+ return true;
+ }
+
+ return false;
+}
+
+void BrowserAccessibility::InitRoleAndState(LONG web_role,
+ LONG web_state) {
+ state_ = 0;
+ ia2_state_ = IA2_STATE_OPAQUE;
+
+ if ((web_state >> WebAccessibility::STATE_CHECKED) & 1)
+ state_ |= STATE_SYSTEM_CHECKED;
+ if ((web_state >> WebAccessibility::STATE_FOCUSABLE) & 1)
+ state_ |= STATE_SYSTEM_FOCUSABLE;
+ if ((web_state >> WebAccessibility::STATE_HOTTRACKED) & 1)
+ state_ |= STATE_SYSTEM_HOTTRACKED;
+ if ((web_state >> WebAccessibility::STATE_INDETERMINATE) & 1)
+ state_ |= STATE_SYSTEM_INDETERMINATE;
+ if ((web_state >> WebAccessibility::STATE_LINKED) & 1)
+ state_ |= STATE_SYSTEM_LINKED;
+ if ((web_state >> WebAccessibility::STATE_MULTISELECTABLE) & 1)
+ state_ |= STATE_SYSTEM_MULTISELECTABLE;
+ if ((web_state >> WebAccessibility::STATE_OFFSCREEN) & 1)
+ state_ |= STATE_SYSTEM_OFFSCREEN;
+ if ((web_state >> WebAccessibility::STATE_PRESSED) & 1)
+ state_ |= STATE_SYSTEM_PRESSED;
+ if ((web_state >> WebAccessibility::STATE_PROTECTED) & 1)
+ state_ |= STATE_SYSTEM_PROTECTED;
+ if ((web_state >> WebAccessibility::STATE_READONLY) & 1)
+ state_ |= STATE_SYSTEM_READONLY;
+ if ((web_state >> WebAccessibility::STATE_TRAVERSED) & 1)
+ state_ |= STATE_SYSTEM_TRAVERSED;
+ if ((web_state >> WebAccessibility::STATE_UNAVAILABLE) & 1)
+ state_ |= STATE_SYSTEM_UNAVAILABLE;
+
+ role_ = 0;
+ ia2_role_ = 0;
+ switch (web_role) {
+ case WebAccessibility::ROLE_ALERT:
+ case WebAccessibility::ROLE_ALERT_DIALOG:
+ role_ = ROLE_SYSTEM_ALERT;
+ break;
case WebAccessibility::ROLE_APPLICATION:
- return ROLE_SYSTEM_APPLICATION;
+ role_ = ROLE_SYSTEM_APPLICATION;
+ break;
+ case WebAccessibility::ROLE_ARTICLE:
+ role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
+ case WebAccessibility::ROLE_BUTTON:
+ role_ = ROLE_SYSTEM_PUSHBUTTON;
+ break;
case WebAccessibility::ROLE_CELL:
- return ROLE_SYSTEM_CELL;
- case WebAccessibility::ROLE_CHECKBUTTON:
- return ROLE_SYSTEM_CHECKBUTTON;
+ role_ = ROLE_SYSTEM_CELL;
+ break;
+ case WebAccessibility::ROLE_CHECKBOX:
+ role_ = ROLE_SYSTEM_CHECKBUTTON;
+ break;
+ case WebAccessibility::ROLE_COLOR_WELL:
+ role_ = ROLE_SYSTEM_CLIENT;
+ ia2_role_ = IA2_ROLE_COLOR_CHOOSER;
+ break;
case WebAccessibility::ROLE_COLUMN:
- return ROLE_SYSTEM_COLUMN;
- case WebAccessibility::ROLE_COLUMNHEADER:
- return ROLE_SYSTEM_COLUMNHEADER;
+ role_ = ROLE_SYSTEM_COLUMN;
+ break;
+ case WebAccessibility::ROLE_COLUMN_HEADER:
+ role_ = ROLE_SYSTEM_COLUMNHEADER;
+ break;
+ case WebAccessibility::ROLE_COMBO_BOX:
+ role_ = ROLE_SYSTEM_COMBOBOX;
+ break;
+ case WebAccessibility::ROLE_DEFINITION_LIST_DEFINITION:
+ role_name_ = L"dd";
+ ia2_role_ = IA2_ROLE_PARAGRAPH;
+ break;
+ case WebAccessibility::ROLE_DEFINITION_LIST_TERM:
+ role_ = ROLE_SYSTEM_LISTITEM;
+ break;
+ case WebAccessibility::ROLE_DIALOG:
+ role_ = ROLE_SYSTEM_DIALOG;
+ break;
case WebAccessibility::ROLE_DOCUMENT:
- return ROLE_SYSTEM_DOCUMENT;
- case WebAccessibility::ROLE_GRAPHIC:
- return ROLE_SYSTEM_GRAPHIC;
- case WebAccessibility::ROLE_GROUPING:
- return ROLE_SYSTEM_GROUPING;
+ case WebAccessibility::ROLE_WEB_AREA:
+ role_ = ROLE_SYSTEM_DOCUMENT;
+ state_ |= STATE_SYSTEM_READONLY;
+ state_ |= STATE_SYSTEM_FOCUSABLE;
+ break;
+ case WebAccessibility::ROLE_EDITABLE_TEXT:
+ role_ = ROLE_SYSTEM_TEXT;
+ ia2_state_ |= IA2_STATE_SINGLE_LINE;
+ ia2_state_ |= IA2_STATE_EDITABLE;
+ break;
+ case WebAccessibility::ROLE_GRID:
+ role_ = ROLE_SYSTEM_TABLE;
+ break;
+ case WebAccessibility::ROLE_GROUP:
+ role_name_ = L"div";
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
+ case WebAccessibility::ROLE_HEADING:
+ // TODO(dmazzoni): support all heading levels
+ role_name_ = L"h1";
+ ia2_role_ = IA2_ROLE_HEADING;
+ break;
+ case WebAccessibility::ROLE_IMAGE:
+ role_ = ROLE_SYSTEM_GRAPHIC;
+ break;
+ case WebAccessibility::ROLE_IMAGE_MAP:
+ role_name_ = L"map";
+ ia2_role_ = IA2_ROLE_IMAGE_MAP;
+ break;
+ case WebAccessibility::ROLE_IMAGE_MAP_LINK:
+ role_ = ROLE_SYSTEM_LINK;
+ state_ |= STATE_SYSTEM_LINKED;
+ break;
+ case WebAccessibility::ROLE_LANDMARK_APPLICATION:
+ case WebAccessibility::ROLE_LANDMARK_BANNER:
+ case WebAccessibility::ROLE_LANDMARK_COMPLEMENTARY:
+ case WebAccessibility::ROLE_LANDMARK_CONTENTINFO:
+ case WebAccessibility::ROLE_LANDMARK_MAIN:
+ case WebAccessibility::ROLE_LANDMARK_NAVIGATION:
+ case WebAccessibility::ROLE_LANDMARK_SEARCH:
+ role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
case WebAccessibility::ROLE_LINK:
- return ROLE_SYSTEM_LINK;
+ case WebAccessibility::ROLE_WEBCORE_LINK:
+ role_ = ROLE_SYSTEM_LINK;
+ state_ |= STATE_SYSTEM_LINKED;
+ break;
case WebAccessibility::ROLE_LIST:
+ role_ = ROLE_SYSTEM_LIST;
+ break;
case WebAccessibility::ROLE_LISTBOX:
- return ROLE_SYSTEM_LIST;
- case WebAccessibility::ROLE_LISTITEM:
- return ROLE_SYSTEM_LISTITEM;
- case WebAccessibility::ROLE_MENUBAR:
- return ROLE_SYSTEM_MENUBAR;
- case WebAccessibility::ROLE_MENUITEM:
- return ROLE_SYSTEM_MENUITEM;
- case WebAccessibility::ROLE_MENUPOPUP:
- return ROLE_SYSTEM_MENUPOPUP;
+ role_ = ROLE_SYSTEM_LIST;
+ break;
+ case WebAccessibility::ROLE_LISTBOX_OPTION:
+ case WebAccessibility::ROLE_LIST_ITEM:
+ case WebAccessibility::ROLE_LIST_MARKER:
+ role_ = ROLE_SYSTEM_LISTITEM;
+ break;
+ case WebAccessibility::ROLE_MENU:
+ case WebAccessibility::ROLE_MENU_BUTTON:
+ role_ = ROLE_SYSTEM_MENUPOPUP;
+ break;
+ case WebAccessibility::ROLE_MENU_BAR:
+ role_ = ROLE_SYSTEM_MENUBAR;
+ break;
+ case WebAccessibility::ROLE_MENU_ITEM:
+ case WebAccessibility::ROLE_MENU_LIST_OPTION:
+ role_ = ROLE_SYSTEM_MENUITEM;
+ break;
+ case WebAccessibility::ROLE_MENU_LIST_POPUP:
+ role_ = ROLE_SYSTEM_MENUPOPUP;
+ break;
+ case WebAccessibility::ROLE_NOTE:
+ role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_NOTE;
+ break;
case WebAccessibility::ROLE_OUTLINE:
- return ROLE_SYSTEM_OUTLINE;
- case WebAccessibility::ROLE_PAGETABLIST:
- return ROLE_SYSTEM_PAGETABLIST;
- case WebAccessibility::ROLE_PROGRESSBAR:
- return ROLE_SYSTEM_PROGRESSBAR;
- case WebAccessibility::ROLE_PUSHBUTTON:
- return ROLE_SYSTEM_PUSHBUTTON;
- case WebAccessibility::ROLE_RADIOBUTTON:
- return ROLE_SYSTEM_RADIOBUTTON;
+ role_ = ROLE_SYSTEM_OUTLINE;
+ break;
+ case WebAccessibility::ROLE_POPUP_BUTTON:
+ role_ = ROLE_SYSTEM_COMBOBOX;
+ break;
+ case WebAccessibility::ROLE_PROGRESS_INDICATOR:
+ role_ = ROLE_SYSTEM_PROGRESSBAR;
+ break;
+ case WebAccessibility::ROLE_RADIO_BUTTON:
+ role_ = ROLE_SYSTEM_RADIOBUTTON;
+ break;
+ case WebAccessibility::ROLE_RADIO_GROUP:
+ role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
+ case WebAccessibility::ROLE_REGION:
+ role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
case WebAccessibility::ROLE_ROW:
- return ROLE_SYSTEM_ROW;
- case WebAccessibility::ROLE_ROWHEADER:
- return ROLE_SYSTEM_ROWHEADER;
- case WebAccessibility::ROLE_SEPARATOR:
- return ROLE_SYSTEM_SEPARATOR;
+ role_ = ROLE_SYSTEM_ROW;
+ break;
+ case WebAccessibility::ROLE_ROW_HEADER:
+ role_ = ROLE_SYSTEM_ROWHEADER;
+ break;
+ case WebAccessibility::ROLE_RULER:
+ role_ = ROLE_SYSTEM_CLIENT;
+ ia2_role_ = IA2_ROLE_RULER;
+ break;
+ case WebAccessibility::ROLE_SCROLLAREA:
+ role_ = ROLE_SYSTEM_CLIENT;
+ ia2_role_ = IA2_ROLE_SCROLL_PANE;
+ break;
+ case WebAccessibility::ROLE_SCROLLBAR:
+ role_ = ROLE_SYSTEM_SCROLLBAR;
+ break;
case WebAccessibility::ROLE_SLIDER:
- return ROLE_SYSTEM_SLIDER;
- case WebAccessibility::ROLE_STATICTEXT:
- return ROLE_SYSTEM_STATICTEXT;
- case WebAccessibility::ROLE_STATUSBAR:
- return ROLE_SYSTEM_STATUSBAR;
+ role_ = ROLE_SYSTEM_SLIDER;
+ break;
+ case WebAccessibility::ROLE_SPLIT_GROUP:
+ role_ = ROLE_SYSTEM_CLIENT;
+ ia2_role_ = IA2_ROLE_SPLIT_PANE;
+ break;
+ case WebAccessibility::ROLE_ANNOTATION:
+ case WebAccessibility::ROLE_STATIC_TEXT:
+ role_ = ROLE_SYSTEM_TEXT;
+ break;
+ case WebAccessibility::ROLE_STATUS:
+ role_ = ROLE_SYSTEM_STATUSBAR;
+ break;
+ case WebAccessibility::ROLE_TAB:
+ role_ = ROLE_SYSTEM_PAGETAB;
+ break;
case WebAccessibility::ROLE_TABLE:
- return ROLE_SYSTEM_TABLE;
- case WebAccessibility::ROLE_TEXT:
- return ROLE_SYSTEM_TEXT;
+ role_ = ROLE_SYSTEM_TABLE;
+ break;
+ case WebAccessibility::ROLE_TABLE_HEADER_CONTAINER:
+ role_ = ROLE_SYSTEM_GROUPING;
+ ia2_role_ = IA2_ROLE_SECTION;
+ break;
+ case WebAccessibility::ROLE_TAB_GROUP:
+ case WebAccessibility::ROLE_TAB_LIST:
+ case WebAccessibility::ROLE_TAB_PANEL:
+ role_ = ROLE_SYSTEM_PAGETABLIST;
+ break;
+ case WebAccessibility::ROLE_TEXTAREA:
+ role_ = ROLE_SYSTEM_TEXT;
+ ia2_state_ |= IA2_STATE_MULTI_LINE;
+ ia2_state_ |= IA2_STATE_EDITABLE;
+ break;
+ case WebAccessibility::ROLE_TEXT_FIELD:
+ role_ = ROLE_SYSTEM_TEXT;
+ ia2_state_ |= IA2_STATE_SINGLE_LINE;
+ ia2_state_ |= IA2_STATE_EDITABLE;
+ break;
case WebAccessibility::ROLE_TOOLBAR:
- return ROLE_SYSTEM_TOOLBAR;
+ role_ = ROLE_SYSTEM_TOOLBAR;
+ break;
case WebAccessibility::ROLE_TOOLTIP:
- return ROLE_SYSTEM_TOOLTIP;
- case WebAccessibility::ROLE_CLIENT:
+ role_ = ROLE_SYSTEM_TOOLTIP;
+ break;
+ case WebAccessibility::ROLE_TREE:
+ role_ = ROLE_SYSTEM_OUTLINE;
+ break;
+ case WebAccessibility::ROLE_TREE_GRID:
+ role_ = ROLE_SYSTEM_OUTLINE;
+ break;
+ case WebAccessibility::ROLE_TREE_ITEM:
+ role_ = ROLE_SYSTEM_OUTLINEITEM;
+ break;
+ case WebAccessibility::ROLE_WINDOW:
+ role_ = ROLE_SYSTEM_WINDOW;
+ break;
+
+ // TODO(dmazzoni): figure out the proper MSAA role for all of these.
+ case WebAccessibility::ROLE_BROWSER:
+ case WebAccessibility::ROLE_BUSY_INDICATOR:
+ case WebAccessibility::ROLE_DIRECTORY:
+ case WebAccessibility::ROLE_DISCLOSURE_TRIANGLE:
+ case WebAccessibility::ROLE_DRAWER:
+ case WebAccessibility::ROLE_GROW_AREA:
+ case WebAccessibility::ROLE_HELP_TAG:
+ case WebAccessibility::ROLE_IGNORED:
+ case WebAccessibility::ROLE_INCREMENTOR:
+ case WebAccessibility::ROLE_LOG:
+ case WebAccessibility::ROLE_MARQUEE:
+ case WebAccessibility::ROLE_MATH:
+ case WebAccessibility::ROLE_MATTE:
+ case WebAccessibility::ROLE_RULER_MARKER:
+ case WebAccessibility::ROLE_SHEET:
+ case WebAccessibility::ROLE_SLIDER_THUMB:
+ case WebAccessibility::ROLE_SPLITTER:
+ case WebAccessibility::ROLE_SYSTEM_WIDE:
+ case WebAccessibility::ROLE_TIMER:
+ case WebAccessibility::ROLE_VALUE_INDICATOR:
default:
- // This is the default role for MSAA.
- return ROLE_SYSTEM_CLIENT;
- }
-}
-
-LONG BrowserAccessibility::MSAAState(LONG browser_accessibility_state) {
- LONG state = 0;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_CHECKED) & 1)
- state |= STATE_SYSTEM_CHECKED;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_FOCUSABLE) & 1)
- state |= STATE_SYSTEM_FOCUSABLE;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_FOCUSED) & 1)
- state |= STATE_SYSTEM_FOCUSED;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_HOTTRACKED) & 1)
- state |= STATE_SYSTEM_HOTTRACKED;
-
- if ((browser_accessibility_state >>
- WebAccessibility::STATE_INDETERMINATE) & 1) {
- state |= STATE_SYSTEM_INDETERMINATE;
+ role_ = ROLE_SYSTEM_CLIENT;
+ break;
}
- if ((browser_accessibility_state >> WebAccessibility::STATE_LINKED) & 1)
- state |= STATE_SYSTEM_LINKED;
-
- if ((browser_accessibility_state >>
- WebAccessibility::STATE_MULTISELECTABLE) & 1) {
- state |= STATE_SYSTEM_MULTISELECTABLE;
- }
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_OFFSCREEN) & 1)
- state |= STATE_SYSTEM_OFFSCREEN;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_PRESSED) & 1)
- state |= STATE_SYSTEM_PRESSED;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_PROTECTED) & 1)
- state |= STATE_SYSTEM_PROTECTED;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_READONLY) & 1)
- state |= STATE_SYSTEM_READONLY;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_TRAVERSED) & 1)
- state |= STATE_SYSTEM_TRAVERSED;
-
- if ((browser_accessibility_state >> WebAccessibility::STATE_UNAVAILABLE) & 1)
- state |= STATE_SYSTEM_UNAVAILABLE;
+ // The role should always be set.
+ DCHECK(!role_name_.empty() || role_);
- return state;
+ // If we didn't explicitly set the IAccessible2 role, make it the same
+ // as the MSAA role.
+ if (!ia2_role_)
+ ia2_role_ = role_;
}
diff --git a/chrome/browser/browser_accessibility.h b/chrome/browser/browser_accessibility.h
index 767ede2..1216d47 100644
--- a/chrome/browser/browser_accessibility.h
+++ b/chrome/browser/browser_accessibility.h
@@ -31,12 +31,16 @@ class ATL_NO_VTABLE BrowserAccessibility
: public CComObjectRootEx<CComMultiThreadModel>,
public IDispatchImpl<IAccessible2, &IID_IAccessible2,
&LIBID_IAccessible2Lib>,
+ public IAccessibleImage,
+ public IAccessibleText,
public IServiceProvider {
public:
BEGIN_COM_MAP(BrowserAccessibility)
COM_INTERFACE_ENTRY2(IDispatch, IAccessible2)
COM_INTERFACE_ENTRY2(IAccessible, IAccessible2)
COM_INTERFACE_ENTRY(IAccessible2)
+ COM_INTERFACE_ENTRY(IAccessibleImage)
+ COM_INTERFACE_ENTRY(IAccessibleText)
COM_INTERFACE_ENTRY(IServiceProvider)
END_COM_MAP()
@@ -71,7 +75,8 @@ class ATL_NO_VTABLE BrowserAccessibility
BrowserAccessibility* GetNextSibling();
// Accessors
- LONG child_id() { return child_id_; }
+ LONG child_id() const { return child_id_; }
+ int32 renderer_id() const { return renderer_id_; }
// Add one to the reference count and return the same object. Always
// use this method when returning a BrowserAccessibility object as
@@ -161,6 +166,10 @@ class ATL_NO_VTABLE BrowserAccessibility
// Returns the state bitmask from a larger set of possible states.
STDMETHODIMP get_states(AccessibleStates* states);
+ // Returns the attributes specific to this IAccessible2 object,
+ // such as a cell's formula.
+ STDMETHODIMP get_attributes(BSTR* attributes);
+
// Get the unique ID of this object so that the client knows if it's
// been encountered previously.
STDMETHODIMP get_uniqueID(LONG* unique_id);
@@ -184,7 +193,7 @@ class ATL_NO_VTABLE BrowserAccessibility
}
STDMETHODIMP get_relations(LONG max_relations,
IAccessibleRelation** relations,
- LONG *n_relations) {
+ LONG* n_relations) {
return E_NOTIMPL;
}
STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) {
@@ -219,7 +228,98 @@ class ATL_NO_VTABLE BrowserAccessibility
STDMETHODIMP get_locale(IA2Locale* locale) {
return E_NOTIMPL;
}
- STDMETHODIMP get_attributes(BSTR* attributes) {
+
+ //
+ // IAccessibleImage methods.
+ //
+
+ STDMETHODIMP get_description(BSTR* description);
+
+ STDMETHODIMP get_imagePosition(enum IA2CoordinateType coordinate_type,
+ long* x, long* y);
+
+ STDMETHODIMP get_imageSize(long* height, long* width);
+
+ //
+ // IAccessibleText methods.
+ //
+
+ STDMETHODIMP get_nCharacters(long* n_characters);
+
+ STDMETHODIMP get_text(long start_offset, long end_offset, BSTR* text);
+
+ STDMETHODIMP get_caretOffset(long* offset);
+
+ // IAccessibleText methods not implemented.
+ STDMETHODIMP addSelection(long start_offset, long end_offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_attributes(long offset, long* start_offset, long* end_offset,
+ BSTR* text_attributes) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_characterExtents(long offset,
+ enum IA2CoordinateType coord_type,
+ long* x, long* y,
+ long* width, long* height) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_nSelections(long* n_selections) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_offsetAtPoint(long x, long y,
+ enum IA2CoordinateType coord_type,
+ long* offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_selection(long selection_index,
+ long* start_offset,
+ long* end_offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_textBeforeOffset(long offset,
+ enum IA2TextBoundaryType boundary_type,
+ 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) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP setCaretOffset(long offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP setSelection(long selection_index,
+ long start_offset,
+ long end_offset) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP scrollSubstringTo(long start_index,
+ long end_index,
+ enum IA2ScrollType scroll_type) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP scrollSubstringToPoint(long start_index, long end_index,
+ enum IA2CoordinateType coordinate_type,
+ long x, long y) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_newText(IA2TextSegment* new_text) {
+ return E_NOTIMPL;
+ }
+ STDMETHODIMP get_oldText(IA2TextSegment* old_text) {
return E_NOTIMPL;
}
@@ -229,6 +329,15 @@ class ATL_NO_VTABLE BrowserAccessibility
STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** object);
+ //
+ // CComObjectRootEx methods.
+ //
+
+ HRESULT WINAPI InternalQueryInterface(void* this_ptr,
+ const _ATL_INTMAP_ENTRY* entries,
+ REFIID iid,
+ void** object);
+
private:
// Many MSAA methods take a var_id parameter indicating that the operation
// should be performed on a particular child ID, rather than this object.
@@ -237,13 +346,17 @@ class ATL_NO_VTABLE BrowserAccessibility
// Does not return a new reference.
BrowserAccessibility* GetTargetFromChildID(const VARIANT& var_id);
- // Returns a conversion from the BrowserAccessibilityRole (as defined in
- // webkit/glue/webaccessibility.h) to an MSAA role.
- LONG MSAARole(LONG browser_accessibility_role);
+ // Initialize the role and state metadata from the role enum and state
+ // bitmasks defined in webkit/glue/webaccessibility.h.
+ void InitRoleAndState(LONG web_accessibility_role,
+ LONG web_accessibility_state);
+
+ // Return true if this attribute is in the attributes map.
+ bool HasAttribute(WebAccessibility::Attribute attribute);
- // Returns a conversion from the BrowserAccessibilityState (as defined in
- // webkit/glue/webaccessibility.h) to MSAA states set.
- LONG MSAAState(LONG browser_accessibility_state);
+ // Retrieve the string value of an attribute from the attribute map and
+ // returns true if found.
+ bool GetAttribute(WebAccessibility::Attribute attribute, string16* value);
// The manager of this tree of accessibility objects; needed for
// global operations like focus tracking.
@@ -264,12 +377,13 @@ class ATL_NO_VTABLE BrowserAccessibility
// events.
string16 name_;
string16 value_;
- string16 action_;
- string16 description_;
- string16 help_;
- string16 shortcut_;
+ std::map<int32, string16> attributes_;
+
LONG role_;
LONG state_;
+ string16 role_name_;
+ LONG ia2_role_;
+ LONG ia2_state_;
WebKit::WebRect location_;
// COM objects are reference-counted. When we're done with this object
diff --git a/chrome/browser/browser_accessibility_manager.cc b/chrome/browser/browser_accessibility_manager.cc
index 8e37719..d82c89b 100644
--- a/chrome/browser/browser_accessibility_manager.cc
+++ b/chrome/browser/browser_accessibility_manager.cc
@@ -30,9 +30,12 @@ LONG BrowserAccessibilityManager::next_child_id_ = -1;
BrowserAccessibilityManager::BrowserAccessibilityManager(
HWND parent_hwnd,
const webkit_glue::WebAccessibility& src,
+ BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
: parent_hwnd_(parent_hwnd),
- factory_(factory) {
+ delegate_(delegate),
+ factory_(factory),
+ focus_(NULL) {
HRESULT hr = ::CreateStdAccessibleObject(
parent_hwnd_, OBJID_WINDOW, IID_IAccessible,
reinterpret_cast<void **>(&window_iaccessible_));
@@ -82,6 +85,17 @@ BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
return NULL;
}
+void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
+ if (delegate_)
+ delegate_->SetAccessibilityFocus(node.renderer_id());
+}
+
+void BrowserAccessibilityManager::DoDefaultAction(
+ const BrowserAccessibility& node) {
+ if (delegate_)
+ delegate_->AccessibilityDoDefaultAction(node.renderer_id());
+}
+
void BrowserAccessibilityManager::OnAccessibilityFocusChange(int renderer_id) {
base::hash_map<int, LONG>::iterator iter =
renderer_id_to_child_id_map_.find(renderer_id);
diff --git a/chrome/browser/browser_accessibility_manager.h b/chrome/browser/browser_accessibility_manager.h
index 1db8100..f9e0491 100644
--- a/chrome/browser/browser_accessibility_manager.h
+++ b/chrome/browser/browser_accessibility_manager.h
@@ -29,12 +29,21 @@ class BrowserAccessibilityFactory {
virtual BrowserAccessibility* Create();
};
+// Class that can perform actions on behalf of the BrowserAccessibilityManager.
+class BrowserAccessibilityDelegate {
+ public:
+ virtual ~BrowserAccessibilityDelegate() {}
+ virtual void SetAccessibilityFocus(int acc_obj_id) = 0;
+ virtual void AccessibilityDoDefaultAction(int acc_obj_id) = 0;
+};
+
// Manages a tree of BrowserAccessibility objects.
class BrowserAccessibilityManager {
public:
BrowserAccessibilityManager(
HWND parent_hwnd,
const webkit_glue::WebAccessibility& src,
+ BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
virtual ~BrowserAccessibilityManager();
@@ -57,6 +66,12 @@ class BrowserAccessibilityManager {
// given root (inclusive). Does not make a new reference.
BrowserAccessibility* GetFocus(BrowserAccessibility* root);
+ // Tell the renderer to set focus to this node.
+ void SetFocus(const BrowserAccessibility& node);
+
+ // Tell the renderer to do the default action for this node.
+ void DoDefaultAction(const BrowserAccessibility& node);
+
// Called when the renderer process has notified us of a focus or state
// change. Send a notification to MSAA clients of the change.
void OnAccessibilityFocusChange(int acc_obj_id);
@@ -73,6 +88,9 @@ class BrowserAccessibilityManager {
// The parent window.
HWND parent_hwnd_;
+ // The object that can perform actions on our behalf.
+ BrowserAccessibilityDelegate* delegate_;
+
// Factory to create BrowserAccessibility objects (for dependency injection).
scoped_ptr<BrowserAccessibilityFactory> factory_;
diff --git a/chrome/browser/browser_accessibility_unittest.cc b/chrome/browser/browser_accessibility_unittest.cc
index f2429ea..217cb10 100644
--- a/chrome/browser/browser_accessibility_unittest.cc
+++ b/chrome/browser/browser_accessibility_unittest.cc
@@ -47,13 +47,13 @@ TEST(BrowserAccessibilityTest, TestNoLeaks) {
WebAccessibility button;
button.id = 2;
button.name = L"Button";
- button.role = WebAccessibility::ROLE_PUSHBUTTON;
+ button.role = WebAccessibility::ROLE_BUTTON;
button.state = 0;
WebAccessibility checkbox;
checkbox.id = 3;
checkbox.name = L"Checkbox";
- checkbox.role = WebAccessibility::ROLE_CHECKBUTTON;
+ checkbox.role = WebAccessibility::ROLE_CHECKBOX;
checkbox.state = 0;
WebAccessibility root;
@@ -71,7 +71,8 @@ TEST(BrowserAccessibilityTest, TestNoLeaks) {
CountedBrowserAccessibility::global_obj_count_ = 0;
BrowserAccessibilityManager* manager =
new BrowserAccessibilityManager(
- GetDesktopWindow(), root, new CountedBrowserAccessibilityFactory());
+ GetDesktopWindow(), root, NULL,
+ new CountedBrowserAccessibilityFactory());
ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_);
// Delete the manager and test that all 3 instances are deleted.
@@ -81,7 +82,8 @@ TEST(BrowserAccessibilityTest, TestNoLeaks) {
// Construct a manager again, and this time use the IAccessible interface
// to get new references to two of the three nodes in the tree.
manager = new BrowserAccessibilityManager(
- GetDesktopWindow(), root, new CountedBrowserAccessibilityFactory());
+ GetDesktopWindow(), root, NULL,
+ new CountedBrowserAccessibilityFactory());
ASSERT_EQ(3, CountedBrowserAccessibility::global_obj_count_);
BrowserAccessibility* root_accessible = manager->GetRoot();
IDispatch* root_iaccessible = NULL;
diff --git a/chrome/browser/renderer_host/render_view_host.cc b/chrome/browser/renderer_host/render_view_host.cc
index 36cc3b0..1d75014 100644
--- a/chrome/browser/renderer_host/render_view_host.cc
+++ b/chrome/browser/renderer_host/render_view_host.cc
@@ -676,10 +676,6 @@ bool RenderViewHost::SuddenTerminationAllowed() const {
return sudden_termination_allowed_ || process()->sudden_termination_allowed();
}
-void RenderViewHost::RequestAccessibilityTree() {
- Send(new ViewMsg_GetAccessibilityTree(routing_id()));
-}
-
///////////////////////////////////////////////////////////////////////////////
// RenderViewHost, IPC message handlers:
diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h
index 8ca6c98..97467f4 100644
--- a/chrome/browser/renderer_host/render_view_host.h
+++ b/chrome/browser/renderer_host/render_view_host.h
@@ -465,9 +465,6 @@ class RenderViewHost : public RenderWidgetHost {
// changed.
void EnablePreferredSizeChangedMode();
- // Requests a snapshot of an accessible DOM tree from the renderer.
- void RequestAccessibilityTree();
-
protected:
// RenderWidgetHost protected overrides.
virtual bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
diff --git a/chrome/browser/renderer_host/render_widget_host.cc b/chrome/browser/renderer_host/render_widget_host.cc
index a0f3be7..6becf7a 100644
--- a/chrome/browser/renderer_host/render_widget_host.cc
+++ b/chrome/browser/renderer_host/render_widget_host.cc
@@ -1076,6 +1076,18 @@ void RenderWidgetHost::AdvanceToNextMisspelling() {
Send(new ViewMsg_AdvanceToNextMisspelling(routing_id_));
}
+void RenderWidgetHost::RequestAccessibilityTree() {
+ Send(new ViewMsg_GetAccessibilityTree(routing_id()));
+}
+
+void RenderWidgetHost::SetAccessibilityFocus(int acc_obj_id) {
+ Send(new ViewMsg_SetAccessibilityFocus(routing_id(), acc_obj_id));
+}
+
+void RenderWidgetHost::AccessibilityDoDefaultAction(int acc_obj_id) {
+ Send(new ViewMsg_AccessibilityDoDefaultAction(routing_id(), acc_obj_id));
+}
+
void RenderWidgetHost::ProcessKeyboardEventAck(int type, bool processed) {
if (key_queue_.size() == 0) {
LOG(ERROR) << "Got a KeyEvent back from the renderer but we "
diff --git a/chrome/browser/renderer_host/render_widget_host.h b/chrome/browser/renderer_host/render_widget_host.h
index 4e5c903..8193058 100644
--- a/chrome/browser/renderer_host/render_widget_host.h
+++ b/chrome/browser/renderer_host/render_widget_host.h
@@ -364,6 +364,17 @@ class RenderWidgetHost : public IPC::Channel::Listener,
// Makes an IPC call to tell webkit to advance to the next misspelling.
void AdvanceToNextMisspelling();
+ // Requests a snapshot of an accessible DOM tree from the renderer.
+ void RequestAccessibilityTree();
+
+ // Relays a request from assistive technology to set focus to the
+ // node with this accessibility object id.
+ void SetAccessibilityFocus(int acc_obj_id);
+
+ // Relays a request from assistive technology to perform the default action
+ // on a node with this accessibility object id.
+ void AccessibilityDoDefaultAction(int acc_obj_id);
+
// Sets the active state (i.e., control tints).
virtual void SetActive(bool active);
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.cc b/chrome/browser/renderer_host/render_widget_host_view_win.cc
index 5696df1..b482b87 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.cc
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.cc
@@ -1480,7 +1480,7 @@ LRESULT RenderWidgetHostViewWin::OnMouseActivate(UINT, WPARAM, LPARAM,
void RenderWidgetHostViewWin::UpdateAccessibilityTree(
const webkit_glue::WebAccessibility& tree) {
browser_accessibility_manager_.reset(
- new BrowserAccessibilityManager(m_hWnd, tree));
+ new BrowserAccessibilityManager(m_hWnd, tree, this));
}
void RenderWidgetHostViewWin::OnAccessibilityFocusChange(int acc_obj_id) {
@@ -1516,6 +1516,28 @@ void RenderWidgetHostViewWin::Observe(NotificationType type,
browser_accessibility_manager_.reset(NULL);
}
+void RenderWidgetHostViewWin::SetAccessibilityFocus(int acc_obj_id) {
+ if (!browser_accessibility_manager_.get() ||
+ !render_widget_host_ ||
+ !render_widget_host_->process() ||
+ !render_widget_host_->process()->HasConnection()) {
+ return;
+ }
+
+ render_widget_host_->SetAccessibilityFocus(acc_obj_id);
+}
+
+void RenderWidgetHostViewWin::AccessibilityDoDefaultAction(int acc_obj_id) {
+ if (!browser_accessibility_manager_.get() ||
+ !render_widget_host_ ||
+ !render_widget_host_->process() ||
+ !render_widget_host_->process()->HasConnection()) {
+ return;
+ }
+
+ render_widget_host_->AccessibilityDoDefaultAction(acc_obj_id);
+}
+
LRESULT RenderWidgetHostViewWin::OnGetObject(UINT message, WPARAM wparam,
LPARAM lparam, BOOL& handled) {
// TODO(dmazzoni): http://crbug.com/25564 Disabling accessibility in the
diff --git a/chrome/browser/renderer_host/render_widget_host_view_win.h b/chrome/browser/renderer_host/render_widget_host_view_win.h
index 23716b9..c298f58 100644
--- a/chrome/browser/renderer_host/render_widget_host_view_win.h
+++ b/chrome/browser/renderer_host/render_widget_host_view_win.h
@@ -58,7 +58,8 @@ class RenderWidgetHostViewWin
CWindow,
RenderWidgetHostHWNDTraits>,
public RenderWidgetHostView,
- public NotificationObserver {
+ public NotificationObserver,
+ public BrowserAccessibilityDelegate {
public:
// The view will associate itself with the given widget.
explicit RenderWidgetHostViewWin(RenderWidgetHost* widget);
@@ -154,6 +155,10 @@ class RenderWidgetHostViewWin
const NotificationSource& source,
const NotificationDetails& details);
+ // Implementation of BrowserAccessibilityDelegate:
+ virtual void SetAccessibilityFocus(int acc_obj_id);
+ virtual void AccessibilityDoDefaultAction(int acc_obj_id);
+
protected:
// Windows Message Handlers
LRESULT OnCreate(CREATESTRUCT* create_struct);