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_form_manager.h"
      6 
      7 #include <algorithm>
      8 #include <set>
      9 
     10 #include "base/metrics/histogram.h"
     11 #include "base/metrics/user_metrics.h"
     12 #include "base/strings/string_split.h"
     13 #include "base/strings/string_util.h"
     14 #include "base/strings/utf_string_conversions.h"
     15 #include "components/autofill/core/browser/autofill_manager.h"
     16 #include "components/autofill/core/browser/form_structure.h"
     17 #include "components/autofill/core/browser/validation.h"
     18 #include "components/autofill/core/common/password_form.h"
     19 #include "components/password_manager/core/browser/password_manager.h"
     20 #include "components/password_manager/core/browser/password_manager_client.h"
     21 #include "components/password_manager/core/browser/password_manager_driver.h"
     22 #include "components/password_manager/core/browser/password_store.h"
     23 
     24 using autofill::FormStructure;
     25 using autofill::PasswordForm;
     26 using autofill::PasswordFormMap;
     27 using base::Time;
     28 
     29 namespace password_manager {
     30 
     31 namespace {
     32 
     33 enum PasswordGenerationSubmissionEvent {
     34   // Generated password was submitted and saved.
     35   PASSWORD_SUBMITTED,
     36 
     37   // Generated password submission failed. These passwords aren't saved.
     38   PASSWORD_SUBMISSION_FAILED,
     39 
     40   // Generated password was not submitted before navigation. Currently these
     41   // passwords are not saved.
     42   PASSWORD_NOT_SUBMITTED,
     43 
     44   // Generated password was overridden by a non-generated one. This generally
     45   // signals that the user was unhappy with the generated password for some
     46   // reason.
     47   PASSWORD_OVERRIDDEN,
     48 
     49   // Number of enum entries, used for UMA histogram reporting macros.
     50   SUBMISSION_EVENT_ENUM_COUNT
     51 };
     52 
     53 void LogPasswordGenerationSubmissionEvent(
     54     PasswordGenerationSubmissionEvent event) {
     55   UMA_HISTOGRAM_ENUMERATION("PasswordGeneration.SubmissionEvent",
     56                             event, SUBMISSION_EVENT_ENUM_COUNT);
     57 }
     58 
     59 PasswordForm CopyAndModifySSLValidity(const PasswordForm& orig,
     60                                       bool ssl_valid) {
     61   PasswordForm result(orig);
     62   result.ssl_valid = ssl_valid;
     63   return result;
     64 }
     65 
     66 }  // namespace
     67 
     68 PasswordFormManager::PasswordFormManager(PasswordManager* password_manager,
     69                                          PasswordManagerClient* client,
     70                                          PasswordManagerDriver* driver,
     71                                          const PasswordForm& observed_form,
     72                                          bool ssl_valid)
     73     : best_matches_deleter_(&best_matches_),
     74       observed_form_(CopyAndModifySSLValidity(observed_form, ssl_valid)),
     75       is_new_login_(true),
     76       has_generated_password_(false),
     77       password_manager_(password_manager),
     78       preferred_match_(NULL),
     79       state_(PRE_MATCHING_PHASE),
     80       client_(client),
     81       driver_(driver),
     82       manager_action_(kManagerActionNone),
     83       user_action_(kUserActionNone),
     84       submit_result_(kSubmitResultNotSubmitted) {
     85   if (observed_form_.origin.is_valid())
     86     base::SplitString(observed_form_.origin.path(), '/', &form_path_tokens_);
     87 }
     88 
     89 PasswordFormManager::~PasswordFormManager() {
     90   UMA_HISTOGRAM_ENUMERATION(
     91       "PasswordManager.ActionsTakenV3", GetActionsTaken(), kMaxNumActionsTaken);
     92   if (has_generated_password_ && submit_result_ == kSubmitResultNotSubmitted)
     93     LogPasswordGenerationSubmissionEvent(PASSWORD_NOT_SUBMITTED);
     94 }
     95 
     96 int PasswordFormManager::GetActionsTaken() {
     97   return user_action_ + kUserActionMax * (manager_action_ +
     98          kManagerActionMax * submit_result_);
     99 }
    100 
    101 // TODO(timsteele): use a hash of some sort in the future?
    102 PasswordFormManager::MatchResultMask PasswordFormManager::DoesManage(
    103     const PasswordForm& form) const {
    104   // Non-HTML form case.
    105   if (observed_form_.scheme != PasswordForm::SCHEME_HTML ||
    106       form.scheme != PasswordForm::SCHEME_HTML) {
    107     const bool forms_match = observed_form_.signon_realm == form.signon_realm &&
    108                              observed_form_.scheme == form.scheme;
    109     return forms_match ? RESULT_COMPLETE_MATCH : RESULT_NO_MATCH;
    110   }
    111 
    112   // HTML form case.
    113   MatchResultMask result = RESULT_NO_MATCH;
    114 
    115   // Easiest case of matching origins.
    116   bool origins_match = form.origin == observed_form_.origin;
    117   // If this is a replay of the same form in the case a user entered an invalid
    118   // password, the origin of the new form may equal the action of the "first"
    119   // form instead.
    120   origins_match = origins_match || (form.origin == observed_form_.action);
    121   // Otherwise, if action hosts are the same, the old URL scheme is HTTP while
    122   // the new one is HTTPS, and the new path equals to or extends the old path,
    123   // we also consider the actions a match. This is to accommodate cases where
    124   // the original login form is on an HTTP page, but a failed login attempt
    125   // redirects to HTTPS (as in http://example.org -> https://example.org/auth).
    126   if (!origins_match && !observed_form_.origin.SchemeIsSecure() &&
    127       form.origin.SchemeIsSecure()) {
    128     const std::string& old_path = observed_form_.origin.path();
    129     const std::string& new_path = form.origin.path();
    130     origins_match =
    131         observed_form_.origin.host() == form.origin.host() &&
    132         observed_form_.origin.port() == form.origin.port() &&
    133         StartsWithASCII(new_path, old_path, /*case_sensitive=*/true);
    134   }
    135 
    136   if (form.username_element == observed_form_.username_element &&
    137       form.password_element == observed_form_.password_element &&
    138       origins_match) {
    139     result |= RESULT_MANDATORY_ATTRIBUTES_MATCH;
    140   }
    141 
    142   // Note: although saved password forms might actually have an empty action
    143   // URL if they were imported (see bug 1107719), the |form| we see here comes
    144   // never from the password store, and should have an exactly matching action.
    145   if (form.action == observed_form_.action)
    146     result |= RESULT_ACTION_MATCH;
    147 
    148   return result;
    149 }
    150 
    151 bool PasswordFormManager::IsBlacklisted() {
    152   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    153   if (preferred_match_ && preferred_match_->blacklisted_by_user)
    154     return true;
    155   return false;
    156 }
    157 
    158 void PasswordFormManager::PermanentlyBlacklist() {
    159   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    160 
    161   // Configure the form about to be saved for blacklist status.
    162   pending_credentials_.preferred = true;
    163   pending_credentials_.blacklisted_by_user = true;
    164   pending_credentials_.username_value.clear();
    165   pending_credentials_.password_value.clear();
    166 
    167   // Retroactively forget existing matches for this form, so we NEVER prompt or
    168   // autofill it again.
    169   int num_passwords_deleted = 0;
    170   if (!best_matches_.empty()) {
    171     PasswordFormMap::const_iterator iter;
    172     PasswordStore* password_store = client_->GetPasswordStore();
    173     if (!password_store) {
    174       NOTREACHED();
    175       return;
    176     }
    177     for (iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) {
    178       // We want to remove existing matches for this form so that the exact
    179       // origin match with |blackisted_by_user == true| is the only result that
    180       // shows up in the future for this origin URL. However, we don't want to
    181       // delete logins that were actually saved on a different page (hence with
    182       // different origin URL) and just happened to match this form because of
    183       // the scoring algorithm. See bug 1204493.
    184       if (iter->second->origin == observed_form_.origin) {
    185         password_store->RemoveLogin(*iter->second);
    186         ++num_passwords_deleted;
    187       }
    188     }
    189   }
    190 
    191   UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedWhenBlacklisting",
    192                        num_passwords_deleted);
    193 
    194   // Save the pending_credentials_ entry marked as blacklisted.
    195   SaveAsNewLogin(false);
    196 }
    197 
    198 void PasswordFormManager::SetUseAdditionalPasswordAuthentication(
    199     bool use_additional_authentication) {
    200   pending_credentials_.use_additional_authentication =
    201       use_additional_authentication;
    202 }
    203 
    204 bool PasswordFormManager::IsNewLogin() {
    205   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    206   return is_new_login_;
    207 }
    208 
    209 bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
    210   return pending_credentials_.IsPublicSuffixMatch();
    211 }
    212 
    213 void PasswordFormManager::SetHasGeneratedPassword() {
    214   has_generated_password_ = true;
    215 }
    216 
    217 bool PasswordFormManager::HasGeneratedPassword() {
    218   // This check is permissive, as the user may have generated a password and
    219   // then edited it in the form itself. However, even in this case the user
    220   // has already given consent, so we treat these cases the same.
    221   return has_generated_password_;
    222 }
    223 
    224 bool PasswordFormManager::HasValidPasswordForm() {
    225   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    226   // Non-HTML password forms (primarily HTTP and FTP autentication)
    227   // do not contain username_element and password_element values.
    228   if (observed_form_.scheme != PasswordForm::SCHEME_HTML)
    229     return true;
    230   return !observed_form_.password_element.empty() ||
    231          !observed_form_.new_password_element.empty();
    232 }
    233 
    234 void PasswordFormManager::ProvisionallySave(
    235     const PasswordForm& credentials,
    236     OtherPossibleUsernamesAction action) {
    237   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    238   DCHECK_NE(RESULT_NO_MATCH, DoesManage(credentials));
    239 
    240   // If this was a sign-up or change password form, we want to persist the new
    241   // password; if this was a login form, then the current password (which might
    242   // still be "new" in the sense that we see these credentials for the first
    243   // time, or that the user manually entered his actual password to overwrite an
    244   // obsolete password we had in the store).
    245   base::string16 password_to_save(credentials.new_password_element.empty() ?
    246       credentials.password_value : credentials.new_password_value);
    247 
    248   // Make sure the important fields stay the same as the initially observed or
    249   // autofilled ones, as they may have changed if the user experienced a login
    250   // failure.
    251   // Look for these credentials in the list containing auto-fill entries.
    252   PasswordFormMap::const_iterator it =
    253       best_matches_.find(credentials.username_value);
    254   if (it != best_matches_.end()) {
    255     // The user signed in with a login we autofilled.
    256     pending_credentials_ = *it->second;
    257     bool password_changed =
    258         pending_credentials_.password_value != password_to_save;
    259     if (IsPendingCredentialsPublicSuffixMatch()) {
    260       // If the autofilled credentials were only a PSL match, store a copy with
    261       // the current origin and signon realm. This ensures that on the next
    262       // visit, a precise match is found.
    263       is_new_login_ = true;
    264       user_action_ = password_changed ? kUserActionChoosePslMatch
    265                                       : kUserActionOverridePassword;
    266       // Normally, the copy of the PSL matched credentials, adapted for the
    267       // current domain, is saved automatically without asking the user, because
    268       // the copy likely represents the same account, i.e., the one for which
    269       // the user already agreed to store a password.
    270       //
    271       // However, if the user changes the suggested password, it might indicate
    272       // that the autofilled credentials and |credentials| actually correspond
    273       // to two different accounts (see http://crbug.com/385619). In that case
    274       // the user should be asked again before saving the password. This is
    275       // ensured by clearing |original_signon_realm| on |pending_credentials_|,
    276       // which unmarks it as a PSL match.
    277       //
    278       // There is still the edge case when the autofilled credentials represent
    279       // the same account as |credentials| but the stored password was out of
    280       // date. In that case, the user just had to manually enter the new
    281       // password, which is now in |credentials|. The best thing would be to
    282       // save automatically, and also update the original credentials. However,
    283       // we have no way to tell if this is the case. This will likely happen
    284       // infrequently, and the inconvenience put on the user by asking them is
    285       // not significant, so we are fine with asking here again.
    286       if (password_changed) {
    287         pending_credentials_.original_signon_realm.clear();
    288         DCHECK(!IsPendingCredentialsPublicSuffixMatch());
    289       }
    290     } else {  // Not a PSL match.
    291       is_new_login_ = false;
    292       if (password_changed)
    293         user_action_ = kUserActionOverridePassword;
    294     }
    295   } else if (action == ALLOW_OTHER_POSSIBLE_USERNAMES &&
    296              UpdatePendingCredentialsIfOtherPossibleUsername(
    297                  credentials.username_value)) {
    298     // |pending_credentials_| is now set. Note we don't update
    299     // |pending_credentials_.username_value| to |credentials.username_value|
    300     // yet because we need to keep the original username to modify the stored
    301     // credential.
    302     selected_username_ = credentials.username_value;
    303     is_new_login_ = false;
    304   } else {
    305     // User typed in a new, unknown username.
    306     user_action_ = kUserActionOverrideUsernameAndPassword;
    307     pending_credentials_ = observed_form_;
    308     pending_credentials_.username_value = credentials.username_value;
    309     pending_credentials_.other_possible_usernames =
    310         credentials.other_possible_usernames;
    311 
    312     // The password value will be filled in later, remove any garbage for now.
    313     pending_credentials_.password_value.clear();
    314     pending_credentials_.new_password_value.clear();
    315 
    316     // If this was a sign-up or change password form, the names of the elements
    317     // are likely different than those on a login form, so do not bother saving
    318     // them. We will fill them with meaningful values in UpdateLogin() when the
    319     // user goes onto a real login form for the first time.
    320     if (!credentials.new_password_element.empty()) {
    321       pending_credentials_.password_element.clear();
    322       pending_credentials_.new_password_element.clear();
    323     }
    324   }
    325 
    326   pending_credentials_.action = credentials.action;
    327   // If the user selected credentials we autofilled from a PasswordForm
    328   // that contained no action URL (IE6/7 imported passwords, for example),
    329   // bless it with the action URL from the observed form. See bug 1107719.
    330   if (pending_credentials_.action.is_empty())
    331     pending_credentials_.action = observed_form_.action;
    332 
    333   pending_credentials_.password_value = password_to_save;
    334   pending_credentials_.preferred = credentials.preferred;
    335 
    336   if (user_action_ == kUserActionOverridePassword &&
    337       pending_credentials_.type == PasswordForm::TYPE_GENERATED &&
    338       !has_generated_password_) {
    339     LogPasswordGenerationSubmissionEvent(PASSWORD_OVERRIDDEN);
    340   }
    341 
    342   if (has_generated_password_)
    343     pending_credentials_.type = PasswordForm::TYPE_GENERATED;
    344 }
    345 
    346 void PasswordFormManager::Save() {
    347   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    348   DCHECK(!driver_->IsOffTheRecord());
    349 
    350   if (IsNewLogin())
    351     SaveAsNewLogin(true);
    352   else
    353     UpdateLogin();
    354 }
    355 
    356 void PasswordFormManager::FetchMatchingLoginsFromPasswordStore(
    357     PasswordStore::AuthorizationPromptPolicy prompt_policy) {
    358   DCHECK_EQ(state_, PRE_MATCHING_PHASE);
    359   state_ = MATCHING_PHASE;
    360   PasswordStore* password_store = client_->GetPasswordStore();
    361   if (!password_store) {
    362     NOTREACHED();
    363     return;
    364   }
    365   password_store->GetLogins(observed_form_, prompt_policy, this);
    366 }
    367 
    368 bool PasswordFormManager::HasCompletedMatching() {
    369   return state_ == POST_MATCHING_PHASE;
    370 }
    371 
    372 void PasswordFormManager::OnRequestDone(
    373     const std::vector<PasswordForm*>& logins_result) {
    374   // Note that the result gets deleted after this call completes, but we own
    375   // the PasswordForm objects pointed to by the result vector, thus we keep
    376   // copies to a minimum here.
    377 
    378   int best_score = 0;
    379   // These credentials will be in the final result regardless of score.
    380   std::vector<PasswordForm> credentials_to_keep;
    381   for (size_t i = 0; i < logins_result.size(); i++) {
    382     if (ShouldIgnoreResult(*logins_result[i])) {
    383       delete logins_result[i];
    384       continue;
    385     }
    386     // Score and update best matches.
    387     int current_score = ScoreResult(*logins_result[i]);
    388     // This check is here so we can append empty path matches in the event
    389     // they don't score as high as others and aren't added to best_matches_.
    390     // This is most commonly imported firefox logins. We skip blacklisted
    391     // ones because clearly we don't want to autofill them, and secondly
    392     // because they only mean something when we have no other matches already
    393     // saved in Chrome - in which case they'll make it through the regular
    394     // scoring flow below by design. Note signon_realm == origin implies empty
    395     // path logins_result, since signon_realm is a prefix of origin for HTML
    396     // password forms.
    397     // TODO(timsteele): Bug 1269400. We probably should do something more
    398     // elegant for any shorter-path match instead of explicitly handling empty
    399     // path matches.
    400     if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
    401         (observed_form_.signon_realm == logins_result[i]->origin.spec()) &&
    402         (current_score > 0) && (!logins_result[i]->blacklisted_by_user)) {
    403       credentials_to_keep.push_back(*logins_result[i]);
    404     }
    405 
    406     // Always keep generated passwords as part of the result set. If a user
    407     // generates a password on a signup form, it should show on a login form
    408     // even if they have a previous login saved.
    409     // TODO(gcasto): We don't want to cut credentials that were saved on signup
    410     // forms even if they weren't generated, but currently it's hard to
    411     // distinguish between those forms and two different login forms on the
    412     // same domain. Filed http://crbug.com/294468 to look into this.
    413     if (logins_result[i]->type == PasswordForm::TYPE_GENERATED)
    414       credentials_to_keep.push_back(*logins_result[i]);
    415 
    416     if (current_score < best_score) {
    417       delete logins_result[i];
    418       continue;
    419     }
    420     if (current_score == best_score) {
    421       PasswordForm* old_form = best_matches_[logins_result[i]->username_value];
    422       if (old_form) {
    423         if (preferred_match_ == old_form)
    424           preferred_match_ = NULL;
    425         delete old_form;
    426       }
    427       best_matches_[logins_result[i]->username_value] = logins_result[i];
    428     } else if (current_score > best_score) {
    429       best_score = current_score;
    430       // This new login has a better score than all those up to this point
    431       // Note 'this' owns all the PasswordForms in best_matches_.
    432       STLDeleteValues(&best_matches_);
    433       preferred_match_ = NULL;  // Don't delete, its owned by best_matches_.
    434       best_matches_[logins_result[i]->username_value] = logins_result[i];
    435     }
    436     preferred_match_ = logins_result[i]->preferred ? logins_result[i]
    437                                                    : preferred_match_;
    438   }
    439   // We're done matching now.
    440   state_ = POST_MATCHING_PHASE;
    441 
    442   client_->AutofillResultsComputed();
    443 
    444   // TODO(gcasto): Change this to check that best_matches_ is empty. This should
    445   // be equivalent for the moment, but it's less clear and may not be
    446   // equivalent in the future.
    447   if (best_score <= 0) {
    448     // If no saved forms can be used, then it isn't blacklisted and generation
    449     // should be allowed.
    450     driver_->AllowPasswordGenerationForForm(observed_form_);
    451     return;
    452   }
    453 
    454   for (std::vector<PasswordForm>::const_iterator it =
    455            credentials_to_keep.begin();
    456        it != credentials_to_keep.end(); ++it) {
    457     // If we don't already have a result with the same username, add the
    458     // lower-scored match (if it had equal score it would already be in
    459     // best_matches_).
    460     if (best_matches_.find(it->username_value) == best_matches_.end())
    461       best_matches_[it->username_value] = new PasswordForm(*it);
    462   }
    463 
    464   UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown",
    465                        logins_result.size() - best_matches_.size());
    466 
    467   // It is possible we have at least one match but have no preferred_match_,
    468   // because a user may have chosen to 'Forget' the preferred match. So we
    469   // just pick the first one and whichever the user selects for submit will
    470   // be saved as preferred.
    471   DCHECK(!best_matches_.empty());
    472   if (!preferred_match_)
    473     preferred_match_ = best_matches_.begin()->second;
    474 
    475   // Check to see if the user told us to ignore this site in the past.
    476   if (preferred_match_->blacklisted_by_user) {
    477     client_->PasswordAutofillWasBlocked(best_matches_);
    478     manager_action_ = kManagerActionBlacklisted;
    479     return;
    480   }
    481 
    482   // If not blacklisted, inform the driver that password generation is allowed
    483   // for |observed_form_|.
    484   driver_->AllowPasswordGenerationForForm(observed_form_);
    485 
    486   // Proceed to autofill.
    487   // Note that we provide the choices but don't actually prefill a value if:
    488   // (1) we are in Incognito mode, (2) the ACTION paths don't match,
    489   // or (3) if it matched using public suffix domain matching.
    490   bool wait_for_username =
    491       driver_->IsOffTheRecord() ||
    492       observed_form_.action.GetWithEmptyPath() !=
    493           preferred_match_->action.GetWithEmptyPath() ||
    494           preferred_match_->IsPublicSuffixMatch();
    495   if (wait_for_username)
    496     manager_action_ = kManagerActionNone;
    497   else
    498     manager_action_ = kManagerActionAutofilled;
    499   password_manager_->Autofill(observed_form_, best_matches_,
    500                               *preferred_match_, wait_for_username);
    501 }
    502 
    503 void PasswordFormManager::OnGetPasswordStoreResults(
    504       const std::vector<autofill::PasswordForm*>& results) {
    505   DCHECK_EQ(state_, MATCHING_PHASE);
    506 
    507   if (results.empty()) {
    508     state_ = POST_MATCHING_PHASE;
    509     // No result means that we visit this site the first time so we don't need
    510     // to check whether this site is blacklisted or not. Just send a message
    511     // to allow password generation.
    512     driver_->AllowPasswordGenerationForForm(observed_form_);
    513     return;
    514   }
    515   OnRequestDone(results);
    516 }
    517 
    518 bool PasswordFormManager::ShouldIgnoreResult(const PasswordForm& form) const {
    519   // Do not autofill on sign-up or change password forms (until we have some
    520   // working change password functionality).
    521   if (!observed_form_.new_password_element.empty())
    522     return true;
    523   // Don't match an invalid SSL form with one saved under secure circumstances.
    524   if (form.ssl_valid && !observed_form_.ssl_valid)
    525     return true;
    526 
    527   if (client_->ShouldFilterAutofillResult(form))
    528     return true;
    529 
    530   return false;
    531 }
    532 
    533 void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) {
    534   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    535   DCHECK(IsNewLogin());
    536   // The new_form is being used to sign in, so it is preferred.
    537   DCHECK(pending_credentials_.preferred);
    538   // new_form contains the same basic data as observed_form_ (because its the
    539   // same form), but with the newly added credentials.
    540 
    541   DCHECK(!driver_->IsOffTheRecord());
    542 
    543   PasswordStore* password_store = client_->GetPasswordStore();
    544   if (!password_store) {
    545     NOTREACHED();
    546     return;
    547   }
    548 
    549   // Upload credentials the first time they are saved. This data is used
    550   // by password generation to help determine account creation sites.
    551   // Blacklisted credentials will never be used, so don't upload a vote for
    552   // them.
    553   if (!pending_credentials_.blacklisted_by_user)
    554     UploadPasswordForm(pending_credentials_.form_data, autofill::PASSWORD);
    555 
    556   pending_credentials_.date_created = Time::Now();
    557   SanitizePossibleUsernames(&pending_credentials_);
    558   password_store->AddLogin(pending_credentials_);
    559 
    560   if (reset_preferred_login) {
    561     UpdatePreferredLoginState(password_store);
    562   }
    563 }
    564 
    565 void PasswordFormManager::SanitizePossibleUsernames(PasswordForm* form) {
    566   // Remove any possible usernames that could be credit cards or SSN for privacy
    567   // reasons. Also remove duplicates, both in other_possible_usernames and
    568   // between other_possible_usernames and username_value.
    569   std::set<base::string16> set;
    570   for (std::vector<base::string16>::iterator it =
    571            form->other_possible_usernames.begin();
    572        it != form->other_possible_usernames.end(); ++it) {
    573     if (!autofill::IsValidCreditCardNumber(*it) && !autofill::IsSSN(*it))
    574       set.insert(*it);
    575   }
    576   set.erase(form->username_value);
    577   std::vector<base::string16> temp(set.begin(), set.end());
    578   form->other_possible_usernames.swap(temp);
    579 }
    580 
    581 void PasswordFormManager::UpdatePreferredLoginState(
    582     PasswordStore* password_store) {
    583   DCHECK(password_store);
    584   PasswordFormMap::iterator iter;
    585   for (iter = best_matches_.begin(); iter != best_matches_.end(); iter++) {
    586     if (iter->second->username_value != pending_credentials_.username_value &&
    587         iter->second->preferred) {
    588       // This wasn't the selected login but it used to be preferred.
    589       iter->second->preferred = false;
    590       if (user_action_ == kUserActionNone)
    591         user_action_ = kUserActionChoose;
    592       password_store->UpdateLogin(*iter->second);
    593     }
    594   }
    595 }
    596 
    597 void PasswordFormManager::UpdateLogin() {
    598   DCHECK_EQ(state_, POST_MATCHING_PHASE);
    599   DCHECK(preferred_match_);
    600   // If we're doing an Update, we either autofilled correctly and need to
    601   // update the stats, or the user typed in a new password for autofilled
    602   // username, or the user selected one of the non-preferred matches,
    603   // thus requiring a swap of preferred bits.
    604   DCHECK(!IsNewLogin() && pending_credentials_.preferred);
    605   DCHECK(!driver_->IsOffTheRecord());
    606 
    607   PasswordStore* password_store = client_->GetPasswordStore();
    608   if (!password_store) {
    609     NOTREACHED();
    610     return;
    611   }
    612 
    613   // Update metadata.
    614   ++pending_credentials_.times_used;
    615 
    616   if (client_->IsSyncAccountCredential(
    617           base::UTF16ToUTF8(pending_credentials_.username_value),
    618           pending_credentials_.signon_realm)) {
    619     base::RecordAction(
    620         base::UserMetricsAction("PasswordManager_SyncCredentialUsed"));
    621   }
    622 
    623   // Check to see if this form is a candidate for password generation.
    624   CheckForAccountCreationForm(pending_credentials_, observed_form_);
    625 
    626   UpdatePreferredLoginState(password_store);
    627 
    628   // Remove alternate usernames. At this point we assume that we have found
    629   // the right username.
    630   pending_credentials_.other_possible_usernames.clear();
    631 
    632   // Update the new preferred login.
    633   if (!selected_username_.empty()) {
    634     // An other possible username is selected. We set this selected username
    635     // as the real username. The PasswordStore API isn't designed to update
    636     // username, so we delete the old credentials and add a new one instead.
    637     password_store->RemoveLogin(pending_credentials_);
    638     pending_credentials_.username_value = selected_username_;
    639     password_store->AddLogin(pending_credentials_);
    640   } else if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
    641              (observed_form_.origin.spec().length() >
    642               observed_form_.signon_realm.length()) &&
    643              (observed_form_.signon_realm ==
    644               pending_credentials_.origin.spec())) {
    645     // Note origin.spec().length > signon_realm.length implies the origin has a
    646     // path, since signon_realm is a prefix of origin for HTML password forms.
    647     //
    648     // The user logged in successfully with one of our autofilled logins on a
    649     // page with non-empty path, but the autofilled entry was initially saved/
    650     // imported with an empty path. Rather than just mark this entry preferred,
    651     // we create a more specific copy for this exact page and leave the "master"
    652     // unchanged. This is to prevent the case where that master login is used
    653     // on several sites (e.g site.com/a and site.com/b) but the user actually
    654     // has a different preference on each site. For example, on /a, he wants the
    655     // general empty-path login so it is flagged as preferred, but on /b he logs
    656     // in with a different saved entry - we don't want to remove the preferred
    657     // status of the former because upon return to /a it won't be the default-
    658     // fill match.
    659     // TODO(timsteele): Bug 1188626 - expire the master copies.
    660     PasswordForm copy(pending_credentials_);
    661     copy.origin = observed_form_.origin;
    662     copy.action = observed_form_.action;
    663     password_store->AddLogin(copy);
    664   } else if (observed_form_.new_password_element.empty() &&
    665              (pending_credentials_.password_element.empty() ||
    666               pending_credentials_.username_element.empty() ||
    667               pending_credentials_.submit_element.empty())) {
    668     // If |observed_form_| was a sign-up or change password form, there is no
    669     // point in trying to update element names: they are likely going to be
    670     // different than those on a login form.
    671     // Otherwise, given that |password_element| and |username_element| can't be
    672     // updated because they are part of Sync and PasswordStore primary key, we
    673     // must delete the old credentials altogether and then add the new ones.
    674     password_store->RemoveLogin(pending_credentials_);
    675     pending_credentials_.password_element = observed_form_.password_element;
    676     pending_credentials_.username_element = observed_form_.username_element;
    677     pending_credentials_.submit_element = observed_form_.submit_element;
    678     password_store->AddLogin(pending_credentials_);
    679   } else {
    680     password_store->UpdateLogin(pending_credentials_);
    681   }
    682 }
    683 
    684 bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
    685     const base::string16& username) {
    686   for (PasswordFormMap::const_iterator it = best_matches_.begin();
    687        it != best_matches_.end(); ++it) {
    688     for (size_t i = 0; i < it->second->other_possible_usernames.size(); ++i) {
    689       if (it->second->other_possible_usernames[i] == username) {
    690         pending_credentials_ = *it->second;
    691         return true;
    692       }
    693     }
    694   }
    695   return false;
    696 }
    697 
    698 void PasswordFormManager::CheckForAccountCreationForm(
    699     const PasswordForm& pending, const PasswordForm& observed) {
    700   // We check to see if the saved form_data is the same as the observed
    701   // form_data, which should never be true for passwords saved on account
    702   // creation forms. This check is only made the first time a password is used
    703   // to cut down on false positives. Specifically a site may have multiple login
    704   // forms with different markup, which might look similar to a signup form.
    705   if (pending.times_used == 1) {
    706     FormStructure pending_structure(pending.form_data);
    707     FormStructure observed_structure(observed.form_data);
    708     // Ignore |pending_structure| if its FormData has no fields. This is to
    709     // weed out those credentials that were saved before FormData was added
    710     // to PasswordForm. Even without this check, these FormStructure's won't
    711     // be uploaded, but it makes it hard to see if we are encountering
    712     // unexpected errors.
    713     if (!pending.form_data.fields.empty() &&
    714         pending_structure.FormSignature() !=
    715             observed_structure.FormSignature()) {
    716       UploadPasswordForm(pending.form_data,
    717                          autofill::ACCOUNT_CREATION_PASSWORD);
    718     }
    719   }
    720 }
    721 
    722 void PasswordFormManager::UploadPasswordForm(
    723     const autofill::FormData& form_data,
    724     const autofill::ServerFieldType& password_type) {
    725   autofill::AutofillManager* autofill_manager =
    726       driver_->GetAutofillManager();
    727   if (!autofill_manager)
    728     return;
    729 
    730   // Note that this doesn't guarantee that the upload succeeded, only that
    731   // |form_data| is considered uploadable.
    732   bool success =
    733       autofill_manager->UploadPasswordForm(form_data, password_type);
    734   UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success);
    735 }
    736 
    737 int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const {
    738   DCHECK_EQ(state_, MATCHING_PHASE);
    739   // For scoring of candidate login data:
    740   // The most important element that should match is the signon_realm followed
    741   // by the origin, the action, the password name, the submit button name, and
    742   // finally the username input field name.
    743   // If public suffix origin match was not used, it gives an addition of
    744   // 128 (1 << 7).
    745   // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
    746   // dirs.
    747   // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
    748   // That way, a partial match cannot trump an exact match even if
    749   // the partial one matches all other attributes (action, elements) (and
    750   // regardless of the matching depth in the URL path).
    751   int score = 0;
    752   if (!candidate.IsPublicSuffixMatch()) {
    753     score += 1 << 7;
    754   }
    755   if (candidate.origin == observed_form_.origin) {
    756     // This check is here for the most common case which
    757     // is we have a single match in the db for the given host,
    758     // so we don't generally need to walk the entire URL path (the else
    759     // clause).
    760     score += (1 << 6) + static_cast<int>(form_path_tokens_.size());
    761   } else {
    762     // Walk the origin URL paths one directory at a time to see how
    763     // deep the two match.
    764     std::vector<std::string> candidate_path_tokens;
    765     base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens);
    766     size_t depth = 0;
    767     size_t max_dirs = std::min(form_path_tokens_.size(),
    768                                candidate_path_tokens.size());
    769     while ((depth < max_dirs) && (form_path_tokens_[depth] ==
    770                                   candidate_path_tokens[depth])) {
    771       depth++;
    772       score++;
    773     }
    774     // do we have a partial match?
    775     score += (depth > 0) ? 1 << 5 : 0;
    776   }
    777   if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
    778     if (candidate.action == observed_form_.action)
    779       score += 1 << 3;
    780     if (candidate.password_element == observed_form_.password_element)
    781       score += 1 << 2;
    782     if (candidate.submit_element == observed_form_.submit_element)
    783       score += 1 << 1;
    784     if (candidate.username_element == observed_form_.username_element)
    785       score += 1 << 0;
    786   }
    787 
    788   return score;
    789 }
    790 
    791 void PasswordFormManager::SubmitPassed() {
    792   submit_result_ = kSubmitResultPassed;
    793   if (has_generated_password_)
    794     LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED);
    795 }
    796 
    797 void PasswordFormManager::SubmitFailed() {
    798   submit_result_ = kSubmitResultFailed;
    799   if (has_generated_password_)
    800     LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED);
    801 }
    802 
    803 }  // namespace password_manager
    804