OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/password_manager/core/browser/login_database.h" | 5 #include "components/password_manager/core/browser/login_database.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <limits> | 8 #include <limits> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/files/file_path.h" | 11 #include "base/files/file_path.h" |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
14 #include "base/pickle.h" | 14 #include "base/pickle.h" |
15 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
16 #include "base/strings/stringprintf.h" | |
16 #include "base/time/time.h" | 17 #include "base/time/time.h" |
17 #include "components/autofill/core/common/password_form.h" | 18 #include "components/autofill/core/common/password_form.h" |
19 #include "components/password_manager/core/browser/password_manager_client.h" | |
18 #include "google_apis/gaia/gaia_auth_util.h" | 20 #include "google_apis/gaia/gaia_auth_util.h" |
19 #include "google_apis/gaia/gaia_urls.h" | 21 #include "google_apis/gaia/gaia_urls.h" |
20 #include "sql/connection.h" | 22 #include "sql/connection.h" |
21 #include "sql/statement.h" | 23 #include "sql/statement.h" |
22 #include "sql/transaction.h" | 24 #include "sql/transaction.h" |
23 | 25 |
24 using autofill::PasswordForm; | 26 using autofill::PasswordForm; |
25 | 27 |
26 namespace password_manager { | 28 namespace password_manager { |
27 | 29 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 s->BindString(COLUMN_AVATAR_URL, form.avatar_url.spec()); | 112 s->BindString(COLUMN_AVATAR_URL, form.avatar_url.spec()); |
111 s->BindString(COLUMN_FEDERATION_URL, form.federation_url.spec()); | 113 s->BindString(COLUMN_FEDERATION_URL, form.federation_url.spec()); |
112 s->BindInt(COLUMN_IS_ZERO_CLICK, form.is_zero_click); | 114 s->BindInt(COLUMN_IS_ZERO_CLICK, form.is_zero_click); |
113 } | 115 } |
114 | 116 |
115 void AddCallback(int err, sql::Statement* /*stmt*/) { | 117 void AddCallback(int err, sql::Statement* /*stmt*/) { |
116 if (err == 19 /*SQLITE_CONSTRAINT*/) | 118 if (err == 19 /*SQLITE_CONSTRAINT*/) |
117 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; | 119 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; |
118 } | 120 } |
119 | 121 |
122 // UMA_* macros assume that the name never changes. This is a helper function | |
123 // where this assumption doesn't hold. | |
124 void LogDynamicUMAStat(const std::string& name, | |
125 int sample, | |
126 int min, | |
127 int max, | |
128 int bucket_size) { | |
129 base::HistogramBase* counter = base::Histogram::FactoryGet( | |
130 name, | |
131 min, | |
132 max, | |
133 bucket_size, | |
134 base::HistogramBase::kUmaTargetedHistogramFlag); | |
135 counter->Add(sample); | |
136 } | |
137 | |
120 } // namespace | 138 } // namespace |
121 | 139 |
122 LoginDatabase::LoginDatabase() { | 140 LoginDatabase::LoginDatabase() { |
123 } | 141 } |
124 | 142 |
125 LoginDatabase::~LoginDatabase() { | 143 LoginDatabase::~LoginDatabase() { |
126 } | 144 } |
127 | 145 |
128 bool LoginDatabase::Init(const base::FilePath& db_path) { | 146 bool LoginDatabase::Init(const base::FilePath& db_path) { |
129 // Set pragmas for a small, private database (based on WebDatabase). | 147 // Set pragmas for a small, private database (based on WebDatabase). |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
270 } | 288 } |
271 if (!db_.Execute("CREATE INDEX logins_signon ON " | 289 if (!db_.Execute("CREATE INDEX logins_signon ON " |
272 "logins (signon_realm)")) { | 290 "logins (signon_realm)")) { |
273 NOTREACHED(); | 291 NOTREACHED(); |
274 return false; | 292 return false; |
275 } | 293 } |
276 } | 294 } |
277 return true; | 295 return true; |
278 } | 296 } |
279 | 297 |
280 void LoginDatabase::ReportMetrics(const std::string& sync_username) { | 298 void LoginDatabase::ReportMetrics(PasswordManagerClient* client) { |
281 sql::Statement s(db_.GetCachedStatement( | 299 sql::Statement s(db_.GetCachedStatement( |
282 SQL_FROM_HERE, | 300 SQL_FROM_HERE, |
283 "SELECT signon_realm, blacklisted_by_user, COUNT(username_value) " | 301 "SELECT signon_realm, blacklisted_by_user, COUNT(username_value) " |
284 "FROM logins GROUP BY signon_realm, blacklisted_by_user")); | 302 "FROM logins GROUP BY signon_realm, blacklisted_by_user")); |
285 | 303 |
286 if (!s.is_valid()) | 304 if (!s.is_valid()) |
287 return; | 305 return; |
288 | 306 |
307 std::string custom_passphrase; | |
vabr (Chromium)
2014/10/13 09:24:18
Should we have a non-empty value describing the si
Garrett Casto
2014/10/13 20:57:56
Yeah, seems reasonable. I was assuming that there
| |
308 if (client->IsPasswordSyncEnabled(ONLY_CUSTOM_PASSPHRASE_USERS)) { | |
309 custom_passphrase = "WithCustomPassphrase"; | |
310 } | |
311 | |
289 int total_accounts = 0; | 312 int total_accounts = 0; |
290 int blacklisted_sites = 0; | 313 int blacklisted_sites = 0; |
291 while (s.Step()) { | 314 while (s.Step()) { |
292 int blacklisted = s.ColumnInt(1); | 315 int blacklisted = s.ColumnInt(1); |
293 int accounts_per_site = s.ColumnInt(2); | 316 int accounts_per_site = s.ColumnInt(2); |
294 if (blacklisted) { | 317 if (blacklisted) { |
295 ++blacklisted_sites; | 318 ++blacklisted_sites; |
296 } else { | 319 } else { |
297 total_accounts += accounts_per_site; | 320 total_accounts += accounts_per_site; |
298 UMA_HISTOGRAM_CUSTOM_COUNTS("PasswordManager.AccountsPerSite", | 321 LogDynamicUMAStat(base::StringPrintf("PasswordManager.AccountsPerSite%s", |
299 accounts_per_site, 0, 32, 6); | 322 custom_passphrase.c_str()), |
323 accounts_per_site, | |
324 0, | |
325 32, | |
326 6); | |
300 } | 327 } |
301 } | 328 } |
302 UMA_HISTOGRAM_CUSTOM_COUNTS("PasswordManager.TotalAccounts", | 329 LogDynamicUMAStat(base::StringPrintf("PasswordManager.TotalAccounts%s", |
303 total_accounts, 0, 32, 6); | 330 custom_passphrase.c_str()), |
304 UMA_HISTOGRAM_CUSTOM_COUNTS("PasswordManager.BlacklistedSites", | 331 total_accounts, |
305 blacklisted_sites, 0, 32, 6); | 332 0, |
333 32, | |
334 6); | |
335 LogDynamicUMAStat(base::StringPrintf("PasswordManager.BlacklistedSites%s", | |
336 custom_passphrase.c_str()), | |
337 blacklisted_sites, | |
338 0, | |
339 32, | |
340 6); | |
306 | 341 |
307 sql::Statement usage_statement(db_.GetCachedStatement( | 342 sql::Statement usage_statement(db_.GetCachedStatement( |
308 SQL_FROM_HERE, | 343 SQL_FROM_HERE, |
309 "SELECT password_type, times_used FROM logins")); | 344 "SELECT password_type, times_used FROM logins")); |
310 | 345 |
311 if (!usage_statement.is_valid()) | 346 if (!usage_statement.is_valid()) |
312 return; | 347 return; |
313 | 348 |
314 while (usage_statement.Step()) { | 349 while (usage_statement.Step()) { |
315 PasswordForm::Type type = static_cast<PasswordForm::Type>( | 350 PasswordForm::Type type = static_cast<PasswordForm::Type>( |
316 usage_statement.ColumnInt(0)); | 351 usage_statement.ColumnInt(0)); |
317 | 352 |
318 if (type == PasswordForm::TYPE_GENERATED) { | 353 if (type == PasswordForm::TYPE_GENERATED) { |
319 UMA_HISTOGRAM_CUSTOM_COUNTS( | 354 LogDynamicUMAStat( |
320 "PasswordManager.TimesGeneratedPasswordUsed", | 355 base::StringPrintf("PasswordManager.TimesGeneratedPasswordUsed%s", |
321 usage_statement.ColumnInt(1), 0, 100, 10); | 356 custom_passphrase.c_str()), |
357 usage_statement.ColumnInt(1), | |
358 0, | |
359 100, | |
360 10); | |
322 } else { | 361 } else { |
323 UMA_HISTOGRAM_CUSTOM_COUNTS( | 362 LogDynamicUMAStat( |
324 "PasswordManager.TimesPasswordUsed", | 363 base::StringPrintf("PasswordManager.TimesPasswordUsed%s", |
325 usage_statement.ColumnInt(1), 0, 100, 10); | 364 custom_passphrase.c_str()), |
365 usage_statement.ColumnInt(1), | |
366 0, | |
367 100, | |
368 10); | |
326 } | 369 } |
327 } | 370 } |
328 | 371 |
329 bool syncing_account_saved = false; | 372 bool syncing_account_saved = false; |
373 std::string sync_username = client->GetSyncUsername(); | |
330 if (!sync_username.empty()) { | 374 if (!sync_username.empty()) { |
331 sql::Statement sync_statement(db_.GetCachedStatement( | 375 sql::Statement sync_statement(db_.GetCachedStatement( |
332 SQL_FROM_HERE, | 376 SQL_FROM_HERE, |
333 "SELECT username_value FROM logins " | 377 "SELECT username_value FROM logins " |
334 "WHERE signon_realm == ?")); | 378 "WHERE signon_realm == ?")); |
335 sync_statement.BindString( | 379 sync_statement.BindString( |
336 0, GaiaUrls::GetInstance()->gaia_url().GetOrigin().spec()); | 380 0, GaiaUrls::GetInstance()->gaia_url().GetOrigin().spec()); |
337 | 381 |
338 if (!sync_statement.is_valid()) | 382 if (!sync_statement.is_valid()) |
339 return; | 383 return; |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
762 | 806 |
763 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { | 807 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { |
764 DCHECK(db_.is_open()); | 808 DCHECK(db_.is_open()); |
765 meta_table_.Reset(); | 809 meta_table_.Reset(); |
766 db_.Close(); | 810 db_.Close(); |
767 sql::Connection::Delete(db_path_); | 811 sql::Connection::Delete(db_path_); |
768 return Init(db_path_); | 812 return Init(db_path_); |
769 } | 813 } |
770 | 814 |
771 } // namespace password_manager | 815 } // namespace password_manager |
OLD | NEW |