Commit 3a307892 authored by Friedrich Horschig's avatar Friedrich Horschig Committed by Commit Bot

[Mfill Android] Use AccessorySheetData in UI

This CL moves the transformation of AccessorySheetTab data to
KeyboardAccessoryData.Items from the ManualFillingBridge into the
PasswordsAccessorySheetMediator.
This enables replacing the Items in a follow-up CL completely and use
the AccessorySheetTab to implement the new layout for the passwords.

This is a step towards generalization of accessory sheet tabs as new
tab will be able to add separate element types with respective views.

Bug: 853772
Change-Id: I678d453245568ef006de932274db044b14ffbdfa
Reviewed-on: https://chromium-review.googlesource.com/c/1350890Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarIoana Pandele <ioanap@chromium.org>
Commit-Queue: Friedrich Horschig [CET] <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613040}
parent 0b9341b1
...@@ -339,6 +339,7 @@ public class KeyboardAccessoryData { ...@@ -339,6 +339,7 @@ public class KeyboardAccessoryData {
*/ */
public final static class UserInfo { public final static class UserInfo {
private final List<Field> mFields = new ArrayList<>(); private final List<Field> mFields = new ArrayList<>();
private final @Nullable Item.FaviconProvider mFaviconProvider;
/** /**
* Represents an item (either selectable or not) presented on the UI, such as the username * Represents an item (either selectable or not) presented on the UI, such as the username
...@@ -403,7 +404,9 @@ public class KeyboardAccessoryData { ...@@ -403,7 +404,9 @@ public class KeyboardAccessoryData {
} }
} }
public UserInfo() {} public UserInfo(@Nullable Item.FaviconProvider faviconProvider) {
mFaviconProvider = faviconProvider;
}
/** /**
* Adds a new field to the group. * Adds a new field to the group.
...@@ -419,6 +422,14 @@ public class KeyboardAccessoryData { ...@@ -419,6 +422,14 @@ public class KeyboardAccessoryData {
public List<Field> getFields() { public List<Field> getFields() {
return mFields; return mFields;
} }
/**
* Possibly holds a favicon provider.
* @return A {@link Item.FaviconProvider}. Optional.
*/
public @Nullable Item.FaviconProvider getFaviconProvider() {
return mFaviconProvider;
}
} }
/** /**
......
...@@ -14,15 +14,11 @@ import org.chromium.chrome.browser.ChromeActivity; ...@@ -14,15 +14,11 @@ import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Action; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Action;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.base.WindowAndroid;
import java.util.ArrayList;
import java.util.List;
class ManualFillingBridge { class ManualFillingBridge {
private final KeyboardAccessoryData.PropertyProvider<Item[]> mItemProvider = private final KeyboardAccessoryData.PropertyProvider<AccessorySheetData> mSheetDataProvider =
new KeyboardAccessoryData.PropertyProvider<>(); new KeyboardAccessoryData.PropertyProvider<>();
private final KeyboardAccessoryData.PropertyProvider<Action[]> mActionProvider = private final KeyboardAccessoryData.PropertyProvider<Action[]> mActionProvider =
new KeyboardAccessoryData.PropertyProvider<>( new KeyboardAccessoryData.PropertyProvider<>(
...@@ -35,7 +31,7 @@ class ManualFillingBridge { ...@@ -35,7 +31,7 @@ class ManualFillingBridge {
mNativeView = nativeView; mNativeView = nativeView;
mActivity = (ChromeActivity) windowAndroid.getActivity().get(); mActivity = (ChromeActivity) windowAndroid.getActivity().get();
mManualFillingCoordinator = mActivity.getManualFillingController(); mManualFillingCoordinator = mActivity.getManualFillingController();
mManualFillingCoordinator.registerPasswordProvider(mItemProvider); mManualFillingCoordinator.registerPasswordProvider(mSheetDataProvider);
mManualFillingCoordinator.registerActionProvider(mActionProvider); mManualFillingCoordinator.registerActionProvider(mActionProvider);
} }
...@@ -46,7 +42,7 @@ class ManualFillingBridge { ...@@ -46,7 +42,7 @@ class ManualFillingBridge {
@CalledByNative @CalledByNative
private void onItemsAvailable(Object objAccessorySheetData) { private void onItemsAvailable(Object objAccessorySheetData) {
mItemProvider.notifyObservers(convertToItems((AccessorySheetData) objAccessorySheetData)); mSheetDataProvider.notifyObservers((AccessorySheetData) objAccessorySheetData);
} }
@CalledByNative @CalledByNative
...@@ -97,7 +93,7 @@ class ManualFillingBridge { ...@@ -97,7 +93,7 @@ class ManualFillingBridge {
@CalledByNative @CalledByNative
private void destroy() { private void destroy() {
mItemProvider.notifyObservers(new Item[] {}); // There are no more items available! mSheetDataProvider.notifyObservers(null);
mNativeView = 0; mNativeView = 0;
} }
...@@ -107,8 +103,8 @@ class ManualFillingBridge { ...@@ -107,8 +103,8 @@ class ManualFillingBridge {
} }
@CalledByNative @CalledByNative
private static Object addUserInfoToAccessorySheetData(Object objAccessorySheetData) { private Object addUserInfoToAccessorySheetData(Object objAccessorySheetData) {
UserInfo userInfo = new UserInfo(); UserInfo userInfo = new UserInfo(this::fetchFavicon);
((AccessorySheetData) objAccessorySheetData).getUserInfoList().add(userInfo); ((AccessorySheetData) objAccessorySheetData).getUserInfoList().add(userInfo);
return userInfo; return userInfo;
} }
...@@ -143,51 +139,6 @@ class ManualFillingBridge { ...@@ -143,51 +139,6 @@ class ManualFillingBridge {
})); }));
} }
private Item[] convertToItems(AccessorySheetData accessorySheetData) {
List<Item> items = new ArrayList<>();
items.add(Item.createTopDivider());
items.add(Item.createLabel(accessorySheetData.getTitle(), accessorySheetData.getTitle()));
for (UserInfo userInfo : accessorySheetData.getUserInfoList()) {
for (UserInfo.Field field : userInfo.getFields()) {
Callback<Item> itemSelectedCallback = null;
if (field.isSelectable()) {
// TODO(crbug.com/902425): Create the callback in addFieldToUserInfo once the
// Item type is replaced with AccessorySheetData.
itemSelectedCallback = (item) -> {
assert mNativeView != 0 : "Controller was destroyed but the bridge wasn't!";
KeyboardAccessoryMetricsRecorder.recordSuggestionSelected(
AccessoryTabType.PASSWORDS,
item.isObfuscated() ? AccessorySuggestionType.PASSWORD
: AccessorySuggestionType.USERNAME);
nativeOnFillingTriggered(
mNativeView, item.isObfuscated(), item.getCaption());
};
}
// clang-format off
items.add(Item.createSuggestion(field.getDisplayText(), field.getA11yDescription(),
field.isObfuscated(), itemSelectedCallback, this::fetchFavicon));
// clang-format on
}
}
if (!accessorySheetData.getFooterCommands().isEmpty()) {
items.add(Item.createDivider());
for (FooterCommand footerCommand : accessorySheetData.getFooterCommands()) {
items.add(Item.createOption(
footerCommand.getDisplayText(), footerCommand.getDisplayText(), (item) -> {
assert mNativeView
!= 0 : "Controller was destroyed but the bridge wasn't!";
nativeOnOptionSelected(mNativeView, item.getCaption());
}));
}
}
return items.toArray(new Item[items.size()]);
}
public void fetchFavicon(@Px int desiredSize, Callback<Bitmap> faviconCallback) { public void fetchFavicon(@Px int desiredSize, Callback<Bitmap> faviconCallback) {
assert mNativeView != 0 : "Favicon was requested after the bridge was destroyed!"; assert mNativeView != 0 : "Favicon was requested after the bridge was destroyed!";
nativeOnFaviconRequested(mNativeView, desiredSize, faviconCallback); nativeOnFaviconRequested(mNativeView, desiredSize, faviconCallback);
......
...@@ -103,8 +103,9 @@ public class ManualFillingCoordinator { ...@@ -103,8 +103,9 @@ public class ManualFillingCoordinator {
mMediator.registerActionProvider(actionProvider); mMediator.registerActionProvider(actionProvider);
} }
void registerPasswordProvider(Provider<KeyboardAccessoryData.Item[]> itemProvider) { void registerPasswordProvider(
mMediator.registerPasswordProvider(itemProvider); Provider<KeyboardAccessoryData.AccessorySheetData> sheetDataProvider) {
mMediator.registerPasswordProvider(sheetDataProvider);
} }
public void showWhenKeyboardIsVisible() { public void showWhenKeyboardIsVisible() {
......
...@@ -220,10 +220,10 @@ class ManualFillingMediator extends EmptyTabObserver ...@@ -220,10 +220,10 @@ class ManualFillingMediator extends EmptyTabObserver
} }
} }
void registerPasswordProvider(Provider<KeyboardAccessoryData.Item[]> itemProvider) { void registerPasswordProvider(Provider<KeyboardAccessoryData.AccessorySheetData> dataProvider) {
PasswordAccessorySheetCoordinator accessorySheet = getPasswordAccessorySheet(); PasswordAccessorySheetCoordinator accessorySheet = getPasswordAccessorySheet();
if (accessorySheet == null) return; // Not available or initialized yet. if (accessorySheet == null) return; // Not available or initialized yet.
accessorySheet.registerItemProvider(itemProvider); accessorySheet.registerDataProvider(dataProvider);
} }
void registerActionProvider(KeyboardAccessoryData.PropertyProvider<Action[]> actionProvider) { void registerActionProvider(KeyboardAccessoryData.PropertyProvider<Action[]> actionProvider) {
......
...@@ -106,10 +106,11 @@ public class PasswordAccessorySheetCoordinator implements KeyboardAccessoryData. ...@@ -106,10 +106,11 @@ public class PasswordAccessorySheetCoordinator implements KeyboardAccessoryData.
/** /**
* Registered item providers can replace the currently shown data in the password sheet. * Registered item providers can replace the currently shown data in the password sheet.
* @param itemProvider The provider this component will listen to. * @param dataProvider The provider this component will listen to.
*/ */
public void registerItemProvider(KeyboardAccessoryData.Provider<Item[]> itemProvider) { public void registerDataProvider(
itemProvider.addObserver(mMediator); KeyboardAccessoryData.Provider<KeyboardAccessoryData.AccessorySheetData> dataProvider) {
dataProvider.addObserver(mMediator);
} }
/** /**
......
...@@ -11,22 +11,27 @@ import android.support.annotation.Nullable; ...@@ -11,22 +11,27 @@ import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.chrome.browser.modelutil.ListModel; import org.chromium.chrome.browser.modelutil.ListModel;
import org.chromium.chrome.browser.modelutil.PropertyModel; import org.chromium.chrome.browser.modelutil.PropertyModel;
import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor; import org.chromium.chrome.browser.modelutil.PropertyModelChangeProcessor;
import java.util.ArrayList;
import java.util.List;
/** /**
* This class contains all logic for the password accessory sheet component. Changes to its internal * This class contains all logic for the password accessory sheet component. Changes to its internal
* {@link PropertyModel} are observed by a {@link PropertyModelChangeProcessor} and affect the * {@link PropertyModel} are observed by a {@link PropertyModelChangeProcessor} and affect the
* {@link PasswordAccessorySheetView}. * {@link PasswordAccessorySheetView}.
*/ */
class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<Item[]> { class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<AccessorySheetData> {
private final PropertyModel mModel; private final PropertyModel mModel;
@Override @Override
public void onItemAvailable(int typeId, Item[] items) { public void onItemAvailable(int typeId, AccessorySheetData accessorySheetData) {
mModel.get(CREDENTIALS).set(items); mModel.get(CREDENTIALS).set(convertToItems(accessorySheetData));
} }
PasswordAccessorySheetMediator( PasswordAccessorySheetMediator(
...@@ -41,6 +46,31 @@ class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<I ...@@ -41,6 +46,31 @@ class PasswordAccessorySheetMediator implements KeyboardAccessoryData.Observer<I
AccessoryTabType.PASSWORDS, mModel.get(CREDENTIALS)); AccessoryTabType.PASSWORDS, mModel.get(CREDENTIALS));
} }
private Item[] convertToItems(AccessorySheetData accessorySheetData) {
if (accessorySheetData == null) return new Item[0];
List<Item> items = new ArrayList<>();
items.add(Item.createTopDivider());
items.add(Item.createLabel(accessorySheetData.getTitle(), accessorySheetData.getTitle()));
for (UserInfo userInfo : accessorySheetData.getUserInfoList()) {
for (UserInfo.Field field : userInfo.getFields()) {
items.add(Item.createSuggestion(field.getDisplayText(), field.getA11yDescription(),
field.isObfuscated(),
item -> field.triggerSelection(), userInfo.getFaviconProvider()));
}
}
if (!accessorySheetData.getFooterCommands().isEmpty()) items.add(Item.createDivider());
for (KeyboardAccessoryData.FooterCommand command : accessorySheetData.getFooterCommands()) {
items.add(Item.createOption(
command.getDisplayText(), command.getDisplayText(), (i) -> command.execute()));
}
return items.toArray(new Item[0]);
}
@VisibleForTesting @VisibleForTesting
ListModel<Item> getModelForTesting() { ListModel<Item> getModelForTesting() {
return mModel.get(CREDENTIALS); return mModel.get(CREDENTIALS);
......
...@@ -18,7 +18,7 @@ import static org.hamcrest.Matchers.is; ...@@ -18,7 +18,7 @@ import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not; import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.TEST_CREDENTIALS; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createTestCredentials;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed;
...@@ -107,7 +107,7 @@ public class ManualFillingIntegrationTest { ...@@ -107,7 +107,7 @@ public class ManualFillingIntegrationTest {
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
onView(withId(R.id.keyboard_accessory)).check(doesNotExist()); onView(withId(R.id.keyboard_accessory)).check(doesNotExist());
mHelper.clickPasswordField(); mHelper.clickPasswordField();
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
mHelper.waitForKeyboard(); mHelper.waitForKeyboard();
// Check that ONLY the accessory is there but the sheet is still hidden. // Check that ONLY the accessory is there but the sheet is still hidden.
...@@ -123,7 +123,7 @@ public class ManualFillingIntegrationTest { ...@@ -123,7 +123,7 @@ public class ManualFillingIntegrationTest {
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
mHelper.clickPasswordField(); mHelper.clickPasswordField();
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
mHelper.waitForKeyboard(); mHelper.waitForKeyboard();
whenDisplayed(withId(R.id.keyboard_accessory)); whenDisplayed(withId(R.id.keyboard_accessory));
...@@ -352,7 +352,7 @@ public class ManualFillingIntegrationTest { ...@@ -352,7 +352,7 @@ public class ManualFillingIntegrationTest {
}); });
listener.addInfoBarAnimationFinished("InfoBar not added."); listener.addInfoBarAnimationFinished("InfoBar not added.");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withText(kInfoBarText)); whenDisplayed(withText(kInfoBarText));
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
...@@ -393,7 +393,7 @@ public class ManualFillingIntegrationTest { ...@@ -393,7 +393,7 @@ public class ManualFillingIntegrationTest {
}); });
listener.addInfoBarAnimationFinished("InfoBar not added."); listener.addInfoBarAnimationFinished("InfoBar not added.");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withText(kInfoBarText)); whenDisplayed(withText(kInfoBarText));
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
...@@ -472,7 +472,7 @@ public class ManualFillingIntegrationTest { ...@@ -472,7 +472,7 @@ public class ManualFillingIntegrationTest {
}); });
listener.addInfoBarAnimationFinished("InfoBar not added."); listener.addInfoBarAnimationFinished("InfoBar not added.");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
assertThat(mActivityTestRule.getInfoBarContainer().getVisibility(), is(View.VISIBLE)); assertThat(mActivityTestRule.getInfoBarContainer().getVisibility(), is(View.VISIBLE));
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
......
...@@ -18,6 +18,7 @@ import static org.chromium.chrome.test.util.ViewUtils.waitForView; ...@@ -18,6 +18,7 @@ import static org.chromium.chrome.test.util.ViewUtils.waitForView;
import static org.chromium.ui.base.LocalizationUtils.setRtlForTesting; import static org.chromium.ui.base.LocalizationUtils.setRtlForTesting;
import android.app.Activity; import android.app.Activity;
import android.support.annotation.Nullable;
import android.support.design.widget.TabLayout; import android.support.design.widget.TabLayout;
import android.support.test.espresso.PerformException; import android.support.test.espresso.PerformException;
import android.support.test.espresso.UiController; import android.support.test.espresso.UiController;
...@@ -30,13 +31,16 @@ import android.view.ViewGroup; ...@@ -30,13 +31,16 @@ import android.view.ViewGroup;
import org.hamcrest.Matcher; import org.hamcrest.Matcher;
import org.junit.Assert; import org.junit.Assert;
import org.chromium.base.Callback;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.UrlUtils; import org.chromium.base.test.util.UrlUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.ChromeWindow; import org.chromium.chrome.browser.ChromeWindow;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Provider; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Provider;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.content_public.browser.ImeAdapter; import org.chromium.content_public.browser.ImeAdapter;
import org.chromium.content_public.browser.WebContents; import org.chromium.content_public.browser.WebContents;
...@@ -54,17 +58,10 @@ import java.util.concurrent.atomic.AtomicReference; ...@@ -54,17 +58,10 @@ import java.util.concurrent.atomic.AtomicReference;
* Helpers in this class simplify interactions with the Keyboard Accessory and the sheet below it. * Helpers in this class simplify interactions with the Keyboard Accessory and the sheet below it.
*/ */
public class ManualFillingTestHelper { public class ManualFillingTestHelper {
public static final Item[] TEST_CREDENTIALS = new Item[] {Item.createTopDivider(),
Item.createLabel("Saved passwords for this site", ""),
Item.createSuggestion("mpark@gmail.com", "", false, (item) -> {}, null),
Item.createSuggestion("TestPassword", "", true, (item) -> {}, null),
Item.createSuggestion("mayapark@googlemail.com", "", false, (item) -> {}, null),
Item.createSuggestion("SomeReallyLongPassword", "", true, (item) -> {}, null),
Item.createDivider(), Item.createOption("Manage Passwords...", "", (item) -> {})};
private final ChromeTabbedActivityTestRule mActivityTestRule; private final ChromeTabbedActivityTestRule mActivityTestRule;
private final AtomicReference<WebContents> mWebContentsRef = new AtomicReference<>(); private final AtomicReference<WebContents> mWebContentsRef = new AtomicReference<>();
private TestInputMethodManagerWrapper mInputMethodManagerWrapper; private TestInputMethodManagerWrapper mInputMethodManagerWrapper;
private Provider<Item[]> mSheetSuggestionsProvider = private Provider<AccessorySheetData> mSheetSuggestionsProvider =
new KeyboardAccessoryData.PropertyProvider<>(); new KeyboardAccessoryData.PropertyProvider<>();
public FakeKeyboard getKeyboard() { public FakeKeyboard getKeyboard() {
...@@ -105,9 +102,7 @@ public class ManualFillingTestHelper { ...@@ -105,9 +102,7 @@ public class ManualFillingTestHelper {
mSheetSuggestionsProvider); mSheetSuggestionsProvider);
}); });
DOMUtils.waitForNonZeroNodeBounds(mWebContentsRef.get(), "password"); DOMUtils.waitForNonZeroNodeBounds(mWebContentsRef.get(), "password");
sendCredentials(new Item[] {Item.createTopDivider(), sendCredentials(createEmptyCredentials());
Item.createLabel("No Saved passwords for this site", ""), Item.createDivider(),
Item.createOption("Manage Passwords...", "", (item) -> {})});
} }
public void clear() { public void clear() {
...@@ -192,7 +187,7 @@ public class ManualFillingTestHelper { ...@@ -192,7 +187,7 @@ public class ManualFillingTestHelper {
/** /**
* Creates and adds a password tab to keyboard accessory and sheet. * Creates and adds a password tab to keyboard accessory and sheet.
*/ */
public void sendCredentials(Item[] testCrendentials) { public void sendCredentials(AccessorySheetData testCrendentials) {
ThreadUtils.runOnUiThreadBlocking( ThreadUtils.runOnUiThreadBlocking(
() -> { mSheetSuggestionsProvider.notifyObservers(testCrendentials); }); () -> { mSheetSuggestionsProvider.notifyObservers(testCrendentials); });
} }
...@@ -327,4 +322,35 @@ public class ManualFillingTestHelper { ...@@ -327,4 +322,35 @@ public class ManualFillingTestHelper {
"Marcus", AccessoryAction.AUTOFILL_SUGGESTION, result -> {})}); "Marcus", AccessoryAction.AUTOFILL_SUGGESTION, result -> {})});
}); });
} }
public static AccessorySheetData createTestCredentials() {
AccessorySheetData testCredentials =
new AccessorySheetData("Saved passwords for this site");
testCredentials.getUserInfoList().add(createUserInfo("mpark@gmail.com", "TestPassword"));
testCredentials.getUserInfoList().add(
createUserInfo("mayapark@googlemail.com", "SomeReallyLongPassword"));
testCredentials.getFooterCommands().add(
new FooterCommand("Manage Passwords...", (item) -> {}));
return testCredentials;
}
public static AccessorySheetData createEmptyCredentials() {
AccessorySheetData testCredentials =
new AccessorySheetData("No Saved passwords for this site");
testCredentials.getFooterCommands().add(
new FooterCommand("Manage Passwords...", (item) -> {}));
return testCredentials;
}
public static UserInfo createUserInfo(String username, String password) {
return createUserInfo(username, password, null);
}
public static UserInfo createUserInfo(
String username, String password, @Nullable Callback<UserInfo.Field> userCallback) {
UserInfo info = new UserInfo(null);
info.addField(new UserInfo.Field(username, username, false, userCallback));
info.addField(new UserInfo.Field(password, "Password for " + username, true, result -> {}));
return info;
}
} }
...@@ -9,7 +9,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId; ...@@ -9,7 +9,7 @@ import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withParent; import static android.support.test.espresso.matcher.ViewMatchers.withParent;
import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.TEST_CREDENTIALS; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createTestCredentials;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.scrollToLastElement; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.scrollToLastElement;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed;
...@@ -75,13 +75,13 @@ public class ManualFillingUiCaptureTest { ...@@ -75,13 +75,13 @@ public class ManualFillingUiCaptureTest {
mHelper.addGenerationButton(); mHelper.addGenerationButton();
mHelper.clickPasswordField(); mHelper.clickPasswordField();
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory(); waitForActionsInAccessory();
waitForUnrelatedChromeUi(); waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBar"); mScreenShooter.shoot("AccessoryBar");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
waitForSuggestionsInSheet(); waitForSuggestionsInSheet();
...@@ -103,13 +103,13 @@ public class ManualFillingUiCaptureTest { ...@@ -103,13 +103,13 @@ public class ManualFillingUiCaptureTest {
mHelper.loadTestPage(true); mHelper.loadTestPage(true);
mHelper.addGenerationButton(); mHelper.addGenerationButton();
mHelper.clickPasswordField(); mHelper.clickPasswordField();
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory(); waitForActionsInAccessory();
waitForUnrelatedChromeUi(); waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBarRTL"); mScreenShooter.shoot("AccessoryBarRTL");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
waitForSuggestionsInSheet(); waitForSuggestionsInSheet();
...@@ -132,13 +132,13 @@ public class ManualFillingUiCaptureTest { ...@@ -132,13 +132,13 @@ public class ManualFillingUiCaptureTest {
mHelper.addGenerationButton(); mHelper.addGenerationButton();
mHelper.clickPasswordField(); mHelper.clickPasswordField();
mHelper.addAutofillChips(); mHelper.addAutofillChips();
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory(); waitForActionsInAccessory();
waitForUnrelatedChromeUi(); waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBarV2"); mScreenShooter.shoot("AccessoryBarV2");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
waitForSuggestionsInSheet(); waitForSuggestionsInSheet();
...@@ -161,13 +161,13 @@ public class ManualFillingUiCaptureTest { ...@@ -161,13 +161,13 @@ public class ManualFillingUiCaptureTest {
mHelper.addGenerationButton(); mHelper.addGenerationButton();
mHelper.clickPasswordField(); mHelper.clickPasswordField();
mHelper.addAutofillChips(); mHelper.addAutofillChips();
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
waitForActionsInAccessory(); waitForActionsInAccessory();
waitForUnrelatedChromeUi(); waitForUnrelatedChromeUi();
mScreenShooter.shoot("AccessoryBarV2RTL"); mScreenShooter.shoot("AccessoryBarV2RTL");
mHelper.sendCredentials(TEST_CREDENTIALS); mHelper.sendCredentials(createTestCredentials());
whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0)); whenDisplayed(withId(R.id.tabs)).perform(selectTabAtPosition(0));
waitForSuggestionsInSheet(); waitForSuggestionsInSheet();
......
...@@ -18,6 +18,7 @@ import static org.hamcrest.Matchers.containsString; ...@@ -18,6 +18,7 @@ import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.createUserInfo;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition;
import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed; import static org.chromium.chrome.browser.autofill.keyboard_accessory.ManualFillingTestHelper.whenDisplayed;
...@@ -37,14 +38,15 @@ import org.junit.Rule; ...@@ -37,14 +38,15 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.base.Callback;
import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.FlakyTest; import org.chromium.base.test.util.FlakyTest;
import org.chromium.base.test.util.RetryOnFailure; import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.FooterCommand;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo.Field;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.Features;
...@@ -128,11 +130,14 @@ public class PasswordAccessoryIntegrationTest { ...@@ -128,11 +130,14 @@ public class PasswordAccessoryIntegrationTest {
public void testPasswordSheetDisplaysProvidedItems() public void testPasswordSheetDisplaysProvidedItems()
throws InterruptedException, TimeoutException { throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false); mHelper.loadTestPage(false);
mHelper.sendCredentials(new Item[] {Item.createLabel("Passwords", "Description_Passwords"),
createSuggestion("mayapark@gmail.com", (item) -> {}), AccessorySheetData accessorySheetData = new AccessorySheetData("Passwords");
createPassword("SomeHiddenPassword"), accessorySheetData.getUserInfoList().add(
createSuggestion("mayaelisabethmercedesgreenepark@googlemail.com", (item) -> {}), createUserInfo("mayapark@gmail.com", "SomeHiddenPassword"));
createPassword("ExtremelyLongPasswordThatUsesQuiteSomeSpaceInTheSheet")}); accessorySheetData.getUserInfoList().add(
createUserInfo("mayaelisabethmercedesgreenepark@googlemail.com",
"ExtremelyLongPasswordThatUsesQuiteSomeSpaceInTheSheet"));
mHelper.sendCredentials(accessorySheetData);
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
mHelper.clickPasswordField(); mHelper.clickPasswordField();
...@@ -153,13 +158,14 @@ public class PasswordAccessoryIntegrationTest { ...@@ -153,13 +158,14 @@ public class PasswordAccessoryIntegrationTest {
public void testPasswordSheetDisplaysNoPasswordsMessageAndOptions() public void testPasswordSheetDisplaysNoPasswordsMessageAndOptions()
throws InterruptedException, TimeoutException { throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false); mHelper.loadTestPage(false);
final AtomicReference<Item> clicked = new AtomicReference<>(); final AtomicReference<FooterCommand> clicked = new AtomicReference<>();
mHelper.sendCredentials(new Item[] { AccessorySheetData accessorySheetData =
Item.createLabel("No saved passwords for abc.com", "Description_Passwords"), new AccessorySheetData("No saved passwords for abc.com");
Item.createDivider(), accessorySheetData.getFooterCommands().add(
Item.createOption( new FooterCommand("Suggest strong password...", clicked::set));
"Suggest strong password...", "Description_Generate", clicked::set), accessorySheetData.getFooterCommands().add(
Item.createOption("Manage passwords...", "Description_Manage", (item) -> {})}); new FooterCommand("Manage passwords...", clicked::set));
mHelper.sendCredentials(accessorySheetData);
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
mHelper.clickPasswordField(); mHelper.clickPasswordField();
...@@ -173,7 +179,7 @@ public class PasswordAccessoryIntegrationTest { ...@@ -173,7 +179,7 @@ public class PasswordAccessoryIntegrationTest {
// The callback should have triggered and set the reference to the selected Item. // The callback should have triggered and set the reference to the selected Item.
assertThat(clicked.get(), notNullValue()); assertThat(clicked.get(), notNullValue());
assertThat(clicked.get().getCaption(), equalTo("Suggest strong password...")); assertThat(clicked.get().getDisplayText(), equalTo("Suggest strong password..."));
} }
@Test @Test
...@@ -182,18 +188,16 @@ public class PasswordAccessoryIntegrationTest { ...@@ -182,18 +188,16 @@ public class PasswordAccessoryIntegrationTest {
@FlakyTest(message = "crbug.com/855617") @FlakyTest(message = "crbug.com/855617")
public void testPasswordSheetTriggersCallback() throws InterruptedException, TimeoutException { public void testPasswordSheetTriggersCallback() throws InterruptedException, TimeoutException {
mHelper.loadTestPage(false); mHelper.loadTestPage(false);
final AtomicReference<Item> clicked = new AtomicReference<>(); final AtomicReference<Field> clicked = new AtomicReference<>();
mHelper.sendCredentials(new Item[] {
Item.createLabel("Passwords", "Description_Passwords"), AccessorySheetData accessorySheetData = new AccessorySheetData("Passwords");
createSuggestion("mpark@abc.com", null), accessorySheetData.getUserInfoList().add(
createPassword("ShorterPassword"), createUserInfo("mpark@abc.com", "ShorterPassword"));
createSuggestion("mayap@xyz.com", null), accessorySheetData.getUserInfoList().add(createUserInfo("mayap@xyz.com", "PWD"));
createPassword("PWD"), accessorySheetData.getUserInfoList().add(createUserInfo("park@googlemail.com", "P@$$W0rt"));
createSuggestion("park@googlemail.com", null), accessorySheetData.getUserInfoList().add(
createPassword("P@$$W0rt"), createUserInfo("mayapark@gmail.com", "SomeHiddenLongPassword", clicked::set));
createSuggestion("mayapark@gmail.com", clicked::set), mHelper.sendCredentials(accessorySheetData);
createPassword("SomeHiddenLongPassword"),
});
// Focus the field to bring up the accessory. // Focus the field to bring up the accessory.
mHelper.clickPasswordField(); mHelper.clickPasswordField();
...@@ -206,7 +210,7 @@ public class PasswordAccessoryIntegrationTest { ...@@ -206,7 +210,7 @@ public class PasswordAccessoryIntegrationTest {
// The callback should have triggered and set the reference to the selected Item. // The callback should have triggered and set the reference to the selected Item.
assertThat(clicked.get(), notNullValue()); assertThat(clicked.get(), notNullValue());
assertThat(clicked.get().getCaption(), equalTo("mayapark@gmail.com")); assertThat(clicked.get().getDisplayText(), equalTo("mayapark@gmail.com"));
} }
@Test @Test
...@@ -250,12 +254,4 @@ public class PasswordAccessoryIntegrationTest { ...@@ -250,12 +254,4 @@ public class PasswordAccessoryIntegrationTest {
} }
}; };
} }
private static Item createSuggestion(String caption, Callback<Item> callback) {
return Item.createSuggestion(caption, "Description_" + caption, false, callback, null);
}
private static Item createPassword(String caption) {
return Item.createSuggestion(caption, "Description_" + caption, true, null, null);
}
} }
...@@ -45,10 +45,11 @@ import org.chromium.chrome.browser.ChromeActivity; ...@@ -45,10 +45,11 @@ import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeKeyboardVisibilityDelegate; import org.chromium.chrome.browser.ChromeKeyboardVisibilityDelegate;
import org.chromium.chrome.browser.ChromeWindow; import org.chromium.chrome.browser.ChromeWindow;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.AccessorySheetData;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Action; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Action;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Item;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.PropertyProvider; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.PropertyProvider;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Provider; import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.Provider;
import org.chromium.chrome.browser.autofill.keyboard_accessory.KeyboardAccessoryData.UserInfo;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.modelutil.ListModel; import org.chromium.chrome.browser.modelutil.ListModel;
import org.chromium.chrome.browser.modelutil.ListObservable; import org.chromium.chrome.browser.modelutil.ListObservable;
...@@ -184,34 +185,29 @@ public class ManualFillingControllerTest { ...@@ -184,34 +185,29 @@ public class ManualFillingControllerTest {
@Test @Test
public void testPasswordItemsPersistAfterSwitchingBrowserTabs() { public void testPasswordItemsPersistAfterSwitchingBrowserTabs() {
ManualFillingMediator mediator = mController.getMediatorForTesting(); ManualFillingMediator mediator = mController.getMediatorForTesting();
Provider<Item[]> firstTabProvider = new PropertyProvider<>(); Provider<AccessorySheetData> firstTabProvider = new PropertyProvider<>();
Provider<Item[]> secondTabProvider = new PropertyProvider<>(); Provider<AccessorySheetData> secondTabProvider = new PropertyProvider<>();
// Simulate opening a new tab which automatically triggers the registration: // Simulate opening a new tab which automatically triggers the registration:
Tab firstTab = addTab(mediator, 1111, null); Tab firstTab = addTab(mediator, 1111, null);
mController.registerPasswordProvider(firstTabProvider); mController.registerPasswordProvider(firstTabProvider);
firstTabProvider.notifyObservers(new Item[] { firstTabProvider.notifyObservers(createPasswordData("FirstPassword"));
Item.createSuggestion("FirstPassword", "FirstPassword", true, result -> {}, null)});
assertThat(mediator.getPasswordAccessorySheet().getModelForTesting().get(0).getCaption(), assertThat(getFirstPassword(mediator), is("FirstPassword"));
is("FirstPassword"));
// Simulate creating a second tab: // Simulate creating a second tab:
Tab secondTab = addTab(mediator, 2222, firstTab); Tab secondTab = addTab(mediator, 2222, firstTab);
mController.registerPasswordProvider(secondTabProvider); mController.registerPasswordProvider(secondTabProvider);
secondTabProvider.notifyObservers(new Item[] {Item.createSuggestion( secondTabProvider.notifyObservers(createPasswordData("SecondPassword"));
"SecondPassword", "SecondPassword", true, result -> {}, null)}); assertThat(getFirstPassword(mediator), is("SecondPassword"));
assertThat(mediator.getPasswordAccessorySheet().getModelForTesting().get(0).getCaption(),
is("SecondPassword"));
// Simulate switching back to the first tab: // Simulate switching back to the first tab:
switchTab(mediator, /*from=*/secondTab, /*to=*/firstTab); switchTab(mediator, /*from=*/secondTab, /*to=*/firstTab);
assertThat(mediator.getPasswordAccessorySheet().getModelForTesting().get(0).getCaption(), assertThat(getFirstPassword(mediator), is("FirstPassword"));
is("FirstPassword"));
// And back to the second: // And back to the second:
switchTab(mediator, /*from=*/firstTab, /*to=*/secondTab); switchTab(mediator, /*from=*/firstTab, /*to=*/secondTab);
assertThat(mediator.getPasswordAccessorySheet().getModelForTesting().get(0).getCaption(), assertThat(getFirstPassword(mediator), is("SecondPassword"));
is("SecondPassword"));
} }
@Test @Test
...@@ -406,10 +402,10 @@ public class ManualFillingControllerTest { ...@@ -406,10 +402,10 @@ public class ManualFillingControllerTest {
.getMediatorForTesting() .getMediatorForTesting()
.getModelForTesting(); .getModelForTesting();
Provider<Item[]> firstTabProvider = new PropertyProvider<>(); Provider<AccessorySheetData> firstTabProvider = new PropertyProvider<>();
PropertyProvider<Action[]> firstActionProvider = PropertyProvider<Action[]> firstActionProvider =
new PropertyProvider<>(GENERATE_PASSWORD_AUTOMATIC); new PropertyProvider<>(GENERATE_PASSWORD_AUTOMATIC);
Provider<Item[]> secondTabProvider = new PropertyProvider<>(); Provider<AccessorySheetData> secondTabProvider = new PropertyProvider<>();
PropertyProvider<Action[]> secondActionProvider = PropertyProvider<Action[]> secondActionProvider =
new PropertyProvider<>(GENERATE_PASSWORD_AUTOMATIC); new PropertyProvider<>(GENERATE_PASSWORD_AUTOMATIC);
...@@ -417,8 +413,7 @@ public class ManualFillingControllerTest { ...@@ -417,8 +413,7 @@ public class ManualFillingControllerTest {
Tab firstTab = addTab(mediator, 1111, null); Tab firstTab = addTab(mediator, 1111, null);
mController.registerPasswordProvider(firstTabProvider); mController.registerPasswordProvider(firstTabProvider);
mController.registerActionProvider(firstActionProvider); mController.registerActionProvider(firstActionProvider);
firstTabProvider.notifyObservers(new Item[] { firstTabProvider.notifyObservers(createPasswordData("FirstPassword"));
Item.createSuggestion("FirstPassword", "FirstPassword", true, result -> {}, null)});
firstActionProvider.notifyObservers(new Action[] { firstActionProvider.notifyObservers(new Action[] {
new Action("2BDestroyed", GENERATE_PASSWORD_AUTOMATIC, (action) -> {})}); new Action("2BDestroyed", GENERATE_PASSWORD_AUTOMATIC, (action) -> {})});
...@@ -426,8 +421,7 @@ public class ManualFillingControllerTest { ...@@ -426,8 +421,7 @@ public class ManualFillingControllerTest {
addTab(mediator, 2222, firstTab); addTab(mediator, 2222, firstTab);
mController.registerPasswordProvider(secondTabProvider); mController.registerPasswordProvider(secondTabProvider);
mController.registerActionProvider(secondActionProvider); mController.registerActionProvider(secondActionProvider);
secondTabProvider.notifyObservers(new Item[] {Item.createSuggestion( secondTabProvider.notifyObservers(createPasswordData("SecondPassword"));
"SecondPassword", "SecondPassword", true, result -> {}, null)});
secondActionProvider.notifyObservers( secondActionProvider.notifyObservers(
new Action[] {new Action("2BKept", GENERATE_PASSWORD_AUTOMATIC, (action) -> {})}); new Action[] {new Action("2BKept", GENERATE_PASSWORD_AUTOMATIC, (action) -> {})});
...@@ -636,4 +630,21 @@ public class ManualFillingControllerTest { ...@@ -636,4 +630,21 @@ public class ManualFillingControllerTest {
mediator.onLayoutChange( mediator.onLayoutChange(
mMockContentView, 0, 0, newWidth, newHeight, 0, 0, oldWidth, oldHeight); mMockContentView, 0, 0, newWidth, newHeight, 0, 0, oldWidth, oldHeight);
} }
private AccessorySheetData createPasswordData(String text) {
AccessorySheetData sheetData = new AccessorySheetData("Passwords");
UserInfo userInfo = new UserInfo(null);
userInfo.addField(new UserInfo.Field("(No username)", "No username", false, null));
userInfo.addField(new UserInfo.Field(text, "Password", true, null));
sheetData.getUserInfoList().add(userInfo);
return sheetData;
}
private String getFirstPassword(ManualFillingMediator mediator) {
assert mediator.getPasswordAccessorySheet() != null;
assert mediator.getPasswordAccessorySheet().getModelForTesting() != null;
assert mediator.getPasswordAccessorySheet().getModelForTesting().size() > 1;
// The 0th item is a divider, the 1st a title, the 2nd a username and 3rd a password.
return mediator.getPasswordAccessorySheet().getModelForTesting().get(3).getCaption();
}
} }
...@@ -75,32 +75,34 @@ public class PasswordAccessorySheetControllerTest { ...@@ -75,32 +75,34 @@ public class PasswordAccessorySheetControllerTest {
@Test @Test
public void testModelNotifiesAboutActionsChangedByProvider() { public void testModelNotifiesAboutActionsChangedByProvider() {
final KeyboardAccessoryData.PropertyProvider<Item[]> testProvider = final KeyboardAccessoryData
.PropertyProvider<KeyboardAccessoryData.AccessorySheetData> testProvider =
new KeyboardAccessoryData.PropertyProvider<>(); new KeyboardAccessoryData.PropertyProvider<>();
final Item testItem = Item.createLabel("Test Item", null); final KeyboardAccessoryData.AccessorySheetData testData =
new KeyboardAccessoryData.AccessorySheetData("Passwords");
mModel.addObserver(mMockItemListObserver); mModel.addObserver(mMockItemListObserver);
mCoordinator.registerItemProvider(testProvider); mCoordinator.registerDataProvider(testProvider);
// If the coordinator receives an initial items, the model should report an insertion. // If the coordinator receives an initial items, the model should report an insertion.
testProvider.notifyObservers(new Item[] {testItem}); testProvider.notifyObservers(testData);
verify(mMockItemListObserver).onItemRangeInserted(mModel, 0, 1); verify(mMockItemListObserver).onItemRangeInserted(mModel, 0, 2);
assertThat(mModel.size(), is(1)); assertThat(mModel.size(), is(2));
assertThat(mModel.get(0), is(equalTo(testItem))); assertThat(mModel.get(1).getCaption(), is(equalTo("Passwords")));
// If the coordinator receives a new set of items, the model should report a change. // If the coordinator receives a new set of items, the model should report a change.
testProvider.notifyObservers(new Item[] {testItem}); testProvider.notifyObservers(testData);
verify(mMockItemListObserver).onItemRangeChanged(mModel, 0, 1, null); verify(mMockItemListObserver).onItemRangeChanged(mModel, 0, 2, null);
assertThat(mModel.size(), is(1)); assertThat(mModel.size(), is(2));
assertThat(mModel.get(0), is(equalTo(testItem))); assertThat(mModel.get(1).getCaption(), is(equalTo("Passwords")));
// If the coordinator receives an empty set of items, the model should report a deletion. // If the coordinator receives an empty set of items, the model should report a deletion.
testProvider.notifyObservers(new Item[] {}); testProvider.notifyObservers(null);
verify(mMockItemListObserver).onItemRangeRemoved(mModel, 0, 1); verify(mMockItemListObserver).onItemRangeRemoved(mModel, 0, 2);
assertThat(mModel.size(), is(0)); assertThat(mModel.size(), is(0));
// There should be no notification if no item are reported repeatedly. // There should be no notification if no item are reported repeatedly.
testProvider.notifyObservers(new Item[] {}); testProvider.notifyObservers(null);
verifyNoMoreInteractions(mMockItemListObserver); verifyNoMoreInteractions(mMockItemListObserver);
} }
......
...@@ -139,8 +139,8 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject( ...@@ -139,8 +139,8 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
for (const UserInfo& user_info : tab_data.user_info_list()) { for (const UserInfo& user_info : tab_data.user_info_list()) {
ScopedJavaLocalRef<jobject> j_user_info = ScopedJavaLocalRef<jobject> j_user_info =
Java_ManualFillingBridge_addUserInfoToAccessorySheetData(env, Java_ManualFillingBridge_addUserInfoToAccessorySheetData(
j_tab_data); env, java_object_, j_tab_data);
for (const UserInfo::Field& field : user_info.fields()) { for (const UserInfo::Field& field : user_info.fields()) {
Java_ManualFillingBridge_addFieldToUserInfo( Java_ManualFillingBridge_addFieldToUserInfo(
env, java_object_, j_user_info, env, java_object_, j_user_info,
......
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