Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(85)

Side by Side Diff: chrome/browser/password_manager/password_manager.cc

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

Powered by Google App Engine
This is Rietveld 408576698