| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/passwords/password_manager_presenter.h" | 5 #include "chrome/browser/ui/passwords/password_manager_presenter.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 69 if (!is_android_uri) | 69 if (!is_android_uri) |
| 70 return "0"; | 70 return "0"; |
| 71 if (is_clickable) | 71 if (is_clickable) |
| 72 return "1"; | 72 return "1"; |
| 73 return "2"; | 73 return "2"; |
| 74 } | 74 } |
| 75 | 75 |
| 76 // Creates key for sorting password or password exception entries. | 76 // Creates key for sorting password or password exception entries. |
| 77 // The key is eTLD+1 followed by subdomains | 77 // The key is eTLD+1 followed by subdomains |
| 78 // (e.g. secure.accounts.example.com => example.com.accounts.secure). | 78 // (e.g. secure.accounts.example.com => example.com.accounts.secure). |
| 79 // If |username_and_password_in_key == true|, username and password is appended | 79 // If |entry_type == SAVED|, username, password and federation are appended to |
| 80 // to the key. The entry type code (non-Android, Android w/ or w/o affiliated | 80 // the key. The entry type code (non-Android, Android w/ or w/o affiliated web |
| 81 // web realm) is also appended to the key. | 81 // realm) is also appended to the key. |
| 82 std::string CreateSortKey(const autofill::PasswordForm& form, | 82 std::string CreateSortKey(const autofill::PasswordForm& form, |
| 83 bool username_and_password_in_key) { | 83 PasswordEntryType entry_type) { |
| 84 bool is_android_uri = false; | 84 bool is_android_uri = false; |
| 85 bool is_clickable = false; | 85 bool is_clickable = false; |
| 86 GURL link_url; | 86 GURL link_url; |
| 87 std::string origin = password_manager::GetShownOriginAndLinkUrl( | 87 std::string origin = password_manager::GetShownOriginAndLinkUrl( |
| 88 form, &is_android_uri, &link_url, &is_clickable); | 88 form, &is_android_uri, &link_url, &is_clickable); |
| 89 | 89 |
| 90 if (!is_clickable) { // e.g. android://com.example.r => r.example.com. | 90 if (!is_clickable) { // e.g. android://com.example.r => r.example.com. |
| 91 origin = SplitByDotAndReverse( | 91 origin = SplitByDotAndReverse( |
| 92 StringPiece(&origin[kAndroidAppSchemeAndDelimiterLength], | 92 StringPiece(&origin[kAndroidAppSchemeAndDelimiterLength], |
| 93 origin.length() - kAndroidAppSchemeAndDelimiterLength)); | 93 origin.length() - kAndroidAppSchemeAndDelimiterLength)); |
| 94 } | 94 } |
| 95 | 95 |
| 96 std::string site_name = | 96 std::string site_name = |
| 97 net::registry_controlled_domains::GetDomainAndRegistry( | 97 net::registry_controlled_domains::GetDomainAndRegistry( |
| 98 origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | 98 origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); |
| 99 if (site_name.empty()) // e.g. localhost. | 99 if (site_name.empty()) // e.g. localhost. |
| 100 site_name = origin; | 100 site_name = origin; |
| 101 std::string key = | 101 std::string key = |
| 102 site_name + SplitByDotAndReverse(StringPiece( | 102 site_name + SplitByDotAndReverse(StringPiece( |
| 103 &origin[0], origin.length() - site_name.length())); | 103 &origin[0], origin.length() - site_name.length())); |
| 104 | 104 |
| 105 if (username_and_password_in_key) { | 105 if (entry_type == PasswordEntryType::SAVED) { |
| 106 key = key + kSortKeyPartsSeparator + | 106 key = key + kSortKeyPartsSeparator + |
| 107 base::UTF16ToUTF8(form.username_value) + kSortKeyPartsSeparator + | 107 base::UTF16ToUTF8(form.username_value) + kSortKeyPartsSeparator + |
| 108 base::UTF16ToUTF8(form.password_value); | 108 base::UTF16ToUTF8(form.password_value); |
| 109 if (!form.federation_origin.unique()) |
| 110 key = key + kSortKeyPartsSeparator + form.federation_origin.host(); |
| 109 } | 111 } |
| 110 | 112 |
| 111 // Since Android and non-Android entries shouldn't be merged into one entry, | 113 // Since Android and non-Android entries shouldn't be merged into one entry, |
| 112 // add the entry type code to the sort key. | 114 // add the entry type code to the sort key. |
| 113 key += | 115 key += |
| 114 kSortKeyPartsSeparator + GetEntryTypeCode(is_android_uri, is_clickable); | 116 kSortKeyPartsSeparator + GetEntryTypeCode(is_android_uri, is_clickable); |
| 115 return key; | 117 return key; |
| 116 } | 118 } |
| 117 | 119 |
| 118 // Finds duplicates of |form| in |duplicates|, removes them from |store| and | 120 // Finds duplicates of |form| in |duplicates|, removes them from |store| and |
| 119 // from |duplicates|. | 121 // from |duplicates|. |
| 120 void RemoveDuplicates(const autofill::PasswordForm& form, | 122 void RemoveDuplicates(const autofill::PasswordForm& form, |
| 121 DuplicatesMap* duplicates, | 123 DuplicatesMap* duplicates, |
| 122 PasswordStore* store, | 124 PasswordStore* store, |
| 123 bool username_and_password_in_key) { | 125 PasswordEntryType entry_type) { |
| 124 std::string key = | 126 std::string key = CreateSortKey(form, entry_type); |
| 125 CreateSortKey(form, username_and_password_in_key); | |
| 126 std::pair<DuplicatesMap::iterator, DuplicatesMap::iterator> dups = | 127 std::pair<DuplicatesMap::iterator, DuplicatesMap::iterator> dups = |
| 127 duplicates->equal_range(key); | 128 duplicates->equal_range(key); |
| 128 for (DuplicatesMap::iterator it = dups.first; it != dups.second; ++it) | 129 for (DuplicatesMap::iterator it = dups.first; it != dups.second; ++it) |
| 129 store->RemoveLogin(*it->second); | 130 store->RemoveLogin(*it->second); |
| 130 duplicates->erase(key); | 131 duplicates->erase(key); |
| 131 } | 132 } |
| 132 | 133 |
| 133 } // namespace | 134 } // namespace |
| 134 | 135 |
| 135 PasswordManagerPresenter::PasswordManagerPresenter( | 136 PasswordManagerPresenter::PasswordManagerPresenter( |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 183 // |index| out of bounds might come from a compromised renderer | 184 // |index| out of bounds might come from a compromised renderer |
| 184 // (http://crbug.com/362054), or the user removed a password while a request | 185 // (http://crbug.com/362054), or the user removed a password while a request |
| 185 // to the store is in progress (i.e. |password_list_| is empty). | 186 // to the store is in progress (i.e. |password_list_| is empty). |
| 186 // Don't let it crash the browser. | 187 // Don't let it crash the browser. |
| 187 return; | 188 return; |
| 188 } | 189 } |
| 189 PasswordStore* store = GetPasswordStore(); | 190 PasswordStore* store = GetPasswordStore(); |
| 190 if (!store) | 191 if (!store) |
| 191 return; | 192 return; |
| 192 | 193 |
| 193 RemoveDuplicates(*password_list_[index], &password_duplicates_, | 194 RemoveDuplicates(*password_list_[index], &password_duplicates_, store, |
| 194 store, true); | 195 PasswordEntryType::SAVED); |
| 195 store->RemoveLogin(*password_list_[index]); | 196 store->RemoveLogin(*password_list_[index]); |
| 196 content::RecordAction( | 197 content::RecordAction( |
| 197 base::UserMetricsAction("PasswordManager_RemoveSavedPassword")); | 198 base::UserMetricsAction("PasswordManager_RemoveSavedPassword")); |
| 198 } | 199 } |
| 199 | 200 |
| 200 void PasswordManagerPresenter::RemovePasswordException(size_t index) { | 201 void PasswordManagerPresenter::RemovePasswordException(size_t index) { |
| 201 if (index >= password_exception_list_.size()) { | 202 if (index >= password_exception_list_.size()) { |
| 202 // |index| out of bounds might come from a compromised renderer | 203 // |index| out of bounds might come from a compromised renderer |
| 203 // (http://crbug.com/362054), or the user removed a password exception while | 204 // (http://crbug.com/362054), or the user removed a password exception while |
| 204 // a request to the store is in progress (i.e. |password_exception_list_| | 205 // a request to the store is in progress (i.e. |password_exception_list_| |
| 205 // is empty). Don't let it crash the browser. | 206 // is empty). Don't let it crash the browser. |
| 206 return; | 207 return; |
| 207 } | 208 } |
| 208 PasswordStore* store = GetPasswordStore(); | 209 PasswordStore* store = GetPasswordStore(); |
| 209 if (!store) | 210 if (!store) |
| 210 return; | 211 return; |
| 211 RemoveDuplicates(*password_exception_list_[index], | 212 RemoveDuplicates(*password_exception_list_[index], |
| 212 &password_exception_duplicates_, store, false); | 213 &password_exception_duplicates_, store, |
| 214 PasswordEntryType::BLACKLISTED); |
| 213 store->RemoveLogin(*password_exception_list_[index]); | 215 store->RemoveLogin(*password_exception_list_[index]); |
| 214 content::RecordAction( | 216 content::RecordAction( |
| 215 base::UserMetricsAction("PasswordManager_RemovePasswordException")); | 217 base::UserMetricsAction("PasswordManager_RemovePasswordException")); |
| 216 } | 218 } |
| 217 | 219 |
| 218 void PasswordManagerPresenter::RequestShowPassword(size_t index) { | 220 void PasswordManagerPresenter::RequestShowPassword(size_t index) { |
| 219 #if !defined(OS_ANDROID) // This is never called on Android. | 221 #if !defined(OS_ANDROID) // This is never called on Android. |
| 220 if (index >= password_list_.size()) { | 222 if (index >= password_list_.size()) { |
| 221 // |index| out of bounds might come from a compromised renderer | 223 // |index| out of bounds might come from a compromised renderer |
| 222 // (http://crbug.com/362054), or the user requested to show a password while | 224 // (http://crbug.com/362054), or the user requested to show a password while |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 password_view_->SetPasswordList(password_list_); | 294 password_view_->SetPasswordList(password_list_); |
| 293 } | 295 } |
| 294 | 296 |
| 295 void PasswordManagerPresenter::SetPasswordExceptionList() { | 297 void PasswordManagerPresenter::SetPasswordExceptionList() { |
| 296 password_view_->SetPasswordExceptionList(password_exception_list_); | 298 password_view_->SetPasswordExceptionList(password_exception_list_); |
| 297 } | 299 } |
| 298 | 300 |
| 299 void PasswordManagerPresenter::SortEntriesAndHideDuplicates( | 301 void PasswordManagerPresenter::SortEntriesAndHideDuplicates( |
| 300 std::vector<std::unique_ptr<autofill::PasswordForm>>* list, | 302 std::vector<std::unique_ptr<autofill::PasswordForm>>* list, |
| 301 DuplicatesMap* duplicates, | 303 DuplicatesMap* duplicates, |
| 302 bool username_and_password_in_key) { | 304 PasswordEntryType entry_type) { |
| 303 std::vector<std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>> | 305 std::vector<std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>> |
| 304 pairs; | 306 pairs; |
| 305 pairs.reserve(list->size()); | 307 pairs.reserve(list->size()); |
| 306 for (auto& form : *list) { | 308 for (auto& form : *list) { |
| 307 pairs.push_back(std::make_pair( | 309 pairs.push_back( |
| 308 CreateSortKey(*form, username_and_password_in_key), std::move(form))); | 310 std::make_pair(CreateSortKey(*form, entry_type), std::move(form))); |
| 309 } | 311 } |
| 310 | 312 |
| 311 std::sort( | 313 std::sort( |
| 312 pairs.begin(), pairs.end(), | 314 pairs.begin(), pairs.end(), |
| 313 [](const std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>& | 315 [](const std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>& |
| 314 left, | 316 left, |
| 315 const std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>& | 317 const std::pair<std::string, std::unique_ptr<autofill::PasswordForm>>& |
| 316 right) { return left.first < right.first; }); | 318 right) { return left.first < right.first; }); |
| 317 | 319 |
| 318 list->clear(); | 320 list->clear(); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 LOG(ERROR) << "No password store! Cannot display passwords."; | 370 LOG(ERROR) << "No password store! Cannot display passwords."; |
| 369 } | 371 } |
| 370 } | 372 } |
| 371 | 373 |
| 372 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults( | 374 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults( |
| 373 ScopedVector<autofill::PasswordForm> results) { | 375 ScopedVector<autofill::PasswordForm> results) { |
| 374 page_->password_list_ = | 376 page_->password_list_ = |
| 375 password_manager_util::ConvertScopedVector(std::move(results)); | 377 password_manager_util::ConvertScopedVector(std::move(results)); |
| 376 page_->SortEntriesAndHideDuplicates(&page_->password_list_, | 378 page_->SortEntriesAndHideDuplicates(&page_->password_list_, |
| 377 &page_->password_duplicates_, | 379 &page_->password_duplicates_, |
| 378 true /* use username and password */); | 380 PasswordEntryType::SAVED); |
| 379 page_->SetPasswordList(); | 381 page_->SetPasswordList(); |
| 380 } | 382 } |
| 381 | 383 |
| 382 PasswordManagerPresenter::PasswordExceptionListPopulater:: | 384 PasswordManagerPresenter::PasswordExceptionListPopulater:: |
| 383 PasswordExceptionListPopulater(PasswordManagerPresenter* page) | 385 PasswordExceptionListPopulater(PasswordManagerPresenter* page) |
| 384 : ListPopulater(page) { | 386 : ListPopulater(page) { |
| 385 } | 387 } |
| 386 | 388 |
| 387 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() { | 389 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() { |
| 388 PasswordStore* store = page_->GetPasswordStore(); | 390 PasswordStore* store = page_->GetPasswordStore(); |
| 389 if (store != NULL) { | 391 if (store != NULL) { |
| 390 cancelable_task_tracker()->TryCancelAll(); | 392 cancelable_task_tracker()->TryCancelAll(); |
| 391 store->GetBlacklistLoginsWithAffiliatedRealms(this); | 393 store->GetBlacklistLoginsWithAffiliatedRealms(this); |
| 392 } else { | 394 } else { |
| 393 LOG(ERROR) << "No password store! Cannot display exceptions."; | 395 LOG(ERROR) << "No password store! Cannot display exceptions."; |
| 394 } | 396 } |
| 395 } | 397 } |
| 396 | 398 |
| 397 void PasswordManagerPresenter::PasswordExceptionListPopulater:: | 399 void PasswordManagerPresenter::PasswordExceptionListPopulater:: |
| 398 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) { | 400 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) { |
| 399 page_->password_exception_list_ = | 401 page_->password_exception_list_ = |
| 400 password_manager_util::ConvertScopedVector(std::move(results)); | 402 password_manager_util::ConvertScopedVector(std::move(results)); |
| 401 page_->SortEntriesAndHideDuplicates(&page_->password_exception_list_, | 403 page_->SortEntriesAndHideDuplicates(&page_->password_exception_list_, |
| 402 &page_->password_exception_duplicates_, | 404 &page_->password_exception_duplicates_, |
| 403 false /* don't use username and password*/); | 405 PasswordEntryType::BLACKLISTED); |
| 404 page_->SetPasswordExceptionList(); | 406 page_->SetPasswordExceptionList(); |
| 405 } | 407 } |
| OLD | NEW |