Commit bdc08330 authored by Fabio Tirelo's avatar Fabio Tirelo Committed by Commit Bot

[Mfill Android] Generalize data passed to password keyboard accessory

This CL is the first step in the refactoring and:
 - Adds a new class (TabData) to represent the data in both C++ and
   Java, which replaces the AccessoryItem/KeyboardAccessoryData.Item
   classes.
 - Replaces AccessoryItem with TabData in the back end and sends it
   to the Java frontend.
 - Converts from TabData to KeyboardAccessoryData.Item in the Java
   frontend, so we don't need to propagate these changes everywhere.

A follow-up CL will completely replace KeyboardAccessoryData.Item
with TabData and remove the conversion listed in the last step above.

Please check the linked bug for the desired final state as well as
the steps of this refactoring to be sent in follow-up CLs.

Bug: 902425
Change-Id: I6c28a31c682176c2409d3e3df2f6604768aed16d
Reviewed-on: https://chromium-review.googlesource.com/c/1320732
Commit-Queue: Fabio Tirelo <ftirelo@chromium.org>
Reviewed-by: default avatarSebastien Seguin-Gagnon <sebsg@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Reviewed-by: default avatarFriedrich Horschig [CET] <fhorschig@chromium.org>
Reviewed-by: default avatarTommy Martino <tmartino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606992}
parent b4786aab
......@@ -59,7 +59,7 @@ public class KeyboardAccessoryData {
/**
* Describes a tab which should be displayed as a small icon at the start of the keyboard
* accessory. Typically, a tab is responsible to change the bottom sheet below the accessory.
* accessory. Typically, a tab is responsible to change the accessory sheet below the accessory.
*/
public final static class Tab {
private final Drawable mIcon;
......@@ -181,6 +181,9 @@ public class KeyboardAccessoryData {
/**
* This describes an item in a accessory sheet. They are usually list items that were created
* natively.
*
* TODO(crbug.com/902425): Remove this class once all code in the frontend uses
* AccessorySheetData.
*/
public final static class Item {
private final int mType;
......@@ -192,6 +195,10 @@ public class KeyboardAccessoryData {
/**
* Items will call a class that implements this interface to request a favicon.
*
* TODO(crbug.com/902425): Move this to UserInfo.Field once Item is deprecated and
* generalize it so it can handle static assets for credit card
* items.
*/
interface FaviconProvider {
/**
......@@ -327,6 +334,155 @@ public class KeyboardAccessoryData {
}
}
/**
* Represents a Profile, or a Credit Card, or the credentials for a website
* (username + password), to be shown on the manual fallback UI.
*/
public final static class UserInfo {
private final List<Field> mFields = new ArrayList<>();
/**
* Represents an item (either selectable or not) presented on the UI, such as the username
* or a credit card number.
*
* TODO(crbug.com/902425): Add a callback to be invoked on user tap.
*/
public final static class Field {
private final String mDisplayText;
private final String mA11yDescription;
private final boolean mIsPassword;
// TODO(crbug.com/902425): Once the selection callback is added to this class, replace
// this with a check if the callback is not null.
private final boolean mSelectable;
/**
* Creates a new Field.
* @param displayText The text to display. Plain text if |isPassword| is false.
* @param a11yDescription The description used for accessibility.
* @param isPassword If true, the displayed caption is transformed into stars.
* @param selectable If true, user can interact with the suggested field.
*/
public Field(String displayText, String a11yDescription, boolean isPassword,
boolean selectable) {
mDisplayText = displayText;
mA11yDescription = a11yDescription;
mIsPassword = isPassword;
mSelectable = selectable;
}
/**
* Returns the text to be displayed on the UI.
*/
public String getDisplayText() {
return mDisplayText;
}
/**
* Returns a translated description that can be used for accessibility.
*/
public String getA11yDescription() {
return mA11yDescription;
}
/**
* Returns whether the user can interact with the selected suggestion. For example,
* this is false if this is a password suggestion on a non-password input field.
*/
public boolean isSelectable() {
return mSelectable;
}
/**
* Returns whether the item (i.e. its caption) contains a password. Can be used to
* determine when to apply text transformations to hide passwords.
*/
public boolean isPassword() {
return mIsPassword;
}
}
public UserInfo() {}
/**
* Adds a new field to the group.
* @param field The field to be added.
*/
public void addField(Field field) {
mFields.add(field);
}
/**
* Returns the list of fields in this group.
*/
public List<Field> getFields() {
return mFields;
}
}
/**
* Represents a command below the suggestions, such as "Manage password...".
*/
public final static class FooterCommand {
private final String mDisplayText;
/**
* Creates a new FooterCommand.
* @param displayText The text to be displayed on the footer.
*/
public FooterCommand(String displayText) {
mDisplayText = displayText;
}
/**
* Returns the translated text to be shown on the UI for this footer command. This text is
* used for accessibility.
*/
public String getDisplayText() {
return mDisplayText;
}
}
/**
* Represents the contents of a accessory sheet tab below the keyboard accessory, which can
* correspond to passwords, credit cards, or profiles data. Created natively.
*
* TODO(crbug.com/902425): Add a field to indicate if this corresponds to password, profile, or
* credit card data.
*/
public final static class AccessorySheetData {
private final String mTitle;
private final List<UserInfo> mUserInfoList = new ArrayList<>();
private final List<FooterCommand> mFooterCommands = new ArrayList<>();
/**
* Creates the AccessorySheetData object.
* @param title The title of accessory sheet tab.
*/
public AccessorySheetData(String title) {
mTitle = title;
}
/**
* Returns the title of the accessory sheet. This text is also used for accessibility.
*/
public String getTitle() {
return mTitle;
}
/**
* Returns the list of {@link UserInfo} to be shown on the accessory sheet.
*/
public List<UserInfo> getUserInfoList() {
return mUserInfoList;
}
/** Returns the list of {@link FooterCommand} to be shown on the accessory sheet.
*/
public List<FooterCommand> getFooterCommands() {
return mFooterCommands;
}
}
/**
* A simple class that holds a list of {@link Observer}s which can be notified about new data by
* directly passing that data into {@link PropertyProvider#notifyObservers(T[])}.
......
......@@ -11,10 +11,16 @@ import org.chromium.base.Callback;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.chrome.R;
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.Action;
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.ui.base.WindowAndroid;
import java.util.ArrayList;
import java.util.List;
class PasswordAccessoryBridge {
private final KeyboardAccessoryData.PropertyProvider<Item> mItemProvider =
new KeyboardAccessoryData.PropertyProvider<>();
......@@ -39,9 +45,8 @@ class PasswordAccessoryBridge {
}
@CalledByNative
private void onItemsAvailable(
String[] text, String[] description, int[] isPassword, int[] itemType) {
mItemProvider.notifyObservers(convertToItems(text, description, isPassword, itemType));
private void onItemsAvailable(Object objAccessorySheetData) {
mItemProvider.notifyObservers(convertToItems((AccessorySheetData) objAccessorySheetData));
}
@CalledByNative
......@@ -96,47 +101,74 @@ class PasswordAccessoryBridge {
mNativeView = 0;
}
private Item[] convertToItems(
String[] text, String[] description, int[] isPassword, int[] type) {
Item[] items = new Item[text.length];
for (int i = 0; i < text.length; i++) {
switch (type[i]) {
case ItemType.LABEL:
items[i] = Item.createLabel(text[i], description[i]);
continue;
case ItemType.SUGGESTION:
items[i] = Item.createSuggestion(
text[i], description[i], isPassword[i] == 1, (item) -> {
assert mNativeView
!= 0 : "Controller was destroyed but the bridge wasn't!";
KeyboardAccessoryMetricsRecorder.recordSuggestionSelected(
AccessoryTabType.PASSWORDS,
item.isPassword() ? AccessorySuggestionType.PASSWORD
: AccessorySuggestionType.USERNAME);
nativeOnFillingTriggered(
mNativeView, item.isPassword(), item.getCaption());
}, this::fetchFavicon);
continue;
case ItemType.NON_INTERACTIVE_SUGGESTION:
items[i] = Item.createSuggestion(
text[i], description[i], isPassword[i] == 1, null, this::fetchFavicon);
continue;
case ItemType.DIVIDER:
items[i] = Item.createDivider();
continue;
case ItemType.OPTION:
items[i] = Item.createOption(text[i], description[i], (item) -> {
@CalledByNative
private static Object createAccessorySheetData(String title) {
return new AccessorySheetData(title);
}
@CalledByNative
private static Object addUserInfoToAccessorySheetData(Object objAccessorySheetData) {
UserInfo userInfo = new UserInfo();
((AccessorySheetData) objAccessorySheetData).getUserInfoList().add(userInfo);
return userInfo;
}
@CalledByNative
private static void addFieldToUserInfo(Object objUserInfo, String displayText,
String a11yDescription, boolean isPassword, boolean selectable) {
((UserInfo) objUserInfo)
.getFields()
.add(new UserInfo.Field(displayText, a11yDescription, isPassword, selectable));
}
@CalledByNative
private static void addFooterCommandToAccessorySheetData(
Object objAccessorySheetData, String displayText) {
((AccessorySheetData) objAccessorySheetData)
.getFooterCommands()
.add(new FooterCommand(displayText));
}
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!";
nativeOnOptionSelected(mNativeView, item.getCaption());
});
continue;
case ItemType.TOP_DIVIDER:
items[i] = Item.createTopDivider();
continue;
KeyboardAccessoryMetricsRecorder.recordSuggestionSelected(
AccessoryTabType.PASSWORDS,
item.isPassword() ? AccessorySuggestionType.PASSWORD
: AccessorySuggestionType.USERNAME);
nativeOnFillingTriggered(mNativeView, item.isPassword(), item.getCaption());
};
}
items.add(Item.createSuggestion(field.getDisplayText(), field.getA11yDescription(),
field.isPassword(), itemSelectedCallback, this ::fetchFavicon));
}
assert false : "Cannot create item for type '" + type[i] + "'.";
}
return items;
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) {
......
......@@ -14,12 +14,47 @@
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "chrome/browser/password_manager/password_accessory_controller.h"
#include "components/autofill/core/browser/accessory_sheet_data.h"
#include "jni/PasswordAccessoryBridge_jni.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/image/image.h"
using base::android::ConvertUTF16ToJavaString;
using base::android::ScopedJavaLocalRef;
namespace {
ScopedJavaLocalRef<jobject> ConvertAccessorySheetDataToJavaObject(
JNIEnv* env,
const AccessorySheetData& data) {
ScopedJavaLocalRef<jobject> j_data =
Java_PasswordAccessoryBridge_createAccessorySheetData(
env, ConvertUTF16ToJavaString(env, data.title()));
for (const UserInfo& user_info : data.user_info_list()) {
ScopedJavaLocalRef<jobject> j_user_info =
Java_PasswordAccessoryBridge_addUserInfoToAccessorySheetData(env,
j_data);
for (const UserInfo::Field& field : user_info.fields()) {
Java_PasswordAccessoryBridge_addFieldToUserInfo(
env, j_user_info, ConvertUTF16ToJavaString(env, field.display_text()),
ConvertUTF16ToJavaString(env, field.a11y_description()),
field.is_password(), field.selectable());
}
}
for (const FooterCommand& footer_command : data.footer_commands()) {
Java_PasswordAccessoryBridge_addFooterCommandToAccessorySheetData(
env, j_data,
ConvertUTF16ToJavaString(env, footer_command.display_text()));
}
return j_data;
}
} // namespace
PasswordAccessoryViewAndroid::PasswordAccessoryViewAndroid(
PasswordAccessoryController* controller)
: controller_(controller) {
......@@ -39,29 +74,12 @@ PasswordAccessoryViewAndroid::~PasswordAccessoryViewAndroid() {
}
void PasswordAccessoryViewAndroid::OnItemsAvailable(
const std::vector<AccessoryItem>& items) {
const AccessorySheetData& data) {
DCHECK(!java_object_.is_null());
std::vector<base::string16> texts;
std::vector<base::string16> descriptions;
std::vector<int> password_stats;
std::vector<int> item_types;
texts.reserve(items.size());
descriptions.reserve(items.size());
password_stats.reserve(items.size());
item_types.reserve(items.size());
for (const auto& item : items) {
texts.emplace_back(item.text);
descriptions.emplace_back(item.content_description);
password_stats.emplace_back(item.is_password);
item_types.emplace_back(static_cast<int>(item.itemType));
}
JNIEnv* env = base::android::AttachCurrentThread();
Java_PasswordAccessoryBridge_onItemsAvailable(
env, java_object_, base::android::ToJavaArrayOfStrings(env, texts),
base::android::ToJavaArrayOfStrings(env, descriptions),
base::android::ToJavaIntArray(env, password_stats),
base::android::ToJavaIntArray(env, item_types));
env, java_object_, ConvertAccessorySheetDataToJavaObject(env, data));
}
void PasswordAccessoryViewAndroid::CloseAccessorySheet() {
......
......@@ -27,7 +27,7 @@ class PasswordAccessoryViewAndroid : public PasswordAccessoryViewInterface {
~PasswordAccessoryViewAndroid() override;
// PasswordAccessoryViewInterface:
void OnItemsAvailable(const std::vector<AccessoryItem>& items) override;
void OnItemsAvailable(const AccessorySheetData& data) override;
void OnAutomaticGenerationStatusChanged(bool available) override;
void CloseAccessorySheet() override;
void SwapSheetWithKeyboard() override;
......
......@@ -33,7 +33,6 @@
#include "ui/base/ui_base_features.h"
using autofill::PasswordForm;
using Item = PasswordAccessoryViewInterface::AccessoryItem;
namespace {
......@@ -69,8 +68,10 @@ struct PasswordAccessoryController::GenerationElementData {
struct PasswordAccessoryController::SuggestionElementData {
SuggestionElementData(base::string16 password,
base::string16 username,
Item::Type username_type)
: password(password), username(username), username_type(username_type) {}
bool username_selectable)
: password(password),
username(username),
username_selectable(username_selectable) {}
// Password string to be used for this credential.
base::string16 password;
......@@ -79,7 +80,7 @@ struct PasswordAccessoryController::SuggestionElementData {
base::string16 username;
// Decides whether the username is interactive (i.e. empty ones are not).
Item::Type username_type;
bool username_selectable;
};
struct PasswordAccessoryController::FaviconRequestData {
......@@ -151,7 +152,7 @@ void PasswordAccessoryController::SavePasswordsForOrigin(
for (const auto& pair : best_matches) {
const PasswordForm* form = pair.second;
suggestions->emplace_back(form->password_value, GetDisplayUsername(*form),
Item::Type::NON_INTERACTIVE_SUGGESTION);
/*username_selectable*/ false);
}
}
......@@ -190,13 +191,13 @@ void PasswordAccessoryController::RefreshSuggestionsForField(
bool is_password_field) {
if (is_fillable) {
current_origin_ = origin;
view_->OnItemsAvailable(CreateViewItems(origin, origin_suggestions_[origin],
is_password_field));
view_->OnItemsAvailable(CreateAccessorySheetData(
origin, origin_suggestions_[origin], is_password_field));
view_->SwapSheetWithKeyboard();
} else {
// For unfillable fields, reset the origin and send the empty state message.
current_origin_ = url::Origin();
view_->OnItemsAvailable(CreateViewItems(
view_->OnItemsAvailable(CreateAccessorySheetData(
origin, std::vector<SuggestionElementData>(), is_password_field));
view_->CloseAccessorySheet();
}
......@@ -323,50 +324,42 @@ gfx::NativeWindow PasswordAccessoryController::native_window() const {
}
// static
std::vector<Item> PasswordAccessoryController::CreateViewItems(
AccessorySheetData PasswordAccessoryController::CreateAccessorySheetData(
const url::Origin& origin,
const std::vector<SuggestionElementData>& suggestions,
bool is_password_field) {
std::vector<Item> items;
base::string16 passwords_title_str;
// Create a horizontal divider line before the title.
items.emplace_back(base::string16(), base::string16(), false,
Item::Type::TOP_DIVIDER);
// Create the title element
passwords_title_str = l10n_util::GetStringFUTF16(
base::string16 passwords_title_str = l10n_util::GetStringFUTF16(
suggestions.empty()
? IDS_PASSWORD_MANAGER_ACCESSORY_PASSWORD_LIST_EMPTY_MESSAGE
: IDS_PASSWORD_MANAGER_ACCESSORY_PASSWORD_LIST_TITLE,
base::ASCIIToUTF16(origin.host()));
items.emplace_back(passwords_title_str, passwords_title_str,
/*is_password=*/false, Item::Type::LABEL);
AccessorySheetData data(passwords_title_str);
// Create a username and a password element for every suggestions
// Create a username and a password element for every suggestion.
for (const SuggestionElementData& suggestion : suggestions) {
items.emplace_back(suggestion.username, suggestion.username,
/*is_password=*/false, suggestion.username_type);
items.emplace_back(suggestion.password,
l10n_util::GetStringFUTF16(
IDS_PASSWORD_MANAGER_ACCESSORY_PASSWORD_DESCRIPTION,
suggestion.username),
/*is_password=*/true,
is_password_field
? Item::Type::SUGGESTION
: Item::Type::NON_INTERACTIVE_SUGGESTION);
}
UserInfo user_info;
user_info.add_field(UserInfo::Field(
suggestion.username, suggestion.username, /*is_password=*/false,
/*selectable=*/suggestion.username_selectable));
// Create a horizontal divider line before the options.
items.emplace_back(base::string16(), base::string16(), false,
Item::Type::DIVIDER);
user_info.add_field(UserInfo::Field(
suggestion.password,
l10n_util::GetStringFUTF16(
IDS_PASSWORD_MANAGER_ACCESSORY_PASSWORD_DESCRIPTION,
suggestion.username),
/*is_password=*/true, /*selectable=*/is_password_field));
data.add_user_info(std::move(user_info));
}
// Create the link to all passwords.
base::string16 manage_passwords_title = l10n_util::GetStringUTF16(
IDS_PASSWORD_MANAGER_ACCESSORY_ALL_PASSWORDS_LINK);
items.emplace_back(manage_passwords_title, manage_passwords_title, false,
Item::Type::OPTION);
return items;
data.add_footer_command(FooterCommand(manage_passwords_title));
return data;
}
void PasswordAccessoryController::OnImageFetched(
......
......@@ -16,6 +16,7 @@
#include "base/strings/string16.h"
#include "base/task/cancelable_task_tracker.h"
#include "chrome/browser/password_manager/password_accessory_view_interface.h"
#include "components/autofill/core/browser/accessory_sheet_data.h"
#include "components/autofill/core/common/filling_status.h"
#include "components/autofill/core/common/password_generation_util.h"
#include "components/favicon_base/favicon_types.h"
......@@ -176,10 +177,10 @@ class PasswordAccessoryController
// Creates the view items based on the given |suggestions|.
// If |is_password_field| is false, password suggestions won't be interactive.
static std::vector<PasswordAccessoryViewInterface::AccessoryItem>
CreateViewItems(const url::Origin& origin,
const std::vector<SuggestionElementData>& suggestions,
bool is_password_field);
static AccessorySheetData CreateAccessorySheetData(
const url::Origin& origin,
const std::vector<SuggestionElementData>& suggestions,
bool is_password_field);
// Handles a favicon response requested by |GetFavicon| and calls the waiting
// last_icon_callback_ with a (possibly empty) icon bitmap.
......
......@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "url/gurl.h"
class AccessorySheetData;
class PasswordAccessoryController;
// The interface for creating and controlling a view for the password accessory.
......@@ -19,57 +20,38 @@ class PasswordAccessoryController;
// any request (like filling a suggestion) back to the controller.
class PasswordAccessoryViewInterface {
public:
// Represents an item that will be shown in the bottom sheet below a keyboard
// accessory.
struct AccessoryItem {
// Defines which item types exist. A java IntDef@ is generated from this.
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.chrome.browser.autofill.keyboard_accessory)
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: ItemType
enum class Type {
// An item in title style to purely to display text. Non-interactive.
LABEL = 1, // e.g. the "Passwords for this site" section header.
// An item in list style to displaying an interactive suggestion.
SUGGESTION = 2, // e.g. a user's email address used for sign-up.
// An item in list style to displaying a non-interactive suggestion.
NON_INTERACTIVE_SUGGESTION = 3, // e.g. the "(No username)" suggestion.
// A horizontal, non-interactive divider used to visually divide sections.
DIVIDER = 4,
// A single, usually static and interactive suggestion.
OPTION = 5, // e.g. the "Manage passwords..." link.
// A horizontal, non-interactive divider used to visually divide the
// accessory sheet from the accessory bar.
TOP_DIVIDER = 6,
};
// The |text| is caption of the item and what will be filled if selected.
base::string16 text;
// The |content_description| is used for accessibility on displayed items.
base::string16 content_description;
// If true, the item contains a password (i.e. it's text should be masked).
bool is_password;
// Visual appearance and whether an item is clickable depend on this.
Type itemType;
AccessoryItem(const base::string16& text,
const base::string16& content_description,
bool is_password,
Type itemType)
: text(text),
content_description(content_description),
is_password(is_password),
itemType(itemType) {}
// Defines which item types exist.
// TODO(crbug.com/902425): Remove this once AccessorySheetData is used on the
// frontend to represent data to present.
// GENERATED_JAVA_ENUM_PACKAGE: (
// org.chromium.chrome.browser.autofill.keyboard_accessory)
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: ItemType
enum class Type {
// An item in title style to purely to display text. Non-interactive.
LABEL = 1, // e.g. the "Passwords for this site" section header.
// An item in list style to displaying an interactive suggestion.
SUGGESTION = 2, // e.g. a user's email address used for sign-up.
// An item in list style to displaying a non-interactive suggestion.
NON_INTERACTIVE_SUGGESTION = 3, // e.g. the "(No username)" suggestion.
// A horizontal, non-interactive divider used to visually divide sections.
DIVIDER = 4,
// A single, usually static and interactive suggestion.
OPTION = 5, // e.g. the "Manage passwords..." link.
// A horizontal, non-interactive divider used to visually divide the
// accessory sheet from the accessory bar.
TOP_DIVIDER = 6,
};
virtual ~PasswordAccessoryViewInterface() = default;
// Called with items that should replace all existing items in the accessory
// sheet. The |items| are the labels and actions that allow the filling.
virtual void OnItemsAvailable(const std::vector<AccessoryItem>& items) = 0;
// Called with data that should replace the data currently shown on the
// accessory sheet.
virtual void OnItemsAvailable(const AccessorySheetData& data) = 0;
// Called when the generation action should be offered or rescinded
// in the keyboard accessory.
......
......@@ -8,6 +8,8 @@ import("//testing/libfuzzer/fuzzer_test.gni")
jumbo_static_library("browser") {
sources = [
"accessory_sheet_data.cc",
"accessory_sheet_data.h",
"account_info_getter.h",
"address.cc",
"address.h",
......
// Copyright 2018 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.
#include "components/autofill/core/browser/accessory_sheet_data.h"
UserInfo::Field::Field(const base::string16& display_text,
const base::string16& a11y_description,
bool is_password,
bool selectable)
: display_text_(display_text),
a11y_description_(a11y_description),
is_password_(is_password),
selectable_(selectable) {}
UserInfo::Field::Field(const Field& field) = default;
UserInfo::Field::Field(Field&& field) = default;
UserInfo::Field::~Field() = default;
UserInfo::Field& UserInfo::Field::operator=(const Field& field) = default;
UserInfo::Field& UserInfo::Field::operator=(Field&& field) = default;
bool UserInfo::Field::operator==(const UserInfo::Field& field) const {
return display_text_ == field.display_text_ &&
a11y_description_ == field.a11y_description_ &&
is_password_ == field.is_password_ && selectable_ == field.selectable_;
}
UserInfo::UserInfo() = default;
UserInfo::UserInfo(const UserInfo& user_info) = default;
UserInfo::UserInfo(UserInfo&& field) = default;
UserInfo::~UserInfo() = default;
UserInfo& UserInfo::operator=(const UserInfo& user_info) = default;
UserInfo& UserInfo::operator=(UserInfo&& user_info) = default;
bool UserInfo::operator==(const UserInfo& user_info) const {
return fields_ == user_info.fields_;
}
FooterCommand::FooterCommand(const base::string16& display_text)
: display_text_(display_text) {}
FooterCommand::FooterCommand(const FooterCommand& footer_command) = default;
FooterCommand::FooterCommand(FooterCommand&& footer_command) = default;
FooterCommand::~FooterCommand() = default;
FooterCommand& FooterCommand::operator=(const FooterCommand& footer_command) =
default;
FooterCommand& FooterCommand::operator=(FooterCommand&& footer_command) =
default;
bool FooterCommand::operator==(const FooterCommand& fc) const {
return display_text_ == fc.display_text_;
}
AccessorySheetData::AccessorySheetData(const base::string16& title)
: title_(title) {}
AccessorySheetData::AccessorySheetData(const AccessorySheetData& data) =
default;
AccessorySheetData::AccessorySheetData(AccessorySheetData&& data) = default;
AccessorySheetData::~AccessorySheetData() = default;
AccessorySheetData& AccessorySheetData::operator=(
const AccessorySheetData& data) = default;
AccessorySheetData& AccessorySheetData::operator=(AccessorySheetData&& data) =
default;
bool AccessorySheetData::operator==(const AccessorySheetData& data) const {
return title_ == data.title_ && user_info_list_ == data.user_info_list_ &&
footer_commands_ == data.footer_commands_;
}
// Copyright 2018 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.
#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_ACCESSORY_SHEET_DATA_H_
#define COMPONENTS_AUTOFILL_CORE_BROWSER_ACCESSORY_SHEET_DATA_H_
#include <vector>
#include "base/strings/string16.h"
// Represents user data to be shown on the manual fallback UI (e.g. a Profile,
// or a Credit Card, or the credentials for a website),
// TODO(crbug.com/902425): Add a member to represent the field type and remove
// the |is_password| field.
class UserInfo {
public:
// Represents a selectable item, such as the username or a credit card
// number.
class Field {
public:
Field(const base::string16& display_text,
const base::string16& a11y_description,
bool is_password,
bool selectable);
Field(const Field& field);
Field(Field&& field);
~Field();
Field& operator=(const Field& field);
Field& operator=(Field&& field);
const base::string16& display_text() const { return display_text_; }
const base::string16& a11y_description() const { return a11y_description_; }
bool is_password() const { return is_password_; }
bool selectable() const { return selectable_; }
bool operator==(const UserInfo::Field& field) const;
private:
base::string16 display_text_;
base::string16 a11y_description_;
bool is_password_;
bool selectable_;
};
UserInfo();
UserInfo(const UserInfo& user_info);
UserInfo(UserInfo&& field);
~UserInfo();
UserInfo& operator=(const UserInfo& user_info);
UserInfo& operator=(UserInfo&& user_info);
void add_field(Field field) { fields_.emplace_back(std::move(field)); }
const std::vector<Field>& fields() const { return fields_; }
bool operator==(const UserInfo& user_info) const;
private:
std::vector<Field> fields_;
};
// Represents a command below the suggestions, such as "Manage password...".
class FooterCommand {
public:
explicit FooterCommand(const base::string16& display_text);
FooterCommand(const FooterCommand& footer_command);
FooterCommand(FooterCommand&& footer_command);
~FooterCommand();
FooterCommand& operator=(const FooterCommand& footer_command);
FooterCommand& operator=(FooterCommand&& footer_command);
const base::string16& display_text() const { return display_text_; }
bool operator==(const FooterCommand& fc) const;
private:
base::string16 display_text_;
};
// Represents the contents of a bottom sheet tab below the keyboard accessory,
// which can correspond to passwords, credit cards, or profiles data.
//
// TODO(crbug.com/902425): Add a field to indicate if this corresponds to
// password, profile, or credit card data.
class AccessorySheetData {
public:
explicit AccessorySheetData(const base::string16& title);
AccessorySheetData(const AccessorySheetData& data);
AccessorySheetData(AccessorySheetData&& data);
~AccessorySheetData();
AccessorySheetData& operator=(const AccessorySheetData& data);
AccessorySheetData& operator=(AccessorySheetData&& data);
const base::string16& title() const { return title_; }
void add_user_info(UserInfo user_info) {
user_info_list_.emplace_back(std::move(user_info));
}
const std::vector<UserInfo>& user_info_list() const {
return user_info_list_;
}
std::vector<UserInfo>& mutable_user_info_list() { return user_info_list_; }
void add_footer_command(FooterCommand footer_command) {
footer_commands_.emplace_back(std::move(footer_command));
}
const std::vector<FooterCommand>& footer_commands() const {
return footer_commands_;
}
bool operator==(const AccessorySheetData& data) const;
private:
base::string16 title_;
std::vector<UserInfo> user_info_list_;
std::vector<FooterCommand> footer_commands_;
};
#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_ACCESSORY_SHEET_DATA_H_
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