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

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: Created 7 years, 4 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"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 ran_once = true; 55 ran_once = true;
56 56
57 // TODO(isherman): This does not actually measure a user action. It should be 57 // TODO(isherman): This does not actually measure a user action. It should be
58 // a boolean histogram. 58 // a boolean histogram.
59 if (password_manager_enabled) 59 if (password_manager_enabled)
60 content::RecordAction(UserMetricsAction("PasswordManager_Enabled")); 60 content::RecordAction(UserMetricsAction("PasswordManager_Enabled"));
61 else 61 else
62 content::RecordAction(UserMetricsAction("PasswordManager_Disabled")); 62 content::RecordAction(UserMetricsAction("PasswordManager_Disabled"));
63 } 63 }
64 64
65 void ReportSavePasswordInfoBarFailure(
66 const enum PasswordManager::PotentialInfoBarErrorReasons reason_id,
67 const GURL& url) {
68 std::string domain_name = url.host();
69
70 if (domain_name.size())
71 domain_name.insert(0, "_");
vabr (Chromium) 2013/08/14 14:39:58 We may not append any domain name, only one of a c
Garrett Casto 2013/08/14 23:02:47 I didn't even realize you could send any identifia
vabr (Chromium) 2013/08/16 09:02:14 Yeah, we have to be careful. Logging the domain fo
72
73 UMA_HISTOGRAM_BOOLEAN("PasswordManager.InfobarDisplayed" + domain_name,
Garrett Casto 2013/08/14 23:02:47 I'm not sure if this is necessary as if this is ne
vabr (Chromium) 2013/08/16 09:02:14 That's a good point. Jordy, when you are back, le
74 false);
75 UMA_HISTOGRAM_ENUMERATION(
76 "PasswordManager.PotentialInfoBarErrorReasons" + domain_name, reason_id,
77 PasswordManager::NUM_ERROR_TYPES);
78 }
79
65 } // namespace 80 } // namespace
66 81
67 // static 82 // static
68 void PasswordManager::RegisterProfilePrefs( 83 void PasswordManager::RegisterProfilePrefs(
69 user_prefs::PrefRegistrySyncable* registry) { 84 user_prefs::PrefRegistrySyncable* registry) {
70 registry->RegisterBooleanPref( 85 registry->RegisterBooleanPref(
71 prefs::kPasswordManagerEnabled, 86 prefs::kPasswordManagerEnabled,
72 true, 87 true,
73 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 88 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
74 registry->RegisterBooleanPref( 89 registry->RegisterBooleanPref(
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 manager->SetHasGeneratedPassword(); 145 manager->SetHasGeneratedPassword();
131 // TODO(gcasto): Add UMA stats to track this. 146 // TODO(gcasto): Add UMA stats to track this.
132 } 147 }
133 148
134 bool PasswordManager::IsSavingEnabled() const { 149 bool PasswordManager::IsSavingEnabled() const {
135 return *password_manager_enabled_ && 150 return *password_manager_enabled_ &&
136 !delegate_->GetProfile()->IsOffTheRecord(); 151 !delegate_->GetProfile()->IsOffTheRecord();
137 } 152 }
138 153
139 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) { 154 void PasswordManager::ProvisionallySavePassword(const PasswordForm& form) {
140 if (!IsSavingEnabled()) 155 if (!IsSavingEnabled()) {
Garrett Casto 2013/08/14 23:02:47 I actually just submitted a CL (https://codereview
156 ReportSavePasswordInfoBarFailure(SAVE_PASSWORD_DISABLE, form.origin);
141 return; 157 return;
158 }
142 159
143 // No password to save? Then don't. 160 // No password to save? Then don't.
144 if (form.password_value.empty()) 161 if (form.password_value.empty()) {
162 ReportSavePasswordInfoBarFailure(EMPTY_PASSWORD, form.origin);
145 return; 163 return;
164 }
146 165
147 scoped_ptr<PasswordFormManager> manager; 166 scoped_ptr<PasswordFormManager> manager;
148 ScopedVector<PasswordFormManager>::iterator matched_manager_it = 167 ScopedVector<PasswordFormManager>::iterator matched_manager_it =
149 pending_login_managers_.end(); 168 pending_login_managers_.end();
150 for (ScopedVector<PasswordFormManager>::iterator iter = 169 for (ScopedVector<PasswordFormManager>::iterator iter =
151 pending_login_managers_.begin(); 170 pending_login_managers_.begin();
152 iter != pending_login_managers_.end(); ++iter) { 171 iter != pending_login_managers_.end(); ++iter) {
153 // If we find a manager that exactly matches the submitted form including 172 // If we find a manager that exactly matches the submitted form including
154 // the action URL, exit the loop. 173 // the action URL, exit the loop.
155 if ((*iter)->DoesManage( 174 if ((*iter)->DoesManage(
(...skipping 10 matching lines...) Expand all
166 } 185 }
167 // If we didn't find a manager, this means a form was submitted without 186 // If we didn't find a manager, this means a form was submitted without
168 // first loading the page containing the form. Don't offer to save 187 // first loading the page containing the form. Don't offer to save
169 // passwords in this case. 188 // passwords in this case.
170 if (matched_manager_it != pending_login_managers_.end()) { 189 if (matched_manager_it != pending_login_managers_.end()) {
171 // Transfer ownership of the manager from |pending_login_managers_| to 190 // Transfer ownership of the manager from |pending_login_managers_| to
172 // |manager|. 191 // |manager|.
173 manager.reset(*matched_manager_it); 192 manager.reset(*matched_manager_it);
174 pending_login_managers_.weak_erase(matched_manager_it); 193 pending_login_managers_.weak_erase(matched_manager_it);
175 } else { 194 } else {
195 ReportSavePasswordInfoBarFailure(FIRST_PAGE_NOT_LOADED, form.origin);
176 return; 196 return;
177 } 197 }
178 198
179 // If we found a manager but it didn't finish matching yet, the user has 199 // If we found a manager but it didn't finish matching yet, the user has
180 // tried to submit credentials before we had time to even find matching 200 // tried to submit credentials before we had time to even find matching
181 // results for the given form and autofill. If this is the case, we just 201 // results for the given form and autofill. If this is the case, we just
182 // give up. 202 // give up.
183 if (!manager->HasCompletedMatching()) 203 if (!manager->HasCompletedMatching()) {
204 ReportSavePasswordInfoBarFailure(MATCHING_ONGOING, form.origin);
184 return; 205 return;
206 }
185 207
186 // Also get out of here if the user told us to 'never remember' passwords for 208 // Also get out of here if the user told us to 'never remember' passwords for
187 // this form. 209 // this form.
188 if (manager->IsBlacklisted()) 210 if (manager->IsBlacklisted()) {
211 ReportSavePasswordInfoBarFailure(NEVER_REMEMBER, form.origin);
189 return; 212 return;
213 }
190 214
191 // Bail if we're missing any of the necessary form components. 215 // Bail if we're missing any of the necessary form components.
192 if (!manager->HasValidPasswordForm()) 216 if (!manager->HasValidPasswordForm()) {
217 ReportSavePasswordInfoBarFailure(INVALID_FORM, form.origin);
193 return; 218 return;
219 }
194 220
195 // Always save generated passwords, as the user expresses explicit intent for 221 // Always save generated passwords, as the user expresses explicit intent for
196 // Chrome to manage such passwords. For other passwords, respect the 222 // Chrome to manage such passwords. For other passwords, respect the
197 // autocomplete attribute. 223 // autocomplete attribute.
198 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) 224 if (!manager->HasGeneratedPassword() && !form.password_autocomplete_set) {
225 ReportSavePasswordInfoBarFailure(PASSWORD_GENERATED_OR_AUTOCOMPLETED,
226 form.origin);
199 return; 227 return;
228 }
200 229
201 PasswordForm provisionally_saved_form(form); 230 PasswordForm provisionally_saved_form(form);
202 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() && 231 provisionally_saved_form.ssl_valid = form.origin.SchemeIsSecure() &&
203 !delegate_->DidLastPageLoadEncounterSSLErrors(); 232 !delegate_->DidLastPageLoadEncounterSSLErrors();
204 provisionally_saved_form.preferred = true; 233 provisionally_saved_form.preferred = true;
205 PasswordFormManager::OtherPossibleUsernamesAction action = 234 PasswordFormManager::OtherPossibleUsernamesAction action =
206 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES; 235 PasswordFormManager::IGNORE_OTHER_POSSIBLE_USERNAMES;
207 if (OtherPossibleUsernamesEnabled()) 236 if (OtherPossibleUsernamesEnabled())
208 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES; 237 action = PasswordFormManager::ALLOW_OTHER_POSSIBLE_USERNAMES;
209 manager->ProvisionallySave(provisionally_saved_form, action); 238 manager->ProvisionallySave(provisionally_saved_form, action);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
263 new PasswordFormManager(delegate_->GetProfile(), 292 new PasswordFormManager(delegate_->GetProfile(),
264 this, 293 this,
265 web_contents(), 294 web_contents(),
266 *iter, 295 *iter,
267 ssl_valid); 296 ssl_valid);
268 pending_login_managers_.push_back(manager); 297 pending_login_managers_.push_back(manager);
269 manager->FetchMatchingLoginsFromPasswordStore(); 298 manager->FetchMatchingLoginsFromPasswordStore();
270 } 299 }
271 } 300 }
272 301
273 bool PasswordManager::ShouldShowSavePasswordInfoBar() const { 302 bool PasswordManager::ShouldShowSavePasswordInfoBar() const {
Garrett Casto 2013/08/14 23:02:47 I don't think that this function does what you thi
274 return provisional_save_manager_->IsNewLogin() && 303
275 !provisional_save_manager_->HasGeneratedPassword() && 304 // All functions are tested on by one in order to send the appropriate
vabr (Chromium) 2013/08/14 14:39:58 on by one -> one by one
276 !provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch(); 305 // UMA signal with the ReportSavePasswordInfoBarFailure function.
306 if (!provisional_save_manager_->IsNewLogin()) {
307 ReportSavePasswordInfoBarFailure(LOGIN_ALREADY_KNEW,
308 GURL(provisional_save_manager_->realm()));
309 return false;
310 }
311 if (provisional_save_manager_->HasGeneratedPassword()) {
312 ReportSavePasswordInfoBarFailure(PASSWORD_GENERATED,
313 GURL(provisional_save_manager_->realm()));
314 return false;
315 }
316 if (provisional_save_manager_->IsPendingCredentialsPublicSuffixMatch()) {
317 ReportSavePasswordInfoBarFailure(ORIGIN_MATCHING_OF_PUBLIC_SUFFIX,
318 GURL(provisional_save_manager_->realm()));
319 return false;
320 }
321 return true;
277 } 322 }
278 323
279 void PasswordManager::OnPasswordFormsRendered( 324 void PasswordManager::OnPasswordFormsRendered(
280 const std::vector<PasswordForm>& visible_forms) { 325 const std::vector<PasswordForm>& visible_forms) {
281 if (!provisional_save_manager_.get()) 326 if (!provisional_save_manager_.get()) {
327 ReportSavePasswordInfoBarFailure(CANNOT_GET_THE_PROVIOSIONAL_PASSWORD,
328 visible_forms[0].origin);
Garrett Casto 2013/08/14 23:02:47 Not sure if any of the reporting in this function
282 return; 329 return;
330 }
283 331
284 DCHECK(IsSavingEnabled()); 332 DCHECK(IsSavingEnabled());
285 333
286 // First, check for a failed login attempt. 334 // First, check for a failed login attempt.
287 for (std::vector<PasswordForm>::const_iterator iter = visible_forms.begin(); 335 for (std::vector<PasswordForm>::const_iterator iter = visible_forms.begin();
288 iter != visible_forms.end(); ++iter) { 336 iter != visible_forms.end(); ++iter) {
289 if (provisional_save_manager_->DoesManage( 337 if (provisional_save_manager_->DoesManage(
290 *iter, PasswordFormManager::ACTION_MATCH_REQUIRED)) { 338 *iter, PasswordFormManager::ACTION_MATCH_REQUIRED)) {
291 // The form trying to be saved has immediately re-appeared. Assume login 339 // The form trying to be saved has immediately re-appeared. Assume login
292 // failure and abort this save, by clearing provisional_save_manager_. 340 // failure and abort this save, by clearing provisional_save_manager_.
341 ReportSavePasswordInfoBarFailure(
342 FORM_REAPPEARED, GURL(provisional_save_manager_->realm()));
Garrett Casto 2013/08/14 23:02:47 We already keep track of this stat in the provisio
293 provisional_save_manager_->SubmitFailed(); 343 provisional_save_manager_->SubmitFailed();
294 provisional_save_manager_.reset(); 344 provisional_save_manager_.reset();
295 return; 345 return;
296 } 346 }
297 } 347 }
298 348
299 if (!provisional_save_manager_->HasValidPasswordForm()) { 349 if (!provisional_save_manager_->HasValidPasswordForm()) {
300 // Form is not completely valid - we do not support it. 350 // Form is not completely valid - we do not support it.
301 NOTREACHED(); 351 NOTREACHED();
352 ReportSavePasswordInfoBarFailure(INVALID_FORM,
353 GURL(provisional_save_manager_->realm()));
302 provisional_save_manager_.reset(); 354 provisional_save_manager_.reset();
303 return; 355 return;
304 } 356 }
305 357
306 // Looks like a successful login attempt. Either show an infobar or 358 // Looks like a successful login attempt. Either show an infobar or
307 // automatically save the login data. We prompt when the user hasn't already 359 // automatically save the login data. We prompt when the user hasn't already
308 // given consent, either through previously accepting the infobar or by having 360 // given consent, either through previously accepting the infobar or by having
309 // the browser generate the password. 361 // the browser generate the password.
310 provisional_save_manager_->SubmitPassed(); 362 provisional_save_manager_->SubmitPassed();
311 if (provisional_save_manager_->HasGeneratedPassword()) 363 if (provisional_save_manager_->HasGeneratedPassword())
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 return; 438 return;
387 } 439 }
388 default: 440 default:
389 FOR_EACH_OBSERVER( 441 FOR_EACH_OBSERVER(
390 LoginModelObserver, 442 LoginModelObserver,
391 observers_, 443 observers_,
392 OnAutofillDataAvailable(preferred_match.username_value, 444 OnAutofillDataAvailable(preferred_match.username_value,
393 preferred_match.password_value)); 445 preferred_match.password_value));
394 } 446 }
395 } 447 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698