| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 #include "sql/statement.h" | 37 #include "sql/statement.h" |
| 38 #include "sql/transaction.h" | 38 #include "sql/transaction.h" |
| 39 #include "url/origin.h" | 39 #include "url/origin.h" |
| 40 #include "url/url_constants.h" | 40 #include "url/url_constants.h" |
| 41 | 41 |
| 42 using autofill::PasswordForm; | 42 using autofill::PasswordForm; |
| 43 | 43 |
| 44 namespace password_manager { | 44 namespace password_manager { |
| 45 | 45 |
| 46 // The current version number of the login database schema. | 46 // The current version number of the login database schema. |
| 47 const int kCurrentVersionNumber = 19; | 47 const int kCurrentVersionNumber = 18; |
| 48 // The oldest version of the schema such that a legacy Chrome client using that | 48 // The oldest version of the schema such that a legacy Chrome client using that |
| 49 // version can still read/write the current database. | 49 // version can still read/write the current database. |
| 50 const int kCompatibleVersionNumber = 19; | 50 const int kCompatibleVersionNumber = 18; |
| 51 | 51 |
| 52 base::Pickle SerializePossibleUsernamePairs( | 52 base::Pickle SerializeVector(const std::vector<base::string16>& vec) { |
| 53 const autofill::PossibleUsernamesVector& vec) { | |
| 54 base::Pickle p; | 53 base::Pickle p; |
| 55 for (size_t i = 0; i < vec.size(); ++i) { | 54 for (size_t i = 0; i < vec.size(); ++i) { |
| 56 p.WriteString16(vec[i].first); | 55 p.WriteString16(vec[i]); |
| 57 p.WriteString16(vec[i].second); | |
| 58 } | 56 } |
| 59 return p; | 57 return p; |
| 60 } | 58 } |
| 61 | 59 |
| 62 autofill::PossibleUsernamesVector DeserializePossibleUsernamePairs( | 60 std::vector<base::string16> DeserializeVector(const base::Pickle& p) { |
| 63 const base::Pickle& p) { | 61 std::vector<base::string16> ret; |
| 64 autofill::PossibleUsernamesVector ret; | 62 base::string16 str; |
| 65 base::string16 value; | |
| 66 base::string16 field_name; | |
| 67 | 63 |
| 68 base::PickleIterator iterator(p); | 64 base::PickleIterator iterator(p); |
| 69 while (iterator.ReadString16(&value)) { | 65 while (iterator.ReadString16(&str)) { |
| 70 bool name_success = iterator.ReadString16(&field_name); | 66 ret.push_back(str); |
| 71 DCHECK(name_success); | |
| 72 ret.push_back(autofill::PossibleUsernamePair(value, field_name)); | |
| 73 } | 67 } |
| 74 return ret; | 68 return ret; |
| 75 } | 69 } |
| 76 | 70 |
| 77 namespace { | 71 namespace { |
| 78 | 72 |
| 79 // Convenience enum for interacting with SQL queries that use all the columns. | 73 // Convenience enum for interacting with SQL queries that use all the columns. |
| 80 enum LoginTableColumns { | 74 enum LoginTableColumns { |
| 81 COLUMN_ORIGIN_URL = 0, | 75 COLUMN_ORIGIN_URL = 0, |
| 82 COLUMN_ACTION_URL, | 76 COLUMN_ACTION_URL, |
| 83 COLUMN_USERNAME_ELEMENT, | 77 COLUMN_USERNAME_ELEMENT, |
| 84 COLUMN_USERNAME_VALUE, | 78 COLUMN_USERNAME_VALUE, |
| 85 COLUMN_PASSWORD_ELEMENT, | 79 COLUMN_PASSWORD_ELEMENT, |
| 86 COLUMN_PASSWORD_VALUE, | 80 COLUMN_PASSWORD_VALUE, |
| 87 COLUMN_SUBMIT_ELEMENT, | 81 COLUMN_SUBMIT_ELEMENT, |
| 88 COLUMN_SIGNON_REALM, | 82 COLUMN_SIGNON_REALM, |
| 89 COLUMN_PREFERRED, | 83 COLUMN_PREFERRED, |
| 90 COLUMN_DATE_CREATED, | 84 COLUMN_DATE_CREATED, |
| 91 COLUMN_BLACKLISTED_BY_USER, | 85 COLUMN_BLACKLISTED_BY_USER, |
| 92 COLUMN_SCHEME, | 86 COLUMN_SCHEME, |
| 93 COLUMN_PASSWORD_TYPE, | 87 COLUMN_PASSWORD_TYPE, |
| 88 COLUMN_POSSIBLE_USERNAMES, |
| 94 COLUMN_TIMES_USED, | 89 COLUMN_TIMES_USED, |
| 95 COLUMN_FORM_DATA, | 90 COLUMN_FORM_DATA, |
| 96 COLUMN_DATE_SYNCED, | 91 COLUMN_DATE_SYNCED, |
| 97 COLUMN_DISPLAY_NAME, | 92 COLUMN_DISPLAY_NAME, |
| 98 COLUMN_ICON_URL, | 93 COLUMN_ICON_URL, |
| 99 COLUMN_FEDERATION_URL, | 94 COLUMN_FEDERATION_URL, |
| 100 COLUMN_SKIP_ZERO_CLICK, | 95 COLUMN_SKIP_ZERO_CLICK, |
| 101 COLUMN_GENERATION_UPLOAD_STATUS, | 96 COLUMN_GENERATION_UPLOAD_STATUS, |
| 102 COLUMN_POSSIBLE_USERNAME_PAIRS, | |
| 103 COLUMN_NUM // Keep this last. | 97 COLUMN_NUM // Keep this last. |
| 104 }; | 98 }; |
| 105 | 99 |
| 106 enum class HistogramSize { SMALL, LARGE }; | 100 enum class HistogramSize { SMALL, LARGE }; |
| 107 | 101 |
| 108 // An enum for UMA reporting. Add values to the end only. | 102 // An enum for UMA reporting. Add values to the end only. |
| 109 enum DatabaseInitError { | 103 enum DatabaseInitError { |
| 110 INIT_OK, | 104 INIT_OK, |
| 111 OPEN_FILE_ERROR, | 105 OPEN_FILE_ERROR, |
| 112 START_TRANSACTION_ERROR, | 106 START_TRANSACTION_ERROR, |
| (...skipping 17 matching lines...) Expand all Loading... |
| 130 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); | 124 s->BindString16(COLUMN_PASSWORD_ELEMENT, form.password_element); |
| 131 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), | 125 s->BindBlob(COLUMN_PASSWORD_VALUE, encrypted_password.data(), |
| 132 static_cast<int>(encrypted_password.length())); | 126 static_cast<int>(encrypted_password.length())); |
| 133 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); | 127 s->BindString16(COLUMN_SUBMIT_ELEMENT, form.submit_element); |
| 134 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); | 128 s->BindString(COLUMN_SIGNON_REALM, form.signon_realm); |
| 135 s->BindInt(COLUMN_PREFERRED, form.preferred); | 129 s->BindInt(COLUMN_PREFERRED, form.preferred); |
| 136 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToInternalValue()); | 130 s->BindInt64(COLUMN_DATE_CREATED, form.date_created.ToInternalValue()); |
| 137 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); | 131 s->BindInt(COLUMN_BLACKLISTED_BY_USER, form.blacklisted_by_user); |
| 138 s->BindInt(COLUMN_SCHEME, form.scheme); | 132 s->BindInt(COLUMN_SCHEME, form.scheme); |
| 139 s->BindInt(COLUMN_PASSWORD_TYPE, form.type); | 133 s->BindInt(COLUMN_PASSWORD_TYPE, form.type); |
| 134 base::Pickle usernames_pickle = |
| 135 SerializeVector(form.other_possible_usernames); |
| 136 s->BindBlob(COLUMN_POSSIBLE_USERNAMES, |
| 137 usernames_pickle.data(), |
| 138 usernames_pickle.size()); |
| 140 s->BindInt(COLUMN_TIMES_USED, form.times_used); | 139 s->BindInt(COLUMN_TIMES_USED, form.times_used); |
| 141 base::Pickle form_data_pickle; | 140 base::Pickle form_data_pickle; |
| 142 autofill::SerializeFormData(form.form_data, &form_data_pickle); | 141 autofill::SerializeFormData(form.form_data, &form_data_pickle); |
| 143 s->BindBlob(COLUMN_FORM_DATA, | 142 s->BindBlob(COLUMN_FORM_DATA, |
| 144 form_data_pickle.data(), | 143 form_data_pickle.data(), |
| 145 form_data_pickle.size()); | 144 form_data_pickle.size()); |
| 146 s->BindInt64(COLUMN_DATE_SYNCED, form.date_synced.ToInternalValue()); | 145 s->BindInt64(COLUMN_DATE_SYNCED, form.date_synced.ToInternalValue()); |
| 147 s->BindString16(COLUMN_DISPLAY_NAME, form.display_name); | 146 s->BindString16(COLUMN_DISPLAY_NAME, form.display_name); |
| 148 s->BindString(COLUMN_ICON_URL, form.icon_url.spec()); | 147 s->BindString(COLUMN_ICON_URL, form.icon_url.spec()); |
| 149 // An empty Origin serializes as "null" which would be strange to store here. | 148 // An empty Origin serializes as "null" which would be strange to store here. |
| 150 s->BindString(COLUMN_FEDERATION_URL, | 149 s->BindString(COLUMN_FEDERATION_URL, |
| 151 form.federation_origin.unique() | 150 form.federation_origin.unique() |
| 152 ? std::string() | 151 ? std::string() |
| 153 : form.federation_origin.Serialize()); | 152 : form.federation_origin.Serialize()); |
| 154 s->BindInt(COLUMN_SKIP_ZERO_CLICK, form.skip_zero_click); | 153 s->BindInt(COLUMN_SKIP_ZERO_CLICK, form.skip_zero_click); |
| 155 s->BindInt(COLUMN_GENERATION_UPLOAD_STATUS, form.generation_upload_status); | 154 s->BindInt(COLUMN_GENERATION_UPLOAD_STATUS, form.generation_upload_status); |
| 156 base::Pickle usernames_pickle = | |
| 157 SerializePossibleUsernamePairs(form.other_possible_usernames); | |
| 158 s->BindBlob(COLUMN_POSSIBLE_USERNAME_PAIRS, usernames_pickle.data(), | |
| 159 usernames_pickle.size()); | |
| 160 } | 155 } |
| 161 | 156 |
| 162 void AddCallback(int err, sql::Statement* /*stmt*/) { | 157 void AddCallback(int err, sql::Statement* /*stmt*/) { |
| 163 if (err == 19 /*SQLITE_CONSTRAINT*/) | 158 if (err == 19 /*SQLITE_CONSTRAINT*/) |
| 164 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; | 159 DLOG(WARNING) << "LoginDatabase::AddLogin updated an existing form"; |
| 165 } | 160 } |
| 166 | 161 |
| 167 bool DoesMatchConstraints(const PasswordForm& form) { | 162 bool DoesMatchConstraints(const PasswordForm& form) { |
| 168 if (!IsValidAndroidFacetURI(form.signon_realm) && form.origin.is_empty()) { | 163 if (!IsValidAndroidFacetURI(form.signon_realm) && form.origin.is_empty()) { |
| 169 DLOG(ERROR) << "Constraint violation: form.origin is empty"; | 164 DLOG(ERROR) << "Constraint violation: form.origin is empty"; |
| (...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 builder->SealVersion(); | 424 builder->SealVersion(); |
| 430 // Version 17. | 425 // Version 17. |
| 431 version = builder->SealVersion(); | 426 version = builder->SealVersion(); |
| 432 DCHECK_EQ(17u, version); | 427 DCHECK_EQ(17u, version); |
| 433 | 428 |
| 434 // Version 18. | 429 // Version 18. |
| 435 builder->DropColumn("ssl_valid"); | 430 builder->DropColumn("ssl_valid"); |
| 436 version = builder->SealVersion(); | 431 version = builder->SealVersion(); |
| 437 DCHECK_EQ(18u, version); | 432 DCHECK_EQ(18u, version); |
| 438 | 433 |
| 439 // Version 19. | |
| 440 builder->DropColumn("possible_usernames"); | |
| 441 builder->AddColumn("possible_username_pairs", "BLOB"); | |
| 442 version = builder->SealVersion(); | |
| 443 DCHECK_EQ(19u, version); | |
| 444 | |
| 445 DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builder->NumberOfColumns()) | 434 DCHECK_EQ(static_cast<size_t>(COLUMN_NUM), builder->NumberOfColumns()) |
| 446 << "Adjust LoginTableColumns if you change column definitions here."; | 435 << "Adjust LoginTableColumns if you change column definitions here."; |
| 447 } | 436 } |
| 448 | 437 |
| 449 // Call this after having called InitializeBuilder, to migrate the database from | 438 // Call this after having called InitializeBuilder, to migrate the database from |
| 450 // the current version to kCurrentVersionNumber. | 439 // the current version to kCurrentVersionNumber. |
| 451 bool MigrateLogins(unsigned current_version, | 440 bool MigrateLogins(unsigned current_version, |
| 452 SQLTableBuilder* builder, | 441 SQLTableBuilder* builder, |
| 453 sql::Connection* db) { | 442 sql::Connection* db) { |
| 454 if (!builder->MigrateFrom(current_version, db)) | 443 if (!builder->MigrateFrom(current_version, db)) |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 848 return PasswordStoreChangeList(); | 837 return PasswordStoreChangeList(); |
| 849 | 838 |
| 850 #if defined(OS_IOS) | 839 #if defined(OS_IOS) |
| 851 DeleteEncryptedPassword(form); | 840 DeleteEncryptedPassword(form); |
| 852 #endif | 841 #endif |
| 853 // Replacement is necessary to deal with updating imported credentials. See | 842 // Replacement is necessary to deal with updating imported credentials. See |
| 854 // crbug.com/349138 for details. | 843 // crbug.com/349138 for details. |
| 855 DCHECK(!update_statement_.empty()); | 844 DCHECK(!update_statement_.empty()); |
| 856 sql::Statement s( | 845 sql::Statement s( |
| 857 db_.GetCachedStatement(SQL_FROM_HERE, update_statement_.c_str())); | 846 db_.GetCachedStatement(SQL_FROM_HERE, update_statement_.c_str())); |
| 858 int next_param = 0; | 847 s.BindString(0, form.action.spec()); |
| 859 s.BindString(next_param++, form.action.spec()); | 848 s.BindBlob(1, encrypted_password.data(), |
| 860 s.BindBlob(next_param++, encrypted_password.data(), | |
| 861 static_cast<int>(encrypted_password.length())); | 849 static_cast<int>(encrypted_password.length())); |
| 862 s.BindString16(next_param++, form.submit_element); | 850 s.BindString16(2, form.submit_element); |
| 863 s.BindInt(next_param++, form.preferred); | 851 s.BindInt(3, form.preferred); |
| 864 s.BindInt64(next_param++, form.date_created.ToInternalValue()); | 852 s.BindInt64(4, form.date_created.ToInternalValue()); |
| 865 s.BindInt(next_param++, form.blacklisted_by_user); | 853 s.BindInt(5, form.blacklisted_by_user); |
| 866 s.BindInt(next_param++, form.scheme); | 854 s.BindInt(6, form.scheme); |
| 867 s.BindInt(next_param++, form.type); | 855 s.BindInt(7, form.type); |
| 868 s.BindInt(next_param++, form.times_used); | 856 base::Pickle pickle = SerializeVector(form.other_possible_usernames); |
| 857 s.BindBlob(8, pickle.data(), pickle.size()); |
| 858 s.BindInt(9, form.times_used); |
| 869 base::Pickle form_data_pickle; | 859 base::Pickle form_data_pickle; |
| 870 autofill::SerializeFormData(form.form_data, &form_data_pickle); | 860 autofill::SerializeFormData(form.form_data, &form_data_pickle); |
| 871 s.BindBlob(next_param++, form_data_pickle.data(), form_data_pickle.size()); | 861 s.BindBlob(10, form_data_pickle.data(), form_data_pickle.size()); |
| 872 s.BindInt64(next_param++, form.date_synced.ToInternalValue()); | 862 s.BindInt64(11, form.date_synced.ToInternalValue()); |
| 873 s.BindString16(next_param++, form.display_name); | 863 s.BindString16(12, form.display_name); |
| 874 s.BindString(next_param++, form.icon_url.spec()); | 864 s.BindString(13, form.icon_url.spec()); |
| 875 // An empty Origin serializes as "null" which would be strange to store here. | 865 // An empty Origin serializes as "null" which would be strange to store here. |
| 876 s.BindString(next_param++, form.federation_origin.unique() | 866 s.BindString(14, form.federation_origin.unique() |
| 877 ? std::string() | 867 ? std::string() |
| 878 : form.federation_origin.Serialize()); | 868 : form.federation_origin.Serialize()); |
| 879 s.BindInt(next_param++, form.skip_zero_click); | 869 s.BindInt(15, form.skip_zero_click); |
| 880 s.BindInt(next_param++, form.generation_upload_status); | 870 s.BindInt(16, form.generation_upload_status); |
| 881 base::Pickle username_pickle = | |
| 882 SerializePossibleUsernamePairs(form.other_possible_usernames); | |
| 883 s.BindBlob(next_param++, username_pickle.data(), username_pickle.size()); | |
| 884 // NOTE: Add new fields here unless the field is a part of the unique key. | |
| 885 // If so, add new field below. | |
| 886 | 871 |
| 887 // WHERE starts here. | 872 // WHERE starts here. |
| 888 s.BindString(next_param++, form.origin.spec()); | 873 s.BindString(17, form.origin.spec()); |
| 889 s.BindString16(next_param++, form.username_element); | 874 s.BindString16(18, form.username_element); |
| 890 s.BindString16(next_param++, form.username_value); | 875 s.BindString16(19, form.username_value); |
| 891 s.BindString16(next_param++, form.password_element); | 876 s.BindString16(20, form.password_element); |
| 892 s.BindString(next_param++, form.signon_realm); | 877 s.BindString(21, form.signon_realm); |
| 893 // NOTE: Add new fields here only if the field is a part of the unique key. | |
| 894 // Otherwise, add the field above "WHERE starts here" comment. | |
| 895 | 878 |
| 896 if (!s.Run()) | 879 if (!s.Run()) |
| 897 return PasswordStoreChangeList(); | 880 return PasswordStoreChangeList(); |
| 898 | 881 |
| 899 PasswordStoreChangeList list; | 882 PasswordStoreChangeList list; |
| 900 if (db_.GetLastChangeCount()) | 883 if (db_.GetLastChangeCount()) |
| 901 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form)); | 884 list.push_back(PasswordStoreChange(PasswordStoreChange::UPDATE, form)); |
| 902 | 885 |
| 903 return list; | 886 return list; |
| 904 } | 887 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1008 form->date_created = | 991 form->date_created = |
| 1009 base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED)); | 992 base::Time::FromInternalValue(s.ColumnInt64(COLUMN_DATE_CREATED)); |
| 1010 form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); | 993 form->blacklisted_by_user = (s.ColumnInt(COLUMN_BLACKLISTED_BY_USER) > 0); |
| 1011 int scheme_int = s.ColumnInt(COLUMN_SCHEME); | 994 int scheme_int = s.ColumnInt(COLUMN_SCHEME); |
| 1012 DCHECK_LE(0, scheme_int); | 995 DCHECK_LE(0, scheme_int); |
| 1013 DCHECK_GE(PasswordForm::SCHEME_LAST, scheme_int); | 996 DCHECK_GE(PasswordForm::SCHEME_LAST, scheme_int); |
| 1014 form->scheme = static_cast<PasswordForm::Scheme>(scheme_int); | 997 form->scheme = static_cast<PasswordForm::Scheme>(scheme_int); |
| 1015 int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE); | 998 int type_int = s.ColumnInt(COLUMN_PASSWORD_TYPE); |
| 1016 DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_LAST) << type_int; | 999 DCHECK(type_int >= 0 && type_int <= PasswordForm::TYPE_LAST) << type_int; |
| 1017 form->type = static_cast<PasswordForm::Type>(type_int); | 1000 form->type = static_cast<PasswordForm::Type>(type_int); |
| 1018 if (s.ColumnByteLength(COLUMN_POSSIBLE_USERNAME_PAIRS)) { | 1001 if (s.ColumnByteLength(COLUMN_POSSIBLE_USERNAMES)) { |
| 1019 base::Pickle pickle( | 1002 base::Pickle pickle( |
| 1020 static_cast<const char*>(s.ColumnBlob(COLUMN_POSSIBLE_USERNAME_PAIRS)), | 1003 static_cast<const char*>(s.ColumnBlob(COLUMN_POSSIBLE_USERNAMES)), |
| 1021 s.ColumnByteLength(COLUMN_POSSIBLE_USERNAME_PAIRS)); | 1004 s.ColumnByteLength(COLUMN_POSSIBLE_USERNAMES)); |
| 1022 form->other_possible_usernames = DeserializePossibleUsernamePairs(pickle); | 1005 form->other_possible_usernames = DeserializeVector(pickle); |
| 1023 } | 1006 } |
| 1024 form->times_used = s.ColumnInt(COLUMN_TIMES_USED); | 1007 form->times_used = s.ColumnInt(COLUMN_TIMES_USED); |
| 1025 if (s.ColumnByteLength(COLUMN_FORM_DATA)) { | 1008 if (s.ColumnByteLength(COLUMN_FORM_DATA)) { |
| 1026 base::Pickle form_data_pickle( | 1009 base::Pickle form_data_pickle( |
| 1027 static_cast<const char*>(s.ColumnBlob(COLUMN_FORM_DATA)), | 1010 static_cast<const char*>(s.ColumnBlob(COLUMN_FORM_DATA)), |
| 1028 s.ColumnByteLength(COLUMN_FORM_DATA)); | 1011 s.ColumnByteLength(COLUMN_FORM_DATA)); |
| 1029 base::PickleIterator form_data_iter(form_data_pickle); | 1012 base::PickleIterator form_data_iter(form_data_pickle); |
| 1030 bool success = | 1013 bool success = |
| 1031 autofill::DeserializeFormData(&form_data_iter, &form->form_data); | 1014 autofill::DeserializeFormData(&form_data_iter, &form->form_data); |
| 1032 metrics_util::FormDeserializationStatus status = | 1015 metrics_util::FormDeserializationStatus status = |
| (...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 DCHECK(blacklisted_statement_.empty()); | 1310 DCHECK(blacklisted_statement_.empty()); |
| 1328 blacklisted_statement_ = | 1311 blacklisted_statement_ = |
| 1329 "SELECT " + all_column_names + | 1312 "SELECT " + all_column_names + |
| 1330 " FROM logins WHERE blacklisted_by_user == ? ORDER BY origin_url"; | 1313 " FROM logins WHERE blacklisted_by_user == ? ORDER BY origin_url"; |
| 1331 DCHECK(encrypted_statement_.empty()); | 1314 DCHECK(encrypted_statement_.empty()); |
| 1332 encrypted_statement_ = | 1315 encrypted_statement_ = |
| 1333 "SELECT password_value FROM logins WHERE " + all_unique_key_column_names; | 1316 "SELECT password_value FROM logins WHERE " + all_unique_key_column_names; |
| 1334 } | 1317 } |
| 1335 | 1318 |
| 1336 } // namespace password_manager | 1319 } // namespace password_manager |
| OLD | NEW |