| Index: webkit/glue/glue_accessibility.cc
|
| ===================================================================
|
| --- webkit/glue/glue_accessibility.cc (revision 0)
|
| +++ webkit/glue/glue_accessibility.cc (revision 0)
|
| @@ -0,0 +1,281 @@
|
| +// 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 "chrome/browser/iaccessible_function_ids.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.
|
| + COMPtr<AccessibleDocument> accessibility_root_;
|
| +};
|
| +
|
| +// class GlueAccessibility
|
| +GlueAccessibility::GlueAccessibility()
|
| + : root_(new GlueAccessibilityRoot) {
|
| +}
|
| +
|
| +GlueAccessibility::~GlueAccessibility() {
|
| + delete root_;
|
| +}
|
| +
|
| +bool GlueAccessibility::GetAccessibilityInfo(WebView* view,
|
| + const ViewMsg_Accessibility_In_Params& in_params,
|
| + ViewHostMsg_Accessibility_Out_Params* out_params) {
|
| + if (!root_->accessibility_root_ && !InitAccessibilityRoot(view)) {
|
| + // Failure in retrieving the root.
|
| + return false;
|
| + }
|
| +
|
| + // Temporary storing for the currently active IAccessible.
|
| + COMPtr<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();
|
| +
|
| + if (!main_frame)
|
| + return false;
|
| +
|
| + WebFrameImpl* main_frame_impl = static_cast<WebFrameImpl*>(main_frame);
|
| + WebCore::Frame* frame = main_frame_impl->frame();
|
| +
|
| + WebCore::Document* currentDocument = frame->document();
|
| + if (!currentDocument) {
|
| + root_->accessibility_root_ = 0;
|
| + 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);
|
| +
|
| + 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;
|
| +}
|
|
|
| Property changes on: webkit\glue\glue_accessibility.cc
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|