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

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: Fix AwContents for ICS Created 7 years, 6 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
index 861375cb14bfec79e98ecf05c18e7ee6c36857c3..52c9258c4459723aa41c2cb796e6d4657acaa959 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -6,6 +6,7 @@
#include <cmath>
+#include "base/android/build_info.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/strings/string_number_conversions.h"
@@ -13,12 +14,21 @@
#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;
using base::android::ScopedJavaLocalRef;
namespace {
+const int kJellyBeanSdkLevel = 16;
+
+// These are enums from android.view.accessibility.AccessibilityEvent in Java:
+enum {
+ ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_CHANGED = 16,
+ ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED = 8192
+};
+
// Restricts |val| to the range [min, max].
int Clamp(int val, int min, int max) {
return std::min(std::max(val, min), max);
@@ -51,16 +61,22 @@ BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
if (content_view_core.is_null())
return;
- // TODO(aboxhall): set up Java references
+ if (base::android::BuildInfo::GetInstance()->sdk_int() < kJellyBeanSdkLevel)
joth 2013/06/21 23:35:39 seems unfortunate to duplicate the check here as w
dmazzoni 2013/06/22 06:53:47 Actually the Java logic does take care of it...thi
+ return;
+
+ JNIEnv* env = AttachCurrentThread();
+ java_ref_ = JavaObjectWeakGlobalRef(
+ env, Java_BrowserAccessibilityManager_create(
+ env, reinterpret_cast<jint>(this), content_view_core.obj()).obj());
}
BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
- JNIEnv* env = base::android::AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
- // TODO(aboxhall): tear down Java references
+ Java_BrowserAccessibilityManager_onNativeObjectDestroyed(env, obj.obj());
}
// static
@@ -75,13 +91,62 @@ AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() {
void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
int type,
BrowserAccessibility* node) {
- JNIEnv* env = base::android::AttachCurrentThread();
+ JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
- // TODO(aboxhall): call into appropriate Java method for each type of
- // notification
+ switch (type) {
+ case AccessibilityNotificationLoadComplete:
+ Java_BrowserAccessibilityManager_handlePageLoaded(
+ env, obj.obj(), focus_->renderer_id());
+ break;
+ case AccessibilityNotificationFocusChanged:
+ Java_BrowserAccessibilityManager_handleFocusChanged(
+ env, obj.obj(), node->renderer_id());
+ break;
+ case AccessibilityNotificationCheckStateChanged:
+ Java_BrowserAccessibilityManager_handleCheckStateChanged(
+ env, obj.obj(), node->renderer_id());
+ break;
+ case AccessibilityNotificationScrolledToAnchor:
+ Java_BrowserAccessibilityManager_handleScrolledToAnchor(
+ env, obj.obj(), node->renderer_id());
+ break;
+ case AccessibilityNotificationAlert:
+ // An alert is a special case of live region. Fall through to the
+ // next case to handle it.
+ case AccessibilityNotificationObjectShow: {
+ // This event is fired when an object appears in a live region.
+ // Speak its text.
+ BrowserAccessibilityAndroid* android_node =
+ static_cast<BrowserAccessibilityAndroid*>(node);
+ Java_BrowserAccessibilityManager_announceLiveRegionText(
+ env, obj.obj(),
+ base::android::ConvertUTF16ToJavaString(
+ env, android_node->GetText()).obj());
+ break;
+ }
+ case AccessibilityNotificationSelectedTextChanged:
+ Java_BrowserAccessibilityManager_handleTextSelectionChanged(
+ env, obj.obj(), node->renderer_id());
+ break;
+ case AccessibilityNotificationChildrenChanged:
+ case AccessibilityNotificationTextChanged:
+ case AccessibilityNotificationValueChanged:
+ if (node->IsEditableText()) {
+ Java_BrowserAccessibilityManager_handleEditableTextChanged(
+ env, obj.obj(), node->renderer_id());
+ } else {
+ Java_BrowserAccessibilityManager_handleContentChanged(
+ env, obj.obj(), node->renderer_id());
+ }
+ break;
+ default:
+ // There are some notifications that aren't meaningful on Android.
+ // It's okay to skip them.
+ break;
+ }
}
jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) {
@@ -109,6 +174,129 @@ jint BrowserAccessibilityManagerAndroid::HitTest(
return root_->renderer_id();
}
+jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
+ JNIEnv* env, jobject obj, jobject info, jint id) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromRendererID(id));
+ if (!node)
+ return false;
+
+ if (node->parent()) {
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoParent(
+ env, obj, info, node->parent()->renderer_id());
+ }
+ if (!node->IsLeaf()) {
+ for (unsigned i = 0; i < node->child_count(); ++i) {
+ Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild(
+ env, obj, info, node->children()[i]->renderer_id());
+ }
+ }
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes(
+ env, obj, info,
+ id,
+ node->IsCheckable(),
+ node->IsChecked(),
+ node->IsClickable(),
+ node->IsEnabled(),
+ node->IsFocusable(),
+ node->IsFocused(),
+ node->IsPassword(),
+ node->IsScrollable(),
+ node->IsSelected(),
+ node->IsVisibleToUser());
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoStringAttributes(
+ env, obj, info,
+ base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj(),
+ base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
+
+ gfx::Rect absolute_rect = node->GetLocalBoundsRect();
+ gfx::Rect parent_relative_rect = absolute_rect;
+ if (node->parent()) {
+ gfx::Rect parent_rect = node->parent()->GetLocalBoundsRect();
+ parent_relative_rect.Offset(-parent_rect.OffsetFromOrigin());
+ }
+ bool is_root = node->parent() == NULL;
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoLocation(
+ env, obj, info,
+ absolute_rect.x(), absolute_rect.y(),
+ parent_relative_rect.x(), parent_relative_rect.y(),
+ absolute_rect.width(), absolute_rect.height(),
+ is_root);
+
+ return true;
+}
+
+jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
+ JNIEnv* env, jobject obj, jobject event, jint id, jint event_type) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromRendererID(id));
+ if (!node)
+ return false;
+
+ Java_BrowserAccessibilityManager_setAccessibilityEventBooleanAttributes(
+ env, obj, event,
+ node->IsChecked(),
+ node->IsEnabled(),
+ node->IsPassword(),
+ node->IsScrollable());
+ Java_BrowserAccessibilityManager_setAccessibilityEventClassName(
+ env, obj, event,
+ base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj());
+ Java_BrowserAccessibilityManager_setAccessibilityEventListAttributes(
+ env, obj, event,
+ node->GetItemIndex(),
+ node->GetItemCount());
+ Java_BrowserAccessibilityManager_setAccessibilityEventScrollAttributes(
+ env, obj, event,
+ node->GetScrollX(),
+ node->GetScrollY(),
+ node->GetMaxScrollX(),
+ node->GetMaxScrollY());
+
+ switch (event_type) {
+ case ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_CHANGED:
+ Java_BrowserAccessibilityManager_setAccessibilityEventTextChangedAttrs(
+ env, obj, event,
+ node->GetTextChangeFromIndex(),
+ node->GetTextChangeAddedCount(),
+ node->GetTextChangeRemovedCount(),
+ base::android::ConvertUTF16ToJavaString(
+ env, node->GetTextChangeBeforeText()).obj(),
+ base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
+ break;
+ case ANDROID_ACCESSIBILITY_EVENT_TYPE_VIEW_TEXT_SELECTION_CHANGED:
+ Java_BrowserAccessibilityManager_setAccessibilityEventSelectionAttrs(
+ env, obj, event,
+ node->GetSelectionStart(),
+ node->GetSelectionEnd(),
+ node->GetEditableTextLength(),
+ base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj());
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void BrowserAccessibilityManagerAndroid::Click(
+ JNIEnv* env, jobject obj, jint id) {
+ BrowserAccessibility* node = GetFromRendererID(id);
+ if (node)
+ DoDefaultAction(*node);
+}
+
+void BrowserAccessibilityManagerAndroid::Focus(
+ JNIEnv* env, jobject obj, jint id) {
+ BrowserAccessibility* node = GetFromRendererID(id);
+ if (node)
+ SetFocus(node, true);
+}
+
+void BrowserAccessibilityManagerAndroid::Blur(JNIEnv* env, jobject obj) {
+ SetFocus(root_, true);
+}
+
BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest(
int x, int y, BrowserAccessibility* start_node) {
BrowserAccessibility* nearest_node = NULL;
@@ -135,7 +323,7 @@ void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl(
return;
}
- if (!node->ComputeName().empty()) {
+ if (!node->GetText().empty()) {
if (distance < *nearest_distance) {
*nearest_candidate = node;
*nearest_distance = distance;
@@ -162,13 +350,13 @@ int BrowserAccessibilityManagerAndroid::CalculateDistanceSquared(
return dx * dx + dy * dy;
}
-jint BrowserAccessibilityManagerAndroid::GetNativeNodeById(
- JNIEnv* env, jobject obj, jint id) {
- return reinterpret_cast<jint>(GetFromRendererID(id));
-}
-
void BrowserAccessibilityManagerAndroid::NotifyRootChanged() {
- // TODO(aboxhall): non-stub implementation
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ if (obj.is_null())
+ return;
+
+ Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj());
}
bool
@@ -178,8 +366,7 @@ BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() {
}
bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
- // TODO(aboxhall): non-stub implementation
- return false;
+ return RegisterNativesImpl(env);
}
} // namespace content

Powered by Google App Engine
This is Rietveld 408576698