• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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