summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorklink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-20 20:12:25 +0000
committerklink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-03-20 20:12:25 +0000
commit6a983b4e4d28c1e3841f39febeb6a9dd681b53b3 (patch)
treea4b5d6a01066c026338d071076db9ff7dae210f3 /webkit
parentfe5a8a4ff6f5758f8dbf7e6e9578df97fb8633db (diff)
downloadchromium_src-6a983b4e4d28c1e3841f39febeb6a9dd681b53b3.zip
chromium_src-6a983b4e4d28c1e3841f39febeb6a9dd681b53b3.tar.gz
chromium_src-6a983b4e4d28c1e3841f39febeb6a9dd681b53b3.tar.bz2
Removes all use of COM and dependencies on Windows-specific classes (including the use of AccessibleBase and AccessibleDocument) in the glue accessibility implementation.Introduces the GlueAccessibilityObject, which serves as a platform-independent wrapper directly around WebKit's AccessibilityObject (also platoform-independent).Updates naming/comments to reflect the independence of IAccessible both in glue and (where appropriate) in the browser-side accessibility.
Review URL: http://codereview.chromium.org/46013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@12207 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/SConscript3
-rw-r--r--webkit/glue/glue.vcproj20
-rw-r--r--webkit/glue/glue_accessibility.cc281
-rw-r--r--webkit/glue/glue_accessibility.h77
-rw-r--r--webkit/glue/glue_accessibility_object.cc445
-rw-r--r--webkit/glue/glue_accessibility_object.h118
-rw-r--r--webkit/glue/webaccessibility.h155
-rw-r--r--webkit/glue/webaccessibilitymanager.h54
-rw-r--r--webkit/glue/webaccessibilitymanager_impl.cc241
-rw-r--r--webkit/glue/webaccessibilitymanager_impl.h70
10 files changed, 1103 insertions, 361 deletions
diff --git a/webkit/glue/SConscript b/webkit/glue/SConscript
index 8a1b050..cd42a67 100644
--- a/webkit/glue/SConscript
+++ b/webkit/glue/SConscript
@@ -116,7 +116,8 @@ if env.Bit('windows'):
input_files.extend([
'$PENDING_DIR/AccessibleBase.cpp',
'$PENDING_DIR/AccessibleDocument.cpp',
- 'glue_accessibility.cc',
+ 'webaccessibilitymanager_impl.cc',
+ 'glue_accessibility_object.cc'
'plugins/mozilla_extensions.cc',
'plugins/webplugin_delegate_impl.cc',
'webdropdata.cc',
diff --git a/webkit/glue/glue.vcproj b/webkit/glue/glue.vcproj
index 35c11a0..17cfc38 100644
--- a/webkit/glue/glue.vcproj
+++ b/webkit/glue/glue.vcproj
@@ -173,6 +173,14 @@
>
</File>
<File
+ RelativePath=".\webaccessibility.h"
+ >
+ </File>
+ <File
+ RelativePath=".\webaccessibilitymanager.h"
+ >
+ </File>
+ <File
RelativePath=".\webdatasource.h"
>
</File>
@@ -425,11 +433,11 @@
>
</File>
<File
- RelativePath=".\glue_accessibility.cc"
+ RelativePath=".\glue_accessibility_object.cc"
>
</File>
<File
- RelativePath=".\glue_accessibility.h"
+ RelativePath=".\glue_accessibility_object.h"
>
</File>
<File
@@ -561,6 +569,14 @@
>
</File>
<File
+ RelativePath=".\webaccessibilitymanager_impl.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\webaccessibilitymanager_impl.h"
+ >
+ </File>
+ <File
RelativePath=".\webclipboard_impl.cc"
>
</File>
diff --git a/webkit/glue/glue_accessibility.cc b/webkit/glue/glue_accessibility.cc
deleted file mode 100644
index c49d15b..0000000
--- a/webkit/glue/glue_accessibility.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-// 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 <comdef.h>
-
-#include "config.h"
-
-#pragma warning(push, 0)
-#include "AccessibleDocument.h"
-#include "AXObjectCache.h"
-#include "Document.h"
-#include "Frame.h"
-#pragma warning(pop)
-#undef LOG
-
-#include "webkit/glue/glue_accessibility.h"
-
-#include "base/logging.h"
-#include "base/ref_counted.h"
-#include "webkit/glue/webframe_impl.h"
-#include "webkit/glue/webview_impl.h"
-
-// struct GlueAccessibility::GlueAccessibilityRoot
-struct GlueAccessibility::GlueAccessibilityRoot {
- GlueAccessibilityRoot() {}
-
- // Root of the WebKit IAccessible tree.
- scoped_refptr<AccessibleDocument> accessibility_root_;
-};
-
-// class GlueAccessibility
-GlueAccessibility::GlueAccessibility()
- : root_(new GlueAccessibilityRoot) {
-}
-
-GlueAccessibility::~GlueAccessibility() {
- delete root_;
-}
-
-bool GlueAccessibility::GetAccessibilityInfo(WebView* view,
- const AccessibilityInParams& in_params,
- AccessibilityOutParams* out_params) {
- WebFrame* main_frame = view->GetMainFrame();
- if (!main_frame || !static_cast<WebFrameImpl*>(main_frame)->frameview())
- return false;
-
- if (!root_->accessibility_root_ && !InitAccessibilityRoot(view)) {
- // Failure in retrieving the root.
- return false;
- }
-
- // Temporary storing for the currently active IAccessible.
- scoped_refptr<IAccessible> active_iaccessible;
- IntToIAccessibleMap::iterator it =
- int_to_iaccessible_map_.find(in_params.iaccessible_id);
-
- if (it == int_to_iaccessible_map_.end()) {
- // Map did not contain the data requested.
- return false;
- }
-
- active_iaccessible = it->second;
-
- if (!active_iaccessible) {
- // Requested IAccessible not found. Paranoia check.
- NOTREACHED();
- return false;
- }
-
- // Input VARIANT, determined by the browser side to be of type VT_I4.
- VARIANT input_variant;
- input_variant.vt = VT_I4;
- input_variant.lVal = in_params.input_variant_lval;
-
- // Output variables, used locally to retrieve data.
- VARIANT output_variant;
- ::VariantInit(&output_variant);
- BSTR output_bstr;
- bool string_output = false;
- HRESULT hr = S_FALSE;
-
- switch (in_params.iaccessible_function_id) {
- case IACCESSIBLE_FUNC_ACCDODEFAULTACTION :
- hr = active_iaccessible->accDoDefaultAction(input_variant);
- break;
- case IACCESSIBLE_FUNC_ACCHITTEST :
- hr = active_iaccessible->accHitTest(in_params.input_long1,
- in_params.input_long2,
- &output_variant);
- break;
- case IACCESSIBLE_FUNC_ACCLOCATION :
- hr = active_iaccessible->accLocation(&out_params->output_long1,
- &out_params->output_long2,
- &out_params->output_long3,
- &out_params->output_long4,
- input_variant);
- break;
- case IACCESSIBLE_FUNC_ACCNAVIGATE :
- hr = active_iaccessible->accNavigate(in_params.input_long1, input_variant,
- &output_variant);
- break;
- case IACCESSIBLE_FUNC_GET_ACCCHILD :
- if (input_variant.lVal == CHILDID_SELF) {
- // If child requested is CHILDID_SELF, stay with the same IAccessible.
- out_params->iaccessible_id = in_params.iaccessible_id;
- hr = S_OK;
- break;
- }
- hr = active_iaccessible->get_accChild(input_variant,
- reinterpret_cast<IDispatch **>(&output_variant.pdispVal));
- output_variant.vt = VT_DISPATCH;
- break;
- case IACCESSIBLE_FUNC_GET_ACCCHILDCOUNT :
- hr = active_iaccessible->get_accChildCount(&out_params->output_long1);
- break;
- case IACCESSIBLE_FUNC_GET_ACCDEFAULTACTION :
- hr = active_iaccessible->get_accDefaultAction(input_variant,
- &output_bstr);
- string_output = true;
- break;
- case IACCESSIBLE_FUNC_GET_ACCDESCRIPTION :
- hr = active_iaccessible->get_accDescription(input_variant, &output_bstr);
- string_output = true;
- break;
- case IACCESSIBLE_FUNC_GET_ACCFOCUS :
- hr = active_iaccessible->get_accFocus(&output_variant);
- break;
- case IACCESSIBLE_FUNC_GET_ACCHELP :
- hr = active_iaccessible->get_accHelp(input_variant, &output_bstr);
- string_output = true;
- break;
- case IACCESSIBLE_FUNC_GET_ACCKEYBOARDSHORTCUT :
- hr = active_iaccessible->get_accKeyboardShortcut(input_variant,
- &output_bstr);
- string_output = true;
- break;
- case IACCESSIBLE_FUNC_GET_ACCNAME :
- hr = active_iaccessible->get_accName(input_variant, &output_bstr);
- string_output = true;
- break;
- case IACCESSIBLE_FUNC_GET_ACCPARENT :
- hr = active_iaccessible->get_accParent(
- reinterpret_cast<IDispatch **>(&output_variant.pdispVal));
- output_variant.vt = VT_DISPATCH;
- break;
- case IACCESSIBLE_FUNC_GET_ACCROLE :
- hr = active_iaccessible->get_accRole(input_variant, &output_variant);
- break;
- case IACCESSIBLE_FUNC_GET_ACCSTATE :
- hr = active_iaccessible->get_accState(input_variant, &output_variant);
- break;
- case IACCESSIBLE_FUNC_GET_ACCVALUE :
- hr = active_iaccessible->get_accValue(input_variant, &output_bstr);
- string_output = true;
- break;
- default:
- // Memory cleanup.
- ::VariantClear(&input_variant);
- ::VariantClear(&output_variant);
-
- // Non-supported function id.
- return false;
- }
-
- // Return code handling.
- if (hr == S_OK) {
- out_params->return_code = true;
-
- // All is ok, assign output string if needed.
- if (string_output) {
- out_params->output_string = _bstr_t(output_bstr);
- ::SysFreeString(output_bstr);
- }
-
- } else if (hr == S_FALSE) {
- out_params->return_code = false;
- } else {
- // Memory cleanup.
- ::VariantClear(&input_variant);
- ::VariantClear(&output_variant);
-
- // Generate a generic failure on the browser side. Input validation is the
- // responsibility of the browser side, as is correctly handling calls to
- // non-supported functions appropriately.
- return false;
- }
-
- // Output and hashmap assignments, as appropriate.
- if (output_variant.vt == VT_DISPATCH && output_variant.pdispVal) {
- IAccessibleToIntMap::iterator it =
- iaccessible_to_int_map_.find(
- reinterpret_cast<IAccessible *>(output_variant.pdispVal));
-
- if (it != iaccessible_to_int_map_.end()) {
- // Data already present in map, return previously assigned id.
- out_params->iaccessible_id = it->second;
- out_params->output_long1 = -1;
- } else {
- // Insert new IAccessible in hashmaps.
- int_to_iaccessible_map_[iaccessible_id_] =
- reinterpret_cast<IAccessible *>(output_variant.pdispVal);
- iaccessible_to_int_map_[
- reinterpret_cast<IAccessible *>(output_variant.pdispVal)] =
- iaccessible_id_;
- out_params->iaccessible_id = iaccessible_id_++;
- out_params->output_long1 = -1;
- }
- } else if (output_variant.vt == VT_I4) {
- out_params->output_long1 = output_variant.lVal;
- }
-
- // Memory cleanup.
- ::VariantClear(&input_variant);
- ::VariantClear(&output_variant);
-
- return true;
-}
-
-bool GlueAccessibility::InitAccessibilityRoot(WebView* view) {
- WebCore::AXObjectCache::enableAccessibility();
- iaccessible_id_ = 0;
-
- WebFrame* main_frame = view->GetMainFrame();
- WebFrameImpl* main_frame_impl = static_cast<WebFrameImpl*>(main_frame);
- WebCore::Frame* frame = main_frame_impl->frame();
- WebCore::Document* currentDocument = frame->document();
-
- if (!currentDocument || !currentDocument->renderer()) {
- return false;
- } else if (!root_->accessibility_root_ ||
- root_->accessibility_root_->document() != currentDocument) {
- // Either we've never had a wrapper for this frame's top-level Document,
- // the Document renderer was destroyed and its wrapper was detached, or
- // the previous Document is in the page cache, and the current document
- // needs to be wrapped.
- root_->accessibility_root_ = new AccessibleDocument(currentDocument);
- }
- // Insert root in hashmaps.
- int_to_iaccessible_map_[iaccessible_id_] = root_->accessibility_root_.get();
- iaccessible_to_int_map_[root_->accessibility_root_.get()] = iaccessible_id_++;
-
- return true;
-}
-
-bool GlueAccessibility::ClearIAccessibleMap(int iaccessible_id,
- bool clear_all) {
- if (clear_all) {
- // Clear maps and invalidate root.
- int_to_iaccessible_map_.clear();
- iaccessible_to_int_map_.clear();
- root_->accessibility_root_ = 0;
- return true;
- }
-
- IntToIAccessibleMap::iterator it =
- int_to_iaccessible_map_.find(iaccessible_id);
-
- if (it == int_to_iaccessible_map_.end()) {
- // Element not found.
- return false;
- } else {
- if (it->second) {
- // Erase element from reverse hashmap.
- IAccessibleToIntMap::iterator it2 =
- iaccessible_to_int_map_.find(it->second.get());
-
- DCHECK(it2 != iaccessible_to_int_map_.end());
- iaccessible_to_int_map_.erase(it2);
- }
-
- int_to_iaccessible_map_.erase(it);
-
- if (iaccessible_id == 0) {
- // Invalidate root.
- root_->accessibility_root_ = 0;
- }
- }
-
- return true;
-}
diff --git a/webkit/glue/glue_accessibility.h b/webkit/glue/glue_accessibility.h
deleted file mode 100644
index 2976c68..0000000
--- a/webkit/glue/glue_accessibility.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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 WEBKIT_GLUE_GLUE_ACCESSIBILITY_H_
-#define WEBKIT_GLUE_GLUE_ACCESSIBILITY_H_
-
-#if defined(OS_WIN)
-#include <oleacc.h>
-#else
-// TODO(port): need an equivalent of
-// http://msdn.microsoft.com/en-us/library/accessibility.iaccessible.aspx
-class IAccessible;
-#endif
-
-#include "base/hash_tables.h"
-#include "base/ref_counted.h"
-#include "chrome/common/accessibility.h"
-
-class WebView;
-
-template <typename T> class COMPtr;
-
-typedef base::hash_map<int, scoped_refptr<IAccessible> > IntToIAccessibleMap;
-typedef base::hash_map<IAccessible*, int> IAccessibleToIntMap;
-
-////////////////////////////////////////////////////////////////////////////////
-//
-// GlueAccessibility
-//
-// Operations that access the underlying WebKit DOM directly, exposing
-// accessibility information.
-////////////////////////////////////////////////////////////////////////////////
-class GlueAccessibility {
- public:
- GlueAccessibility();
- ~GlueAccessibility();
-
- // Retrieves the IAccessible information as requested in in_params, by calling
- // into WebKit's implementation of IAccessible. Maintains a hashmap of the
- // currently active (browser ref count not zero) IAccessibles. Returns true if
- // successful, false otherwise.
- bool GetAccessibilityInfo(WebView* view,
- const AccessibilityInParams& in_params,
- AccessibilityOutParams* out_params);
-
- // Erases the entry identified by the |iaccessible_id| from the hash map. If
- // |clear_all| is true, all entries are erased. Returns true if successful,
- // false otherwise.
- bool ClearIAccessibleMap(int iaccessible_id, bool clear_all);
-
- private:
- // Retrieves the RenderObject associated with this WebView, and uses it to
- // initialize the root of the render-side MSAA tree with the associated
- // accessibility information. Returns true if successful, false otherwise.
- bool InitAccessibilityRoot(WebView* view);
-
- // Wrapper around the COM pointer that holds the root of the MSAA tree, to
- // ensure that we are not requiring WebKit includes outside of glue.
- struct GlueAccessibilityRoot;
- GlueAccessibilityRoot* root_;
-
- // Hashmap for cashing of elements in use by the AT, mapping id (int) to an
- // IAccessible pointer.
- IntToIAccessibleMap int_to_iaccessible_map_;
- // Hashmap for cashing of elements in use by the AT, mapping an IAccessible
- // pointer to its id (int). Needed for reverse lookup, to ensure unnecessary
- // duplicate entries are not created in the IntToIAccessibleMap (above).
- IAccessibleToIntMap iaccessible_to_int_map_;
-
- // Unique identifier for retrieving an IAccessible from the page's hashmap.
- int iaccessible_id_;
-
- DISALLOW_COPY_AND_ASSIGN(GlueAccessibility);
-};
-
-#endif // WEBKIT_GLUE_GLUE_ACCESSIBILITY_H_
diff --git a/webkit/glue/glue_accessibility_object.cc b/webkit/glue/glue_accessibility_object.cc
new file mode 100644
index 0000000..17a693e
--- /dev/null
+++ b/webkit/glue/glue_accessibility_object.cc
@@ -0,0 +1,445 @@
+// Copyright (c) 2006-2009 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 "config.h"
+
+#include "AccessibilityObject.h"
+#include "EventHandler.h"
+#include "FrameView.h"
+#include "PlatformKeyboardEvent.h"
+
+#include "webkit/glue/glue_accessibility_object.h"
+
+using WebCore::AccessibilityObject;
+using WebCore::String;
+using webkit_glue::WebAccessibility;
+
+GlueAccessibilityObject::GlueAccessibilityObject(AccessibilityObject* obj)
+ : AccessibilityObjectWrapper(obj) {
+ m_object->setWrapper(this);
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::CreateInstance(
+ AccessibilityObject* obj) {
+ if (!obj)
+ return NULL;
+
+ return new GlueAccessibilityObject(obj);
+}
+
+bool GlueAccessibilityObject::DoDefaultAction(int child_id) {
+ AccessibilityObject* child_obj;
+
+ if (!GetAccessibilityObjectForChild(child_id, child_obj) ||
+ !child_obj->performDefaultAction()) {
+ return false;
+ }
+ return true;
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::HitTest(long x, long y) {
+ if (!m_object)
+ return NULL;
+
+ // x, y - coordinates are passed in as window coordinates, to maintain
+ // sandbox functionality.
+ WebCore::IntPoint point =
+ m_object->documentFrameView()->windowToContents(WebCore::IntPoint(x, y));
+ AccessibilityObject* child_obj = m_object->doAccessibilityHitTest(point);
+
+ if (!child_obj) {
+ // If we did not hit any child objects, test whether the point hit us, and
+ // report that.
+ if (!m_object->boundingBoxRect().contains(point))
+ return NULL;
+ child_obj = m_object;
+ }
+ // TODO(klink): simple object child?
+ ToWrapper(child_obj)->ref();
+ return ToWrapper(child_obj);
+}
+
+bool GlueAccessibilityObject::Location(long* left, long* top, long* width,
+ long* height, int child_id) {
+ if (!left || !top || !width || !height)
+ return false;
+
+ *left = *top = *width = *height = 0;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ // Returning window coordinates, to be handled and converted appropriately by
+ // the client.
+ WebCore::IntRect window_rect(child_obj->documentFrameView()->contentsToWindow(
+ child_obj->boundingBoxRect()));
+ *left = window_rect.x();
+ *top = window_rect.y();
+ *width = window_rect.width();
+ *height = window_rect.height();
+ return true;
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::Navigate(
+ WebAccessibility::Direction dir, int start_child_id) {
+ AccessibilityObject* child_obj = 0;
+
+ switch (dir) {
+ case WebAccessibility::DIRECTION_DOWN:
+ case WebAccessibility::DIRECTION_UP:
+ case WebAccessibility::DIRECTION_LEFT:
+ case WebAccessibility::DIRECTION_RIGHT:
+ // These directions are not implemented, matching Mozilla and IE.
+ return NULL;
+ case WebAccessibility::DIRECTION_LASTCHILD:
+ case WebAccessibility::DIRECTION_FIRSTCHILD:
+ // MSDN states that navigating to first/last child can only be from self.
+ if (start_child_id != 0 || !m_object)
+ return NULL;
+
+ if (dir == WebAccessibility::DIRECTION_FIRSTCHILD) {
+ child_obj = m_object->firstChild();
+ } else {
+ child_obj = m_object->lastChild();
+ }
+ break;
+ case WebAccessibility::DIRECTION_NEXT:
+ case WebAccessibility::DIRECTION_PREVIOUS: {
+ // Navigating to next and previous is allowed from self or any of our
+ // children.
+ if (!GetAccessibilityObjectForChild(start_child_id, child_obj))
+ return NULL;
+
+ if (dir == WebAccessibility::DIRECTION_NEXT) {
+ child_obj = child_obj->nextSibling();
+ } else {
+ child_obj = child_obj->previousSibling();
+ }
+ break;
+ }
+ default:
+ return NULL;
+ }
+
+ if (!child_obj)
+ return NULL;
+
+ // TODO(klink): simple object child?
+ ToWrapper(child_obj)->ref();
+ return ToWrapper(child_obj);
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::GetChild(int child_id) {
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ // TODO(klink): simple object child?
+ ToWrapper(child_obj)->ref();
+ return ToWrapper(child_obj);
+}
+
+bool GlueAccessibilityObject::ChildCount(long* count) {
+ if (!m_object || !count)
+ return false;
+
+ *count = static_cast<long>(m_object->children().size());
+ return true;
+}
+
+bool GlueAccessibilityObject::DefaultAction(int child_id, String* action) {
+ if (!action)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ *action = child_obj->actionVerb();
+ return !action->isEmpty();
+}
+
+bool GlueAccessibilityObject::Description(int child_id, String* description) {
+ if (!description)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ // TODO(klink): Description, for SELECT subitems, should be a string
+ // describing the position of the item in its group and of the group in the
+ // list (see Firefox).
+ *description = ToWrapper(child_obj)->description();
+ return !description->isEmpty();
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::GetFocusedChild() {
+ if (!m_object)
+ return NULL;
+
+ AccessibilityObject* focused_obj = m_object->focusedUIElement();
+ if (!focused_obj)
+ return NULL;
+
+ // Only return the focused child if it's us or a child of us.
+ if (focused_obj == m_object || focused_obj->parentObject() == m_object) {
+ ToWrapper(focused_obj)->ref();
+ return ToWrapper(focused_obj);
+ }
+ return NULL;
+}
+
+bool GlueAccessibilityObject::HelpText(int child_id, String* help) {
+ if (!help)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ *help = child_obj->helpText();
+ return !help->isEmpty();
+}
+
+bool GlueAccessibilityObject::KeyboardShortcut(int child_id, String* shortcut) {
+ if (!shortcut)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ String access_key = child_obj->accessKey();
+ if (access_key.isNull())
+ return false;
+
+ static String access_key_modifiers;
+ if (access_key_modifiers.isNull()) {
+ unsigned modifiers = WebCore::EventHandler::accessKeyModifiers();
+ // Follow the same order as Mozilla MSAA implementation:
+ // Ctrl+Alt+Shift+Meta+key. MSDN states that keyboard shortcut strings
+ // should not be localized and defines the separator as "+".
+ if (modifiers & WebCore::PlatformKeyboardEvent::CtrlKey)
+ access_key_modifiers += "Ctrl+";
+ if (modifiers & WebCore::PlatformKeyboardEvent::AltKey)
+ access_key_modifiers += "Alt+";
+ if (modifiers & WebCore::PlatformKeyboardEvent::ShiftKey)
+ access_key_modifiers += "Shift+";
+ if (modifiers & WebCore::PlatformKeyboardEvent::MetaKey)
+ access_key_modifiers += "Win+";
+ }
+ *shortcut = access_key_modifiers + access_key;
+ return !shortcut->isEmpty();
+}
+
+bool GlueAccessibilityObject::Name(int child_id, String* name) {
+ if (!name)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ *name = ToWrapper(child_obj)->name();
+ return !name->isEmpty();
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::GetParent() {
+ if (!m_object)
+ return NULL;
+
+ AccessibilityObject* parent_obj = m_object->parentObject();
+
+ if (parent_obj) {
+ ToWrapper(parent_obj)->ref();
+ return ToWrapper(parent_obj);
+ }
+ // No valid parent, or parent is the containing window.
+ return NULL;
+}
+
+bool GlueAccessibilityObject::Role(int child_id, long* role) {
+ if (!role)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ *role = ToWrapper(child_obj)->role();
+ return true;
+}
+
+bool GlueAccessibilityObject::Value(int child_id, String* value) {
+ if (!value)
+ return false;
+
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ *value = ToWrapper(child_obj)->value();
+ return !value->isEmpty();
+}
+
+bool GlueAccessibilityObject::State(int child_id, long* state) {
+ if (!state)
+ return false;
+
+ *state = 0;
+ AccessibilityObject* child_obj;
+ if (!GetAccessibilityObjectForChild(child_id, child_obj))
+ return false;
+
+ if (child_obj->isAnchor())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_LINKED);
+
+ if (child_obj->isHovered())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_HOTTRACKED);
+
+ if (!child_obj->isEnabled())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_UNAVAILABLE);
+
+ if (child_obj->isReadOnly())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_READONLY);
+
+ if (child_obj->isOffScreen())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_OFFSCREEN);
+
+ if (child_obj->isMultiSelect())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_MULTISELECTABLE);
+
+ if (child_obj->isPasswordField())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_PROTECTED);
+
+ if (child_obj->isIndeterminate())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_INDETERMINATE);
+
+ if (child_obj->isChecked())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_CHECKED);
+
+ if (child_obj->isPressed())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_PRESSED);
+
+ if (child_obj->isFocused())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSED);
+
+ if (child_obj->isVisited())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_TRAVERSED);
+
+ if (child_obj->canSetFocusAttribute())
+ *state |= static_cast<long>(1 << WebAccessibility::STATE_FOCUSABLE);
+
+ // TODO(klink): Add selected and selectable states.
+
+ return true;
+}
+
+// Helper functions
+String GlueAccessibilityObject::name() const {
+ return m_object->title();
+}
+
+String GlueAccessibilityObject::value() const {
+ return m_object->stringValue();
+}
+
+String GlueAccessibilityObject::description() const {
+ String desc = m_object->accessibilityDescription();
+ if (desc.isNull())
+ return desc;
+
+ // From the Mozilla MSAA implementation:
+ // "Signal to screen readers that this description is speakable and is not
+ // a formatted positional information description. Don't localize the
+ // 'Description: ' part of this string, it will be parsed out by assistive
+ // technologies."
+ return "Description: " + desc;
+}
+
+// Provides a conversion between the WebCore::AccessibilityRole and a
+// role supported on the Browser side. Static function.
+static WebAccessibility::Role SupportedRole(WebCore::AccessibilityRole role) {
+ switch (role) {
+ case WebCore::ButtonRole:
+ return WebAccessibility::ROLE_PUSHBUTTON;
+ case WebCore::RadioButtonRole:
+ return WebAccessibility::ROLE_RADIOBUTTON;
+ case WebCore::CheckBoxRole:
+ return WebAccessibility::ROLE_CHECKBUTTON;
+ case WebCore::SliderRole:
+ return WebAccessibility::ROLE_SLIDER;
+ case WebCore::TabGroupRole:
+ return WebAccessibility::ROLE_PAGETABLIST;
+ case WebCore::TextFieldRole:
+ case WebCore::TextAreaRole:
+ case WebCore::ListMarkerRole:
+ return WebAccessibility::ROLE_TEXT;
+ case WebCore::StaticTextRole:
+ return WebAccessibility::ROLE_STATICTEXT;
+ case WebCore::OutlineRole:
+ return WebAccessibility::ROLE_OUTLINE;
+ case WebCore::ColumnRole:
+ return WebAccessibility::ROLE_COLUMN;
+ case WebCore::RowRole:
+ return WebAccessibility::ROLE_ROW;
+ case WebCore::GroupRole:
+ return WebAccessibility::ROLE_GROUPING;
+ case WebCore::ListRole:
+ return WebAccessibility::ROLE_LIST;
+ case WebCore::TableRole:
+ return WebAccessibility::ROLE_TABLE;
+ case WebCore::LinkRole:
+ case WebCore::WebCoreLinkRole:
+ return WebAccessibility::ROLE_LINK;
+ case WebCore::ImageMapRole:
+ case WebCore::ImageRole:
+ return WebAccessibility::ROLE_GRAPHIC;
+ default:
+ // This is the default role.
+ return WebAccessibility::ROLE_CLIENT;
+ }
+}
+
+WebAccessibility::Role GlueAccessibilityObject::role() const {
+ return SupportedRole(m_object->roleValue());
+}
+
+bool GlueAccessibilityObject::GetAccessibilityObjectForChild(int child_id,
+ AccessibilityObject*& child_obj) const {
+ child_obj = 0;
+
+ if (!m_object || child_id < 0)
+ return false;
+
+ if (child_id == 0) {
+ child_obj = m_object;
+ } else {
+ size_t child_index = static_cast<size_t>(child_id - 1);
+
+ if (child_index >= m_object->children().size())
+ return false;
+ child_obj = m_object->children().at(child_index).get();
+ }
+
+ if (!child_obj)
+ return false;
+
+ return true;
+}
+
+GlueAccessibilityObject* GlueAccessibilityObject::ToWrapper(
+ AccessibilityObject* obj) {
+ if (!obj)
+ return NULL;
+
+ GlueAccessibilityObject* result =
+ static_cast<GlueAccessibilityObject*>(obj->wrapper());
+ if (!result)
+ result = CreateInstance(obj);
+
+ return result;
+}
diff --git a/webkit/glue/glue_accessibility_object.h b/webkit/glue/glue_accessibility_object.h
new file mode 100644
index 0000000..137a7e3
--- /dev/null
+++ b/webkit/glue/glue_accessibility_object.h
@@ -0,0 +1,118 @@
+// 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 WEBKIT_GLUE_GLUE_ACCESSIBILITY_OBJECT_H_
+#define WEBKIT_GLUE_GLUE_ACCESSIBILITY_OBJECT_H_
+
+#include "AccessibilityObjectWrapper.h"
+
+#include "base/basictypes.h"
+#include "webkit/glue/webaccessibility.h"
+
+namespace WebCore {
+class AccessibilityObject;
+enum AccessibilityRole;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// GlueAccessibilityObject
+//
+// Operations that access the underlying WebKit DOM directly, exposing
+// accessibility information to the GlueAccessibilityManager. Also provides a
+// platform-independent wrapper to WebKit's AccessibilityObject.
+////////////////////////////////////////////////////////////////////////////////
+class GlueAccessibilityObject : public WebCore::AccessibilityObjectWrapper {
+ public:
+ static GlueAccessibilityObject* CreateInstance(WebCore::AccessibilityObject*);
+
+ // Performs the default action on a given object.
+ bool DoDefaultAction(int child_id);
+
+ // Retrieves the child element or child object at a given point on the screen.
+ GlueAccessibilityObject* HitTest(long x, long y);
+
+ // Retrieves the specified object's current screen location.
+ bool Location(long* left,
+ long* top,
+ long* width,
+ long* height,
+ int child_id);
+
+ // Traverses to another UI element and retrieves the object.
+ GlueAccessibilityObject* Navigate(
+ webkit_glue::WebAccessibility::Direction dir,
+ int start_child_id);
+
+ // Retrieves an GlueAccessibilityObject pointer for the specified [child_id].
+ GlueAccessibilityObject* GetChild(int child_id);
+
+ // Retrieves the number of accessible children.
+ bool ChildCount(long* count);
+
+ // Retrieves a string that describes the object's default action.
+ bool DefaultAction(int child_id, WebCore::String* action);
+
+ // Retrieves the object's description.
+ bool Description(int child_id, WebCore::String* description);
+
+ // Retrieves the object that has the keyboard focus.
+ GlueAccessibilityObject* GetFocusedChild();
+
+ // Retrieves the help information associated with the object.
+ bool HelpText(int child_id, WebCore::String* help);
+
+ // Retrieves the specified object's shortcut.
+ bool KeyboardShortcut(int child_id, WebCore::String* shortcut);
+
+ // Retrieves the name of the specified object.
+ bool Name(int child_id, WebCore::String* name);
+
+ // Retrieves the GlueAccessibilityObject of the object's parent. In the case
+ // of the root object (where the parent is the containing window), it is up
+ // to the browser side to handle this.
+ GlueAccessibilityObject* GetParent();
+
+ // Retrieves information describing the role of the specified object.
+ bool Role(int child_id, long* role);
+
+ // Retrieves the current state of the specified object.
+ bool State(int child_id, long* state);
+
+ // Returns the value associated with the object.
+ bool Value(int child_id, WebCore::String* value);
+
+ // WebCore::AccessiblityObjectWrapper.
+ virtual void detach() {
+ if (m_object)
+ m_object = 0;
+ }
+
+ protected:
+ explicit GlueAccessibilityObject(WebCore::AccessibilityObject*);
+ virtual ~GlueAccessibilityObject() {}
+
+ // Helper functions.
+ WebCore::String name() const;
+ WebCore::String value() const;
+ WebCore::String description() const;
+ webkit_glue::WebAccessibility::Role role() const;
+
+ // Retrieves the AccessibilityObject for a given [child_id]. Returns false if
+ // [child_id] is less than 0, or if no valid AccessibilityObject is found.
+ // A [child_id] of 0 is treated as referring to the current object itself.
+ bool GetAccessibilityObjectForChild(int child_id,
+ WebCore::AccessibilityObject*&) const;
+
+ // Wraps the given AccessibilityObject in a GlueAccessibilityObject and
+ // returns it. If the AccessibilityObject already has a wrapper assigned, that
+ // one is returned. Otherwise, a new instance of GlueAccessibilityObject is
+ // created and assigned as the wrapper.
+ static GlueAccessibilityObject* ToWrapper(WebCore::AccessibilityObject*);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GlueAccessibilityObject);
+};
+
+#endif // WEBKIT_GLUE_GLUE_ACCESSIBILITY_OBJECT_H_
diff --git a/webkit/glue/webaccessibility.h b/webkit/glue/webaccessibility.h
new file mode 100644
index 0000000..538e612
--- /dev/null
+++ b/webkit/glue/webaccessibility.h
@@ -0,0 +1,155 @@
+// 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 WEBKIT_GLUE_WEBACCESSIBILITY_H_
+#define WEBKIT_GLUE_WEBACCESSIBILITY_H_
+
+#include "base/string16.h"
+
+namespace webkit_glue {
+
+class WebAccessibility {
+ public:
+ // This defines an enumeration of IDs that can uniquely identify a call to a
+ // specific accessibility information function. Should match the support
+ // implemented in WebKit and GlueAccessibilityObject (functions marked with
+ // return value E_NOTIMPL in WebKit are also excluded).
+ enum Function {
+ FUNCTION_NONE = 0,
+
+ // Supported accessibility information retrieval functions.
+ FUNCTION_DODEFAULTACTION,
+ FUNCTION_HITTEST,
+ FUNCTION_LOCATION,
+ FUNCTION_NAVIGATE,
+ FUNCTION_GETCHILD,
+ FUNCTION_CHILDCOUNT,
+ FUNCTION_DEFAULTACTION,
+ FUNCTION_DESCRIPTION,
+ FUNCTION_GETFOCUSEDCHILD,
+ FUNCTION_HELPTEXT,
+ FUNCTION_KEYBOARDSHORTCUT,
+ FUNCTION_NAME,
+ FUNCTION_GETPARENT,
+ FUNCTION_ROLE,
+ FUNCTION_STATE,
+ FUNCTION_VALUE
+
+ // The deprecated put_accName and put_accValue (IAccessible) are not
+ // supported here, nor is accSelect, get_accHelpTopic and get_accSelection
+ // (matching WebKit's support for IAccessible).
+ };
+
+ // This defines an enumeration of navigation directions based on (but
+ // independent of) the MSAA Navigation Constants. However, to avoid the use of
+ // COM in our Glue layer, we use this as a substitute with a one-to-one
+ // conversion between Browser side (has COM) and Glue.
+ enum Direction {
+ DIRECTION_NONE = 0,
+
+ // Valid directions.
+ DIRECTION_UP,
+ DIRECTION_DOWN,
+ DIRECTION_LEFT,
+ DIRECTION_RIGHT,
+ DIRECTION_NEXT,
+ DIRECTION_PREVIOUS,
+ DIRECTION_FIRSTCHILD,
+ DIRECTION_LASTCHILD
+ };
+
+ // This defines an enumeration of the supported accessibility roles in our
+ // Glue layer (used in GlueAccessibilityObject::Role). Any interface using
+ // roles must provide a conversion to its own roles (see e.g.
+ // BrowserAccessibility::get_accRole and BrowserAccessibility::MSAARole).
+ enum Role {
+ ROLE_PUSHBUTTON,
+ ROLE_RADIOBUTTON,
+ ROLE_CHECKBUTTON,
+ ROLE_SLIDER,
+ ROLE_PAGETABLIST,
+ ROLE_TEXT,
+ ROLE_STATICTEXT,
+ ROLE_OUTLINE,
+ ROLE_COLUMN,
+ ROLE_ROW,
+ ROLE_GROUPING,
+ ROLE_LIST,
+ ROLE_TABLE,
+ ROLE_LINK,
+ ROLE_GRAPHIC,
+ ROLE_CLIENT
+ };
+
+ // This defines an enumeration of the supported accessibility states in our
+ // Glue layer (used in GlueAccessibilityObject::State). Any interface using
+ // states must provide a conversion to its own states (see e.g.
+ // BrowserAccessibility::get_accState and BrowserAccessibility::MSAAState).
+ enum State {
+ STATE_LINKED,
+ STATE_HOTTRACKED,
+ STATE_UNAVAILABLE,
+ STATE_READONLY,
+ STATE_OFFSCREEN,
+ STATE_MULTISELECTABLE,
+ STATE_PROTECTED,
+ STATE_INDETERMINATE,
+ STATE_CHECKED,
+ STATE_PRESSED,
+ STATE_FOCUSED,
+ STATE_TRAVERSED,
+ STATE_FOCUSABLE
+ };
+
+ // Parameters structure to hold a union of the possible accessibility function
+ // INPUT variables, with the unused fields always set to default value. Used
+ // in ViewMsg_GetAccessibilityInfo, as only parameter.
+ struct InParams {
+ // Identifier to uniquely distinguish which instance of accessibility
+ // information is being called upon on the renderer side.
+ int object_id;
+
+ // Identifier to resolve which accessibility information retrieval function
+ // is being called.
+ int function_id;
+
+ // Id of accessible child, whose information is being requested.
+ int child_id;
+
+ // 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 accessibility function
+ // OUTPUT variables, with the unused fields always set to default value. Used
+ // in ViewHostMsg_GetAccessibilityInfoResponse, as only parameter.
+ struct OutParams {
+ // Identifier to uniquely distinguish which instance of accessibility
+ // information is being called upon on the renderer side.
+ int object_id;
+
+ // 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.
+ string16 output_string;
+
+ // Return code, either true (MSAA S_OK) or false (MSAA S_FALSE).
+ // Interface-specific error return codes (e.g. MSAA's E_POINTER,
+ // E_INVALIDARG, E_FAIL, E_NOTIMPL) must be handled on the browser side by
+ // input validation.
+ bool return_code;
+ };
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_GLUE_WEBACCESSIBILITY_H_
diff --git a/webkit/glue/webaccessibilitymanager.h b/webkit/glue/webaccessibilitymanager.h
new file mode 100644
index 0000000..cebe94c
--- /dev/null
+++ b/webkit/glue/webaccessibilitymanager.h
@@ -0,0 +1,54 @@
+// 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 WEBKIT_GLUE_WEBACCESSIBILITYMANAGER_H_
+#define WEBKIT_GLUE_WEBACCESSIBILITYMANAGER_H_
+
+#include "webkit/glue/webaccessibility.h"
+
+class WebView;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WebAccessibilityManager
+//
+// Responds to incoming accessibility requests from the browser side. Retrieves
+// the requested information from the active AccessibilityObject, through the
+// GlueAccessibilityObject.
+////////////////////////////////////////////////////////////////////////////////
+namespace webkit_glue {
+
+class WebAccessibilityManager {
+ public:
+ WebAccessibilityManager() {}
+ virtual ~WebAccessibilityManager() {}
+
+ static WebAccessibilityManager* Create();
+
+ // Retrieves the accessibility information as requested in in_params, by
+ // calling into WebKit's AccessibilityObject. Maintains a hashmap of the
+ // currently active (browser side ref-count non-zero) instances. Returns true
+ // if successful, false otherwise.
+ virtual bool GetAccObjInfo(WebView* view,
+ const WebAccessibility::InParams& in_params,
+ WebAccessibility::OutParams* out_params) = 0;
+
+ // Erases the entry identified by the [acc_obj_id] from the hash maps. If
+ // [clear_all] is true, all entries are erased. Returns true if successful,
+ // false otherwise.
+ virtual bool ClearAccObjMap(int acc_obj_id, bool clear_all) = 0;
+
+ // Retrieves the RenderObject associated with this WebView, and uses it to
+ // initialize the root of the GlueAccessibilityObject tree with the
+ // associated accessibility information. Returns true if successful, false
+ // otherwise.
+ virtual bool InitAccObjRoot(WebView* view) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebAccessibilityManager);
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_GLUE_WEBACCESSIBILITYMANAGER_H_
diff --git a/webkit/glue/webaccessibilitymanager_impl.cc b/webkit/glue/webaccessibilitymanager_impl.cc
new file mode 100644
index 0000000..57ac0c7
--- /dev/null
+++ b/webkit/glue/webaccessibilitymanager_impl.cc
@@ -0,0 +1,241 @@
+// 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 "config.h"
+
+#include "AXObjectCache.h"
+#include "Document.h"
+#include "Frame.h"
+#include "RefPtr.h"
+#undef LOG
+
+#include "webkit/glue/webaccessibilitymanager_impl.h"
+
+#include "webkit/glue/glue_accessibility_object.h"
+#include "webkit/glue/glue_util.h"
+#include "webkit/glue/webframe_impl.h"
+#include "webkit/glue/webview_impl.h"
+
+namespace webkit_glue {
+
+// struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot
+struct WebAccessibilityManagerImpl::GlueAccessibilityObjectRoot {
+ GlueAccessibilityObjectRoot() {}
+
+ // Root of the WebKit AccessibilityObject tree.
+ RefPtr<GlueAccessibilityObject> acc_obj_root_;
+};
+
+/*static*/
+WebAccessibilityManager* WebAccessibilityManager::Create() {
+ return new WebAccessibilityManagerImpl();
+}
+
+// class WebAccessibilityManagerImpl
+WebAccessibilityManagerImpl::WebAccessibilityManagerImpl()
+ : root_(new GlueAccessibilityObjectRoot) {
+}
+
+bool WebAccessibilityManagerImpl::GetAccObjInfo(WebView* view,
+ const WebAccessibility::InParams& in_params,
+ WebAccessibility::OutParams* out_params) {
+ if (!root_->acc_obj_root_ && !InitAccObjRoot(view)) {
+ // Failure in retrieving or initializing the root.
+ return false;
+ }
+
+ // Find GlueAccessibilityObject requested by [in_params.object_id].
+ IntToAccObjMap::iterator it =
+ int_to_acc_obj_map_.find(in_params.object_id);
+ if (it == int_to_acc_obj_map_.end() || !it->second) {
+ // Map did not contain a valid instance of the data requested.
+ return false;
+ }
+ RefPtr<GlueAccessibilityObject> active_acc_obj = it->second;
+
+ // Function input parameters.
+ int child_id = in_params.child_id;
+
+ // Temp paramters for holding output information.
+ RefPtr<GlueAccessibilityObject> out_acc_obj = NULL;
+ WebCore::String out_string;
+
+ switch (in_params.function_id) {
+ case WebAccessibility::FUNCTION_DODEFAULTACTION :
+ if (!active_acc_obj->DoDefaultAction(child_id))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_HITTEST :
+ out_acc_obj = active_acc_obj->HitTest(in_params.input_long1,
+ in_params.input_long2);
+ if (!out_acc_obj.get())
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_LOCATION :
+ if (!active_acc_obj->Location(&out_params->output_long1,
+ &out_params->output_long2,
+ &out_params->output_long3,
+ &out_params->output_long4,
+ child_id)) {
+ return false;
+ }
+ break;
+ case WebAccessibility::FUNCTION_NAVIGATE :
+ out_acc_obj = active_acc_obj->Navigate(
+ static_cast<WebAccessibility::Direction>(in_params.input_long1),
+ child_id);
+ if (!out_acc_obj.get())
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_GETCHILD :
+ if (child_id == 0) {
+ // If child requested is self, stay with the same accessibility object.
+ out_params->object_id = in_params.object_id;
+ out_acc_obj = active_acc_obj.get();
+ } else {
+ out_acc_obj = active_acc_obj->GetChild(child_id);
+ }
+
+ if (!out_acc_obj.get())
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_CHILDCOUNT :
+ if (!active_acc_obj->ChildCount(&out_params->output_long1))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_DEFAULTACTION :
+ if (!active_acc_obj->DefaultAction(child_id, &out_string))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_DESCRIPTION :
+ if (!active_acc_obj->Description(child_id, &out_string))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_GETFOCUSEDCHILD :
+ out_acc_obj = active_acc_obj->GetFocusedChild();
+ if (!out_acc_obj.get())
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_HELPTEXT :
+ if (!active_acc_obj->HelpText(child_id, &out_string))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_KEYBOARDSHORTCUT :
+ if (!active_acc_obj->KeyboardShortcut(child_id, &out_string))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_NAME :
+ if (!active_acc_obj->Name(child_id, &out_string))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_GETPARENT :
+ out_acc_obj = active_acc_obj->GetParent();
+ if (!out_acc_obj.get())
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_ROLE :
+ if (!active_acc_obj->Role(child_id, &out_params->output_long1))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_STATE :
+ if (!active_acc_obj->State(child_id, &out_params->output_long1))
+ return false;
+ break;
+ case WebAccessibility::FUNCTION_VALUE :
+ if (!active_acc_obj->Value(child_id, &out_string))
+ return false;
+ break;
+ default:
+ // Non-supported function id.
+ return false;
+ }
+
+ // Output and hashmap assignments, as appropriate.
+ if (!out_string.isEmpty())
+ out_params->output_string = StringToString16(out_string);
+
+ if (out_acc_obj) {
+ AccObjToIntMap::iterator it = acc_obj_to_int_map_.find(out_acc_obj.get());
+
+ if (it != acc_obj_to_int_map_.end()) {
+ // Data already present in map, return previously assigned id.
+ out_params->object_id = it->second;
+ out_params->output_long1 = -1;
+ } else {
+ // Insert new GlueAccessibilityObject in hashmaps.
+ int_to_acc_obj_map_[acc_obj_id_] = out_acc_obj.get();
+ acc_obj_to_int_map_[out_acc_obj.get()] = acc_obj_id_;
+ out_params->object_id = acc_obj_id_++;
+ out_params->output_long1 = -1;
+ }
+ }
+ // TODO(klink): Handle simple objects returned.
+ return true;
+}
+
+bool WebAccessibilityManagerImpl::InitAccObjRoot(WebView* view) {
+ // Root id is always 0.
+ acc_obj_id_ = 0;
+
+ // Enable accessibility and retrieve Document.
+ WebCore::AXObjectCache::enableAccessibility();
+ WebFrameImpl* main_frame_impl =
+ static_cast<WebFrameImpl*>(view->GetMainFrame());
+ if (!main_frame_impl || !main_frame_impl->frame())
+ return false;
+
+ WebCore::Document* doc = main_frame_impl->frame()->document();
+
+ if (!doc || !doc->renderer())
+ return false;
+
+ if (!root_->acc_obj_root_) {
+ // Either we've never had a wrapper for this frame's top-level Document,
+ // the Document renderer was destroyed and its wrapper was detached, or
+ // the previous Document is in the page cache, and the current document
+ // needs to be wrapped.
+ root_->acc_obj_root_ = GlueAccessibilityObject::CreateInstance(doc->
+ axObjectCache()->getOrCreate(doc->renderer()));
+ }
+ // Insert root in hashmaps.
+ int_to_acc_obj_map_[acc_obj_id_] = root_->acc_obj_root_.get();
+ acc_obj_to_int_map_[root_->acc_obj_root_.get()] = acc_obj_id_++;
+
+ return true;
+}
+
+bool WebAccessibilityManagerImpl::ClearAccObjMap(int acc_obj_id,
+ bool clear_all) {
+ if (clear_all) {
+ // Clear maps and invalidate root.
+ int_to_acc_obj_map_.clear();
+ acc_obj_to_int_map_.clear();
+ root_->acc_obj_root_ = 0;
+ return true;
+ }
+
+ IntToAccObjMap::iterator it = int_to_acc_obj_map_.find(acc_obj_id);
+
+ if (it == int_to_acc_obj_map_.end()) {
+ // Element not found.
+ return false;
+ }
+
+ if (it->second) {
+ // Erase element from reverse hashmap.
+ AccObjToIntMap::iterator it2 = acc_obj_to_int_map_.find(it->second);
+
+ if (it2 != acc_obj_to_int_map_.end())
+ acc_obj_to_int_map_.erase(it2);
+ }
+ int_to_acc_obj_map_.erase(it);
+
+ if (acc_obj_id == 0) {
+ // Invalidate root.
+ root_->acc_obj_root_ = 0;
+ }
+ return true;
+}
+
+} // namespace webkit_glue
diff --git a/webkit/glue/webaccessibilitymanager_impl.h b/webkit/glue/webaccessibilitymanager_impl.h
new file mode 100644
index 0000000..fe28e4e
--- /dev/null
+++ b/webkit/glue/webaccessibilitymanager_impl.h
@@ -0,0 +1,70 @@
+// 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 WEBKIT_GLUE_WEBACCESSIBILITYMANAGER_IMPL_H_
+#define WEBKIT_GLUE_WEBACCESSIBILITYMANAGER_IMPL_H_
+
+#include "base/hash_tables.h"
+#include "webkit/glue/webaccessibilitymanager.h"
+
+class GlueAccessibilityObject;
+
+namespace webkit_glue {
+typedef base::hash_map<int, GlueAccessibilityObject*> IntToAccObjMap;
+typedef base::hash_map<GlueAccessibilityObject*, int> AccObjToIntMap;
+
+////////////////////////////////////////////////////////////////////////////////
+//
+// WebAccessibilityManagerImpl
+//
+//
+// Implements WebAccessibilityManager.
+// Responds to incoming accessibility requests from the browser side. Retrieves
+// the requested information from the active AccessibilityObject, through the
+// GlueAccessibilityObject.
+////////////////////////////////////////////////////////////////////////////////
+class WebAccessibilityManagerImpl : public WebAccessibilityManager {
+ public:
+ // From WebAccessibilityManager.
+ bool GetAccObjInfo(WebView* view, const WebAccessibility::InParams& in_params,
+ WebAccessibility::OutParams* out_params);
+
+ // From WebAccessibilityManager.
+ bool ClearAccObjMap(int acc_obj_id, bool clear_all);
+
+ protected:
+ // Needed so WebAccessibilityManager::Create can call our constructor.
+ friend class WebAccessibilityManager;
+
+ WebAccessibilityManagerImpl();
+ ~WebAccessibilityManagerImpl() {}
+
+ private:
+ // From WebAccessibilityManager.
+ bool InitAccObjRoot(WebView* view);
+
+ // Wrapper around the pointer that holds the root of the AccessibilityObject
+ // tree, to allow the use of a scoped_refptr.
+ struct GlueAccessibilityObjectRoot;
+ GlueAccessibilityObjectRoot* root_;
+
+ // Hashmap for cashing of elements in use by the AT, mapping id (int) to a
+ // GlueAccessibilityObject pointer.
+ IntToAccObjMap int_to_acc_obj_map_;
+ // Hashmap for cashing of elements in use by the AT, mapping a
+ // GlueAccessibilityObject pointer to its id (int). Needed for reverse lookup,
+ // to ensure unnecessary duplicate entries are not created in the
+ // IntToAccObjMap (above).
+ AccObjToIntMap acc_obj_to_int_map_;
+
+ // Unique identifier for retrieving a GlueAccessibilityObject from the page's
+ // hashmaps.
+ int acc_obj_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebAccessibilityManagerImpl);
+};
+
+} // namespace webkit_glue
+
+#endif // WEBKIT_GLUE_WEBACCESSIBILITYMANAGER_IMPL_H_