Chromium Code Reviews| 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 |