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