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