Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1165)

Unified Diff: content/browser/accessibility/browser_accessibility_manager_android.cc

Issue 15741009: Native Android accessibility. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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(
David Trainor- moved to gerrit 2013/06/04 20:27:18 Could this also be static?
dmazzoni 2013/06/07 20:23:16 Done.
+ 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) {
David Trainor- moved to gerrit 2013/06/04 20:27:18 anonymous namespace instead of static?
dmazzoni 2013/06/07 20:23:16 Done.
+ if (val < min)
David Trainor- moved to gerrit 2013/06/04 20:27:18 Since you're std in most places: std::min(std::max
dmazzoni 2013/06/07 20:23:16 Done.
dmazzoni 2013/06/07 20:23:16 Done.
+ 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);
David Trainor- moved to gerrit 2013/06/04 20:27:18 You could always just track MinDistanceSquared ins
dmazzoni 2013/06/07 20:23:16 Done.
+}
+
+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

Powered by Google App Engine
This is Rietveld 408576698