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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 s->BindString(COLUMN_AVATAR_URL, form.avatar_url.spec()); | 110 s->BindString(COLUMN_AVATAR_URL, form.avatar_url.spec()); |
109 s->BindString(COLUMN_FEDERATION_URL, form.federation_url.spec()); | 111 s->BindString(COLUMN_FEDERATION_URL, form.federation_url.spec()); |
110 s->BindInt(COLUMN_IS_ZERO_CLICK, form.is_zero_click); | 112 s->BindInt(COLUMN_IS_ZERO_CLICK, form.is_zero_click); |
111 } | 113 } |
112 | 114 |
113 void AddCallback(int err, sql::Statement* /*stmt*/) { | 115 void AddCallback(int err, sql::Statement* /*stmt*/) { |
114 if (err == 19 /*SQLITE_CONSTRAINT*/) | 116 if (err == 19 /*SQLITE_CONSTRAINT*/) |
115 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; | 117 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; |
116 } | 118 } |
117 | 119 |
| 120 // UMA_* macros assume that the name never changes. This is a helper function |
| 121 // where this assumption doesn't hold. |
| 122 void LogDynamicUMAStat(const std::string& name, |
| 123 int sample, |
| 124 int min, |
| 125 int max, |
| 126 int bucket_size) { |
| 127 base::HistogramBase* counter = base::Histogram::FactoryGet( |
| 128 name, |
| 129 min, |
| 130 max, |
| 131 bucket_size, |
| 132 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 133 counter->Add(sample); |
| 134 } |
| 135 |
| 136 void LogAccountStat(const std::string& name, int sample) { |
| 137 LogDynamicUMAStat(name, sample, 0, 32, 6); |
| 138 } |
| 139 |
| 140 void LogTimesUsedStat(const std::string& name, int sample) { |
| 141 LogDynamicUMAStat(name, sample, 0, 100, 10); |
| 142 } |
| 143 |
118 } // namespace | 144 } // namespace |
119 | 145 |
120 LoginDatabase::LoginDatabase() { | 146 LoginDatabase::LoginDatabase() { |
121 } | 147 } |
122 | 148 |
123 LoginDatabase::~LoginDatabase() { | 149 LoginDatabase::~LoginDatabase() { |
124 } | 150 } |
125 | 151 |
126 bool LoginDatabase::Init(const base::FilePath& db_path) { | 152 bool LoginDatabase::Init(const base::FilePath& db_path) { |
127 // Set pragmas for a small, private database (based on WebDatabase). | 153 // Set pragmas for a small, private database (based on WebDatabase). |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 } | 300 } |
275 if (!db_.Execute("CREATE INDEX logins_signon ON " | 301 if (!db_.Execute("CREATE INDEX logins_signon ON " |
276 "logins (signon_realm)")) { | 302 "logins (signon_realm)")) { |
277 NOTREACHED(); | 303 NOTREACHED(); |
278 return false; | 304 return false; |
279 } | 305 } |
280 } | 306 } |
281 return true; | 307 return true; |
282 } | 308 } |
283 | 309 |
284 void LoginDatabase::ReportMetrics(const std::string& sync_username) { | 310 void LoginDatabase::ReportMetrics(const std::string& sync_username, |
| 311 bool custom_passphrase_sync_enabled) { |
285 sql::Statement s(db_.GetCachedStatement( | 312 sql::Statement s(db_.GetCachedStatement( |
286 SQL_FROM_HERE, | 313 SQL_FROM_HERE, |
287 "SELECT signon_realm, blacklisted_by_user, COUNT(username_value) " | 314 "SELECT signon_realm, blacklisted_by_user, COUNT(username_value) " |
288 "FROM logins GROUP BY signon_realm, blacklisted_by_user")); | 315 "FROM logins GROUP BY signon_realm, blacklisted_by_user")); |
289 | 316 |
290 if (!s.is_valid()) | 317 if (!s.is_valid()) |
291 return; | 318 return; |
292 | 319 |
| 320 std::string custom_passphrase = "WithoutCustomPassphrase"; |
| 321 if (custom_passphrase_sync_enabled) { |
| 322 custom_passphrase = "WithCustomPassphrase"; |
| 323 } |
| 324 |
293 int total_accounts = 0; | 325 int total_accounts = 0; |
294 int blacklisted_sites = 0; | 326 int blacklisted_sites = 0; |
295 while (s.Step()) { | 327 while (s.Step()) { |
296 int blacklisted = s.ColumnInt(1); | 328 int blacklisted = s.ColumnInt(1); |
297 int accounts_per_site = s.ColumnInt(2); | 329 int accounts_per_site = s.ColumnInt(2); |
298 if (blacklisted) { | 330 if (blacklisted) { |
299 ++blacklisted_sites; | 331 ++blacklisted_sites; |
300 } else { | 332 } else { |
301 total_accounts += accounts_per_site; | 333 total_accounts += accounts_per_site; |
302 UMA_HISTOGRAM_CUSTOM_COUNTS("PasswordManager.AccountsPerSite", | 334 LogAccountStat(base::StringPrintf("PasswordManager.AccountsPerSite.%s", |
303 accounts_per_site, 0, 32, 6); | 335 custom_passphrase.c_str()), |
| 336 accounts_per_site); |
304 } | 337 } |
305 } | 338 } |
306 UMA_HISTOGRAM_CUSTOM_COUNTS("PasswordManager.TotalAccounts", | 339 LogAccountStat(base::StringPrintf("PasswordManager.TotalAccounts.%s", |
307 total_accounts, 0, 32, 6); | 340 custom_passphrase.c_str()), |
308 UMA_HISTOGRAM_CUSTOM_COUNTS("PasswordManager.BlacklistedSites", | 341 total_accounts); |
309 blacklisted_sites, 0, 32, 6); | 342 LogAccountStat(base::StringPrintf("PasswordManager.BlacklistedSites.%s", |
| 343 custom_passphrase.c_str()), |
| 344 blacklisted_sites); |
310 | 345 |
311 sql::Statement usage_statement(db_.GetCachedStatement( | 346 sql::Statement usage_statement(db_.GetCachedStatement( |
312 SQL_FROM_HERE, | 347 SQL_FROM_HERE, |
313 "SELECT password_type, times_used FROM logins")); | 348 "SELECT password_type, times_used FROM logins")); |
314 | 349 |
315 if (!usage_statement.is_valid()) | 350 if (!usage_statement.is_valid()) |
316 return; | 351 return; |
317 | 352 |
318 while (usage_statement.Step()) { | 353 while (usage_statement.Step()) { |
319 PasswordForm::Type type = static_cast<PasswordForm::Type>( | 354 PasswordForm::Type type = static_cast<PasswordForm::Type>( |
320 usage_statement.ColumnInt(0)); | 355 usage_statement.ColumnInt(0)); |
321 | 356 |
322 if (type == PasswordForm::TYPE_GENERATED) { | 357 if (type == PasswordForm::TYPE_GENERATED) { |
323 UMA_HISTOGRAM_CUSTOM_COUNTS( | 358 LogTimesUsedStat( |
324 "PasswordManager.TimesGeneratedPasswordUsed", | 359 base::StringPrintf("PasswordManager.TimesGeneratedPasswordUsed.%s", |
325 usage_statement.ColumnInt(1), 0, 100, 10); | 360 custom_passphrase.c_str()), |
| 361 usage_statement.ColumnInt(1)); |
326 } else { | 362 } else { |
327 UMA_HISTOGRAM_CUSTOM_COUNTS( | 363 LogTimesUsedStat( |
328 "PasswordManager.TimesPasswordUsed", | 364 base::StringPrintf("PasswordManager.TimesPasswordUsed.%s", |
329 usage_statement.ColumnInt(1), 0, 100, 10); | 365 custom_passphrase.c_str()), |
| 366 usage_statement.ColumnInt(1)); |
330 } | 367 } |
331 } | 368 } |
332 | 369 |
333 bool syncing_account_saved = false; | 370 bool syncing_account_saved = false; |
334 if (!sync_username.empty()) { | 371 if (!sync_username.empty()) { |
335 sql::Statement sync_statement(db_.GetCachedStatement( | 372 sql::Statement sync_statement(db_.GetCachedStatement( |
336 SQL_FROM_HERE, | 373 SQL_FROM_HERE, |
337 "SELECT username_value FROM logins " | 374 "SELECT username_value FROM logins " |
338 "WHERE signon_realm == ?")); | 375 "WHERE signon_realm == ?")); |
339 sync_statement.BindString( | 376 sync_statement.BindString( |
(...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
764 | 801 |
765 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { | 802 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { |
766 DCHECK(db_.is_open()); | 803 DCHECK(db_.is_open()); |
767 meta_table_.Reset(); | 804 meta_table_.Reset(); |
768 db_.Close(); | 805 db_.Close(); |
769 sql::Connection::Delete(db_path_); | 806 sql::Connection::Delete(db_path_); |
770 return Init(db_path_); | 807 return Init(db_path_); |
771 } | 808 } |
772 | 809 |
773 } // namespace password_manager | 810 } // namespace password_manager |
OLD | NEW |