summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authordmazzoni <dmazzoni@chromium.org>2015-06-19 11:21:33 -0700
committerCommit bot <commit-bot@chromium.org>2015-06-19 18:22:11 +0000
commit9fb23b32cdc2864c1ec142e307343abfb1dbdf91 (patch)
tree1ac3dbe6ecdb4a213a48ed70d423c6e5cef900e0 /content/browser
parentaa0a6946ec4d465cc5fbfd4b983b2409fb340c37 (diff)
downloadchromium_src-9fb23b32cdc2864c1ec142e307343abfb1dbdf91.zip
chromium_src-9fb23b32cdc2864c1ec142e307343abfb1dbdf91.tar.gz
chromium_src-9fb23b32cdc2864c1ec142e307343abfb1dbdf91.tar.bz2
Implement accessible scroll actions on Android.
Previously we only exposed scroll information for the main frame, now we expose scroll information and support scrolling actions on all scrollable objects. Depends on: https://codereview.chromium.org/1121473004/ BUG=483653 Review URL: https://codereview.chromium.org/1136523007 Cr-Commit-Position: refs/heads/master@{#335299}
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/accessibility/BUILD.gn15
-rw-r--r--content/browser/accessibility/accessibility_tree_formatter_android.cc8
-rw-r--r--content/browser/accessibility/browser_accessibility_android.cc141
-rw-r--r--content/browser/accessibility/browser_accessibility_android.h11
-rw-r--r--content/browser/accessibility/browser_accessibility_manager.cc7
-rw-r--r--content/browser/accessibility/browser_accessibility_manager.h6
-rw-r--r--content/browser/accessibility/browser_accessibility_manager_android.cc24
-rw-r--r--content/browser/accessibility/browser_accessibility_manager_android.h18
-rw-r--r--content/browser/accessibility/browser_accessibility_manager_unittest.cc2
-rw-r--r--content/browser/frame_host/render_frame_host_impl.cc6
-rw-r--r--content/browser/frame_host/render_frame_host_impl.h2
11 files changed, 212 insertions, 28 deletions
diff --git a/content/browser/accessibility/BUILD.gn b/content/browser/accessibility/BUILD.gn
new file mode 100644
index 0000000..f76c0e3
--- /dev/null
+++ b/content/browser/accessibility/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2015 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.
+
+import("//build/config/android/config.gni")
+import("//build/config/android/rules.gni")
+
+java_cpp_enum("content_browser_accessibility_java_enums_srcjar") {
+ sources = [
+ "//content/browser/accessibility/browser_accessibility_manager_android.h",
+ ]
+ outputs = [
+ "org/chromium/content/browser/accessibility/ScrollDirection.java",
+ ]
+}
diff --git a/content/browser/accessibility/accessibility_tree_formatter_android.cc b/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 97cfc7f..c74d01f 100644
--- a/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -117,6 +117,14 @@ void AccessibilityTreeFormatter::AddProperties(
dict->SetInteger("range_max", static_cast<int>(android_node->RangeMax()));
dict->SetInteger("range_current_value",
static_cast<int>(android_node->RangeCurrentValue()));
+
+ // Actions.
+ dict->SetBoolean("action_scroll_forward", android_node->CanScrollForward());
+ dict->SetBoolean("action_scroll_backward", android_node->CanScrollBackward());
+ dict->SetBoolean("action_scroll_up", android_node->CanScrollUp());
+ dict->SetBoolean("action_scroll_down", android_node->CanScrollDown());
+ dict->SetBoolean("action_scroll_left", android_node->CanScrollLeft());
+ dict->SetBoolean("action_scroll_right", android_node->CanScrollRight());
}
base::string16 AccessibilityTreeFormatter::ToString(
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc
index 0efb78f..dd3c8b7 100644
--- a/content/browser/accessibility/browser_accessibility_android.cc
+++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -101,24 +101,6 @@ bool BrowserAccessibilityAndroid::PlatformIsLeaf() const {
return BrowserAccessibility::PlatformIsLeaf();
}
-bool BrowserAccessibilityAndroid::CanScrollForward() const {
- if (!IsSlider())
- return false;
-
- float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
- float max = GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE);
- return value < max;
-}
-
-bool BrowserAccessibilityAndroid::CanScrollBackward() const {
- if (!IsSlider())
- return false;
-
- float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
- float min = GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE);
- return value > min;
-}
-
bool BrowserAccessibilityAndroid::IsCheckable() const {
bool checkable = false;
bool is_aria_pressed_defined;
@@ -234,8 +216,8 @@ bool BrowserAccessibilityAndroid::IsRangeType() const {
}
bool BrowserAccessibilityAndroid::IsScrollable() const {
- int dummy;
- return GetIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, &dummy);
+ return (HasIntAttribute(ui::AX_ATTR_SCROLL_X_MAX) &&
+ GetRole() != ui::AX_ROLE_SCROLL_AREA);
}
bool BrowserAccessibilityAndroid::IsSelected() const {
@@ -486,6 +468,44 @@ int BrowserAccessibilityAndroid::GetItemCount() const {
return count;
}
+bool BrowserAccessibilityAndroid::CanScrollForward() const {
+ if (IsSlider()) {
+ float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
+ float max = GetFloatAttribute(ui::AX_ATTR_MAX_VALUE_FOR_RANGE);
+ return value < max;
+ } else {
+ return GetScrollX() < GetMaxScrollX() ||
+ GetScrollY() < GetMaxScrollY();
+ }
+}
+
+bool BrowserAccessibilityAndroid::CanScrollBackward() const {
+ if (IsSlider()) {
+ float value = GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE);
+ float min = GetFloatAttribute(ui::AX_ATTR_MIN_VALUE_FOR_RANGE);
+ return value > min;
+ } else {
+ return GetScrollX() > GetMinScrollX() ||
+ GetScrollY() > GetMinScrollY();
+ }
+}
+
+bool BrowserAccessibilityAndroid::CanScrollUp() const {
+ return GetScrollY() > GetMinScrollY();
+}
+
+bool BrowserAccessibilityAndroid::CanScrollDown() const {
+ return GetScrollY() < GetMaxScrollY();
+}
+
+bool BrowserAccessibilityAndroid::CanScrollLeft() const {
+ return GetScrollX() > GetMinScrollX();
+}
+
+bool BrowserAccessibilityAndroid::CanScrollRight() const {
+ return GetScrollX() < GetMaxScrollX();
+}
+
int BrowserAccessibilityAndroid::GetScrollX() const {
int value = 0;
GetIntAttribute(ui::AX_ATTR_SCROLL_X, &value);
@@ -498,16 +518,85 @@ int BrowserAccessibilityAndroid::GetScrollY() const {
return value;
}
+int BrowserAccessibilityAndroid::GetMinScrollX() const {
+ return GetIntAttribute(ui::AX_ATTR_SCROLL_X_MIN);
+}
+
+int BrowserAccessibilityAndroid::GetMinScrollY() const {
+ return GetIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN);
+}
+
int BrowserAccessibilityAndroid::GetMaxScrollX() const {
- int value = 0;
- GetIntAttribute(ui::AX_ATTR_SCROLL_X_MAX, &value);
- return value;
+ return GetIntAttribute(ui::AX_ATTR_SCROLL_X_MAX);
}
int BrowserAccessibilityAndroid::GetMaxScrollY() const {
- int value = 0;
- GetIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX, &value);
- return value;
+ return GetIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX);
+}
+
+bool BrowserAccessibilityAndroid::Scroll(int direction) const {
+ int x = GetIntAttribute(ui::AX_ATTR_SCROLL_X);
+ int x_min = GetIntAttribute(ui::AX_ATTR_SCROLL_X_MIN);
+ int x_max = GetIntAttribute(ui::AX_ATTR_SCROLL_X_MAX);
+ int y = GetIntAttribute(ui::AX_ATTR_SCROLL_Y);
+ int y_min = GetIntAttribute(ui::AX_ATTR_SCROLL_Y_MIN);
+ int y_max = GetIntAttribute(ui::AX_ATTR_SCROLL_Y_MAX);
+
+ // Figure out the bounding box of the visible portion of this scrollable
+ // view so we know how much to scroll by.
+ gfx::Rect bounds;
+ if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) {
+ // If this is the root web area, use the bounds of the view to determine
+ // how big one page is.
+ if (!manager()->delegate())
+ return false;
+ bounds = manager()->delegate()->AccessibilityGetViewBounds();
+ } else if (GetRole() == ui::AX_ROLE_WEB_AREA) {
+ // If this is a web area inside of an iframe, try to use the bounds of
+ // the containing element.
+ BrowserAccessibility* parent = GetParent();
+ while (parent && (parent->GetLocation().width() == 0 ||
+ parent->GetLocation().height() == 0)) {
+ parent = parent->GetParent();
+ }
+ if (parent)
+ bounds = parent->GetLocation();
+ else
+ bounds = GetLocation();
+ } else {
+ // Otherwise this is something like a scrollable div, just use the
+ // bounds of this object itself.
+ bounds = GetLocation();
+ }
+
+ // Scroll by 80% of one page.
+ int page_x = std::max(bounds.width() * 4 / 5, 1);
+ int page_y = std::max(bounds.height() * 4 / 5, 1);
+
+ if (direction == FORWARD)
+ direction = y_max > y_min ? DOWN : RIGHT;
+ if (direction == BACKWARD)
+ direction = y_max > y_min ? UP : LEFT;
+
+ switch (direction) {
+ case UP:
+ y = std::min(std::max(y - page_y, y_min), y_max);
+ break;
+ case DOWN:
+ y = std::min(std::max(y + page_y, y_min), y_max);
+ break;
+ case LEFT:
+ x = std::min(std::max(x - page_x, x_min), x_max);
+ break;
+ case RIGHT:
+ x = std::min(std::max(x + page_x, x_min), x_max);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ manager()->SetScrollOffset(*this, gfx::Point(x, y));
+ return true;
}
int BrowserAccessibilityAndroid::GetTextChangeFromIndex() const {
diff --git a/content/browser/accessibility/browser_accessibility_android.h b/content/browser/accessibility/browser_accessibility_android.h
index 203812c..d9a63b1 100644
--- a/content/browser/accessibility/browser_accessibility_android.h
+++ b/content/browser/accessibility/browser_accessibility_android.h
@@ -19,8 +19,6 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
bool PlatformIsLeaf() const override;
- bool CanScrollForward() const;
- bool CanScrollBackward() const;
bool IsCheckable() const;
bool IsChecked() const;
bool IsClickable() const;
@@ -53,10 +51,19 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
int GetItemIndex() const;
int GetItemCount() const;
+ bool CanScrollForward() const;
+ bool CanScrollBackward() const;
+ bool CanScrollUp() const;
+ bool CanScrollDown() const;
+ bool CanScrollLeft() const;
+ bool CanScrollRight() const;
int GetScrollX() const;
int GetScrollY() const;
+ int GetMinScrollX() const;
+ int GetMinScrollY() const;
int GetMaxScrollX() const;
int GetMaxScrollY() const;
+ bool Scroll(int direction) const;
int GetTextChangeFromIndex() const;
int GetTextChangeAddedCount() const;
diff --git a/content/browser/accessibility/browser_accessibility_manager.cc b/content/browser/accessibility/browser_accessibility_manager.cc
index 742e229..15c1a35 100644
--- a/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/content/browser/accessibility/browser_accessibility_manager.cc
@@ -357,6 +357,13 @@ void BrowserAccessibilityManager::ScrollToPoint(
}
}
+void BrowserAccessibilityManager::SetScrollOffset(
+ const BrowserAccessibility& node, gfx::Point offset) {
+ if (delegate_) {
+ delegate_->AccessibilitySetScrollOffset(node.GetId(), offset);
+ }
+}
+
void BrowserAccessibilityManager::SetValue(
const BrowserAccessibility& node,
const base::string16& value) {
diff --git a/content/browser/accessibility/browser_accessibility_manager.h b/content/browser/accessibility/browser_accessibility_manager.h
index 48c9b1e..21391ca 100644
--- a/content/browser/accessibility/browser_accessibility_manager.h
+++ b/content/browser/accessibility/browser_accessibility_manager.h
@@ -59,6 +59,8 @@ class CONTENT_EXPORT BrowserAccessibilityDelegate {
int acc_obj_id, const gfx::Rect& subfocus) = 0;
virtual void AccessibilityScrollToPoint(
int acc_obj_id, const gfx::Point& point) = 0;
+ virtual void AccessibilitySetScrollOffset(
+ int acc_obj_id, const gfx::Point& offset) = 0;
virtual void AccessibilitySetTextSelection(
int acc_obj_id, int start_offset, int end_offset) = 0;
virtual void AccessibilitySetValue(
@@ -177,6 +179,10 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
void ScrollToPoint(
const BrowserAccessibility& node, gfx::Point point);
+ // If |node| is itself a scrollable container, set its scroll
+ // offset to |offset|.
+ void SetScrollOffset(const BrowserAccessibility& node, gfx::Point offset);
+
// Tell the renderer to set the value of an editable text node.
void SetValue(
const BrowserAccessibility& node, const base::string16& value);
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc
index 79f2b1c..703d800 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -269,6 +269,10 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
id,
node->CanScrollForward(),
node->CanScrollBackward(),
+ node->CanScrollUp(),
+ node->CanScrollDown(),
+ node->CanScrollLeft(),
+ node->CanScrollRight(),
node->IsClickable(),
node->IsEditableText(),
node->IsEnabled(),
@@ -735,6 +739,26 @@ void BrowserAccessibilityManagerAndroid::SetAccessibilityFocus(
delegate_->AccessibilitySetAccessibilityFocus(id);
}
+bool BrowserAccessibilityManagerAndroid::IsSlider(
+ JNIEnv* env, jobject obj, jint id) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ return node->GetRole() == ui::AX_ROLE_SLIDER;
+}
+
+bool BrowserAccessibilityManagerAndroid::Scroll(
+ JNIEnv* env, jobject obj, jint id, int direction) {
+ BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
+ GetFromID(id));
+ if (!node)
+ return false;
+
+ return node->Scroll(direction);
+}
+
void BrowserAccessibilityManagerAndroid::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.h b/content/browser/accessibility/browser_accessibility_manager_android.h
index 70aaba8..4c69b23 100644
--- a/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -16,6 +16,17 @@ namespace aria_strings {
extern const char kAriaLiveAssertive[];
}
+// A Java counterpart will be generated for this enum.
+// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.content.browser.accessibility
+enum ScrollDirection {
+ FORWARD,
+ BACKWARD,
+ UP,
+ DOWN,
+ LEFT,
+ RIGHT
+};
+
// From android.view.accessibility.AccessibilityNodeInfo in Java:
enum AndroidMovementGranularity {
ANDROID_ACCESSIBILITY_NODE_INFO_MOVEMENT_GRANULARITY_CHARACTER = 1,
@@ -133,6 +144,13 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
// accurate movement by granularities on this node.
void SetAccessibilityFocus(JNIEnv* env, jobject obj, jint id);
+ // Returns true if the object is a slider.
+ bool IsSlider(JNIEnv* env, jobject obj, jint id);
+
+ // Scrolls any scrollable container by about 80% of one page in the
+ // given direction.
+ bool Scroll(JNIEnv* env, jobject obj, jint id, int direction);
+
protected:
// AXTreeDelegate overrides.
void OnAtomicUpdateFinished(
diff --git a/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index 2027c12..d30c258 100644
--- a/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -70,6 +70,8 @@ class TestBrowserAccessibilityDelegate
const gfx::Rect& subfocus) override {}
void AccessibilityScrollToPoint(int acc_obj_id,
const gfx::Point& point) override {}
+ void AccessibilitySetScrollOffset(int acc_obj_id,
+ const gfx::Point& offset) override {}
void AccessibilitySetTextSelection(int acc_obj_id,
int start_offset,
int end_offset) override {}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 11ae65a..5bb22ec 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -469,6 +469,12 @@ void RenderFrameHostImpl::AccessibilityScrollToPoint(
routing_id_, acc_obj_id, point));
}
+void RenderFrameHostImpl::AccessibilitySetScrollOffset(
+ int acc_obj_id, const gfx::Point& offset) {
+ Send(new AccessibilityMsg_SetScrollOffset(
+ routing_id_, acc_obj_id, offset));
+}
+
void RenderFrameHostImpl::AccessibilitySetTextSelection(
int object_id, int start_offset, int end_offset) {
Send(new AccessibilityMsg_SetTextSelection(
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 519936d..6cf70cb 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -165,6 +165,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
const gfx::Rect& subfocus) override;
void AccessibilityScrollToPoint(int acc_obj_id,
const gfx::Point& point) override;
+ void AccessibilitySetScrollOffset(int acc_obj_id,
+ const gfx::Point& offset) override;
void AccessibilitySetTextSelection(int acc_obj_id,
int start_offset,
int end_offset) override;