Commit 8c418847 authored by Ioana Pandele's avatar Ioana Pandele Committed by Commit Bot

Add toggle to re-enable saving to the AccessorySheetData

The toggle allowing to re-enable saving should be displayed when the password
field is focused, if saving is/was disabled for the the current origin when
the page was loaded. The state of the toggle will reflect whether saving is
now disabled or enabled (if the user chose to toggle it on).

Bug: 1044930
Change-Id: I7c4b51d6f015f3ce8cfe8315259b8334771c7b85
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2056913
Commit-Queue: Ioana Pandele <ioanap@chromium.org>
Reviewed-by: default avatarVadym Doroshenko <dvadym@chromium.org>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#748766}
parent b1eb4c49
......@@ -120,6 +120,12 @@ class ManualFillingComponentBridge {
return new AccessorySheetData(type, title, warning);
}
@CalledByNative
private void addOptionToggleToAccessorySheetData(Object objAccessorySheetData,
String displayText, boolean enabled, @AccessoryAction int accessoryAction) {
// TODO(crbug.com/1044930): Implement this.
}
@CalledByNative
private Object addUserInfoToAccessorySheetData(
Object objAccessorySheetData, String origin, boolean isPslMatch) {
......
......@@ -5904,6 +5904,9 @@ the Bookmarks menu.">
<message name="IDS_PASSWORD_MANAGER_UPDATE_BUTTON" desc="Label for the 'update' button in the Update Password infobar. This infobar asks if the user wishes to update the saved password for a site to a new password the user has just entered; the button applies the suggested update.">
Update
</message>
<message name="IDS_PASSWORD_SAVING_STATUS_TOGGLE" desc="Label for the toggle that shows whether saving passwords for the current site is enabled or disabled.">
Save passwords for this site
</message>
<message name="IDS_PASSWORD_MANAGER_ACCESSORY_PASSWORD_DESCRIPTION" desc="Description for a field containing a password that belongs to a user.">
Password for <ph name="username">$1<ex>Alexander</ex></ph>
</message>
......
7831bd7cea14eba60618f36107cbfe9963bb913f
\ No newline at end of file
......@@ -294,6 +294,7 @@ AccessoryController* ManualFillingControllerImpl::GetControllerForAction(
return address_controller_.get();
case AccessoryAction::MANAGE_CREDIT_CARDS:
return cc_controller_.get();
case AccessoryAction::TOGGLE_SAVE_PASSWORDS:
case AccessoryAction::AUTOFILL_SUGGESTION:
case AccessoryAction::COUNT:
break; // Intentional failure;
......
......@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/containers/span.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/utf_string_conversions.h"
......@@ -22,6 +23,7 @@
#include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
#include "chrome/browser/vr/vr_tab_helper.h"
#include "chrome/grit/generated_resources.h"
#include "components/autofill/core/browser/ui/accessory_sheet_data.h"
#include "components/autofill/core/browser/ui/accessory_sheet_enums.h"
#include "components/autofill/core/common/autofill_features.h"
#include "components/autofill/core/common/autofill_util.h"
......@@ -29,6 +31,7 @@
#include "components/password_manager/content/browser/content_password_manager_driver.h"
#include "components/password_manager/content/browser/content_password_manager_driver_factory.h"
#include "components/password_manager/core/browser/android_affiliation/affiliation_utils.h"
#include "components/password_manager/core/browser/origin_credential_store.h"
#include "components/password_manager/core/browser/password_manager_driver.h"
#include "components/password_manager/core/browser/password_manager_util.h"
#include "components/password_manager/core/common/password_manager_features.h"
......@@ -43,6 +46,8 @@ using autofill::UserInfo;
using autofill::mojom::FocusedFieldType;
using password_manager::CredentialCache;
using password_manager::UiCredential;
using BlacklistedStatus =
password_manager::OriginCredentialStore::BlacklistedStatus;
using FillingSource = ManualFillingController::FillingSource;
using IsPslMatch = autofill::UserInfo::IsPslMatch;
......@@ -251,12 +256,26 @@ void PasswordAccessoryControllerImpl::RefreshSuggestionsForField(
manage_passwords_title, autofill::AccessoryAction::MANAGE_PASSWORDS));
bool has_suggestions = !info_to_add.empty();
AccessorySheetData data = autofill::CreateAccessorySheetData(
autofill::AccessoryTabType::PASSWORDS, GetTitle(has_suggestions, origin),
std::move(info_to_add), std::move(footer_commands_to_add));
if (base::FeatureList::IsEnabled(
password_manager::features::kRecoverFromNeverSaveAndroid) &&
is_password_field) {
BlacklistedStatus blacklisted_status =
credential_cache_->GetCredentialStore(origin).GetBlacklistedStatus();
if (blacklisted_status == BlacklistedStatus::kWasBlacklisted ||
blacklisted_status == BlacklistedStatus::kIsBlacklisted) {
bool enabled = (blacklisted_status == BlacklistedStatus::kWasBlacklisted);
autofill::OptionToggle option_toggle = autofill::OptionToggle(
l10n_util::GetStringUTF16(IDS_PASSWORD_SAVING_STATUS_TOGGLE), enabled,
autofill::AccessoryAction::TOGGLE_SAVE_PASSWORDS);
data.set_option_toggle(option_toggle);
}
}
GetManualFillingController()->RefreshSuggestions(
autofill::CreateAccessorySheetData(autofill::AccessoryTabType::PASSWORDS,
GetTitle(has_suggestions, origin),
std::move(info_to_add),
std::move(footer_commands_to_add)));
GetManualFillingController()->RefreshSuggestions(std::move(data));
}
void PasswordAccessoryControllerImpl::OnGenerationRequested(
......
......@@ -550,3 +550,43 @@ TEST_F(PasswordAccessoryControllerTest, OnManualGenerationRequested) {
autofill::password_generation::PasswordGenerationType::kManual));
controller()->OnOptionSelected(AccessoryAction::GENERATE_PASSWORD_MANUAL);
}
TEST_F(PasswordAccessoryControllerTest, AddsSaveToggleIfIsBlacklisted) {
cache()->SaveCredentialsAndBlacklistedForOrigin(
{}, CredentialCache::IsOriginBlacklisted(true),
url::Origin::Create(GURL(kExampleSite)));
AccessorySheetData::Builder data_builder(AccessoryTabType::PASSWORDS,
passwords_empty_str(kExampleDomain));
data_builder
.SetOptionToggle(base::ASCIIToUTF16("Save passwords"), false,
autofill::AccessoryAction::TOGGLE_SAVE_PASSWORDS)
.AppendFooterCommand(manage_passwords_str(),
autofill::AccessoryAction::MANAGE_PASSWORDS);
EXPECT_CALL(mock_manual_filling_controller_,
RefreshSuggestions(std::move(data_builder).Build()));
controller()->RefreshSuggestionsForField(
FocusedFieldType::kFillablePasswordField,
/*is_manual_generation_available=*/false);
}
TEST_F(PasswordAccessoryControllerTest, AddsSaveToggleIfWasBlacklisted) {
cache()->SaveCredentialsAndBlacklistedForOrigin(
{}, CredentialCache::IsOriginBlacklisted(true),
url::Origin::Create(GURL(kExampleSite)));
// Simulate unblacklisting.
cache()->UpdateBlacklistedForOrigin(
url::Origin::Create(GURL(kExampleSite)),
CredentialCache::IsOriginBlacklisted(false));
AccessorySheetData::Builder data_builder(AccessoryTabType::PASSWORDS,
passwords_empty_str(kExampleDomain));
data_builder
.SetOptionToggle(base::ASCIIToUTF16("Save passwords"), true,
autofill::AccessoryAction::TOGGLE_SAVE_PASSWORDS)
.AppendFooterCommand(manage_passwords_str(),
autofill::AccessoryAction::MANAGE_PASSWORDS);
EXPECT_CALL(mock_manual_filling_controller_,
RefreshSuggestions(std::move(data_builder).Build()));
controller()->RefreshSuggestionsForField(
FocusedFieldType::kFillablePasswordField,
/*is_manual_generation_available=*/false);
}
......@@ -126,6 +126,14 @@ ManualFillingViewAndroid::ConvertAccessorySheetDataToJavaObject(
ConvertUTF16ToJavaString(env, tab_data.title()),
ConvertUTF16ToJavaString(env, tab_data.warning()));
if (tab_data.option_toggle().has_value()) {
autofill::OptionToggle toggle = tab_data.option_toggle().value();
Java_ManualFillingComponentBridge_addOptionToggleToAccessorySheetData(
env, java_object_, j_tab_data,
ConvertUTF16ToJavaString(env, toggle.display_text()),
toggle.is_enabled(), static_cast<int>(toggle.accessory_action()));
}
for (const UserInfo& user_info : tab_data.user_info_list()) {
ScopedJavaLocalRef<jobject> j_user_info =
Java_ManualFillingComponentBridge_addUserInfoToAccessorySheetData(
......
......@@ -5,6 +5,7 @@
#include "components/autofill/core/browser/ui/accessory_sheet_data.h"
#include "base/strings/string_piece.h"
#include "components/autofill/core/browser/ui/accessory_sheet_enums.h"
namespace autofill {
......@@ -113,6 +114,36 @@ std::ostream& operator<<(std::ostream& os, const FooterCommand& fc) {
<< "action: " << static_cast<int>(fc.accessory_action()) << ")";
}
OptionToggle::OptionToggle(base::string16 display_text,
bool enabled,
autofill::AccessoryAction action)
: display_text_(display_text),
enabled_(enabled),
accessory_action_(action) {}
OptionToggle::OptionToggle(const OptionToggle& option_toggle) = default;
OptionToggle::OptionToggle(OptionToggle&& option_toggle) = default;
OptionToggle::~OptionToggle() = default;
OptionToggle& OptionToggle::operator=(const OptionToggle& option_toggle) =
default;
OptionToggle& OptionToggle::operator=(OptionToggle&& option_toggle) = default;
bool OptionToggle::operator==(const OptionToggle& option_toggle) const {
return display_text_ == option_toggle.display_text_ &&
enabled_ == option_toggle.enabled_ &&
accessory_action_ == option_toggle.accessory_action_;
}
std::ostream& operator<<(std::ostream& os, const OptionToggle& ot) {
return os << "(display text: \"" << ot.display_text() << "\", "
<< "state: " << ot.is_enabled() << ", "
<< "action: " << static_cast<int>(ot.accessory_action()) << ")";
}
std::ostream& operator<<(std::ostream& os, const AccessoryTabType& type) {
switch (type) {
case AccessoryTabType::PASSWORDS:
......@@ -161,8 +192,14 @@ bool AccessorySheetData::operator==(const AccessorySheetData& data) const {
}
std::ostream& operator<<(std::ostream& os, const AccessorySheetData& data) {
os << data.get_sheet_type() << " with title: \"" << data.title()
<< "\", warning: \"" << data.warning() << "\", and user info list: [";
os << data.get_sheet_type() << " with title: \"" << data.title();
if (data.option_toggle().has_value()) {
os << "\", with option toggle: \"" << data.option_toggle().value();
} else {
os << "\", with option toggle: \"none";
}
os << "\", warning: \"" << data.warning() << "\", and user info list: [";
for (const UserInfo& user_info : data.user_info_list()) {
os << user_info << ", ";
}
......@@ -191,6 +228,23 @@ AccessorySheetData::Builder& AccessorySheetData::Builder::SetWarning(
return *this;
}
AccessorySheetData::Builder&& AccessorySheetData::Builder::SetOptionToggle(
base::string16 display_text,
bool enabled,
autofill::AccessoryAction action) && {
// Calls SetOptionToggle(...)& since |this| is an lvalue.
return std::move(SetOptionToggle(std::move(display_text), enabled, action));
}
AccessorySheetData::Builder& AccessorySheetData::Builder::SetOptionToggle(
base::string16 display_text,
bool enabled,
autofill::AccessoryAction action) & {
accessory_sheet_data_.set_option_toggle(
OptionToggle(std::move(display_text), enabled, action));
return *this;
}
AccessorySheetData::Builder&& AccessorySheetData::Builder::AddUserInfo(
std::string origin,
UserInfo::IsPslMatch is_psl_match) && {
......
......@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
#include "base/optional.h"
#include "base/strings/string16.h"
#include "base/util/type_safety/strong_alias.h"
#include "components/autofill/core/browser/ui/accessory_sheet_enums.h"
......@@ -123,6 +124,35 @@ std::ostream& operator<<(std::ostream& out, const FooterCommand& fc);
std::ostream& operator<<(std::ostream& out, const AccessoryTabType& type);
// Toggle to be displayed above the suggestions. One such toggle can be used,
// for example, to turn password saving on for the current origin.
class OptionToggle {
public:
OptionToggle(base::string16 display_text,
bool enabled,
AccessoryAction accessory_action);
OptionToggle(const OptionToggle& option_toggle);
OptionToggle(OptionToggle&& option_toggle);
~OptionToggle();
OptionToggle& operator=(const OptionToggle& option_toggle);
OptionToggle& operator=(OptionToggle&& option_toggle);
const base::string16& display_text() const { return display_text_; }
bool is_enabled() const { return enabled_; }
AccessoryAction accessory_action() const { return accessory_action_; }
bool operator==(const OptionToggle& option_toggle) const;
private:
base::string16 display_text_;
bool enabled_;
autofill::AccessoryAction accessory_action_;
};
// Represents the contents of a bottom sheet tab below the keyboard accessory,
// which can correspond to passwords, credit cards, or profiles data.
class AccessorySheetData {
......@@ -147,6 +177,13 @@ class AccessorySheetData {
const base::string16& warning() const { return warning_; }
void set_warning(base::string16 warning) { warning_ = std::move(warning); }
void set_option_toggle(OptionToggle toggle) {
option_toggle_ = std::move(toggle);
}
const base::Optional<OptionToggle>& option_toggle() const {
return option_toggle_;
}
void add_user_info(UserInfo user_info) {
user_info_list_.emplace_back(std::move(user_info));
}
......@@ -171,6 +208,7 @@ class AccessorySheetData {
AccessoryTabType sheet_type_;
base::string16 title_;
base::string16 warning_;
base::Optional<OptionToggle> option_toggle_;
std::vector<UserInfo> user_info_list_;
std::vector<FooterCommand> footer_commands_;
};
......@@ -199,6 +237,14 @@ class AccessorySheetData::Builder {
Builder&& SetWarning(base::string16 warning) &&;
Builder& SetWarning(base::string16 warning) &;
// Sets the option toggle in the accessory sheet.
Builder&& SetOptionToggle(base::string16 display_text,
bool enabled,
autofill::AccessoryAction action) &&;
Builder& SetOptionToggle(base::string16 display_text,
bool enabled,
autofill::AccessoryAction action) &;
// Adds a new UserInfo object to |accessory_sheet_data_|.
Builder&& AddUserInfo(
std::string origin = std::string(),
......
......@@ -36,6 +36,7 @@ enum class AccessoryAction {
MANAGE_CREDIT_CARDS = 3,
MANAGE_ADDRESSES = 4,
GENERATE_PASSWORD_MANUAL = 5,
TOGGLE_SAVE_PASSWORDS = 6,
COUNT,
};
......
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