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

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

Issue 23140005: Added of new UMA signals in order to be able to discover early if the "save password" feature gets … (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Additional minor changes Created 7 years, 3 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
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698