Home | History | Annotate | Download | only in password_manager
      1 // Copyright (c) 2011 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 "chrome/browser/password_manager/password_manager.h"
      6 
      7 #include <vector>
      8 
      9 #include "base/stl_util-inl.h"
     10 #include "base/threading/platform_thread.h"
     11 #include "base/utf_string_conversions.h"
     12 #include "chrome/browser/metrics/user_metrics.h"
     13 #include "chrome/browser/password_manager/password_form_manager.h"
     14 #include "chrome/browser/password_manager/password_manager_delegate.h"
     15 #include "chrome/browser/prefs/pref_service.h"
     16 #include "chrome/browser/profiles/profile.h"
     17 #include "chrome/common/autofill_messages.h"
     18 #include "chrome/common/pref_names.h"
     19 #include "content/common/view_messages.h"
     20 #include "grit/generated_resources.h"
     21 
     22 using webkit_glue::PasswordForm;
     23 using webkit_glue::PasswordFormMap;
     24 
     25 // static
     26 void PasswordManager::RegisterUserPrefs(PrefService* prefs) {
     27   prefs->RegisterBooleanPref(prefs::kPasswordManagerEnabled, true);
     28   prefs->RegisterBooleanPref(prefs::kPasswordManagerAllowShowPasswords, true);
     29 }
     30 
     31 // This routine is called when PasswordManagers are constructed.
     32 //
     33 // Currently we report metrics only once at startup. We require
     34 // that this is only ever called from a single thread in order to
     35 // avoid needing to lock (a static boolean flag is then sufficient to
     36 // guarantee running only once).
     37 static void ReportMetrics(bool password_manager_enabled) {
     38   static base::PlatformThreadId initial_thread_id =
     39       base::PlatformThread::CurrentId();
     40   DCHECK(initial_thread_id == base::PlatformThread::CurrentId());
     41 
     42   static bool ran_once = false;
     43   if (ran_once)
     44     return;
     45   ran_once = true;
     46 
     47   if (password_manager_enabled)
     48     UserMetrics::RecordAction(UserMetricsAction("PasswordManager_Enabled"));
     49   else
     50     UserMetrics::RecordAction(UserMetricsAction("PasswordManager_Disabled"));
     51 }
     52 
     53 PasswordManager::PasswordManager(TabContents* tab_contents,
     54                                  PasswordManagerDelegate* delegate)
     55     : TabContentsObserver(tab_contents),
     56       login_managers_deleter_(&pending_login_managers_),
     57       delegate_(delegate),
     58       observer_(NULL) {
     59   DCHECK(delegate_);
     60   password_manager_enabled_.Init(prefs::kPasswordManagerEnabled,
     61       delegate_->GetProfileForPasswordManager()->GetPrefs(), NULL);
     62 
     63   ReportMetrics(*password_manager_enabled_);
     64 }
     65 
     66 PasswordManager::~PasswordManager() {
     67 }
     68 
     69 void PasswordManager::ProvisionallySavePassword(PasswordForm form) {
     70   if (!delegate_->GetProfileForPasswordManager() ||
     71       delegate_->GetProfileForPasswordManager()->IsOffTheRecord() ||
     72       !*password_manager_enabled_)
     73     return;
     74 
     75   // No password to save? Then don't.
     76   if (form.password_value.empty())
     77     return;
     78 
     79   LoginManagers::iterator iter;
     80   PasswordFormManager* manager = NULL;
     81   for (iter = pending_login_managers_.begin();
     82        iter != pending_login_managers_.end(); iter++) {
     83     if ((*iter)->DoesManage(form)) {
     84       manager = *iter;
     85       break;
     86     }
     87   }
     88   // If we didn't find a manager, this means a form was submitted without
     89   // first loading the page containing the form. Don't offer to save
     90   // passwords in this case.
     91   if (!manager)
     92     return;
     93 
     94   // If we found a manager but it didn't finish matching yet, the user has
     95   // tried to submit credentials before we had time to even find matching
     96   // results for the given form and autofill. If this is the case, we just
     97   // give up.
     98   if (!manager->HasCompletedMatching())
     99     return;
    100 
    101   // Also get out of here if the user told us to 'never remember' passwords for
    102   // this form.
    103   if (manager->IsBlacklisted())
    104     return;
    105 
    106   form.ssl_valid = form.origin.SchemeIsSecure() &&
    107       !delegate_->DidLastPageLoadEncounterSSLErrors();
    108   form.preferred = true;
    109   manager->ProvisionallySave(form);
    110   provisional_save_manager_.reset(manager);
    111   pending_login_managers_.erase(iter);
    112   // We don't care about the rest of the forms on the page now that one
    113   // was selected.
    114   STLDeleteElements(&pending_login_managers_);
    115 }
    116 
    117 void PasswordManager::DidNavigate() {
    118   // As long as this navigation isn't due to a currently pending
    119   // password form submit, we're ready to reset and move on.
    120   if (!provisional_save_manager_.get() && !pending_login_managers_.empty())
    121     STLDeleteElements(&pending_login_managers_);
    122 }
    123 
    124 void PasswordManager::ClearProvisionalSave() {
    125   provisional_save_manager_.reset();
    126 }
    127 
    128 void PasswordManager::SetObserver(LoginModelObserver* observer) {
    129   observer_ = observer;
    130 }
    131 
    132 void PasswordManager::DidStopLoading() {
    133   if (!provisional_save_manager_.get())
    134     return;
    135 
    136   DCHECK(!delegate_->GetProfileForPasswordManager()->IsOffTheRecord());
    137   DCHECK(!provisional_save_manager_->IsBlacklisted());
    138 
    139   if (!delegate_->GetProfileForPasswordManager())
    140     return;
    141   // Form is not completely valid - we do not support it.
    142   if (!provisional_save_manager_->HasValidPasswordForm())
    143     return;
    144 
    145   provisional_save_manager_->SubmitPassed();
    146   if (provisional_save_manager_->IsNewLogin()) {
    147     delegate_->AddSavePasswordInfoBar(provisional_save_manager_.release());
    148   } else {
    149     // If the save is not a new username entry, then we just want to save this
    150     // data (since the user already has related data saved), so don't prompt.
    151     provisional_save_manager_->Save();
    152     provisional_save_manager_.reset();
    153   }
    154 }
    155 
    156 void PasswordManager::DidNavigateAnyFramePostCommit(
    157       const NavigationController::LoadCommittedDetails& details,
    158       const ViewHostMsg_FrameNavigate_Params& params) {
    159   if (params.password_form.origin.is_valid())
    160     ProvisionallySavePassword(params.password_form);
    161 }
    162 
    163 bool PasswordManager::OnMessageReceived(const IPC::Message& message) {
    164   bool handled = true;
    165   IPC_BEGIN_MESSAGE_MAP(PasswordManager, message)
    166     IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordFormsFound,
    167                         OnPasswordFormsFound)
    168     IPC_MESSAGE_HANDLER(AutofillHostMsg_PasswordFormsVisible,
    169                         OnPasswordFormsVisible)
    170     IPC_MESSAGE_UNHANDLED(handled = false)
    171   IPC_END_MESSAGE_MAP()
    172   return handled;
    173 }
    174 
    175 void PasswordManager::OnPasswordFormsFound(
    176     const std::vector<PasswordForm>& forms) {
    177   if (!delegate_->GetProfileForPasswordManager())
    178     return;
    179   if (!*password_manager_enabled_)
    180     return;
    181 
    182   // Ask the SSLManager for current security.
    183   bool had_ssl_error = delegate_->DidLastPageLoadEncounterSSLErrors();
    184 
    185   std::vector<PasswordForm>::const_iterator iter;
    186   for (iter = forms.begin(); iter != forms.end(); iter++) {
    187     bool ssl_valid = iter->origin.SchemeIsSecure() && !had_ssl_error;
    188     PasswordFormManager* manager =
    189         new PasswordFormManager(delegate_->GetProfileForPasswordManager(),
    190                                 this, *iter, ssl_valid);
    191     pending_login_managers_.push_back(manager);
    192     manager->FetchMatchingLoginsFromPasswordStore();
    193   }
    194 }
    195 
    196 void PasswordManager::OnPasswordFormsVisible(
    197     const std::vector<PasswordForm>& visible_forms) {
    198   if (!provisional_save_manager_.get())
    199     return;
    200   std::vector<PasswordForm>::const_iterator iter;
    201   for (iter = visible_forms.begin(); iter != visible_forms.end(); iter++) {
    202     if (provisional_save_manager_->DoesManage(*iter)) {
    203       // The form trying to be saved has immediately re-appeared. Assume login
    204       // failure and abort this save, by clearing provisional_save_manager_.
    205       // Don't delete the login managers since the user may try again
    206       // and we want to be able to save in that case.
    207       provisional_save_manager_->SubmitFailed();
    208       ClearProvisionalSave();
    209       break;
    210     }
    211   }
    212 }
    213 
    214 void PasswordManager::Autofill(
    215     const PasswordForm& form_for_autofill,
    216     const PasswordFormMap& best_matches,
    217     const PasswordForm* const preferred_match,
    218     bool wait_for_username) const {
    219   DCHECK(preferred_match);
    220   switch (form_for_autofill.scheme) {
    221     case PasswordForm::SCHEME_HTML: {
    222       // Note the check above is required because the observer_ for a non-HTML
    223       // schemed password form may have been freed, so we need to distinguish.
    224       webkit_glue::PasswordFormFillData fill_data;
    225       webkit_glue::PasswordFormDomManager::InitFillData(form_for_autofill,
    226                                                         best_matches,
    227                                                         preferred_match,
    228                                                         wait_for_username,
    229                                                         &fill_data);
    230       delegate_->FillPasswordForm(fill_data);
    231       return;
    232     }
    233     default:
    234       if (observer_) {
    235         observer_->OnAutofillDataAvailable(
    236             UTF16ToWideHack(preferred_match->username_value),
    237             UTF16ToWideHack(preferred_match->password_value));
    238       }
    239   }
    240 }
    241