Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/password_manager/password_manager.h" | 5 #include "chrome/browser/password_manager/password_manager.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
| 11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
| 14 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 14 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
| 15 #include "chrome/browser/password_manager/password_form_manager.h" | 15 #include "chrome/browser/password_manager/password_form_manager.h" |
| 16 #include "chrome/browser/password_manager/password_manager_delegate.h" | 16 #include "chrome/browser/password_manager/password_manager_delegate.h" |
| 17 #include "chrome/browser/password_manager/password_manager_util.h" | |
| 17 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
| 18 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
| 19 #include "chrome/common/chrome_version_info.h" | 20 #include "chrome/common/chrome_version_info.h" |
| 20 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
| 21 #include "components/autofill/core/common/autofill_messages.h" | 22 #include "components/autofill/core/common/autofill_messages.h" |
| 22 #include "components/user_prefs/pref_registry_syncable.h" | 23 #include "components/user_prefs/pref_registry_syncable.h" |
| 23 #include "content/public/browser/navigation_details.h" | 24 #include "content/public/browser/navigation_details.h" |
| 24 #include "content/public/browser/user_metrics.h" | 25 #include "content/public/browser/user_metrics.h" |
| 25 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
| 26 #include "content/public/common/frame_navigate_params.h" | 27 #include "content/public/common/frame_navigate_params.h" |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 48 void ReportMetrics(bool password_manager_enabled) { | 49 void ReportMetrics(bool password_manager_enabled) { |
| 49 static base::PlatformThreadId initial_thread_id = | 50 static base::PlatformThreadId initial_thread_id = |
| 50 base::PlatformThread::CurrentId(); | 51 base::PlatformThread::CurrentId(); |
| 51 DCHECK(initial_thread_id == base::PlatformThread::CurrentId()); | 52 DCHECK(initial_thread_id == base::PlatformThread::CurrentId()); |
| 52 | 53 |
| 53 static bool ran_once = false; | 54 static bool ran_once = false; |
| 54 if (ran_once) | 55 if (ran_once) |
| 55 return; | 56 return; |
| 56 ran_once = true; | 57 ran_once = true; |
| 57 | 58 |
| 58 // TODO(isherman): This does not actually measure a user action. It should be | |
| 59 // a boolean histogram. | |
| 60 if (password_manager_enabled) | 59 if (password_manager_enabled) |
| 61 content::RecordAction(UserMetricsAction("PasswordManager_Enabled")); | 60 UMA_HISTOGRAM_BOOLEAN("PasswordManager.PasswordManager_Enabled", true); |
| 62 else | 61 else |
| 63 content::RecordAction(UserMetricsAction("PasswordManager_Disabled")); | 62 UMA_HISTOGRAM_BOOLEAN("PasswordManager.PasswordManager_Enabled", false); |
|
Garrett Casto
2013/08/28 01:09:17
I would think that the name should be "PasswordMan
| |
| 64 } | 63 } |
| 65 | 64 |
| 66 } // namespace | 65 } // namespace |
| 67 | 66 |
| 68 // static | 67 // static |
| 69 void PasswordManager::RegisterProfilePrefs( | 68 void PasswordManager::RegisterProfilePrefs( |
| 70 user_prefs::PrefRegistrySyncable* registry) { | 69 user_prefs::PrefRegistrySyncable* registry) { |
| 71 registry->RegisterBooleanPref( | 70 registry->RegisterBooleanPref( |
| 72 prefs::kPasswordManagerEnabled, | 71 prefs::kPasswordManagerEnabled, |
| 73 true, | 72 true, |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 132 // TODO(gcasto): Add UMA stats to track this. | 131 // TODO(gcasto): Add UMA stats to track this. |
| 133 } | 132 } |
| 134 | 133 |
| 135 bool PasswordManager::IsSavingEnabled() const { | 134 bool PasswordManager::IsSavingEnabled() const { |
| 136 return *password_manager_enabled_ && | 135 return *password_manager_enabled_ && |
| 137 !delegate_->GetProfile()->IsOffTheRecord(); | 136 !delegate_->GetProfile()->IsOffTheRecord(); |
| 138 } | 137 } |
| 139 | 138 |
| 140 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { | 139 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { |
| 141 if (!IsSavingEnabled()) { | 140 if (!IsSavingEnabled()) { |
| 142 RecordFailure(SAVING_DISABLED); | 141 RecordFailure(SAVING_DISABLED, form.origin.host()); |
| 143 return; | 142 return; |
| 144 } | 143 } |
| 145 | 144 |
| 146 // No password to save? Then don't. | 145 // No password to save? Then don't. |
| 147 if (form.password_value.empty()) { | 146 if (form.password_value.empty()) { |
| 148 RecordFailure(EMPTY_PASSWORD); | 147 RecordFailure(EMPTY_PASSWORD, form.origin.host()); |
| 149 return; | 148 return; |
| 150 } | 149 } |
| 151 | 150 |
| 152 scoped_ptr<PasswordFormManager> manager; | 151 scoped_ptr<PasswordFormManager> manager; |
| 153 ScopedVector<PasswordFormManager>::iterator matched_manager_it = | 152 ScopedVector<PasswordFormManager>::iterator matched_manager_it = |
| 154 pending_login_managers_.end(); | 153 pending_login_managers_.end(); |
| 155 for (ScopedVector<PasswordFormManager>::iterator iter = | 154 for (ScopedVector<PasswordFormManager>::iterator iter = |
| 156 pending_login_managers_.begin(); | 155 pending_login_managers_.begin(); |
| 157 iter != pending_login_managers_.end(); ++iter) { | 156 iter != pending_login_managers_.end(); ++iter) { |
| 158 // If we find a manager that exactly matches the submitted form including | 157 // If we find a manager that exactly matches the submitted form including |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 171 } | 170 } |
| 172 // If we didn't find a manager, this means a form was submitted without | 171 // If we didn't find a manager, this means a form was submitted without |
| 173 // first loading the page containing the form. Don't offer to save | 172 // first loading the page containing the form. Don't offer to save |
| 174 // passwords in this case. | 173 // passwords in this case. |
| 175 if (matched_manager_it != pending_login_managers_.end()) { | 174 if (matched_manager_it != pending_login_managers_.end()) { |
| 176 // Transfer ownership of the manager from |pending_login_managers_| to | 175 // Transfer ownership of the manager from |pending_login_managers_| to |
| 177 // |manager|. | 176 // |manager|. |
| 178 manager.reset(*matched_manager_it); | 177 manager.reset(*matched_manager_it); |
| 179 pending_login_managers_.weak_erase(matched_manager_it); | 178 pending_login_managers_.weak_erase(matched_manager_it); |
| 180 } else { | 179 } else { |
| 181 RecordFailure(NO_MATCHING_FORM); | 180 RecordFailure(NO_MATCHING_FORM, form.origin.host()); |
| 182 return; | 181 return; |
| 183 } | 182 } |
| 184 | 183 |
| 185 // If we found a manager but it didn't finish matching yet, the user has | 184 // If we found a manager but it didn't finish matching yet, the user has |
| 186 // tried to submit credentials before we had time to even find matching | 185 // tried to submit credentials before we had time to even find matching |
| 187 // results for the given form and autofill. If this is the case, we just | 186 // results for the given form and autofill. If this is the case, we just |
| 188 // give up. | 187 // give up. |
| 189 if (!manager->HasCompletedMatching()) { | 188 if (!manager->HasCompletedMatching()) { |
| 190 RecordFailure(MATCHING_NOT_COMPLETE); | 189 RecordFailure(MATCHING_NOT_COMPLETE, form.origin.host()); |
| 191 return; | 190 return; |
| 192 } | 191 } |
| 193 | 192 |
| 194 // Also get out of here if the user told us to 'never remember' passwords for | 193 // Also get out of here if the user told us to 'never remember' passwords for |
| 195 // this form. | 194 // this form. |
| 196 if (manager->IsBlacklisted()) { | 195 if (manager->IsBlacklisted()) { |
| 197 RecordFailure(FORM_BLACKLISTED); | 196 RecordFailure(FORM_BLACKLISTED, form.origin.host()); |
| 198 return; | 197 return; |
| 199 } | 198 } |
| 200 | 199 |
| 201 // Bail if we're missing any of the necessary form components. | 200 // Bail if we're missing any of the necessary form components. |
| 202 if (!manager->HasValidPasswordForm()) { | 201 if (!manager->HasValidPasswordForm()) { |
| 203 RecordFailure(INVALID_FORM); | 202 RecordFailure(INVALID_FORM, form.origin.host()); |
| 204 return; | 203 return; |
| 205 } | 204 } |
| 206 | 205 |
| 207 // Always save generated passwords, as the user expresses explicit intent for | 206 // Always save generated passwords, as the user expresses explicit intent for |
| 208 // Chrome to manage such passwords. For other passwords, respect the | 207 // Chrome to manage such passwords. For other passwords, respect the |
| 209 // autocomplete attribute. | 208 // autocomplete attribute. |
| 210 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) { | 209 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) { |
| 211 RecordFailure(AUTOCOMPLETE_OFF); | 210 RecordFailure(AUTOCOMPLETE_OFF, form.origin.host()); |
| 212 return; | 211 return; |
| 213 } | 212 } |
| 214 | 213 |
| 215 PasswordForm provisionally_saved_form(form); | 214 PasswordForm provisionally_saved_form(form); |
| 216 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && | 215 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && |
| 217 !delegate_->DidLastPageLoadEncounterSSLErrors(); | 216 !delegate_->DidLastPageLoadEncounterSSLErrors(); |
| 218 provisionally_saved_form.preferred = true; | 217 provisionally_saved_form.preferred = true; |
| 219 PasswordFormManager::OtherPossibleUsernamesAction action = | 218 PasswordFormManager::OtherPossibleUsernamesAction action = |
| 220 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; | 219 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; |
| 221 if (OtherPossibleUsernamesEnabled()) | 220 if (OtherPossibleUsernamesEnabled()) |
| 222 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; | 221 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; |
| 223 manager->ProvisionallySave(provisionally_saved_form, action); | 222 manager->ProvisionallySave(provisionally_saved_form, action); |
| 224 provisional_save_manager_.swap(manager); | 223 provisional_save_manager_.swap(manager); |
| 225 } | 224 } |
| 226 | 225 |
| 227 void PasswordManager::RecordFailure(ProvisionalSaveFailure failure) { | 226 void PasswordManager::RecordFailure(ProvisionalSaveFailure failure, |
| 227 const std::string& url_host) { | |
| 228 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ProvisionalSaveFailure", | 228 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ProvisionalSaveFailure", |
| 229 failure, MAX_FAILURE_VALUE); | 229 failure, MAX_FAILURE_VALUE); |
| 230 | |
| 231 std::string domain_name; | |
| 232 if (PasswordManagerUtil::IsDomainNameMonitored(url_host, domain_name)) { | |
| 233 domain_name.insert(0, "_"); | |
| 234 UMA_HISTOGRAM_ENUMERATION( | |
|
Garrett Casto
2013/08/28 01:09:17
Unfortunately this doesn't work. If you check out
jdomingos
2013/08/28 15:23:20
Normally I think it should work because I added a
Garrett Casto
2013/08/28 19:15:19
I think you pasted the wrong link.
Do you mean yo
| |
| 235 "PasswordManager.ProvisionalSaveFailure" + domain_name, failure, | |
| 236 MAX_FAILURE_VALUE); | |
| 237 } | |
| 230 } | 238 } |
| 231 | 239 |
| 232 void PasswordManager::AddSubmissionCallback( | 240 void PasswordManager::AddSubmissionCallback( |
| 233 const PasswordSubmittedCallback& callback) { | 241 const PasswordSubmittedCallback& callback) { |
| 234 submission_callbacks_.push_back(callback); | 242 submission_callbacks_.push_back(callback); |
| 235 } | 243 } |
| 236 | 244 |
| 237 void PasswordManager::AddObserver(LoginModelObserver* observer) { | 245 void PasswordManager::AddObserver(LoginModelObserver* observer) { |
| 238 observers_.AddObserver(observer); | 246 observers_.AddObserver(observer); |
| 239 } | 247 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 294 web_contents(), | 302 web_contents(), |
| 295 *iter, | 303 *iter, |
| 296 ssl_valid); | 304 ssl_valid); |
| 297 pending_login_managers_.push_back(manager); | 305 pending_login_managers_.push_back(manager); |
| 298 manager->FetchMatchingLoginsFromPasswordStore(); | 306 manager->FetchMatchingLoginsFromPasswordStore(); |
| 299 } | 307 } |
| 300 } | 308 } |
| 301 | 309 |
| 302 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { | 310 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { |
| 303 return provisional_save_manager_->IsNewLogin() && | 311 return provisional_save_manager_->IsNewLogin() && |
| 304 !provisional_save_manager_->HasGeneratedPassword() && | 312 !provisional_save_manager_->HasGeneratedPassword() && |
| 305 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); | 313 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); |
| 306 } | 314 } |
| 307 | 315 |
| 308 void PasswordManager::OnPasswordFormsRendered( | 316 void PasswordManager::OnPasswordFormsRendered( |
| 309 const std::vector<PasswordForm>& visible_forms) { | 317 const std::vector<PasswordForm>& visible_forms) { |
| 310 if (!provisional_save_manager_.get()) | 318 if (!provisional_save_manager_.get()) |
| 311 return; | 319 return; |
| 312 | 320 |
| 313 DCHECK(IsSavingEnabled()); | 321 DCHECK(IsSavingEnabled()); |
| 314 | 322 |
| 315 // First, check for a failed login attempt. | 323 // First, check for a failed login attempt. |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 return; | 428 return; |
| 421 } | 429 } |
| 422 default: | 430 default: |
| 423 FOR_EACH_OBSERVER( | 431 FOR_EACH_OBSERVER( |
| 424 LoginModelObserver, | 432 LoginModelObserver, |
| 425 observers_, | 433 observers_, |
| 426 OnAutofillDataAvailable(preferred_match.username_value, | 434 OnAutofillDataAvailable(preferred_match.username_value, |
| 427 preferred_match.password_value)); | 435 preferred_match.password_value)); |
| 428 } | 436 } |
| 429 } | 437 } |
| OLD | NEW |