Commit 7c10648c authored by Ioana Pandele's avatar Ioana Pandele Committed by Commit Bot

[Android] Handle GetCurrentForms returning empty vector in update infobar

ManagePasswordsState::GetCurrentForms() can return an empty vector. When
this happens, the infobar should display the username from the pending
credential since that is the only credential eligible for
password update.

This change also extracts the logic which determines the usernames to
display from the infobar and moves it to the delegate.

Bug:1045941

Change-Id: Idcc8a7149fa931b90d541dc0159e78151183f561
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2027472Reviewed-by: default avatarMatthew Jones <mdjones@chromium.org>
Reviewed-by: default avatarVasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Ioana Pandele <ioanap@chromium.org>
Cr-Commit-Position: refs/heads/master@{#738112}
parent d70dba1e
......@@ -60,6 +60,41 @@ UpdatePasswordInfoBarDelegate::GetCurrentForms() const {
return passwords_state_.GetCurrentForms();
}
const base::string16& UpdatePasswordInfoBarDelegate::GetDefaultUsername()
const {
return passwords_state_.form_manager()
->GetPendingCredentials()
.username_value;
}
unsigned int UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
std::vector<base::string16>* usernames) {
return UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
GetCurrentForms(), GetDefaultUsername(), usernames);
}
// static
unsigned int UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
const std::vector<std::unique_ptr<autofill::PasswordForm>>& current_forms,
const base::string16& default_username,
std::vector<base::string16>* usernames) {
unsigned int selected_username = 0;
for (const auto& form : current_forms) {
usernames->push_back(GetDisplayUsername(*form));
if (form->username_value == default_username) {
selected_username = usernames->size() - 1;
}
}
if (usernames->empty() ||
usernames->at(selected_username) != default_username) {
usernames->push_back(default_username);
selected_username = usernames->size() - 1;
}
return selected_username;
}
UpdatePasswordInfoBarDelegate::UpdatePasswordInfoBarDelegate(
content::WebContents* web_contents,
std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_update,
......
......@@ -9,6 +9,7 @@
#include <vector>
#include "base/macros.h"
#include "base/strings/string16.h"
#include "chrome/browser/password_manager/password_manager_infobar_delegate_android.h"
#include "chrome/browser/ui/passwords/manage_passwords_state.h"
#include "components/password_manager/core/browser/password_form_manager_for_ui.h"
......@@ -41,15 +42,21 @@ class UpdatePasswordInfoBarDelegate : public PasswordManagerInfoBarDelegate {
// credential is being affected.
bool ShowMultipleAccounts() const;
const std::vector<std::unique_ptr<autofill::PasswordForm>>&
GetCurrentForms() const;
const std::vector<std::unique_ptr<autofill::PasswordForm>>& GetCurrentForms()
const;
// Returns the username of the saved credentials to be updated by default.
const base::string16& get_default_username() const {
return passwords_state_.form_manager()
->GetPendingCredentials()
.username_value;
}
const base::string16& GetDefaultUsername() const;
// Determines the usernames to be displayed in the update infobar and returns
// the index of the one selected by default.
unsigned int GetDisplayUsernames(std::vector<base::string16>* usernames);
// Exposed for testing.
static unsigned int GetDisplayUsernames(
const std::vector<std::unique_ptr<autofill::PasswordForm>>& current_forms,
const base::string16& default_username,
std::vector<base::string16>* usernames);
protected:
// Makes a ctor available in tests.
......
......@@ -6,6 +6,7 @@
#include <memory>
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/password_manager/chrome_password_manager_client.h"
#include "chrome/browser/ui/autofill/chrome_autofill_client.h"
......@@ -18,11 +19,13 @@
#include "components/password_manager/core/browser/stub_form_saver.h"
#include "components/password_manager/core/browser/stub_password_manager_client.h"
#include "components/password_manager/core/browser/stub_password_manager_driver.h"
#include "components/strings/grit/components_strings.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
using password_manager::PasswordFormManager;
using password_manager::PasswordSaveManagerImpl;
using testing::ElementsAre;
namespace {
......@@ -51,11 +54,14 @@ class UpdatePasswordInfoBarDelegateTest
void TearDown() override;
const autofill::PasswordForm& test_form() { return test_form_; }
// TODO(crbug.com/1048107): Replace real PasswordFormManager instance with the
// mock.
std::unique_ptr<password_manager::PasswordFormManager>
CreateTestFormManager();
protected:
std::unique_ptr<PasswordManagerInfoBarDelegate> CreateDelegate(
std::unique_ptr<UpdatePasswordInfoBarDelegate> CreateDelegate(
std::unique_ptr<password_manager::PasswordFormManager>
password_form_manager,
bool is_smartlock_branding_enabled);
......@@ -115,12 +121,12 @@ UpdatePasswordInfoBarDelegateTest::CreateTestFormManager() {
return manager;
}
std::unique_ptr<PasswordManagerInfoBarDelegate>
std::unique_ptr<UpdatePasswordInfoBarDelegate>
UpdatePasswordInfoBarDelegateTest::CreateDelegate(
std::unique_ptr<password_manager::PasswordFormManager>
password_form_manager,
bool is_smartlock_branding_enabled) {
std::unique_ptr<PasswordManagerInfoBarDelegate> delegate(
std::unique_ptr<UpdatePasswordInfoBarDelegate> delegate(
new TestUpdatePasswordInfoBarDelegate(web_contents(),
std::move(password_form_manager),
is_smartlock_branding_enabled));
......@@ -145,3 +151,71 @@ TEST_F(UpdatePasswordInfoBarDelegateTest, EmptyDetailsMessageForNotSignedIn) {
false /* is_smartlock_branding_enabled */));
EXPECT_TRUE(infobar->GetDetailsMessageText().empty());
}
TEST_F(UpdatePasswordInfoBarDelegateTest, NoCurrentForms) {
std::vector<base::string16> usernames;
std::vector<std::unique_ptr<autofill::PasswordForm>> current_forms;
base::string16 default_username = base::ASCIIToUTF16("username");
unsigned int selected_username =
UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
current_forms, default_username, &usernames);
EXPECT_EQ(default_username, usernames[selected_username]);
EXPECT_THAT(usernames, ElementsAre(default_username));
}
TEST_F(UpdatePasswordInfoBarDelegateTest, MultipleCurrentForms) {
std::vector<std::unique_ptr<autofill::PasswordForm>> current_forms;
autofill::PasswordForm additional_form;
additional_form.username_value = base::ASCIIToUTF16("another username");
current_forms.push_back(std::make_unique<autofill::PasswordForm>(test_form_));
current_forms.push_back(
std::make_unique<autofill::PasswordForm>(additional_form));
base::string16 default_username = base::ASCIIToUTF16("another username");
std::vector<base::string16> usernames;
unsigned int selected_username =
UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
current_forms, default_username, &usernames);
EXPECT_EQ(default_username, usernames[selected_username]);
EXPECT_THAT(usernames,
ElementsAre(test_form_.username_value, default_username));
}
TEST_F(UpdatePasswordInfoBarDelegateTest, EmptyUsername) {
std::vector<std::unique_ptr<autofill::PasswordForm>> current_forms;
autofill::PasswordForm additional_form;
current_forms.push_back(std::make_unique<autofill::PasswordForm>(test_form_));
current_forms.push_back(
std::make_unique<autofill::PasswordForm>(additional_form));
base::string16 default_username = test_form_.username_value;
std::vector<base::string16> usernames;
unsigned int selected_username =
UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
current_forms, default_username, &usernames);
base::string16 empty_username =
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN);
EXPECT_EQ(default_username, usernames[selected_username]);
EXPECT_THAT(usernames, ElementsAre(default_username, empty_username));
}
TEST_F(UpdatePasswordInfoBarDelegateTest, DefaultUsernameNotFound) {
std::vector<std::unique_ptr<autofill::PasswordForm>> current_forms;
current_forms.push_back(std::make_unique<autofill::PasswordForm>(test_form_));
base::string16 default_username = base::ASCIIToUTF16("not found username");
std::vector<base::string16> usernames;
unsigned int selected_username =
UpdatePasswordInfoBarDelegate::GetDisplayUsernames(
current_forms, default_username, &usernames);
base::string16 empty_username =
l10n_util::GetStringUTF16(IDS_PASSWORD_MANAGER_EMPTY_LOGIN);
EXPECT_EQ(default_username, usernames[selected_username]);
EXPECT_THAT(usernames,
ElementsAre(test_form_.username_value, default_username));
}
......@@ -42,19 +42,14 @@ UpdatePasswordInfoBar::CreateRenderInfoBar(JNIEnv* env) {
env, update_password_delegate->GetDetailsMessageText());
std::vector<base::string16> usernames;
int selected_username = 0;
for (const auto& form : update_password_delegate->GetCurrentForms()) {
usernames.push_back(GetDisplayUsername(*form));
if (form->username_value ==
update_password_delegate->get_default_username()) {
selected_username = usernames.size() - 1;
}
}
unsigned int selected_username =
update_password_delegate->GetDisplayUsernames(&usernames);
ScopedJavaLocalRef<jobjectArray> display_usernames =
base::android::ToJavaArrayOfStrings(env, usernames);
base::android::ScopedJavaLocalRef<jobject> infobar;
infobar.Reset(Java_UpdatePasswordInfoBar_show(
env, GetEnumeratedIconId(),
base::android::ToJavaArrayOfStrings(env, usernames), selected_username,
env, GetEnumeratedIconId(), display_usernames, selected_username,
message_text, details_message_text, ok_button_text));
java_infobar_.Reset(env, infobar.obj());
......
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