summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorklink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-30 23:56:50 +0000
committerklink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-09-30 23:56:50 +0000
commit266eb6ff422cf97eef1e56e78d0a9e73e9aef34a (patch)
treee2534c18efb1e38683a0b835956d2c067df7f6be /chrome
parenteed46c091b85924b097a5d506b3da6371b93007f (diff)
downloadchromium_src-266eb6ff422cf97eef1e56e78d0a9e73e9aef34a.zip
chromium_src-266eb6ff422cf97eef1e56e78d0a9e73e9aef34a.tar.gz
chromium_src-266eb6ff422cf97eef1e56e78d0a9e73e9aef34a.tar.bz2
Adds MSAA/IAccessible exposure of web content.
Review URL: http://codereview.chromium.org/4057 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@2738 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/browser.vcproj24
-rw-r--r--chrome/browser/browser_accessibility.cc555
-rw-r--r--chrome/browser/browser_accessibility.h169
-rw-r--r--chrome/browser/browser_accessibility_manager.cc167
-rw-r--r--chrome/browser/browser_accessibility_manager.h108
-rw-r--r--chrome/browser/iaccessible_function_ids.h38
-rw-r--r--chrome/browser/render_view_host.cc6
-rw-r--r--chrome/browser/render_widget_host_hwnd.cc51
-rw-r--r--chrome/browser/render_widget_host_hwnd.h8
-rw-r--r--chrome/common/render_messages.h129
-rw-r--r--chrome/common/render_messages_internal.h14
-rw-r--r--chrome/renderer/render_view.cc39
-rw-r--r--chrome/renderer/render_view.h8
13 files changed, 1309 insertions, 7 deletions
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index e87a3e0..70830bc 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -1959,6 +1959,30 @@
</File>
</Filter>
<Filter
+ Name="Accessibility"
+ >
+ <File
+ RelativePath=".\browser_accessibility.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_accessibility.h"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_accessibility_manager.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\browser_accessibility_manager.h"
+ >
+ </File>
+ <File
+ RelativePath=".\iaccessible_function_ids.h"
+ >
+ </File>
+ </Filter>
+ <Filter
Name="Download"
>
<File
diff --git a/chrome/browser/browser_accessibility.cc b/chrome/browser/browser_accessibility.cc
new file mode 100644
index 0000000..bb6b8d2
--- /dev/null
+++ b/chrome/browser/browser_accessibility.cc
@@ -0,0 +1,555 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/browser_accessibility.h"
+
+#include "chrome/browser/browser_accessibility_manager.h"
+#include "chrome/browser/iaccessible_function_ids.h"
+
+BrowserAccessibility::BrowserAccessibility()
+ : iaccessible_id_(-1),
+ instance_active_(true) {
+}
+
+HRESULT BrowserAccessibility::accDoDefaultAction(VARIANT var_id) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ // TODO(klink): Once we have MSAA events, change these fails for having
+ // BrowserAccessibilityManager firing the right event.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_ACCDODEFAULTACTION, var_id,
+ NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code)
+ return S_FALSE;
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::accHitTest(LONG x_left, LONG y_top,
+ VARIANT* child) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (!child)
+ return E_INVALIDARG;
+
+ if (!parent_hwnd()) {
+ // Parent HWND needed for coordinate conversion.
+ return E_FAIL;
+ }
+
+ // Convert coordinates to test from screen into client window coordinates, to
+ // maintain sandbox functionality on renderer side.
+ POINT p = {x_left, y_top};
+ ::ScreenToClient(parent_hwnd(), &p);
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_ACCHITTEST, EmptyVariant(),
+ p.x, p.y)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // The point is outside of the object's boundaries.
+ child->vt = VT_EMPTY;
+ return S_FALSE;
+ }
+
+ if (response().output_long1 == -1) {
+ if (CreateInstance(IID_IAccessible, response().iaccessible_id,
+ reinterpret_cast<void**>(&child->pdispVal)) == S_OK) {
+ child->vt = VT_DISPATCH;
+ // Increment the reference count for the retrieved interface.
+ child->pdispVal->AddRef();
+ } else {
+ return E_NOINTERFACE;
+ }
+ } else {
+ child->vt = VT_I4;
+ child->lVal = response().output_long1;
+ }
+
+ return S_OK;
+}
+
+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.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !x_left || !y_top || !width || !height ||
+ !parent_hwnd()) {
+ return E_INVALIDARG;
+ }
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_ACCLOCATION, var_id, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ POINT top_left = {0, 0};
+
+ // Find the top left corner of the containing window in screen coords, and
+ // adjust the output position by this amount.
+ ::ClientToScreen(parent_hwnd(), &top_left);
+
+ *x_left = response().output_long1 + top_left.x;
+ *y_top = response().output_long2 + top_left.y;
+
+ *width = response().output_long3;
+ *height = response().output_long4;
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::accNavigate(LONG nav_dir, VARIANT start,
+ VARIANT* end) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (start.vt != VT_I4 || !end)
+ return E_INVALIDARG;
+
+ if ((nav_dir == NAVDIR_LASTCHILD || nav_dir == NAVDIR_FIRSTCHILD) &&
+ start.lVal != CHILDID_SELF) {
+ // MSAA states that navigating to first/last child can only be from self.
+ return E_INVALIDARG;
+ }
+
+ if (nav_dir == NAVDIR_DOWN || nav_dir == NAVDIR_UP ||
+ nav_dir == NAVDIR_LEFT || nav_dir == NAVDIR_RIGHT) {
+ // Directions not implemented, matching Mozilla and IE.
+ return E_INVALIDARG;
+ }
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_ACCNAVIGATE, start, nav_dir,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No screen element was found in the specified direction.
+ end->vt = VT_EMPTY;
+ return S_FALSE;
+ }
+
+ if (response().output_long1 == -1) {
+ if (CreateInstance(IID_IAccessible, response().iaccessible_id,
+ reinterpret_cast<void**>(&end->pdispVal)) == S_OK) {
+ end->vt = VT_DISPATCH;
+ // Increment the reference count for the retrieved interface.
+ end->pdispVal->AddRef();
+ } else {
+ return E_NOINTERFACE;
+ }
+ } else {
+ end->vt = VT_I4;
+ end->lVal = response().output_long1;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accChild(VARIANT var_child,
+ IDispatch** disp_child) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_child.vt != VT_I4 || !disp_child)
+ return E_INVALIDARG;
+
+ // If var_child is the parent, remain with the same IDispatch.
+ if (var_child.lVal == CHILDID_SELF && iaccessible_id_ != 0)
+ return S_OK;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCCHILD, var_child, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // When at a leaf, children are handled by the parent object.
+ *disp_child = NULL;
+ return S_FALSE;
+ }
+
+ // Retrieve the IUnknown interface for the parent view, and assign the
+ // IDispatch returned.
+ if (CreateInstance(IID_IAccessible, response().iaccessible_id,
+ reinterpret_cast<void**>(disp_child)) == S_OK) {
+ // Increment the reference count for the retrieved interface.
+ (*disp_child)->AddRef();
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+STDMETHODIMP BrowserAccessibility::get_accChildCount(LONG* child_count) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (!child_count)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCCHILDCOUNT,
+ EmptyVariant(), NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ *child_count = response().output_long1;
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accDefaultAction(VARIANT var_id,
+ BSTR* def_action) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !def_action)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCDEFAULTACTION, var_id,
+ NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No string found.
+ return S_FALSE;
+ }
+
+ *def_action = CComBSTR(response().output_string.c_str()).Detach();
+
+ DCHECK(*def_action);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accDescription(VARIANT var_id,
+ BSTR* desc) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !desc)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCDESCRIPTION, var_id,
+ NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No string found.
+ return S_FALSE;
+ }
+
+ *desc = CComBSTR(response().output_string.c_str()).Detach();
+
+ DCHECK(*desc);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accFocus(VARIANT* focus_child) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (!focus_child)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCFOCUS, EmptyVariant(),
+ NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // The window that contains this object is not the active window.
+ focus_child->vt = VT_EMPTY;
+ return S_FALSE;
+ }
+
+ if (response().output_long1 == -1) {
+ if (CreateInstance(IID_IAccessible, response().iaccessible_id,
+ reinterpret_cast<void**>(&focus_child->pdispVal)) == S_OK) {
+ focus_child->vt = VT_DISPATCH;
+ // Increment the reference count for the retrieved interface.
+ focus_child->pdispVal->AddRef();
+ } else {
+ return E_NOINTERFACE;
+ }
+ } else {
+ focus_child->vt = VT_I4;
+ focus_child->lVal = response().output_long1;
+ }
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accHelp(VARIANT var_id, BSTR* help) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !help)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCHELP, var_id, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No string found.
+ return S_FALSE;
+ }
+
+ *help = CComBSTR(response().output_string.c_str()).Detach();
+
+ DCHECK(*help);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accKeyboardShortcut(VARIANT var_id,
+ BSTR* acc_key) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !acc_key)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCKEYBOARDSHORTCUT,
+ var_id, NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No string found.
+ return S_FALSE;
+ }
+
+ *acc_key = CComBSTR(response().output_string.c_str()).Detach();
+
+ DCHECK(*acc_key);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accName(VARIANT var_id, BSTR* name) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !name)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCNAME, var_id, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No string found.
+ return S_FALSE;
+ }
+
+ *name = CComBSTR(response().output_string.c_str()).Detach();
+
+ DCHECK(*name);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accParent(IDispatch** disp_parent) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (!disp_parent || !parent_hwnd())
+ return E_INVALIDARG;
+
+ // Root node's parent is the containing HWND's IAccessible.
+ if (iaccessible_id() == 0) {
+ // For an object that has no parent (e.g. root), point the accessible parent
+ // to the default implementation.
+ HRESULT hr =
+ ::CreateStdAccessibleObject(parent_hwnd(), OBJID_WINDOW,
+ IID_IAccessible,
+ reinterpret_cast<void**>(disp_parent));
+
+ if (!SUCCEEDED(hr)) {
+ *disp_parent = NULL;
+ return S_FALSE;
+ }
+ return S_OK;
+ }
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCPARENT, EmptyVariant(),
+ NULL, NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No parent exists for this object.
+ return S_FALSE;
+ }
+
+ // Retrieve the IUnknown interface for the parent view, and assign the
+ // IDispatch returned.
+ if (CreateInstance(IID_IAccessible, response().iaccessible_id,
+ reinterpret_cast<void**>(disp_parent)) == S_OK) {
+ // Increment the reference count for the retrieved interface.
+ (*disp_parent)->AddRef();
+ return S_OK;
+ } else {
+ return E_NOINTERFACE;
+ }
+}
+
+STDMETHODIMP BrowserAccessibility::get_accRole(VARIANT var_id, VARIANT* role) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !role)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCROLE, var_id, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ role->vt = VT_I4;
+ role->lVal = response().output_long1;
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accState(VARIANT var_id,
+ VARIANT* state) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !state)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCSTATE, var_id, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ state->vt = VT_I4;
+ state->lVal = response().output_long1;
+
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accValue(VARIANT var_id, BSTR* value) {
+ if (!instance_active()) {
+ // Instance no longer active, fail gracefully.
+ return E_FAIL;
+ }
+
+ if (var_id.vt != VT_I4 || !value)
+ return E_INVALIDARG;
+
+ if (!RequestAccessibilityInfo(IACCESSIBLE_FUNC_GET_ACCVALUE, var_id, NULL,
+ NULL)) {
+ return E_FAIL;
+ }
+
+ if (!response().return_code) {
+ // No string found.
+ return S_FALSE;
+ }
+
+ *value = CComBSTR(response().output_string.c_str()).Detach();
+
+ DCHECK(*value);
+ return S_OK;
+}
+
+STDMETHODIMP BrowserAccessibility::accSelect(LONG flags_select,
+ VARIANT var_id) {
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accHelpTopic(BSTR* help_file,
+ VARIANT var_id,
+ LONG* topic_id) {
+ if (help_file) {
+ *help_file = NULL;
+ }
+ if (topic_id) {
+ *topic_id = static_cast<LONG>(-1);
+ }
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP BrowserAccessibility::get_accSelection(VARIANT* selected) {
+ if (selected)
+ selected->vt = VT_EMPTY;
+
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP BrowserAccessibility::put_accName(VARIANT var_id, BSTR put_name) {
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP BrowserAccessibility::put_accValue(VARIANT var_id, BSTR put_val) {
+ return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP BrowserAccessibility::CreateInstance(REFIID iid,
+ int iaccessible_id,
+ void** interface_ptr) {
+ return BrowserAccessibilityManager::Instance()->CreateAccessibilityInstance(
+ iid, iaccessible_id, instance_id(), interface_ptr);
+}
+
+bool BrowserAccessibility::RequestAccessibilityInfo(int iaccessible_func_id,
+ VARIANT var_id, LONG input1,
+ LONG input2) {
+ return BrowserAccessibilityManager::Instance()->RequestAccessibilityInfo(
+ iaccessible_id(), instance_id(), iaccessible_func_id, var_id, input1,
+ input2);
+}
+
+ViewHostMsg_Accessibility_Out_Params BrowserAccessibility::response() {
+ return BrowserAccessibilityManager::Instance()->response();
+}
+
+HWND BrowserAccessibility::parent_hwnd() {
+ return BrowserAccessibilityManager::Instance()->parent_hwnd(instance_id());
+}
+
diff --git a/chrome/browser/browser_accessibility.h b/chrome/browser/browser_accessibility.h
new file mode 100644
index 0000000..5032183
--- /dev/null
+++ b/chrome/browser/browser_accessibility.h
@@ -0,0 +1,169 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BROWSER_ACCESSIBILITY_H_
+#define CHROME_BROWSER_BROWSER_ACCESSIBILITY_H_
+
+#include <atlbase.h>
+#include <atlcom.h>
+
+#include <oleacc.h>
+
+#include "chrome/common/render_messages.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// BrowserAccessibility
+//
+// Class implementing the MSAA IAccessible COM interface for the
+// Browser-Renderer communication of MSAA information, providing accessibility
+// to be used by screen readers and other assistive technology (AT).
+//
+////////////////////////////////////////////////////////////////////////////////
+class ATL_NO_VTABLE BrowserAccessibility
+ : public CComObjectRootEx<CComMultiThreadModel>,
+ public IDispatchImpl<IAccessible, &IID_IAccessible, &LIBID_Accessibility> {
+ public:
+ BEGIN_COM_MAP(BrowserAccessibility)
+ COM_INTERFACE_ENTRY2(IDispatch, IAccessible)
+ COM_INTERFACE_ENTRY(IAccessible)
+ END_COM_MAP()
+
+ BrowserAccessibility();
+ ~BrowserAccessibility() {}
+
+ // Supported IAccessible methods.
+
+ // Performs the default action on a given object.
+ STDMETHODIMP accDoDefaultAction(VARIANT var_id);
+
+ // Retrieves the child element or child object at a given point on the screen.
+ STDMETHODIMP accHitTest(LONG x_left, LONG y_top, VARIANT* child);
+
+ // Retrieves the specified object's current screen location.
+ STDMETHODIMP accLocation(LONG* x_left,
+ LONG* y_top,
+ LONG* width,
+ LONG* height,
+ VARIANT var_id);
+
+ // Traverses to another UI element and retrieves the object.
+ STDMETHODIMP accNavigate(LONG nav_dir, VARIANT start, VARIANT* end);
+
+ // Retrieves an IDispatch interface pointer for the specified child.
+ STDMETHODIMP get_accChild(VARIANT var_child, IDispatch** disp_child);
+
+ // Retrieves the number of accessible children.
+ STDMETHODIMP get_accChildCount(LONG* child_count);
+
+ // Retrieves a string that describes the object's default action.
+ STDMETHODIMP get_accDefaultAction(VARIANT var_id, BSTR* default_action);
+
+ // Retrieves the object's description.
+ STDMETHODIMP get_accDescription(VARIANT var_id, BSTR* desc);
+
+ // Retrieves the object that has the keyboard focus.
+ STDMETHODIMP get_accFocus(VARIANT* focus_child);
+
+ // Retrieves the help information associated with the object.
+ STDMETHODIMP get_accHelp(VARIANT var_id, BSTR* help);
+
+ // Retrieves the specified object's shortcut.
+ STDMETHODIMP get_accKeyboardShortcut(VARIANT var_id, BSTR* access_key);
+
+ // Retrieves the name of the specified object.
+ STDMETHODIMP get_accName(VARIANT var_id, BSTR* name);
+
+ // Retrieves the IDispatch interface of the object's parent.
+ STDMETHODIMP get_accParent(IDispatch** disp_parent);
+
+ // Retrieves information describing the role of the specified object.
+ STDMETHODIMP get_accRole(VARIANT var_id, VARIANT* role);
+
+ // Retrieves the current state of the specified object.
+ STDMETHODIMP get_accState(VARIANT var_id, VARIANT* state);
+
+ // Returns the value associated with the object.
+ STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value);
+
+ // Non-supported (by WebKit) IAccessible methods.
+ STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id);
+
+ STDMETHODIMP get_accHelpTopic(BSTR* help_file,
+ VARIANT var_id,
+ LONG* topic_id);
+
+ STDMETHODIMP get_accSelection(VARIANT* selected);
+
+ // Deprecated functions, not implemented here.
+ STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name);
+ STDMETHODIMP put_accValue(VARIANT var_id, BSTR put_val);
+
+ // Modify/retrieve the unique id of this IAccessible instance.
+ void set_iaccessible_id(int iaccessible_id) {
+ iaccessible_id_ = iaccessible_id;
+ }
+ int iaccessible_id() const { return iaccessible_id_; }
+
+ // Modify/retrieve the unique id of this IAccessible's routing variables.
+ void set_instance_id(int instance_id) {
+ instance_id_ = instance_id;
+ }
+ int instance_id() const { return instance_id_; }
+
+ // Modify/retrieve the state (active/inactive) of this instance.
+ void set_instance_active(bool instance_active) {
+ instance_active_ = instance_active;
+ }
+ int instance_active() const { return instance_active_; }
+
+ private:
+ // Creates an empty VARIANT. Used as the equivalent of a NULL (unused) input
+ // parameter.
+ VARIANT EmptyVariant() const {
+ VARIANT empty;
+ empty.vt = VT_EMPTY;
+ return empty;
+ }
+
+ // Wrapper functions, calling through to singleton instance of
+ // BrowserAccessibilityManager.
+
+ // Creates an instance of BrowserAccessibility, initializes it and sets the
+ // |iaccessible_id| and |parent_id|.
+ STDMETHODIMP CreateInstance(REFIID iid,
+ int iaccessible_id,
+ void** interface_ptr);
+
+ // Composes and sends a message for requesting needed accessibility
+ // information. Unused LONG input parameters should be NULL, and the VARIANT
+ // an empty, valid instance.
+ bool RequestAccessibilityInfo(int iaccessible_func_id,
+ VARIANT var_id,
+ LONG input1, LONG input2);
+
+ // Accessors.
+ ViewHostMsg_Accessibility_Out_Params response();
+ HWND parent_hwnd();
+
+ // Id to uniquely distinguish this instance in the render-side caching,
+ // mapping it to the correct IAccessible on that side. Initialized to -1.
+ int iaccessible_id_;
+
+ // The unique id of this IAccessible instance. Used to help
+ // BrowserAccessibilityManager instance retrieve the correct member
+ // variables for this process.
+ int instance_id_;
+
+ // The instance should only be active if there is a non-terminated
+ // RenderProcessHost associated with it. The BrowserAccessibilityManager keeps
+ // track of this state, and sets it to false to disable all calls into the
+ // renderer from this instance of BroweserAccessibility, and have all
+ // IAccessible functions return E_FAIL.
+ bool instance_active_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserAccessibility);
+};
+#endif // CHROME_BROWSER_BROWSER_ACCESSIBILITY_H_
+
diff --git a/chrome/browser/browser_accessibility_manager.cc b/chrome/browser/browser_accessibility_manager.cc
new file mode 100644
index 0000000..c670cf8
--- /dev/null
+++ b/chrome/browser/browser_accessibility_manager.cc
@@ -0,0 +1,167 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/browser_accessibility_manager.h"
+
+#include "chrome/browser/browser_accessibility.h"
+#include "chrome/browser/render_process_host.h"
+#include "chrome/browser/render_widget_host.h"
+
+// The time in ms after which we give up and return an error when processing an
+// accessibility message and no response has been received from the renderer.
+static const int kAccessibilityMessageTimeOut = 500;
+
+// static
+BrowserAccessibilityManager* BrowserAccessibilityManager::Instance() {
+ return Singleton<BrowserAccessibilityManager>::get();
+}
+
+BrowserAccessibilityManager::BrowserAccessibilityManager()
+ : instance_id_(0) {
+ NotificationService::current()->AddObserver(this,
+ NOTIFY_RENDERER_PROCESS_TERMINATED, NotificationService::AllSources());
+}
+
+BrowserAccessibilityManager::~BrowserAccessibilityManager() {
+ // Clear hashmaps.
+ instance_map_.clear();
+ render_process_host_map_.clear();
+
+ NotificationService::current()->RemoveObserver(this,
+ NOTIFY_RENDERER_PROCESS_TERMINATED, NotificationService::AllSources());
+}
+
+STDMETHODIMP BrowserAccessibilityManager::CreateAccessibilityInstance(
+ REFIID iid, int iaccessible_id, int instance_id, void** interface_ptr) {
+ if (IID_IUnknown == iid || IID_IDispatch == iid || IID_IAccessible == iid) {
+ CComObject<BrowserAccessibility>* instance = NULL;
+
+ HRESULT hr = CComObject<BrowserAccessibility>::CreateInstance(&instance);
+ DCHECK(SUCCEEDED(hr));
+
+ if (!instance)
+ return E_FAIL;
+
+ CComPtr<IAccessible> accessibility_instance(instance);
+
+ // Set unique ids.
+ instance->set_iaccessible_id(iaccessible_id);
+ instance->set_instance_id(instance_id);
+
+ // Retrieve the RenderWidgetHost connected to this request.
+ InstanceMap::iterator it = instance_map_.find(instance_id);
+
+ if (it != instance_map_.end()) {
+ UniqueMembers* members = it->second;
+
+ if (!members || !members->render_widget_host_)
+ return E_FAIL;
+
+ render_process_host_map_[members->render_widget_host_->process()] =
+ instance;
+ } else {
+ // No RenderProcess active for this instance.
+ return E_FAIL;
+ }
+
+ // All is well, assign the temp instance to the output pointer.
+ *interface_ptr = accessibility_instance.Detach();
+ return S_OK;
+ }
+ // No supported interface found, return error.
+ *interface_ptr = NULL;
+ return E_NOINTERFACE;
+}
+
+bool BrowserAccessibilityManager::RequestAccessibilityInfo(
+ int iaccessible_id, int instance_id, int iaccessible_func_id,
+ VARIANT var_id, LONG input1, LONG input2) {
+ // Create and populate input message structure.
+ ViewMsg_Accessibility_In_Params in_params;
+
+ in_params.iaccessible_id = iaccessible_id;
+ in_params.iaccessible_function_id = iaccessible_func_id;
+ in_params.input_variant_lval = var_id.lVal;
+ in_params.input_long1 = input1;
+ in_params.input_long2 = input2;
+
+ // Retrieve the RenderWidgetHost connected to this request.
+ InstanceMap::iterator it = instance_map_.find(instance_id);
+
+ if (it == instance_map_.end()) {
+ // Id not found.
+ return false;
+ }
+
+ UniqueMembers* members = it->second;
+
+ if (!members || !members->render_widget_host_)
+ return false;
+
+ IPC::SyncMessage* msg =
+ new ViewMsg_GetAccessibilityInfo(
+ members->render_widget_host_->routing_id(), in_params, &out_params_);
+
+ // Necessary for the send to keep the UI responsive.
+ msg->EnableMessagePumping();
+ bool success = members->render_widget_host_->process()->channel()->
+ SendWithTimeout(msg, kAccessibilityMessageTimeOut);
+
+ return success;
+}
+
+ViewHostMsg_Accessibility_Out_Params BrowserAccessibilityManager::response() {
+ return out_params_;
+}
+
+HWND BrowserAccessibilityManager::parent_hwnd(int id) {
+ // Retrieve the parent HWND connected to the requester's id.
+ InstanceMap::iterator it = instance_map_.find(id);
+
+ if (it == instance_map_.end()) {
+ // Id not found.
+ return NULL;
+ }
+
+ UniqueMembers* members = it->second;
+
+ if (!members || !members->parent_hwnd_)
+ return NULL;
+
+ return members->parent_hwnd_;
+}
+
+int BrowserAccessibilityManager::SetMembers(BrowserAccessibility* browser_acc,
+ HWND parent_hwnd, RenderWidgetHost* render_widget_host) {
+ // Set HWND and RenderWidgetHost connected to |browser_acc|.
+ instance_map_[instance_id_] =
+ new UniqueMembers(parent_hwnd, render_widget_host);
+
+ render_process_host_map_[render_widget_host->process()] = browser_acc;
+ return instance_id_++;
+}
+
+void BrowserAccessibilityManager::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK(type == NOTIFY_RENDERER_PROCESS_TERMINATED);
+ RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
+ DCHECK(rph);
+ RenderProcessHostMap::iterator it = render_process_host_map_.find(rph);
+
+ if (it == render_process_host_map_.end() || !it->second) {
+ // RenderProcessHost not associated with any BrowserAccessibility instance.
+ return;
+ }
+
+ // Set BrowserAccessibility instance to inactive state.
+ it->second->set_instance_active(false);
+ render_process_host_map_.erase(it);
+
+ // Delete entry also from InstanceMap.
+ InstanceMap::iterator it2 = instance_map_.find(it->second->instance_id());
+
+ if (it2 != instance_map_.end())
+ instance_map_.erase(it2);
+}
diff --git a/chrome/browser/browser_accessibility_manager.h b/chrome/browser/browser_accessibility_manager.h
new file mode 100644
index 0000000..1ac25e4
--- /dev/null
+++ b/chrome/browser/browser_accessibility_manager.h
@@ -0,0 +1,108 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_BROWSER_ACCESSIBILITY_MANAGER_H_
+#define CHROME_BROWSER_BROWSER_ACCESSIBILITY_MANAGER_H_
+
+#include <oaidl.h> // Needed for VARIANT structure.
+#include <hash_map>
+
+#include "base/singleton.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/render_messages.h"
+
+class BrowserAccessibility;
+class RenderProcessHost;
+class RenderWidgetHost;
+
+// Member variable structure, used in instance hashmap.
+struct UniqueMembers {
+ RenderWidgetHost* render_widget_host_;
+ HWND parent_hwnd_;
+
+ UniqueMembers(HWND parent_hwnd, RenderWidgetHost* render_widget_host)
+ : parent_hwnd_(parent_hwnd),
+ render_widget_host_(render_widget_host) {
+ }
+};
+
+typedef stdext::hash_map<int, UniqueMembers*> InstanceMap;
+typedef stdext::hash_map<RenderProcessHost*, BrowserAccessibility*>
+ RenderProcessHostMap;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// BrowserAccessibilityManager
+//
+// Used to manage instance creation and memory handling for browser side
+// accessibility. A singleton class. It implements NotificationObserver to
+// ensure that a termination of a renderer process gets propagated to the
+// active BrowserAccessibility instances calling into it. Each such instance
+// will upon such an event be set to an inactive state, failing calls from the
+// assistive technology gracefully.
+////////////////////////////////////////////////////////////////////////////////
+class BrowserAccessibilityManager : public NotificationObserver {
+ public:
+ // Gets the singleton BrowserAccessibilityManager object. The first time this
+ // method is called, a CacheManagerHost object is constructed and returned.
+ // Subsequent calls will return the same object.
+ static BrowserAccessibilityManager* Instance();
+
+ // Creates an instance of BrowserAccessibility, initializes it and sets the
+ // iaccessible_id and parent_id.
+ STDMETHODIMP CreateAccessibilityInstance(REFIID iid,
+ int iaccessible_id,
+ int instance_id,
+ void** interface_ptr);
+
+ // Composes and sends a message for requesting needed accessibility
+ // information. Unused LONG input parameters should be NULL, and the VARIANT
+ // an empty, valid instance.
+ bool RequestAccessibilityInfo(int iaccessible_id,
+ int instance_id,
+ int iaccessible_func_id,
+ VARIANT var_id,
+ LONG input1,
+ LONG input2);
+
+ // Wrapper function, for cleaner code.
+ ViewHostMsg_Accessibility_Out_Params response();
+
+ // Retrieves the parent HWND connected to the provided id.
+ HWND parent_hwnd(int id);
+
+ // Mutator, needed since constructor does not take any arguments, and to keep
+ // instance accessor clean.
+ int SetMembers(BrowserAccessibility* browser_acc,
+ HWND parent_hwnd,
+ RenderWidgetHost* render_widget_host);
+
+ // NotificationObserver implementation.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+ protected:
+ // This class is a singleton. Do not instantiate directly.
+ BrowserAccessibilityManager();
+ friend DefaultSingletonTraits<BrowserAccessibilityManager>;
+
+ ~BrowserAccessibilityManager();
+
+ private:
+ // Caching of the unique member variables used to handle browser accessibility
+ // requests from multiple processes.
+ InstanceMap instance_map_;
+ int instance_id_;
+
+ // Reverse mapping to track which RenderProcessHosts are active. If a
+ // RenderProcessHost is found to be terminated, it should be removed from this
+ // mapping, and the connected BrowserAccessibility ids/instances invalidated.
+ RenderProcessHostMap render_process_host_map_;
+
+ ViewHostMsg_Accessibility_Out_Params out_params_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManager);
+};
+#endif // CHROME_BROWSER_BROWSER_ACCESSIBILITY_MANAGER_H_
diff --git a/chrome/browser/iaccessible_function_ids.h b/chrome/browser/iaccessible_function_ids.h
new file mode 100644
index 0000000..4f97681
--- /dev/null
+++ b/chrome/browser/iaccessible_function_ids.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This defines an enumeration of IDs that can uniquely identify a call to a
+// specific IAccessible function. Should match the support implemented in WebKit
+// (functions marked with return value E_NOTIMPL are also excluded).
+
+#ifndef CHROME_BROWSER_IACCESSIBLE_FUNCTION_IDS_H_
+#define CHROME_BROWSER_IACCESSIBLE_FUNCTION_IDS_H_
+
+enum IAccessibleID {
+ IACCESSIBLE_FUNC_NONE = 0,
+
+ // Supported IAccessible interface functions.
+ IACCESSIBLE_FUNC_ACCDODEFAULTACTION,
+ IACCESSIBLE_FUNC_ACCHITTEST,
+ IACCESSIBLE_FUNC_ACCLOCATION,
+ IACCESSIBLE_FUNC_ACCNAVIGATE,
+ IACCESSIBLE_FUNC_GET_ACCCHILD,
+ IACCESSIBLE_FUNC_GET_ACCCHILDCOUNT,
+ IACCESSIBLE_FUNC_GET_ACCDEFAULTACTION,
+ IACCESSIBLE_FUNC_GET_ACCDESCRIPTION,
+ IACCESSIBLE_FUNC_GET_ACCFOCUS,
+ IACCESSIBLE_FUNC_GET_ACCHELP,
+ IACCESSIBLE_FUNC_GET_ACCKEYBOARDSHORTCUT,
+ IACCESSIBLE_FUNC_GET_ACCNAME,
+ IACCESSIBLE_FUNC_GET_ACCPARENT,
+ IACCESSIBLE_FUNC_GET_ACCROLE,
+ IACCESSIBLE_FUNC_GET_ACCSTATE,
+ IACCESSIBLE_FUNC_GET_ACCVALUE
+
+ // The deprecated put_accName and put_accValue are not supported here, nor is
+ // accSelect, get_accHelpTopic and get_accSelection (matching WebKit's
+ // support).
+};
+
+#endif // CHROME_BROWSER_IACCESSIBLE_FUNCTION_IDS_H_
diff --git a/chrome/browser/render_view_host.cc b/chrome/browser/render_view_host.cc
index 9128c87..d269017 100644
--- a/chrome/browser/render_view_host.cc
+++ b/chrome/browser/render_view_host.cc
@@ -246,7 +246,7 @@ void RenderViewHost::FirePageUnload() {
// Start the hang monitor in case the renderer hangs in the unload handler.
is_waiting_for_unload_ack_ = true;
StartHangMonitorTimeout(TimeDelta::FromMilliseconds(kUnloadTimeoutMS));
- ClosePage(site_instance()->process_host_id(),
+ ClosePage(site_instance()->process_host_id(),
routing_id());
}
@@ -638,7 +638,7 @@ void RenderViewHost::OnMessageReceived(const IPC::Message& msg) {
#ifdef CHROME_PERSONALIZATION
IPC_MESSAGE_HANDLER(ViewHostMsg_PersonalizationEvent,
OnPersonalizationEvent)
-#endif
+#endif
IPC_MESSAGE_HANDLER(ViewHostMsg_GoToEntryAtOffset,
OnMsgGoToEntryAtOffset)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetTooltipText, OnMsgSetTooltipText)
@@ -1193,7 +1193,7 @@ void RenderViewHost::OnDebugDisconnect() {
}
#ifdef CHROME_PERSONALIZATION
-void RenderViewHost::RaisePersonalizationEvent(std::string event_name,
+void RenderViewHost::RaisePersonalizationEvent(std::string event_name,
std::string event_arg) {
Send(new ViewMsg_PersonalizationEvent(routing_id_,
event_name,
diff --git a/chrome/browser/render_widget_host_hwnd.cc b/chrome/browser/render_widget_host_hwnd.cc
index 8ca727c..bae1cfa 100644
--- a/chrome/browser/render_widget_host_hwnd.cc
+++ b/chrome/browser/render_widget_host_hwnd.cc
@@ -9,6 +9,8 @@
#include "base/gfx/rect.h"
#include "base/histogram.h"
#include "base/win_util.h"
+#include "chrome/browser/browser_accessibility.h"
+#include "chrome/browser/browser_accessibility_manager.h"
#include "chrome/browser/render_process_host.h"
// TODO(beng): (Cleanup) we should not need to include this file... see comment
// in |DidBecomeSelected|.
@@ -747,6 +749,55 @@ LRESULT RenderWidgetHostHWND::OnMouseActivate(UINT, WPARAM, LPARAM,
}
}
+LRESULT RenderWidgetHostHWND::OnGetObject(UINT message, WPARAM wparam,
+ LPARAM lparam, BOOL& handled) {
+ LRESULT reference_result = static_cast<LRESULT>(0L);
+
+ // Accessibility readers will send an OBJID_CLIENT message.
+ if (OBJID_CLIENT == lparam) {
+ // If our MSAA DOM root is already created, reuse that pointer. Otherwise,
+ // create a new one.
+ if (!browser_accessibility_root_) {
+ CComObject<BrowserAccessibility>* accessibility = NULL;
+
+ if (!SUCCEEDED(CComObject<BrowserAccessibility>::CreateInstance(
+ &accessibility)) || !accessibility) {
+ // Return with failure.
+ return static_cast<LRESULT>(0L);
+ }
+
+ CComPtr<IAccessible> accessibility_comptr(accessibility);
+
+ // Root id is always 0, to distinguish this particular instance when
+ // mapping to the render-side IAccessible.
+ accessibility->set_iaccessible_id(0);
+
+ // Set the unique member variables of this particular process.
+ accessibility->set_instance_id(BrowserAccessibilityManager::Instance()->
+ SetMembers(accessibility, m_hWnd, render_widget_host_));
+
+ // All is well, assign the temp instance to the class smart pointer.
+ browser_accessibility_root_.Attach(accessibility_comptr.Detach());
+
+ if (!browser_accessibility_root_) {
+ // Paranoia check. Return with failure.
+ NOTREACHED();
+ return static_cast<LRESULT>(0L);
+ }
+
+ // Notify that an instance of IAccessible was allocated for m_hWnd.
+ ::NotifyWinEvent(EVENT_OBJECT_CREATE, m_hWnd, OBJID_CLIENT,
+ CHILDID_SELF);
+ }
+
+ // Create a reference to ViewAccessibility that MSAA will marshall
+ // to the client.
+ reference_result = LresultFromObject(IID_IAccessible, wparam,
+ static_cast<IAccessible*>(browser_accessibility_root_));
+ }
+ return reference_result;
+}
+
void RenderWidgetHostHWND::OnFinalMessage(HWND window) {
render_widget_host_->ViewDestroyed();
delete this;
diff --git a/chrome/browser/render_widget_host_hwnd.h b/chrome/browser/render_widget_host_hwnd.h
index bc16c6d..c9a392b 100644
--- a/chrome/browser/render_widget_host_hwnd.h
+++ b/chrome/browser/render_widget_host_hwnd.h
@@ -107,6 +107,7 @@ class RenderWidgetHostHWND :
MESSAGE_HANDLER(WM_SYSCHAR, OnKeyEvent)
MESSAGE_HANDLER(WM_IME_CHAR, OnKeyEvent)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, OnMouseActivate)
+ MESSAGE_HANDLER(WM_GETOBJECT, OnGetObject)
END_MSG_MAP()
// Overridden from RenderWidgetHostView:
@@ -164,6 +165,9 @@ class RenderWidgetHostHWND :
LRESULT OnWheelEvent(
UINT message, WPARAM wparam, LPARAM lparam, BOOL& handled);
LRESULT OnMouseActivate(UINT, WPARAM, LPARAM, BOOL& handled);
+ // Handle MSAA requests for accessibility information.
+ LRESULT OnGetObject(UINT message, WPARAM wparam, LPARAM lparam,
+ BOOL& handled);
// Handle vertical scrolling
LRESULT OnVScroll(int code, short position, HWND scrollbar_control);
// Handle horizontal scrolling
@@ -246,6 +250,10 @@ class RenderWidgetHostHWND :
// when shown again.
HWND parent_hwnd_;
+ // Instance of accessibility information for the root of the MSAA
+ // tree representation of the WebKit render tree.
+ CComPtr<IAccessible> browser_accessibility_root_;
+
// The time at which this view started displaying white pixels as a result of
// not having anything to paint (empty backing store from renderer). This
// value returns true for is_null() if we are not recording whiteout times.
diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h
index 3c2ee58..c4038a2 100644
--- a/chrome/common/render_messages.h
+++ b/chrome/common/render_messages.h
@@ -375,6 +375,55 @@ struct ViewHostMsg_DidPrintPage_Params {
double actual_shrink;
};
+// Parameters structure to hold a union of the possible IAccessible function
+// INPUT variables, with the unused fields always set to default value. Used in
+// ViewMsg_GetAccessibilityInfo, as only parameter.
+struct ViewMsg_Accessibility_In_Params {
+ // Identifier to uniquely distinguish which instance of IAccessible is being
+ // called upon on the renderer side.
+ int iaccessible_id;
+
+ // Identifier to resolve which IAccessible interface function is being called.
+ int iaccessible_function_id;
+
+ // Function input parameters.
+ // Input VARIANT structure's LONG field to specify requested object.
+ long input_variant_lval;
+
+ // LONG input parameters, used differently depending on the function called.
+ long input_long1;
+ long input_long2;
+};
+
+// Parameters structure to hold a union of the possible IAccessible function
+// OUTPUT variables, with the unused fields always set to default value. Used in
+// ViewHostMsg_GetAccessibilityInfoResponse, as only parameter.
+struct ViewHostMsg_Accessibility_Out_Params {
+ // Identifier to uniquely distinguish which instance of IAccessible is being
+ // called upon on the renderer side.
+ int iaccessible_id;
+
+ // Function output parameters.
+ // Output VARIANT structure's LONG field to specify requested object.
+ long output_variant_lval;
+
+ // LONG output parameters, used differently depending on the function called.
+ // output_long1 can in some cases be set to -1 to indicate that the child
+ // object found by the called IAccessible function is not a simple object.
+ long output_long1;
+ long output_long2;
+ long output_long3;
+ long output_long4;
+
+ // String output parameter.
+ std::wstring output_string;
+
+ // Return code, either S_OK (true) or S_FALSE (false). WebKit MSAA error
+ // return codes (E_POINTER, E_INVALIDARG, E_FAIL, E_NOTIMPL) must be handled
+ // on the browser side by input validation.
+ bool return_code;
+};
+
// The first parameter for the ViewHostMsg_ImeUpdateStatus message.
enum ViewHostMsg_ImeControl {
IME_DISABLE = 0,
@@ -579,6 +628,86 @@ struct ParamTraits<WebInputEvent::Type> {
}
};
+// Traits for ViewMsg_Accessibility_In_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewMsg_Accessibility_In_Params> {
+ typedef ViewMsg_Accessibility_In_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.iaccessible_id);
+ WriteParam(m, p.iaccessible_function_id);
+ WriteParam(m, p.input_variant_lval);
+ WriteParam(m, p.input_long1);
+ WriteParam(m, p.input_long2);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->iaccessible_id) &&
+ ReadParam(m, iter, &p->iaccessible_function_id) &&
+ ReadParam(m, iter, &p->input_variant_lval) &&
+ ReadParam(m, iter, &p->input_long1) &&
+ ReadParam(m, iter, &p->input_long2);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.iaccessible_id, l);
+ l->append(L", ");
+ LogParam(p.iaccessible_function_id, l);
+ l->append(L", ");
+ LogParam(p.input_variant_lval, l);
+ l->append(L", ");
+ LogParam(p.input_long1, l);
+ l->append(L", ");
+ LogParam(p.input_long2, l);
+ l->append(L")");
+ }
+};
+
+// Traits for ViewHostMsg_Accessibility_Out_Params structure to pack/unpack.
+template <>
+struct ParamTraits<ViewHostMsg_Accessibility_Out_Params> {
+ typedef ViewHostMsg_Accessibility_Out_Params param_type;
+ static void Write(Message* m, const param_type& p) {
+ WriteParam(m, p.iaccessible_id);
+ WriteParam(m, p.output_variant_lval);
+ WriteParam(m, p.output_long1);
+ WriteParam(m, p.output_long2);
+ WriteParam(m, p.output_long3);
+ WriteParam(m, p.output_long4);
+ WriteParam(m, p.output_string);
+ WriteParam(m, p.return_code);
+ }
+ static bool Read(const Message* m, void** iter, param_type* p) {
+ return
+ ReadParam(m, iter, &p->iaccessible_id) &&
+ ReadParam(m, iter, &p->output_variant_lval) &&
+ ReadParam(m, iter, &p->output_long1) &&
+ ReadParam(m, iter, &p->output_long2) &&
+ ReadParam(m, iter, &p->output_long3) &&
+ ReadParam(m, iter, &p->output_long4) &&
+ ReadParam(m, iter, &p->output_string) &&
+ ReadParam(m, iter, &p->return_code);
+ }
+ static void Log(const param_type& p, std::wstring* l) {
+ l->append(L"(");
+ LogParam(p.iaccessible_id, l);
+ l->append(L", ");
+ LogParam(p.output_variant_lval, l);
+ l->append(L", ");
+ LogParam(p.output_long1, l);
+ l->append(L", ");
+ LogParam(p.output_long2, l);
+ l->append(L", ");
+ LogParam(p.output_long3, l);
+ l->append(L", ");
+ LogParam(p.output_long4, l);
+ l->append(L", ");
+ LogParam(p.output_string, l);
+ l->append(L", ");
+ LogParam(p.return_code, l);
+ l->append(L")");
+ }
+};
+
template <>
struct ParamTraits<ViewHostMsg_ImeControl> {
typedef ViewHostMsg_ImeControl param_type;
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index faf8beb..9480f06 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -372,6 +372,20 @@ IPC_BEGIN_MESSAGES(View, 1)
int /* back_list_count */,
int /* forward_list_count */)
+ // Retreive information from the MSAA DOM subtree, for accessibility purposes.
+ IPC_SYNC_MESSAGE_ROUTED1_1(ViewMsg_GetAccessibilityInfo,
+ ViewMsg_Accessibility_In_Params
+ /* input parameters */,
+ ViewHostMsg_Accessibility_Out_Params
+ /* output parameters */)
+
+ // Requests the renderer to clear cashed accessibility information. Takes an
+ // id to clear a specific hashmap entry, and a bool; true clears all, false
+ // does not.
+ IPC_MESSAGE_ROUTED2(ViewMsg_ClearAccessibilityInfo,
+ int /* iaccessible_id */,
+ bool /* clear_all */)
+
// Get all savable resource links from current webpage, include main
// frame and sub-frame.
IPC_MESSAGE_ROUTED1(ViewMsg_GetAllSavableResourceLinksForCurrentPage,
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 636fc54..af907c1 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -310,7 +310,8 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
OnAllowDomAutomationBindings)
IPC_MESSAGE_HANDLER(ViewMsg_AllowBindings, OnAllowBindings)
IPC_MESSAGE_HANDLER(ViewMsg_SetDOMUIProperty, OnSetDOMUIProperty)
- IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved, OnDragSourceEndedOrMoved)
+ IPC_MESSAGE_HANDLER(ViewMsg_DragSourceEndedOrMoved,
+ OnDragSourceEndedOrMoved)
IPC_MESSAGE_HANDLER(ViewMsg_DragSourceSystemDragEnded,
OnDragSourceSystemDragEnded)
IPC_MESSAGE_HANDLER(ViewMsg_SetInitialFocus, OnSetInitialFocus)
@@ -328,6 +329,9 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_GetSerializedHtmlDataForCurrentPageWithLocalLinks,
OnGetSerializedHtmlDataForCurrentPageWithLocalLinks)
IPC_MESSAGE_HANDLER(ViewMsg_GetApplicationInfo, OnGetApplicationInfo)
+ IPC_MESSAGE_HANDLER(ViewMsg_GetAccessibilityInfo, OnGetAccessibilityInfo)
+ IPC_MESSAGE_HANDLER(ViewMsg_ClearAccessibilityInfo,
+ OnClearAccessibilityInfo)
IPC_MESSAGE_HANDLER(ViewMsg_ShouldClose, OnMsgShouldClose)
IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
@@ -1051,6 +1055,11 @@ void RenderView::UpdateURL(WebFrame* frame) {
// we don't want the transition type to persist.
if (extra_data)
extra_data->transition_type = PageTransition::LINK; // Just clear it.
+
+ if (glue_accessibility_.get()) {
+ // Clear accessibility info cache.
+ glue_accessibility_->ClearIAccessibleMap(-1, true);
+ }
}
// Tell the embedding application that the title of the active page has changed
@@ -1146,7 +1155,7 @@ void RenderView::DidStartProvisionalLoadForFrame(
NavigationGesture gesture) {
if (webview->GetMainFrame() == frame) {
navigation_gesture_ = gesture;
-
+
// Make sure redirect tracking state is clear for the new load.
completed_client_redirect_src_ = GURL();
}
@@ -2260,8 +2269,7 @@ void RenderView::OnAllowDomAutomationBindings(bool allow_bindings) {
}
void RenderView::OnAllowBindings(bool enable_dom_ui_bindings,
- bool enable_external_host_bindings)
-{
+ bool enable_external_host_bindings) {
enable_dom_ui_bindings_ = enable_dom_ui_bindings;
enable_external_host_bindings_ = enable_external_host_bindings;
}
@@ -2406,6 +2414,29 @@ void RenderView::OnUpdateBackForwardListCount(int back_list_count,
history_forward_list_count_ = forward_list_count;
}
+void RenderView::OnGetAccessibilityInfo(
+ const ViewMsg_Accessibility_In_Params& in_params,
+ ViewHostMsg_Accessibility_Out_Params* out_params) {
+
+ if (!glue_accessibility_.get())
+ glue_accessibility_.reset(new GlueAccessibility());
+
+ if (!glue_accessibility_->
+ GetAccessibilityInfo(webview(), in_params, out_params)) {
+ return;
+ }
+}
+
+void RenderView::OnClearAccessibilityInfo(int iaccessible_id, bool clear_all) {
+ if (!glue_accessibility_.get()) {
+ // If accessibility is not activated, ignore clearing message.
+ return;
+ }
+
+ if (!glue_accessibility_->ClearIAccessibleMap(iaccessible_id, clear_all))
+ return;
+}
+
void RenderView::OnGetAllSavableResourceLinksForCurrentPage(
const GURL& page_url) {
// Prepare list to storage all savable resource links.
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index 6f6b9c3..71faf63 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -26,6 +26,7 @@
#include "chrome/renderer/render_widget.h"
#include "webkit/glue/console_message_level.h"
#include "webkit/glue/dom_serializer_delegate.h"
+#include "webkit/glue/glue_accessibility.h"
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/webview.h"
@@ -418,6 +419,9 @@ class RenderView : public RenderWidget, public WebViewDelegate,
void OnEnableViewSourceMode();
void OnUpdateBackForwardListCount(int back_list_count,
int forward_list_count);
+ void OnGetAccessibilityInfo(const ViewMsg_Accessibility_In_Params& in_params,
+ ViewHostMsg_Accessibility_Out_Params* out_params);
+ void OnClearAccessibilityInfo(int iaccessible_id, bool clear_all);
// Checks if the RenderView should close, runs the beforeunload handler and
// sends ViewMsg_ShouldClose to the browser.
@@ -612,6 +616,10 @@ class RenderView : public RenderWidget, public WebViewDelegate,
// True if the page has any frame-level unload or beforeunload listeners.
bool has_unload_listener_;
+ // Handles accessibility requests into the renderer side, as well as
+ // maintains the cache and other features of the accessibility tree.
+ scoped_ptr<GlueAccessibility> glue_accessibility_;
+
DISALLOW_EVIL_CONSTRUCTORS(RenderView);
};