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