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" | |
| 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" |
| 34 | 38 |
| 39 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
| 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 |
| 41 using password_manager::PasswordStore; | 46 using password_manager::PasswordStore; |
| 42 | 47 |
| 48 namespace { | |
| 49 | |
| 50 const int kAndroidAppSchemeAndDelimeterLength = 10; // Length of 'android://'. | |
|
vabr (Chromium)
2016/03/08 13:09:28
typo: delimeter -> delimiter
kolos1
2016/03/08 15:14:23
Done.
| |
| 51 | |
| 52 const char kSortKeyPartsSeparator = ' '; | |
| 53 | |
| 54 // Reverse order of subdomains in hostname. | |
| 55 std::string SplitByDotAndReverse(const std::string& host) { | |
|
vabr (Chromium)
2016/03/08 13:09:28
To improve efficiency, consider passing a StringPi
kolos1
2016/03/08 15:14:24
Yes, it would be nice to replace std::string with
vabr (Chromium)
2016/03/08 16:04:44
This is not about changing the SplitString/JoinStr
kolos1
2016/03/09 09:56:39
Done.
| |
| 56 std::vector<std::string> parts = | |
| 57 base::SplitString(host, ".", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); | |
| 58 std::reverse(parts.begin(), parts.end()); | |
| 59 return base::JoinString(parts, "."); | |
| 60 } | |
| 61 | |
| 62 // Helper function that returns the type of the entry (non-Android credentials, | |
| 63 // Android w/ affiliated web realm (i.e. clickable) or w/o web realm). | |
| 64 std::string GetEntryTypeCode(bool is_android_uri, bool is_clickable) { | |
| 65 if (!is_android_uri) | |
| 66 return "0"; | |
| 67 if (is_clickable) | |
| 68 return "1"; | |
| 69 return "2"; | |
| 70 } | |
| 71 | |
| 72 // Creates key for sorting password or password exception entries. | |
| 73 // The key is eTLD+1 followed by subdomains | |
| 74 // (e.g. secure.accounts.example.com => example.com.accounts.secure). | |
| 75 // If |username_and_password_in_key == true|, the key is appended with username | |
|
vabr (Chromium)
2016/03/08 13:09:28
nit: To avoid misunderstanding of what is appended
kolos1
2016/03/08 15:14:23
Done.
| |
| 76 // and hashed password. The key is also appended with entry type code | |
| 77 // (non-Android, Android w/ or w/o affiliated web realm). | |
| 78 std::string CreateSortKey(const scoped_ptr<autofill::PasswordForm>& form, | |
|
vabr (Chromium)
2016/03/08 13:09:28
Please replace the const scoped_ptr with just a ra
kolos1
2016/03/08 15:14:23
Since we don't modify |form|, I redeclared it as c
vabr (Chromium)
2016/03/08 16:04:44
Acknowledged.
| |
| 79 const std::string& languages, | |
| 80 bool username_and_password_in_key) { | |
| 81 bool is_android_uri = false; | |
| 82 bool is_clickable = false; | |
| 83 GURL link_url; | |
| 84 std::string origin = password_manager::GetShownOriginAndLinkUrl( | |
| 85 *form, languages, &is_android_uri, &link_url, &is_clickable); | |
| 86 | |
| 87 if (!is_clickable) // e.g. android://com.example.r => r.example.com. | |
| 88 origin = SplitByDotAndReverse( | |
| 89 origin.substr(kAndroidAppSchemeAndDelimeterLength)); | |
| 90 | |
| 91 std::string site_name = | |
| 92 net::registry_controlled_domains::GetDomainAndRegistry( | |
| 93 origin, net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES); | |
| 94 if (site_name.empty()) // e.g. localhost. | |
| 95 site_name = origin; | |
| 96 std::string key = site_name + SplitByDotAndReverse(origin.substr( | |
| 97 0, origin.length() - site_name.length())); | |
| 98 | |
| 99 if (username_and_password_in_key) | |
|
vabr (Chromium)
2016/03/08 13:09:28
nit: Add { and }, this is not a one-liner.
kolos1
2016/03/08 15:14:23
Done.
| |
| 100 key = key + kSortKeyPartsSeparator + | |
| 101 base::UTF16ToUTF8(form->username_value) + kSortKeyPartsSeparator + | |
| 102 base::SHA1HashString(base::UTF16ToUTF8(form->password_value)); | |
|
vabr (Chromium)
2016/03/08 14:48:24
Why do we actually hash the passwords? The keys no
kolos1
2016/03/08 15:14:23
Lets somebody want to see one of passwords listed
vabr (Chromium)
2016/03/08 16:04:44
Oh, that's a interesting good point, especially th
kolos1
2016/03/09 09:56:39
I discussed this question with security team. They
| |
| 103 | |
| 104 // Since Android and non-Android entries shouldn't be merged into one entry, | |
| 105 // add the entry type code to the sort key. | |
| 106 key += | |
| 107 kSortKeyPartsSeparator + GetEntryTypeCode(is_android_uri, is_clickable); | |
| 108 return key; | |
| 109 } | |
| 110 | |
| 111 // Finds duplicates of |form| in |duplicates|, removes them from |store| and | |
| 112 // from |duplicates|. | |
| 113 void RemoveDuplicates(const scoped_ptr<autofill::PasswordForm>& form, | |
|
vabr (Chromium)
2016/03/08 13:09:28
Also here: raw pointer instead of a scoped_ptr.
kolos1
2016/03/08 15:14:23
Since we don't modify form, redeclared as const re
vabr (Chromium)
2016/03/08 16:04:44
Acknowledged.
| |
| 114 const std::string& languages, | |
| 115 autofill::DuplicatesMap* duplicates, | |
| 116 PasswordStore* store, | |
| 117 bool username_and_password_in_key) { | |
| 118 std::string key = | |
| 119 CreateSortKey(form, languages, username_and_password_in_key); | |
| 120 std::pair<autofill::DuplicatesMap::iterator, | |
| 121 autofill::DuplicatesMap::iterator> | |
| 122 dups = duplicates->equal_range(key); | |
| 123 for (autofill::DuplicatesMap::iterator it = dups.first; it != dups.second; | |
|
vabr (Chromium)
2016/03/08 13:09:28
nit: Use range-based loop, it's shorter and easier
kolos1
2016/03/08 15:14:23
dups is a pair of iterators.
I didn't find a way
vabr (Chromium)
2016/03/08 16:04:44
Ah right, I got confused by the STL naming. :) The
| |
| 124 ++it) | |
| 125 store->RemoveLogin(*it->second); | |
| 126 duplicates->erase(key); | |
| 127 } | |
| 128 | |
| 129 } // namespace | |
| 130 | |
| 43 PasswordManagerPresenter::PasswordManagerPresenter( | 131 PasswordManagerPresenter::PasswordManagerPresenter( |
| 44 PasswordUIView* password_view) | 132 PasswordUIView* password_view) |
| 45 : populater_(this), | 133 : populater_(this), |
| 46 exception_populater_(this), | 134 exception_populater_(this), |
| 47 require_reauthentication_( | 135 require_reauthentication_( |
| 48 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 136 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 49 switches::kDisablePasswordManagerReauthentication)), | 137 switches::kDisablePasswordManagerReauthentication)), |
| 50 password_view_(password_view) { | 138 password_view_(password_view) { |
| 51 DCHECK(password_view_); | 139 DCHECK(password_view_); |
| 52 } | 140 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 91 ServiceAccessType::EXPLICIT_ACCESS) | 179 ServiceAccessType::EXPLICIT_ACCESS) |
| 92 .get(); | 180 .get(); |
| 93 } | 181 } |
| 94 | 182 |
| 95 void PasswordManagerPresenter::UpdatePasswordLists() { | 183 void PasswordManagerPresenter::UpdatePasswordLists() { |
| 96 // Reset so that showing a password will require re-authentication. | 184 // Reset so that showing a password will require re-authentication. |
| 97 last_authentication_time_ = base::TimeTicks(); | 185 last_authentication_time_ = base::TimeTicks(); |
| 98 | 186 |
| 99 // Reset the current lists. | 187 // Reset the current lists. |
| 100 password_list_.clear(); | 188 password_list_.clear(); |
| 189 password_duplicates_.clear(); | |
| 101 password_exception_list_.clear(); | 190 password_exception_list_.clear(); |
| 191 password_exception_duplicates_.clear(); | |
| 102 | 192 |
| 103 populater_.Populate(); | 193 populater_.Populate(); |
| 104 exception_populater_.Populate(); | 194 exception_populater_.Populate(); |
| 105 } | 195 } |
| 106 | 196 |
| 107 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) { | 197 void PasswordManagerPresenter::RemoveSavedPassword(size_t index) { |
| 108 if (index >= password_list_.size()) { | 198 if (index >= password_list_.size()) { |
| 109 // |index| out of bounds might come from a compromised renderer, don't let | 199 // |index| out of bounds might come from a compromised renderer, don't let |
| 110 // it crash the browser. http://crbug.com/362054 | 200 // it crash the browser. http://crbug.com/362054 |
| 111 NOTREACHED(); | 201 NOTREACHED(); |
| 112 return; | 202 return; |
| 113 } | 203 } |
| 114 PasswordStore* store = GetPasswordStore(); | 204 PasswordStore* store = GetPasswordStore(); |
| 115 if (!store) | 205 if (!store) |
| 116 return; | 206 return; |
| 207 | |
| 208 RemoveDuplicates(password_list_[index], languages_, &password_duplicates_, | |
| 209 store, true); | |
| 117 store->RemoveLogin(*password_list_[index]); | 210 store->RemoveLogin(*password_list_[index]); |
| 118 content::RecordAction( | 211 content::RecordAction( |
| 119 base::UserMetricsAction("PasswordManager_RemoveSavedPassword")); | 212 base::UserMetricsAction("PasswordManager_RemoveSavedPassword")); |
| 120 } | 213 } |
| 121 | 214 |
| 122 void PasswordManagerPresenter::RemovePasswordException(size_t index) { | 215 void PasswordManagerPresenter::RemovePasswordException(size_t index) { |
| 123 if (index >= password_exception_list_.size()) { | 216 if (index >= password_exception_list_.size()) { |
| 124 // |index| out of bounds might come from a compromised renderer, don't let | 217 // |index| out of bounds might come from a compromised renderer, don't let |
| 125 // it crash the browser. http://crbug.com/362054 | 218 // it crash the browser. http://crbug.com/362054 |
| 126 NOTREACHED(); | 219 NOTREACHED(); |
| 127 return; | 220 return; |
| 128 } | 221 } |
| 129 PasswordStore* store = GetPasswordStore(); | 222 PasswordStore* store = GetPasswordStore(); |
| 130 if (!store) | 223 if (!store) |
| 131 return; | 224 return; |
| 225 RemoveDuplicates(password_exception_list_[index], languages_, | |
| 226 &password_exception_duplicates_, store, false); | |
| 132 store->RemoveLogin(*password_exception_list_[index]); | 227 store->RemoveLogin(*password_exception_list_[index]); |
| 133 content::RecordAction( | 228 content::RecordAction( |
| 134 base::UserMetricsAction("PasswordManager_RemovePasswordException")); | 229 base::UserMetricsAction("PasswordManager_RemovePasswordException")); |
| 135 } | 230 } |
| 136 | 231 |
| 137 void PasswordManagerPresenter::RequestShowPassword(size_t index) { | 232 void PasswordManagerPresenter::RequestShowPassword(size_t index) { |
| 138 #if !defined(OS_ANDROID) // This is never called on Android. | 233 #if !defined(OS_ANDROID) // This is never called on Android. |
| 139 if (index >= password_list_.size()) { | 234 if (index >= password_list_.size()) { |
| 140 // |index| out of bounds might come from a compromised renderer, don't let | 235 // |index| out of bounds might come from a compromised renderer, don't let |
| 141 // it crash the browser. http://crbug.com/362054 | 236 // it crash the browser. http://crbug.com/362054 |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 Initialize(); | 309 Initialize(); |
| 215 | 310 |
| 216 bool show_passwords = *show_passwords_ && !require_reauthentication_; | 311 bool show_passwords = *show_passwords_ && !require_reauthentication_; |
| 217 password_view_->SetPasswordList(password_list_, show_passwords); | 312 password_view_->SetPasswordList(password_list_, show_passwords); |
| 218 } | 313 } |
| 219 | 314 |
| 220 void PasswordManagerPresenter::SetPasswordExceptionList() { | 315 void PasswordManagerPresenter::SetPasswordExceptionList() { |
| 221 password_view_->SetPasswordExceptionList(password_exception_list_); | 316 password_view_->SetPasswordExceptionList(password_exception_list_); |
| 222 } | 317 } |
| 223 | 318 |
| 319 void PasswordManagerPresenter::SortEntriesAndHideDuplicates( | |
| 320 const std::string& languages, | |
| 321 std::vector<scoped_ptr<autofill::PasswordForm>>* list, | |
| 322 autofill::DuplicatesMap* duplicates_, | |
| 323 bool username_and_password_in_key) { | |
| 324 std::vector<std::pair<std::string, scoped_ptr<autofill::PasswordForm>>> pairs; | |
| 325 pairs.reserve(list->size()); | |
| 326 for (auto& form : *list) { | |
| 327 pairs.push_back(std::make_pair( | |
| 328 CreateSortKey(form, languages, username_and_password_in_key), | |
| 329 std::move(form))); | |
| 330 } | |
| 331 | |
| 332 std::sort( | |
| 333 pairs.begin(), pairs.end(), | |
| 334 [](const std::pair<std::string, scoped_ptr<autofill::PasswordForm>>& left, | |
| 335 const std::pair<std::string, scoped_ptr<autofill::PasswordForm>>& | |
| 336 right) { return left.first < right.first; }); | |
| 337 | |
| 338 list->clear(); | |
| 339 duplicates_->clear(); | |
| 340 std::string previous_key; | |
| 341 for (auto& pair : pairs) { | |
| 342 if (pair.first != previous_key) { | |
| 343 list->push_back(std::move(pair.second)); | |
| 344 previous_key = pair.first; | |
| 345 } else { | |
| 346 duplicates_->insert(std::make_pair(previous_key, std::move(pair.second))); | |
| 347 } | |
| 348 } | |
| 349 } | |
| 350 | |
| 224 PasswordManagerPresenter::ListPopulater::ListPopulater( | 351 PasswordManagerPresenter::ListPopulater::ListPopulater( |
| 225 PasswordManagerPresenter* page) : page_(page) { | 352 PasswordManagerPresenter* page) : page_(page) { |
| 226 } | 353 } |
| 227 | 354 |
| 228 PasswordManagerPresenter::ListPopulater::~ListPopulater() { | 355 PasswordManagerPresenter::ListPopulater::~ListPopulater() { |
| 229 } | 356 } |
| 230 | 357 |
| 231 PasswordManagerPresenter::PasswordListPopulater::PasswordListPopulater( | 358 PasswordManagerPresenter::PasswordListPopulater::PasswordListPopulater( |
| 232 PasswordManagerPresenter* page) : ListPopulater(page) { | 359 PasswordManagerPresenter* page) : ListPopulater(page) { |
| 233 } | 360 } |
| 234 | 361 |
| 235 void PasswordManagerPresenter::PasswordListPopulater::Populate() { | 362 void PasswordManagerPresenter::PasswordListPopulater::Populate() { |
| 236 PasswordStore* store = page_->GetPasswordStore(); | 363 PasswordStore* store = page_->GetPasswordStore(); |
| 237 if (store != NULL) { | 364 if (store != NULL) { |
| 238 cancelable_task_tracker()->TryCancelAll(); | 365 cancelable_task_tracker()->TryCancelAll(); |
| 239 store->GetAutofillableLoginsWithAffiliatedRealms(this); | 366 store->GetAutofillableLoginsWithAffiliatedRealms(this); |
| 240 } else { | 367 } else { |
| 241 LOG(ERROR) << "No password store! Cannot display passwords."; | 368 LOG(ERROR) << "No password store! Cannot display passwords."; |
| 242 } | 369 } |
| 243 } | 370 } |
| 244 | 371 |
| 245 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults( | 372 void PasswordManagerPresenter::PasswordListPopulater::OnGetPasswordStoreResults( |
| 246 ScopedVector<autofill::PasswordForm> results) { | 373 ScopedVector<autofill::PasswordForm> results) { |
| 247 page_->password_list_ = | 374 page_->password_list_ = |
| 248 password_manager_util::ConvertScopedVector(std::move(results)); | 375 password_manager_util::ConvertScopedVector(std::move(results)); |
| 376 page_->SortEntriesAndHideDuplicates(page_->languages_, &page_->password_list_, | |
| 377 &page_->password_duplicates_, | |
| 378 true /* use username and password */); | |
| 249 page_->SetPasswordList(); | 379 page_->SetPasswordList(); |
| 250 } | 380 } |
| 251 | 381 |
| 252 PasswordManagerPresenter::PasswordExceptionListPopulater:: | 382 PasswordManagerPresenter::PasswordExceptionListPopulater:: |
| 253 PasswordExceptionListPopulater(PasswordManagerPresenter* page) | 383 PasswordExceptionListPopulater(PasswordManagerPresenter* page) |
| 254 : ListPopulater(page) { | 384 : ListPopulater(page) { |
| 255 } | 385 } |
| 256 | 386 |
| 257 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() { | 387 void PasswordManagerPresenter::PasswordExceptionListPopulater::Populate() { |
| 258 PasswordStore* store = page_->GetPasswordStore(); | 388 PasswordStore* store = page_->GetPasswordStore(); |
| 259 if (store != NULL) { | 389 if (store != NULL) { |
| 260 cancelable_task_tracker()->TryCancelAll(); | 390 cancelable_task_tracker()->TryCancelAll(); |
| 261 store->GetBlacklistLogins(this); | 391 store->GetBlacklistLogins(this); |
| 262 } else { | 392 } else { |
| 263 LOG(ERROR) << "No password store! Cannot display exceptions."; | 393 LOG(ERROR) << "No password store! Cannot display exceptions."; |
| 264 } | 394 } |
| 265 } | 395 } |
| 266 | 396 |
| 267 void PasswordManagerPresenter::PasswordExceptionListPopulater:: | 397 void PasswordManagerPresenter::PasswordExceptionListPopulater:: |
| 268 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) { | 398 OnGetPasswordStoreResults(ScopedVector<autofill::PasswordForm> results) { |
| 269 page_->password_exception_list_ = | 399 page_->password_exception_list_ = |
| 270 password_manager_util::ConvertScopedVector(std::move(results)); | 400 password_manager_util::ConvertScopedVector(std::move(results)); |
| 401 page_->SortEntriesAndHideDuplicates( | |
| 402 page_->languages_, &page_->password_exception_list_, | |
| 403 &page_->password_exception_duplicates_, | |
| 404 false /* don't use username and password*/); | |
| 271 page_->SetPasswordExceptionList(); | 405 page_->SetPasswordExceptionList(); |
| 272 } | 406 } |
| OLD | NEW |