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 #ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_MANAGER_H_
      6 #define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_MANAGER_H_
      7 #pragma once
      8 
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "build/build_config.h"
     13 
     14 #include "base/stl_util-inl.h"
     15 #include "chrome/browser/password_manager/password_store_consumer.h"
     16 #include "webkit/glue/password_form.h"
     17 
     18 class PasswordManager;
     19 class PasswordStore;
     20 class Profile;
     21 
     22 // Per-password-form-{on-page, dialog} class responsible for interactions
     23 // between a given form, the per-tab PasswordManager, and the PasswordStore.
     24 class PasswordFormManager : public PasswordStoreConsumer {
     25  public:
     26   // profile contains the link to the PasswordStore and whether we're off
     27   //           the record
     28   // password_manager owns this object
     29   // form_on_page is the form that may be submitted and could need login data.
     30   // ssl_valid represents the security of the page containing observed_form,
     31   //           used to filter login results from database.
     32   PasswordFormManager(Profile* profile,
     33                       PasswordManager* password_manager,
     34                       const webkit_glue::PasswordForm& observed_form,
     35                       bool ssl_valid);
     36   virtual ~PasswordFormManager();
     37 
     38   // Compare basic data of observed_form_ with argument.
     39   bool DoesManage(const webkit_glue::PasswordForm& form) const;
     40 
     41   // Retrieves potential matching logins from the database.
     42   void FetchMatchingLoginsFromPasswordStore();
     43 
     44   // Simple state-check to verify whether this object as received a callback
     45   // from the PasswordStore and completed its matching phase. Note that the
     46   // callback in question occurs on the same (and only) main thread from which
     47   // instances of this class are ever used, but it is required since it is
     48   // conceivable that a user (or ui test) could attempt to submit a login
     49   // prompt before the callback has occured, which would InvokeLater a call to
     50   // PasswordManager::ProvisionallySave, which would interact with this object
     51   // before the db has had time to answer with matching password entries.
     52   // This is intended to be a one-time check; if the return value is false the
     53   // expectation is caller will give up. This clearly won't work if you put it
     54   // in a loop and wait for matching to complete; you're (supposed to be) on
     55   // the same thread!
     56   bool HasCompletedMatching();
     57 
     58   // Determines if the user opted to 'never remember' passwords for this form.
     59   bool IsBlacklisted();
     60 
     61   // Used by PasswordManager to determine whether or not to display
     62   // a SavePasswordBar when given the green light to save the PasswordForm
     63   // managed by this.
     64   bool IsNewLogin();
     65 
     66   // Checks if the form is a valid password form. Forms which lack either
     67   // login or password field are not considered valid.
     68   bool HasValidPasswordForm();
     69 
     70   // Determines if we need to autofill given the results of the query.
     71   void OnRequestDone(
     72       int handle, const std::vector<webkit_glue::PasswordForm*>& result);
     73 
     74   // PasswordStoreConsumer implementation.
     75   virtual void OnPasswordStoreRequestDone(
     76       CancelableRequestProvider::Handle handle,
     77       const std::vector<webkit_glue::PasswordForm*>& result);
     78 
     79   // A user opted to 'never remember' passwords for this form.
     80   // Blacklist it so that from now on when it is seen we ignore it.
     81   void PermanentlyBlacklist();
     82 
     83   // If the user has submitted observed_form_, provisionally hold on to
     84   // the submitted credentials until we are told by PasswordManager whether
     85   // or not the login was successful.
     86   void ProvisionallySave(const webkit_glue::PasswordForm& credentials);
     87 
     88   // Handles save-as-new or update of the form managed by this manager.
     89   // Note the basic data of updated_credentials must match that of
     90   // observed_form_ (e.g DoesManage(pending_credentials_) == true).
     91   void Save();
     92 
     93   // Call these if/when we know the form submission worked or failed.
     94   // These routines are used to update internal statistics ("ActionsTaken").
     95   void SubmitPassed();
     96   void SubmitFailed();
     97 
     98  private:
     99   friend class PasswordFormManagerTest;
    100 
    101   // ManagerAction - What does the manager do with this form? Either it
    102   // fills it, or it doesn't. If it doesn't fill it, that's either
    103   // because it has no match, or it is blacklisted, or it is disabled
    104   // via the AUTOCOMPLETE=off attribute. Note that if we don't have
    105   // an exact match, we still provide candidates that the user may
    106   // end up choosing.
    107   enum ManagerAction {
    108     kManagerActionNone = 0,
    109     kManagerActionAutofilled,
    110     kManagerActionBlacklisted,
    111     kManagerActionDisabled,
    112     kManagerActionMax
    113   };
    114 
    115   // UserAction - What does the user do with this form? If he or she
    116   // does nothing (either by accepting what the password manager did, or
    117   // by simply (not typing anything at all), you get None. If there were
    118   // multiple choices and the user selects one other than the default,
    119   // you get Choose, and if the user types in a new value, you get
    120   // Override.
    121   enum UserAction {
    122     kUserActionNone = 0,
    123     kUserActionChoose,
    124     kUserActionOverride,
    125     kUserActionMax
    126   };
    127 
    128   // Result - What happens to the form?
    129   enum SubmitResult {
    130     kSubmitResultNotSubmitted = 0,
    131     kSubmitResultFailed,
    132     kSubmitResultPassed,
    133     kSubmitResultMax
    134   };
    135 
    136   // The maximum number of combinations of the three preceding enums.
    137   // This is used when recording the actions taken by the form in UMA.
    138   static const int kMaxNumActionsTaken = kManagerActionMax * kUserActionMax *
    139                                          kSubmitResultMax;
    140 
    141   // Helper for OnPasswordStoreRequestDone to determine whether or not
    142   // the given result form is worth scoring.
    143   bool IgnoreResult(const webkit_glue::PasswordForm& form) const;
    144 
    145   // Helper for Save in the case that best_matches.size() == 0, meaning
    146   // we have no prior record of this form/username/password and the user
    147   // has opted to 'Save Password'. If |reset_preferred_login| is set,
    148   // the previously preferred login from |best_matches_| will be reset.
    149   void SaveAsNewLogin(bool reset_preferred_login);
    150 
    151   // Helper for OnPasswordStoreRequestDone to score an individual result
    152   // against the observed_form_.
    153   int ScoreResult(const webkit_glue::PasswordForm& form) const;
    154 
    155   // Helper for Save in the case that best_matches.size() > 0, meaning
    156   // we have at least one match for this form/username/password. This
    157   // Updates the form managed by this object, as well as any matching forms
    158   // that now need to have preferred bit changed, since updated_credentials
    159   // is now implicitly 'preferred'.
    160   void UpdateLogin();
    161 
    162   // Update all login matches to reflect new preferred state - preferred flag
    163   // will be reset on all matched logins that different than the current
    164   // |pending_credentials_|.
    165   void UpdatePreferredLoginState(PasswordStore* password_store);
    166 
    167   // Converts the "ActionsTaken" fields into an int so they can be logged to
    168   // UMA.
    169   int GetActionsTaken();
    170 
    171   // Set of PasswordForms from the DB that best match the form
    172   // being managed by this. Use a map instead of vector, because we most
    173   // frequently require lookups by username value in IsNewLogin.
    174   webkit_glue::PasswordFormMap best_matches_;
    175 
    176   // Cleans up when best_matches_ goes out of scope.
    177   STLValueDeleter<webkit_glue::PasswordFormMap> best_matches_deleter_;
    178 
    179   // The PasswordForm from the page or dialog managed by this.
    180   webkit_glue::PasswordForm observed_form_;
    181 
    182   // The origin url path of observed_form_ tokenized, for convenience when
    183   // scoring.
    184   std::vector<std::string> form_path_tokens_;
    185 
    186   // Stores updated credentials when the form was submitted but success is
    187   // still unknown.
    188   webkit_glue::PasswordForm pending_credentials_;
    189 
    190   // Whether pending_credentials_ stores a new login or is an update
    191   // to an existing one.
    192   bool is_new_login_;
    193 
    194   // PasswordManager owning this.
    195   const PasswordManager* const password_manager_;
    196 
    197   // Handle to any pending PasswordStore::GetLogins query.
    198   CancelableRequestProvider::Handle pending_login_query_;
    199 
    200   // Convenience pointer to entry in best_matches_ that is marked
    201   // as preferred. This is only allowed to be null if there are no best matches
    202   // at all, since there will always be one preferred login when there are
    203   // multiple matches (when first saved, a login is marked preferred).
    204   const webkit_glue::PasswordForm* preferred_match_;
    205 
    206   typedef enum {
    207     PRE_MATCHING_PHASE,      // Have not yet invoked a GetLogins query to find
    208                              // matching login information from password store.
    209     MATCHING_PHASE,          // We've made a GetLogins request, but
    210                              // haven't received or finished processing result.
    211     POST_MATCHING_PHASE      // We've queried the DB and processed matching
    212                              // login results.
    213   } PasswordFormManagerState;
    214 
    215   // State of matching process, used to verify that we don't call methods
    216   // assuming we've already processed the request for matching logins,
    217   // when we actually haven't.
    218   PasswordFormManagerState state_;
    219 
    220   // The profile from which we get the PasswordStore.
    221   Profile* profile_;
    222 
    223   // These three fields record the "ActionsTaken" by the browser and
    224   // the user with this form, and the result. They are combined and
    225   // recorded in UMA when the manager is destroyed.
    226   ManagerAction manager_action_;
    227   UserAction user_action_;
    228   SubmitResult submit_result_;
    229 
    230   DISALLOW_COPY_AND_ASSIGN(PasswordFormManager);
    231 };
    232 #endif  // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_MANAGER_H_
    233