diff options
15 files changed, 398 insertions, 1029 deletions
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContents.java b/android_webview/java/src/org/chromium/android_webview/AwContents.java index c451d68..d7f3727 100644 --- a/android_webview/java/src/org/chromium/android_webview/AwContents.java +++ b/android_webview/java/src/org/chromium/android_webview/AwContents.java @@ -26,7 +26,6 @@ import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.webkit.GeolocationPermissions; @@ -1131,13 +1130,6 @@ public class AwContents { } /** - * @see android.view.View#dispatchHoverEvent() - */ - public boolean dispatchHoverEvent(MotionEvent event) { - return mContentViewCore.dispatchHoverEvent(event); - } - - /** * @see android.view.View#onConfigurationChanged() */ public void onConfigurationChanged(Configuration newConfig) { @@ -1303,13 +1295,6 @@ public class AwContents { } /** - * @see View#getAccessibilityNodeProvider() - */ - public AccessibilityNodeProvider getAccessibilityNodeProvider() { - return mContentViewCore.getAccessibilityNodeProvider(); - } - - /** * @see android.webkit.WebView#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) */ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc index 11f4be6..cc1a852 100644 --- a/content/browser/accessibility/accessibility_tree_formatter_android.cc +++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc @@ -52,36 +52,54 @@ void AccessibilityTreeFormatter::AddProperties( const BrowserAccessibility& node, DictionaryValue* dict) { const BrowserAccessibilityAndroid* android_node = static_cast<const BrowserAccessibilityAndroid*>(&node); + JNIEnv* env = base::android::AttachCurrentThread(); // Class name. - dict->SetString("class", android_node->GetClassName()); + dict->SetString("class", base::android::ConvertJavaStringToUTF8( + android_node->GetClassNameJNI(env, NULL))); // Bool attributes. - dict->SetBoolean("focusable", android_node->IsFocusable()); - dict->SetBoolean("focused", android_node->IsFocused()); - dict->SetBoolean("clickable", android_node->IsClickable()); - dict->SetBoolean("editable_text", android_node->IsEditableText()); - dict->SetBoolean("checkable", android_node->IsCheckable()); - dict->SetBoolean("checked", android_node->IsChecked()); - dict->SetBoolean("disabled", !android_node->IsEnabled()); - dict->SetBoolean("scrollable", android_node->IsScrollable()); - dict->SetBoolean("password", android_node->IsPassword()); - dict->SetBoolean("selected", android_node->IsSelected()); - dict->SetBoolean("invisible", !android_node->IsVisibleToUser()); + dict->SetBoolean("focusable", + android_node->IsFocusableJNI(env, NULL)); + dict->SetBoolean("focused", + android_node->IsFocusedJNI(env, NULL)); + dict->SetBoolean("clickable", + android_node->GetClickableJNI(env, NULL)); + dict->SetBoolean("editable_text", + android_node->IsEditableTextJNI(env, NULL)); + dict->SetBoolean("checkable", + android_node->IsCheckableJNI(env, NULL)); + dict->SetBoolean("checked", + android_node->IsCheckedJNI(env, NULL)); + dict->SetBoolean("disabled", + !android_node->IsEnabledJNI(env, NULL)); + dict->SetBoolean("scrollable", + android_node->IsScrollableJNI(env, NULL)); + dict->SetBoolean("password", + android_node->IsPasswordJNI(env, NULL)); + dict->SetBoolean("selected", + android_node->IsSelectedJNI(env, NULL)); + dict->SetBoolean("invisible", + !android_node->IsVisibleJNI(env, NULL)); // String attributes. - dict->SetString("name", android_node->GetText()); + dict->SetString("name", base::android::ConvertJavaStringToUTF8( + android_node->GetNameJNI(env, NULL))); // Int attributes. - dict->SetInteger("item_index", android_node->GetItemIndex()); - dict->SetInteger("item_count", android_node->GetItemCount()); + dict->SetInteger("item_index", + android_node->GetItemIndexJNI(env, NULL)); + dict->SetInteger("item_count", + android_node->GetItemCountJNI(env, NULL)); } bool AccessibilityTreeFormatter::IncludeChildren( const BrowserAccessibility& node) { const BrowserAccessibilityAndroid* android_node = static_cast<const BrowserAccessibilityAndroid*>(&node); - return !android_node->IsLeaf(); + JNIEnv* env = base::android::AttachCurrentThread(); + + return 0 != android_node->GetChildCountJNI(env, NULL); } string16 AccessibilityTreeFormatter::ToString(const DictionaryValue& dict, diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index 8ff37ec..2f1ab2d 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc @@ -4,11 +4,17 @@ #include "content/browser/accessibility/browser_accessibility_android.h" +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/android/jni_string.h" +#include "base/android/scoped_java_ref.h" #include "base/strings/utf_string_conversions.h" #include "content/browser/accessibility/browser_accessibility_manager_android.h" #include "content/common/accessibility_messages.h" #include "content/common/accessibility_node_data.h" +using base::android::ScopedJavaLocalRef; + namespace content { // static @@ -24,95 +30,101 @@ bool BrowserAccessibilityAndroid::IsNative() const { return true; } -bool BrowserAccessibilityAndroid::IsLeaf() const { - if (child_count() == 0) - return true; +// +// Actions, called from Java. +// - // Iframes are always allowed to contain children. - if (IsIframe() || - role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA || - role() == AccessibilityNodeData::ROLE_WEB_AREA) { - return false; - } +void BrowserAccessibilityAndroid::FocusJNI(JNIEnv* env, jobject obj) { + manager_->SetFocus(this, true); +} - // If it has a focusable child, we definitely can't leave out children. - if (HasFocusableChild()) - return false; +void BrowserAccessibilityAndroid::ClickJNI(JNIEnv* env, jobject obj) { + manager_->DoDefaultAction(*this); +} - // Headings with text can drop their children. - string16 name = GetText(); - if (role() == AccessibilityNodeData::ROLE_HEADING && !name.empty()) - return true; +// +// Const accessors, called from Java. +// - // Focusable nodes with text can drop their children. - if (HasState(AccessibilityNodeData::STATE_FOCUSABLE) && !name.empty()) - return true; +ScopedJavaLocalRef<jstring> +BrowserAccessibilityAndroid::GetNameJNI(JNIEnv* env, jobject obj) const { + return base::android::ConvertUTF16ToJavaString(env, ComputeName()); +} - // Nodes with only static text as children can drop their children. - if (HasOnlyStaticTextChildren()) - return true; +ScopedJavaLocalRef<jobject> +BrowserAccessibilityAndroid::GetAbsoluteRectJNI( + JNIEnv* env, jobject obj) const { + gfx::Rect rect = GetLocalBoundsRect(); - return false; + // TODO(aboxhall): replace with non-stub implementation + return ScopedJavaLocalRef<jobject>(env, NULL); } -bool BrowserAccessibilityAndroid::IsCheckable() const { - bool checkable = false; - bool is_aria_pressed_defined; - bool is_mixed; - GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed); - if (role() == AccessibilityNodeData::ROLE_CHECKBOX || - role() == AccessibilityNodeData::ROLE_RADIO_BUTTON || - is_aria_pressed_defined) { - checkable = true; +ScopedJavaLocalRef<jobject> +BrowserAccessibilityAndroid::GetRectInParentJNI( + JNIEnv* env, jobject obj) const { + gfx::Rect rect = GetLocalBoundsRect(); + if (parent()) { + gfx::Rect parent_rect = parent()->GetLocalBoundsRect(); + rect.Offset(-parent_rect.OffsetFromOrigin()); } - if (HasState(AccessibilityNodeData::STATE_CHECKED)) - checkable = true; - return checkable; -} -bool BrowserAccessibilityAndroid::IsChecked() const { - return HasState(AccessibilityNodeData::STATE_CHECKED); + // TODO(aboxhall): replace with non-stub implementation + return ScopedJavaLocalRef<jobject>(env, NULL); } -bool BrowserAccessibilityAndroid::IsClickable() const { - return (IsLeaf() && !GetText().empty()); +jboolean +BrowserAccessibilityAndroid::IsFocusableJNI(JNIEnv* env, jobject obj) const { + return static_cast<jboolean>(IsFocusable()); } -bool BrowserAccessibilityAndroid::IsEnabled() const { - return !HasState(AccessibilityNodeData::STATE_UNAVAILABLE); +jboolean +BrowserAccessibilityAndroid::IsEditableTextJNI(JNIEnv* env, jobject obj) const { + return IsEditableText(); } -bool BrowserAccessibilityAndroid::IsFocusable() const { - bool focusable = HasState(AccessibilityNodeData::STATE_FOCUSABLE); - if (IsIframe() || - role() == AccessibilityNodeData::ROLE_WEB_AREA) { - focusable = false; - } - return focusable; -} - -bool BrowserAccessibilityAndroid::IsFocused() const { - return manager()->GetFocus(manager()->GetRoot()) == this; +jint BrowserAccessibilityAndroid::GetParentJNI(JNIEnv* env, jobject obj) const { + return static_cast<jint>(parent()->renderer_id()); } -bool BrowserAccessibilityAndroid::IsPassword() const { - return HasState(AccessibilityNodeData::STATE_PROTECTED); +jint +BrowserAccessibilityAndroid::GetChildCountJNI(JNIEnv* env, jobject obj) const { + if (IsLeaf()) + return 0; + else + return static_cast<jint>(child_count()); } -bool BrowserAccessibilityAndroid::IsScrollable() const { - int dummy; - return GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X_MAX, &dummy); +jint BrowserAccessibilityAndroid::GetChildIdAtJNI(JNIEnv* env, + jobject obj, + jint child_index) const { + return static_cast<jint>(GetChild(child_index)->renderer_id()); } -bool BrowserAccessibilityAndroid::IsSelected() const { - return HasState(AccessibilityNodeData::STATE_SELECTED); +jboolean +BrowserAccessibilityAndroid::IsCheckableJNI(JNIEnv* env, jobject obj) const { + bool checkable = false; + bool is_aria_pressed_defined; + bool is_mixed; + GetAriaTristate("aria-pressed", &is_aria_pressed_defined, &is_mixed); + if (role() == AccessibilityNodeData::ROLE_CHECKBOX || + role() == AccessibilityNodeData::ROLE_RADIO_BUTTON || + is_aria_pressed_defined) { + checkable = true; + } + if (HasState(AccessibilityNodeData::STATE_CHECKED)) + checkable = true; + return static_cast<jboolean>(checkable); } -bool BrowserAccessibilityAndroid::IsVisibleToUser() const { - return !HasState(AccessibilityNodeData::STATE_INVISIBLE); +jboolean +BrowserAccessibilityAndroid::IsCheckedJNI(JNIEnv* env, jobject obj) const { + return static_cast<jboolean>( + HasState(AccessibilityNodeData::STATE_CHECKED)); } -const char* BrowserAccessibilityAndroid::GetClassName() const { +base::android::ScopedJavaLocalRef<jstring> +BrowserAccessibilityAndroid::GetClassNameJNI(JNIEnv* env, jobject obj) const { const char* class_name = NULL; switch(role()) { @@ -165,52 +177,53 @@ const char* BrowserAccessibilityAndroid::GetClassName() const { break; } - return class_name; + return base::android::ConvertUTF8ToJavaString(env, class_name); } -string16 BrowserAccessibilityAndroid::GetText() const { - if (IsIframe() || - role() == AccessibilityNodeData::ROLE_WEB_AREA) { - return string16(); - } +jboolean +BrowserAccessibilityAndroid::IsEnabledJNI(JNIEnv* env, jobject obj) const { + return static_cast<jboolean>( + !HasState(AccessibilityNodeData::STATE_UNAVAILABLE)); +} - string16 description; - GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, &description); +jboolean +BrowserAccessibilityAndroid::IsFocusedJNI(JNIEnv* env, jobject obj) const { + return manager()->GetFocus(manager()->GetRoot()) == this; +} - string16 text; - if (!name().empty()) - text = name(); - else if (!description.empty()) - text = description; - else if (!value().empty()) - text = value(); +jboolean +BrowserAccessibilityAndroid::IsPasswordJNI(JNIEnv* env, jobject obj) const { + return static_cast<jboolean>( + HasState(AccessibilityNodeData::STATE_PROTECTED)); +} - if (text.empty() && HasOnlyStaticTextChildren()) { - for (uint32 i = 0; i < child_count(); i++) { - BrowserAccessibility* child = GetChild(i); - text += static_cast<BrowserAccessibilityAndroid*>(child)->GetText(); - } - } +jboolean +BrowserAccessibilityAndroid::IsScrollableJNI(JNIEnv* env, jobject obj) const { + int dummy; + bool scrollable = GetIntAttribute( + AccessibilityNodeData::ATTR_SCROLL_X_MAX, &dummy); + return static_cast<jboolean>(scrollable); +} - switch(role()) { - case AccessibilityNodeData::ROLE_IMAGE_MAP_LINK: - case AccessibilityNodeData::ROLE_LINK: - case AccessibilityNodeData::ROLE_WEBCORE_LINK: - if (!text.empty()) - text += ASCIIToUTF16(" "); - text += ASCIIToUTF16("Link"); - break; - case AccessibilityNodeData::ROLE_HEADING: - // Only append "heading" if this node already has text. - if (!text.empty()) - text += ASCIIToUTF16(" Heading"); - break; - } +jboolean +BrowserAccessibilityAndroid::IsSelectedJNI(JNIEnv* env, jobject obj) const { + return static_cast<jboolean>( + HasState(AccessibilityNodeData::STATE_SELECTED)); +} - return text; +jboolean +BrowserAccessibilityAndroid::IsVisibleJNI(JNIEnv* env, jobject obj) const { + return static_cast<jboolean>( + !HasState(AccessibilityNodeData::STATE_INVISIBLE)); +} + +base::android::ScopedJavaLocalRef<jstring> +BrowserAccessibilityAndroid::GetAriaLiveJNI(JNIEnv* env, jobject obj) const { + return base::android::ConvertUTF16ToJavaString(env, GetAriaLive()); } -int BrowserAccessibilityAndroid::GetItemIndex() const { +jint BrowserAccessibilityAndroid::GetItemIndexJNI( + JNIEnv* env, jobject obj) const { int index = 0; switch(role()) { case AccessibilityNodeData::ROLE_LIST_ITEM: @@ -227,10 +240,11 @@ int BrowserAccessibilityAndroid::GetItemIndex() const { break; } } - return index; + return static_cast<jint>(index); } -int BrowserAccessibilityAndroid::GetItemCount() const { +jint +BrowserAccessibilityAndroid::GetItemCountJNI(JNIEnv* env, jobject obj) const { int count = 0; switch(role()) { case AccessibilityNodeData::ROLE_LIST: @@ -247,34 +261,63 @@ int BrowserAccessibilityAndroid::GetItemCount() const { break; } } - return count; + return static_cast<jint>(count); } -int BrowserAccessibilityAndroid::GetScrollX() const { +jint +BrowserAccessibilityAndroid::GetScrollXJNI(JNIEnv* env, jobject obj) const { int value = 0; GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X, &value); - return value; + return static_cast<jint>(value); } -int BrowserAccessibilityAndroid::GetScrollY() const { +jint +BrowserAccessibilityAndroid::GetScrollYJNI(JNIEnv* env, jobject obj) const { int value = 0; GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y, &value); - return value; + return static_cast<jint>(value); } -int BrowserAccessibilityAndroid::GetMaxScrollX() const { +jint +BrowserAccessibilityAndroid::GetMaxScrollXJNI(JNIEnv* env, jobject obj) const { int value = 0; GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_X_MAX, &value); - return value; + return static_cast<jint>(value); } -int BrowserAccessibilityAndroid::GetMaxScrollY() const { +jint +BrowserAccessibilityAndroid::GetMaxScrollYJNI(JNIEnv* env, jobject obj) const { int value = 0; GetIntAttribute(AccessibilityNodeData::ATTR_SCROLL_Y_MAX, &value); - return value; + return static_cast<jint>(value); +} + +jboolean +BrowserAccessibilityAndroid::GetClickableJNI(JNIEnv* env, jobject obj) const { + return (IsLeaf() && !ComputeName().empty()); +} + +jint BrowserAccessibilityAndroid::GetSelectionStartJNI(JNIEnv* env, jobject obj) + const { + int sel_start = 0; + GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START, &sel_start); + return sel_start; +} + +jint BrowserAccessibilityAndroid::GetSelectionEndJNI(JNIEnv* env, jobject obj) + const { + int sel_end = 0; + GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_END, &sel_end); + return sel_end; +} + +jint BrowserAccessibilityAndroid::GetEditableTextLengthJNI( + JNIEnv* env, jobject obj) const { + return value().length(); } -int BrowserAccessibilityAndroid::GetTextChangeFromIndex() const { +int BrowserAccessibilityAndroid::GetTextChangeFromIndexJNI( + JNIEnv* env, jobject obj) const { size_t index = 0; while (index < old_value_.length() && index < new_value_.length() && @@ -284,7 +327,8 @@ int BrowserAccessibilityAndroid::GetTextChangeFromIndex() const { return index; } -int BrowserAccessibilityAndroid::GetTextChangeAddedCount() const { +jint BrowserAccessibilityAndroid::GetTextChangeAddedCountJNI( + JNIEnv* env, jobject obj) const { size_t old_len = old_value_.length(); size_t new_len = new_value_.length(); size_t left = 0; @@ -302,7 +346,8 @@ int BrowserAccessibilityAndroid::GetTextChangeAddedCount() const { return (new_len - left - right); } -int BrowserAccessibilityAndroid::GetTextChangeRemovedCount() const { +jint BrowserAccessibilityAndroid::GetTextChangeRemovedCountJNI( + JNIEnv* env, jobject obj) const { size_t old_len = old_value_.length(); size_t new_len = new_value_.length(); size_t left = 0; @@ -320,24 +365,62 @@ int BrowserAccessibilityAndroid::GetTextChangeRemovedCount() const { return (old_len - left - right); } -string16 BrowserAccessibilityAndroid::GetTextChangeBeforeText() const { - return old_value_; +base::android::ScopedJavaLocalRef<jstring> +BrowserAccessibilityAndroid::GetTextChangeBeforeTextJNI( + JNIEnv* env, jobject obj) const { + return base::android::ConvertUTF16ToJavaString(env, old_value_); } -int BrowserAccessibilityAndroid::GetSelectionStart() const { - int sel_start = 0; - GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_START, &sel_start); - return sel_start; -} +string16 BrowserAccessibilityAndroid::ComputeName() const { + if (IsIframe() || + role() == AccessibilityNodeData::ROLE_WEB_AREA) { + return string16(); + } -int BrowserAccessibilityAndroid::GetSelectionEnd() const { - int sel_end = 0; - GetIntAttribute(AccessibilityNodeData::ATTR_TEXT_SEL_END, &sel_end); - return sel_end; + string16 description; + GetStringAttribute(AccessibilityNodeData::ATTR_DESCRIPTION, + &description); + + string16 text; + if (!name().empty()) + text = name(); + else if (!description.empty()) + text = description; + else if (!value().empty()) + text = value(); + + if (text.empty() && HasOnlyStaticTextChildren()) { + for (uint32 i = 0; i < child_count(); i++) { + BrowserAccessibility* child = GetChild(i); + text += static_cast<BrowserAccessibilityAndroid*>(child)->ComputeName(); + } + } + + switch(role()) { + case AccessibilityNodeData::ROLE_IMAGE_MAP_LINK: + case AccessibilityNodeData::ROLE_LINK: + case AccessibilityNodeData::ROLE_WEBCORE_LINK: + if (!text.empty()) + text += ASCIIToUTF16(" "); + text += ASCIIToUTF16("Link"); + break; + case AccessibilityNodeData::ROLE_HEADING: + // Only append "heading" if this node already has text. + if (!text.empty()) + text += ASCIIToUTF16(" Heading"); + break; + } + + return text; } -int BrowserAccessibilityAndroid::GetEditableTextLength() const { - return value().length(); +string16 BrowserAccessibilityAndroid::GetAriaLive() const { + string16 aria_live; + if (GetStringAttribute(AccessibilityNodeData::ATTR_CONTAINER_LIVE_STATUS, + &aria_live)) { + return aria_live; + } + return string16(); } bool BrowserAccessibilityAndroid::HasFocusableChild() const { @@ -366,6 +449,46 @@ bool BrowserAccessibilityAndroid::IsIframe() const { return html_tag == ASCIIToUTF16("iframe"); } +bool BrowserAccessibilityAndroid::IsFocusable() const { + bool focusable = HasState(AccessibilityNodeData::STATE_FOCUSABLE); + if (IsIframe() || + role() == AccessibilityNodeData::ROLE_WEB_AREA) { + focusable = false; + } + return focusable; +} + +bool BrowserAccessibilityAndroid::IsLeaf() const { + if (child_count() == 0) + return true; + + // Iframes are always allowed to contain children. + if (IsIframe() || + role() == AccessibilityNodeData::ROLE_ROOT_WEB_AREA || + role() == AccessibilityNodeData::ROLE_WEB_AREA) { + return false; + } + + // If it has a focusable child, we definitely can't leave out children. + if (HasFocusableChild()) + return false; + + // Headings with text can drop their children. + string16 name = ComputeName(); + if (role() == AccessibilityNodeData::ROLE_HEADING && !name.empty()) + return true; + + // Focusable nodes with text can drop their children. + if (HasState(AccessibilityNodeData::STATE_FOCUSABLE) && !name.empty()) + return true; + + // Nodes with only static text as children can drop their children. + if (HasOnlyStaticTextChildren()) + return true; + + return false; +} + void BrowserAccessibilityAndroid::PostInitialize() { BrowserAccessibility::PostInitialize(); @@ -393,7 +516,7 @@ void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) { !EqualsASCII(aria_live, aria_strings::kAriaLiveAssertive)) return; - string16 text = GetText(); + string16 text = ComputeName(); if (cached_text_ != text) { if (!text.empty()) { manager_->NotifyAccessibilityEvent(AccessibilityNotificationObjectShow, @@ -403,4 +526,9 @@ void BrowserAccessibilityAndroid::NotifyLiveRegionUpdate(string16& aria_live) { } } +bool RegisterBrowserAccessibility(JNIEnv* env) { + // TODO(aboxhall): replace with non-stub implementation + return false; +} + } // namespace content diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h index 8b4ed84..2de8c75 100644 --- a/content/browser/accessibility/browser_accessibility_android.h +++ b/content/browser/accessibility/browser_accessibility_android.h @@ -16,48 +16,71 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility { virtual void PostInitialize() OVERRIDE; virtual bool IsNative() const OVERRIDE; - bool IsLeaf() const; - - bool IsCheckable() const; - bool IsChecked() const; - bool IsClickable() const; - bool IsEnabled() const; - bool IsFocusable() const; - bool IsFocused() const; - bool IsPassword() const; - bool IsScrollable() const; - bool IsSelected() const; - bool IsVisibleToUser() const; - - const char* GetClassName() const; - string16 GetText() const; - - int GetItemIndex() const; - int GetItemCount() const; - - int GetScrollX() const; - int GetScrollY() const; - int GetMaxScrollX() const; - int GetMaxScrollY() const; - - int GetTextChangeFromIndex() const; - int GetTextChangeAddedCount() const; - int GetTextChangeRemovedCount() const; - string16 GetTextChangeBeforeText() const; - - int GetSelectionStart() const; - int GetSelectionEnd() const; - int GetEditableTextLength() const; + // -------------------------------------------------------------------------- + // Methods called from Java via JNI + // -------------------------------------------------------------------------- + + // Actions + void FocusJNI(JNIEnv* env, jobject obj); + void ClickJNI(JNIEnv* env, jobject obj); + + // Const accessors + jboolean GetClickableJNI(JNIEnv* env, jobject obj) const; + jboolean IsFocusedJNI(JNIEnv* env, jobject obj) const; + jboolean IsEditableTextJNI(JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef<jstring> GetNameJNI( + JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef<jobject> GetAbsoluteRectJNI( + JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef<jobject> GetRectInParentJNI( + JNIEnv* env, jobject obj) const; + jboolean IsFocusableJNI(JNIEnv* env, jobject obj) const; + jint GetParentJNI(JNIEnv* env, jobject obj) const; + jint GetChildCountJNI(JNIEnv* env, jobject obj) const; + jint GetChildIdAtJNI( + JNIEnv* env, jobject obj, jint child_index) const; + jboolean IsCheckableJNI(JNIEnv* env, jobject obj) const; + jboolean IsCheckedJNI(JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef<jstring> GetClassNameJNI( + JNIEnv* env, jobject obj) const; + jboolean IsEnabledJNI(JNIEnv* env, jobject obj) const; + jboolean IsPasswordJNI(JNIEnv* env, jobject obj) const; + jboolean IsScrollableJNI(JNIEnv* env, jobject obj) const; + jboolean IsSelectedJNI(JNIEnv* env, jobject obj) const; + jboolean IsVisibleJNI(JNIEnv* env, jobject obj) const; + jint GetItemIndexJNI(JNIEnv* env, jobject obj) const; + jint GetItemCountJNI(JNIEnv* env, jobject obj) const; + jint GetScrollXJNI(JNIEnv* env, jobject obj) const; + jint GetScrollYJNI(JNIEnv* env, jobject obj) const; + jint GetMaxScrollXJNI(JNIEnv* env, jobject obj) const; + jint GetMaxScrollYJNI(JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef<jstring> GetAriaLiveJNI( + JNIEnv* env, jobject obj) const; + jint GetSelectionStartJNI(JNIEnv* env, jobject obj) const; + jint GetSelectionEndJNI(JNIEnv* env, jobject obj) const; + jint GetEditableTextLengthJNI(JNIEnv* env, jobject obj) const; + jint GetTextChangeFromIndexJNI(JNIEnv* env, jobject obj) const; + jint GetTextChangeAddedCountJNI(JNIEnv* env, jobject obj) const; + jint GetTextChangeRemovedCountJNI(JNIEnv* env, jobject obj) const; + base::android::ScopedJavaLocalRef<jstring> GetTextChangeBeforeTextJNI( + JNIEnv* env, jobject obj) const; private: // This gives BrowserAccessibility::Create access to the class constructor. friend class BrowserAccessibility; + // Allow BrowserAccessibilityManagerAndroid to call these private methods. + friend class BrowserAccessibilityManagerAndroid; + BrowserAccessibilityAndroid(); + string16 ComputeName() const; + string16 GetAriaLive() const; + bool IsFocusable() const; bool HasFocusableChild() const; bool HasOnlyStaticTextChildren() const; bool IsIframe() const; + bool IsLeaf() const; void NotifyLiveRegionUpdate(string16& aria_live); @@ -69,6 +92,8 @@ class BrowserAccessibilityAndroid : public BrowserAccessibility { DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAndroid); }; +bool RegisterBrowserAccessibility(JNIEnv* env); + } // namespace content #endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_ANDROID_H_ diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 112ffdb..861375c 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc @@ -13,19 +13,12 @@ #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 { -// 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); @@ -58,19 +51,16 @@ BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid( if (content_view_core.is_null()) return; - JNIEnv* env = AttachCurrentThread(); - java_ref_ = JavaObjectWeakGlobalRef( - env, Java_BrowserAccessibilityManager_create( - env, reinterpret_cast<jint>(this), content_view_core.obj()).obj()); + // TODO(aboxhall): set up Java references } BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); if (obj.is_null()) return; - Java_BrowserAccessibilityManager_onNativeObjectDestroyed(env, obj.obj()); + // TODO(aboxhall): tear down Java references } // static @@ -85,62 +75,13 @@ AccessibilityNodeData BrowserAccessibilityManagerAndroid::GetEmptyDocument() { void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent( int type, BrowserAccessibility* node) { - JNIEnv* env = AttachCurrentThread(); + JNIEnv* env = base::android::AttachCurrentThread(); ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); if (obj.is_null()) return; - 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; - } + // TODO(aboxhall): call into appropriate Java method for each type of + // notification } jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) { @@ -168,128 +109,6 @@ 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, - 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; @@ -316,7 +135,7 @@ void BrowserAccessibilityManagerAndroid::FuzzyHitTestImpl( return; } - if (!node->GetText().empty()) { + if (!node->ComputeName().empty()) { if (distance < *nearest_distance) { *nearest_candidate = node; *nearest_distance = distance; @@ -343,13 +162,13 @@ int BrowserAccessibilityManagerAndroid::CalculateDistanceSquared( return dx * dx + dy * dy; } -void BrowserAccessibilityManagerAndroid::NotifyRootChanged() { - JNIEnv* env = AttachCurrentThread(); - ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); - if (obj.is_null()) - return; +jint BrowserAccessibilityManagerAndroid::GetNativeNodeById( + JNIEnv* env, jobject obj, jint id) { + return reinterpret_cast<jint>(GetFromRendererID(id)); +} - Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj()); +void BrowserAccessibilityManagerAndroid::NotifyRootChanged() { + // TODO(aboxhall): non-stub implementation } bool @@ -359,7 +178,8 @@ BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() { } bool RegisterBrowserAccessibilityManager(JNIEnv* env) { - return RegisterNativesImpl(env); + // TODO(aboxhall): non-stub implementation + return false; } } // namespace content diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h index 2a6c291..0ca04e5 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.h +++ b/content/browser/accessibility/browser_accessibility_manager_android.h @@ -41,16 +41,9 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid jint GetRootId(JNIEnv* env, jobject obj); jint HitTest(JNIEnv* env, jobject obj, jint x, jint y); - // Populate Java accessibility data structures with info about a node. - jboolean PopulateAccessibilityNodeInfo( - JNIEnv* env, jobject obj, jobject info, jint id); - jboolean PopulateAccessibilityEvent( - JNIEnv* env, jobject obj, jobject event, jint id, jint event_type); - - // Perform actions. - void Click(JNIEnv* env, jobject obj, jint id); - void Focus(JNIEnv* env, jobject obj, jint id); - void Blur(JNIEnv* env, jobject obj); + // Gets a temporary pointer to a specific node, only valid in this scope. + // May return 0 if that node id is no longer valid. + jint GetNativeNodeById(JNIEnv* env, jobject obj, jint id); protected: virtual void NotifyRootChanged() OVERRIDE; diff --git a/content/browser/android/browser_jni_registrar.cc b/content/browser/android/browser_jni_registrar.cc index b914a9a..1cd4061 100644 --- a/content/browser/android/browser_jni_registrar.cc +++ b/content/browser/android/browser_jni_registrar.cc @@ -6,8 +6,6 @@ #include "base/android/jni_android.h" #include "base/android/jni_registrar.h" -#include "content/browser/accessibility/browser_accessibility_android.h" -#include "content/browser/accessibility/browser_accessibility_manager_android.h" #include "content/browser/android/android_browser_process.h" #include "content/browser/android/child_process_launcher_android.h" #include "content/browser/android/content_settings.h" @@ -36,8 +34,6 @@ base::android::RegistrationMethod kContentRegisteredMethods[] = { { "AndroidLocationApiAdapter", content::AndroidLocationApiAdapter::RegisterGeolocationService }, { "AndroidBrowserProcess", content::RegisterAndroidBrowserProcess }, - { "BrowserAccessibilityManager", - content::RegisterBrowserAccessibilityManager }, { "ChildProcessLauncher", content::RegisterChildProcessLauncher }, { "ContentSettings", content::ContentSettings::RegisterContentSettings }, { "ContentViewRenderView", diff --git a/content/browser/android/content_view_core_impl.cc b/content/browser/android/content_view_core_impl.cc index 6ad7c47..790cc75 100644 --- a/content/browser/android/content_view_core_impl.cc +++ b/content/browser/android/content_view_core_impl.cc @@ -32,7 +32,6 @@ #include "content/browser/web_contents/web_contents_view_android.h" #include "content/common/input_messages.h" #include "content/common/view_messages.h" -#include "content/public/browser/browser_accessibility_state.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/notification_details.h" @@ -1573,19 +1572,6 @@ void ContentViewCoreImpl::SetUseDesktopUserAgent( } } -void ContentViewCoreImpl::SetAccessibilityEnabled(JNIEnv* env, jobject obj, - bool enabled) { - RenderWidgetHostImpl* host_impl = RenderWidgetHostImpl::From( - GetRenderWidgetHostViewAndroid()->GetRenderWidgetHost()); - if (enabled) { - BrowserAccessibilityState::GetInstance()->EnableAccessibility(); - host_impl->SetAccessibilityMode(AccessibilityModeComplete); - } else { - BrowserAccessibilityState::GetInstance()->DisableAccessibility(); - host_impl->SetAccessibilityMode(AccessibilityModeOff); - } -} - // This is called for each ContentView. jint Init(JNIEnv* env, jobject obj, jboolean hardware_accelerated, diff --git a/content/browser/android/content_view_core_impl.h b/content/browser/android/content_view_core_impl.h index b4d796f..94bff0a 100644 --- a/content/browser/android/content_view_core_impl.h +++ b/content/browser/android/content_view_core_impl.h @@ -221,7 +221,6 @@ class ContentViewCoreImpl : public ContentViewCore, jint player_id, jobject jsurface); void DetachExternalVideoSurface(JNIEnv* env, jobject obj, jint player_id); - void SetAccessibilityEnabled(JNIEnv* env, jobject obj, bool enabled); // -------------------------------------------------------------------------- // Public methods that call to Java via JNI diff --git a/content/content_jni.gypi b/content/content_jni.gypi index c9b63cb..8520269 100644 --- a/content/content_jni.gypi +++ b/content/content_jni.gypi @@ -11,7 +11,6 @@ 'public/android/java/src/org/chromium/content/app/ChildProcessService.java', 'public/android/java/src/org/chromium/content/app/ContentMain.java', 'public/android/java/src/org/chromium/content/app/LibraryLoader.java', - 'public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java', 'public/android/java/src/org/chromium/content/browser/AndroidBrowserProcess.java', 'public/android/java/src/org/chromium/content/browser/ChildProcessLauncher.java', 'public/android/java/src/org/chromium/content/browser/ContentSettings.java', diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentView.java b/content/public/android/java/src/org/chromium/content/browser/ContentView.java index 9db7c3c..22f8fe8 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentView.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentView.java @@ -17,7 +17,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.widget.FrameLayout; @@ -489,14 +488,6 @@ public class ContentView extends FrameLayout return mContentViewCore.onGenericMotionEvent(event); } - @Override - public boolean dispatchHoverEvent(MotionEvent event) { - if (mContentViewCore.dispatchHoverEvent(event)) { - return true; - } - return super.dispatchHoverEvent(event); - } - /** * Sets the current amount to offset incoming touch events by. This is used to handle content * moving and not lining up properly with the android input system. @@ -588,16 +579,6 @@ public class ContentView extends FrameLayout } @Override - public AccessibilityNodeProvider getAccessibilityNodeProvider() { - AccessibilityNodeProvider provider = mContentViewCore.getAccessibilityNodeProvider(); - if (provider != null) { - return provider; - } else { - return super.getAccessibilityNodeProvider(); - } - } - - @Override public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { super.onInitializeAccessibilityNodeInfo(info); mContentViewCore.onInitializeAccessibilityNodeInfo(info); diff --git a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java index 896645a..eeebf03 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java +++ b/content/public/android/java/src/org/chromium/content/browser/ContentViewCore.java @@ -9,18 +9,14 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; -import android.database.ContentObserver; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Rect; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.ResultReceiver; -import android.provider.Settings; -import android.provider.Settings.Secure; import android.text.Editable; import android.util.Log; import android.util.Pair; @@ -34,10 +30,7 @@ import android.view.ViewGroup; import android.view.Window; import android.view.WindowManager; import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener; import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; import android.view.inputmethod.InputMethodManager; @@ -51,7 +44,6 @@ import org.chromium.base.WeakContext; import org.chromium.content.R; import org.chromium.content.browser.ContentViewGestureHandler.MotionEventDelegate; import org.chromium.content.browser.accessibility.AccessibilityInjector; -import org.chromium.content.browser.accessibility.BrowserAccessibilityManager; import org.chromium.content.browser.input.AdapterInputConnection; import org.chromium.content.browser.input.HandleView; import org.chromium.content.browser.input.ImeAdapter; @@ -66,8 +58,6 @@ import org.chromium.ui.WindowAndroid; import org.chromium.ui.gfx.DeviceDisplayInfo; import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -78,9 +68,7 @@ import java.util.Map; * being tied to the view system. */ @JNINamespace("content") - public class ContentViewCore implements MotionEventDelegate, - NavigationClient, - AccessibilityStateChangeListener { +public class ContentViewCore implements MotionEventDelegate, NavigationClient { /** * Indicates that input events are batched together and delivered just before vsync. */ @@ -360,12 +348,6 @@ import java.util.Map; // The AccessibilityInjector that handles loading Accessibility scripts into the web page. private AccessibilityInjector mAccessibilityInjector; - // Handles native accessibility, i.e. without any script injection. - private BrowserAccessibilityManager mBrowserAccessibilityManager; - - // System accessibility service. - private final AccessibilityManager mAccessibilityManager; - // Temporary notification to tell onSizeChanged to focus a form element, // because the OSK was just brought up. private boolean mUnfocusOnNextSizeChanged = false; @@ -387,7 +369,6 @@ import java.util.Map; private ViewAndroid mViewAndroid; - /** * Constructs a new ContentViewCore. Embedders must call initialize() after constructing * a ContentViewCore and before using it. @@ -407,8 +388,6 @@ import java.util.Map; mStartHandlePoint = mRenderCoordinates.createNormalizedPoint(); mEndHandlePoint = mRenderCoordinates.createNormalizedPoint(); mInsertionHandlePoint = mRenderCoordinates.createNormalizedPoint(); - mAccessibilityManager = (AccessibilityManager) - getContext().getSystemService(Context.ACCESSIBILITY_SERVICE); } /** @@ -654,24 +633,8 @@ import java.util.Map; mContentSettings = new ContentSettings(this, mNativeContentViewCore); initializeContainerView(internalDispatcher, inputEventDeliveryMode); - try { - Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION"); - field.setAccessible(true); - String accessibilityScriptInjection = (String) field.get(null); - getContext().getContentResolver().registerContentObserver( - Settings.Secure.getUriFor(accessibilityScriptInjection), - false, - new ContentObserver(new Handler()) { - public void onChange(boolean selfChange, Uri uri) { - setAccessibilityState(mAccessibilityManager.isEnabled()); - } - }); - } catch (Exception e) { - Log.e("chromium", "Could not add listener for script injection preference. " + - "Defaulting to native accessibility.\n" + e.toString()); - } - mAccessibilityInjector = AccessibilityInjector.newInstance(this); + mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary(); String contentDescription = "Web View"; if (R.string.accessibility_content_view == 0) { @@ -1325,6 +1288,7 @@ import java.util.Map; TraceEvent.begin(); hidePopupDialog(); nativeOnHide(mNativeContentViewCore); + setAccessibilityState(false); TraceEvent.end(); } @@ -1333,7 +1297,7 @@ import java.util.Map; */ public void onActivityResume() { nativeOnShow(mNativeContentViewCore); - setAccessibilityState(mAccessibilityManager.isEnabled()); + setAccessibilityState(true); } /** @@ -1341,7 +1305,7 @@ import java.util.Map; */ public void onShow() { nativeOnShow(mNativeContentViewCore); - setAccessibilityState(mAccessibilityManager.isEnabled()); + setAccessibilityState(true); } /** @@ -1349,7 +1313,7 @@ import java.util.Map; */ public void onHide() { hidePopupDialog(); - setInjectedAccessibility(false); + setAccessibilityState(false); nativeOnHide(mNativeContentViewCore); } @@ -1402,7 +1366,7 @@ import java.util.Map; ChildProcessLauncher.bindAsHighPriority(pid); } } - setAccessibilityState(mAccessibilityManager.isEnabled()); + setAccessibilityState(true); } /** @@ -1417,7 +1381,7 @@ import java.util.Map; ChildProcessLauncher.unbindAsHighPriority(pid); } } - setInjectedAccessibility(false); + setAccessibilityState(false); hidePopupDialog(); mZoomControlsDelegate.dismissZoomPicker(); } @@ -1682,23 +1646,6 @@ import java.util.Map; } /** - * Any View that uses ContentViewCore should call override dispatchHoverEvent - * and call this method first so that all hover events can be intercepted and - * used for touch exploration if accessibility is on, and then only call the - * inherited method if this returns false. - * - * @see View#dispatchHoverEvent(MotionEvent) - */ - public boolean dispatchHoverEvent(MotionEvent event) { - if (mBrowserAccessibilityManager != null) { - return mBrowserAccessibilityManager.dispatchHoverEvent(event); - } else { - // The client view should call super.dispatchHoverEvent. - return false; - } - } - - /** * @see View#scrollBy(int, int) * Currently the ContentView scrolling happens in the native side. In * the Java view system, it is always pinned at (0, 0). scrollBy() and scrollTo() @@ -2224,9 +2171,6 @@ import java.util.Map; controlsOffsetPix, contentOffsetYPix, overdrawBottomHeightPix); mPendingRendererFrame = true; - if (mBrowserAccessibilityManager != null) { - mBrowserAccessibilityManager.notifyFrameInfoInitialized(); - } } @SuppressWarnings("unused") @@ -2609,11 +2553,6 @@ import java.util.Map; getContentViewClient().onStartContentIntent(getContext(), contentUrl); } - @Override - public void onAccessibilityStateChanged(boolean enabled) { - setAccessibilityState(enabled); - } - /** * Determines whether or not this ContentViewCore can handle this accessibility action. * @param action The action to perform. @@ -2642,39 +2581,9 @@ import java.util.Map; } /** - * Set the BrowserAccessibilityManager, used for native accessibility - * (not script injection). This is only set when system accessibility - * has been enabled. - * @param manager The new BrowserAccessibilityManager. - */ - public void setBrowserAccessibilityManager(BrowserAccessibilityManager manager) { - mBrowserAccessibilityManager = manager; - } - - /** - * Get the BrowserAccessibilityManager, used for native accessibility - * (not script injection). This will return null when system accessibility - * is not enabled. - * @return This view's BrowserAccessibilityManager. - */ - public BrowserAccessibilityManager getBrowserAccessibilityManager() { - return mBrowserAccessibilityManager; - } - - /** - * @see View#getAccessibilityNodeProvider(View host) - */ - public AccessibilityNodeProvider getAccessibilityNodeProvider() { - // Note: this is only used for native accessibility, i.e. without - // script injection. - return mBrowserAccessibilityManager; - } - - /** * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo) */ public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { - // Note: this is only used by the script-injecting accessibility code. mAccessibilityInjector.onInitializeAccessibilityNodeInfo(info); } @@ -2682,7 +2591,6 @@ import java.util.Map; * @see View#onInitializeAccessibilityEvent(AccessibilityEvent) */ public void onInitializeAccessibilityEvent(AccessibilityEvent event) { - // Note: this is only used by the script-injecting accessibility code. event.setClassName(this.getClass().getName()); // Identify where the top-left of the screen currently points to. @@ -2704,35 +2612,6 @@ import java.util.Map; } /** - * Returns whether accessibility script injection is enabled on the device - */ - public boolean isDeviceAccessibilityScriptInjectionEnabled() { - try { - if (!mContentSettings.getJavaScriptEnabled()) { - return false; - } - - int result = getContext().checkCallingOrSelfPermission( - android.Manifest.permission.INTERNET); - if (result != PackageManager.PERMISSION_GRANTED) { - return false; - } - - Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION"); - field.setAccessible(true); - String accessibilityScriptInjection = (String) field.get(null); - - boolean onDeviceScriptInjectionEnabled = - Settings.Secure.getInt(getContext().getContentResolver(), - accessibilityScriptInjection, 0) == 1; - return onDeviceScriptInjectionEnabled; - } catch (NoSuchFieldException e) { - } catch (IllegalAccessException e) { - } - return false; - } - - /** * Returns whether or not accessibility injection is being used. */ public boolean isInjectingAccessibilityScript() { @@ -2740,38 +2619,10 @@ import java.util.Map; } /** - * Turns browser accessibility on or off. - * If |state| is |false|, this turns off both native and injected accessibility. - * Otherwise, if accessibility script injection is enabled, this will enable the injected - * accessibility scripts, and if it is disabled this will enable the native accessibility. + * Enable or disable accessibility features. */ public void setAccessibilityState(boolean state) { - boolean injectedAccessibility = false; - boolean nativeAccessibility = false; - if (state) { - if (isDeviceAccessibilityScriptInjectionEnabled()) { - injectedAccessibility = true; - } else { - nativeAccessibility = true; - } - } - setInjectedAccessibility(injectedAccessibility); - setNativeAccessibilityState(nativeAccessibility); - } - - /** - * Enable or disable native accessibility features. - */ - public void setNativeAccessibilityState(boolean enabled) { - nativeSetAccessibilityEnabled(mNativeContentViewCore, enabled); - } - - /** - * Enable or disable injected accessibility features - */ - public void setInjectedAccessibility(boolean enabled) { - mAccessibilityInjector.addOrRemoveAccessibilityApisIfNecessary(); - mAccessibilityInjector.setScriptEnabled(enabled); + mAccessibilityInjector.setScriptEnabled(state); } /** @@ -3104,7 +2955,4 @@ import java.util.Map; private native void nativeDetachExternalVideoSurface( int nativeContentViewCoreImpl, int playerId); - - private native void nativeSetAccessibilityEnabled( - int nativeContentViewCoreImpl, boolean enabled); } diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java index 2a85b4f..c0dcf03a 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityInjector.java @@ -130,17 +130,27 @@ public class AccessibilityInjector extends WebContentsObserverAndroid { if (!accessibilityIsAvailable()) return; int axsParameterValue = getAxsUrlParameterValue(); - if (axsParameterValue != ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED) { - return; - } - - String js = getScreenReaderInjectingJs(); - if (mContentViewCore.isDeviceAccessibilityScriptInjectionEnabled() && - js != null && mContentViewCore.isAlive()) { - addOrRemoveAccessibilityApisIfNecessary(); - mContentViewCore.evaluateJavaScript(js, null); - mInjectedScriptEnabled = true; - mScriptInjected = true; + if (axsParameterValue == ACCESSIBILITY_SCRIPT_INJECTION_UNDEFINED) { + try { + Field field = Settings.Secure.class.getField("ACCESSIBILITY_SCRIPT_INJECTION"); + field.setAccessible(true); + String ACCESSIBILITY_SCRIPT_INJECTION = (String) field.get(null); + + boolean onDeviceScriptInjectionEnabled = (Settings.Secure.getInt( + mContentViewCore.getContext().getContentResolver(), + ACCESSIBILITY_SCRIPT_INJECTION, 0) == 1); + String js = getScreenReaderInjectingJs(); + + if (onDeviceScriptInjectionEnabled && js != null && mContentViewCore.isAlive()) { + addOrRemoveAccessibilityApisIfNecessary(); + mContentViewCore.evaluateJavaScript(js, null); + mInjectedScriptEnabled = true; + mScriptInjected = true; + } + } catch (NoSuchFieldException ex) { + } catch (IllegalArgumentException ex) { + } catch (IllegalAccessException ex) { + } } } @@ -188,11 +198,10 @@ public class AccessibilityInjector extends WebContentsObserverAndroid { /** * Sets whether or not the script is enabled. If the script is disabled, we also stop any - * we output that is occurring. If the script has not yet been injected, injects it. + * we output that is occurring. * @param enabled Whether or not to enable the script. */ public void setScriptEnabled(boolean enabled) { - if (enabled && !mScriptInjected) injectAccessibilityScriptIntoPage(); if (!accessibilityIsAvailable() || mInjectedScriptEnabled == enabled) return; mInjectedScriptEnabled = enabled; diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java deleted file mode 100644 index f25ae0b..0000000 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java +++ /dev/null @@ -1,419 +0,0 @@ -// 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. - -package org.chromium.content.browser.accessibility; - -import android.content.Context; -import android.graphics.Rect; -import android.os.Bundle; -import android.view.MotionEvent; -import android.view.View; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; -import android.view.accessibility.AccessibilityNodeInfo; -import android.view.accessibility.AccessibilityNodeProvider; -import android.view.inputmethod.InputMethodManager; - -import org.chromium.base.CalledByNative; -import org.chromium.base.JNINamespace; -import org.chromium.content.browser.ContentViewCore; -import org.chromium.content.browser.RenderCoordinates; - -import java.util.ArrayList; -import java.util.List; - -/** - * Native accessibility for a {@link ContentViewCore}. - */ -@JNINamespace("content") -public class BrowserAccessibilityManager extends AccessibilityNodeProvider { - private static final String TAG = BrowserAccessibilityManager.class.getSimpleName(); - - private ContentViewCore mContentViewCore; - private AccessibilityManager mAccessibilityManager; - private RenderCoordinates mRenderCoordinates; - private int mNativeObj; - private int mAccessibilityFocusId; - private final int[] mTempLocation = new int[2]; - private View mView; - private boolean mUserHasTouchExplored; - private boolean mFrameInfoInitialized; - - // If this is true, enables an experimental feature that focuses the web page after it - // finishes loading. Disabled for now because it can be confusing if the user was - // trying to do something when this happens. - private boolean mFocusPageOnLoad; - - /** - * Create a BrowserAccessibilityManager object, which is owned by the C++ - * BrowserAccessibilityManagerAndroid instance, and connects to the content view. - * @param nativeBrowserAccessibilityManagerAndroid A pointer to the counterpart native - * C++ object that owns this object. - * @param contentViewCore The content view that this object provides accessibility for. - */ - @CalledByNative - private static BrowserAccessibilityManager create(int nativeBrowserAccessibilityManagerAndroid, - ContentViewCore contentViewCore) { - return new BrowserAccessibilityManager( - nativeBrowserAccessibilityManagerAndroid, contentViewCore); - } - - private BrowserAccessibilityManager(int nativeBrowserAccessibilityManagerAndroid, - ContentViewCore contentViewCore) { - mNativeObj = nativeBrowserAccessibilityManagerAndroid; - mContentViewCore = contentViewCore; - mContentViewCore.setBrowserAccessibilityManager(this); - mAccessibilityFocusId = View.NO_ID; - mView = mContentViewCore.getContainerView(); - mRenderCoordinates = mContentViewCore.getRenderCoordinates(); - mAccessibilityManager = - (AccessibilityManager) mContentViewCore.getContext() - .getSystemService(Context.ACCESSIBILITY_SERVICE); - } - - @CalledByNative - private void onNativeObjectDestroyed() { - if (mContentViewCore.getBrowserAccessibilityManager() == this) { - mContentViewCore.setBrowserAccessibilityManager(null); - } - mNativeObj = 0; - mContentViewCore = null; - } - - @Override - public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) { - if (!mAccessibilityManager.isEnabled() || mNativeObj == 0 || !mFrameInfoInitialized) { - return null; - } - - int rootId = nativeGetRootId(mNativeObj); - if (virtualViewId == View.NO_ID) { - virtualViewId = rootId; - } - if (mAccessibilityFocusId == View.NO_ID) { - mAccessibilityFocusId = rootId; - } - - final AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(mView); - info.setPackageName(mContentViewCore.getContext().getPackageName()); - info.setSource(mView, virtualViewId); - - if (nativePopulateAccessibilityNodeInfo(mNativeObj, info, virtualViewId)) { - return info; - } else { - return null; - } - } - - /** @inheritDoc */ - public List<AccessibilityNodeInfo> findAccessibilityNodeInfosByText(String text, - int virtualViewId) { - return new ArrayList<AccessibilityNodeInfo>(); - } - - /** @inheritDoc */ - public boolean performAction(int virtualViewId, int action, Bundle arguments) { - if (!mAccessibilityManager.isEnabled() || mNativeObj == 0) { - return false; - } - - switch (action) { - case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: - if (mAccessibilityFocusId == virtualViewId) { - return true; - } - - if (mAccessibilityFocusId != View.NO_ID) { - sendAccessibilityEvent(mAccessibilityFocusId, - AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); - } - mAccessibilityFocusId = virtualViewId; - sendAccessibilityEvent(mAccessibilityFocusId, - AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); - return true; - case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: - if (mAccessibilityFocusId == virtualViewId) { - mAccessibilityFocusId = View.NO_ID; - } - return true; - case AccessibilityNodeInfo.ACTION_CLICK: - nativeClick(mNativeObj, virtualViewId); - break; - case AccessibilityNodeInfo.ACTION_FOCUS: - nativeFocus(mNativeObj, virtualViewId); - break; - case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: - nativeBlur(mNativeObj); - break; - default: - break; - } - return false; - } - - /** - * @see View#dispatchHoverEvent(MotionEvent) - */ - public boolean dispatchHoverEvent(MotionEvent event) { - if (!mAccessibilityManager.isEnabled() || mNativeObj == 0) { - return false; - } - - mUserHasTouchExplored = true; - float x = event.getX(); - float y = event.getY(); - - // Offset by the location of the web content within the view. - // Note: the MotionEvent has view-relative coordinates already, - // so we don't have to offset by the view relative to the screen. - y -= mRenderCoordinates.getContentOffsetYPix(); - - // Convert to CSS coordinates. - int cssX = (int) (mRenderCoordinates.fromPixToLocalCss(x) + - mRenderCoordinates.getScrollX()); - int cssY = (int) (mRenderCoordinates.fromPixToLocalCss(y) + - mRenderCoordinates.getScrollY()); - int id = nativeHitTest(mNativeObj, cssX, cssY); - if (mAccessibilityFocusId != id) { - mAccessibilityFocusId = id; - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); - } - - return true; - } - - /** - * Called by ContentViewCore to notify us when the frame info is initialized, - * the first time, since until that point, we can't use mRenderCoordinates to transform - * web coordinates to screen coordinates. - */ - public void notifyFrameInfoInitialized() { - if (mFrameInfoInitialized) return; - - mFrameInfoInitialized = true; - // (Re-) focus focused element, since we weren't able to create an - // AccessibilityNodeInfo for this element before. - if (mAccessibilityFocusId != View.NO_ID) { - sendAccessibilityEvent(mAccessibilityFocusId, - AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); - } - } - - private void sendAccessibilityEvent(int virtualViewId, int eventType) { - if (!mAccessibilityManager.isEnabled() || mNativeObj == 0) return; - - final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); - event.setPackageName(mContentViewCore.getContext().getPackageName()); - int rootId = nativeGetRootId(mNativeObj); - if (virtualViewId == rootId) { - virtualViewId = View.NO_ID; - } - event.setSource(mView, virtualViewId); - if (!nativePopulateAccessibilityEvent(mNativeObj, event, virtualViewId, eventType)) return; - - // This is currently needed if we want Android to draw the yellow box around - // the item that has accessibility focus. In practice, this doesn't seem to slow - // things down, because it's only called when the accessibility focus moves. - // TODO(dmazzoni): remove this if/when Android framework fixes bug. - mContentViewCore.getContainerView().postInvalidate(); - - mContentViewCore.getContainerView().requestSendAccessibilityEvent(mView, event); - } - - @CalledByNative - private void handlePageLoaded(int id) { - if (mUserHasTouchExplored) return; - - if (mFocusPageOnLoad) { - // Focus the natively focused node (usually document), - // if this feature is enabled. - mAccessibilityFocusId = id; - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_FOCUSED); - } - } - - @CalledByNative - private void handleFocusChanged(int id) { - if (mAccessibilityFocusId == id) return; - - mAccessibilityFocusId = id; - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_FOCUSED); - } - - @CalledByNative - private void handleCheckStateChanged(int id) { - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_CLICKED); - } - - @CalledByNative - private void handleTextSelectionChanged(int id) { - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED); - } - - @CalledByNative - private void handleEditableTextChanged(int id) { - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED); - } - - @CalledByNative - private void handleContentChanged(int id) { - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - } - - @CalledByNative - private void handleNavigate() { - mAccessibilityFocusId = View.NO_ID; - mUserHasTouchExplored = false; - mFrameInfoInitialized = false; - } - - @CalledByNative - private void handleScrolledToAnchor(int id) { - if (mAccessibilityFocusId == id) { - return; - } - - mAccessibilityFocusId = id; - sendAccessibilityEvent(id, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); - } - - @CalledByNative - private void announceLiveRegionText(String text) { - mView.announceForAccessibility(text); - } - - @CalledByNative - private void setAccessibilityNodeInfoParent(AccessibilityNodeInfo node, int parentId) { - node.setParent(mView, parentId); - } - - @CalledByNative - private void addAccessibilityNodeInfoChild(AccessibilityNodeInfo node, int child_id) { - node.addChild(mView, child_id); - } - - @CalledByNative - private void setAccessibilityNodeInfoBooleanAttributes(AccessibilityNodeInfo node, - boolean checkable, boolean checked, boolean clickable, - boolean enabled, boolean focusable, boolean focused, boolean password, - boolean scrollable, boolean selected, boolean visibleToUser) { - node.setCheckable(checkable); - node.setChecked(checked); - node.setClickable(clickable); - node.setEnabled(enabled); - node.setFocusable(focusable); - node.setFocused(focused); - node.setPassword(password); - node.setScrollable(scrollable); - node.setSelected(selected); - node.setVisibleToUser(visibleToUser); - } - - @CalledByNative - private void setAccessibilityNodeInfoStringAttributes(AccessibilityNodeInfo node, - String className, String contentDescription) { - node.setClassName(className); - node.setContentDescription(contentDescription); - } - - @CalledByNative - private void setAccessibilityNodeInfoLocation(AccessibilityNodeInfo node, - int absoluteLeft, int absoluteTop, int parentRelativeLeft, int parentRelativeTop, - int width, int height, boolean isRootNode) { - // First set the bounds in parent. - Rect boundsInParent = new Rect(parentRelativeLeft, parentRelativeTop, - parentRelativeLeft + width, parentRelativeTop + height); - if (isRootNode) { - // Offset of the web content relative to the View. - boundsInParent.offset(0, (int) mRenderCoordinates.getContentOffsetYPix()); - } - node.setBoundsInParent(boundsInParent); - - // Now set the absolute rect, which requires several transformations. - Rect rect = new Rect(absoluteLeft, absoluteTop, absoluteLeft + width, absoluteTop + height); - - // Offset by the scroll position. - rect.offset(-(int) mRenderCoordinates.getScrollX(), - -(int) mRenderCoordinates.getScrollY()); - - // Convert CSS (web) pixels to Android View pixels - rect.left = (int) mRenderCoordinates.fromLocalCssToPix(rect.left); - rect.top = (int) mRenderCoordinates.fromLocalCssToPix(rect.top); - rect.bottom = (int) mRenderCoordinates.fromLocalCssToPix(rect.bottom); - rect.right = (int) mRenderCoordinates.fromLocalCssToPix(rect.right); - - // Offset by the location of the web content within the view. - rect.offset(0, - (int) mRenderCoordinates.getContentOffsetYPix()); - - // Finally offset by the location of the view within the screen. - final int[] viewLocation = new int[2]; - mView.getLocationOnScreen(viewLocation); - rect.offset(viewLocation[0], viewLocation[1]); - - node.setBoundsInScreen(rect); - } - - @CalledByNative - private void setAccessibilityEventBooleanAttributes(AccessibilityEvent event, - boolean checked, boolean enabled, boolean password, boolean scrollable) { - event.setChecked(checked); - event.setEnabled(enabled); - event.setPassword(password); - event.setScrollable(scrollable); - } - - @CalledByNative - private void setAccessibilityEventClassName(AccessibilityEvent event, String className) { - event.setClassName(className); - } - - @CalledByNative - private void setAccessibilityEventListAttributes(AccessibilityEvent event, - int currentItemIndex, int itemCount) { - event.setCurrentItemIndex(currentItemIndex); - event.setItemCount(itemCount); - } - - @CalledByNative - private void setAccessibilityEventScrollAttributes(AccessibilityEvent event, - int scrollX, int scrollY, int maxScrollX, int maxScrollY) { - event.setScrollX(scrollX); - event.setScrollY(scrollY); - event.setMaxScrollX(maxScrollX); - event.setMaxScrollY(maxScrollY); - } - - @CalledByNative - private void setAccessibilityEventTextChangedAttrs(AccessibilityEvent event, - int fromIndex, int addedCount, int removedCount, String beforeText, String text) { - event.setFromIndex(fromIndex); - event.setAddedCount(addedCount); - event.setRemovedCount(removedCount); - event.setBeforeText(beforeText); - event.getText().add(text); - } - - @CalledByNative - private void setAccessibilityEventSelectionAttrs(AccessibilityEvent event, - int fromIndex, int addedCount, int itemCount, String text) { - event.setFromIndex(fromIndex); - event.setAddedCount(addedCount); - event.setItemCount(itemCount); - event.getText().add(text); - } - - private native int nativeGetRootId(int nativeBrowserAccessibilityManagerAndroid); - private native int nativeHitTest(int nativeBrowserAccessibilityManagerAndroid, int x, int y); - private native boolean nativePopulateAccessibilityNodeInfo( - int nativeBrowserAccessibilityManagerAndroid, AccessibilityNodeInfo info, int id); - private native boolean nativePopulateAccessibilityEvent( - int nativeBrowserAccessibilityManagerAndroid, AccessibilityEvent event, int id, - int eventType); - private native void nativeClick(int nativeBrowserAccessibilityManagerAndroid, int id); - private native void nativeFocus(int nativeBrowserAccessibilityManagerAndroid, int id); - private native void nativeBlur(int nativeBrowserAccessibilityManagerAndroid); -} diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java index a065870..4dc2736 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/JellyBeanAccessibilityInjector.java @@ -7,6 +7,7 @@ package org.chromium.content.browser.accessibility; import android.content.Context; import android.os.Bundle; import android.os.SystemClock; +import android.view.View; import android.view.accessibility.AccessibilityNodeInfo; import org.chromium.content.browser.ContentViewCore; |