diff options
author | klink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-20 20:12:25 +0000 |
---|---|---|
committer | klink@chromium.org <klink@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-03-20 20:12:25 +0000 |
commit | 6a983b4e4d28c1e3841f39febeb6a9dd681b53b3 (patch) | |
tree | a4b5d6a01066c026338d071076db9ff7dae210f3 /webkit | |
parent | fe5a8a4ff6f5758f8dbf7e6e9578df97fb8633db (diff) | |
download | chromium_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/SConscript | 3 | ||||
-rw-r--r-- | webkit/glue/glue.vcproj | 20 | ||||
-rw-r--r-- | webkit/glue/glue_accessibility.cc | 281 | ||||
-rw-r--r-- | webkit/glue/glue_accessibility.h | 77 | ||||
-rw-r--r-- | webkit/glue/glue_accessibility_object.cc | 445 | ||||
-rw-r--r-- | webkit/glue/glue_accessibility_object.h | 118 | ||||
-rw-r--r-- | webkit/glue/webaccessibility.h | 155 | ||||
-rw-r--r-- | webkit/glue/webaccessibilitymanager.h | 54 | ||||
-rw-r--r-- | webkit/glue/webaccessibilitymanager_impl.cc | 241 | ||||
-rw-r--r-- | webkit/glue/webaccessibilitymanager_impl.h | 70 |
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_ |