Commit ee7d152c authored by estade@chromium.org's avatar estade@chromium.org

android: Don't allow AutofillPopup on outside touch

By default, PopupWindows dismiss when the user touches outside the window. The only
way to avert this behavior when using a ListPopupWindow is to rely on a hidden API.

This manifested as the linked bug because each tap dismissed the popup and detached it from the anchor view. C++ didn't realize the popup was dismissed, and tried to update it, but there was no anchor view.

BUG=400601

Review URL: https://codereview.chromium.org/442933002

Cr-Commit-Position: refs/heads/master@{#291463}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@291463 0039d316-1c4b-4281-b951-d872f2087c98
parent d0e4ad0c
......@@ -50,7 +50,7 @@ public class AwAutofillClient {
mContentViewCore.getViewAndroidDelegate(),
new AutofillPopup.AutofillPopupDelegate() {
@Override
public void requestHide() { }
public void dismissed() { }
@Override
public void suggestionSelected(int listIndex) {
nativeSuggestionSelected(mNativeAwAutofillClient, listIndex);
......
......@@ -35,7 +35,7 @@ public class AutofillPopupBridge implements AutofillPopupDelegate{
new Handler().post(new Runnable() {
@Override
public void run() {
requestHide();
dismissed();
}
});
} else {
......@@ -51,8 +51,8 @@ public class AutofillPopupBridge implements AutofillPopupDelegate{
}
@Override
public void requestHide() {
nativeRequestHide(mNativeAutofillPopup);
public void dismissed() {
nativePopupDismissed(mNativeAutofillPopup);
}
@Override
......@@ -109,7 +109,7 @@ public class AutofillPopupBridge implements AutofillPopupDelegate{
array[index] = new AutofillSuggestion(label, sublabel, uniqueId);
}
private native void nativeRequestHide(long nativeAutofillPopupViewAndroid);
private native void nativePopupDismissed(long nativeAutofillPopupViewAndroid);
private native void nativeSuggestionSelected(long nativeAutofillPopupViewAndroid,
int listIndex);
}
......@@ -82,7 +82,7 @@ public class AutofillTest extends ChromeShellTestBase {
}
@Override
public void requestHide() {
public void dismissed() {
}
}
......
......@@ -38,9 +38,9 @@ void AutofillPopupViewAndroid::Show() {
}
void AutofillPopupViewAndroid::Hide() {
controller_ = NULL;
JNIEnv* env = base::android::AttachCurrentThread();
Java_AutofillPopupBridge_hide(env, java_object_.obj());
delete this;
}
void AutofillPopupViewAndroid::UpdateBoundsAndRedrawPopup() {
......@@ -84,8 +84,11 @@ void AutofillPopupViewAndroid::SuggestionSelected(JNIEnv* env,
controller_->AcceptSuggestion(list_index);
}
void AutofillPopupViewAndroid::RequestHide(JNIEnv* env, jobject obj) {
controller_->Hide();
void AutofillPopupViewAndroid::PopupDismissed(JNIEnv* env, jobject obj) {
if (controller_)
controller_->ViewDestroyed();
delete this;
}
void AutofillPopupViewAndroid::InvalidateRow(size_t) {}
......
......@@ -29,7 +29,7 @@ class AutofillPopupViewAndroid : public AutofillPopupView {
// Called when an autofill item was selected.
void SuggestionSelected(JNIEnv* env, jobject obj, jint list_index);
void RequestHide(JNIEnv* env, jobject obj);
void PopupDismissed(JNIEnv* env, jobject obj);
static bool RegisterAutofillPopupViewAndroid(JNIEnv* env);
......
......@@ -6,8 +6,11 @@ package org.chromium.ui.autofill;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListPopupWindow;
import android.widget.PopupWindow;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.ui.DropdownAdapter;
......@@ -15,6 +18,7 @@ import org.chromium.ui.DropdownItem;
import org.chromium.ui.DropdownPopupWindow;
import org.chromium.ui.base.ViewAndroidDelegate;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
......@@ -23,7 +27,8 @@ import java.util.List;
/**
* The Autofill suggestion popup that lists relevant suggestions.
*/
public class AutofillPopup extends DropdownPopupWindow implements AdapterView.OnItemClickListener {
public class AutofillPopup extends DropdownPopupWindow implements AdapterView.OnItemClickListener,
PopupWindow.OnDismissListener {
/**
* Constants defining types of Autofill suggestion entries.
......@@ -47,9 +52,9 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
*/
public interface AutofillPopupDelegate {
/**
* Requests the controller to hide AutofillPopup.
* Informs the controller the AutofillPopup was hidden.
*/
public void requestHide();
public void dismissed();
/**
* Handles the selection of an Autofill suggestion from an AutofillPopup.
......@@ -71,6 +76,7 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
mAutofillCallback = autofillCallback;
setOnItemClickListener(this);
setOnDismissListener(this);
}
/**
......@@ -96,21 +102,27 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
show();
ApiCompatibilityUtils.setLayoutDirection(getListView(),
isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
}
/**
* Overrides the default dismiss behavior to request the controller to dismiss the view.
*/
@Override
public void dismiss() {
mAutofillCallback.requestHide();
// HACK: The ListPopupWindow's mPopup automatically dismisses on an outside tap. There's
// no way to override it or prevent it, except reaching into ListPopupWindow's hidden
// API. This allows the C++ controller to completely control showing/hiding the popup.
// See http://crbug.com/400601
try {
Method setForceIgnoreOutsideTouch = ListPopupWindow.class.getMethod(
"setForceIgnoreOutsideTouch", new Class[] { boolean.class });
setForceIgnoreOutsideTouch.invoke(this, new Object[] { true });
} catch (Exception e) {
Log.e("AutofillPopup",
"ListPopupWindow.setForceIgnoreOutsideTouch not found",
e);
}
}
/**
* Hides the popup.
*/
public void hide() {
super.dismiss();
dismiss();
}
@Override
......@@ -120,4 +132,9 @@ public class AutofillPopup extends DropdownPopupWindow implements AdapterView.On
assert listIndex > -1;
mAutofillCallback.suggestionSelected(listIndex);
}
@Override
public void onDismiss() {
mAutofillCallback.dismissed();
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment