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" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 55 ran_once = true; | 55 ran_once = true; |
| 56 | 56 |
| 57 // TODO(isherman): This does not actually measure a user action. It should be | 57 // TODO(isherman): This does not actually measure a user action. It should be |
| 58 // a boolean histogram. | 58 // a boolean histogram. |
| 59 if (password_manager_enabled) | 59 if (password_manager_enabled) |
| 60 content::RecordAction(UserMetricsAction("PasswordManager_Enabled")); | 60 content::RecordAction(UserMetricsAction("PasswordManager_Enabled")); |
| 61 else | 61 else |
| 62 content::RecordAction(UserMetricsAction("PasswordManager_Disabled")); | 62 content::RecordAction(UserMetricsAction("PasswordManager_Disabled")); |
| 63 } | 63 } |
| 64 | 64 |
| 65 void ReportSavePasswordInfoBarFailure( | |
| 66 const enum PasswordManager::PotentialInfoBarErrorReasons reason_id, | |
| 67 const GURL& url) { | |
| 68 std::string domain_name = url.host(); | |
| 69 | |
| 70 if (domain_name.size()) | |
| 71 domain_name.insert(0, "_"); | |
|
vabr (Chromium)
2013/08/14 14:39:58
We may not append any domain name, only one of a c
Garrett Casto
2013/08/14 23:02:47
I didn't even realize you could send any identifia
vabr (Chromium)
2013/08/16 09:02:14
Yeah, we have to be careful. Logging the domain fo
| |
| 72 | |
| 73 UMA_HISTOGRAM_BOOLEAN("PasswordManager.InfobarDisplayed" + domain_name, | |
|
Garrett Casto
2013/08/14 23:02:47
I'm not sure if this is necessary as if this is ne
vabr (Chromium)
2013/08/16 09:02:14
That's a good point.
Jordy, when you are back, le
| |
| 74 false); | |
| 75 UMA_HISTOGRAM_ENUMERATION( | |
| 76 "PasswordManager.PotentialInfoBarErrorReasons" + domain_name, reason_id, | |
| 77 PasswordManager::NUM_ERROR_TYPES); | |
| 78 } | |
| 79 | |
| 65 } // namespace | 80 } // namespace |
| 66 | 81 |
| 67 // static | 82 // static |
| 68 void PasswordManager::RegisterProfilePrefs( | 83 void PasswordManager::RegisterProfilePrefs( |
| 69 user_prefs::PrefRegistrySyncable* registry) { | 84 user_prefs::PrefRegistrySyncable* registry) { |
| 70 registry->RegisterBooleanPref( | 85 registry->RegisterBooleanPref( |
| 71 prefs::kPasswordManagerEnabled, | 86 prefs::kPasswordManagerEnabled, |
| 72 true, | 87 true, |
| 73 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); | 88 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); |
| 74 registry->RegisterBooleanPref( | 89 registry->RegisterBooleanPref( |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 manager->SetHasGeneratedPassword(); | 145 manager->SetHasGeneratedPassword(); |
| 131 // TODO(gcasto): Add UMA stats to track this. | 146 // TODO(gcasto): Add UMA stats to track this. |
| 132 } | 147 } |
| 133 | 148 |
| 134 bool PasswordManager::IsSavingEnabled() const { | 149 bool PasswordManager::IsSavingEnabled() const { |
| 135 return *password_manager_enabled_ && | 150 return *password_manager_enabled_ && |
| 136 !delegate_->GetProfile()->IsOffTheRecord(); | 151 !delegate_->GetProfile()->IsOffTheRecord(); |
| 137 } | 152 } |
| 138 | 153 |
| 139 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { | 154 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { |
| 140 if (!IsSavingEnabled()) | 155 if (!IsSavingEnabled()) { |
|
Garrett Casto
2013/08/14 23:02:47
I actually just submitted a CL (https://codereview
| |
| 156 ReportSavePasswordInfoBarFailure(SAVE_PASSWORD_DISABLE, form.origin); | |
| 141 return; | 157 return; |
| 158 } | |
| 142 | 159 |
| 143 // No password to save? Then don't. | 160 // No password to save? Then don't. |
| 144 if (form.password_value.empty()) | 161 if (form.password_value.empty()) { |
| 162 ReportSavePasswordInfoBarFailure(EMPTY_PASSWORD, form.origin); | |
| 145 return; | 163 return; |
| 164 } | |
| 146 | 165 |
| 147 scoped_ptr<PasswordFormManager> manager; | 166 scoped_ptr<PasswordFormManager> manager; |
| 148 ScopedVector<PasswordFormManager>::iterator matched_manager_it = | 167 ScopedVector<PasswordFormManager>::iterator matched_manager_it = |
| 149 pending_login_managers_.end(); | 168 pending_login_managers_.end(); |
| 150 for (ScopedVector<PasswordFormManager>::iterator iter = | 169 for (ScopedVector<PasswordFormManager>::iterator iter = |
| 151 pending_login_managers_.begin(); | 170 pending_login_managers_.begin(); |
| 152 iter != pending_login_managers_.end(); ++iter) { | 171 iter != pending_login_managers_.end(); ++iter) { |
| 153 // If we find a manager that exactly matches the submitted form including | 172 // If we find a manager that exactly matches the submitted form including |
| 154 // the action URL, exit the loop. | 173 // the action URL, exit the loop. |
| 155 if ((*iter)->DoesManage( | 174 if ((*iter)->DoesManage( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 166 } | 185 } |
| 167 // If we didn't find a manager, this means a form was submitted without | 186 // If we didn't find a manager, this means a form was submitted without |
| 168 // first loading the page containing the form. Don't offer to save | 187 // first loading the page containing the form. Don't offer to save |
| 169 // passwords in this case. | 188 // passwords in this case. |
| 170 if (matched_manager_it != pending_login_managers_.end()) { | 189 if (matched_manager_it != pending_login_managers_.end()) { |
| 171 // Transfer ownership of the manager from |pending_login_managers_| to | 190 // Transfer ownership of the manager from |pending_login_managers_| to |
| 172 // |manager|. | 191 // |manager|. |
| 173 manager.reset(*matched_manager_it); | 192 manager.reset(*matched_manager_it); |
| 174 pending_login_managers_.weak_erase(matched_manager_it); | 193 pending_login_managers_.weak_erase(matched_manager_it); |
| 175 } else { | 194 } else { |
| 195 ReportSavePasswordInfoBarFailure(FIRST_PAGE_NOT_LOADED, form.origin); | |
| 176 return; | 196 return; |
| 177 } | 197 } |
| 178 | 198 |
| 179 // If we found a manager but it didn't finish matching yet, the user has | 199 // If we found a manager but it didn't finish matching yet, the user has |
| 180 // tried to submit credentials before we had time to even find matching | 200 // tried to submit credentials before we had time to even find matching |
| 181 // results for the given form and autofill. If this is the case, we just | 201 // results for the given form and autofill. If this is the case, we just |
| 182 // give up. | 202 // give up. |
| 183 if (!manager->HasCompletedMatching()) | 203 if (!manager->HasCompletedMatching()) { |
| 204 ReportSavePasswordInfoBarFailure(MATCHING_ONGOING, form.origin); | |
| 184 return; | 205 return; |
| 206 } | |
| 185 | 207 |
| 186 // Also get out of here if the user told us to 'never remember' passwords for | 208 // Also get out of here if the user told us to 'never remember' passwords for |
| 187 // this form. | 209 // this form. |
| 188 if (manager->IsBlacklisted()) | 210 if (manager->IsBlacklisted()) { |
| 211 ReportSavePasswordInfoBarFailure(NEVER_REMEMBER, form.origin); | |
| 189 return; | 212 return; |
| 213 } | |
| 190 | 214 |
| 191 // Bail if we're missing any of the necessary form components. | 215 // Bail if we're missing any of the necessary form components. |
| 192 if (!manager->HasValidPasswordForm()) | 216 if (!manager->HasValidPasswordForm()) { |
| 217 ReportSavePasswordInfoBarFailure(INVALID_FORM, form.origin); | |
| 193 return; | 218 return; |
| 219 } | |
| 194 | 220 |
| 195 // Always save generated passwords, as the user expresses explicit intent for | 221 // Always save generated passwords, as the user expresses explicit intent for |
| 196 // Chrome to manage such passwords. For other passwords, respect the | 222 // Chrome to manage such passwords. For other passwords, respect the |
| 197 // autocomplete attribute. | 223 // autocomplete attribute. |
| 198 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) | 224 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) { |
| 225 ReportSavePasswordInfoBarFailure(PASSWORD_GENERATED_OR_AUTOCOMPLETED, | |
| 226 form.origin); | |
| 199 return; | 227 return; |
| 228 } | |
| 200 | 229 |
| 201 PasswordForm provisionally_saved_form(form); | 230 PasswordForm provisionally_saved_form(form); |
| 202 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && | 231 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && |
| 203 !delegate_->DidLastPageLoadEncounterSSLErrors(); | 232 !delegate_->DidLastPageLoadEncounterSSLErrors(); |
| 204 provisionally_saved_form.preferred = true; | 233 provisionally_saved_form.preferred = true; |
| 205 PasswordFormManager::OtherPossibleUsernamesAction action = | 234 PasswordFormManager::OtherPossibleUsernamesAction action = |
| 206 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; | 235 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; |
| 207 if (OtherPossibleUsernamesEnabled()) | 236 if (OtherPossibleUsernamesEnabled()) |
| 208 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; | 237 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; |
| 209 manager->ProvisionallySave(provisionally_saved_form, action); | 238 manager->ProvisionallySave(provisionally_saved_form, action); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 263 new PasswordFormManager(delegate_->GetProfile(), | 292 new PasswordFormManager(delegate_->GetProfile(), |
| 264 this, | 293 this, |
| 265 web_contents(), | 294 web_contents(), |
| 266 *iter, | 295 *iter, |
| 267 ssl_valid); | 296 ssl_valid); |
| 268 pending_login_managers_.push_back(manager); | 297 pending_login_managers_.push_back(manager); |
| 269 manager->FetchMatchingLoginsFromPasswordStore(); | 298 manager->FetchMatchingLoginsFromPasswordStore(); |
| 270 } | 299 } |
| 271 } | 300 } |
| 272 | 301 |
| 273 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { | 302 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { |
|
Garrett Casto
2013/08/14 23:02:47
I don't think that this function does what you thi
| |
| 274 return provisional_save_manager_->IsNewLogin() && | 303 |
| 275 !provisional_save_manager_->HasGeneratedPassword() && | 304 // All functions are tested on by one in order to send the appropriate |
|
vabr (Chromium)
2013/08/14 14:39:58
on by one -> one by one
| |
| 276 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); | 305 // UMA signal with the ReportSavePasswordInfoBarFailure function. |
| 306 if (!provisional_save_manager_->IsNewLogin()) { | |
| 307 ReportSavePasswordInfoBarFailure(LOGIN_ALREADY_KNEW, | |
| 308 GURL(provisional_save_manager_->realm())); | |
| 309 return false; | |
| 310 } | |
| 311 if (provisional_save_manager_->HasGeneratedPassword()) { | |
| 312 ReportSavePasswordInfoBarFailure(PASSWORD_GENERATED, | |
| 313 GURL(provisional_save_manager_->realm())); | |
| 314 return false; | |
| 315 } | |
| 316 if (provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch()) { | |
| 317 ReportSavePasswordInfoBarFailure(ORIGIN_MATCHING_OF_PUBLIC_SUFFIX, | |
| 318 GURL(provisional_save_manager_->realm())); | |
| 319 return false; | |
| 320 } | |
| 321 return true; | |
| 277 } | 322 } |
| 278 | 323 |
| 279 void PasswordManager::OnPasswordFormsRendered( | 324 void PasswordManager::OnPasswordFormsRendered( |
| 280 const std::vector<PasswordForm>& visible_forms) { | 325 const std::vector<PasswordForm>& visible_forms) { |
| 281 if (!provisional_save_manager_.get()) | 326 if (!provisional_save_manager_.get()) { |
| 327 ReportSavePasswordInfoBarFailure(CANNOT_GET_THE_PROVIOSIONAL_PASSWORD, | |
| 328 visible_forms[0].origin); | |
|
Garrett Casto
2013/08/14 23:02:47
Not sure if any of the reporting in this function
| |
| 282 return; | 329 return; |
| 330 } | |
| 283 | 331 |
| 284 DCHECK(IsSavingEnabled()); | 332 DCHECK(IsSavingEnabled()); |
| 285 | 333 |
| 286 // First, check for a failed login attempt. | 334 // First, check for a failed login attempt. |
| 287 for (std::vector<PasswordForm>::const_iterator iter = visible_forms.begin(); | 335 for (std::vector<PasswordForm>::const_iterator iter = visible_forms.begin(); |
| 288 iter != visible_forms.end(); ++iter) { | 336 iter != visible_forms.end(); ++iter) { |
| 289 if (provisional_save_manager_->DoesManage( | 337 if (provisional_save_manager_->DoesManage( |
| 290 *iter, PasswordFormManager::ACTION_MATCH_REQUIRED)) { | 338 *iter, PasswordFormManager::ACTION_MATCH_REQUIRED)) { |
| 291 // The form trying to be saved has immediately re-appeared. Assume login | 339 // The form trying to be saved has immediately re-appeared. Assume login |
| 292 // failure and abort this save, by clearing provisional_save_manager_. | 340 // failure and abort this save, by clearing provisional_save_manager_. |
| 341 ReportSavePasswordInfoBarFailure( | |
| 342 FORM_REAPPEARED, GURL(provisional_save_manager_->realm())); | |
|
Garrett Casto
2013/08/14 23:02:47
We already keep track of this stat in the provisio
| |
| 293 provisional_save_manager_->SubmitFailed(); | 343 provisional_save_manager_->SubmitFailed(); |
| 294 provisional_save_manager_.reset(); | 344 provisional_save_manager_.reset(); |
| 295 return; | 345 return; |
| 296 } | 346 } |
| 297 } | 347 } |
| 298 | 348 |
| 299 if (!provisional_save_manager_->HasValidPasswordForm()) { | 349 if (!provisional_save_manager_->HasValidPasswordForm()) { |
| 300 // Form is not completely valid - we do not support it. | 350 // Form is not completely valid - we do not support it. |
| 301 NOTREACHED(); | 351 NOTREACHED(); |
| 352 ReportSavePasswordInfoBarFailure(INVALID_FORM, | |
| 353 GURL(provisional_save_manager_->realm())); | |
| 302 provisional_save_manager_.reset(); | 354 provisional_save_manager_.reset(); |
| 303 return; | 355 return; |
| 304 } | 356 } |
| 305 | 357 |
| 306 // Looks like a successful login attempt. Either show an infobar or | 358 // Looks like a successful login attempt. Either show an infobar or |
| 307 // automatically save the login data. We prompt when the user hasn't already | 359 // automatically save the login data. We prompt when the user hasn't already |
| 308 // given consent, either through previously accepting the infobar or by having | 360 // given consent, either through previously accepting the infobar or by having |
| 309 // the browser generate the password. | 361 // the browser generate the password. |
| 310 provisional_save_manager_->SubmitPassed(); | 362 provisional_save_manager_->SubmitPassed(); |
| 311 if (provisional_save_manager_->HasGeneratedPassword()) | 363 if (provisional_save_manager_->HasGeneratedPassword()) |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 386 return; | 438 return; |
| 387 } | 439 } |
| 388 default: | 440 default: |
| 389 FOR_EACH_OBSERVER( | 441 FOR_EACH_OBSERVER( |
| 390 LoginModelObserver, | 442 LoginModelObserver, |
| 391 observers_, | 443 observers_, |
| 392 OnAutofillDataAvailable(preferred_match.username_value, | 444 OnAutofillDataAvailable(preferred_match.username_value, |
| 393 preferred_match.password_value)); | 445 preferred_match.password_value)); |
| 394 } | 446 } |
| 395 } | 447 } |
| OLD | NEW |