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
24using autofill::FormStructure;
25using autofill::PasswordForm;
26using autofill::PasswordFormMap;
27using base::Time;
28
29namespace password_manager {
30
31namespace {
32
33enum 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
53void LogPasswordGenerationSubmissionEvent(
54    PasswordGenerationSubmissionEvent event) {
55  UMA_HISTOGRAM_ENUMERATION("PasswordGeneration.SubmissionEvent",
56                            event, SUBMISSION_EVENT_ENUM_COUNT);
57}
58
59PasswordForm 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
68PasswordFormManager::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
89PasswordFormManager::~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
96int 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?
102PasswordFormManager::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
151bool 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
158void 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
198void PasswordFormManager::SetUseAdditionalPasswordAuthentication(
199    bool use_additional_authentication) {
200  pending_credentials_.use_additional_authentication =
201      use_additional_authentication;
202}
203
204bool PasswordFormManager::IsNewLogin() {
205  DCHECK_EQ(state_, POST_MATCHING_PHASE);
206  return is_new_login_;
207}
208
209bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
210  return pending_credentials_.IsPublicSuffixMatch();
211}
212
213void PasswordFormManager::SetHasGeneratedPassword() {
214  has_generated_password_ = true;
215}
216
217bool 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
224bool 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
234void 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
346void 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
356void 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
368bool PasswordFormManager::HasCompletedMatching() {
369  return state_ == POST_MATCHING_PHASE;
370}
371
372void 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
503void 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
518bool 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
533void 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
565void 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
581void 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
597void 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
684bool 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
698void 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
722void 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
737int 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
791void PasswordFormManager::SubmitPassed() {
792  submit_result_ = kSubmitResultPassed;
793  if (has_generated_password_)
794    LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED);
795}
796
797void PasswordFormManager::SubmitFailed() {
798  submit_result_ = kSubmitResultFailed;
799  if (has_generated_password_)
800    LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED);
801}
802
803}  // namespace password_manager
804