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