Commit 647b714e authored by Reda Tawfik's avatar Reda Tawfik Committed by Commit Bot

[Android][Mfill] Show warning dialog before presenting the bottom sheet

1. Sends the origin of current focused field from native to Java.
2. Shows a warning message in a `ModalDialog` when
'Use other password' button is clicked.
3. Adds a controller test for the warning dialog.

Screenshot: https://bugs.chromium.org/p/chromium/issues/detail?id=1129351#c7

Bug: 1129351, 1104132
Change-Id: I921b679898ac9c0e84dd9310c38d957d3f31e294
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2416358
Commit-Queue: Reda Tawfik <redatawfik@google.com>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#810575}
parent 3518a663
...@@ -24,6 +24,7 @@ android_library("internal_java") { ...@@ -24,6 +24,7 @@ android_library("internal_java") {
"//chrome/browser/util:java", "//chrome/browser/util:java",
"//components/autofill/android:autofill_java", "//components/autofill/android:autofill_java",
"//components/browser_ui/android/bottomsheet:java", "//components/browser_ui/android/bottomsheet:java",
"//components/browser_ui/modaldialog/android:java",
"//components/browser_ui/widget/android:java", "//components/browser_ui/widget/android:java",
"//components/embedder_support/android:util_java", "//components/embedder_support/android:util_java",
"//components/feature_engagement/public:public_java", "//components/feature_engagement/public:public_java",
...@@ -110,6 +111,7 @@ android_resources("java_resources") { ...@@ -110,6 +111,7 @@ android_resources("java_resources") {
"java/res/drawable/ic_vpn_key_off.xml", "java/res/drawable/ic_vpn_key_off.xml",
"java/res/layout/address_accessory_sheet.xml", "java/res/layout/address_accessory_sheet.xml",
"java/res/layout/all_passwords_bottom_sheet.xml", "java/res/layout/all_passwords_bottom_sheet.xml",
"java/res/layout/all_passwords_bottom_sheet_warning_dialog.xml",
"java/res/layout/credit_card_accessory_sheet.xml", "java/res/layout/credit_card_accessory_sheet.xml",
"java/res/layout/keyboard_accessory.xml", "java/res/layout/keyboard_accessory.xml",
"java/res/layout/keyboard_accessory_action.xml", "java/res/layout/keyboard_accessory_action.xml",
......
<?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. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/warning_dialog"
android:padding="@dimen/all_passwords_warning_dialog_padding"
android:orientation="vertical">
<org.chromium.ui.widget.TextViewWithLeading
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/warning_text_view"
android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
app:leading="20sp"
android:layout_marginBottom="@dimen/all_passwords_warning_dialog_padding"/>
<org.chromium.ui.widget.TextViewWithLeading
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/all_passwords_bottom_sheet_warning_dialog_message_second"
android:textAppearance="@style/TextAppearance.TextMedium.Secondary"
app:leading="20sp"/>
</LinearLayout>
\ No newline at end of file
...@@ -30,4 +30,5 @@ ...@@ -30,4 +30,5 @@
<dimen name="all_passwords_bottom_sheet_padding">20dp</dimen> <dimen name="all_passwords_bottom_sheet_padding">20dp</dimen>
<dimen name="all_passwords_bottom_sheet_recycler_view_padding">6dp</dimen> <dimen name="all_passwords_bottom_sheet_recycler_view_padding">6dp</dimen>
<dimen name="all_passwords_bottom_sheet_search_view_padding">14dp</dimen> <dimen name="all_passwords_bottom_sheet_search_view_padding">14dp</dimen>
<dimen name="all_passwords_warning_dialog_padding">24dp</dimen>
</resources> </resources>
...@@ -18,19 +18,20 @@ class AllPasswordsBottomSheetBridge implements AllPasswordsBottomSheetCoordinato ...@@ -18,19 +18,20 @@ class AllPasswordsBottomSheetBridge implements AllPasswordsBottomSheetCoordinato
private Credential[] mCredentials; private Credential[] mCredentials;
private final AllPasswordsBottomSheetCoordinator mAllPasswordsBottomSheetCoordinator; private final AllPasswordsBottomSheetCoordinator mAllPasswordsBottomSheetCoordinator;
private AllPasswordsBottomSheetBridge(long nativeView, WindowAndroid windowAndroid) { private AllPasswordsBottomSheetBridge(
long nativeView, WindowAndroid windowAndroid, String origin) {
mNativeView = nativeView; mNativeView = nativeView;
assert (mNativeView != 0); assert (mNativeView != 0);
assert (windowAndroid.getActivity().get() != null); assert (windowAndroid.getActivity().get() != null);
mAllPasswordsBottomSheetCoordinator = new AllPasswordsBottomSheetCoordinator(); mAllPasswordsBottomSheetCoordinator = new AllPasswordsBottomSheetCoordinator();
mAllPasswordsBottomSheetCoordinator.initialize(windowAndroid.getActivity().get(), mAllPasswordsBottomSheetCoordinator.initialize(windowAndroid.getActivity().get(),
BottomSheetControllerProvider.from(windowAndroid), this); BottomSheetControllerProvider.from(windowAndroid), this, origin);
} }
@CalledByNative @CalledByNative
private static AllPasswordsBottomSheetBridge create( private static AllPasswordsBottomSheetBridge create(
long nativeView, WindowAndroid windowAndroid) { long nativeView, WindowAndroid windowAndroid, String origin) {
return new AllPasswordsBottomSheetBridge(nativeView, windowAndroid); return new AllPasswordsBottomSheetBridge(nativeView, windowAndroid, origin);
} }
@CalledByNative @CalledByNative
......
...@@ -5,12 +5,28 @@ ...@@ -5,12 +5,28 @@
package org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet; package org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.StyleSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.browser.keyboard_accessory.R;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.components.browser_ui.modaldialog.AppModalPresenter;
import org.chromium.components.url_formatter.SchemeDisplay;
import org.chromium.components.url_formatter.UrlFormatter;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor; import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
import org.chromium.url.GURL;
/** /**
* Creates the AllPasswordsBottomSheet. AllPasswordsBottomSheet uses a bottom sheet to let the * Creates the AllPasswordsBottomSheet. AllPasswordsBottomSheet uses a bottom sheet to let the
...@@ -41,12 +57,15 @@ class AllPasswordsBottomSheetCoordinator { ...@@ -41,12 +57,15 @@ class AllPasswordsBottomSheetCoordinator {
* @param context A {@link Context} to create views and retrieve resources. * @param context A {@link Context} to create views and retrieve resources.
* @param sheetController A {@link BottomSheetController} used to show/hide the sheet. * @param sheetController A {@link BottomSheetController} used to show/hide the sheet.
* @param delegate A {@link Delegate} that handles select and dismiss events. * @param delegate A {@link Delegate} that handles select and dismiss events.
* @param origin The origin for the current focused frame.
*/ */
public void initialize(Context context, BottomSheetController sheetController, public void initialize(Context context, BottomSheetController sheetController,
AllPasswordsBottomSheetCoordinator.Delegate delegate) { AllPasswordsBottomSheetCoordinator.Delegate delegate, String origin) {
PropertyModel model = AllPasswordsBottomSheetProperties.createDefaultModel( PropertyModel model = AllPasswordsBottomSheetProperties.createDefaultModel(
mMediator::onDismissed, mMediator::onQueryTextChange); mMediator::onDismissed, mMediator::onQueryTextChange);
mMediator.initialize(delegate, model); mMediator.initialize(
new ModalDialogManager(new AppModalPresenter(context), ModalDialogType.APP),
getWarningDialogModel(context, mMediator, origin), delegate, model);
setUpModelChangeProcessor(model, new AllPasswordsBottomSheetView(context, sheetController)); setUpModelChangeProcessor(model, new AllPasswordsBottomSheetView(context, sheetController));
} }
...@@ -57,7 +76,8 @@ class AllPasswordsBottomSheetCoordinator { ...@@ -57,7 +76,8 @@ class AllPasswordsBottomSheetCoordinator {
* any other field type (e.g username, ...). * any other field type (e.g username, ...).
*/ */
public void showCredentials(Credential[] credentials, boolean isPasswordField) { public void showCredentials(Credential[] credentials, boolean isPasswordField) {
mMediator.showCredentials(credentials, isPasswordField); mMediator.setCredentials(credentials, isPasswordField);
mMediator.warnAndShow();
} }
@VisibleForTesting @VisibleForTesting
...@@ -65,4 +85,45 @@ class AllPasswordsBottomSheetCoordinator { ...@@ -65,4 +85,45 @@ class AllPasswordsBottomSheetCoordinator {
PropertyModelChangeProcessor.create( PropertyModelChangeProcessor.create(
model, view, AllPasswordsBottomSheetViewBinder::bindAllPasswordsBottomSheet); model, view, AllPasswordsBottomSheetViewBinder::bindAllPasswordsBottomSheet);
} }
private PropertyModel getWarningDialogModel(
Context context, AllPasswordsBottomSheetMediator mediator, String origin) {
View contentView = createWarningDialogView(context, origin);
Resources resources = context.getResources();
return new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
.with(ModalDialogProperties.CONTROLLER, mediator)
.with(ModalDialogProperties.TITLE, resources,
R.string.all_passwords_bottom_sheet_warning_dialog_title)
.with(ModalDialogProperties.CUSTOM_VIEW, contentView)
.with(ModalDialogProperties.POSITIVE_BUTTON_TEXT, resources,
R.string.all_passwords_bottom_sheet_accept)
.with(ModalDialogProperties.NEGATIVE_BUTTON_TEXT, resources,
R.string.all_passwords_bottom_sheet_cancel)
.with(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY, true)
.build();
}
private View createWarningDialogView(Context context, String origin) {
LinearLayout contentView = (LinearLayout) LayoutInflater.from(context).inflate(
R.layout.all_passwords_bottom_sheet_warning_dialog, null);
TextView warningTextView = contentView.findViewById(R.id.warning_text_view);
Resources resources = context.getResources();
String formattedOrigin = UrlFormatter.formatUrlForSecurityDisplay(
new GURL(origin), SchemeDisplay.OMIT_CRYPTOGRAPHIC);
String message = String.format(
resources.getString(
R.string.all_passwords_bottom_sheet_warning_dialog_message_first),
formattedOrigin);
int startIndex = message.indexOf(formattedOrigin);
int endIndex = startIndex + formattedOrigin.length();
Spannable spannableMessage = new SpannableString(message);
StyleSpan boldStyle = new StyleSpan(android.graphics.Typeface.BOLD);
spannableMessage.setSpan(
boldStyle, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
warningTextView.setText(spannableMessage);
return contentView;
}
} }
\ No newline at end of file
...@@ -7,6 +7,9 @@ package org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_shee ...@@ -7,6 +7,9 @@ package org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_shee
import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.SHEET_ITEMS; import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.SHEET_ITEMS;
import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.VISIBLE; import static org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.VISIBLE;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.ListModel; import org.chromium.ui.modelutil.ListModel;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
...@@ -17,19 +20,42 @@ import java.util.Locale; ...@@ -17,19 +20,42 @@ import java.util.Locale;
* Contains the logic for the AllPasswordsBottomSheet. It sets the state of the model and reacts to * Contains the logic for the AllPasswordsBottomSheet. It sets the state of the model and reacts to
* events like clicks. * events like clicks.
*/ */
class AllPasswordsBottomSheetMediator { class AllPasswordsBottomSheetMediator implements ModalDialogProperties.Controller {
private AllPasswordsBottomSheetCoordinator.Delegate mDelegate; private AllPasswordsBottomSheetCoordinator.Delegate mDelegate;
private PropertyModel mModel; private PropertyModel mModel;
private Credential[] mCredentials; private Credential[] mCredentials;
private boolean mIsPasswordField; private boolean mIsPasswordField;
private ModalDialogManager mModalDialogManager;
private PropertyModel mDialogModel;
void initialize(AllPasswordsBottomSheetCoordinator.Delegate delegate, PropertyModel model) { @Override
public void onClick(PropertyModel model, int buttonType) {
int dismissalCause = DialogDismissalCause.NEGATIVE_BUTTON_CLICKED;
if (buttonType == ModalDialogProperties.ButtonType.POSITIVE) {
showCredentials();
dismissalCause = DialogDismissalCause.POSITIVE_BUTTON_CLICKED;
}
mModalDialogManager.dismissDialog(mDialogModel, dismissalCause);
}
@Override
public void onDismiss(PropertyModel model, int dismissalCause) {
if (dismissalCause == DialogDismissalCause.NEGATIVE_BUTTON_CLICKED) {
mDelegate.onDismissed();
}
}
void initialize(ModalDialogManager modalDialogManager, PropertyModel dialogModel,
AllPasswordsBottomSheetCoordinator.Delegate delegate, PropertyModel model) {
assert delegate != null; assert delegate != null;
assert dialogModel != null;
mModalDialogManager = modalDialogManager;
mDialogModel = dialogModel;
mDelegate = delegate; mDelegate = delegate;
mModel = model; mModel = model;
} }
void showCredentials(Credential[] credentials, boolean isPasswordField) { void setCredentials(Credential[] credentials, boolean isPasswordField) {
assert credentials != null; assert credentials != null;
mCredentials = credentials; mCredentials = credentials;
mIsPasswordField = isPasswordField; mIsPasswordField = isPasswordField;
...@@ -41,11 +67,17 @@ class AllPasswordsBottomSheetMediator { ...@@ -41,11 +67,17 @@ class AllPasswordsBottomSheetMediator {
if (credential.getPassword().isEmpty() && isPasswordField) continue; if (credential.getPassword().isEmpty() && isPasswordField) continue;
final PropertyModel model = final PropertyModel model =
AllPasswordsBottomSheetProperties.CredentialProperties.createCredentialModel( AllPasswordsBottomSheetProperties.CredentialProperties.createCredentialModel(
credential, this::onCredentialSelected, isPasswordField); credential, this::onCredentialSelected, mIsPasswordField);
sheetItems.add( sheetItems.add(
new ListItem(AllPasswordsBottomSheetProperties.ItemType.CREDENTIAL, model)); new ListItem(AllPasswordsBottomSheetProperties.ItemType.CREDENTIAL, model));
} }
}
void warnAndShow() {
mModalDialogManager.showDialog(mDialogModel, ModalDialogManager.ModalDialogType.APP);
}
private void showCredentials() {
mModel.set(VISIBLE, true); mModel.set(VISIBLE, true);
} }
......
...@@ -186,9 +186,24 @@ ...@@ -186,9 +186,24 @@
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_SEARCH_HINT" desc="The label for a search button appears in all passwords bottom sheet."> <message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_SEARCH_HINT" desc="The label for a search button appears in all passwords bottom sheet.">
Search Search
</message> </message>
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_NO_PASSWORD" desc="The title for disabled buttons on the All passwords bottom sheet UI when a credential doesn't contains a password."> <message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_NO_PASSWORD" desc="The title for the disabled button on the all passwords bottom sheet UI when a credential doesn't contain a password.">
No password No password
</message> </message>
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_WARNING_DIALOG_TITLE" desc="The title for the warning message showing when `User other password` button is clicked.">
Use other password
</message>
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_WARNING_DIALOG_MESSAGE_FIRST" desc="The first paragraph in the warning message showing when the `User other password` button is clicked.">
If you trust <ph name="ORIGIN">%s<ex>example.com</ex></ph>, you can use a saved password for another site.
</message>
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_WARNING_DIALOG_MESSAGE_SECOND" desc="The second paragraph in the warning message showing when the `User other password` button is clicked.">
Try to use a unique password for every site.
</message>
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_ACCEPT" desc="The text for the positive button in a warning dialog. The all passwords bottom sheet will be shown if this button clicked.">
Continue
</message>
<message name="IDS_ALL_PASSWORDS_BOTTOM_SHEET_CANCEL" desc="The text for the negative button which appears in a warning dialog. Dismisses the warning and all passwords bottom sheet will not be shown.">
Cancel
</message>
<message name="IDS_AUTOFILL_KEYBOARD_ACCESSORY_CONTENT_DESCRIPTION" desc="The text announced by the screen reader when the password suggestions are shown."> <message name="IDS_AUTOFILL_KEYBOARD_ACCESSORY_CONTENT_DESCRIPTION" desc="The text announced by the screen reader when the password suggestions are shown.">
Passwords available Passwords available
</message> </message>
......
...@@ -26,6 +26,9 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList; ...@@ -26,6 +26,9 @@ import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.ItemType; import org.chromium.chrome.browser.keyboard_accessory.all_passwords_bottom_sheet.AllPasswordsBottomSheetProperties.ItemType;
import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modaldialog.ModalDialogProperties.ButtonType;
import org.chromium.ui.modelutil.ListModel; import org.chromium.ui.modelutil.ListModel;
import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ListItem;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
...@@ -49,16 +52,21 @@ public class AllPasswordsBottomSheetControllerTest { ...@@ -49,16 +52,21 @@ public class AllPasswordsBottomSheetControllerTest {
@Mock @Mock
private AllPasswordsBottomSheetCoordinator.Delegate mMockDelegate; private AllPasswordsBottomSheetCoordinator.Delegate mMockDelegate;
@Mock
private ModalDialogManager mModalDialogManager;
private AllPasswordsBottomSheetMediator mMediator; private AllPasswordsBottomSheetMediator mMediator;
private PropertyModel mModel; private PropertyModel mModel;
private PropertyModel mModalDialogModel;
@Before @Before
public void setUp() { public void setUp() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
mMediator = new AllPasswordsBottomSheetMediator(); mMediator = new AllPasswordsBottomSheetMediator();
mModalDialogModel = getModalDialogModel(mMediator);
mModel = AllPasswordsBottomSheetProperties.createDefaultModel( mModel = AllPasswordsBottomSheetProperties.createDefaultModel(
mMediator::onDismissed, mMediator::onQueryTextChange); mMediator::onDismissed, mMediator::onQueryTextChange);
mMediator.initialize(mMockDelegate, mModel); mMediator.initialize(mModalDialogManager, mModalDialogModel, mMockDelegate, mModel);
} }
@Test @Test
...@@ -69,14 +77,32 @@ public class AllPasswordsBottomSheetControllerTest { ...@@ -69,14 +77,32 @@ public class AllPasswordsBottomSheetControllerTest {
} }
@Test @Test
public void testShowCredentialsSetsVisibile() { public void testWarningModalDialog() {
mMediator.showCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD); mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.warnAndShow();
verify(mModalDialogManager)
.showDialog(mModalDialogModel, ModalDialogManager.ModalDialogType.APP);
}
@Test
public void testBottomSheetIsShowingIfWarningAccepted() {
mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ModalDialogProperties.ButtonType.POSITIVE);
assertThat(mModel.get(VISIBLE), is(true)); assertThat(mModel.get(VISIBLE), is(true));
} }
@Test
public void testBottomSheetNotShowingIfWarningDismissed() {
mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ButtonType.NEGATIVE);
assertThat(mModel.get(VISIBLE), is(false));
}
@Test @Test
public void testShowCredentialSetsCredentialListModel() { public void testShowCredentialSetsCredentialListModel() {
mMediator.showCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD); mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ModalDialogProperties.ButtonType.POSITIVE);
ListModel<ListItem> itemList = mModel.get(SHEET_ITEMS); ListModel<ListItem> itemList = mModel.get(SHEET_ITEMS);
assertThat(itemList.size(), is(3)); assertThat(itemList.size(), is(3));
...@@ -90,7 +116,8 @@ public class AllPasswordsBottomSheetControllerTest { ...@@ -90,7 +116,8 @@ public class AllPasswordsBottomSheetControllerTest {
@Test @Test
public void testOnCredentialSelected() { public void testOnCredentialSelected() {
mMediator.showCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD); mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ModalDialogProperties.ButtonType.POSITIVE);
mMediator.onCredentialSelected(TEST_CREDENTIALS[1]); mMediator.onCredentialSelected(TEST_CREDENTIALS[1]);
assertThat(mModel.get(VISIBLE), is(false)); assertThat(mModel.get(VISIBLE), is(false));
verify(mMockDelegate).onCredentialSelected(TEST_CREDENTIALS[1]); verify(mMockDelegate).onCredentialSelected(TEST_CREDENTIALS[1]);
...@@ -98,7 +125,8 @@ public class AllPasswordsBottomSheetControllerTest { ...@@ -98,7 +125,8 @@ public class AllPasswordsBottomSheetControllerTest {
@Test @Test
public void testOnDismiss() { public void testOnDismiss() {
mMediator.showCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD); mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ModalDialogProperties.ButtonType.POSITIVE);
mMediator.onDismissed(BottomSheetController.StateChangeReason.BACK_PRESS); mMediator.onDismissed(BottomSheetController.StateChangeReason.BACK_PRESS);
assertThat(mModel.get(VISIBLE), is(false)); assertThat(mModel.get(VISIBLE), is(false));
verify(mMockDelegate).onDismissed(); verify(mMockDelegate).onDismissed();
...@@ -106,15 +134,24 @@ public class AllPasswordsBottomSheetControllerTest { ...@@ -106,15 +134,24 @@ public class AllPasswordsBottomSheetControllerTest {
@Test @Test
public void testSearchFilterByUsername() { public void testSearchFilterByUsername() {
mMediator.showCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD); mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ModalDialogProperties.ButtonType.POSITIVE);
mMediator.onQueryTextChange("Bob"); mMediator.onQueryTextChange("Bob");
assertThat(mModel.get(SHEET_ITEMS).size(), is(1)); assertThat(mModel.get(SHEET_ITEMS).size(), is(1));
} }
@Test @Test
public void testSearchFilterByURL() { public void testSearchFilterByURL() {
mMediator.showCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD); mMediator.setCredentials(TEST_CREDENTIALS, IS_PASSWORD_FIELD);
mMediator.onClick(mModalDialogModel, ModalDialogProperties.ButtonType.POSITIVE);
mMediator.onQueryTextChange("subdomain"); mMediator.onQueryTextChange("subdomain");
assertThat(mModel.get(SHEET_ITEMS).size(), is(1)); assertThat(mModel.get(SHEET_ITEMS).size(), is(1));
} }
private PropertyModel getModalDialogModel(AllPasswordsBottomSheetMediator mediator) {
return new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)
.with(ModalDialogProperties.CONTROLLER, mediator)
.with(ModalDialogProperties.FILTER_TOUCH_FOR_SECURITY, true)
.build();
}
} }
...@@ -86,3 +86,7 @@ void AllPasswordsBottomSheetController::OnCredentialSelected( ...@@ -86,3 +86,7 @@ void AllPasswordsBottomSheetController::OnCredentialSelected(
void AllPasswordsBottomSheetController::OnDismiss() { void AllPasswordsBottomSheetController::OnDismiss() {
std::move(dismissal_callback_).Run(); std::move(dismissal_callback_).Run();
} }
const GURL& AllPasswordsBottomSheetController::GetFrameUrl() {
return driver_->GetLastCommittedURL();
}
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "components/autofill/core/common/mojom/autofill_types.mojom-forward.h" #include "components/autofill/core/common/mojom/autofill_types.mojom-forward.h"
#include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/password_store_consumer.h"
#include "ui/gfx/native_widget_types.h" #include "ui/gfx/native_widget_types.h"
#include "url/gurl.h"
namespace password_manager { namespace password_manager {
class PasswordManagerDriver; class PasswordManagerDriver;
...@@ -63,6 +64,9 @@ class AllPasswordsBottomSheetController ...@@ -63,6 +64,9 @@ class AllPasswordsBottomSheetController
// consumes |dismissal_callback|. // consumes |dismissal_callback|.
void OnDismiss(); void OnDismiss();
// Returns the last committed URL of the frame from |driver_|.
const GURL& GetFrameUrl();
private: private:
// The controller takes |view_| ownership. // The controller takes |view_| ownership.
std::unique_ptr<AllPasswordsBottomSheetView> view_; std::unique_ptr<AllPasswordsBottomSheetView> view_;
......
...@@ -99,5 +99,7 @@ AllPasswordsBottomSheetViewImpl::GetOrCreateJavaObject() { ...@@ -99,5 +99,7 @@ AllPasswordsBottomSheetViewImpl::GetOrCreateJavaObject() {
} }
return java_object_internal_ = Java_AllPasswordsBottomSheetBridge_create( return java_object_internal_ = Java_AllPasswordsBottomSheetBridge_create(
AttachCurrentThread(), reinterpret_cast<intptr_t>(this), AttachCurrentThread(), reinterpret_cast<intptr_t>(this),
controller_->GetNativeView()->GetWindowAndroid()->GetJavaObject()); controller_->GetNativeView()->GetWindowAndroid()->GetJavaObject(),
ConvertUTF8ToJavaString(AttachCurrentThread(),
controller_->GetFrameUrl().spec()));
} }
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