| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/accessibility/browser_accessibility_manager_android.h" | 5 #include "content/browser/accessibility/browser_accessibility_manager_android.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 | 8 |
| 9 #include "base/android/jni_android.h" | 9 #include "base/android/jni_android.h" |
| 10 #include "base/android/jni_string.h" | 10 #include "base/android/jni_string.h" |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 if (obj.is_null()) | 121 if (obj.is_null()) |
| 122 return; | 122 return; |
| 123 | 123 |
| 124 if (event_type == ui::AX_EVENT_HIDE) | 124 if (event_type == ui::AX_EVENT_HIDE) |
| 125 return; | 125 return; |
| 126 | 126 |
| 127 // Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify | 127 // Always send AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED to notify |
| 128 // the Android system that the accessibility hierarchy rooted at this | 128 // the Android system that the accessibility hierarchy rooted at this |
| 129 // node has changed. | 129 // node has changed. |
| 130 Java_BrowserAccessibilityManager_handleContentChanged( | 130 Java_BrowserAccessibilityManager_handleContentChanged( |
| 131 env, obj.obj(), node->renderer_id()); | 131 env, obj.obj(), node->GetId()); |
| 132 | 132 |
| 133 switch (event_type) { | 133 switch (event_type) { |
| 134 case ui::AX_EVENT_LOAD_COMPLETE: | 134 case ui::AX_EVENT_LOAD_COMPLETE: |
| 135 Java_BrowserAccessibilityManager_handlePageLoaded( | 135 Java_BrowserAccessibilityManager_handlePageLoaded( |
| 136 env, obj.obj(), focus_->renderer_id()); | 136 env, obj.obj(), focus_->GetId()); |
| 137 break; | 137 break; |
| 138 case ui::AX_EVENT_FOCUS: | 138 case ui::AX_EVENT_FOCUS: |
| 139 Java_BrowserAccessibilityManager_handleFocusChanged( | 139 Java_BrowserAccessibilityManager_handleFocusChanged( |
| 140 env, obj.obj(), node->renderer_id()); | 140 env, obj.obj(), node->GetId()); |
| 141 break; | 141 break; |
| 142 case ui::AX_EVENT_CHECKED_STATE_CHANGED: | 142 case ui::AX_EVENT_CHECKED_STATE_CHANGED: |
| 143 Java_BrowserAccessibilityManager_handleCheckStateChanged( | 143 Java_BrowserAccessibilityManager_handleCheckStateChanged( |
| 144 env, obj.obj(), node->renderer_id()); | 144 env, obj.obj(), node->GetId()); |
| 145 break; | 145 break; |
| 146 case ui::AX_EVENT_SCROLL_POSITION_CHANGED: | 146 case ui::AX_EVENT_SCROLL_POSITION_CHANGED: |
| 147 Java_BrowserAccessibilityManager_handleScrollPositionChanged( | 147 Java_BrowserAccessibilityManager_handleScrollPositionChanged( |
| 148 env, obj.obj(), node->renderer_id()); | 148 env, obj.obj(), node->GetId()); |
| 149 break; | 149 break; |
| 150 case ui::AX_EVENT_SCROLLED_TO_ANCHOR: | 150 case ui::AX_EVENT_SCROLLED_TO_ANCHOR: |
| 151 Java_BrowserAccessibilityManager_handleScrolledToAnchor( | 151 Java_BrowserAccessibilityManager_handleScrolledToAnchor( |
| 152 env, obj.obj(), node->renderer_id()); | 152 env, obj.obj(), node->GetId()); |
| 153 break; | 153 break; |
| 154 case ui::AX_EVENT_ALERT: | 154 case ui::AX_EVENT_ALERT: |
| 155 // An alert is a special case of live region. Fall through to the | 155 // An alert is a special case of live region. Fall through to the |
| 156 // next case to handle it. | 156 // next case to handle it. |
| 157 case ui::AX_EVENT_SHOW: { | 157 case ui::AX_EVENT_SHOW: { |
| 158 // This event is fired when an object appears in a live region. | 158 // This event is fired when an object appears in a live region. |
| 159 // Speak its text. | 159 // Speak its text. |
| 160 BrowserAccessibilityAndroid* android_node = | 160 BrowserAccessibilityAndroid* android_node = |
| 161 static_cast<BrowserAccessibilityAndroid*>(node); | 161 static_cast<BrowserAccessibilityAndroid*>(node); |
| 162 Java_BrowserAccessibilityManager_announceLiveRegionText( | 162 Java_BrowserAccessibilityManager_announceLiveRegionText( |
| 163 env, obj.obj(), | 163 env, obj.obj(), |
| 164 base::android::ConvertUTF16ToJavaString( | 164 base::android::ConvertUTF16ToJavaString( |
| 165 env, android_node->GetText()).obj()); | 165 env, android_node->GetText()).obj()); |
| 166 break; | 166 break; |
| 167 } | 167 } |
| 168 case ui::AX_EVENT_SELECTED_TEXT_CHANGED: | 168 case ui::AX_EVENT_SELECTED_TEXT_CHANGED: |
| 169 Java_BrowserAccessibilityManager_handleTextSelectionChanged( | 169 Java_BrowserAccessibilityManager_handleTextSelectionChanged( |
| 170 env, obj.obj(), node->renderer_id()); | 170 env, obj.obj(), node->GetId()); |
| 171 break; | 171 break; |
| 172 case ui::AX_EVENT_CHILDREN_CHANGED: | 172 case ui::AX_EVENT_CHILDREN_CHANGED: |
| 173 case ui::AX_EVENT_TEXT_CHANGED: | 173 case ui::AX_EVENT_TEXT_CHANGED: |
| 174 case ui::AX_EVENT_VALUE_CHANGED: | 174 case ui::AX_EVENT_VALUE_CHANGED: |
| 175 if (node->IsEditableText()) { | 175 if (node->IsEditableText()) { |
| 176 Java_BrowserAccessibilityManager_handleEditableTextChanged( | 176 Java_BrowserAccessibilityManager_handleEditableTextChanged( |
| 177 env, obj.obj(), node->renderer_id()); | 177 env, obj.obj(), node->GetId()); |
| 178 } | 178 } |
| 179 break; | 179 break; |
| 180 default: | 180 default: |
| 181 // There are some notifications that aren't meaningful on Android. | 181 // There are some notifications that aren't meaningful on Android. |
| 182 // It's okay to skip them. | 182 // It's okay to skip them. |
| 183 break; | 183 break; |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) { | 187 jint BrowserAccessibilityManagerAndroid::GetRootId(JNIEnv* env, jobject obj) { |
| 188 return static_cast<jint>(root_->renderer_id()); | 188 return static_cast<jint>(root_->GetId()); |
| 189 } | 189 } |
| 190 | 190 |
| 191 jboolean BrowserAccessibilityManagerAndroid::IsNodeValid( | 191 jboolean BrowserAccessibilityManagerAndroid::IsNodeValid( |
| 192 JNIEnv* env, jobject obj, jint id) { | 192 JNIEnv* env, jobject obj, jint id) { |
| 193 return GetFromRendererID(id) != NULL; | 193 return GetFromRendererID(id) != NULL; |
| 194 } | 194 } |
| 195 | 195 |
| 196 jint BrowserAccessibilityManagerAndroid::HitTest( | 196 jint BrowserAccessibilityManagerAndroid::HitTest( |
| 197 JNIEnv* env, jobject obj, jint x, jint y) { | 197 JNIEnv* env, jobject obj, jint x, jint y) { |
| 198 BrowserAccessibilityAndroid* result = | 198 BrowserAccessibilityAndroid* result = |
| 199 static_cast<BrowserAccessibilityAndroid*>( | 199 static_cast<BrowserAccessibilityAndroid*>( |
| 200 root_->BrowserAccessibilityForPoint(gfx::Point(x, y))); | 200 root_->BrowserAccessibilityForPoint(gfx::Point(x, y))); |
| 201 | 201 |
| 202 if (!result) | 202 if (!result) |
| 203 return root_->renderer_id(); | 203 return root_->GetId(); |
| 204 | 204 |
| 205 if (result->IsFocusable()) | 205 if (result->IsFocusable()) |
| 206 return result->renderer_id(); | 206 return result->GetId(); |
| 207 | 207 |
| 208 // Examine the children of |result| to find the nearest accessibility focus | 208 // Examine the children of |result| to find the nearest accessibility focus |
| 209 // candidate | 209 // candidate |
| 210 BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result); | 210 BrowserAccessibility* nearest_node = FuzzyHitTest(x, y, result); |
| 211 if (nearest_node) | 211 if (nearest_node) |
| 212 return nearest_node->renderer_id(); | 212 return nearest_node->GetId(); |
| 213 | 213 |
| 214 return root_->renderer_id(); | 214 return root_->GetId(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo( | 217 jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo( |
| 218 JNIEnv* env, jobject obj, jobject info, jint id) { | 218 JNIEnv* env, jobject obj, jobject info, jint id) { |
| 219 BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>( | 219 BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>( |
| 220 GetFromRendererID(id)); | 220 GetFromRendererID(id)); |
| 221 if (!node) | 221 if (!node) |
| 222 return false; | 222 return false; |
| 223 | 223 |
| 224 if (node->parent()) { | 224 if (node->GetParent()) { |
| 225 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoParent( | 225 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoParent( |
| 226 env, obj, info, node->parent()->renderer_id()); | 226 env, obj, info, node->GetParent()->GetId()); |
| 227 } | 227 } |
| 228 for (unsigned i = 0; i < node->PlatformChildCount(); ++i) { | 228 for (unsigned i = 0; i < node->PlatformChildCount(); ++i) { |
| 229 Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild( | 229 Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild( |
| 230 env, obj, info, node->children()[i]->renderer_id()); | 230 env, obj, info, node->InternalGetChild(i)->GetId()); |
| 231 } | 231 } |
| 232 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes( | 232 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes( |
| 233 env, obj, info, | 233 env, obj, info, |
| 234 id, | 234 id, |
| 235 node->IsCheckable(), | 235 node->IsCheckable(), |
| 236 node->IsChecked(), | 236 node->IsChecked(), |
| 237 node->IsClickable(), | 237 node->IsClickable(), |
| 238 node->IsEnabled(), | 238 node->IsEnabled(), |
| 239 node->IsFocusable(), | 239 node->IsFocusable(), |
| 240 node->IsFocused(), | 240 node->IsFocused(), |
| 241 node->IsPassword(), | 241 node->IsPassword(), |
| 242 node->IsScrollable(), | 242 node->IsScrollable(), |
| 243 node->IsSelected(), | 243 node->IsSelected(), |
| 244 node->IsVisibleToUser()); | 244 node->IsVisibleToUser()); |
| 245 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoClassName( | 245 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoClassName( |
| 246 env, obj, info, | 246 env, obj, info, |
| 247 base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj()); | 247 base::android::ConvertUTF8ToJavaString(env, node->GetClassName()).obj()); |
| 248 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoContentDescription( | 248 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoContentDescription( |
| 249 env, obj, info, | 249 env, obj, info, |
| 250 base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj(), | 250 base::android::ConvertUTF16ToJavaString(env, node->GetText()).obj(), |
| 251 node->IsLink()); | 251 node->IsLink()); |
| 252 | 252 |
| 253 gfx::Rect absolute_rect = node->GetLocalBoundsRect(); | 253 gfx::Rect absolute_rect = node->GetLocalBoundsRect(); |
| 254 gfx::Rect parent_relative_rect = absolute_rect; | 254 gfx::Rect parent_relative_rect = absolute_rect; |
| 255 if (node->parent()) { | 255 if (node->GetParent()) { |
| 256 gfx::Rect parent_rect = node->parent()->GetLocalBoundsRect(); | 256 gfx::Rect parent_rect = node->GetParent()->GetLocalBoundsRect(); |
| 257 parent_relative_rect.Offset(-parent_rect.OffsetFromOrigin()); | 257 parent_relative_rect.Offset(-parent_rect.OffsetFromOrigin()); |
| 258 } | 258 } |
| 259 bool is_root = node->parent() == NULL; | 259 bool is_root = node->GetParent() == NULL; |
| 260 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoLocation( | 260 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoLocation( |
| 261 env, obj, info, | 261 env, obj, info, |
| 262 absolute_rect.x(), absolute_rect.y(), | 262 absolute_rect.x(), absolute_rect.y(), |
| 263 parent_relative_rect.x(), parent_relative_rect.y(), | 263 parent_relative_rect.x(), parent_relative_rect.y(), |
| 264 absolute_rect.width(), absolute_rect.height(), | 264 absolute_rect.width(), absolute_rect.height(), |
| 265 is_root); | 265 is_root); |
| 266 | 266 |
| 267 // New KitKat APIs | 267 // New KitKat APIs |
| 268 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoKitKatAttributes( | 268 Java_BrowserAccessibilityManager_setAccessibilityNodeInfoKitKatAttributes( |
| 269 env, obj, info, | 269 env, obj, info, |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 403 } | 403 } |
| 404 | 404 |
| 405 void BrowserAccessibilityManagerAndroid::Blur(JNIEnv* env, jobject obj) { | 405 void BrowserAccessibilityManagerAndroid::Blur(JNIEnv* env, jobject obj) { |
| 406 SetFocus(root_, true); | 406 SetFocus(root_, true); |
| 407 } | 407 } |
| 408 | 408 |
| 409 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible( | 409 void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible( |
| 410 JNIEnv* env, jobject obj, jint id) { | 410 JNIEnv* env, jobject obj, jint id) { |
| 411 BrowserAccessibility* node = GetFromRendererID(id); | 411 BrowserAccessibility* node = GetFromRendererID(id); |
| 412 if (node) | 412 if (node) |
| 413 ScrollToMakeVisible(*node, gfx::Rect(node->location().size())); | 413 ScrollToMakeVisible(*node, gfx::Rect(node->GetLocation().size())); |
| 414 } | 414 } |
| 415 | 415 |
| 416 BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest( | 416 BrowserAccessibility* BrowserAccessibilityManagerAndroid::FuzzyHitTest( |
| 417 int x, int y, BrowserAccessibility* start_node) { | 417 int x, int y, BrowserAccessibility* start_node) { |
| 418 BrowserAccessibility* nearest_node = NULL; | 418 BrowserAccessibility* nearest_node = NULL; |
| 419 int min_distance = INT_MAX; | 419 int min_distance = INT_MAX; |
| 420 FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance); | 420 FuzzyHitTestImpl(x, y, start_node, &nearest_node, &min_distance); |
| 421 return nearest_node; | 421 return nearest_node; |
| 422 } | 422 } |
| 423 | 423 |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 471 if (!node) | 471 if (!node) |
| 472 return 0; | 472 return 0; |
| 473 | 473 |
| 474 AndroidHtmlElementType element_type = HtmlElementTypeFromString( | 474 AndroidHtmlElementType element_type = HtmlElementTypeFromString( |
| 475 base::android::ConvertJavaStringToUTF16(env, element_type_str)); | 475 base::android::ConvertJavaStringToUTF16(env, element_type_str)); |
| 476 | 476 |
| 477 node = forwards ? NextInTreeOrder(node) : PreviousInTreeOrder(node); | 477 node = forwards ? NextInTreeOrder(node) : PreviousInTreeOrder(node); |
| 478 while (node) { | 478 while (node) { |
| 479 switch(element_type) { | 479 switch(element_type) { |
| 480 case HTML_ELEMENT_TYPE_SECTION: | 480 case HTML_ELEMENT_TYPE_SECTION: |
| 481 if (node->role() == ui::AX_ROLE_ARTICLE || | 481 if (node->GetRole() == ui::AX_ROLE_ARTICLE || |
| 482 node->role() == ui::AX_ROLE_APPLICATION || | 482 node->GetRole() == ui::AX_ROLE_APPLICATION || |
| 483 node->role() == ui::AX_ROLE_BANNER || | 483 node->GetRole() == ui::AX_ROLE_BANNER || |
| 484 node->role() == ui::AX_ROLE_COMPLEMENTARY || | 484 node->GetRole() == ui::AX_ROLE_COMPLEMENTARY || |
| 485 node->role() == ui::AX_ROLE_CONTENT_INFO || | 485 node->GetRole() == ui::AX_ROLE_CONTENT_INFO || |
| 486 node->role() == ui::AX_ROLE_HEADING || | 486 node->GetRole() == ui::AX_ROLE_HEADING || |
| 487 node->role() == ui::AX_ROLE_MAIN || | 487 node->GetRole() == ui::AX_ROLE_MAIN || |
| 488 node->role() == ui::AX_ROLE_NAVIGATION || | 488 node->GetRole() == ui::AX_ROLE_NAVIGATION || |
| 489 node->role() == ui::AX_ROLE_SEARCH || | 489 node->GetRole() == ui::AX_ROLE_SEARCH || |
| 490 node->role() == ui::AX_ROLE_REGION) { | 490 node->GetRole() == ui::AX_ROLE_REGION) { |
| 491 return node->renderer_id(); | 491 return node->GetId(); |
| 492 } | 492 } |
| 493 break; | 493 break; |
| 494 case HTML_ELEMENT_TYPE_LIST: | 494 case HTML_ELEMENT_TYPE_LIST: |
| 495 if (node->role() == ui::AX_ROLE_LIST || | 495 if (node->GetRole() == ui::AX_ROLE_LIST || |
| 496 node->role() == ui::AX_ROLE_GRID || | 496 node->GetRole() == ui::AX_ROLE_GRID || |
| 497 node->role() == ui::AX_ROLE_TABLE || | 497 node->GetRole() == ui::AX_ROLE_TABLE || |
| 498 node->role() == ui::AX_ROLE_TREE) { | 498 node->GetRole() == ui::AX_ROLE_TREE) { |
| 499 return node->renderer_id(); | 499 return node->GetId(); |
| 500 } | 500 } |
| 501 break; | 501 break; |
| 502 case HTML_ELEMENT_TYPE_CONTROL: | 502 case HTML_ELEMENT_TYPE_CONTROL: |
| 503 if (static_cast<BrowserAccessibilityAndroid*>(node)->IsFocusable()) | 503 if (static_cast<BrowserAccessibilityAndroid*>(node)->IsFocusable()) |
| 504 return node->renderer_id(); | 504 return node->GetId(); |
| 505 break; | 505 break; |
| 506 case HTML_ELEMENT_TYPE_ANY: | 506 case HTML_ELEMENT_TYPE_ANY: |
| 507 // In theory, the API says that an accessibility service could | 507 // In theory, the API says that an accessibility service could |
| 508 // jump to an element by element name, like 'H1' or 'P'. This isn't | 508 // jump to an element by element name, like 'H1' or 'P'. This isn't |
| 509 // currently used by any accessibility service, and we think it's | 509 // currently used by any accessibility service, and we think it's |
| 510 // better to keep them high-level like 'SECTION' or 'CONTROL', so we | 510 // better to keep them high-level like 'SECTION' or 'CONTROL', so we |
| 511 // just fall back on linear navigation when we don't recognize the | 511 // just fall back on linear navigation when we don't recognize the |
| 512 // element type. | 512 // element type. |
| 513 if (static_cast<BrowserAccessibilityAndroid*>(node)->IsClickable()) | 513 if (static_cast<BrowserAccessibilityAndroid*>(node)->IsClickable()) |
| 514 return node->renderer_id(); | 514 return node->GetId(); |
| 515 break; | 515 break; |
| 516 } | 516 } |
| 517 | 517 |
| 518 node = forwards ? NextInTreeOrder(node) : PreviousInTreeOrder(node); | 518 node = forwards ? NextInTreeOrder(node) : PreviousInTreeOrder(node); |
| 519 } | 519 } |
| 520 | 520 |
| 521 return 0; | 521 return 0; |
| 522 } | 522 } |
| 523 | 523 |
| 524 void BrowserAccessibilityManagerAndroid::NotifyRootChanged() { | 524 void BrowserAccessibilityManagerAndroid::NotifyRootChanged() { |
| 525 JNIEnv* env = AttachCurrentThread(); | 525 JNIEnv* env = AttachCurrentThread(); |
| 526 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); | 526 ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); |
| 527 if (obj.is_null()) | 527 if (obj.is_null()) |
| 528 return; | 528 return; |
| 529 | 529 |
| 530 Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj()); | 530 Java_BrowserAccessibilityManager_handleNavigate(env, obj.obj()); |
| 531 } | 531 } |
| 532 | 532 |
| 533 bool | 533 bool |
| 534 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() { | 534 BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() { |
| 535 // The Java layer handles the root scroll offset. | 535 // The Java layer handles the root scroll offset. |
| 536 return false; | 536 return false; |
| 537 } | 537 } |
| 538 | 538 |
| 539 bool RegisterBrowserAccessibilityManager(JNIEnv* env) { | 539 bool RegisterBrowserAccessibilityManager(JNIEnv* env) { |
| 540 return RegisterNativesImpl(env); | 540 return RegisterNativesImpl(env); |
| 541 } | 541 } |
| 542 | 542 |
| 543 } // namespace content | 543 } // namespace content |
| OLD | NEW |