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/strings/stringprintf.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #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" | 19 #include "components/password_manager/core/browser/password_manager_client.h" |
| 20 #include "google_apis/gaia/gaia_auth_util.h" | 20 #include "google_apis/gaia/gaia_auth_util.h" |
| 21 #include "google_apis/gaia/gaia_urls.h" | 21 #include "google_apis/gaia/gaia_urls.h" |
| 22 #include "sql/connection.h" | 22 #include "sql/connection.h" |
| 23 #include "sql/statement.h" | 23 #include "sql/statement.h" |
| 24 #include "sql/transaction.h" | 24 #include "sql/transaction.h" |
| 25 | 25 |
| 26 using autofill::PasswordForm; | 26 using autofill::PasswordForm; |
| 27 | 27 |
| 28 namespace password_manager { | 28 namespace password_manager { |
| 29 | 29 |
| 30 static const int kCurrentVersionNumber = 8; | 30 static const int kCurrentVersionNumber = 9; |
| 31 static const int kCompatibleVersionNumber = 1; | 31 static const int kCompatibleVersionNumber = 1; |
| 32 | 32 |
| 33 Pickle SerializeVector(const std::vector<base::string16>& vec) { | 33 Pickle SerializeVector(const std::vector<base::string16>& vec) { |
| 34 Pickle p; | 34 Pickle p; |
| 35 for (size_t i = 0; i < vec.size(); ++i) { | 35 for (size_t i = 0; i < vec.size(); ++i) { |
| 36 p.WriteString16(vec[i]); | 36 p.WriteString16(vec[i]); |
| 37 } | 37 } |
| 38 return p; | 38 return p; |
| 39 } | 39 } |
| 40 | 40 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 84 s->BindString(COLUMN_ACTION_URL, form.action.spec()); | 84 s->BindString(COLUMN_ACTION_URL, form.action.spec()); |
| 85 s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); | 85 s->BindString16(COLUMN_USERNAME_ELEMENT, form.username_element); |
| 86 s->BindString16(COLUMN_USERNAME_VALUE, form.username_value); | 86 s->BindString16(COLUMN_USERNAME_VALUE, form.username_value); |
| 87 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); | 87 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); |
| 88 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), | 88 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), |
| 89 static_cast<int>(encrypted_password.length())); | 89 static_cast<int>(encrypted_password.length())); |
| 90 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); | 90 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); |
| 91 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); | 91 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); |
| 92 s->BindInt(COLUMN_SSL_VALID, form.ssl_valid); | 92 s->BindInt(COLUMN_SSL_VALID, form.ssl_valid); |
| 93 s->BindInt(COLUMN_PREFERRED, form.preferred); | 93 s->BindInt(COLUMN_PREFERRED, form.preferred); |
| 94 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToTimeT()); | 94 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToInternalValue()); |
| 95 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); | 95 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); |
| 96 s->BindInt(COLUMN_SCHEME, form.scheme); | 96 s->BindInt(COLUMN_SCHEME, form.scheme); |
| 97 s->BindInt(COLUMN_PASSWORD_TYPE, form.type); | 97 s->BindInt(COLUMN_PASSWORD_TYPE, form.type); |
| 98 Pickle usernames_pickle = SerializeVector(form.other_possible_usernames); | 98 Pickle usernames_pickle = SerializeVector(form.other_possible_usernames); |
| 99 s->BindBlob(COLUMN_POSSIBLE_USERNAMES, | 99 s->BindBlob(COLUMN_POSSIBLE_USERNAMES, |
| 100 usernames_pickle.data(), | 100 usernames_pickle.data(), |
| 101 usernames_pickle.size()); | 101 usernames_pickle.size()); |
| 102 s->BindInt(COLUMN_TIMES_USED, form.times_used); | 102 s->BindInt(COLUMN_TIMES_USED, form.times_used); |
| 103 Pickle form_data_pickle; | 103 Pickle form_data_pickle; |
| 104 autofill::SerializeFormData(form.form_data, &form_data_pickle); | 104 autofill::SerializeFormData(form.form_data, &form_data_pickle); |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 250 } | 250 } |
| 251 meta_table_.SetVersionNumber(7); | 251 meta_table_.SetVersionNumber(7); |
| 252 // Fall through. | 252 // Fall through. |
| 253 case 7: | 253 case 7: |
| 254 // Keep version 8 around even though no changes are made. See | 254 // Keep version 8 around even though no changes are made. See |
| 255 // crbug.com/423716 for context. | 255 // crbug.com/423716 for context. |
| 256 meta_table_.SetVersionNumber(8); | 256 meta_table_.SetVersionNumber(8); |
| 257 // Fall through. | 257 // Fall through. |
| 258 // TODO(gcasto): Remove use_additional_auth by copying table. | 258 // TODO(gcasto): Remove use_additional_auth by copying table. |
| 259 // https://www.sqlite.org/lang_altertable.html | 259 // https://www.sqlite.org/lang_altertable.html |
| 260 case 8: { | |
| 261 sql::Statement s; | |
| 262 s.Assign(db_.GetCachedStatement(SQL_FROM_HERE, | |
| 263 "UPDATE logins SET " | |
| 264 "date_created = " | |
| 265 "(date_created * ?)")); | |
| 266 s.BindInt64(0, base::Time::kMicrosecondsPerSecond); | |
|
Garrett Casto
2014/11/05 22:14:59
It doesn't look like this is safe. Epoch for time_
erikchen
2014/11/06 01:35:01
You're right. I updated the SQL statement to corre
| |
| 267 if (!s.Run()) | |
| 268 return false; | |
| 269 meta_table_.SetVersionNumber(9); | |
| 270 // Fall through. | |
| 271 } | |
| 260 case kCurrentVersionNumber: | 272 case kCurrentVersionNumber: |
| 261 // Already up to date | 273 // Already up to date |
| 262 return true; | 274 return true; |
| 263 default: | 275 default: |
| 264 NOTREACHED(); | 276 NOTREACHED(); |
| 265 return false; | 277 return false; |
| 266 } | 278 } |
| 267 } | 279 } |
| 268 | 280 |
| 269 bool LoginDatabase::InitLoginsTable() { | 281 bool LoginDatabase::InitLoginsTable() { |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 469 s.BindString(0, form.action.spec()); | 481 s.BindString(0, form.action.spec()); |
| 470 s.BindBlob(1, encrypted_password.data(), | 482 s.BindBlob(1, encrypted_password.data(), |
| 471 static_cast<int>(encrypted_password.length())); | 483 static_cast<int>(encrypted_password.length())); |
| 472 s.BindInt(2, form.ssl_valid); | 484 s.BindInt(2, form.ssl_valid); |
| 473 s.BindInt(3, form.preferred); | 485 s.BindInt(3, form.preferred); |
| 474 Pickle pickle = SerializeVector(form.other_possible_usernames); | 486 Pickle pickle = SerializeVector(form.other_possible_usernames); |
| 475 s.BindBlob(4, pickle.data(), pickle.size()); | 487 s.BindBlob(4, pickle.data(), pickle.size()); |
| 476 s.BindInt(5, form.times_used); | 488 s.BindInt(5, form.times_used); |
| 477 s.BindString16(6, form.submit_element); | 489 s.BindString16(6, form.submit_element); |
| 478 s.BindInt64(7, form.date_synced.ToInternalValue()); | 490 s.BindInt64(7, form.date_synced.ToInternalValue()); |
| 479 s.BindInt64(8, form.date_created.ToTimeT()); | 491 s.BindInt64(8, form.date_created.ToInternalValue()); |
| 480 s.BindInt(9, form.blacklisted_by_user); | 492 s.BindInt(9, form.blacklisted_by_user); |
| 481 s.BindInt(10, form.scheme); | 493 s.BindInt(10, form.scheme); |
| 482 s.BindInt(11, form.type); | 494 s.BindInt(11, form.type); |
| 483 s.BindString16(12, form.display_name); | 495 s.BindString16(12, form.display_name); |
| 484 s.BindString(13, form.avatar_url.spec()); | 496 s.BindString(13, form.avatar_url.spec()); |
| 485 s.BindString(14, form.federation_url.spec()); | 497 s.BindString(14, form.federation_url.spec()); |
| 486 s.BindInt(15, form.is_zero_click); | 498 s.BindInt(15, form.is_zero_click); |
| 487 | 499 |
| 488 // WHERE starts here. | 500 // WHERE starts here. |
| 489 s.BindString(16, form.origin.spec()); | 501 s.BindString(16, form.origin.spec()); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 520 s.BindString(5, form.signon_realm); | 532 s.BindString(5, form.signon_realm); |
| 521 | 533 |
| 522 return s.Run(); | 534 return s.Run(); |
| 523 } | 535 } |
| 524 | 536 |
| 525 bool LoginDatabase::RemoveLoginsCreatedBetween(base::Time delete_begin, | 537 bool LoginDatabase::RemoveLoginsCreatedBetween(base::Time delete_begin, |
| 526 base::Time delete_end) { | 538 base::Time delete_end) { |
| 527 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, | 539 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, |
| 528 "DELETE FROM logins WHERE " | 540 "DELETE FROM logins WHERE " |
| 529 "date_created >= ? AND date_created < ?")); | 541 "date_created >= ? AND date_created < ?")); |
| 530 s.BindInt64(0, delete_begin.ToTimeT()); | 542 s.BindInt64(0, delete_begin.ToInternalValue()); |
| 531 s.BindInt64(1, delete_end.is_null() ? std::numeric_limits<int64>::max() | 543 s.BindInt64(1, delete_end.is_null() ? std::numeric_limits<int64>::max() |
| 532 : delete_end.ToTimeT()); | 544 : delete_end.ToInternalValue()); |
| 533 | 545 |
| 534 return s.Run(); | 546 return s.Run(); |
| 535 } | 547 } |
| 536 | 548 |
| 537 bool LoginDatabase::RemoveLoginsSyncedBetween(base::Time delete_begin, | 549 bool LoginDatabase::RemoveLoginsSyncedBetween(base::Time delete_begin, |
| 538 base::Time delete_end) { | 550 base::Time delete_end) { |
| 539 sql::Statement s(db_.GetCachedStatement( | 551 sql::Statement s(db_.GetCachedStatement( |
| 540 SQL_FROM_HERE, | 552 SQL_FROM_HERE, |
| 541 "DELETE FROM logins WHERE date_synced >= ? AND date_synced < ?")); | 553 "DELETE FROM logins WHERE date_synced >= ? AND date_synced < ?")); |
| 542 s.BindInt64(0, delete_begin.ToInternalValue()); | 554 s.BindInt64(0, delete_begin.ToInternalValue()); |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 564 form->action = GURL(tmp); | 576 form->action = GURL(tmp); |
| 565 form->username_element = s.ColumnString16(COLUMN_USERNAME_ELEMENT); | 577 form->username_element = s.ColumnString16(COLUMN_USERNAME_ELEMENT); |
| 566 form->username_value = s.ColumnString16(COLUMN_USERNAME_VALUE); | 578 form->username_value = s.ColumnString16(COLUMN_USERNAME_VALUE); |
| 567 form->password_element = s.ColumnString16(COLUMN_PASSWORD_ELEMENT); | 579 form->password_element = s.ColumnString16(COLUMN_PASSWORD_ELEMENT); |
| 568 form->password_value = decrypted_password; | 580 form->password_value = decrypted_password; |
| 569 form->submit_element = s.ColumnString16(COLUMN_SUBMIT_ELEMENT); | 581 form->submit_element = s.ColumnString16(COLUMN_SUBMIT_ELEMENT); |
| 570 tmp = s.ColumnString(COLUMN_SIGNON_REALM); | 582 tmp = s.ColumnString(COLUMN_SIGNON_REALM); |
| 571 form->signon_realm = tmp; | 583 form->signon_realm = tmp; |
| 572 form->ssl_valid = (s.ColumnInt(COLUMN_SSL_VALID) > 0); | 584 form->ssl_valid = (s.ColumnInt(COLUMN_SSL_VALID) > 0); |
| 573 form->preferred = (s.ColumnInt(COLUMN_PREFERRED) > 0); | 585 form->preferred = (s.ColumnInt(COLUMN_PREFERRED) > 0); |
| 574 form->date_created = base::Time::FromTimeT( | 586 form->date_created = |
| 575 s.ColumnInt64(COLUMN_DATE_CREATED)); | 587 base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED)); |
| 576 form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); | 588 form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); |
| 577 int scheme_int = s.ColumnInt(COLUMN_SCHEME); | 589 int scheme_int = s.ColumnInt(COLUMN_SCHEME); |
| 578 DCHECK((scheme_int >= 0) && (scheme_int <= PasswordForm::SCHEME_OTHER)); | 590 DCHECK((scheme_int >= 0) && (scheme_int <= PasswordForm::SCHEME_OTHER)); |
| 579 form->scheme = static_cast<PasswordForm::Scheme>(scheme_int); | 591 form->scheme = static_cast<PasswordForm::Scheme>(scheme_int); |
| 580 int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE); | 592 int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE); |
| 581 DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_GENERATED); | 593 DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_GENERATED); |
| 582 form->type = static_cast<PasswordForm::Type>(type_int); | 594 form->type = static_cast<PasswordForm::Type>(type_int); |
| 583 if (s.ColumnByteLength(COLUMN_POSSIBLE_USERNAMES)) { | 595 if (s.ColumnByteLength(COLUMN_POSSIBLE_USERNAMES)) { |
| 584 Pickle pickle( | 596 Pickle pickle( |
| 585 static_cast<const char*>(s.ColumnBlob(COLUMN_POSSIBLE_USERNAMES)), | 597 static_cast<const char*>(s.ColumnBlob(COLUMN_POSSIBLE_USERNAMES)), |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 704 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, | 716 sql::Statement s(db_.GetCachedStatement(SQL_FROM_HERE, |
| 705 "SELECT origin_url, action_url, " | 717 "SELECT origin_url, action_url, " |
| 706 "username_element, username_value, " | 718 "username_element, username_value, " |
| 707 "password_element, password_value, submit_element, " | 719 "password_element, password_value, submit_element, " |
| 708 "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " | 720 "signon_realm, ssl_valid, preferred, date_created, blacklisted_by_user, " |
| 709 "scheme, password_type, possible_usernames, times_used, form_data, " | 721 "scheme, password_type, possible_usernames, times_used, form_data, " |
| 710 "date_synced, display_name, avatar_url, " | 722 "date_synced, display_name, avatar_url, " |
| 711 "federation_url, is_zero_click FROM logins " | 723 "federation_url, is_zero_click FROM logins " |
| 712 "WHERE date_created >= ? AND date_created < ?" | 724 "WHERE date_created >= ? AND date_created < ?" |
| 713 "ORDER BY origin_url")); | 725 "ORDER BY origin_url")); |
| 714 s.BindInt64(0, begin.ToTimeT()); | 726 s.BindInt64(0, begin.ToInternalValue()); |
| 715 s.BindInt64(1, end.is_null() ? std::numeric_limits<int64>::max() | 727 s.BindInt64(1, end.is_null() ? std::numeric_limits<int64>::max() |
| 716 : end.ToTimeT()); | 728 : end.ToInternalValue()); |
| 717 | 729 |
| 718 while (s.Step()) { | 730 while (s.Step()) { |
| 719 scoped_ptr<PasswordForm> new_form(new PasswordForm()); | 731 scoped_ptr<PasswordForm> new_form(new PasswordForm()); |
| 720 EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s); | 732 EncryptionResult result = InitPasswordFormFromStatement(new_form.get(), s); |
| 721 if (result == ENCRYPTION_RESULT_SERVICE_FAILURE) | 733 if (result == ENCRYPTION_RESULT_SERVICE_FAILURE) |
| 722 return false; | 734 return false; |
| 723 if (result == ENCRYPTION_RESULT_ITEM_FAILURE) | 735 if (result == ENCRYPTION_RESULT_ITEM_FAILURE) |
| 724 continue; | 736 continue; |
| 725 DCHECK(result == ENCRYPTION_RESULT_SUCCESS); | 737 DCHECK(result == ENCRYPTION_RESULT_SUCCESS); |
| 726 forms->push_back(new_form.release()); | 738 forms->push_back(new_form.release()); |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 801 | 813 |
| 802 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { | 814 bool LoginDatabase::DeleteAndRecreateDatabaseFile() { |
| 803 DCHECK(db_.is_open()); | 815 DCHECK(db_.is_open()); |
| 804 meta_table_.Reset(); | 816 meta_table_.Reset(); |
| 805 db_.Close(); | 817 db_.Close(); |
| 806 sql::Connection::Delete(db_path_); | 818 sql::Connection::Delete(db_path_); |
| 807 return Init(db_path_); | 819 return Init(db_path_); |
| 808 } | 820 } |
| 809 | 821 |
| 810 } // namespace password_manager | 822 } // namespace password_manager |
| OLD | NEW |