diff options
Diffstat (limited to 'chromium/ui/android')
13 files changed, 411 insertions, 53 deletions
diff --git a/chromium/ui/android/BUILD.gn b/chromium/ui/android/BUILD.gn index 0f5c728944c..7b8a034042b 100644 --- a/chromium/ui/android/BUILD.gn +++ b/chromium/ui/android/BUILD.gn @@ -66,6 +66,7 @@ component("android") { "//skia", "//third_party/blink/public:blink_headers", "//ui/base", + "//ui/base/cursor:cursor_base", "//ui/base/cursor/mojom:cursor_type", "//ui/compositor", "//ui/display", @@ -213,7 +214,9 @@ android_library("ui_utils_java") { deps = [ "//base:base_java", "//components/payments/mojom:mojom_java", - "//third_party/android_deps:android_support_v7_appcompat_java", + "//third_party/android_deps:androidx_appcompat_appcompat_java", + "//third_party/android_deps:androidx_appcompat_appcompat_resources_java", + "//third_party/android_deps:androidx_core_core_java", "//third_party/blink/public/mojom:mojom_platform_java", ] } @@ -317,6 +320,7 @@ android_library("ui_full_java") { "java/src/org/chromium/ui/resources/system/SystemResourceLoader.java", "java/src/org/chromium/ui/text/NoUnderlineClickableSpan.java", "java/src/org/chromium/ui/text/SpanApplier.java", + "java/src/org/chromium/ui/util/AccessibilityUtil.java", "java/src/org/chromium/ui/util/ColorUtils.java", "java/src/org/chromium/ui/util/TokenHolder.java", "java/src/org/chromium/ui/vr/VrModeObserver.java", @@ -345,6 +349,7 @@ android_library("ui_full_java") { "//base:jni_java", "//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:androidx_appcompat_appcompat_resources_java", "//third_party/android_deps:androidx_asynclayoutinflater_asynclayoutinflater_java", "//third_party/android_deps:androidx_recyclerview_recyclerview_java", "//ui/base/cursor/mojom:cursor_type_java", @@ -366,6 +371,7 @@ android_library("ui_java_test_support") { "javatests/src/org/chromium/ui/test/util/UiRestriction.java", "javatests/src/org/chromium/ui/test/util/UiRestrictionSkipCheck.java", "javatests/src/org/chromium/ui/test/util/modelutil/FakeViewProvider.java", + "junit/src/org/chromium/ui/base/TestActivity.java", ] deps = [ ":ui_java", @@ -378,19 +384,20 @@ android_library("ui_java_test_support") { } android_resources("ui_javatest_resources") { - custom_package = "org.chromium.test.ui" + testonly = true sources = [ "junit/res/layout/inflated_view.xml", "junit/res/layout/layout_view_builder_test.xml", "junit/res/layout/main_view.xml", ] + android_manifest = "junit/AndroidManifest.xml" } junit_binary("ui_junit_tests") { - package_name = "org.chromium.test.ui" sources = [ "junit/src/org/chromium/ui/AsyncViewProviderTest.java", "junit/src/org/chromium/ui/AsyncViewStubTest.java", + "junit/src/org/chromium/ui/base/ActivityAndroidPermissionDelegateTest.java", "junit/src/org/chromium/ui/base/ApplicationViewportInsetSupplierTest.java", "junit/src/org/chromium/ui/base/ClipboardTest.java", "junit/src/org/chromium/ui/base/EventOffsetHandlerTest.java", @@ -425,7 +432,17 @@ junit_binary("ui_junit_tests") { "//base:base_java_test_support", "//base:base_junit_test_support", "//base/test:test_support_java", + "//third_party/android_deps:androidx_annotation_annotation_java", + "//third_party/android_deps:androidx_appcompat_appcompat_java", + "//third_party/android_deps:androidx_appcompat_appcompat_resources_java", + "//third_party/android_deps:androidx_asynclayoutinflater_asynclayoutinflater_java", + "//third_party/android_deps:androidx_test_core_java", + "//third_party/android_deps:androidx_test_ext_junit_java", + "//third_party/android_deps:androidx_test_runner_java", + "//third_party/hamcrest:hamcrest_java", + "//third_party/mockito:mockito_java", ] + android_manifest = "junit/AndroidManifest.xml" } test("ui_android_unittests") { @@ -471,6 +488,7 @@ android_library("clipboard_java_test_support") { deps = [ "//base:base_java", "//base:base_java_test_support", + "//base:jni_java", ] } diff --git a/chromium/ui/android/event_forwarder.cc b/chromium/ui/android/event_forwarder.cc index cd3643cbe37..8eac9e2ecbf 100644 --- a/chromium/ui/android/event_forwarder.cc +++ b/chromium/ui/android/event_forwarder.cc @@ -72,6 +72,7 @@ jboolean EventForwarder::OnTouchEvent(JNIEnv* env, jfloat raw_pos_y, jint android_tool_type_0, jint android_tool_type_1, + jint android_gesture_classification, jint android_button_state, jint android_meta_state, jboolean for_touch_handle) { @@ -84,9 +85,9 @@ jboolean EventForwarder::OnTouchEvent(JNIEnv* env, ui::MotionEventAndroid event( env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, time_ms, android_action, pointer_count, history_size, action_index, - 0 /* action_button */, android_button_state, android_meta_state, - raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, for_touch_handle, &pointer0, - &pointer1); + 0 /* action_button */, android_gesture_classification, + android_button_state, android_meta_state, raw_pos_x - pos_x_0, + raw_pos_y - pos_y_0, for_touch_handle, &pointer0, &pointer1); return view_->OnTouchEvent(event); } @@ -113,10 +114,10 @@ void EventForwarder::OnMouseEvent(JNIEnv* env, ui::MotionEventAndroid event( env, nullptr /* event */, 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */, - 0 /* action_index */, android_action_button, android_button_state, - android_meta_state, 0 /* raw_offset_x_pixels */, - 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer, - nullptr); + 0 /* action_index */, android_action_button, + 0 /* gesture_classification */, android_button_state, android_meta_state, + 0 /* raw_offset_x_pixels */, 0 /* raw_offset_y_pixels */, + false /* for_touch_handle */, &pointer, nullptr); view_->OnMouseEvent(event); } @@ -168,7 +169,7 @@ jboolean EventForwarder::OnGenericMotionEvent( ui::MotionEventAndroid::Pointer pointer0(0, x, y, 0, 0, 0, 0, 0); ui::MotionEventAndroid event( env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f, - time_ms, 0, 1, 0, 0, 0, 0, 0, 0, 0, false, &pointer0, nullptr); + time_ms, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, false, &pointer0, nullptr); return view_->OnGenericMotionEvent(event); } diff --git a/chromium/ui/android/event_forwarder.h b/chromium/ui/android/event_forwarder.h index 18b75e76384..cfdbd57fa7c 100644 --- a/chromium/ui/android/event_forwarder.h +++ b/chromium/ui/android/event_forwarder.h @@ -46,6 +46,7 @@ class EventForwarder { jfloat raw_pos_y, jint android_tool_type_0, jint android_tool_type_1, + jint android_gesture_classification, jint android_button_state, jint android_meta_state, jboolean is_touch_handle_event); diff --git a/chromium/ui/android/junit/AndroidManifest.xml b/chromium/ui/android/junit/AndroidManifest.xml new file mode 100644 index 00000000000..26fe399d700 --- /dev/null +++ b/chromium/ui/android/junit/AndroidManifest.xml @@ -0,0 +1,19 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2020 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. +--> + +<!-- This manifest is required for tests using + androidx.test.core.app.ActivityScenario to work. +--> +<manifest xmlns:android="http://schemas.android.com/apk/res/android" + package="org.chromium.test.ui"> + + <!-- Value used by ActivityAndroidPermissionDelegateTest --> + <uses-permission android:name="android.permission.INTERNET"/> + + <application android:theme="@style/Theme.AppCompat.Light"> + <activity android:name="org.chromium.ui.base.TestActivity"/> + </application> +</manifest> diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/ActivityAndroidPermissionDelegateTest.java b/chromium/ui/android/junit/src/org/chromium/ui/base/ActivityAndroidPermissionDelegateTest.java new file mode 100644 index 00000000000..1df70151bcb --- /dev/null +++ b/chromium/ui/android/junit/src/org/chromium/ui/base/ActivityAndroidPermissionDelegateTest.java @@ -0,0 +1,260 @@ +// Copyright 2020 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.ui.base; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import android.content.pm.PackageManager; + +import androidx.test.core.app.ActivityScenario; +import androidx.test.ext.junit.rules.ActivityScenarioRule; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.robolectric.Shadows; +import org.robolectric.shadows.ShadowActivity; +import org.robolectric.shadows.ShadowActivity.PermissionsRequest; + +import org.chromium.base.test.BaseRobolectricTestRunner; + +import java.lang.ref.WeakReference; + +/** + * Robolectric unit tests for {@link ActivityAndroidPermissionDelegate} and + * {@link AndroidPermissionDelegateWithRequester}. + */ +@RunWith(BaseRobolectricTestRunner.class) +public class ActivityAndroidPermissionDelegateTest { + /** + * Rule managing the lifecycle of activity in each {@code @Test}. + * <p> + * To access the activity and run code on its main thread, use + * {@link ActivityScenario#onActivity}: + * <pre> + * mActivityScenarios.getScenario().onActivity(activity -> { + * // Your test code using the activity here. + * }); + * </pre> + */ + @Rule + public ActivityScenarioRule<TestActivity> mActivityScenarios = + new ActivityScenarioRule<>(TestActivity.class); + + @Test + public void testHasPermissionDenied() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + + boolean hasPermission = + permissionDelegate.hasPermission(android.Manifest.permission.INTERNET); + + assertFalse("The default result of hasPermission should be false", hasPermission); + }); + } + + @Test + public void testHasPermissionGranted() { + mActivityScenarios.getScenario().onActivity(activity -> { + Shadows.shadowOf(activity).grantPermissions(android.Manifest.permission.INTERNET); + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + + boolean hasPermission = + permissionDelegate.hasPermission(android.Manifest.permission.INTERNET); + + assertTrue("hasPermission should return true if permission is granted", hasPermission); + }); + } + + @Test + public void testCanRequestPermissionInitial() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + + boolean canRequest = + permissionDelegate.canRequestPermission(android.Manifest.permission.INTERNET); + + assertTrue("The default result of canRequestPermission should be true", canRequest); + }); + } + + @Test + public void testRequestPermissionsGranted() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + PermissionCallback callback = Mockito.mock(PermissionCallback.class); + + // Request permission + permissionDelegate.requestPermissions( + new String[] {android.Manifest.permission.INTERNET}, callback); + + PermissionsRequest lastRequest = + Shadows.shadowOf(activity).getLastRequestedPermission(); + assertEquals(new String[] {android.Manifest.permission.INTERNET}, + lastRequest.requestedPermissions); + verify(callback, + never().description("PermissionCallback should not receive results before " + + "handlePermissionResult is invoked")) + .onRequestPermissionsResult(any(), any()); + + // Respond to the request + int[] grantResults = new int[] {PackageManager.PERMISSION_GRANTED}; + permissionDelegate.handlePermissionResult( + lastRequest.requestCode, lastRequest.requestedPermissions, grantResults); + + verify(callback, + Mockito.description( + "handlePermissionResult should invoke the PermissionCallback")) + .onRequestPermissionsResult(lastRequest.requestedPermissions, grantResults); + }); + } + + @Test + public void testRequestPermissionsDenied() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + PermissionCallback callback = Mockito.mock(PermissionCallback.class); + + // Request permission + permissionDelegate.requestPermissions( + new String[] {android.Manifest.permission.INTERNET}, callback); + + PermissionsRequest lastRequest = + Shadows.shadowOf(activity).getLastRequestedPermission(); + assertEquals(new String[] {android.Manifest.permission.INTERNET}, + lastRequest.requestedPermissions); + verify(callback, + never().description("PermissionCallback should not receive results before " + + "handlePermissionResult is invoked")) + .onRequestPermissionsResult(any(), any()); + + // Respond to the request + int[] grantResults = new int[] {PackageManager.PERMISSION_DENIED}; + permissionDelegate.handlePermissionResult( + lastRequest.requestCode, lastRequest.requestedPermissions, grantResults); + + verify(callback, + Mockito.description( + "handlePermissionResult should invoke the PermissionCallback")) + .onRequestPermissionsResult(lastRequest.requestedPermissions, grantResults); + }); + } + + @Test + public void testCanRequestPermissionAfterRequestGranted() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + performRequestPermission(permissionDelegate, Shadows.shadowOf(activity), + android.Manifest.permission.INTERNET, PackageManager.PERMISSION_GRANTED); + + boolean canRequest = + permissionDelegate.canRequestPermission(android.Manifest.permission.INTERNET); + + assertTrue("After a granted permission request canRequestPermission should return true", + canRequest); + }); + } + + @Test + public void testCanRequestPermissionAfterRequestDenied() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + performRequestPermission(permissionDelegate, Shadows.shadowOf(activity), + android.Manifest.permission.INTERNET, PackageManager.PERMISSION_DENIED); + + boolean canRequest = + permissionDelegate.canRequestPermission(android.Manifest.permission.INTERNET); + + assertFalse( + "After a denied permission request canRequestPermission should return false", + canRequest); + }); + } + + @Test + public void testCanRequestPermissionWithShowRequestRationale() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + performRequestPermission(permissionDelegate, Shadows.shadowOf(activity), + android.Manifest.permission.INTERNET, PackageManager.PERMISSION_DENIED); + Shadows.shadowOf(activity.getPackageManager()) + .setShouldShowRequestPermissionRationale( + android.Manifest.permission.INTERNET, true); + + boolean canRequest = + permissionDelegate.canRequestPermission(android.Manifest.permission.INTERNET); + + assertTrue("When shouldShowRequestPermissionRationale is true " + + "canRequestPermission should return true", + canRequest); + }); + } + + @Test + public void testCanRequestPermissionAfterHasPermissionGranted() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + performRequestPermission(permissionDelegate, Shadows.shadowOf(activity), + android.Manifest.permission.INTERNET, PackageManager.PERMISSION_DENIED); + + Shadows.shadowOf(activity).grantPermissions(android.Manifest.permission.INTERNET); + permissionDelegate.hasPermission(android.Manifest.permission.INTERNET); + Shadows.shadowOf(activity).denyPermissions(android.Manifest.permission.INTERNET); + + boolean canRequest = + permissionDelegate.canRequestPermission(android.Manifest.permission.INTERNET); + + assertTrue("After hasPermission sees that a permission is granted " + + "canRequestPermission should return true", + canRequest); + }); + } + + @Test + public void testCanRequestPermissionWhileGranted() { + mActivityScenarios.getScenario().onActivity(activity -> { + AndroidPermissionDelegate permissionDelegate = + new ActivityAndroidPermissionDelegate(new WeakReference(activity)); + performRequestPermission(permissionDelegate, Shadows.shadowOf(activity), + android.Manifest.permission.INTERNET, PackageManager.PERMISSION_DENIED); + Shadows.shadowOf(activity).grantPermissions(android.Manifest.permission.INTERNET); + + boolean canRequest = + permissionDelegate.canRequestPermission(android.Manifest.permission.INTERNET); + + assertTrue( + "If a permission is currently granted canRequestPermission should return true", + canRequest); + }); + } + + /** + * Calls {@link AndroidPermissionDelegate#requestPermissions} and {@link + * AndroidPermissionDelegate#handlePermissionResult} for a single permission. + */ + private void performRequestPermission(AndroidPermissionDelegate permissionDelegate, + ShadowActivity shadowActivity, String permission, int grantResult) { + permissionDelegate.requestPermissions( + new String[] {permission}, Mockito.mock(PermissionCallback.class)); + PermissionsRequest lastRequest = shadowActivity.getLastRequestedPermission(); + permissionDelegate.handlePermissionResult( + lastRequest.requestCode, lastRequest.requestedPermissions, new int[] {grantResult}); + } +} diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java b/chromium/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java index 09724c4210f..2698c6be83e 100644 --- a/chromium/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java +++ b/chromium/ui/android/junit/src/org/chromium/ui/base/LocalizationUtilsTest.java @@ -4,12 +4,12 @@ package org.chromium.ui.base; -import android.support.test.filters.SmallTest; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import androidx.test.filters.SmallTest; + import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.annotation.Config; diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java b/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java index 49e622b471b..cd5fe373955 100644 --- a/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java +++ b/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java @@ -5,6 +5,8 @@ package org.chromium.ui.base; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import android.net.Uri; import android.webkit.MimeTypeMap; @@ -16,8 +18,12 @@ import org.robolectric.annotation.Config; import org.robolectric.shadows.ShadowMimeTypeMap; import org.chromium.base.ContextUtils; +import org.chromium.base.PathUtils; import org.chromium.base.test.BaseRobolectricTestRunner; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -153,4 +159,42 @@ public class SelectFileDialogTest { assertEquals(task.mFilePaths[1].toString(), "///storage/emulated/0/DCIM/Camera/IMG_1.jpg"); } + + @Test + public void testFilePathSelected() throws IOException { + SelectFileDialog selectFileDialog = new SelectFileDialog(0); + PathUtils.setPrivateDataDirectorySuffix("test"); + String dataDir = new File(PathUtils.getDataDirectory()).getCanonicalPath(); + + SelectFileDialog.FilePathSelectedTask task = selectFileDialog.new FilePathSelectedTask( + ContextUtils.getApplicationContext(), dataDir, null); + assertFalse(task.doInBackground()); + + task = selectFileDialog.new FilePathSelectedTask( + ContextUtils.getApplicationContext(), dataDir + "/tmp/xyz.jpg", null); + assertFalse(task.doInBackground()); + + task = selectFileDialog.new FilePathSelectedTask( + ContextUtils.getApplicationContext(), dataDir + "/../xyz.jpg", null); + assertTrue(task.doInBackground()); + + task = selectFileDialog.new FilePathSelectedTask( + ContextUtils.getApplicationContext(), dataDir + "/tmp/../xyz.jpg", null); + assertFalse(task.doInBackground()); + + task = selectFileDialog.new FilePathSelectedTask( + ContextUtils.getApplicationContext(), "/data/local/tmp.jpg", null); + assertTrue(task.doInBackground()); + + Path path = new File(dataDir).toPath(); + String parent = path.getParent().toString(); + String lastComponent = path.getName(path.getNameCount() - 1).toString(); + task = selectFileDialog.new FilePathSelectedTask(ContextUtils.getApplicationContext(), + parent + "/./" + lastComponent + "/xyz.jpg", null); + assertFalse(task.doInBackground()); + + task = selectFileDialog.new FilePathSelectedTask(ContextUtils.getApplicationContext(), + dataDir + "/../" + lastComponent + "/xyz.jpg", null); + assertFalse(task.doInBackground()); + } } diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/TestActivity.java b/chromium/ui/android/junit/src/org/chromium/ui/base/TestActivity.java new file mode 100644 index 00000000000..aaabcf4097f --- /dev/null +++ b/chromium/ui/android/junit/src/org/chromium/ui/base/TestActivity.java @@ -0,0 +1,14 @@ +// Copyright 2020 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.ui.base; + +import androidx.appcompat.app.AppCompatActivity; + +/** + * Activity used in {@code ui/base} tests. + * <p> + * This activity is declared in {@code ui/android/junit/AndroidManifest.xml}. + */ +public class TestActivity extends AppCompatActivity {} diff --git a/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java b/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java index 4b033999efa..8a13da1e3c3 100644 --- a/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java +++ b/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java @@ -15,7 +15,6 @@ import org.junit.runner.RunWith; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; import org.robolectric.shadow.api.Shadow; -import org.robolectric.shadows.ShadowStateListDrawable; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.ui.shadows.ShadowAnimatedStateListDrawable; @@ -31,23 +30,7 @@ public class StateListDrawableBuilderTest { private static final int DEFAULT_DRAWABLE = 45678; @Test - @Config(sdk = 19) - public void testPreL() { - StateListDrawableBuilder b = new StateListDrawableBuilder(RuntimeEnvironment.application); - b.addState(CHECKED_DRAWABLE, android.R.attr.state_checked); - b.addState(DEFAULT_DRAWABLE, WILDCARD_STATE); - StateListDrawable result = b.build(); - assertEquals(result.getClass(), StateListDrawable.class); - ShadowStateListDrawable drawable = shadowOf(result); - assertEquals(CHECKED_DRAWABLE, - shadowOf(drawable.getDrawableForState(CHECKED_STATE)).getCreatedFromResId()); - assertEquals(DEFAULT_DRAWABLE, - shadowOf(drawable.getDrawableForState(WILDCARD_STATE)).getCreatedFromResId()); - } - - @Test - @Config(sdk = 21) - public void testPostL() { + public void testBuild() { StateListDrawableBuilder b = new StateListDrawableBuilder(RuntimeEnvironment.application); b.addState(CHECKED_DRAWABLE, android.R.attr.state_checked); b.addState(DEFAULT_DRAWABLE, WILDCARD_STATE); diff --git a/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/ModalDialogManagerTest.java b/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/ModalDialogManagerTest.java index 0e7e800f582..f23cb9c94ee 100644 --- a/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/ModalDialogManagerTest.java +++ b/chromium/ui/android/junit/src/org/chromium/ui/modaldialog/ModalDialogManagerTest.java @@ -79,16 +79,19 @@ public class ModalDialogManagerTest { @Feature({"ModalDialogManagerObserver"}) public void testModalDialogObserver() { // Show two dialogs and make sure show is only called on one until it is hidden. - verify(mObserver, times(0)).onDialogShown(mDialogModels.get(0)); + verify(mObserver, times(0)).onDialogAdded(mDialogModels.get(0)); mModalDialogManager.showDialog(mDialogModels.get(0), ModalDialogType.APP); mModalDialogManager.showDialog(mDialogModels.get(1), ModalDialogType.APP); - verify(mObserver, times(1)).onDialogShown(mDialogModels.get(0)); - verify(mObserver, times(0)).onDialogShown(mDialogModels.get(1)); + verify(mObserver, times(1)).onDialogAdded(mDialogModels.get(0)); + verify(mObserver, times(0)).onDialogAdded(mDialogModels.get(1)); - verify(mObserver, times(0)).onDialogHidden(mDialogModels.get(0)); + verify(mObserver, times(0)).onDialogDismissed(mDialogModels.get(0)); mModalDialogManager.dismissDialog(mDialogModels.get(0), ModalDialogType.APP); - verify(mObserver, times(1)).onDialogHidden(mDialogModels.get(0)); - verify(mObserver, times(1)).onDialogShown(mDialogModels.get(1)); + verify(mObserver, times(1)).onDialogDismissed(mDialogModels.get(0)); + verify(mObserver, times(1)).onDialogAdded(mDialogModels.get(1)); + + mModalDialogManager.dismissDialog(mDialogModels.get(1), ModalDialogType.APP); + verify(mObserver, times(1)).onLastDialogDismissed(); } /** Tests showing a dialog when no dialog is currently showing. */ diff --git a/chromium/ui/android/view_android.cc b/chromium/ui/android/view_android.cc index 7d2e6ded2f0..9de5d840506 100644 --- a/chromium/ui/android/view_android.cc +++ b/chromium/ui/android/view_android.cc @@ -14,9 +14,11 @@ #include "base/stl_util.h" #include "cc/layers/layer.h" #include "components/viz/common/frame_sinks/copy_output_request.h" +#include "third_party/skia/include/core/SkBitmap.h" #include "ui/android/event_forwarder.h" #include "ui/android/ui_android_jni_headers/ViewAndroidDelegate_jni.h" #include "ui/android/window_android.h" +#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h" #include "ui/base/layout.h" #include "ui/events/android/drag_event_android.h" @@ -25,6 +27,7 @@ #include "ui/events/android/key_event_android.h" #include "ui/events/android/motion_event_android.h" #include "ui/gfx/android/java_bitmap.h" +#include "ui/gfx/geometry/point.h" #include "url/gurl.h" namespace ui { @@ -389,25 +392,25 @@ bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext, jimage); } -void ViewAndroid::OnCursorChanged(int type, - const SkBitmap& custom_image, - const gfx::Point& hotspot) { +void ViewAndroid::OnCursorChanged(const Cursor& cursor) { ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); if (delegate.is_null()) return; JNIEnv* env = base::android::AttachCurrentThread(); - if (type == static_cast<int>(ui::mojom::CursorType::kCustom)) { - if (custom_image.drawsNothing()) { + if (cursor.type() == mojom::CursorType::kCustom) { + const SkBitmap& bitmap = cursor.custom_bitmap(); + const gfx::Point& hotspot = cursor.custom_hotspot(); + if (bitmap.drawsNothing()) { Java_ViewAndroidDelegate_onCursorChanged( - env, delegate, static_cast<int>(ui::mojom::CursorType::kPointer)); + env, delegate, static_cast<int>(mojom::CursorType::kPointer)); return; } - ScopedJavaLocalRef<jobject> java_bitmap = - gfx::ConvertToJavaBitmap(&custom_image); + ScopedJavaLocalRef<jobject> java_bitmap = gfx::ConvertToJavaBitmap(&bitmap); Java_ViewAndroidDelegate_onCursorChangedToCustom(env, delegate, java_bitmap, hotspot.x(), hotspot.y()); } else { - Java_ViewAndroidDelegate_onCursorChanged(env, delegate, type); + Java_ViewAndroidDelegate_onCursorChanged(env, delegate, + static_cast<int>(cursor.type())); } } @@ -461,6 +464,16 @@ void ViewAndroid::OnBrowserControlsHeightChanged() { } } +void ViewAndroid::OnVerticalScrollDirectionChanged(bool direction_up, + float current_scroll_ratio) { + ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate()); + if (delegate.is_null()) + return; + JNIEnv* env = base::android::AttachCurrentThread(); + Java_ViewAndroidDelegate_onVerticalScrollDirectionChanged( + env, delegate, direction_up, current_scroll_ratio); +} + void ViewAndroid::OnSizeChanged(int width, int height) { // Match-parent view must not receive size events. DCHECK(!match_parent()); diff --git a/chromium/ui/android/view_android.h b/chromium/ui/android/view_android.h index cf88a186583..5c989d6b05e 100644 --- a/chromium/ui/android/view_android.h +++ b/chromium/ui/android/view_android.h @@ -18,8 +18,6 @@ #include "ui/android/view_android_observer.h" #include "ui/gfx/geometry/rect_f.h" -class SkBitmap; - namespace cc { class Layer; } @@ -34,6 +32,7 @@ class CopyOutputRequest; } namespace ui { +class Cursor; class DragEventAndroid; class EventForwarder; class EventHandlerAndroid; @@ -154,9 +153,7 @@ class UI_ANDROID_EXPORT ViewAndroid { void OnSizeChanged(int width, int height); void OnPhysicalBackingSizeChanged(const gfx::Size& size); - void OnCursorChanged(int type, - const SkBitmap& custom_image, - const gfx::Point& hotspot); + void OnCursorChanged(const Cursor& cursor); void OnBackgroundColorChanged(unsigned int color); void OnTopControlsChanged(float top_controls_offset, float top_content_offset, @@ -164,6 +161,11 @@ class UI_ANDROID_EXPORT ViewAndroid { void OnBottomControlsChanged(float bottom_controls_offset, float bottom_controls_min_height_offset); void OnBrowserControlsHeightChanged(); + // |current_scroll_ratio| is the ratio of vertical scroll in [0, 1] range. + // Scroll at top of page is 0, and bottom of page is 1. It is defined as 0 + // if page is not scrollable, though this should not be called in that case. + void OnVerticalScrollDirectionChanged(bool direction_up, + float current_scroll_ratio); // Gets the Visual Viewport inset to apply in physical pixels. int GetViewportInsetBottom(); diff --git a/chromium/ui/android/view_android_unittests.cc b/chromium/ui/android/view_android_unittests.cc index d42e19b6484..b24c1ad5285 100644 --- a/chromium/ui/android/view_android_unittests.cc +++ b/chromium/ui/android/view_android_unittests.cc @@ -76,8 +76,8 @@ class ViewAndroidBoundsTest : public testing::Test { ui::MotionEventAndroid::Pointer pointer0(0, x, y, 0, 0, 0, 0, 0); ui::MotionEventAndroid::Pointer pointer1(0, 0, 0, 0, 0, 0, 0, 0); ui::MotionEventAndroid event(nullptr, JavaParamRef<jobject>(nullptr), 1.f, - 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, false, - &pointer0, &pointer1); + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + false, &pointer0, &pointer1); root_.OnTouchEvent(event); } |