| 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 |