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 3 // found in the LICENSE file. 4 5 #include "components/password_manager/core/browser/password_manager.h" 6 7 #include "base/command_line.h" 8 #include "base/metrics/field_trial.h" 9 #include "base/metrics/histogram.h" 10 #include "base/prefs/pref_service.h" 11 #include "base/strings/string_util.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/threading/platform_thread.h" 14 #include "components/autofill/core/common/password_autofill_util.h" 15 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h" 16 #include "components/password_manager/core/browser/password_autofill_manager.h" 17 #include "components/password_manager/core/browser/password_form_manager.h" 18 #include "components/password_manager/core/browser/password_manager_client.h" 19 #include "components/password_manager/core/browser/password_manager_driver.h" 20 #include "components/password_manager/core/browser/password_manager_metrics_util.h" 21 #include "components/password_manager/core/common/password_manager_pref_names.h" 22 #include "components/pref_registry/pref_registry_syncable.h" 23 24 using autofill::PasswordForm; 25 using autofill::PasswordFormMap; 26 27 namespace password_manager { 28 29 namespace { 30 31 const char kSpdyProxyRealm[] = "/SpdyProxy"; 32 33 // Shorten the name to spare line breaks. The code provides enough context 34 // already. 35 typedef autofill::SavePasswordProgressLogger Logger; 36 37 // This routine is called when PasswordManagers are constructed. 38 // 39 // Currently we report metrics only once at startup. We require 40 // that this is only ever called from a single thread in order to 41 // avoid needing to lock (a static boolean flag is then sufficient to 42 // guarantee running only once). 43 void ReportMetrics(bool password_manager_enabled) { 44 static base::PlatformThreadId initial_thread_id = 45 base::PlatformThread::CurrentId(); 46 DCHECK(initial_thread_id == base::PlatformThread::CurrentId()); 47 48 static bool ran_once = false; 49 if (ran_once) 50 return; 51 ran_once = true; 52 53 UMA_HISTOGRAM_BOOLEAN("PasswordManager.Enabled", password_manager_enabled); 54 } 55 56 } // namespace 57 58 const char PasswordManager::kOtherPossibleUsernamesExperiment[] = 59 "PasswordManagerOtherPossibleUsernames"; 60 61 // static 62 void PasswordManager::RegisterProfilePrefs( 63 user_prefs::PrefRegistrySyncable* registry) { 64 registry->RegisterBooleanPref( 65 prefs::kPasswordManagerEnabled, 66 true, 67 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 68 registry->RegisterBooleanPref( 69 prefs::kPasswordManagerAllowShowPasswords, 70 true, 71 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 72 registry->RegisterListPref(prefs::kPasswordManagerGroupsForDomains, 73 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 74 } 75 76 PasswordManager::PasswordManager(PasswordManagerClient* client) 77 : client_(client), driver_(client->GetDriver()) { 78 DCHECK(client_); 79 DCHECK(driver_); 80 password_manager_enabled_.Init(prefs::kPasswordManagerEnabled, 81 client_->GetPrefs()); 82 83 ReportMetrics(*password_manager_enabled_); 84 } 85 86 PasswordManager::~PasswordManager() { 87 FOR_EACH_OBSERVER(LoginModelObserver, observers_, OnLoginModelDestroying()); 88 } 89 90 void PasswordManager::SetFormHasGeneratedPassword(const PasswordForm& form) { 91 DCHECK(IsSavingEnabledForCurrentPage()); 92 93 for (ScopedVector<PasswordFormManager>::iterator iter = 94 pending_login_managers_.begin(); 95 iter != pending_login_managers_.end(); 96 ++iter) { 97 if ((*iter)->DoesManage(form, PasswordFormManager::ACTION_MATCH_REQUIRED)) { 98 (*iter)->SetHasGeneratedPassword(); 99 return; 100 } 101 } 102 // If there is no corresponding PasswordFormManager, we create one. This is 103 // not the common case, and should only happen when there is a bug in our 104 // ability to detect forms. 105 bool ssl_valid = form.origin.SchemeIsSecure(); 106 PasswordFormManager* manager = 107 new PasswordFormManager(this, client_, driver_, form, ssl_valid); 108 pending_login_managers_.push_back(manager); 109 manager->SetHasGeneratedPassword(); 110 // TODO(gcasto): Add UMA stats to track this. 111 } 112 113 bool PasswordManager::IsSavingEnabledForCurrentPage() const { 114 return *password_manager_enabled_ && !driver_->IsOffTheRecord() && 115 !driver_->DidLastPageLoadEncounterSSLErrors(); 116 } 117 118 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { 119 bool is_saving_enabled = IsSavingEnabledForCurrentPage(); 120 121 scoped_ptr<BrowserSavePasswordProgressLogger> logger; 122 if (client_->IsLoggingActive()) { 123 logger.reset(new BrowserSavePasswordProgressLogger(client_)); 124 logger->LogMessage(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_METHOD); 125 logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVE_PASSWORD_FORM, 126 form); 127 logger->LogBoolean(Logger::STRING_IS_SAVING_ENABLED, is_saving_enabled); 128 logger->LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, 129 driver_->DidLastPageLoadEncounterSSLErrors()); 130 } 131 132 if (!is_saving_enabled) { 133 RecordFailure(SAVING_DISABLED, form.origin.host(), logger.get()); 134 return; 135 } 136 137 // No password to save? Then don't. 138 if (form.password_value.empty()) { 139 RecordFailure(EMPTY_PASSWORD, form.origin.host(), logger.get()); 140 return; 141 } 142 143 scoped_ptr<PasswordFormManager> manager; 144 ScopedVector<PasswordFormManager>::iterator matched_manager_it = 145 pending_login_managers_.end(); 146 for (ScopedVector<PasswordFormManager>::iterator iter = 147 pending_login_managers_.begin(); 148 iter != pending_login_managers_.end(); 149 ++iter) { 150 if ((*iter)->DoesManage(form, PasswordFormManager::ACTION_MATCH_REQUIRED)) { 151 // If we find a manager that exactly matches the submitted form including 152 // the action URL, exit the loop. 153 if (logger) 154 logger->LogMessage(Logger::STRING_EXACT_MATCH); 155 matched_manager_it = iter; 156 break; 157 } else if ((*iter)->DoesManage( 158 form, PasswordFormManager::ACTION_MATCH_NOT_REQUIRED)) { 159 // If the current manager matches the submitted form excluding the action 160 // URL, remember it as a candidate and continue searching for an exact 161 // match. 162 if (logger) 163 logger->LogMessage(Logger::STRING_MATCH_WITHOUT_ACTION); 164 matched_manager_it = iter; 165 } 166 } 167 // 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 169 // passwords in this case. 170 if (matched_manager_it != pending_login_managers_.end()) { 171 // Transfer ownership of the manager from |pending_login_managers_| to 172 // |manager|. 173 manager.reset(*matched_manager_it); 174 pending_login_managers_.weak_erase(matched_manager_it); 175 } else { 176 RecordFailure(NO_MATCHING_FORM, form.origin.host(), logger.get()); 177 return; 178 } 179 180 // If we found a manager but it didn't finish matching yet, the user has 181 // tried to submit credentials before we had time to even find matching 182 // results for the given form and autofill. If this is the case, we just 183 // give up. 184 if (!manager->HasCompletedMatching()) { 185 RecordFailure(MATCHING_NOT_COMPLETE, form.origin.host(), logger.get()); 186 return; 187 } 188 189 // Also get out of here if the user told us to 'never remember' passwords for 190 // this form. 191 if (manager->IsBlacklisted()) { 192 RecordFailure(FORM_BLACKLISTED, form.origin.host(), logger.get()); 193 return; 194 } 195 196 // Bail if we're missing any of the necessary form components. 197 if (!manager->HasValidPasswordForm()) { 198 RecordFailure(INVALID_FORM, form.origin.host(), logger.get()); 199 return; 200 } 201 202 // Always save generated passwords, as the user expresses explicit intent for 203 // Chrome to manage such passwords. For other passwords, respect the 204 // autocomplete attribute if autocomplete='off' is not ignored. 205 if (!autofill::ShouldIgnoreAutocompleteOffForPasswordFields() && 206 !manager->HasGeneratedPassword() && !form.password_autocomplete_set) { 207 RecordFailure(AUTOCOMPLETE_OFF, form.origin.host(), logger.get()); 208 return; 209 } 210 211 PasswordForm provisionally_saved_form(form); 212 provisionally_saved_form.ssl_valid = 213 form.origin.SchemeIsSecure() && 214 !driver_->DidLastPageLoadEncounterSSLErrors(); 215 provisionally_saved_form.preferred = true; 216 if (logger) { 217 logger->LogPasswordForm(Logger::STRING_PROVISIONALLY_SAVED_FORM, 218 provisionally_saved_form); 219 } 220 PasswordFormManager::OtherPossibleUsernamesAction action = 221 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; 222 if (OtherPossibleUsernamesEnabled()) 223 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; 224 if (logger) { 225 logger->LogBoolean( 226 Logger::STRING_IGNORE_POSSIBLE_USERNAMES, 227 action == PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES); 228 } 229 manager->ProvisionallySave(provisionally_saved_form, action); 230 provisional_save_manager_.swap(manager); 231 } 232 233 void PasswordManager::RecordFailure(ProvisionalSaveFailure failure, 234 const std::string& form_origin, 235 BrowserSavePasswordProgressLogger* logger) { 236 UMA_HISTOGRAM_ENUMERATION( 237 "PasswordManager.ProvisionalSaveFailure", failure, MAX_FAILURE_VALUE); 238 239 std::string group_name = metrics_util::GroupIdToString( 240 metrics_util::MonitoredDomainGroupId(form_origin, client_->GetPrefs())); 241 if (!group_name.empty()) { 242 metrics_util::LogUMAHistogramEnumeration( 243 "PasswordManager.ProvisionalSaveFailure_" + group_name, 244 failure, 245 MAX_FAILURE_VALUE); 246 } 247 248 if (logger) { 249 switch (failure) { 250 case SAVING_DISABLED: 251 logger->LogMessage(Logger::STRING_SAVING_DISABLED); 252 break; 253 case EMPTY_PASSWORD: 254 logger->LogMessage(Logger::STRING_EMPTY_PASSWORD); 255 break; 256 case MATCHING_NOT_COMPLETE: 257 logger->LogMessage(Logger::STRING_NO_FORM_MANAGER); 258 break; 259 case NO_MATCHING_FORM: 260 logger->LogMessage(Logger::STRING_NO_MATCHING_FORM); 261 break; 262 case FORM_BLACKLISTED: 263 logger->LogMessage(Logger::STRING_FORM_BLACKLISTED); 264 break; 265 case INVALID_FORM: 266 logger->LogMessage(Logger::STRING_INVALID_FORM); 267 break; 268 case AUTOCOMPLETE_OFF: 269 logger->LogMessage(Logger::STRING_AUTOCOMPLETE_OFF); 270 break; 271 case MAX_FAILURE_VALUE: 272 NOTREACHED(); 273 return; 274 } 275 logger->LogMessage(Logger::STRING_DECISION_DROP); 276 } 277 } 278 279 void PasswordManager::AddSubmissionCallback( 280 const PasswordSubmittedCallback& callback) { 281 submission_callbacks_.push_back(callback); 282 } 283 284 void PasswordManager::AddObserver(LoginModelObserver* observer) { 285 observers_.AddObserver(observer); 286 } 287 288 void PasswordManager::RemoveObserver(LoginModelObserver* observer) { 289 observers_.RemoveObserver(observer); 290 } 291 292 void PasswordManager::DidNavigateMainFrame(bool is_in_page) { 293 // Clear data after main frame navigation if the navigation was to a 294 // different page. 295 if (!is_in_page) { 296 pending_login_managers_.clear(); 297 driver_->GetPasswordAutofillManager()->Reset(); 298 } 299 } 300 301 void PasswordManager::OnPasswordFormSubmitted( 302 const PasswordForm& password_form) { 303 ProvisionallySavePassword(password_form); 304 for (size_t i = 0; i < submission_callbacks_.size(); ++i) { 305 submission_callbacks_[i].Run(password_form); 306 } 307 308 pending_login_managers_.clear(); 309 } 310 311 void PasswordManager::OnPasswordFormsParsed( 312 const std::vector<PasswordForm>& forms) { 313 CreatePendingLoginManagers(forms); 314 } 315 316 void PasswordManager::CreatePendingLoginManagers( 317 const std::vector<PasswordForm>& forms) { 318 // Don't try to autofill or save passwords in the presence of SSL errors. 319 if (driver_->DidLastPageLoadEncounterSSLErrors()) 320 return; 321 322 // Copy the weak pointers to the currently known login managers for comparison 323 // against the newly added. 324 std::vector<PasswordFormManager*> old_login_managers( 325 pending_login_managers_.get()); 326 for (std::vector<PasswordForm>::const_iterator iter = forms.begin(); 327 iter != forms.end(); 328 ++iter) { 329 // Don't involve the password manager if this form corresponds to 330 // SpdyProxy authentication, as indicated by the realm. 331 if (EndsWith(iter->signon_realm, kSpdyProxyRealm, true)) 332 continue; 333 bool old_manager_found = false; 334 for (std::vector<PasswordFormManager*>::const_iterator old_manager = 335 old_login_managers.begin(); 336 !old_manager_found && old_manager != old_login_managers.end(); 337 ++old_manager) { 338 old_manager_found |= (*old_manager)->DoesManage( 339 *iter, PasswordFormManager::ACTION_MATCH_REQUIRED); 340 } 341 if (old_manager_found) 342 continue; // The current form is already managed. 343 344 bool ssl_valid = iter->origin.SchemeIsSecure(); 345 PasswordFormManager* manager = 346 new PasswordFormManager(this, client_, driver_, *iter, ssl_valid); 347 pending_login_managers_.push_back(manager); 348 349 // Avoid prompting the user for access to a password if they don't have 350 // password saving enabled. 351 PasswordStore::AuthorizationPromptPolicy prompt_policy = 352 *password_manager_enabled_ ? PasswordStore::ALLOW_PROMPT 353 : PasswordStore::DISALLOW_PROMPT; 354 355 manager->FetchMatchingLoginsFromPasswordStore(prompt_policy); 356 } 357 } 358 359 bool PasswordManager::ShouldPromptUserToSavePassword() const { 360 return !client_->IsAutomaticPasswordSavingEnabled() && 361 provisional_save_manager_->IsNewLogin() && 362 !provisional_save_manager_->HasGeneratedPassword() && 363 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); 364 } 365 366 void PasswordManager::OnPasswordFormsRendered( 367 const std::vector<PasswordForm>& visible_forms) { 368 CreatePendingLoginManagers(visible_forms); 369 370 scoped_ptr<BrowserSavePasswordProgressLogger> logger; 371 if (client_->IsLoggingActive()) { 372 logger.reset(new BrowserSavePasswordProgressLogger(client_)); 373 logger->LogMessage(Logger::STRING_ON_PASSWORD_FORMS_RENDERED_METHOD); 374 } 375 376 if (!provisional_save_manager_.get()) { 377 if (logger) { 378 logger->LogMessage(Logger::STRING_NO_PROVISIONAL_SAVE_MANAGER); 379 logger->LogMessage(Logger::STRING_DECISION_DROP); 380 } 381 return; 382 } 383 384 DCHECK(IsSavingEnabledForCurrentPage()); 385 386 if (logger) { 387 logger->LogNumber(Logger::STRING_NUMBER_OF_VISIBLE_FORMS, 388 visible_forms.size()); 389 } 390 391 // If we see the login form again, then the login failed. 392 for (size_t i = 0; i < visible_forms.size(); ++i) { 393 // TODO(vabr): The similarity check is just action equality for now. If it 394 // becomes more complex, it may make sense to consider modifying and using 395 // PasswordFormManager::DoesManage for it. 396 if (visible_forms[i].action.is_valid() && 397 provisional_save_manager_->pending_credentials().action == 398 visible_forms[i].action) { 399 if (logger) { 400 logger->LogPasswordForm(Logger::STRING_PASSWORD_FORM_REAPPEARED, 401 visible_forms[i]); 402 logger->LogMessage(Logger::STRING_DECISION_DROP); 403 } 404 provisional_save_manager_->SubmitFailed(); 405 provisional_save_manager_.reset(); 406 return; 407 } 408 } 409 410 // Looks like a successful login attempt. Either show an infobar or 411 // automatically save the login data. We prompt when the user hasn't already 412 // given consent, either through previously accepting the infobar or by having 413 // the browser generate the password. 414 provisional_save_manager_->SubmitPassed(); 415 416 if (ShouldPromptUserToSavePassword()) { 417 if (logger) 418 logger->LogMessage(Logger::STRING_DECISION_ASK); 419 client_->PromptUserToSavePassword(provisional_save_manager_.release()); 420 } else { 421 if (logger) 422 logger->LogMessage(Logger::STRING_DECISION_SAVE); 423 provisional_save_manager_->Save(); 424 provisional_save_manager_.reset(); 425 } 426 } 427 428 void PasswordManager::PossiblyInitializeUsernamesExperiment( 429 const PasswordFormMap& best_matches) const { 430 if (base::FieldTrialList::Find(kOtherPossibleUsernamesExperiment)) 431 return; 432 433 bool other_possible_usernames_exist = false; 434 for (autofill::PasswordFormMap::const_iterator it = best_matches.begin(); 435 it != best_matches.end(); 436 ++it) { 437 if (!it->second->other_possible_usernames.empty()) { 438 other_possible_usernames_exist = true; 439 break; 440 } 441 } 442 443 if (!other_possible_usernames_exist) 444 return; 445 446 const base::FieldTrial::Probability kDivisor = 100; 447 scoped_refptr<base::FieldTrial> trial( 448 base::FieldTrialList::FactoryGetFieldTrial( 449 kOtherPossibleUsernamesExperiment, 450 kDivisor, 451 "Disabled", 452 2013, 12, 31, 453 base::FieldTrial::ONE_TIME_RANDOMIZED, 454 NULL)); 455 base::FieldTrial::Probability enabled_probability = 456 client_->GetProbabilityForExperiment(kOtherPossibleUsernamesExperiment); 457 trial->AppendGroup("Enabled", enabled_probability); 458 } 459 460 bool PasswordManager::OtherPossibleUsernamesEnabled() const { 461 return base::FieldTrialList::FindFullName( 462 kOtherPossibleUsernamesExperiment) == "Enabled"; 463 } 464 465 void PasswordManager::Autofill(const PasswordForm& form_for_autofill, 466 const PasswordFormMap& best_matches, 467 const PasswordForm& preferred_match, 468 bool wait_for_username) const { 469 PossiblyInitializeUsernamesExperiment(best_matches); 470 471 // TODO(tedchoc): Switch to only requesting authentication if the user is 472 // acting on the autofilled forms (crbug.com/342594) instead 473 // of on page load. 474 bool authentication_required = preferred_match.use_additional_authentication; 475 for (autofill::PasswordFormMap::const_iterator it = best_matches.begin(); 476 !authentication_required && it != best_matches.end(); 477 ++it) { 478 if (it->second->use_additional_authentication) 479 authentication_required = true; 480 } 481 482 switch (form_for_autofill.scheme) { 483 case PasswordForm::SCHEME_HTML: { 484 // Note the check above is required because the observers_ for a non-HTML 485 // schemed password form may have been freed, so we need to distinguish. 486 scoped_ptr<autofill::PasswordFormFillData> fill_data( 487 new autofill::PasswordFormFillData()); 488 InitPasswordFormFillData(form_for_autofill, 489 best_matches, 490 &preferred_match, 491 wait_for_username, 492 OtherPossibleUsernamesEnabled(), 493 fill_data.get()); 494 if (authentication_required) 495 client_->AuthenticateAutofillAndFillForm(fill_data.Pass()); 496 else 497 driver_->FillPasswordForm(*fill_data.get()); 498 break; 499 } 500 default: 501 FOR_EACH_OBSERVER( 502 LoginModelObserver, 503 observers_, 504 OnAutofillDataAvailable(preferred_match.username_value, 505 preferred_match.password_value)); 506 break; 507 } 508 509 client_->PasswordWasAutofilled(best_matches); 510 } 511 512 } // namespace password_manager 513