OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/autofill/core/browser/webdata/autofill_table.h" | 5 #include "components/autofill/core/browser/webdata/autofill_table.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
24 #include "base/strings/utf_string_conversions.h" | 24 #include "base/strings/utf_string_conversions.h" |
25 #include "base/time/time.h" | 25 #include "base/time/time.h" |
26 #include "components/autofill/core/browser/autofill_country.h" | 26 #include "components/autofill/core/browser/autofill_country.h" |
27 #include "components/autofill/core/browser/autofill_profile.h" | 27 #include "components/autofill/core/browser/autofill_profile.h" |
28 #include "components/autofill/core/browser/autofill_type.h" | 28 #include "components/autofill/core/browser/autofill_type.h" |
29 #include "components/autofill/core/browser/credit_card.h" | 29 #include "components/autofill/core/browser/credit_card.h" |
30 #include "components/autofill/core/browser/personal_data_manager.h" | 30 #include "components/autofill/core/browser/personal_data_manager.h" |
31 #include "components/autofill/core/browser/webdata/autofill_change.h" | 31 #include "components/autofill/core/browser/webdata/autofill_change.h" |
32 #include "components/autofill/core/browser/webdata/autofill_entry.h" | 32 #include "components/autofill/core/browser/webdata/autofill_entry.h" |
33 #include "components/autofill/core/browser/webdata/autofill_table_encryptor_fact ory.h" | |
33 #include "components/autofill/core/common/autofill_clock.h" | 34 #include "components/autofill/core/common/autofill_clock.h" |
34 #include "components/autofill/core/common/autofill_switches.h" | 35 #include "components/autofill/core/common/autofill_switches.h" |
35 #include "components/autofill/core/common/autofill_util.h" | 36 #include "components/autofill/core/common/autofill_util.h" |
36 #include "components/autofill/core/common/form_field_data.h" | 37 #include "components/autofill/core/common/form_field_data.h" |
37 #include "components/os_crypt/os_crypt.h" | |
38 #include "components/sync/base/model_type.h" | 38 #include "components/sync/base/model_type.h" |
39 #include "components/sync/protocol/entity_metadata.pb.h" | 39 #include "components/sync/protocol/entity_metadata.pb.h" |
40 #include "components/sync/protocol/model_type_state.pb.h" | 40 #include "components/sync/protocol/model_type_state.pb.h" |
41 #include "components/webdata/common/web_database.h" | 41 #include "components/webdata/common/web_database.h" |
42 #include "sql/statement.h" | 42 #include "sql/statement.h" |
43 #include "sql/transaction.h" | 43 #include "sql/transaction.h" |
44 #include "ui/base/l10n/l10n_util.h" | 44 #include "ui/base/l10n/l10n_util.h" |
45 #include "url/gurl.h" | 45 #include "url/gurl.h" |
46 | 46 |
47 using base::ASCIIToUTF16; | 47 using base::ASCIIToUTF16; |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
122 profile->set_use_count(s.ColumnInt64(index++)); | 122 profile->set_use_count(s.ColumnInt64(index++)); |
123 profile->set_use_date(Time::FromTimeT(s.ColumnInt64(index++))); | 123 profile->set_use_date(Time::FromTimeT(s.ColumnInt64(index++))); |
124 profile->set_modification_date(Time::FromTimeT(s.ColumnInt64(index++))); | 124 profile->set_modification_date(Time::FromTimeT(s.ColumnInt64(index++))); |
125 profile->set_origin(s.ColumnString(index++)); | 125 profile->set_origin(s.ColumnString(index++)); |
126 profile->set_language_code(s.ColumnString(index++)); | 126 profile->set_language_code(s.ColumnString(index++)); |
127 | 127 |
128 return profile; | 128 return profile; |
129 } | 129 } |
130 | 130 |
131 void BindEncryptedCardToColumn(sql::Statement* s, | 131 void BindEncryptedCardToColumn(sql::Statement* s, |
132 int column_index, | 132 int column_index, |
133 const base::string16& number) { | 133 const base::string16& number, |
134 const AutofillTableEncryptor& encryptor) { | |
134 std::string encrypted_data; | 135 std::string encrypted_data; |
135 OSCrypt::EncryptString16(number, &encrypted_data); | 136 encryptor.EncryptString16(number, &encrypted_data); |
136 s->BindBlob(column_index, encrypted_data.data(), | 137 s->BindBlob(column_index, encrypted_data.data(), |
137 static_cast<int>(encrypted_data.length())); | 138 static_cast<int>(encrypted_data.length())); |
138 } | 139 } |
139 | 140 |
140 void BindCreditCardToStatement(const CreditCard& credit_card, | 141 void BindCreditCardToStatement(const CreditCard& credit_card, |
141 const Time& modification_date, | 142 const Time& modification_date, |
142 sql::Statement* s) { | 143 sql::Statement* s, |
144 const AutofillTableEncryptor& encryptor) { | |
143 DCHECK(base::IsValidGUID(credit_card.guid())); | 145 DCHECK(base::IsValidGUID(credit_card.guid())); |
144 int index = 0; | 146 int index = 0; |
145 s->BindString(index++, credit_card.guid()); | 147 s->BindString(index++, credit_card.guid()); |
146 | 148 |
147 s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_NAME_FULL)); | 149 s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_NAME_FULL)); |
148 s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_MONTH)); | 150 s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_MONTH)); |
149 s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_4_DIGIT_YEAR)); | 151 s->BindString16(index++, GetInfo(credit_card, CREDIT_CARD_EXP_4_DIGIT_YEAR)); |
150 BindEncryptedCardToColumn(s, index++, | 152 BindEncryptedCardToColumn( |
151 credit_card.GetRawInfo(CREDIT_CARD_NUMBER)); | 153 s, index++, credit_card.GetRawInfo(CREDIT_CARD_NUMBER), encryptor); |
152 | 154 |
153 s->BindInt64(index++, credit_card.use_count()); | 155 s->BindInt64(index++, credit_card.use_count()); |
154 s->BindInt64(index++, credit_card.use_date().ToTimeT()); | 156 s->BindInt64(index++, credit_card.use_date().ToTimeT()); |
155 s->BindInt64(index++, modification_date.ToTimeT()); | 157 s->BindInt64(index++, modification_date.ToTimeT()); |
156 s->BindString(index++, credit_card.origin()); | 158 s->BindString(index++, credit_card.origin()); |
157 s->BindString(index++, credit_card.billing_address_id()); | 159 s->BindString(index++, credit_card.billing_address_id()); |
158 } | 160 } |
159 | 161 |
160 base::string16 UnencryptedCardFromColumn(const sql::Statement& s, | 162 base::string16 UnencryptedCardFromColumn( |
161 int column_index) { | 163 const sql::Statement& s, |
164 int column_index, | |
165 const AutofillTableEncryptor& encryptor) { | |
162 base::string16 credit_card_number; | 166 base::string16 credit_card_number; |
163 int encrypted_number_len = s.ColumnByteLength(column_index); | 167 int encrypted_number_len = s.ColumnByteLength(column_index); |
164 if (encrypted_number_len) { | 168 if (encrypted_number_len) { |
165 std::string encrypted_number; | 169 std::string encrypted_number; |
166 encrypted_number.resize(encrypted_number_len); | 170 encrypted_number.resize(encrypted_number_len); |
167 memcpy(&encrypted_number[0], s.ColumnBlob(column_index), | 171 memcpy(&encrypted_number[0], s.ColumnBlob(column_index), |
168 encrypted_number_len); | 172 encrypted_number_len); |
169 OSCrypt::DecryptString16(encrypted_number, &credit_card_number); | 173 encryptor.DecryptString16(encrypted_number, &credit_card_number); |
170 } | 174 } |
171 return credit_card_number; | 175 return credit_card_number; |
172 } | 176 } |
173 | 177 |
174 std::unique_ptr<CreditCard> CreditCardFromStatement(const sql::Statement& s) { | 178 std::unique_ptr<CreditCard> CreditCardFromStatement( |
179 const sql::Statement& s, | |
180 const AutofillTableEncryptor& encryptor) { | |
175 std::unique_ptr<CreditCard> credit_card(new CreditCard); | 181 std::unique_ptr<CreditCard> credit_card(new CreditCard); |
176 | 182 |
177 int index = 0; | 183 int index = 0; |
178 credit_card->set_guid(s.ColumnString(index++)); | 184 credit_card->set_guid(s.ColumnString(index++)); |
179 DCHECK(base::IsValidGUID(credit_card->guid())); | 185 DCHECK(base::IsValidGUID(credit_card->guid())); |
180 | 186 |
181 credit_card->SetRawInfo(CREDIT_CARD_NAME_FULL, s.ColumnString16(index++)); | 187 credit_card->SetRawInfo(CREDIT_CARD_NAME_FULL, s.ColumnString16(index++)); |
182 credit_card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(index++)); | 188 credit_card->SetRawInfo(CREDIT_CARD_EXP_MONTH, s.ColumnString16(index++)); |
183 credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, | 189 credit_card->SetRawInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, |
184 s.ColumnString16(index++)); | 190 s.ColumnString16(index++)); |
185 credit_card->SetRawInfo(CREDIT_CARD_NUMBER, | 191 credit_card->SetRawInfo(CREDIT_CARD_NUMBER, |
186 UnencryptedCardFromColumn(s, index++)); | 192 UnencryptedCardFromColumn(s, index++, encryptor)); |
187 credit_card->set_use_count(s.ColumnInt64(index++)); | 193 credit_card->set_use_count(s.ColumnInt64(index++)); |
188 credit_card->set_use_date(Time::FromTimeT(s.ColumnInt64(index++))); | 194 credit_card->set_use_date(Time::FromTimeT(s.ColumnInt64(index++))); |
189 credit_card->set_modification_date(Time::FromTimeT(s.ColumnInt64(index++))); | 195 credit_card->set_modification_date(Time::FromTimeT(s.ColumnInt64(index++))); |
190 credit_card->set_origin(s.ColumnString(index++)); | 196 credit_card->set_origin(s.ColumnString(index++)); |
191 credit_card->set_billing_address_id(s.ColumnString(index++)); | 197 credit_card->set_billing_address_id(s.ColumnString(index++)); |
192 | 198 |
193 return credit_card; | 199 return credit_card; |
194 } | 200 } |
195 | 201 |
196 bool AddAutofillProfileNamesToProfile(sql::Connection* db, | 202 bool AddAutofillProfileNamesToProfile(sql::Connection* db, |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
392 } | 398 } |
393 | 399 |
394 return result; | 400 return result; |
395 } | 401 } |
396 | 402 |
397 } // namespace | 403 } // namespace |
398 | 404 |
399 // static | 405 // static |
400 const size_t AutofillTable::kMaxDataLength = 1024; | 406 const size_t AutofillTable::kMaxDataLength = 1024; |
401 | 407 |
402 AutofillTable::AutofillTable() { | 408 AutofillTable::AutofillTable() |
403 } | 409 : AutofillTable( |
410 std::move(AutofillTableEncryptorFactory::GetInstance()->Create())) {} | |
Roger McFarlane (Chromium)
2017/02/17 21:04:08
nit:
you don't need to std::move() a temporary. s
devarajn
2017/02/17 22:28:53
Done.
| |
411 | |
412 AutofillTable::AutofillTable( | |
413 std::unique_ptr<AutofillTableEncryptor> autofill_table_encryptor) | |
414 : autofill_table_encryptor_(std::move(autofill_table_encryptor)) {} | |
404 | 415 |
405 AutofillTable::~AutofillTable() { | 416 AutofillTable::~AutofillTable() { |
406 } | 417 } |
407 | 418 |
408 AutofillTable* AutofillTable::FromWebDatabase(WebDatabase* db) { | 419 AutofillTable* AutofillTable::FromWebDatabase(WebDatabase* db) { |
409 return static_cast<AutofillTable*>(db->GetTable(GetKey())); | 420 return static_cast<AutofillTable*>(db->GetTable(GetKey())); |
410 } | 421 } |
411 | 422 |
412 WebDatabaseTable::TypeKey AutofillTable::GetTypeKey() const { | 423 WebDatabaseTable::TypeKey AutofillTable::GetTypeKey() const { |
413 return GetKey(); | 424 return GetKey(); |
(...skipping 744 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1158 return s4.Run(); | 1169 return s4.Run(); |
1159 } | 1170 } |
1160 | 1171 |
1161 bool AutofillTable::AddCreditCard(const CreditCard& credit_card) { | 1172 bool AutofillTable::AddCreditCard(const CreditCard& credit_card) { |
1162 sql::Statement s(db_->GetUniqueStatement( | 1173 sql::Statement s(db_->GetUniqueStatement( |
1163 "INSERT INTO credit_cards" | 1174 "INSERT INTO credit_cards" |
1164 "(guid, name_on_card, expiration_month, expiration_year, " | 1175 "(guid, name_on_card, expiration_month, expiration_year, " |
1165 " card_number_encrypted, use_count, use_date, date_modified, origin," | 1176 " card_number_encrypted, use_count, use_date, date_modified, origin," |
1166 " billing_address_id)" | 1177 " billing_address_id)" |
1167 "VALUES (?,?,?,?,?,?,?,?,?,?)")); | 1178 "VALUES (?,?,?,?,?,?,?,?,?,?)")); |
1168 BindCreditCardToStatement(credit_card, AutofillClock::Now(), &s); | 1179 BindCreditCardToStatement(credit_card, AutofillClock::Now(), &s, |
1180 *autofill_table_encryptor_); | |
1169 | 1181 |
1170 if (!s.Run()) | 1182 if (!s.Run()) |
1171 return false; | 1183 return false; |
1172 | 1184 |
1173 DCHECK_GT(db_->GetLastChangeCount(), 0); | 1185 DCHECK_GT(db_->GetLastChangeCount(), 0); |
1174 return true; | 1186 return true; |
1175 } | 1187 } |
1176 | 1188 |
1177 std::unique_ptr<CreditCard> AutofillTable::GetCreditCard( | 1189 std::unique_ptr<CreditCard> AutofillTable::GetCreditCard( |
1178 const std::string& guid) { | 1190 const std::string& guid) { |
1179 DCHECK(base::IsValidGUID(guid)); | 1191 DCHECK(base::IsValidGUID(guid)); |
1180 sql::Statement s(db_->GetUniqueStatement( | 1192 sql::Statement s(db_->GetUniqueStatement( |
1181 "SELECT guid, name_on_card, expiration_month, expiration_year, " | 1193 "SELECT guid, name_on_card, expiration_month, expiration_year, " |
1182 "card_number_encrypted, use_count, use_date, date_modified, " | 1194 "card_number_encrypted, use_count, use_date, date_modified, " |
1183 "origin, billing_address_id " | 1195 "origin, billing_address_id " |
1184 "FROM credit_cards " | 1196 "FROM credit_cards " |
1185 "WHERE guid = ?")); | 1197 "WHERE guid = ?")); |
1186 s.BindString(0, guid); | 1198 s.BindString(0, guid); |
1187 | 1199 |
1188 if (!s.Step()) | 1200 if (!s.Step()) |
1189 return std::unique_ptr<CreditCard>(); | 1201 return std::unique_ptr<CreditCard>(); |
1190 | 1202 |
1191 return CreditCardFromStatement(s); | 1203 return CreditCardFromStatement(s, *autofill_table_encryptor_); |
1192 } | 1204 } |
1193 | 1205 |
1194 bool AutofillTable::GetCreditCards( | 1206 bool AutofillTable::GetCreditCards( |
1195 std::vector<std::unique_ptr<CreditCard>>* credit_cards) { | 1207 std::vector<std::unique_ptr<CreditCard>>* credit_cards) { |
1196 DCHECK(credit_cards); | 1208 DCHECK(credit_cards); |
1197 credit_cards->clear(); | 1209 credit_cards->clear(); |
1198 | 1210 |
1199 sql::Statement s(db_->GetUniqueStatement( | 1211 sql::Statement s(db_->GetUniqueStatement( |
1200 "SELECT guid " | 1212 "SELECT guid " |
1201 "FROM credit_cards " | 1213 "FROM credit_cards " |
(...skipping 28 matching lines...) Expand all Loading... | |
1230 "exp_year," // 9 | 1242 "exp_year," // 9 |
1231 "metadata.billing_address_id " // 10 | 1243 "metadata.billing_address_id " // 10 |
1232 "FROM masked_credit_cards masked " | 1244 "FROM masked_credit_cards masked " |
1233 "LEFT OUTER JOIN unmasked_credit_cards USING (id) " | 1245 "LEFT OUTER JOIN unmasked_credit_cards USING (id) " |
1234 "LEFT OUTER JOIN server_card_metadata metadata USING (id)")); | 1246 "LEFT OUTER JOIN server_card_metadata metadata USING (id)")); |
1235 while (s.Step()) { | 1247 while (s.Step()) { |
1236 int index = 0; | 1248 int index = 0; |
1237 | 1249 |
1238 // If the card_number_encrypted field is nonempty, we can assume this card | 1250 // If the card_number_encrypted field is nonempty, we can assume this card |
1239 // is a full card, otherwise it's masked. | 1251 // is a full card, otherwise it's masked. |
1240 base::string16 full_card_number = UnencryptedCardFromColumn(s, index++); | 1252 base::string16 full_card_number = |
1253 UnencryptedCardFromColumn(s, index++, *autofill_table_encryptor_); | |
1241 base::string16 last_four = s.ColumnString16(index++); | 1254 base::string16 last_four = s.ColumnString16(index++); |
1242 CreditCard::RecordType record_type = full_card_number.empty() ? | 1255 CreditCard::RecordType record_type = full_card_number.empty() ? |
1243 CreditCard::MASKED_SERVER_CARD : | 1256 CreditCard::MASKED_SERVER_CARD : |
1244 CreditCard::FULL_SERVER_CARD; | 1257 CreditCard::FULL_SERVER_CARD; |
1245 std::string server_id = s.ColumnString(index++); | 1258 std::string server_id = s.ColumnString(index++); |
1246 | 1259 |
1247 std::unique_ptr<CreditCard> card = | 1260 std::unique_ptr<CreditCard> card = |
1248 base::MakeUnique<CreditCard>(record_type, server_id); | 1261 base::MakeUnique<CreditCard>(record_type, server_id); |
1249 card->SetRawInfo( | 1262 card->SetRawInfo( |
1250 CREDIT_CARD_NUMBER, | 1263 CREDIT_CARD_NUMBER, |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1337 MaskServerCreditCard(masked.server_id()); | 1350 MaskServerCreditCard(masked.server_id()); |
1338 sql::Statement s(db_->GetUniqueStatement( | 1351 sql::Statement s(db_->GetUniqueStatement( |
1339 "INSERT INTO unmasked_credit_cards(" | 1352 "INSERT INTO unmasked_credit_cards(" |
1340 "id," | 1353 "id," |
1341 "card_number_encrypted," | 1354 "card_number_encrypted," |
1342 "unmask_date)" | 1355 "unmask_date)" |
1343 "VALUES (?,?,?)")); | 1356 "VALUES (?,?,?)")); |
1344 s.BindString(0, masked.server_id()); | 1357 s.BindString(0, masked.server_id()); |
1345 | 1358 |
1346 std::string encrypted_data; | 1359 std::string encrypted_data; |
1347 OSCrypt::EncryptString16(full_number, &encrypted_data); | 1360 autofill_table_encryptor_->EncryptString16(full_number, &encrypted_data); |
1348 s.BindBlob(1, encrypted_data.data(), | 1361 s.BindBlob(1, encrypted_data.data(), |
1349 static_cast<int>(encrypted_data.length())); | 1362 static_cast<int>(encrypted_data.length())); |
1350 s.BindInt64(2, AutofillClock::Now().ToInternalValue()); // unmask_date | 1363 s.BindInt64(2, AutofillClock::Now().ToInternalValue()); // unmask_date |
1351 | 1364 |
1352 s.Run(); | 1365 s.Run(); |
1353 | 1366 |
1354 CreditCard unmasked = masked; | 1367 CreditCard unmasked = masked; |
1355 unmasked.set_record_type(CreditCard::FULL_SERVER_CARD); | 1368 unmasked.set_record_type(CreditCard::FULL_SERVER_CARD); |
1356 unmasked.SetNumber(full_number); | 1369 unmasked.SetNumber(full_number); |
1357 unmasked.RecordAndLogUse(); | 1370 unmasked.RecordAndLogUse(); |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1471 sql::Statement s(db_->GetUniqueStatement( | 1484 sql::Statement s(db_->GetUniqueStatement( |
1472 "UPDATE credit_cards " | 1485 "UPDATE credit_cards " |
1473 "SET guid=?, name_on_card=?, expiration_month=?," | 1486 "SET guid=?, name_on_card=?, expiration_month=?," |
1474 "expiration_year=?, card_number_encrypted=?, use_count=?, use_date=?," | 1487 "expiration_year=?, card_number_encrypted=?, use_count=?, use_date=?," |
1475 "date_modified=?, origin=?, billing_address_id=?" | 1488 "date_modified=?, origin=?, billing_address_id=?" |
1476 "WHERE guid=?1")); | 1489 "WHERE guid=?1")); |
1477 BindCreditCardToStatement(credit_card, | 1490 BindCreditCardToStatement(credit_card, |
1478 update_modification_date | 1491 update_modification_date |
1479 ? AutofillClock::Now() | 1492 ? AutofillClock::Now() |
1480 : old_credit_card->modification_date(), | 1493 : old_credit_card->modification_date(), |
1481 &s); | 1494 &s, *autofill_table_encryptor_); |
1482 | 1495 |
1483 bool result = s.Run(); | 1496 bool result = s.Run(); |
1484 DCHECK_GT(db_->GetLastChangeCount(), 0); | 1497 DCHECK_GT(db_->GetLastChangeCount(), 0); |
1485 return result; | 1498 return result; |
1486 } | 1499 } |
1487 | 1500 |
1488 bool AutofillTable::RemoveCreditCard(const std::string& guid) { | 1501 bool AutofillTable::RemoveCreditCard(const std::string& guid) { |
1489 DCHECK(base::IsValidGUID(guid)); | 1502 DCHECK(base::IsValidGUID(guid)); |
1490 sql::Statement s(db_->GetUniqueStatement( | 1503 sql::Statement s(db_->GetUniqueStatement( |
1491 "DELETE FROM credit_cards WHERE guid = ?")); | 1504 "DELETE FROM credit_cards WHERE guid = ?")); |
(...skipping 1034 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2526 if (!db_->Execute("DROP TABLE masked_credit_cards") || | 2539 if (!db_->Execute("DROP TABLE masked_credit_cards") || |
2527 !db_->Execute("ALTER TABLE masked_credit_cards_temp " | 2540 !db_->Execute("ALTER TABLE masked_credit_cards_temp " |
2528 "RENAME TO masked_credit_cards")) { | 2541 "RENAME TO masked_credit_cards")) { |
2529 return false; | 2542 return false; |
2530 } | 2543 } |
2531 | 2544 |
2532 return transaction.Commit(); | 2545 return transaction.Commit(); |
2533 } | 2546 } |
2534 | 2547 |
2535 } // namespace autofill | 2548 } // namespace autofill |
OLD | NEW |