Chromium Code Reviews| 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" |
| 11 #include "base/metrics/user_metrics_action.h" | 11 #include "base/metrics/user_metrics_action.h" |
| 12 #include "base/sha1.h" | |
|
vabr (Chromium)
2016/03/09 10:00:11
This is no longer needed.
kolos1
2016/03/09 13:34:55
Done.
| |
| 13 #include "base/strings/string_piece.h" | |
| 14 #include "base/strings/string_split.h" | |
| 15 #include "base/strings/string_util.h" | |
| 12 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 14 #include "base/values.h" | 18 #include "base/values.h" |
| 15 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 16 #include "chrome/browser/password_manager/password_store_factory.h" | 20 #include "chrome/browser/password_manager/password_store_factory.h" |
| 17 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/browser/signin/signin_manager_factory.h" | 22 #include "chrome/browser/signin/signin_manager_factory.h" |
| 19 #include "chrome/browser/sync/profile_sync_service_factory.h" | 23 #include "chrome/browser/sync/profile_sync_service_factory.h" |
| 20 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" | 24 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h" |
| 21 #include "chrome/browser/ui/passwords/password_ui_view.h" | 25 #include "chrome/browser/ui/passwords/password_ui_view.h" |
| 22 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
| 23 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
| 24 #include "chrome/common/url_constants.h" | 28 #include "chrome/common/url_constants.h" |
| 25 #include "components/autofill/core/common/password_form.h" | 29 #include "components/autofill/core/common/password_form.h" |
| 26 #include "components/browser_sync/browser/profile_sync_service.h" | 30 #include "components/browser_sync/browser/profile_sync_service.h" |
| 27 #include "components/password_manager/core/browser/affiliation_utils.h" | 31 #include "components/password_manager/core/browser/affiliation_utils.h" |
| 28 #include "components/password_manager/core/browser/password_manager_util.h" | 32 #include "components/password_manager/core/browser/password_manager_util.h" |
| 33 #include "components/password_manager/core/browser/password_ui_utils.h" | |
| 29 #include "components/password_manager/core/common/password_manager_pref_names.h" | 34 #include "components/password_manager/core/common/password_manager_pref_names.h" |
| 30 #include "components/password_manager/sync/browser/password_sync_util.h" | 35 #include "components/password_manager/sync/browser/password_sync_util.h" |
| 31 #include "components/prefs/pref_service.h" | 36 #include "components/prefs/pref_service.h" |
| 32 #include "content/public/browser/user_metrics.h" | 37 #include "content/public/browser/user_metrics.h" |
| 33 #include "content/public/browser/web_contents.h" | 38 #include "content/public/browser/web_contents.h" |
| 39 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
| 34 | 40 |
| 35 #if defined(OS_WIN) | 41 #if defined(OS_WIN) |
| 36 #include "chrome/browser/password_manager/password_manager_util_win.h" | 42 #include "chrome/browser/password_manager/password_manager_util_win.h" |
| 37 #elif defined(OS_MACOSX) | 43 #elif defined(OS_MACOSX) |
| 38 #include "chrome/browser/password_manager/password_manager_util_mac.h" | 44 #include "chrome/browser/password_manager/password_manager_util_mac.h" |
| 39 #endif | 45 #endif |
| 40 | 46 |
| 47 using base::StringPiece; | |
| 41 using password_manager::PasswordStore; | 48 using password_manager::PasswordStore; |
| 42 | 49 |
| 50 namespace { | |
| 51 | |
| 52 const int kAndroidAppSchemeAndDelimiterLength = 10; // Length of 'android://'. | |
| 53 | |
| 54 const char kSortKeyPartsSeparator = ' '; | |
| 55 | |
| 56 // Reverse order of subdomains in hostname. | |
| 57 std::string SplitByDotAndReverse(StringPiece host) { | |
| 58 std::vector<std::string> parts = | |
| 59 base::SplitString(host, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 60 std::reverse(parts.begin(), parts.end()); | |
| 61 return base::JoinString(parts, "."); | |
| 62 } | |
| 63 | |
| 64 // Helper function that returns the type of the entry (non-Android credentials, | |
| 65 // Android w/ affiliated web realm (i.e. clickable) or w/o web realm). | |
| 66 std::string GetEntryTypeCode(bool is_android_uri, bool is_clickable) { | |
| 67 if (!is_android_uri) | |
| 68 return "0"; | |
| 69 if (is_clickable) | |
| 70 return "1"; | |
| 71 return "2"; | |
| 72 } | |
| 73 | |
| 74 // Creates key for sorting password or password exception entries. | |
| 75 // The key is eTLD+1 followed by subdomains | |
| 76 // (e.g. secure.accounts.example.com => example.com.accounts.secure). | |
| 77 // If |username_and_password_in_key == true|, username and hashed password is | |
| 78 // appended to the key. The entry type code (non-Android, Android w/ or w/o | |
| 79 // affiliated web realm) is also appended to the key. | |
| 80 std::string CreateSortKey(const autofill::PasswordForm& form, | |
| 81 const std::string& languages, | |
| 82 bool username_and_password_in_key) { | |
| 83 bool is_android_uri = false; | |
| 84 bool is_clickable = false; | |
| 85 GURL link_url; | |
| 86 std::string origin = password_manager::GetShownOriginAndLinkUrl( | |
| 87 form, languages, &is_android_uri, &link_url, &is_clickable); | |
| 88 | |
| 89 if (!is_clickable) { // e.g. android://com.example.r => r.example.com. | |
| 90 origin = SplitByDotAndReverse( | |
| 91 StringPiece(&origin[kAndroidAppSchemeAndDelimiterLength], | |
| 92 origin.length() - kAndroidAppSchemeAndDelimiterLength)); | |
| 93 } | |
| 94 | |
| 95 std::string site_name = | |
| 96 net::registry_controlled_domains::GetDomainAndRegistry( | |
| 97 origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | |
| 98 if (site_name.empty()) // e.g. localhost. | |
| 99 site_name = origin; | |
| 100 std::string key = | |
| 101 site_name + SplitByDotAndReverse(StringPiece( | |
| 102 &origin[0], origin.length() - site_name.length())); | |
| 103 | |
| 104 if (username_and_password_in_key) { | |
| 105 key = key + kSortKeyPartsSeparator + | |
| 106 base::UTF16ToUTF8(form.username_value) + kSortKeyPartsSeparator + | |
| 107 base::UTF16ToUTF8(form.password_value); | |
| 108 } | |
| 109 | |
| 110 // Since Android and non-Android entries shouldn't be merged into one entry, | |
| 111 // add the entry type code to the sort key. | |
| 112 key += | |
| 113 kSortKeyPartsSeparator + GetEntryTypeCode(is_android_uri, is_clickable); | |
| 114 return key; | |
| 115 } | |
| 116 | |
| 117 // Finds duplicates of |form| in |duplicates|, removes them from |store| and | |
| 118 // from |duplicates|. | |
| 119 void RemoveDuplicates(const autofill::PasswordForm& form, | |
| 120 const std::string& languages, | |
| 121 DuplicatesMap* duplicates, | |
| 122 PasswordStore* store, | |
| 123 bool username_and_password_in_key) { | |
| 124 std::string key = | |
| 125 CreateSortKey(form, languages, username_and_password_in_key); | |
| 126 std::pair<DuplicatesMap::iterator, DuplicatesMap::iterator> dups = | |
| 127 duplicates->equal_range(key); | |
| 128 for (DuplicatesMap::iterator it = dups.first; it != dups.second; ++it) | |
| 129 store->RemoveLogin(*it->second); | |
| 130 duplicates->erase(key); | |
| 131 } | |
| 132 | |
| 133 } // namespace | |
| 134 | |
| 43 PasswordManagerPresenter::PasswordManagerPresenter( | 135 PasswordManagerPresenter::PasswordManagerPresenter( |
| 44 PasswordUIView* password_view) | 136 PasswordUIView* password_view) |
| 45 : populater_(this), | 137 : populater_(this), |
| 46 exception_populater_(this), | 138 exception_populater_(this), |
| 47 require_reauthentication_( | 139 require_reauthentication_( |
| 48 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 140 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 49 switches::kDisablePasswordManagerReauthentication)), | 141 switches::kDisablePasswordManagerReauthentication)), |
| 50 password_view_(password_view) { | 142 password_view_(password_view) { |
| 51 DCHECK(password_view_); | 143 DCHECK(password_view_); |
| 52 } | 144 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 ServiceAccessType::EXPLICIT_ACCESS) | 183 ServiceAccessType::EXPLICIT_ACCESS) |
| 92 .get(); | 184 .get(); |
| 93 } | 185 } |
| 94 | 186 |
| 95 void PasswordManagerPresenter::UpdatePasswordLists() { | 187 void PasswordManagerPresenter::UpdatePasswordLists() { |
| 96 // Reset so that showing a password will require re-authentication. | 188 // Reset so that showing a password will require re-authentication. |
| 97 last_authentication_time_ = base::TimeTicks(); | 189 last_authentication_time_ = base::TimeTicks(); |
| 98 | 190 |
| 99 // Reset the current lists. | 191 // Reset the current lists. |
| 100 password_list_.clear(); | 192 password_list_.clear(); |
| 193 password_duplicates_.clear(); | |
| 101 password_exception_list_.clear(); | 194 password_exception_list_.clear(); |
| 195 password_exception_duplicates_.clear(); | |
| 102 | 196 |
| 103 populater_.Populate(); | 197 populater_.Populate(); |
| 104 exception_populater_.Populate(); | 198 exception_populater_.Populate(); |
| 105 } | 199 } |
| 106 | 200 |
| 107 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) { | 201 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) { |
| 108 if (index >= password_list_.size()) { | 202 if (index >= password_list_.size()) { |
| 109 // |index| out of bounds might come from a compromised renderer, don't let | 203 // |index| out of bounds might come from a compromised renderer, don't let |
| 110 // it crash the browser. http://crbug.com/362054 | 204 // it crash the browser. http://crbug.com/362054 |
| 111 NOTREACHED(); | 205 NOTREACHED(); |
| 112 return; | 206 return; |
| 113 } | 207 } |
| 114 PasswordStore* store = GetPasswordStore(); | 208 PasswordStore* store = GetPasswordStore(); |
| 115 if (!store) | 209 if (!store) |
| 116 return; | 210 return; |
| 211 | |
| 212 RemoveDuplicates(*password_list_[index], languages_, &password_duplicates_, | |
| 213 store, true); | |
| 117 store->RemoveLogin(*password_list_[index]); | 214 store->RemoveLogin(*password_list_[index]); |
| 118 content::RecordAction( | 215 content::RecordAction( |
| 119 base::UserMetricsAction("PasswordManager_RemoveSavedPassword")); | 216 base::UserMetricsAction("PasswordManager_RemoveSavedPassword")); |
| 120 } | 217 } |
| 121 | 218 |
| 122 void PasswordManagerPresenter::RemovePasswordException(size_t index) { | 219 void PasswordManagerPresenter::RemovePasswordException(size_t index) { |
| 123 if (index >= password_exception_list_.size()) { | 220 if (index >= password_exception_list_.size()) { |
| 124 // |index| out of bounds might come from a compromised renderer, don't let | 221 // |index| out of bounds might come from a compromised renderer, don't let |
| 125 // it crash the browser. http://crbug.com/362054 | 222 // it crash the browser. http://crbug.com/362054 |
| 126 NOTREACHED(); | 223 NOTREACHED(); |
| 127 return; | 224 return; |
| 128 } | 225 } |
| 129 PasswordStore* store = GetPasswordStore(); | 226 PasswordStore* store = GetPasswordStore(); |
| 130 if (!store) | 227 if (!store) |
| 131 return; | 228 return; |
| 229 RemoveDuplicates(*password_exception_list_[index], languages_, | |
| 230 &password_exception_duplicates_, store, false); | |
| 132 store->RemoveLogin(*password_exception_list_[index]); | 231 store->RemoveLogin(*password_exception_list_[index]); |
| 133 content::RecordAction( | 232 content::RecordAction( |
| 134 base::UserMetricsAction("PasswordManager_RemovePasswordException")); | 233 base::UserMetricsAction("PasswordManager_RemovePasswordException")); |
| 135 } | 234 } |
| 136 | 235 |
| 137 void PasswordManagerPresenter::RequestShowPassword(size_t index) { | 236 void PasswordManagerPresenter::RequestShowPassword(size_t index) { |
| 138 #if !defined(OS_ANDROID) // This is never called on Android. | 237 #if !defined(OS_ANDROID) // This is never called on Android. |
| 139 if (index >= password_list_.size()) { | 238 if (index >= password_list_.size()) { |
| 140 // |index| out of bounds might come from a compromised renderer, don't let | 239 // |index| out of bounds might come from a compromised renderer, don't let |
| 141 // it crash the browser. http://crbug.com/362054 | 240 // it crash the browser. http://crbug.com/362054 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 Initialize(); | 313 Initialize(); |
| 215 | 314 |
| 216 bool show_passwords = *show_passwords_ && !require_reauthentication_; | 315 bool show_passwords = *show_passwords_ && !require_reauthentication_; |
| 217 password_view_->SetPasswordList(password_list_, show_passwords); | 316 password_view_->SetPasswordList(password_list_, show_passwords); |
| 218 } | 317 } |
| 219 | 318 |
| 220 void PasswordManagerPresenter::SetPasswordExceptionList() { | 319 void PasswordManagerPresenter::SetPasswordExceptionList() { |
| 221 password_view_->SetPasswordExceptionList(password_exception_list_); | 320 password_view_->SetPasswordExceptionList(password_exception_list_); |
| 222 } | 321 } |
| 223 | 322 |
| 323 void PasswordManagerPresenter::SortEntriesAndHideDuplicates( | |
| 324 const std::string& languages, | |
| 325 std::vector<scoped_ptr<autofill::PasswordForm>>* list, | |
| 326 DuplicatesMap* duplicates, | |
| 327 bool username_and_password_in_key) { | |
| 328 std::vector<std::pair<std::string, scoped_ptr<autofill::PasswordForm>>> pairs; | |
| 329 pairs.reserve(list->size()); | |
| 330 for (auto& form : *list) { | |
| 331 pairs.push_back(std::make_pair( | |
| 332 CreateSortKey(*form, languages, username_and_password_in_key), | |
| 333 std::move(form))); | |
| 334 } | |
| 335 | |
| 336 std::sort( | |
| 337 pairs.begin(), pairs.end(), | |
| 338 [](const std::pair<std::string, scoped_ptr<autofill::PasswordForm>>& left, | |
| 339 const std::pair<std::string, scoped_ptr<autofill::PasswordForm>>& | |
| 340 right) { return left.first < right.first; }); | |
| 341 | |
| 342 list->clear(); | |
| 343 duplicates->clear(); | |
| 344 std::string previous_key; | |
| 345 for (auto& pair : pairs) { | |
| 346 if (pair.first != previous_key) { | |
| 347 list->push_back(std::move(pair.second)); | |
| 348 previous_key = pair.first; | |
| 349 } else { | |
| 350 duplicates->insert(std::make_pair(previous_key, std::move(pair.second))); | |
| 351 } | |
| 352 } | |
| 353 } | |
| 354 | |
| 224 PasswordManagerPresenter::ListPopulater::ListPopulater( | 355 PasswordManagerPresenter::ListPopulater::ListPopulater( |
| 225 PasswordManagerPresenter* page) : page_(page) { | 356 PasswordManagerPresenter* page) : page_(page) { |
| 226 } | 357 } |
| 227 | 358 |
| 228 PasswordManagerPresenter::ListPopulater::~ListPopulater() { | 359 PasswordManagerPresenter::ListPopulater::~ListPopulater() { |
| 229 } | 360 } |
| 230 | 361 |
| 231 PasswordManagerPresenter::PasswordListPopulater::PasswordListPopulater( | 362 PasswordManagerPresenter::PasswordListPopulater::PasswordListPopulater( |
| 232 PasswordManagerPresenter* page) : ListPopulater(page) { | 363 PasswordManagerPresenter* page) : ListPopulater(page) { |
| 233 } | 364 } |
| 234 | 365 |
| 235 void PasswordManagerPresenter::PasswordListPopulater::Populate() { | 366 void PasswordManagerPresenter::PasswordListPopulater::Populate() { |
| 236 PasswordStore* store = page_->GetPasswordStore(); | 367 PasswordStore* store = page_->GetPasswordStore(); |
| 237 if (store != NULL) { | 368 if (store != NULL) { |
| 238 cancelable_task_tracker()->TryCancelAll(); | 369 cancelable_task_tracker()->TryCancelAll(); |
| 239 store->GetAutofillableLoginsWithAffiliatedRealms(this); | 370 store->GetAutofillableLoginsWithAffiliatedRealms(this); |
| 240 } else { | 371 } else { |
| 241 LOG(ERROR) << "No password store! Cannot display passwords."; | 372 LOG(ERROR) << "No password store! Cannot display passwords."; |
| 242 } | 373 } |
| 243 } | 374 } |
| 244 | 375 |
| 245 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults( | 376 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults( |
| 246 ScopedVector<autofill::PasswordForm> results) { | 377 ScopedVector<autofill::PasswordForm> results) { |
| 247 page_->password_list_ = | 378 page_->password_list_ = |
| 248 password_manager_util::ConvertScopedVector(std::move(results)); | 379 password_manager_util::ConvertScopedVector(std::move(results)); |
| 380 page_->SortEntriesAndHideDuplicates(page_->languages_, &page_->password_list_, | |
| 381 &page_->password_duplicates_, | |
| 382 true /* use username and password */); | |
| 249 page_->SetPasswordList(); | 383 page_->SetPasswordList(); |
| 250 } | 384 } |
| 251 | 385 |
| 252 PasswordManagerPresenter::PasswordExceptionListPopulater:: | 386 PasswordManagerPresenter::PasswordExceptionListPopulater:: |
| 253 PasswordExceptionListPopulater(PasswordManagerPresenter* page) | 387 PasswordExceptionListPopulater(PasswordManagerPresenter* page) |
| 254 : ListPopulater(page) { | 388 : ListPopulater(page) { |
| 255 } | 389 } |
| 256 | 390 |
| 257 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() { | 391 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() { |
| 258 PasswordStore* store = page_->GetPasswordStore(); | 392 PasswordStore* store = page_->GetPasswordStore(); |
| 259 if (store != NULL) { | 393 if (store != NULL) { |
| 260 cancelable_task_tracker()->TryCancelAll(); | 394 cancelable_task_tracker()->TryCancelAll(); |
| 261 store->GetBlacklistLogins(this); | 395 store->GetBlacklistLogins(this); |
| 262 } else { | 396 } else { |
| 263 LOG(ERROR) << "No password store! Cannot display exceptions."; | 397 LOG(ERROR) << "No password store! Cannot display exceptions."; |
| 264 } | 398 } |
| 265 } | 399 } |
| 266 | 400 |
| 267 void PasswordManagerPresenter::PasswordExceptionListPopulater:: | 401 void PasswordManagerPresenter::PasswordExceptionListPopulater:: |
| 268 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) { | 402 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) { |
| 269 page_->password_exception_list_ = | 403 page_->password_exception_list_ = |
| 270 password_manager_util::ConvertScopedVector(std::move(results)); | 404 password_manager_util::ConvertScopedVector(std::move(results)); |
| 405 page_->SortEntriesAndHideDuplicates( | |
| 406 page_->languages_, &page_->password_exception_list_, | |
| 407 &page_->password_exception_duplicates_, | |
| 408 false /* don't use username and password*/); | |
| 271 page_->SetPasswordExceptionList(); | 409 page_->SetPasswordExceptionList(); |
| 272 } | 410 } |
| OLD | NEW |