Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(656)

Unified Diff: chrome/browser/ui/passwords/password_manager_presenter.cc

Issue 1589483002: [Password Manager] Implements entries sorting and duplicates omitting on chrome://settings/passwords (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mistype in a comment Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/passwords/password_manager_presenter.cc
diff --git a/chrome/browser/ui/passwords/password_manager_presenter.cc b/chrome/browser/ui/passwords/password_manager_presenter.cc
index 1b30d119803487ee8b2aeea6968e618c7c7c9078..23fa5cbaced13172587c9a57c362654f7cb37866 100644
--- a/chrome/browser/ui/passwords/password_manager_presenter.cc
+++ b/chrome/browser/ui/passwords/password_manager_presenter.cc
@@ -9,6 +9,9 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/metrics/user_metrics_action.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
@@ -26,11 +29,13 @@
#include "components/browser_sync/browser/profile_sync_service.h"
#include "components/password_manager/core/browser/affiliation_utils.h"
#include "components/password_manager/core/browser/password_manager_util.h"
+#include "components/password_manager/core/browser/password_ui_utils.h"
#include "components/password_manager/core/common/password_manager_pref_names.h"
#include "components/password_manager/sync/browser/password_sync_util.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#if defined(OS_WIN)
#include "chrome/browser/password_manager/password_manager_util_win.h"
@@ -38,8 +43,94 @@
#include "chrome/browser/password_manager/password_manager_util_mac.h"
#endif
+using base::StringPiece;
using password_manager::PasswordStore;
+namespace {
+
+const int kAndroidAppSchemeAndDelimiterLength = 10; // Length of 'android://'.
+
+const char kSortKeyPartsSeparator = ' ';
+
+// Reverse order of subdomains in hostname.
+std::string SplitByDotAndReverse(StringPiece host) {
+ std::vector<std::string> parts =
+ base::SplitString(host, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ std::reverse(parts.begin(), parts.end());
+ return base::JoinString(parts, ".");
+}
+
+// Helper function that returns the type of the entry (non-Android credentials,
+// Android w/ affiliated web realm (i.e. clickable) or w/o web realm).
+std::string GetEntryTypeCode(bool is_android_uri, bool is_clickable) {
+ if (!is_android_uri)
+ return "0";
+ if (is_clickable)
+ return "1";
+ return "2";
+}
+
+// Creates key for sorting password or password exception entries.
+// The key is eTLD+1 followed by subdomains
+// (e.g. secure.accounts.example.com => example.com.accounts.secure).
+// If |username_and_password_in_key == true|, username and password is appended
+// to the key. The entry type code (non-Android, Android w/ or w/o affiliated
+// web realm) is also appended to the key.
+std::string CreateSortKey(const autofill::PasswordForm& form,
+ const std::string& languages,
+ bool username_and_password_in_key) {
+ bool is_android_uri = false;
+ bool is_clickable = false;
+ GURL link_url;
+ std::string origin = password_manager::GetShownOriginAndLinkUrl(
+ form, languages, &is_android_uri, &link_url, &is_clickable);
+
+ if (!is_clickable) { // e.g. android://com.example.r => r.example.com.
+ origin = SplitByDotAndReverse(
+ StringPiece(&origin[kAndroidAppSchemeAndDelimiterLength],
+ origin.length() - kAndroidAppSchemeAndDelimiterLength));
+ }
+
+ std::string site_name =
+ net::registry_controlled_domains::GetDomainAndRegistry(
+ origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ if (site_name.empty()) // e.g. localhost.
+ site_name = origin;
+ std::string key =
+ site_name + SplitByDotAndReverse(StringPiece(
+ &origin[0], origin.length() - site_name.length()));
+
+ if (username_and_password_in_key) {
+ key = key + kSortKeyPartsSeparator +
+ base::UTF16ToUTF8(form.username_value) + kSortKeyPartsSeparator +
+ base::UTF16ToUTF8(form.password_value);
+ }
+
+ // Since Android and non-Android entries shouldn't be merged into one entry,
+ // add the entry type code to the sort key.
+ key +=
+ kSortKeyPartsSeparator + GetEntryTypeCode(is_android_uri, is_clickable);
+ return key;
+}
+
+// Finds duplicates of |form| in |duplicates|, removes them from |store| and
+// from |duplicates|.
+void RemoveDuplicates(const autofill::PasswordForm& form,
+ const std::string& languages,
+ DuplicatesMap* duplicates,
+ PasswordStore* store,
+ bool username_and_password_in_key) {
+ std::string key =
+ CreateSortKey(form, languages, username_and_password_in_key);
+ std::pair<DuplicatesMap::iterator, DuplicatesMap::iterator> dups =
+ duplicates->equal_range(key);
+ for (DuplicatesMap::iterator it = dups.first; it != dups.second; ++it)
+ store->RemoveLogin(*it->second);
+ duplicates->erase(key);
+}
+
+} // namespace
+
PasswordManagerPresenter::PasswordManagerPresenter(
PasswordUIView* password_view)
: populater_(this),
@@ -98,7 +189,9 @@ void PasswordManagerPresenter::UpdatePasswordLists() {
// Reset the current lists.
password_list_.clear();
+ password_duplicates_.clear();
password_exception_list_.clear();
+ password_exception_duplicates_.clear();
populater_.Populate();
exception_populater_.Populate();
@@ -114,6 +207,9 @@ void PasswordManagerPresenter::RemoveSavedPassword(size_t index) {
PasswordStore* store = GetPasswordStore();
if (!store)
return;
+
+ RemoveDuplicates(*password_list_[index], languages_, &password_duplicates_,
+ store, true);
store->RemoveLogin(*password_list_[index]);
content::RecordAction(
base::UserMetricsAction("PasswordManager_RemoveSavedPassword"));
@@ -129,6 +225,8 @@ void PasswordManagerPresenter::RemovePasswordException(size_t index) {
PasswordStore* store = GetPasswordStore();
if (!store)
return;
+ RemoveDuplicates(*password_exception_list_[index], languages_,
+ &password_exception_duplicates_, store, false);
store->RemoveLogin(*password_exception_list_[index]);
content::RecordAction(
base::UserMetricsAction("PasswordManager_RemovePasswordException"));
@@ -221,6 +319,38 @@ void PasswordManagerPresenter::SetPasswordExceptionList() {
password_view_->SetPasswordExceptionList(password_exception_list_);
}
+void PasswordManagerPresenter::SortEntriesAndHideDuplicates(
+ const std::string& languages,
+ std::vector<scoped_ptr<autofill::PasswordForm>>* list,
+ DuplicatesMap* duplicates,
+ bool username_and_password_in_key) {
+ std::vector<std::pair<std::string, scoped_ptr<autofill::PasswordForm>>> pairs;
+ pairs.reserve(list->size());
+ for (auto& form : *list) {
+ pairs.push_back(std::make_pair(
+ CreateSortKey(*form, languages, username_and_password_in_key),
+ std::move(form)));
+ }
+
+ std::sort(
+ pairs.begin(), pairs.end(),
+ [](const std::pair<std::string, scoped_ptr<autofill::PasswordForm>>& left,
+ const std::pair<std::string, scoped_ptr<autofill::PasswordForm>>&
+ right) { return left.first < right.first; });
+
+ list->clear();
+ duplicates->clear();
+ std::string previous_key;
+ for (auto& pair : pairs) {
+ if (pair.first != previous_key) {
+ list->push_back(std::move(pair.second));
+ previous_key = pair.first;
+ } else {
+ duplicates->insert(std::make_pair(previous_key, std::move(pair.second)));
+ }
+ }
+}
+
PasswordManagerPresenter::ListPopulater::ListPopulater(
PasswordManagerPresenter* page) : page_(page) {
}
@@ -246,6 +376,9 @@ void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults(
ScopedVector<autofill::PasswordForm> results) {
page_->password_list_ =
password_manager_util::ConvertScopedVector(std::move(results));
+ page_->SortEntriesAndHideDuplicates(page_->languages_, &page_->password_list_,
+ &page_->password_duplicates_,
+ true /* use username and password */);
page_->SetPasswordList();
}
@@ -268,5 +401,9 @@ void PasswordManagerPresenter::PasswordExceptionListPopulater::
OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) {
page_->password_exception_list_ =
password_manager_util::ConvertScopedVector(std::move(results));
+ page_->SortEntriesAndHideDuplicates(
+ page_->languages_, &page_->password_exception_list_,
+ &page_->password_exception_duplicates_,
+ false /* don't use username and password*/);
page_->SetPasswordExceptionList();
}

Powered by Google App Engine
This is Rietveld 408576698