| Index: content/browser/accessibility/browser_accessibility_manager_android.cc
|
| diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..911eff730fd3724cb3e7b3e8a489a182431ccf20
|
| --- /dev/null
|
| +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
|
| @@ -0,0 +1,225 @@
|
| +// Copyright (c) 2013 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 "content/browser/accessibility/browser_accessibility_manager_android.h"
|
| +
|
| +#include <cmath>
|
| +
|
| +#include "base/android/jni_android.h"
|
| +#include "base/android/jni_string.h"
|
| +#include "base/strings/string_number_conversions.h"
|
| +#include "base/utf_string_conversions.h"
|
| +#include "base/values.h"
|
| +#include "content/browser/accessibility/browser_accessibility_android.h"
|
| +#include "content/common/accessibility_messages.h"
|
| +#include "jni/BrowserAccessibilityManager_jni.h"
|
| +
|
| +using base::android::AttachCurrentThread;
|
| +
|
| +namespace content {
|
| +
|
| +namespace aria_strings {
|
| + const char kAriaLivePolite[] = "polite";
|
| + const char kAriaLiveAssertive[] = "assertive";
|
| +}
|
| +
|
| +// static
|
| +BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
|
| + const AccessibilityNodeData& src,
|
| + BrowserAccessibilityDelegate* delegate,
|
| + BrowserAccessibilityFactory* factory) {
|
| + return new BrowserAccessibilityManagerAndroid(NULL, src, delegate, factory);
|
| +}
|
| +
|
| +BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
|
| + ContentViewCoreImpl* content_view_core,
|
| + const AccessibilityNodeData& src,
|
| + BrowserAccessibilityDelegate* delegate,
|
| + BrowserAccessibilityFactory* factory)
|
| + : BrowserAccessibilityManager(src, delegate, factory),
|
| + content_view_core_(content_view_core) {
|
| + if (!content_view_core)
|
| + return;
|
| + JNIEnv* env = AttachCurrentThread();
|
| + base::android::ScopedJavaLocalRef<jobject> content_view_core_java =
|
| + content_view_core->GetJavaObject();
|
| + java_ref_.Reset(Java_BrowserAccessibilityManager_create(
|
| + env, reinterpret_cast<jint>(this), content_view_core_java.obj()));
|
| +}
|
| +
|
| +BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
|
| + if (java_ref_.is_null())
|
| + return;
|
| + JNIEnv* env = AttachCurrentThread();
|
| + Java_BrowserAccessibilityManager_onNativeObjectDestroyed(
|
| + env, java_ref_.obj());
|
| +}
|
| +
|
| +// static
|
| +AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
|
| + AccessibilityNodeData empty_document;
|
| + empty_document.id = 0;
|
| + empty_document.role = AccessibilityNodeData::ROLE_ROOT_WEB_AREA;
|
| + empty_document.state = 1 << AccessibilityNodeData::STATE_READONLY;
|
| + return empty_document;
|
| +}
|
| +
|
| +void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
|
| + int type,
|
| + BrowserAccessibility* node) {
|
| + if (java_ref_.is_null())
|
| + return;
|
| +
|
| + JNIEnv* env = AttachCurrentThread();
|
| + switch (type) {
|
| + case AccessibilityNotificationLoadComplete:
|
| + Java_BrowserAccessibilityManager_handlePageLoaded(
|
| + env, java_ref_.obj(), focus_->renderer_id());
|
| + break;
|
| + case AccessibilityNotificationFocusChanged:
|
| + Java_BrowserAccessibilityManager_handleFocusChanged(
|
| + env, java_ref_.obj(), node->renderer_id());
|
| + break;
|
| + case AccessibilityNotificationCheckStateChanged:
|
| + Java_BrowserAccessibilityManager_handleCheckStateChanged(
|
| + env, java_ref_.obj(), node->renderer_id());
|
| + break;
|
| + case AccessibilityNotificationScrolledToAnchor:
|
| + Java_BrowserAccessibilityManager_handleScrolledToAnchor(
|
| + env, java_ref_.obj(), node->renderer_id());
|
| + break;
|
| + case AccessibilityNotificationAlert:
|
| + Java_BrowserAccessibilityManager_announceObjectShow(
|
| + env, java_ref_.obj(), node->renderer_id(), JNI_TRUE);
|
| + case AccessibilityNotificationObjectShow:
|
| + Java_BrowserAccessibilityManager_announceObjectShow(
|
| + env, java_ref_.obj(), node->renderer_id(), JNI_FALSE);
|
| + case AccessibilityNotificationSelectedTextChanged:
|
| + Java_BrowserAccessibilityManager_handleTextSelectionChanged(
|
| + env, java_ref_.obj(), node->renderer_id());
|
| + break;
|
| + case AccessibilityNotificationChildrenChanged:
|
| + case AccessibilityNotificationTextChanged:
|
| + case AccessibilityNotificationValueChanged:
|
| + if (node->IsEditableText()) {
|
| + Java_BrowserAccessibilityManager_handleEditableTextChanged(
|
| + env, java_ref_.obj(), node->renderer_id());
|
| + } else {
|
| + Java_BrowserAccessibilityManager_handleContentChanged(
|
| + env, java_ref_.obj(), node->renderer_id());
|
| + }
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| +}
|
| +
|
| +jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
|
| + return static_cast<jint>(root_->renderer_id());
|
| +}
|
| +
|
| +jint BrowserAccessibilityManagerAndroid::HitTest(
|
| + JNIEnv* env, jobject obj, jint x, jint y) {
|
| + BrowserAccessibilityAndroid* result =
|
| + static_cast<BrowserAccessibilityAndroid*>(
|
| + root_->BrowserAccessibilityForPoint(gfx::Point(x, y)));
|
| +
|
| + if (!result)
|
| + return root_->renderer_id();
|
| +
|
| + if (result->IsFocusable())
|
| + return result->renderer_id();
|
| +
|
| + // Examine the children of |result| to find the nearest accessibility focus
|
| + // candidate
|
| + BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result);
|
| + if (nearest_node)
|
| + return nearest_node->renderer_id();
|
| +
|
| + return root_->renderer_id();
|
| +}
|
| +
|
| +BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest(
|
| + int x, int y, BrowserAccessibility* start_node) {
|
| + BrowserAccessibility* nearest_node = NULL;
|
| + float min_distance = MAXFLOAT;
|
| + FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance);
|
| + return nearest_node;
|
| +}
|
| +
|
| +void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl(
|
| + int x, int y, BrowserAccessibility* start_node,
|
| + BrowserAccessibility** nearest_candidate, float* nearest_distance) {
|
| + BrowserAccessibilityAndroid* node =
|
| + static_cast<BrowserAccessibilityAndroid*>(start_node);
|
| + float distance = CalculateDistance(x, y, node);
|
| +
|
| + if (node->IsFocusable()) {
|
| + if (distance < *nearest_distance) {
|
| + *nearest_candidate = node;
|
| + *nearest_distance = distance;
|
| + }
|
| + // Don't examine any more children of focusable node
|
| + // TODO(aboxhall): what about focusable children?
|
| + return;
|
| + }
|
| +
|
| + if (!node->ComputeName().empty()) {
|
| + if (distance < *nearest_distance) {
|
| + *nearest_candidate = node;
|
| + *nearest_distance = distance;
|
| + }
|
| + return;
|
| + }
|
| +
|
| + if (!node->IsLeaf()) {
|
| + for (uint32 i = 0; i < node->child_count(); i++) {
|
| + BrowserAccessibility* child = node->GetChild(i);
|
| + FuzzyHitTestImpl(x, y, child, nearest_candidate, nearest_distance);
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Restricts |val| to the range [min, max].
|
| +static int clamp(int val, int min, int max) {
|
| + if (val < min)
|
| + return min;
|
| + else if (val > max)
|
| + return max;
|
| + else
|
| + return val;
|
| +}
|
| +
|
| +// static
|
| +float BrowserAccessibilityManagerAndroid::CalculateDistance(
|
| + int x, int y, BrowserAccessibility* node) {
|
| + gfx::Rect node_bounds = node->GetLocalBoundsRect();
|
| + int nearest_x = clamp(x, node_bounds.x(), node_bounds.right());
|
| + int nearest_y = clamp(y, node_bounds.y(), node_bounds.bottom());
|
| + float dx = std::abs(x - nearest_x);
|
| + float dy = std::abs(y - nearest_y);
|
| + return std::sqrt(dx * dx + dy * dy);
|
| +}
|
| +
|
| +jint BrowserAccessibilityManagerAndroid::GetNativeNodeById(
|
| + JNIEnv* env, jobject obj, jint id) {
|
| + return reinterpret_cast<jint>(GetFromRendererID(id));
|
| +}
|
| +
|
| +void BrowserAccessibilityManagerAndroid::NotifyRootChanged() {
|
| + JNIEnv* env = AttachCurrentThread();
|
| + Java_BrowserAccessibilityManager_handleNavigate(env, java_ref_.obj());
|
| +}
|
| +
|
| +bool
|
| +BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() {
|
| + // The Java layer handles the root scroll offset.
|
| + return false;
|
| +}
|
| +
|
| +bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
|
| + return RegisterNativesImpl(env);
|
| +}
|
| +
|
| +} // namespace content
|
|
|