diff options
Diffstat (limited to 'chromium/components/autofill/android')
-rw-r--r-- | chromium/components/autofill/android/BUILD.gn | 47 | ||||
-rw-r--r-- | chromium/components/autofill/android/OWNERS | 6 | ||||
-rw-r--r-- | chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java | 157 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/BUILD.gn | 53 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/OWNERS (renamed from chromium/components/autofill/android/junit/OWNERS) | 0 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/autofill_provider_android.cc (renamed from chromium/components/autofill/android/autofill_provider_android.cc) | 61 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/autofill_provider_android.h (renamed from chromium/components/autofill/android/autofill_provider_android.h) | 16 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/form_data_android.cc (renamed from chromium/components/autofill/android/form_data_android.cc) | 6 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/form_data_android.h (renamed from chromium/components/autofill/android/form_data_android.h) | 6 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/form_field_data_android.cc (renamed from chromium/components/autofill/android/form_field_data_android.cc) | 11 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/form_field_data_android.h (renamed from chromium/components/autofill/android/form_field_data_android.h) | 6 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java (renamed from chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java) | 0 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java (renamed from chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java) | 0 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java (renamed from chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java) | 340 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java (renamed from chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderUMA.java) | 0 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java (renamed from chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java) | 0 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java (renamed from chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java) | 20 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/junit/BUILD.gn (renamed from chromium/components/autofill/android/junit/BUILD.gn) | 8 | ||||
-rw-r--r-- | chromium/components/autofill/android/provider/junit/src/org/chromium/components/autofill/AutofillProviderTest.java (renamed from chromium/components/autofill/android/junit/src/org/chromium/components/autofill/AutofillProviderImplTest.java) | 13 |
19 files changed, 462 insertions, 288 deletions
diff --git a/chromium/components/autofill/android/BUILD.gn b/chromium/components/autofill/android/BUILD.gn index f246baeb159..e29c613e982 100644 --- a/chromium/components/autofill/android/BUILD.gn +++ b/chromium/components/autofill/android/BUILD.gn @@ -41,6 +41,7 @@ android_library("autofill_java") { "//base:base_java", "//content/public/android:content_java", "//third_party/android_deps:android_support_v7_appcompat_java", + "//third_party/android_deps:androidx_appcompat_appcompat_resources_java", "//ui/android:ui_java", ] sources = [ @@ -54,49 +55,3 @@ android_library("autofill_java") { ] srcjar_deps = [ ":autofill_core_browser_java_enums" ] } - -android_library("provider_java") { - deps = [ - "//base:base_java", - "//base:jni_java", - "//components/autofill/core/common/mojom:mojo_types_java", - "//components/version_info/android:version_constants_java", - "//content/public/android:content_java", - "//third_party/android_deps:androidx_annotation_annotation_java", - "//ui/android:ui_java", - ] - annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] - sources = [ - "java/src/org/chromium/components/autofill/AutofillActionModeCallback.java", - "java/src/org/chromium/components/autofill/AutofillManagerWrapper.java", - "java/src/org/chromium/components/autofill/AutofillProvider.java", - "java/src/org/chromium/components/autofill/AutofillProviderImpl.java", - "java/src/org/chromium/components/autofill/AutofillProviderUMA.java", - "java/src/org/chromium/components/autofill/FormData.java", - "java/src/org/chromium/components/autofill/FormFieldData.java", - ] -} - -generate_jni("jni_headers") { - sources = [ - "java/src/org/chromium/components/autofill/AutofillProvider.java", - "java/src/org/chromium/components/autofill/FormData.java", - "java/src/org/chromium/components/autofill/FormFieldData.java", - ] -} - -static_library("provider") { - sources = [ - "autofill_provider_android.cc", - "autofill_provider_android.h", - "form_data_android.cc", - "form_data_android.h", - "form_field_data_android.cc", - "form_field_data_android.h", - ] - deps = [ - ":jni_headers", - "//components/autofill/core/browser:browser", - "//content/public/browser", - ] -} diff --git a/chromium/components/autofill/android/OWNERS b/chromium/components/autofill/android/OWNERS index 7f956d082c5..475b1659fb0 100644 --- a/chromium/components/autofill/android/OWNERS +++ b/chromium/components/autofill/android/OWNERS @@ -1,8 +1,2 @@ file://ui/android/OWNERS -# Files related to integration with system autofill -per-file *autofill_provider*=michaelbai@chromium.org -per-file *AutofillProvider*=michaelbai@chromium.org -per-file *AutofillManagerWrapper*=michaelbai@chromium.org -per-file *form*=michaelbai@chromium.org -per-file *Form*=michaelbai@chromium.org diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java b/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java deleted file mode 100644 index a7d05d359a4..00000000000 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProvider.java +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2017 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.components.autofill; - -import android.util.SparseArray; -import android.view.ViewGroup; -import android.view.ViewStructure; -import android.view.autofill.AutofillValue; - -import org.chromium.base.annotations.CalledByNative; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.NativeMethods; -import org.chromium.content_public.browser.WebContents; - -/** - * This class defines interface of AutofillProvider, it doesn't use chrome's - * autofill service or suggestion UI, instead, uses third party autofill service - * by knowing of format structure and user's input. - * - * AutofillProvider handles one autofill session at time, each call of - * queryFormFieldAutofill cancels previous session and starts a new one, the - * calling of other methods shall associate with current session. - * - */ -@JNINamespace("autofill") -public abstract class AutofillProvider { - public AutofillProvider() {} - - /** - * Invoked when container view is changed. - * - * @param containerView new container view. - */ - public abstract void onContainerViewChanged(ViewGroup containerView); - - public abstract void setWebContents(WebContents webContents); - - /** - * Invoked when autofill value is available, AutofillProvider shall fill the - * form with the provided values. - * - * @param values the array of autofill values, the key is virtual id of form - * field. - */ - public abstract void autofill(final SparseArray<AutofillValue> values); - - /** - * Invoked when autofill service needs the form structure. - * - * @param structure see View.onProvideAutofillVirtualStructure() - * @param flags see View.onProvideAutofillVirtualStructure() - */ - public abstract void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags); - - /** - * @return whether query autofill suggestion. - */ - public abstract boolean shouldQueryAutofillSuggestion(); - - public abstract void queryAutofillSuggestion(); - - /** - * Invoked when filling form is need. AutofillProvider shall ask autofill - * service for the values with which to fill the form. - * - * @param formData the form needs to fill. - * @param focus the index of focus field in formData - * @param x the boundary of focus field. - * @param y the boundary of focus field. - * @param width the boundary of focus field. - * @param height the boundary of focus field. - */ - @CalledByNative - protected abstract void startAutofillSession( - FormData formData, int focus, float x, float y, float width, float height); - - /** - * Invoked when form field's value is changed. - * - * @param index index of field in current form. - * @param x the boundary of focus field. - * @param y the boundary of focus field. - * @param width the boundary of focus field. - * @param height the boundary of focus field. - * - */ - @CalledByNative - protected abstract void onFormFieldDidChange( - int index, float x, float y, float width, float height); - - /** - * Invoked when text field is scrolled. - * - * @param index index of field in current form. - * @param x the boundary of focus field. - * @param y the boundary of focus field. - * @param width the boundary of focus field. - * @param height the boundary of focus field. - * - */ - @CalledByNative - protected abstract void onTextFieldDidScroll( - int index, float x, float y, float width, float height); - - /** - * Invoked when current form will be submitted. - * @param submissionSource the submission source, could be any member defined in - * SubmissionSource.java - */ - @CalledByNative - protected abstract void onFormSubmitted(int submissionSource); - - /** - * Invoked when focus field changed. - * - * @param focusOnForm whether focus is still on form. - * @param focusItem the index of field has focus - * @param x the boundary of focus field. - * @param y the boundary of focus field. - * @param width the boundary of focus field. - * @param height the boundary of focus field. - */ - @CalledByNative - protected abstract void onFocusChanged( - boolean focusOnForm, int focusItem, float x, float y, float width, float height); - - /** - * Send form to renderer for filling. - * - * @param nativeAutofillProvider the native autofill provider. - * @param formData the form to fill. - */ - protected void autofill(long nativeAutofillProvider, FormData formData) { - AutofillProviderJni.get().onAutofillAvailable( - nativeAutofillProvider, AutofillProvider.this, formData); - } - - /** - * Invoked when current query need to be reset. - */ - @CalledByNative - protected abstract void reset(); - - @CalledByNative - protected abstract void setNativeAutofillProvider(long nativeAutofillProvider); - - @CalledByNative - protected abstract void onDidFillAutofillFormData(); - - @NativeMethods - interface Natives { - void onAutofillAvailable( - long nativeAutofillProviderAndroid, AutofillProvider caller, FormData formData); - } -} diff --git a/chromium/components/autofill/android/provider/BUILD.gn b/chromium/components/autofill/android/provider/BUILD.gn new file mode 100644 index 00000000000..263b88afd5e --- /dev/null +++ b/chromium/components/autofill/android/provider/BUILD.gn @@ -0,0 +1,53 @@ +# 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. + +import("//build/config/android/rules.gni") +import("//build/config/locales.gni") + +android_library("java") { + deps = [ + "//base:base_java", + "//base:jni_java", + "//components/autofill/android:autofill_java", + "//components/autofill/core/common/mojom:mojo_types_java", + "//components/version_info/android:version_constants_java", + "//content/public/android:content_java", + "//third_party/android_deps:androidx_annotation_annotation_java", + "//ui/android:ui_java", + ] + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] + sources = [ + "java/src/org/chromium/components/autofill/AutofillActionModeCallback.java", + "java/src/org/chromium/components/autofill/AutofillManagerWrapper.java", + "java/src/org/chromium/components/autofill/AutofillProvider.java", + "java/src/org/chromium/components/autofill/AutofillProviderUMA.java", + "java/src/org/chromium/components/autofill/FormData.java", + "java/src/org/chromium/components/autofill/FormFieldData.java", + ] +} + +generate_jni("jni_headers") { + sources = [ + "java/src/org/chromium/components/autofill/AutofillProvider.java", + "java/src/org/chromium/components/autofill/FormData.java", + "java/src/org/chromium/components/autofill/FormFieldData.java", + ] +} + +static_library("provider") { + sources = [ + "autofill_provider_android.cc", + "autofill_provider_android.h", + "form_data_android.cc", + "form_data_android.h", + "form_field_data_android.cc", + "form_field_data_android.h", + ] + deps = [ + ":jni_headers", + "//components/autofill/core/browser:browser", + "//content/public/browser", + "//ui/android", + ] +} diff --git a/chromium/components/autofill/android/junit/OWNERS b/chromium/components/autofill/android/provider/OWNERS index 44a22b15980..44a22b15980 100644 --- a/chromium/components/autofill/android/junit/OWNERS +++ b/chromium/components/autofill/android/provider/OWNERS diff --git a/chromium/components/autofill/android/autofill_provider_android.cc b/chromium/components/autofill/android/provider/autofill_provider_android.cc index 76129371d95..408ff96c130 100644 --- a/chromium/components/autofill/android/autofill_provider_android.cc +++ b/chromium/components/autofill/android/provider/autofill_provider_android.cc @@ -2,27 +2,30 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/android/autofill_provider_android.h" +#include "components/autofill/android/provider/autofill_provider_android.h" #include <memory> #include "base/android/jni_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" -#include "components/autofill/android/form_data_android.h" -#include "components/autofill/android/jni_headers/AutofillProvider_jni.h" +#include "components/autofill/android/provider/form_data_android.h" +#include "components/autofill/android/provider/jni_headers/AutofillProvider_jni.h" #include "components/autofill/core/browser/autofill_driver.h" #include "components/autofill/core/browser/autofill_handler_proxy.h" #include "components/autofill/core/common/autofill_constants.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" +#include "ui/android/window_android.h" #include "ui/gfx/geometry/rect_f.h" using base::android::AttachCurrentThread; +using base::android::ConvertJavaStringToUTF16; using base::android::ConvertUTF16ToJavaString; using base::android::ConvertUTF8ToJavaString; using base::android::JavaRef; using base::android::ScopedJavaLocalRef; +using base::android::ToJavaArrayOfStrings; using content::BrowserThread; using content::WebContents; using gfx::RectF; @@ -85,6 +88,21 @@ void AutofillProviderAndroid::OnQueryFormFieldAutofill( // ignored if the form is same. if (ShouldStartNewSession(handler, form)) StartNewSession(handler, form, field, bounding_box); + + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) + return; + + if (!field.datalist_values.empty()) { + ScopedJavaLocalRef<jobjectArray> jdatalist_values = + ToJavaArrayOfStrings(env, field.datalist_values); + ScopedJavaLocalRef<jobjectArray> jdatalist_labels = + ToJavaArrayOfStrings(env, field.datalist_labels); + Java_AutofillProvider_showDatalistPopup( + env, obj, jdatalist_values, jdatalist_labels, + field.text_direction == base::i18n::RIGHT_TO_LEFT); + } } bool AutofillProviderAndroid::ShouldStartNewSession( @@ -141,6 +159,31 @@ void AutofillProviderAndroid::OnAutofillAvailable(JNIEnv* env, } } +void AutofillProviderAndroid::OnAcceptDataListSuggestion(JNIEnv* env, + jobject jcaller, + jstring value) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (auto* handler = handler_.get()) { + RendererShouldAcceptDataListSuggestion( + handler, ConvertJavaStringToUTF16(env, value)); + } +} + +void AutofillProviderAndroid::SetAnchorViewRect(JNIEnv* env, + jobject jcaller, + jobject anchor_view, + jfloat x, + jfloat y, + jfloat width, + jfloat height) { + ui::ViewAndroid* view_android = web_contents_->GetNativeView(); + if (!view_android) + return; + + view_android->SetAnchorRect(ScopedJavaLocalRef<jobject>(env, anchor_view), + gfx::RectF(x, y, width, height)); +} + void AutofillProviderAndroid::OnTextFieldDidChange( AutofillHandlerProxy* handler, const FormData& form, @@ -314,6 +357,18 @@ void AutofillProviderAndroid::OnFormsSeen(AutofillHandlerProxy* handler, FireSuccessfulSubmission(pending_submission_source_); } +void AutofillProviderAndroid::OnHidePopup(AutofillHandlerProxy* handler) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + if (handler == handler_.get()) { + JNIEnv* env = AttachCurrentThread(); + ScopedJavaLocalRef<jobject> obj = java_ref_.get(env); + if (obj.is_null()) + return; + + Java_AutofillProvider_hidePopup(env, obj); + } +} + void AutofillProviderAndroid::Reset(AutofillHandlerProxy* handler) { DCHECK_CURRENTLY_ON(BrowserThread::UI); if (handler == handler_.get()) { diff --git a/chromium/components/autofill/android/autofill_provider_android.h b/chromium/components/autofill/android/provider/autofill_provider_android.h index 270a05eea00..b0830e2338e 100644 --- a/chromium/components/autofill/android/autofill_provider_android.h +++ b/chromium/components/autofill/android/provider/autofill_provider_android.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_ANDROID_AUTOFILL_PROVIDER_ANDROID_H_ -#define COMPONENTS_AUTOFILL_ANDROID_AUTOFILL_PROVIDER_ANDROID_H_ +#ifndef COMPONENTS_AUTOFILL_ANDROID_PROVIDER_AUTOFILL_PROVIDER_ANDROID_H_ +#define COMPONENTS_AUTOFILL_ANDROID_PROVIDER_AUTOFILL_PROVIDER_ANDROID_H_ #include "base/android/jni_weak_ref.h" #include "base/memory/weak_ptr.h" @@ -67,11 +67,21 @@ class AutofillProviderAndroid : public AutofillProvider { void OnFormsSeen(AutofillHandlerProxy* handler, const std::vector<FormData>& forms, const base::TimeTicks timestamp) override; + void OnHidePopup(AutofillHandlerProxy* handler) override; void Reset(AutofillHandlerProxy* handler) override; // Methods called by Java. void OnAutofillAvailable(JNIEnv* env, jobject jcaller, jobject form_data); + void OnAcceptDataListSuggestion(JNIEnv* env, jobject jcaller, jstring value); + + void SetAnchorViewRect(JNIEnv* env, + jobject jcaller, + jobject anchor_view, + jfloat x, + jfloat y, + jfloat width, + jfloat height); private: void FireSuccessfulSubmission(mojom::SubmissionSource source); @@ -114,4 +124,4 @@ class AutofillProviderAndroid : public AutofillProvider { }; } // namespace autofill -#endif // COMPONENTS_AUTOFILL_ANDROID_AUTOFILL_PROVIDER_ANDROID_H_ +#endif // COMPONENTS_AUTOFILL_ANDROID_PROVIDER_AUTOFILL_PROVIDER_ANDROID_H_ diff --git a/chromium/components/autofill/android/form_data_android.cc b/chromium/components/autofill/android/provider/form_data_android.cc index c91a0c62472..7f24f8967c5 100644 --- a/chromium/components/autofill/android/form_data_android.cc +++ b/chromium/components/autofill/android/provider/form_data_android.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/android/form_data_android.h" +#include "components/autofill/android/provider/form_data_android.h" #include "base/android/jni_string.h" -#include "components/autofill/android/form_field_data_android.h" -#include "components/autofill/android/jni_headers/FormData_jni.h" +#include "components/autofill/android/provider/form_field_data_android.h" +#include "components/autofill/android/provider/jni_headers/FormData_jni.h" #include "components/autofill/core/browser/form_structure.h" using base::android::AttachCurrentThread; diff --git a/chromium/components/autofill/android/form_data_android.h b/chromium/components/autofill/android/provider/form_data_android.h index a2b33c8d917..8882a788673 100644 --- a/chromium/components/autofill/android/form_data_android.h +++ b/chromium/components/autofill/android/provider/form_data_android.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_ANDROID_FORM_DATA_ANDROID_H_ -#define COMPONENTS_AUTOFILL_ANDROID_FORM_DATA_ANDROID_H_ +#ifndef COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_DATA_ANDROID_H_ +#define COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_DATA_ANDROID_H_ #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" @@ -70,4 +70,4 @@ class FormDataAndroid { } // namespace autofill -#endif // COMPONENTS_AUTOFILL_ANDROID_FORM_DATA_ANDROID_H_ +#endif // COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_DATA_ANDROID_H_ diff --git a/chromium/components/autofill/android/form_field_data_android.cc b/chromium/components/autofill/android/provider/form_field_data_android.cc index da134267220..ee5471f5239 100644 --- a/chromium/components/autofill/android/form_field_data_android.cc +++ b/chromium/components/autofill/android/provider/form_field_data_android.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/autofill/android/form_field_data_android.h" +#include "components/autofill/android/provider/form_field_data_android.h" #include "base/android/jni_array.h" #include "base/android/jni_string.h" -#include "components/autofill/android/jni_headers/FormFieldData_jni.h" +#include "components/autofill/android/provider/jni_headers/FormFieldData_jni.h" #include "components/autofill/core/common/autofill_util.h" using base::android::AttachCurrentThread; @@ -50,6 +50,10 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() { if (!heuristic_type_.IsUnknown()) jheuristic_type = ConvertUTF8ToJavaString(env, heuristic_type_.ToString()); + ScopedJavaLocalRef<jobjectArray> jdatalist_values = + ToJavaArrayOfStrings(env, field_ptr_->datalist_values); + ScopedJavaLocalRef<jobjectArray> jdatalist_labels = + ToJavaArrayOfStrings(env, field_ptr_->datalist_labels); obj = Java_FormFieldData_createFormFieldData( env, jname, jlabel, jvalue, jautocomplete_attr, @@ -57,7 +61,8 @@ ScopedJavaLocalRef<jobject> FormFieldDataAndroid::GetJavaPeer() { joption_values, joption_contents, IsCheckable(field_ptr_->check_status), IsChecked(field_ptr_->check_status), field_ptr_->max_length, jheuristic_type, field_ptr_->bounds.x(), field_ptr_->bounds.y(), - field_ptr_->bounds.right(), field_ptr_->bounds.bottom()); + field_ptr_->bounds.right(), field_ptr_->bounds.bottom(), + jdatalist_values, jdatalist_labels); java_ref_ = JavaObjectWeakGlobalRef(env, obj); } return obj; diff --git a/chromium/components/autofill/android/form_field_data_android.h b/chromium/components/autofill/android/provider/form_field_data_android.h index e882bb49704..a12ad979bfe 100644 --- a/chromium/components/autofill/android/form_field_data_android.h +++ b/chromium/components/autofill/android/provider/form_field_data_android.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef COMPONENTS_AUTOFILL_ANDROID_FORM_FIELD_DATA_ANDROID_H_ -#define COMPONENTS_AUTOFILL_ANDROID_FORM_FIELD_DATA_ANDROID_H_ +#ifndef COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_FIELD_DATA_ANDROID_H_ +#define COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_FIELD_DATA_ANDROID_H_ #include "base/android/jni_weak_ref.h" #include "base/android/scoped_java_ref.h" @@ -39,4 +39,4 @@ class FormFieldDataAndroid { } // namespace autofill -#endif // COMPONENTS_AUTOFILL_ANDROID_FORM_FIELD_DATA_ANDROID_H_ +#endif // COMPONENTS_AUTOFILL_ANDROID_PROVIDER_FORM_FIELD_DATA_ANDROID_H_ diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java index 6921fcab52c..6921fcab52c 100644 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java +++ b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillActionModeCallback.java diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java index 0287ac38f97..0287ac38f97 100644 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java +++ b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillManagerWrapper.java diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java index e53188067c3..acbf7a61a22 100644 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderImpl.java +++ b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProvider.java @@ -19,18 +19,30 @@ import android.view.autofill.AutofillValue; import androidx.annotation.VisibleForTesting; +import org.chromium.base.ContextUtils; import org.chromium.base.Log; +import org.chromium.base.StrictModeContext; import org.chromium.base.ThreadUtils; -import org.chromium.base.annotations.DoNotInline; +import org.chromium.base.annotations.CalledByNative; +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; +import org.chromium.base.annotations.VerifiesOnO; import org.chromium.base.metrics.ScopedSysTraceEvent; import org.chromium.components.version_info.VersionConstants; import org.chromium.content_public.browser.WebContents; +import org.chromium.content_public.browser.WebContentsAccessibility; +import org.chromium.ui.DropdownItem; +import org.chromium.ui.base.ViewAndroidDelegate; import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.display.DisplayAndroid; /** - * This class uses Android autofill service to fill web form. All methods are - * supposed to be called in UI thread. + * This class works with Android autofill service to fill web form, it doesn't use chrome's + * autofill service or suggestion UI. All methods are supposed to be called in UI thread. + * + * AutofillProvider handles one autofill session at time, each call of + * queryFormFieldAutofill cancels previous session and starts a new one, the + * calling of other methods shall associate with current session. * * This class doesn't have 1:1 mapping to native AutofillProviderAndroid; the * normal ownership model is that this object is owned by the embedder-specific @@ -38,12 +50,13 @@ import org.chromium.ui.display.DisplayAndroid; * AutofillProviderAndroid is owned by the embedder-specific C++ WebContents * wrapper (e.g., native AwContents in //android_webview). * - * DoNotInline since it causes class verification errors, see crbug.com/991851. + * VerifiesOnO since it causes class verification errors, see crbug.com/991851. */ -@DoNotInline +@VerifiesOnO @TargetApi(Build.VERSION_CODES.O) -public class AutofillProviderImpl extends AutofillProvider { - private static final String TAG = "AutofillProviderImpl"; +@JNINamespace("autofill") +public class AutofillProvider { + private static final String TAG = "AutofillProvider"; private static class FocusField { public final short fieldIndex; public final Rect absBound; @@ -117,11 +130,15 @@ public class AutofillProviderImpl extends AutofillProvider { child.setAutofillValue(AutofillValue.forToggle(field.isChecked())); break; case FormFieldData.ControlType.TEXT: + case FormFieldData.ControlType.DATALIST: child.setAutofillType(View.AUTOFILL_TYPE_TEXT); child.setAutofillValue(AutofillValue.forText(field.getValue())); if (field.mMaxLength != 0) { builder.addAttribute("maxlength", String.valueOf(field.mMaxLength)); } + if (field.getControlType() == FormFieldData.ControlType.DATALIST) { + child.setAutofillOptions(field.mDatalistValues); + } break; default: break; @@ -151,6 +168,7 @@ public class AutofillProviderImpl extends AutofillProvider { field.setChecked(value.getToggleValue()); break; case FormFieldData.ControlType.TEXT: + case FormFieldData.ControlType.DATALIST: field.setAutofillValue((String) value.getTextValue()); break; default: @@ -188,6 +206,7 @@ public class AutofillProviderImpl extends AutofillProvider { case FormFieldData.ControlType.TOGGLE: return AutofillValue.forToggle(field.isChecked()); case FormFieldData.ControlType.TEXT: + case FormFieldData.ControlType.DATALIST: return AutofillValue.forText(field.getValue()); default: return null; @@ -240,17 +259,20 @@ public class AutofillProviderImpl extends AutofillProvider { private AutofillProviderUMA mAutofillUMA; private AutofillManagerWrapper.InputUIObserver mInputUIObserver; private long mAutofillTriggeredTimeMillis; + private Context mContext; + private AutofillPopup mDatalistPopup; + private WebContentsAccessibility mWebContentsAccessibility; + private View mAnchorView; - public AutofillProviderImpl(Context context, ViewGroup containerView, String providerName) { + public AutofillProvider(Context context, ViewGroup containerView, String providerName) { this(containerView, new AutofillManagerWrapper(context), context, providerName); } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public AutofillProviderImpl(ViewGroup containerView, AutofillManagerWrapper manager, + public AutofillProvider(ViewGroup containerView, AutofillManagerWrapper manager, Context context, String providerName) { mProviderName = providerName; - try (ScopedSysTraceEvent e = - ScopedSysTraceEvent.scoped("AutofillProviderImpl.constructor")) { + try (ScopedSysTraceEvent e = ScopedSysTraceEvent.scoped("AutofillProvider.constructor")) { assert Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; mAutofillManager = manager; mContainerView = containerView; @@ -266,15 +288,25 @@ public class AutofillProviderImpl extends AutofillProvider { } }; mAutofillManager.addInputUIObserver(mInputUIObserver); + mContext = context; } } - @Override + /** + * Invoked when container view is changed. + * + * @param containerView new container view. + */ public void onContainerViewChanged(ViewGroup containerView) { mContainerView = containerView; } - @Override + /** + * Invoked when autofill service needs the form structure. + * + * @param structure see View.onProvideAutofillVirtualStructure() + * @param flags see View.onProvideAutofillVirtualStructure() + */ public void onProvideAutoFillVirtualStructure(ViewStructure structure, int flags) { // This method could be called for the session started by the native // control outside of the scope of autofill, e.g. the URL bar, in this case, we simply @@ -295,7 +327,13 @@ public class AutofillProviderImpl extends AutofillProvider { mAutofillUMA.onVirtualStructureProvided(); } - @Override + /** + * Invoked when autofill value is available, AutofillProvider shall fill the + * form with the provided values. + * + * @param values the array of autofill values, the key is virtual id of form + * field. + */ public void autofill(final SparseArray<AutofillValue> values) { if (mNativeAutofillProvider != 0 && mRequest != null && mRequest.autofill((values))) { autofill(mNativeAutofillProvider, mRequest.mFormData); @@ -306,13 +344,14 @@ public class AutofillProviderImpl extends AutofillProvider { } } - @Override + /** + * @return whether query autofill suggestion. + */ public boolean shouldQueryAutofillSuggestion() { return mRequest != null && mRequest.getFocusField() != null && !mAutofillManager.isAutofillInputUIShowing(); } - @Override public void queryAutofillSuggestion() { if (shouldQueryAutofillSuggestion()) { FocusField focusField = mRequest.getFocusField(); @@ -321,27 +360,50 @@ public class AutofillProviderImpl extends AutofillProvider { } } - @Override + /** + * Invoked when filling form is need. AutofillProvider shall ask autofill + * service for the values with which to fill the form. + * + * @param formData the form needs to fill. + * @param focus the index of focus field in formData + * @param x the boundary of focus field. + * @param y the boundary of focus field. + * @param width the boundary of focus field. + * @param height the boundary of focus field. + */ + @CalledByNative public void startAutofillSession( FormData formData, int focus, float x, float y, float width, float height) { // Check focusField inside short value? - // Autofill Manager might have session that wasn't started by AutofillProviderImpl, + // Autofill Manager might have session that wasn't started by AutofillProvider, // we just always cancel existing session here. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) { mAutofillManager.cancel(); } - mAutofillManager.notifyNewSessionStarted(); + Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height)); - if (mRequest != null) notifyViewExitBeforeDestoryRequest(); + if (mRequest != null) notifyViewExitBeforeDestroyRequest(); transformFormFieldToContainViewCoordinates(formData); mRequest = new AutofillRequest(formData, new FocusField((short) focus, absBound)); int virtualId = mRequest.getVirtualId((short) focus); - mAutofillManager.notifyVirtualViewEntered(mContainerView, virtualId, absBound); + notifyVirtualViewEntered(mContainerView, virtualId, absBound); mAutofillUMA.onSessionStarted(mAutofillManager.isDisabled()); mAutofillTriggeredTimeMillis = System.currentTimeMillis(); + + mAutofillManager.notifyNewSessionStarted(); } - @Override + /** + * Invoked when form field's value is changed. + * + * @param index index of field in current form. + * @param x the boundary of focus field. + * @param y the boundary of focus field. + * @param width the boundary of focus field. + * @param height the boundary of focus field. + * + */ + @CalledByNative public void onFormFieldDidChange(int index, float x, float y, float width, float height) { // Check index inside short value? if (mRequest == null) return; @@ -358,17 +420,27 @@ public class AutofillProviderImpl extends AutofillProvider { int virtualId = mRequest.getVirtualId(sIndex); Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height)); if (!focusField.absBound.equals(absBound)) { - mAutofillManager.notifyVirtualViewExited(mContainerView, virtualId); - mAutofillManager.notifyVirtualViewEntered(mContainerView, virtualId, absBound); + notifyVirtualViewExited(mContainerView, virtualId); + notifyVirtualViewEntered(mContainerView, virtualId, absBound); // Update focus field position. mRequest.setFocusField(new FocusField(focusField.fieldIndex, absBound)); } } - notifyVirtualValueChanged(index); + notifyVirtualValueChanged(index, /* forceNotify = */ false); mAutofillUMA.onUserChangeFieldValue(mRequest.getField(sIndex).hasPreviouslyAutofilled()); } - @Override + /** + * Invoked when text field is scrolled. + * + * @param index index of field in current form. + * @param x the boundary of focus field. + * @param y the boundary of focus field. + * @param width the boundary of focus field. + * @param height the boundary of focus field. + * + */ + @CalledByNative public void onTextFieldDidScroll(int index, float x, float y, float width, float height) { // crbug.com/730764 - from P and above, Android framework listens to the onScrollChanged() // and repositions the autofill UI automatically. @@ -383,42 +455,94 @@ public class AutofillProviderImpl extends AutofillProvider { Rect absBound = transformToWindowBounds(new RectF(x, y, x + width, y + height)); // Notify the new position to the Android framework. Note that we do not call // notifyVirtualViewExited() here intentionally to avoid flickering. - mAutofillManager.notifyVirtualViewEntered(mContainerView, virtualId, absBound); + notifyVirtualViewEntered(mContainerView, virtualId, absBound); // Update focus field position. mRequest.setFocusField(new FocusField(focusField.fieldIndex, absBound)); } - private void notifyVirtualValueChanged(int index) { + private boolean isDatalistField(int childId) { + FormFieldData field = mRequest.getField((short) childId); + return field.mControlType == FormFieldData.ControlType.DATALIST; + } + + private void notifyVirtualValueChanged(int index, boolean forceNotify) { + // The ValueChanged, ViewEntered and ViewExited aren't notified to the autofill service for + // the focused datalist to avoid the potential UI conflict. + // The datalist support was added later and the option list is displayed by WebView, the + // autofill service might also show its suggestions when the datalist (associated the input + // field) is focused, the two UI overlap, the solution is to completely hide the fact that + // the datalist is being focused to the autofill service to prevent it from displaying the + // suggestion. + // The ValueChange will still be sent to autofill service when the form + // submitted or autofilled. + if (!forceNotify && isDatalistField(index)) return; AutofillValue autofillValue = mRequest.getFieldNewValue(index); if (autofillValue == null) return; mAutofillManager.notifyVirtualValueChanged( mContainerView, mRequest.getVirtualId((short) index), autofillValue); } - @Override + private void notifyVirtualViewEntered(View parent, int childId, Rect absBounds) { + // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling. + if (isDatalistField(childId)) return; + mAutofillManager.notifyVirtualViewEntered(parent, childId, absBounds); + } + + private void notifyVirtualViewExited(View parent, int childId) { + // Refer to notifyVirtualValueChanged() for the reason of the datalist's special handling. + if (isDatalistField(childId)) return; + mAutofillManager.notifyVirtualViewExited(parent, childId); + } + + /** + * Invoked when current form will be submitted. + * @param submissionSource the submission source, could be any member defined in + * SubmissionSource.java + */ + @CalledByNative public void onFormSubmitted(int submissionSource) { // The changes could be missing, like those made by Javascript, we'd better to notify // AutofillManager current values. also see crbug.com/353001 and crbug.com/732856. - notifyFormValues(); + forceNotifyFormValues(); mAutofillManager.commit(submissionSource); mRequest = null; mAutofillUMA.onFormSubmitted(submissionSource); } - @Override + /** + * Invoked when focus field changed. + * + * @param focusOnForm whether focus is still on form. + * @param focusItem the index of field has focus + * @param x the boundary of focus field. + * @param y the boundary of focus field. + * @param width the boundary of focus field. + * @param height the boundary of focus field. + */ + @CalledByNative public void onFocusChanged( boolean focusOnForm, int focusField, float x, float y, float width, float height) { onFocusChangedImpl( focusOnForm, focusField, x, y, width, height, false /*causedByValueChange*/); } - private void notifyViewExitBeforeDestoryRequest() { + @CalledByNative + public void hidePopup() { + if (mDatalistPopup != null) { + mDatalistPopup.dismiss(); + mDatalistPopup = null; + } + if (mWebContentsAccessibility != null) { + mWebContentsAccessibility.onAutofillPopupDismissed(); + } + } + + private void notifyViewExitBeforeDestroyRequest() { if (mRequest == null) return; FocusField focusField = mRequest.getFocusField(); if (focusField == null) return; - mAutofillManager.notifyVirtualViewExited( - mContainerView, mRequest.getVirtualId(focusField.fieldIndex)); + notifyVirtualViewExited(mContainerView, mRequest.getVirtualId(focusField.fieldIndex)); mRequest.setFocusField(null); } @@ -436,37 +560,118 @@ public class AutofillProviderImpl extends AutofillProvider { // Notify focus changed. if (prev != null) { - mAutofillManager.notifyVirtualViewExited( - mContainerView, mRequest.getVirtualId(prev.fieldIndex)); + notifyVirtualViewExited(mContainerView, mRequest.getVirtualId(prev.fieldIndex)); } - mAutofillManager.notifyVirtualViewEntered( + notifyVirtualViewEntered( mContainerView, mRequest.getVirtualId((short) focusField), absBound); if (!causedByValueChange) { // The focus field value might not sync with platform's // AutofillManager, just notify it value changed. - notifyVirtualValueChanged(focusField); + notifyVirtualValueChanged(focusField, /* forceNotify = */ false); mAutofillTriggeredTimeMillis = System.currentTimeMillis(); } mRequest.setFocusField(new FocusField((short) focusField, absBound)); } else { if (prev == null) return; // Notify focus changed. - mAutofillManager.notifyVirtualViewExited( - mContainerView, mRequest.getVirtualId(prev.fieldIndex)); + notifyVirtualViewExited(mContainerView, mRequest.getVirtualId(prev.fieldIndex)); mRequest.setFocusField(null); } } - @Override + @CalledByNative + protected void showDatalistPopup( + String[] datalistValues, String[] datalistLabels, boolean isRtl) { + if (mRequest == null) return; + FocusField focusField = mRequest.getFocusField(); + if (focusField != null) { + showDatalistPopup(datalistValues, datalistLabels, + mRequest.getField(focusField.fieldIndex).getBounds(), isRtl); + } + } + + /** + * Display the simplest popup for the datalist. This is same as WebView's datalist popup in + * Android pre-o. No suggestion from the autofill service will be presented, No advance + * features of AutofillPopup are used. + */ + private void showDatalistPopup( + String[] datalistValues, String[] datalistLabels, RectF bounds, boolean isRtl) { + final AutofillSuggestion[] suggestions = new AutofillSuggestion[datalistValues.length]; + for (int i = 0; i < suggestions.length; i++) { + suggestions[i] = new AutofillSuggestion(datalistValues[i], datalistLabels[i], + DropdownItem.NO_ICON, false /* isIconAtLeft */, i, false /* isDeletable */, + false /* isMultilineLabel */, false /* isBoldLabel */); + } + if (mWebContentsAccessibility == null) { + mWebContentsAccessibility = WebContentsAccessibility.fromWebContents(mWebContents); + } + if (mDatalistPopup == null) { + if (ContextUtils.activityFromContext(mContext) == null) return; + ViewAndroidDelegate delegate = mWebContents.getViewAndroidDelegate(); + if (mAnchorView == null) mAnchorView = delegate.acquireView(); + setAnchorViewRect(bounds); + try (StrictModeContext ignored = StrictModeContext.allowDiskReads()) { + mDatalistPopup = new AutofillPopup(mContext, mAnchorView, new AutofillDelegate() { + @Override + public void dismissed() { + onDatalistPopupDismissed(); + } + + @Override + public void suggestionSelected(int listIndex) { + onSuggestionSelected(suggestions[listIndex].getLabel()); + } + + @Override + public void deleteSuggestion(int listIndex) {} + + @Override + public void accessibilityFocusCleared() { + mWebContentsAccessibility.onAutofillPopupAccessibilityFocusCleared(); + } + }); + } catch (RuntimeException e) { + // Deliberately swallowing exception because bad framework implementation can + // throw exceptions in ListPopupWindow constructor. + onDatalistPopupDismissed(); + return; + } + } + mDatalistPopup.filterAndShow(suggestions, isRtl, false); + if (mWebContentsAccessibility != null) { + mWebContentsAccessibility.onAutofillPopupDisplayed(mDatalistPopup.getListView()); + } + } + + private void onDatalistPopupDismissed() { + ViewAndroidDelegate delegate = mWebContents.getViewAndroidDelegate(); + delegate.removeView(mAnchorView); + mAnchorView = null; + } + + private void onSuggestionSelected(String value) { + acceptDataListSuggestion(mNativeAutofillProvider, value); + hidePopup(); + } + + private void setAnchorViewRect(RectF rect) { + setAnchorViewRect(mNativeAutofillProvider, mAnchorView, rect); + } + + /** + * Invoked when current query need to be reset. + */ + @CalledByNative protected void reset() { // We don't need to reset anything here, it should be safe to cancel // current autofill session when new one starts in // startAutofillSession(). } - @Override + @CalledByNative protected void setNativeAutofillProvider(long nativeAutofillProvider) { if (nativeAutofillProvider == mNativeAutofillProvider) return; // Setting the mNativeAutofillProvider to 0 may occur as a @@ -482,21 +687,29 @@ public class AutofillProviderImpl extends AutofillProvider { if (nativeAutofillProvider == 0) mAutofillManager.destroy(); } - @Override public void setWebContents(WebContents webContents) { if (webContents == mWebContents) return; if (mWebContents != null) mRequest = null; mWebContents = webContents; } - @Override + @CalledByNative protected void onDidFillAutofillFormData() { - notifyFormValues(); + // The changes were caused by the autofill service autofill form, + // notified it about the result. + forceNotifyFormValues(); } - private void notifyFormValues() { + private void forceNotifyFormValues() { if (mRequest == null) return; - for (int i = 0; i < mRequest.getFieldCount(); ++i) notifyVirtualValueChanged(i); + for (int i = 0; i < mRequest.getFieldCount(); ++i) { + notifyVirtualValueChanged(i, /* forceNotify = */ true); + } + } + + @VisibleForTesting + public AutofillPopup getDatalistPopupForTesting() { + return mDatalistPopup; } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @@ -537,4 +750,37 @@ public class AutofillProviderImpl extends AutofillProvider { field.setBoundsInContainerViewCoordinates(bounds); } } + + /** + * Send form to renderer for filling. + * + * @param nativeAutofillProvider the native autofill provider. + * @param formData the form to fill. + */ + private void autofill(long nativeAutofillProvider, FormData formData) { + AutofillProviderJni.get().onAutofillAvailable( + nativeAutofillProvider, AutofillProvider.this, formData); + } + + private void acceptDataListSuggestion(long nativeAutofillProvider, String value) { + AutofillProviderJni.get().onAcceptDataListSuggestion( + nativeAutofillProvider, AutofillProvider.this, value); + } + + private void setAnchorViewRect(long nativeAutofillProvider, View anchorView, RectF rect) { + AutofillProviderJni.get().setAnchorViewRect(nativeAutofillProvider, AutofillProvider.this, + anchorView, rect.left, rect.top, rect.width(), rect.height()); + } + + @NativeMethods + interface Natives { + void onAutofillAvailable( + long nativeAutofillProviderAndroid, AutofillProvider caller, FormData formData); + + void onAcceptDataListSuggestion( + long nativeAutofillProviderAndroid, AutofillProvider caller, String value); + + void setAnchorViewRect(long nativeAutofillProviderAndroid, AutofillProvider caller, + View anchorView, float x, float y, float width, float height); + } } diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderUMA.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java index 394cd849c95..394cd849c95 100644 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/AutofillProviderUMA.java +++ b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/AutofillProviderUMA.java diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java index 8069aa887b6..8069aa887b6 100644 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormData.java +++ b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormData.java diff --git a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java index 964c73206c7..eb0a94a6bce 100644 --- a/chromium/components/autofill/android/java/src/org/chromium/components/autofill/FormFieldData.java +++ b/chromium/components/autofill/android/provider/java/src/org/chromium/components/autofill/FormFieldData.java @@ -22,13 +22,17 @@ import java.lang.annotation.RetentionPolicy; public class FormFieldData { /** * Define the control types supported by android.view.autofill.AutofillValue. + * + * Android doesn't have DATALIST control, it is sent to the Autofill service as + * View.AUTOFILL_TYPE_TEXT with AutofillOptions. */ - @IntDef({ControlType.TEXT, ControlType.TOGGLE, ControlType.LIST}) + @IntDef({ControlType.TEXT, ControlType.TOGGLE, ControlType.LIST, ControlType.DATALIST}) @Retention(RetentionPolicy.SOURCE) public @interface ControlType { int TEXT = 0; int TOGGLE = 1; int LIST = 2; + int DATALIST = 3; } public final String mLabel; @@ -43,6 +47,9 @@ public class FormFieldData { public final @ControlType int mControlType; public final int mMaxLength; public final String mHeuristicType; + public final String[] mDatalistValues; + public final String[] mDatalistLabels; + // The bounds in the viewport's coordinates private final RectF mBounds; // The bounds in the container view's coordinates. @@ -58,7 +65,8 @@ public class FormFieldData { private FormFieldData(String name, String label, String value, String autocompleteAttr, boolean shouldAutocomplete, String placeholder, String type, String id, String[] optionValues, String[] optionContents, boolean isCheckField, boolean isChecked, - int maxLength, String heuristicType, float left, float top, float right, float bottom) { + int maxLength, String heuristicType, float left, float top, float right, float bottom, + String[] datalistValues, String[] datalistLabels) { mName = name; mLabel = label; mValue = value; @@ -70,8 +78,12 @@ public class FormFieldData { mOptionValues = optionValues; mOptionContents = optionContents; mIsChecked = isChecked; + mDatalistLabels = datalistLabels; + mDatalistValues = datalistValues; if (mOptionValues != null && mOptionValues.length != 0) { mControlType = ControlType.LIST; + } else if (mDatalistValues != null && mDatalistValues.length != 0) { + mControlType = ControlType.DATALIST; } else if (isCheckField) { mControlType = ControlType.TOGGLE; } else { @@ -142,9 +154,9 @@ public class FormFieldData { String autocompleteAttr, boolean shouldAutocomplete, String placeholder, String type, String id, String[] optionValues, String[] optionContents, boolean isCheckField, boolean isChecked, int maxLength, String heuristicType, float left, float top, - float right, float bottom) { + float right, float bottom, String[] datalistValues, String[] datalistLabels) { return new FormFieldData(name, label, value, autocompleteAttr, shouldAutocomplete, placeholder, type, id, optionValues, optionContents, isCheckField, isChecked, - maxLength, heuristicType, left, top, right, bottom); + maxLength, heuristicType, left, top, right, bottom, datalistValues, datalistLabels); } } diff --git a/chromium/components/autofill/android/junit/BUILD.gn b/chromium/components/autofill/android/provider/junit/BUILD.gn index 0f58b8ac6fa..95cea50bf90 100644 --- a/chromium/components/autofill/android/junit/BUILD.gn +++ b/chromium/components/autofill/android/provider/junit/BUILD.gn @@ -9,13 +9,15 @@ java_library("components_autofill_junit_tests") { # Platform checks are broken for Robolectric. See https://crbug.com/1071638. bypass_platform_checks = true testonly = true - sources = - [ "src/org/chromium/components/autofill/AutofillProviderImplTest.java" ] + sources = [ "src/org/chromium/components/autofill/AutofillProviderTest.java" ] deps = [ "//base:base_java_test_support", "//base:base_junit_test_support", - "//components/autofill/android:provider_java", + "//components/autofill/android/provider:java", "//content/public/android:content_java", + "//third_party/android_deps:robolectric_all_java", + "//third_party/junit", + "//third_party/mockito:mockito_java", "//ui/android:ui_java", ] } diff --git a/chromium/components/autofill/android/junit/src/org/chromium/components/autofill/AutofillProviderImplTest.java b/chromium/components/autofill/android/provider/junit/src/org/chromium/components/autofill/AutofillProviderTest.java index d8c8c2bfd3d..e4b12cec808 100644 --- a/chromium/components/autofill/android/junit/src/org/chromium/components/autofill/AutofillProviderImplTest.java +++ b/chromium/components/autofill/android/provider/junit/src/org/chromium/components/autofill/AutofillProviderTest.java @@ -31,11 +31,11 @@ import org.chromium.ui.display.DisplayAndroid; import java.util.ArrayList; /** - * The unit tests for AutofillProviderImpl. + * The unit tests for AutofillProvider. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) -public class AutofillProviderImplTest { +public class AutofillProviderTest { private static final float EXPECTED_DIP_SCALE = 2; private static final int SCROLL_X = 15; private static final int SCROLL_Y = 155; @@ -46,7 +46,7 @@ public class AutofillProviderImplTest { private WindowAndroid mWindowAndroid; private WebContents mWebContents; private ViewGroup mContainerView; - private AutofillProviderImpl mAutofillProvider; + private AutofillProvider mAutofillProvider; private DisplayAndroid mDisplayAndroid; @Before @@ -57,8 +57,7 @@ public class AutofillProviderImplTest { mDisplayAndroid = Mockito.mock(DisplayAndroid.class); mWebContents = Mockito.mock(WebContents.class); mContainerView = Mockito.mock(ViewGroup.class); - mAutofillProvider = - new AutofillProviderImpl(mContext, mContainerView, "AutofillProviderImplTest"); + mAutofillProvider = new AutofillProvider(mContext, mContainerView, "AutofillProviderTest"); mAutofillProvider.setWebContents(mWebContents); when(mWebContents.getTopLevelNativeWindow()).thenReturn(mWindowAndroid); @@ -85,10 +84,10 @@ public class AutofillProviderImplTest { ArrayList<FormFieldData> fields = new ArrayList<FormFieldData>(1); fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null, null, null, null, false, false, 0, null, 10 /* left */, 20 /* top */, - 300 /* right */, 60 /*bottom*/)); + 300 /* right */, 60 /*bottom*/, null, null)); fields.add(FormFieldData.createFormFieldData(null, null, null, null, false, null, null, null, null, null, false, false, 0, null, 20 /* left */, 100 /* top */, - 400 /* right */, 200 /*bottom*/)); + 400 /* right */, 200 /*bottom*/, null, null)); FormData formData = new FormData(null, null, fields); mAutofillProvider.transformFormFieldToContainViewCoordinates(formData); RectF result = formData.mFields.get(0).getBoundsInContainerViewCoordinates(); |