OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/field_trial.h" | 8 #include "base/metrics/field_trial.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
11 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
13 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
14 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 14 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
15 #include "chrome/browser/password_manager/password_form_manager.h" | 15 #include "chrome/browser/password_manager/password_form_manager.h" |
16 #include "chrome/browser/password_manager/password_manager_delegate.h" | 16 #include "chrome/browser/password_manager/password_manager_delegate.h" |
17 #include "chrome/browser/password_manager/password_manager_util.h" | |
17 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
18 #include "chrome/common/chrome_switches.h" | 19 #include "chrome/common/chrome_switches.h" |
19 #include "chrome/common/chrome_version_info.h" | 20 #include "chrome/common/chrome_version_info.h" |
20 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
21 #include "components/autofill/core/common/autofill_messages.h" | 22 #include "components/autofill/core/common/autofill_messages.h" |
22 #include "components/user_prefs/pref_registry_syncable.h" | 23 #include "components/user_prefs/pref_registry_syncable.h" |
23 #include "content/public/browser/navigation_details.h" | 24 #include "content/public/browser/navigation_details.h" |
24 #include "content/public/browser/user_metrics.h" | 25 #include "content/public/browser/user_metrics.h" |
25 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
26 #include "content/public/common/frame_navigate_params.h" | 27 #include "content/public/common/frame_navigate_params.h" |
(...skipping 21 matching lines...) Expand all Loading... | |
48 void ReportMetrics(bool password_manager_enabled) { | 49 void ReportMetrics(bool password_manager_enabled) { |
49 static base::PlatformThreadId initial_thread_id = | 50 static base::PlatformThreadId initial_thread_id = |
50 base::PlatformThread::CurrentId(); | 51 base::PlatformThread::CurrentId(); |
51 DCHECK(initial_thread_id == base::PlatformThread::CurrentId()); | 52 DCHECK(initial_thread_id == base::PlatformThread::CurrentId()); |
52 | 53 |
53 static bool ran_once = false; | 54 static bool ran_once = false; |
54 if (ran_once) | 55 if (ran_once) |
55 return; | 56 return; |
56 ran_once = true; | 57 ran_once = true; |
57 | 58 |
58 // TODO(isherman): This does not actually measure a user action. It should be | |
59 // a boolean histogram. | |
60 if (password_manager_enabled) | 59 if (password_manager_enabled) |
61 content::RecordAction(UserMetricsAction("PasswordManager_Enabled")); | 60 UMA_HISTOGRAM_BOOLEAN("PasswordManager.PasswordManager_Enabled", true); |
62 else | 61 else |
63 content::RecordAction(UserMetricsAction("PasswordManager_Disabled")); | 62 UMA_HISTOGRAM_BOOLEAN("PasswordManager.PasswordManager_Enabled", false); |
Garrett Casto
2013/08/28 01:09:17
I would think that the name should be "PasswordMan
| |
64 } | 63 } |
65 | 64 |
66 } // namespace | 65 } // namespace |
67 | 66 |
68 // static | 67 // static |
69 void PasswordManager::RegisterProfilePrefs( | 68 void PasswordManager::RegisterProfilePrefs( |
70 user_prefs::PrefRegistrySyncable* registry) { | 69 user_prefs::PrefRegistrySyncable* registry) { |
71 registry->RegisterBooleanPref( | 70 registry->RegisterBooleanPref( |
72 prefs::kPasswordManagerEnabled, | 71 prefs::kPasswordManagerEnabled, |
73 true, | 72 true, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
132 // TODO(gcasto): Add UMA stats to track this. | 131 // TODO(gcasto): Add UMA stats to track this. |
133 } | 132 } |
134 | 133 |
135 bool PasswordManager::IsSavingEnabled() const { | 134 bool PasswordManager::IsSavingEnabled() const { |
136 return *password_manager_enabled_ && | 135 return *password_manager_enabled_ && |
137 !delegate_->GetProfile()->IsOffTheRecord(); | 136 !delegate_->GetProfile()->IsOffTheRecord(); |
138 } | 137 } |
139 | 138 |
140 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { | 139 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { |
141 if (!IsSavingEnabled()) { | 140 if (!IsSavingEnabled()) { |
142 RecordFailure(SAVING_DISABLED); | 141 RecordFailure(SAVING_DISABLED, form.origin.host()); |
143 return; | 142 return; |
144 } | 143 } |
145 | 144 |
146 // No password to save? Then don't. | 145 // No password to save? Then don't. |
147 if (form.password_value.empty()) { | 146 if (form.password_value.empty()) { |
148 RecordFailure(EMPTY_PASSWORD); | 147 RecordFailure(EMPTY_PASSWORD, form.origin.host()); |
149 return; | 148 return; |
150 } | 149 } |
151 | 150 |
152 scoped_ptr<PasswordFormManager> manager; | 151 scoped_ptr<PasswordFormManager> manager; |
153 ScopedVector<PasswordFormManager>::iterator matched_manager_it = | 152 ScopedVector<PasswordFormManager>::iterator matched_manager_it = |
154 pending_login_managers_.end(); | 153 pending_login_managers_.end(); |
155 for (ScopedVector<PasswordFormManager>::iterator iter = | 154 for (ScopedVector<PasswordFormManager>::iterator iter = |
156 pending_login_managers_.begin(); | 155 pending_login_managers_.begin(); |
157 iter != pending_login_managers_.end(); ++iter) { | 156 iter != pending_login_managers_.end(); ++iter) { |
158 // If we find a manager that exactly matches the submitted form including | 157 // If we find a manager that exactly matches the submitted form including |
(...skipping 12 matching lines...) Expand all Loading... | |
171 } | 170 } |
172 // If we didn't find a manager, this means a form was submitted without | 171 // If we didn't find a manager, this means a form was submitted without |
173 // first loading the page containing the form. Don't offer to save | 172 // first loading the page containing the form. Don't offer to save |
174 // passwords in this case. | 173 // passwords in this case. |
175 if (matched_manager_it != pending_login_managers_.end()) { | 174 if (matched_manager_it != pending_login_managers_.end()) { |
176 // Transfer ownership of the manager from |pending_login_managers_| to | 175 // Transfer ownership of the manager from |pending_login_managers_| to |
177 // |manager|. | 176 // |manager|. |
178 manager.reset(*matched_manager_it); | 177 manager.reset(*matched_manager_it); |
179 pending_login_managers_.weak_erase(matched_manager_it); | 178 pending_login_managers_.weak_erase(matched_manager_it); |
180 } else { | 179 } else { |
181 RecordFailure(NO_MATCHING_FORM); | 180 RecordFailure(NO_MATCHING_FORM, form.origin.host()); |
182 return; | 181 return; |
183 } | 182 } |
184 | 183 |
185 // If we found a manager but it didn't finish matching yet, the user has | 184 // If we found a manager but it didn't finish matching yet, the user has |
186 // tried to submit credentials before we had time to even find matching | 185 // tried to submit credentials before we had time to even find matching |
187 // results for the given form and autofill. If this is the case, we just | 186 // results for the given form and autofill. If this is the case, we just |
188 // give up. | 187 // give up. |
189 if (!manager->HasCompletedMatching()) { | 188 if (!manager->HasCompletedMatching()) { |
190 RecordFailure(MATCHING_NOT_COMPLETE); | 189 RecordFailure(MATCHING_NOT_COMPLETE, form.origin.host()); |
191 return; | 190 return; |
192 } | 191 } |
193 | 192 |
194 // Also get out of here if the user told us to 'never remember' passwords for | 193 // Also get out of here if the user told us to 'never remember' passwords for |
195 // this form. | 194 // this form. |
196 if (manager->IsBlacklisted()) { | 195 if (manager->IsBlacklisted()) { |
197 RecordFailure(FORM_BLACKLISTED); | 196 RecordFailure(FORM_BLACKLISTED, form.origin.host()); |
198 return; | 197 return; |
199 } | 198 } |
200 | 199 |
201 // Bail if we're missing any of the necessary form components. | 200 // Bail if we're missing any of the necessary form components. |
202 if (!manager->HasValidPasswordForm()) { | 201 if (!manager->HasValidPasswordForm()) { |
203 RecordFailure(INVALID_FORM); | 202 RecordFailure(INVALID_FORM, form.origin.host()); |
204 return; | 203 return; |
205 } | 204 } |
206 | 205 |
207 // Always save generated passwords, as the user expresses explicit intent for | 206 // Always save generated passwords, as the user expresses explicit intent for |
208 // Chrome to manage such passwords. For other passwords, respect the | 207 // Chrome to manage such passwords. For other passwords, respect the |
209 // autocomplete attribute. | 208 // autocomplete attribute. |
210 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) { | 209 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) { |
211 RecordFailure(AUTOCOMPLETE_OFF); | 210 RecordFailure(AUTOCOMPLETE_OFF, form.origin.host()); |
212 return; | 211 return; |
213 } | 212 } |
214 | 213 |
215 PasswordForm provisionally_saved_form(form); | 214 PasswordForm provisionally_saved_form(form); |
216 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && | 215 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && |
217 !delegate_->DidLastPageLoadEncounterSSLErrors(); | 216 !delegate_->DidLastPageLoadEncounterSSLErrors(); |
218 provisionally_saved_form.preferred = true; | 217 provisionally_saved_form.preferred = true; |
219 PasswordFormManager::OtherPossibleUsernamesAction action = | 218 PasswordFormManager::OtherPossibleUsernamesAction action = |
220 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; | 219 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; |
221 if (OtherPossibleUsernamesEnabled()) | 220 if (OtherPossibleUsernamesEnabled()) |
222 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; | 221 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; |
223 manager->ProvisionallySave(provisionally_saved_form, action); | 222 manager->ProvisionallySave(provisionally_saved_form, action); |
224 provisional_save_manager_.swap(manager); | 223 provisional_save_manager_.swap(manager); |
225 } | 224 } |
226 | 225 |
227 void PasswordManager::RecordFailure(ProvisionalSaveFailure failure) { | 226 void PasswordManager::RecordFailure(ProvisionalSaveFailure failure, |
227 const std::string& url_host) { | |
228 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ProvisionalSaveFailure", | 228 UMA_HISTOGRAM_ENUMERATION("PasswordManager.ProvisionalSaveFailure", |
229 failure, MAX_FAILURE_VALUE); | 229 failure, MAX_FAILURE_VALUE); |
230 | |
231 std::string domain_name; | |
232 if (PasswordManagerUtil::IsDomainNameMonitored(url_host, domain_name)) { | |
233 domain_name.insert(0, "_"); | |
234 UMA_HISTOGRAM_ENUMERATION( | |
Garrett Casto
2013/08/28 01:09:17
Unfortunately this doesn't work. If you check out
jdomingos
2013/08/28 15:23:20
Normally I think it should work because I added a
Garrett Casto
2013/08/28 19:15:19
I think you pasted the wrong link.
Do you mean yo
| |
235 "PasswordManager.ProvisionalSaveFailure" + domain_name, failure, | |
236 MAX_FAILURE_VALUE); | |
237 } | |
230 } | 238 } |
231 | 239 |
232 void PasswordManager::AddSubmissionCallback( | 240 void PasswordManager::AddSubmissionCallback( |
233 const PasswordSubmittedCallback& callback) { | 241 const PasswordSubmittedCallback& callback) { |
234 submission_callbacks_.push_back(callback); | 242 submission_callbacks_.push_back(callback); |
235 } | 243 } |
236 | 244 |
237 void PasswordManager::AddObserver(LoginModelObserver* observer) { | 245 void PasswordManager::AddObserver(LoginModelObserver* observer) { |
238 observers_.AddObserver(observer); | 246 observers_.AddObserver(observer); |
239 } | 247 } |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
294 web_contents(), | 302 web_contents(), |
295 *iter, | 303 *iter, |
296 ssl_valid); | 304 ssl_valid); |
297 pending_login_managers_.push_back(manager); | 305 pending_login_managers_.push_back(manager); |
298 manager->FetchMatchingLoginsFromPasswordStore(); | 306 manager->FetchMatchingLoginsFromPasswordStore(); |
299 } | 307 } |
300 } | 308 } |
301 | 309 |
302 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { | 310 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { |
303 return provisional_save_manager_->IsNewLogin() && | 311 return provisional_save_manager_->IsNewLogin() && |
304 !provisional_save_manager_->HasGeneratedPassword() && | 312 !provisional_save_manager_->HasGeneratedPassword() && |
305 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); | 313 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); |
306 } | 314 } |
307 | 315 |
308 void PasswordManager::OnPasswordFormsRendered( | 316 void PasswordManager::OnPasswordFormsRendered( |
309 const std::vector<PasswordForm>& visible_forms) { | 317 const std::vector<PasswordForm>& visible_forms) { |
310 if (!provisional_save_manager_.get()) | 318 if (!provisional_save_manager_.get()) |
311 return; | 319 return; |
312 | 320 |
313 DCHECK(IsSavingEnabled()); | 321 DCHECK(IsSavingEnabled()); |
314 | 322 |
315 // First, check for a failed login attempt. | 323 // First, check for a failed login attempt. |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
420 return; | 428 return; |
421 } | 429 } |
422 default: | 430 default: |
423 FOR_EACH_OBSERVER( | 431 FOR_EACH_OBSERVER( |
424 LoginModelObserver, | 432 LoginModelObserver, |
425 observers_, | 433 observers_, |
426 OnAutofillDataAvailable(preferred_match.username_value, | 434 OnAutofillDataAvailable(preferred_match.username_value, |
427 preferred_match.password_value)); | 435 preferred_match.password_value)); |
428 } | 436 } |
429 } | 437 } |
OLD | NEW |