6033da65ac42cb799550c4cc21a7b2244838b3fb
[platform/framework/web/crosswalk.git] / src / components / password_manager / core / browser / password_form_manager.cc
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
9 #include "base/metrics/histogram.h"
10 #include "base/metrics/user_metrics.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "components/autofill/core/browser/autofill_manager.h"
15 #include "components/autofill/core/browser/form_structure.h"
16 #include "components/autofill/core/browser/validation.h"
17 #include "components/autofill/core/common/password_form.h"
18 #include "components/password_manager/core/browser/password_manager.h"
19 #include "components/password_manager/core/browser/password_manager_client.h"
20 #include "components/password_manager/core/browser/password_manager_driver.h"
21 #include "components/password_manager/core/browser/password_store.h"
22
23 using autofill::FormStructure;
24 using autofill::PasswordForm;
25 using autofill::PasswordFormMap;
26 using base::Time;
27
28 namespace password_manager {
29
30 namespace {
31
32 enum PasswordGenerationSubmissionEvent {
33   // Generated password was submitted and saved.
34   PASSWORD_SUBMITTED,
35
36   // Generated password submission failed. These passwords aren't saved.
37   PASSWORD_SUBMISSION_FAILED,
38
39   // Generated password was not submitted before navigation. Currently these
40   // passwords are not saved.
41   PASSWORD_NOT_SUBMITTED,
42
43   // Generated password was overridden by a non-generated one. This generally
44   // signals that the user was unhappy with the generated password for some
45   // reason.
46   PASSWORD_OVERRIDDEN,
47
48   // Number of enum entries, used for UMA histogram reporting macros.
49   SUBMISSION_EVENT_ENUM_COUNT
50 };
51
52 void LogPasswordGenerationSubmissionEvent(
53     PasswordGenerationSubmissionEvent event) {
54   UMA_HISTOGRAM_ENUMERATION("PasswordGeneration.SubmissionEvent",
55                             event, SUBMISSION_EVENT_ENUM_COUNT);
56 }
57
58 PasswordForm CopyAndModifySSLValidity(const PasswordForm& orig,
59                                       bool ssl_valid) {
60   PasswordForm result(orig);
61   result.ssl_valid = ssl_valid;
62   return result;
63 }
64
65 }  // namespace
66
67 PasswordFormManager::PasswordFormManager(PasswordManager* password_manager,
68                                          PasswordManagerClient* client,
69                                          PasswordManagerDriver* driver,
70                                          const PasswordForm& observed_form,
71                                          bool ssl_valid)
72     : best_matches_deleter_(&best_matches_),
73       observed_form_(CopyAndModifySSLValidity(observed_form, ssl_valid)),
74       is_new_login_(true),
75       has_generated_password_(false),
76       password_manager_(password_manager),
77       preferred_match_(NULL),
78       state_(PRE_MATCHING_PHASE),
79       client_(client),
80       driver_(driver),
81       manager_action_(kManagerActionNone),
82       user_action_(kUserActionNone),
83       submit_result_(kSubmitResultNotSubmitted) {
84   if (observed_form_.origin.is_valid())
85     base::SplitString(observed_form_.origin.path(), '/', &form_path_tokens_);
86 }
87
88 PasswordFormManager::~PasswordFormManager() {
89   UMA_HISTOGRAM_ENUMERATION(
90       "PasswordManager.ActionsTakenV3", GetActionsTaken(), kMaxNumActionsTaken);
91   if (has_generated_password_ && submit_result_ == kSubmitResultNotSubmitted)
92     LogPasswordGenerationSubmissionEvent(PASSWORD_NOT_SUBMITTED);
93 }
94
95 int PasswordFormManager::GetActionsTaken() {
96   return user_action_ + kUserActionMax * (manager_action_ +
97          kManagerActionMax * submit_result_);
98 };
99
100 // TODO(timsteele): use a hash of some sort in the future?
101 PasswordFormManager::MatchResultMask PasswordFormManager::DoesManage(
102     const PasswordForm& form) const {
103   // Non-HTML form case.
104   if (observed_form_.scheme != PasswordForm::SCHEME_HTML ||
105       form.scheme != PasswordForm::SCHEME_HTML) {
106     const bool forms_match = observed_form_.signon_realm == form.signon_realm &&
107                              observed_form_.scheme == form.scheme;
108     return forms_match ? RESULT_COMPLETE_MATCH : RESULT_NO_MATCH;
109   }
110
111   // HTML form case.
112   MatchResultMask result = RESULT_NO_MATCH;
113
114   // Easiest case of matching origins.
115   bool origins_match = form.origin == observed_form_.origin;
116   // If this is a replay of the same form in the case a user entered an invalid
117   // password, the origin of the new form may equal the action of the "first"
118   // form instead.
119   origins_match = origins_match || (form.origin == observed_form_.action);
120   // Otherwise, if action hosts are the same, the old URL scheme is HTTP while
121   // the new one is HTTPS, and the new path equals to or extends the old path,
122   // we also consider the actions a match. This is to accommodate cases where
123   // the original login form is on an HTTP page, but a failed login attempt
124   // redirects to HTTPS (as in http://example.org -> https://example.org/auth).
125   if (!origins_match && !observed_form_.origin.SchemeIsSecure() &&
126       form.origin.SchemeIsSecure()) {
127     const std::string& old_path = observed_form_.origin.path();
128     const std::string& new_path = form.origin.path();
129     origins_match =
130         observed_form_.origin.host() == form.origin.host() &&
131         observed_form_.origin.port() == form.origin.port() &&
132         StartsWithASCII(new_path, old_path, /*case_sensitive=*/true);
133   }
134
135   if (form.username_element == observed_form_.username_element &&
136       form.password_element == observed_form_.password_element &&
137       origins_match) {
138     result |= RESULT_MANDATORY_ATTRIBUTES_MATCH;
139   }
140
141   // Note: although saved password forms might actually have an empty action
142   // URL if they were imported (see bug 1107719), the |form| we see here comes
143   // never from the password store, and should have an exactly matching action.
144   if (form.action == observed_form_.action)
145     result |= RESULT_ACTION_MATCH;
146
147   return result;
148 }
149
150 bool PasswordFormManager::IsBlacklisted() {
151   DCHECK_EQ(state_, POST_MATCHING_PHASE);
152   if (preferred_match_ && preferred_match_->blacklisted_by_user)
153     return true;
154   return false;
155 }
156
157 void PasswordFormManager::PermanentlyBlacklist() {
158   DCHECK_EQ(state_, POST_MATCHING_PHASE);
159
160   // Configure the form about to be saved for blacklist status.
161   pending_credentials_.preferred = true;
162   pending_credentials_.blacklisted_by_user = true;
163   pending_credentials_.username_value.clear();
164   pending_credentials_.password_value.clear();
165
166   // Retroactively forget existing matches for this form, so we NEVER prompt or
167   // autofill it again.
168   int num_passwords_deleted = 0;
169   if (!best_matches_.empty()) {
170     PasswordFormMap::const_iterator iter;
171     PasswordStore* password_store = client_->GetPasswordStore();
172     if (!password_store) {
173       NOTREACHED();
174       return;
175     }
176     for (iter = best_matches_.begin(); iter != best_matches_.end(); ++iter) {
177       // We want to remove existing matches for this form so that the exact
178       // origin match with |blackisted_by_user == true| is the only result that
179       // shows up in the future for this origin URL. However, we don't want to
180       // delete logins that were actually saved on a different page (hence with
181       // different origin URL) and just happened to match this form because of
182       // the scoring algorithm. See bug 1204493.
183       if (iter->second->origin == observed_form_.origin) {
184         password_store->RemoveLogin(*iter->second);
185         ++num_passwords_deleted;
186       }
187     }
188   }
189
190   UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsDeletedWhenBlacklisting",
191                        num_passwords_deleted);
192
193   // Save the pending_credentials_ entry marked as blacklisted.
194   SaveAsNewLogin(false);
195 }
196
197 void PasswordFormManager::SetUseAdditionalPasswordAuthentication(
198     bool use_additional_authentication) {
199   pending_credentials_.use_additional_authentication =
200       use_additional_authentication;
201 }
202
203 bool PasswordFormManager::IsNewLogin() {
204   DCHECK_EQ(state_, POST_MATCHING_PHASE);
205   return is_new_login_;
206 }
207
208 bool PasswordFormManager::IsPendingCredentialsPublicSuffixMatch() {
209   return pending_credentials_.IsPublicSuffixMatch();
210 }
211
212 void PasswordFormManager::SetHasGeneratedPassword() {
213   has_generated_password_ = true;
214 }
215
216 bool PasswordFormManager::HasGeneratedPassword() {
217   // This check is permissive, as the user may have generated a password and
218   // then edited it in the form itself. However, even in this case the user
219   // has already given consent, so we treat these cases the same.
220   return has_generated_password_;
221 }
222
223 bool PasswordFormManager::HasValidPasswordForm() {
224   DCHECK_EQ(state_, POST_MATCHING_PHASE);
225   // Non-HTML password forms (primarily HTTP and FTP autentication)
226   // do not contain username_element and password_element values.
227   if (observed_form_.scheme != PasswordForm::SCHEME_HTML)
228     return true;
229   return !observed_form_.username_element.empty() &&
230          (!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   if (best_score <= 0) {
445     return;
446   }
447
448   for (std::vector<PasswordForm>::const_iterator it =
449            credentials_to_keep.begin();
450        it != credentials_to_keep.end(); ++it) {
451     // If we don't already have a result with the same username, add the
452     // lower-scored match (if it had equal score it would already be in
453     // best_matches_).
454     if (best_matches_.find(it->username_value) == best_matches_.end())
455       best_matches_[it->username_value] = new PasswordForm(*it);
456   }
457
458   UMA_HISTOGRAM_COUNTS("PasswordManager.NumPasswordsNotShown",
459                        logins_result.size() - best_matches_.size());
460
461   // It is possible we have at least one match but have no preferred_match_,
462   // because a user may have chosen to 'Forget' the preferred match. So we
463   // just pick the first one and whichever the user selects for submit will
464   // be saved as preferred.
465   DCHECK(!best_matches_.empty());
466   if (!preferred_match_)
467     preferred_match_ = best_matches_.begin()->second;
468
469   // Check to see if the user told us to ignore this site in the past.
470   if (preferred_match_->blacklisted_by_user) {
471     client_->PasswordAutofillWasBlocked(best_matches_);
472     manager_action_ = kManagerActionBlacklisted;
473     return;
474   }
475
476   // If not blacklisted, inform the driver that password generation is allowed
477   // for |observed_form_|.
478   driver_->AllowPasswordGenerationForForm(observed_form_);
479
480   // Proceed to autofill.
481   // Note that we provide the choices but don't actually prefill a value if:
482   // (1) we are in Incognito mode, (2) the ACTION paths don't match,
483   // or (3) if it matched using public suffix domain matching.
484   bool wait_for_username =
485       driver_->IsOffTheRecord() ||
486       observed_form_.action.GetWithEmptyPath() !=
487           preferred_match_->action.GetWithEmptyPath() ||
488           preferred_match_->IsPublicSuffixMatch();
489   if (wait_for_username)
490     manager_action_ = kManagerActionNone;
491   else
492     manager_action_ = kManagerActionAutofilled;
493   password_manager_->Autofill(observed_form_, best_matches_,
494                               *preferred_match_, wait_for_username);
495 }
496
497 void PasswordFormManager::OnGetPasswordStoreResults(
498       const std::vector<autofill::PasswordForm*>& results) {
499   DCHECK_EQ(state_, MATCHING_PHASE);
500
501   if (results.empty()) {
502     state_ = POST_MATCHING_PHASE;
503     // No result means that we visit this site the first time so we don't need
504     // to check whether this site is blacklisted or not. Just send a message
505     // to allow password generation.
506     driver_->AllowPasswordGenerationForForm(observed_form_);
507     return;
508   }
509   OnRequestDone(results);
510 }
511
512 bool PasswordFormManager::ShouldIgnoreResult(const PasswordForm& form) const {
513   // Do not autofill on sign-up or change password forms (until we have some
514   // working change password functionality).
515   if (!observed_form_.new_password_element.empty())
516     return true;
517   // Don't match an invalid SSL form with one saved under secure circumstances.
518   if (form.ssl_valid && !observed_form_.ssl_valid)
519     return true;
520
521   if (client_->ShouldFilterAutofillResult(form))
522     return true;
523
524   return false;
525 }
526
527 void PasswordFormManager::SaveAsNewLogin(bool reset_preferred_login) {
528   DCHECK_EQ(state_, POST_MATCHING_PHASE);
529   DCHECK(IsNewLogin());
530   // The new_form is being used to sign in, so it is preferred.
531   DCHECK(pending_credentials_.preferred);
532   // new_form contains the same basic data as observed_form_ (because its the
533   // same form), but with the newly added credentials.
534
535   DCHECK(!driver_->IsOffTheRecord());
536
537   PasswordStore* password_store = client_->GetPasswordStore();
538   if (!password_store) {
539     NOTREACHED();
540     return;
541   }
542
543   pending_credentials_.date_created = Time::Now();
544   SanitizePossibleUsernames(&pending_credentials_);
545   password_store->AddLogin(pending_credentials_);
546
547   if (reset_preferred_login) {
548     UpdatePreferredLoginState(password_store);
549   }
550 }
551
552 void PasswordFormManager::SanitizePossibleUsernames(PasswordForm* form) {
553   // Remove any possible usernames that could be credit cards or SSN for privacy
554   // reasons. Also remove duplicates, both in other_possible_usernames and
555   // between other_possible_usernames and username_value.
556   std::set<base::string16> set;
557   for (std::vector<base::string16>::iterator it =
558            form->other_possible_usernames.begin();
559        it != form->other_possible_usernames.end(); ++it) {
560     if (!autofill::IsValidCreditCardNumber(*it) && !autofill::IsSSN(*it))
561       set.insert(*it);
562   }
563   set.erase(form->username_value);
564   std::vector<base::string16> temp(set.begin(), set.end());
565   form->other_possible_usernames.swap(temp);
566 }
567
568 void PasswordFormManager::UpdatePreferredLoginState(
569     PasswordStore* password_store) {
570   DCHECK(password_store);
571   PasswordFormMap::iterator iter;
572   for (iter = best_matches_.begin(); iter != best_matches_.end(); iter++) {
573     if (iter->second->username_value != pending_credentials_.username_value &&
574         iter->second->preferred) {
575       // This wasn't the selected login but it used to be preferred.
576       iter->second->preferred = false;
577       if (user_action_ == kUserActionNone)
578         user_action_ = kUserActionChoose;
579       password_store->UpdateLogin(*iter->second);
580     }
581   }
582 }
583
584 void PasswordFormManager::UpdateLogin() {
585   DCHECK_EQ(state_, POST_MATCHING_PHASE);
586   DCHECK(preferred_match_);
587   // If we're doing an Update, we either autofilled correctly and need to
588   // update the stats, or the user typed in a new password for autofilled
589   // username, or the user selected one of the non-preferred matches,
590   // thus requiring a swap of preferred bits.
591   DCHECK(!IsNewLogin() && pending_credentials_.preferred);
592   DCHECK(!driver_->IsOffTheRecord());
593
594   PasswordStore* password_store = client_->GetPasswordStore();
595   if (!password_store) {
596     NOTREACHED();
597     return;
598   }
599
600   // Update metadata.
601   ++pending_credentials_.times_used;
602
603   if (client_->IsSyncAccountCredential(
604           base::UTF16ToUTF8(pending_credentials_.username_value),
605           pending_credentials_.signon_realm)) {
606     base::RecordAction(
607         base::UserMetricsAction("PasswordManager_SyncCredentialUsed"));
608   }
609
610   // Check to see if this form is a candidate for password generation.
611   CheckForAccountCreationForm(pending_credentials_, observed_form_);
612
613   UpdatePreferredLoginState(password_store);
614
615   // Remove alternate usernames. At this point we assume that we have found
616   // the right username.
617   pending_credentials_.other_possible_usernames.clear();
618
619   // Update the new preferred login.
620   if (!selected_username_.empty()) {
621     // An other possible username is selected. We set this selected username
622     // as the real username. The PasswordStore API isn't designed to update
623     // username, so we delete the old credentials and add a new one instead.
624     password_store->RemoveLogin(pending_credentials_);
625     pending_credentials_.username_value = selected_username_;
626     password_store->AddLogin(pending_credentials_);
627   } else if ((observed_form_.scheme == PasswordForm::SCHEME_HTML) &&
628              (observed_form_.origin.spec().length() >
629               observed_form_.signon_realm.length()) &&
630              (observed_form_.signon_realm ==
631               pending_credentials_.origin.spec())) {
632     // Note origin.spec().length > signon_realm.length implies the origin has a
633     // path, since signon_realm is a prefix of origin for HTML password forms.
634     //
635     // The user logged in successfully with one of our autofilled logins on a
636     // page with non-empty path, but the autofilled entry was initially saved/
637     // imported with an empty path. Rather than just mark this entry preferred,
638     // we create a more specific copy for this exact page and leave the "master"
639     // unchanged. This is to prevent the case where that master login is used
640     // on several sites (e.g site.com/a and site.com/b) but the user actually
641     // has a different preference on each site. For example, on /a, he wants the
642     // general empty-path login so it is flagged as preferred, but on /b he logs
643     // in with a different saved entry - we don't want to remove the preferred
644     // status of the former because upon return to /a it won't be the default-
645     // fill match.
646     // TODO(timsteele): Bug 1188626 - expire the master copies.
647     PasswordForm copy(pending_credentials_);
648     copy.origin = observed_form_.origin;
649     copy.action = observed_form_.action;
650     password_store->AddLogin(copy);
651   } else if (observed_form_.new_password_element.empty() &&
652              (pending_credentials_.password_element.empty() ||
653               pending_credentials_.username_element.empty() ||
654               pending_credentials_.submit_element.empty())) {
655     // If |observed_form_| was a sign-up or change password form, there is no
656     // point in trying to update element names: they are likely going to be
657     // different than those on a login form.
658     // Otherwise, given that |password_element| and |username_element| can't be
659     // updated because they are part of Sync and PasswordStore primary key, we
660     // must delete the old credentials altogether and then add the new ones.
661     password_store->RemoveLogin(pending_credentials_);
662     pending_credentials_.password_element = observed_form_.password_element;
663     pending_credentials_.username_element = observed_form_.username_element;
664     pending_credentials_.submit_element = observed_form_.submit_element;
665     password_store->AddLogin(pending_credentials_);
666   } else {
667     password_store->UpdateLogin(pending_credentials_);
668   }
669 }
670
671 bool PasswordFormManager::UpdatePendingCredentialsIfOtherPossibleUsername(
672     const base::string16& username) {
673   for (PasswordFormMap::const_iterator it = best_matches_.begin();
674        it != best_matches_.end(); ++it) {
675     for (size_t i = 0; i < it->second->other_possible_usernames.size(); ++i) {
676       if (it->second->other_possible_usernames[i] == username) {
677         pending_credentials_ = *it->second;
678         return true;
679       }
680     }
681   }
682   return false;
683 }
684
685 void PasswordFormManager::CheckForAccountCreationForm(
686     const PasswordForm& pending, const PasswordForm& observed) {
687   // We check to see if the saved form_data is the same as the observed
688   // form_data, which should never be true for passwords saved on account
689   // creation forms. This check is only made the first time a password is used
690   // to cut down on false positives. Specifically a site may have multiple login
691   // forms with different markup, which might look similar to a signup form.
692   if (pending.times_used == 1) {
693     FormStructure pending_structure(pending.form_data);
694     FormStructure observed_structure(observed.form_data);
695     // Ignore |pending_structure| if its FormData has no fields. This is to
696     // weed out those credentials that were saved before FormData was added
697     // to PasswordForm. Even without this check, these FormStructure's won't
698     // be uploaded, but it makes it hard to see if we are encountering
699     // unexpected errors.
700     if (!pending.form_data.fields.empty() &&
701         pending_structure.FormSignature() !=
702             observed_structure.FormSignature()) {
703       autofill::AutofillManager* autofill_manager =
704           driver_->GetAutofillManager();
705       if (autofill_manager) {
706         // Note that this doesn't guarantee that the upload succeeded, only that
707         // |pending.form_data| is considered uploadable.
708         bool success =
709             autofill_manager->UploadPasswordGenerationForm(pending.form_data);
710         UMA_HISTOGRAM_BOOLEAN("PasswordGeneration.UploadStarted", success);
711       }
712     }
713   }
714 }
715
716 int PasswordFormManager::ScoreResult(const PasswordForm& candidate) const {
717   DCHECK_EQ(state_, MATCHING_PHASE);
718   // For scoring of candidate login data:
719   // The most important element that should match is the signon_realm followed
720   // by the origin, the action, the password name, the submit button name, and
721   // finally the username input field name.
722   // If public suffix origin match was not used, it gives an addition of
723   // 128 (1 << 7).
724   // Exact origin match gives an addition of 64 (1 << 6) + # of matching url
725   // dirs.
726   // Partial match gives an addition of 32 (1 << 5) + # matching url dirs
727   // That way, a partial match cannot trump an exact match even if
728   // the partial one matches all other attributes (action, elements) (and
729   // regardless of the matching depth in the URL path).
730   int score = 0;
731   if (!candidate.IsPublicSuffixMatch()) {
732     score += 1 << 7;
733   }
734   if (candidate.origin == observed_form_.origin) {
735     // This check is here for the most common case which
736     // is we have a single match in the db for the given host,
737     // so we don't generally need to walk the entire URL path (the else
738     // clause).
739     score += (1 << 6) + static_cast<int>(form_path_tokens_.size());
740   } else {
741     // Walk the origin URL paths one directory at a time to see how
742     // deep the two match.
743     std::vector<std::string> candidate_path_tokens;
744     base::SplitString(candidate.origin.path(), '/', &candidate_path_tokens);
745     size_t depth = 0;
746     size_t max_dirs = std::min(form_path_tokens_.size(),
747                                candidate_path_tokens.size());
748     while ((depth < max_dirs) && (form_path_tokens_[depth] ==
749                                   candidate_path_tokens[depth])) {
750       depth++;
751       score++;
752     }
753     // do we have a partial match?
754     score += (depth > 0) ? 1 << 5 : 0;
755   }
756   if (observed_form_.scheme == PasswordForm::SCHEME_HTML) {
757     if (candidate.action == observed_form_.action)
758       score += 1 << 3;
759     if (candidate.password_element == observed_form_.password_element)
760       score += 1 << 2;
761     if (candidate.submit_element == observed_form_.submit_element)
762       score += 1 << 1;
763     if (candidate.username_element == observed_form_.username_element)
764       score += 1 << 0;
765   }
766
767   return score;
768 }
769
770 void PasswordFormManager::SubmitPassed() {
771   submit_result_ = kSubmitResultPassed;
772   if (has_generated_password_)
773     LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMITTED);
774 }
775
776 void PasswordFormManager::SubmitFailed() {
777   submit_result_ = kSubmitResultFailed;
778   if (has_generated_password_)
779     LogPasswordGenerationSubmissionEvent(PASSWORD_SUBMISSION_FAILED);
780 }
781
782 }  // namespace password_manager