Commit a4aeac71 authored by Victor Hugo Vianna Silva's avatar Victor Hugo Vianna Silva Committed by Commit Bot

[b4p/Settings] Plumb frontend id to JS

This CL introduces a new frontendId field to chrome.passwordsPrivate
types for passwords and exceptions. This field will be used to group
existing duplicates across stores in future CLs.

Bug: 1049141
Change-Id: Ib856778e0a06043e44d2d624d4440c38a3358527
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2210462Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: default avatarFriedrich [CET] <fhorschig@chromium.org>
Commit-Queue: Victor Vianna <victorvianna@google.com>
Cr-Commit-Position: refs/heads/master@{#772054}
parent 12674481
......@@ -341,6 +341,9 @@ void PasswordsPrivateDelegateImpl::SetPasswordList(
entry.username = base::UTF16ToUTF8(form->username_value);
entry.id = password_id_generator_.GenerateId(
password_manager::CreateSortKey(*form));
entry.frontend_id = password_frontend_id_generator_.GenerateId(
password_manager::CreateSortKey(*form,
password_manager::IgnoreStore(true)));
if (!form->federation_origin.opaque()) {
entry.federation_text.reset(new std::string(l10n_util::GetStringFUTF8(
......@@ -376,6 +379,10 @@ void PasswordsPrivateDelegateImpl::SetPasswordExceptionList(
current_exception_entry.urls = CreateUrlCollectionFromForm(*form);
current_exception_entry.id = exception_id_generator_.GenerateId(
password_manager::CreateSortKey(*form));
current_exception_entry.frontend_id =
exception_frontend_id_generator_.GenerateId(
password_manager::CreateSortKey(
*form, password_manager::IgnoreStore(true)));
current_exception_entry.from_account_store = form->IsUsingAccountStore();
current_exceptions_.push_back(std::move(current_exception_entry));
......
......@@ -162,7 +162,9 @@ class PasswordsPrivateDelegateImpl : public PasswordsPrivateDelegate,
// Generators that map between sort keys used by |password_manager_presenter_|
// and ids used by the JavaScript front end.
IdGenerator<std::string> password_id_generator_;
IdGenerator<std::string> password_frontend_id_generator_;
IdGenerator<std::string> exception_id_generator_;
IdGenerator<std::string> exception_frontend_id_generator_;
// Whether SetPasswordList and SetPasswordExceptionList have been called, and
// whether this class has been initialized, meaning both have been called.
......
......@@ -52,6 +52,7 @@ using password_manager::TestPasswordStore;
using ::testing::Eq;
using ::testing::Ne;
using ::testing::Return;
using ::testing::SizeIs;
using ::testing::StrictMock;
namespace extensions {
......@@ -247,6 +248,34 @@ TEST_F(PasswordsPrivateDelegateImplTest, GetSavedPasswordsList) {
delegate.GetSavedPasswordsList(callback.Get());
}
TEST_F(PasswordsPrivateDelegateImplTest,
PasswordsDuplicatedInStoresHaveSameFrontendId) {
PasswordsPrivateDelegateImpl delegate(&profile_);
auto account_password = std::make_unique<autofill::PasswordForm>();
account_password->in_store = autofill::PasswordForm::Store::kAccountStore;
auto profile_password = std::make_unique<autofill::PasswordForm>();
profile_password->in_store = autofill::PasswordForm::Store::kProfileStore;
PasswordFormList list;
list.push_back(std::move(account_password));
list.push_back(std::move(profile_password));
delegate.SetPasswordList(list);
base::MockCallback<PasswordsPrivateDelegate::UiEntriesCallback> callback;
int first_frontend_id, second_frontend_id;
EXPECT_CALL(callback, Run(SizeIs(2)))
.WillOnce([&](const PasswordsPrivateDelegate::UiEntries& passwords) {
first_frontend_id = passwords[0].frontend_id;
second_frontend_id = passwords[1].frontend_id;
});
delegate.GetSavedPasswordsList(callback.Get());
EXPECT_EQ(first_frontend_id, second_frontend_id);
}
TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
PasswordsPrivateDelegateImpl delegate(&profile_);
......@@ -265,6 +294,38 @@ TEST_F(PasswordsPrivateDelegateImplTest, GetPasswordExceptionsList) {
delegate.GetPasswordExceptionsList(callback.Get());
}
TEST_F(PasswordsPrivateDelegateImplTest,
ExceptionsDuplicatedInStoresHaveSameFrontendId) {
PasswordsPrivateDelegateImpl delegate(&profile_);
auto account_exception = std::make_unique<autofill::PasswordForm>();
account_exception->blacklisted_by_user = true;
account_exception->in_store = autofill::PasswordForm::Store::kAccountStore;
auto profile_exception = std::make_unique<autofill::PasswordForm>();
profile_exception->blacklisted_by_user = true;
profile_exception->in_store = autofill::PasswordForm::Store::kProfileStore;
PasswordFormList list;
list.push_back(std::move(account_exception));
list.push_back(std::move(profile_exception));
delegate.SetPasswordExceptionList(list);
base::MockCallback<PasswordsPrivateDelegate::ExceptionEntriesCallback>
callback;
int first_frontend_id, second_frontend_id;
EXPECT_CALL(callback, Run(SizeIs(2)))
.WillOnce(
[&](const PasswordsPrivateDelegate::ExceptionEntries& exceptions) {
first_frontend_id = exceptions[0].frontend_id;
second_frontend_id = exceptions[1].frontend_id;
});
delegate.GetPasswordExceptionsList(callback.Get());
EXPECT_EQ(first_frontend_id, second_frontend_id);
}
TEST_F(PasswordsPrivateDelegateImplTest, ChangeSavedPassword) {
autofill::PasswordForm sample_form = CreateSampleForm();
SetUpPasswordStore({sample_form});
......
......@@ -26,6 +26,7 @@ api::passwords_private::PasswordUiEntry CreateEntry(int id) {
entry.urls.link = entry.urls.origin;
entry.username = "testName" + base::NumberToString(id);
entry.id = id;
entry.frontend_id = id;
return entry;
}
......@@ -35,6 +36,7 @@ api::passwords_private::ExceptionEntry CreateException(int id) {
exception.urls.origin = "http://" + exception.urls.shown + "/login";
exception.urls.link = exception.urls.origin;
exception.id = id;
exception.frontend_id = id;
return exception;
}
} // namespace
......
......@@ -82,6 +82,10 @@ namespace passwordsPrivate {
// An index to refer back to a unique password entry record.
long id;
// An index to refer to an entry displayed by the UI. May correspond to
// multiple entries in the backend.
long frontend_id;
// If true, the entry came from the Gaia-account-scoped password store
// rather than from the profile-scoped one.
boolean fromAccountStore;
......@@ -94,6 +98,10 @@ namespace passwordsPrivate {
// An id to refer back to a unique exception entry record.
long id;
// An index to refer to an exception entry displayed by the UI. May
// correspond to multiple entries in the backend.
long frontend_id;
// If true, the entry came from the Gaia-account-scoped password store
// rather than from the profile-scoped one.
boolean fromAccountStore;
......
......@@ -33,6 +33,7 @@ export function createPasswordEntry(url, username, id) {
},
username: username,
id: id,
frontendId: id,
fromAccountStore: false,
};
}
......@@ -53,6 +54,7 @@ export function createExceptionEntry(url, id) {
link: 'http://' + url + '/login',
},
id: id,
frontendId: id,
fromAccountStore: false,
};
}
......
......@@ -27,7 +27,8 @@ constexpr char kSortKeyNoFederationSymbol = '-';
} // namespace
std::string CreateSortKey(const autofill::PasswordForm& form) {
std::string CreateSortKey(const autofill::PasswordForm& form,
IgnoreStore ignore_store) {
std::string shown_origin;
GURL link_url;
std::tie(shown_origin, link_url) = GetShownOriginAndLinkUrl(form);
......@@ -74,7 +75,8 @@ std::string CreateSortKey(const autofill::PasswordForm& form) {
// To separate HTTP/HTTPS credentials, add the scheme to the key.
key += kSortKeyPartsSeparator + link_url.scheme();
if (form.in_store == autofill::PasswordForm::Store::kAccountStore) {
if (!ignore_store &&
form.in_store == autofill::PasswordForm::Store::kAccountStore) {
key += kSortKeyPartsSeparator + std::string("account");
}
......
......@@ -10,6 +10,8 @@
#include <string>
#include <vector>
#include "base/util/type_safety/strong_alias.h"
namespace autofill {
struct PasswordForm;
}
......@@ -19,6 +21,7 @@ namespace password_manager {
// Multimap from sort key to password forms.
using DuplicatesMap =
std::multimap<std::string, std::unique_ptr<autofill::PasswordForm>>;
using IgnoreStore = util::StrongAlias<class IgnoreStoreTag, bool>;
// Creates key for sorting password or password exception entries. The key is
// eTLD+1 followed by the reversed list of domains (e.g.
......@@ -26,7 +29,10 @@ using DuplicatesMap =
// the scheme. If |form| is not blacklisted, username, password and federation
// are appended to the key. If not, no further information is added. For Android
// credentials the canocial spec is included.
std::string CreateSortKey(const autofill::PasswordForm& form);
// If |ignore_store| is true, forms differing only by the originating password
// store will map to the same key.
std::string CreateSortKey(const autofill::PasswordForm& form,
IgnoreStore ignore_store = IgnoreStore(false));
// Sort entries of |list| based on sort key. The key is the concatenation of
// origin, entry type (non-Android credential, Android w/ affiliated web realm
......
......@@ -189,4 +189,18 @@ TEST(PasswordListSorterTest, Sorting_SpecialCharacters) {
SortAndCheckPositions(test_cases);
}
TEST(PasswordListSorterTest, EntriesDifferingByStoreShouldMapToSameKey) {
autofill::PasswordForm account_form;
account_form.signon_realm = "https://g.com/";
account_form.origin = GURL(account_form.signon_realm);
account_form.blacklisted_by_user = false;
account_form.in_store = autofill::PasswordForm::Store::kAccountStore;
autofill::PasswordForm profile_form(account_form);
profile_form.in_store = autofill::PasswordForm::Store::kProfileStore;
EXPECT_EQ(CreateSortKey(account_form, IgnoreStore(true)),
CreateSortKey(profile_form, IgnoreStore(true)));
}
} // namespace password_manager
......@@ -73,6 +73,7 @@ chrome.passwordsPrivate.UrlCollection;
* username: string,
* federationText: (string|undefined),
* id: number,
* frontendId: number,
* fromAccountStore: boolean
* }}
*/
......@@ -82,6 +83,7 @@ chrome.passwordsPrivate.PasswordUiEntry;
* @typedef {{
* urls: !chrome.passwordsPrivate.UrlCollection,
* id: number,
* frontendId: number,
* fromAccountStore: boolean
* }}
*/
......
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