Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(239)

Side by Side Diff: components/autofill/core/browser/webdata/autofill_table.cc

Issue 962583003: Raze old WebDatabases. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <algorithm> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 #include <map> 10 #include <map>
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 UnencryptedCardFromColumn(s, index++)); 182 UnencryptedCardFromColumn(s, index++));
183 credit_card->set_use_count(s.ColumnInt64(index++)); 183 credit_card->set_use_count(s.ColumnInt64(index++));
184 credit_card->set_use_date(base::Time::FromTimeT(s.ColumnInt64(index++))); 184 credit_card->set_use_date(base::Time::FromTimeT(s.ColumnInt64(index++)));
185 credit_card->set_modification_date( 185 credit_card->set_modification_date(
186 base::Time::FromTimeT(s.ColumnInt64(index++))); 186 base::Time::FromTimeT(s.ColumnInt64(index++)));
187 credit_card->set_origin(s.ColumnString(index++)); 187 credit_card->set_origin(s.ColumnString(index++));
188 188
189 return credit_card.Pass(); 189 return credit_card.Pass();
190 } 190 }
191 191
192 // Obsolete version of AddAutofillProfileNamesToProfile, but still needed
193 // for MigrateToVersion37MergeAndCullOlderProfiles().
194 bool AddAutofillProfileNamesToProfileForVersion37(sql::Connection* db,
195 AutofillProfile* profile) {
196 sql::Statement s(db->GetUniqueStatement(
197 "SELECT guid, first_name, middle_name, last_name "
198 "FROM autofill_profile_names "
199 "WHERE guid=?"));
200 s.BindString(0, profile->guid());
201
202 if (!s.is_valid())
203 return false;
204
205 std::vector<base::string16> first_names;
206 std::vector<base::string16> middle_names;
207 std::vector<base::string16> last_names;
208 while (s.Step()) {
209 DCHECK_EQ(profile->guid(), s.ColumnString(0));
210 first_names.push_back(s.ColumnString16(1));
211 middle_names.push_back(s.ColumnString16(2));
212 last_names.push_back(s.ColumnString16(3));
213 }
214 if (!s.Succeeded())
215 return false;
216
217 profile->SetRawMultiInfo(NAME_FIRST, first_names);
218 profile->SetRawMultiInfo(NAME_MIDDLE, middle_names);
219 profile->SetRawMultiInfo(NAME_LAST, last_names);
220 return true;
221 }
222
223 bool AddAutofillProfileNamesToProfile(sql::Connection* db, 192 bool AddAutofillProfileNamesToProfile(sql::Connection* db,
224 AutofillProfile* profile) { 193 AutofillProfile* profile) {
225 sql::Statement s(db->GetUniqueStatement( 194 sql::Statement s(db->GetUniqueStatement(
226 "SELECT guid, first_name, middle_name, last_name, full_name " 195 "SELECT guid, first_name, middle_name, last_name, full_name "
227 "FROM autofill_profile_names " 196 "FROM autofill_profile_names "
228 "WHERE guid=?")); 197 "WHERE guid=?"));
229 s.BindString(0, profile->guid()); 198 s.BindString(0, profile->guid());
230 199
231 if (!s.is_valid()) 200 if (!s.is_valid())
232 return false; 201 return false;
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 DCHECK_EQ(profile->guid(), s.ColumnString(0)); 260 DCHECK_EQ(profile->guid(), s.ColumnString(0));
292 numbers.push_back(s.ColumnString16(1)); 261 numbers.push_back(s.ColumnString16(1));
293 } 262 }
294 if (!s.Succeeded()) 263 if (!s.Succeeded())
295 return false; 264 return false;
296 265
297 profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers); 266 profile->SetRawMultiInfo(PHONE_HOME_WHOLE_NUMBER, numbers);
298 return true; 267 return true;
299 } 268 }
300 269
301 // Obsolete version of AddAutofillProfileNames needed for
302 // MigrateToVersion33ProfilesBasedOnFirstName() and
303 // MigrateToVersion37MergeAndCullOlderProfiles().
304 bool AddAutofillProfileNamesForVersion3x(
305 const AutofillProfile& profile,
306 sql::Connection* db) {
307 std::vector<base::string16> first_names;
308 profile.GetRawMultiInfo(NAME_FIRST, &first_names);
309 std::vector<base::string16> middle_names;
310 profile.GetRawMultiInfo(NAME_MIDDLE, &middle_names);
311 std::vector<base::string16> last_names;
312 profile.GetRawMultiInfo(NAME_LAST, &last_names);
313 DCHECK_EQ(first_names.size(), middle_names.size());
314 DCHECK_EQ(first_names.size(), last_names.size());
315
316 for (size_t i = 0; i < first_names.size(); ++i) {
317 // Add the new name.
318 sql::Statement s(db->GetUniqueStatement(
319 "INSERT INTO autofill_profile_names"
320 " (guid, first_name, middle_name, last_name) "
321 "VALUES (?,?,?,?)"));
322 s.BindString(0, profile.guid());
323 s.BindString16(1, first_names[i]);
324 s.BindString16(2, middle_names[i]);
325 s.BindString16(3, last_names[i]);
326
327 if (!s.Run())
328 return false;
329 }
330 return true;
331 }
332
333 bool AddAutofillProfileNames(const AutofillProfile& profile, 270 bool AddAutofillProfileNames(const AutofillProfile& profile,
334 sql::Connection* db) { 271 sql::Connection* db) {
335 std::vector<base::string16> first_names; 272 std::vector<base::string16> first_names;
336 profile.GetRawMultiInfo(NAME_FIRST, &first_names); 273 profile.GetRawMultiInfo(NAME_FIRST, &first_names);
337 std::vector<base::string16> middle_names; 274 std::vector<base::string16> middle_names;
338 profile.GetRawMultiInfo(NAME_MIDDLE, &middle_names); 275 profile.GetRawMultiInfo(NAME_MIDDLE, &middle_names);
339 std::vector<base::string16> last_names; 276 std::vector<base::string16> last_names;
340 profile.GetRawMultiInfo(NAME_LAST, &last_names); 277 profile.GetRawMultiInfo(NAME_LAST, &last_names);
341 std::vector<base::string16> full_names; 278 std::vector<base::string16> full_names;
342 profile.GetRawMultiInfo(NAME_FULL, &full_names); 279 profile.GetRawMultiInfo(NAME_FULL, &full_names);
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
504 } 441 }
505 442
506 bool AutofillTable::IsSyncable() { 443 bool AutofillTable::IsSyncable() {
507 return true; 444 return true;
508 } 445 }
509 446
510 bool AutofillTable::MigrateToVersion(int version, 447 bool AutofillTable::MigrateToVersion(int version,
511 bool* update_compatible_version) { 448 bool* update_compatible_version) {
512 // Migrate if necessary. 449 // Migrate if necessary.
513 switch (version) { 450 switch (version) {
514 case 22:
515 return MigrateToVersion22ClearAutofillEmptyValueElements();
516 case 23:
517 return MigrateToVersion23AddCardNumberEncryptedColumn();
518 case 24:
519 return MigrateToVersion24CleanupOversizedStringFields();
520 case 27:
521 *update_compatible_version = true;
522 return MigrateToVersion27UpdateLegacyCreditCards();
523 case 30:
524 *update_compatible_version = true;
525 return MigrateToVersion30AddDateModifed();
526 case 31:
527 *update_compatible_version = true;
528 return MigrateToVersion31AddGUIDToCreditCardsAndProfiles();
529 case 32:
530 *update_compatible_version = true;
531 return MigrateToVersion32UpdateProfilesAndCreditCards();
532 case 33:
533 *update_compatible_version = true;
534 return MigrateToVersion33ProfilesBasedOnFirstName();
535 case 34:
536 *update_compatible_version = true;
537 return MigrateToVersion34ProfilesBasedOnCountryCode();
538 case 35:
539 *update_compatible_version = true;
540 return MigrateToVersion35GreatBritainCountryCodes();
541 // Combine migrations 36 and 37. This is due to enhancements to the merge
542 // step when migrating profiles. The original migration from 35 to 36 did
543 // not merge profiles with identical addresses, but the migration from 36 to
544 // 37 does. The step from 35 to 36 should only happen on the Chrome 12 dev
545 // channel. Chrome 12 beta and release users will jump from 35 to 37
546 // directly getting the full benefits of the multi-valued merge as well as
547 // the culling of bad data.
548 case 37:
549 *update_compatible_version = true;
550 return MigrateToVersion37MergeAndCullOlderProfiles();
551 case 51:
552 // Combine migrations 50 and 51. The migration code from version 49 to 50
553 // worked correctly for users with existing 'origin' columns, but failed
554 // to create these columns for new users.
555 return MigrateToVersion51AddOriginColumn();
556 case 54: 451 case 54:
557 *update_compatible_version = true; 452 *update_compatible_version = true;
558 return MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields(); 453 return MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields();
559 case 55: 454 case 55:
560 *update_compatible_version = true; 455 *update_compatible_version = true;
561 return MigrateToVersion55MergeAutofillDatesTable(); 456 return MigrateToVersion55MergeAutofillDatesTable();
562 case 56: 457 case 56:
563 *update_compatible_version = true; 458 *update_compatible_version = true;
564 return MigrateToVersion56AddProfileLanguageCodeForFormatting(); 459 return MigrateToVersion56AddProfileLanguageCodeForFormatting();
565 case 57: 460 case 57:
(...skipping 1222 matching lines...) Expand 10 before | Expand all | Expand 10 after
1788 "sorting_code VARCHAR," 1683 "sorting_code VARCHAR,"
1789 "country_code VARCHAR," 1684 "country_code VARCHAR,"
1790 "language_code VARCHAR)")) { 1685 "language_code VARCHAR)")) {
1791 NOTREACHED(); 1686 NOTREACHED();
1792 return false; 1687 return false;
1793 } 1688 }
1794 } 1689 }
1795 return true; 1690 return true;
1796 } 1691 }
1797 1692
1798 bool AutofillTable::MigrateToVersion22ClearAutofillEmptyValueElements() {
1799 if (!db_->DoesTableExist("autofill") &&
1800 (!db_->Execute("CREATE TABLE autofill ("
1801 " name VARCHAR,"
1802 " value VARCHAR,"
1803 " value_lower VARCHAR,"
1804 " pair_id INTEGER PRIMARY KEY,"
1805 " count INTEGER DEFAULT 1)") ||
1806 !db_->Execute("CREATE INDEX autofill_name ON autofill (name)") ||
1807 !db_->Execute("CREATE INDEX autofill_name_value_lower ON"
1808 " autofill (name, value_lower)") ||
1809 !db_->Execute("CREATE TABLE autofill_dates ("
1810 " pair_id INTEGER DEFAULT 0,"
1811 " date_created INTEGER DEFAULT 0)") ||
1812 !db_->Execute("CREATE INDEX autofill_dates_pair_id ON"
1813 " autofill (pair_id)")))
1814 return false;
1815
1816
1817 sql::Statement s(db_->GetUniqueStatement(
1818 "SELECT pair_id FROM autofill WHERE TRIM(value) = \"\""));
1819 if (!s.is_valid())
1820 return false;
1821
1822 std::set<int64> ids;
1823 while (s.Step())
1824 ids.insert(s.ColumnInt64(0));
1825 if (!s.Succeeded())
1826 return false;
1827
1828 if (!db_->Execute("DELETE FROM autofill WHERE TRIM(value) = \"\""))
1829 return false;
1830
1831 for (std::set<int64>::const_iterator it = ids.begin(); it != ids.end();
1832 ++it) {
1833 sql::Statement s(db_->GetUniqueStatement(
1834 "DELETE FROM autofill_dates WHERE pair_id = ?"));
1835 s.BindInt64(0, *it);
1836 if (!s.Run())
1837 return false;
1838 }
1839
1840 return true;
1841 }
1842
1843 // Add the card_number_encrypted column if credit card table was not
1844 // created in this build (otherwise the column already exists).
1845 // WARNING: Do not change the order of the execution of the SQL
1846 // statements in this case! Profile corruption and data migration
1847 // issues WILL OCCUR. See http://crbug.com/10913
1848 //
1849 // The problem is that if a user has a profile which was created before
1850 // r37036, when the credit_cards table was added, and then failed to
1851 // update this profile between the credit card addition and the addition
1852 // of the "encrypted" columns (44963), the next data migration will put
1853 // the user's profile in an incoherent state: The user will update from
1854 // a data profile set to be earlier than 22, and therefore pass through
1855 // this update case. But because the user did not have a credit_cards
1856 // table before starting Chrome, it will have just been initialized
1857 // above, and so already have these columns -- and thus this data
1858 // update step will have failed.
1859 //
1860 // The false assumption in this case is that at this step in the
1861 // migration, the user has a credit card table, and that this
1862 // table does not include encrypted columns!
1863 // Because this case does not roll back the complete set of SQL
1864 // transactions properly in case of failure (that is, it does not
1865 // roll back the table initialization done above), the incoherent
1866 // profile will now see itself as being at version 22 -- but include a
1867 // fully initialized credit_cards table. Every time Chrome runs, it
1868 // will try to update the web database and fail at this step, unless
1869 // we allow for the faulty assumption described above by checking for
1870 // the existence of the columns only AFTER we've executed the commands
1871 // to add them.
1872 bool AutofillTable::MigrateToVersion23AddCardNumberEncryptedColumn() {
1873 if (!db_->DoesTableExist("autofill_profiles") &&
1874 (!db_->Execute("CREATE TABLE autofill_profiles ( "
1875 "label VARCHAR, "
1876 "unique_id INTEGER PRIMARY KEY, "
1877 "first_name VARCHAR, "
1878 "middle_name VARCHAR, "
1879 "last_name VARCHAR, "
1880 "email VARCHAR, "
1881 "company_name VARCHAR, "
1882 "address_line_1 VARCHAR, "
1883 "address_line_2 VARCHAR, "
1884 "city VARCHAR, "
1885 "state VARCHAR, "
1886 "zipcode VARCHAR, "
1887 "country VARCHAR, "
1888 "phone VARCHAR, "
1889 "fax VARCHAR)") ||
1890 !db_->Execute("CREATE INDEX autofill_profiles_label_index"
1891 " ON autofill_profiles (label)")))
1892 return false;
1893
1894 if (!db_->DoesTableExist("credit_cards") &&
1895 (!db_->Execute("CREATE TABLE credit_cards ( "
1896 "label VARCHAR, "
1897 "unique_id INTEGER PRIMARY KEY, "
1898 "name_on_card VARCHAR, "
1899 "type VARCHAR, "
1900 "card_number VARCHAR, "
1901 "expiration_month INTEGER, "
1902 "expiration_year INTEGER, "
1903 "verification_code VARCHAR, "
1904 "billing_address VARCHAR, "
1905 "shipping_address VARCHAR)") ||
1906 !db_->Execute("CREATE INDEX credit_cards_label_index"
1907 " ON credit_cards (label)")))
1908 return false;
1909
1910 if (!db_->DoesColumnExist("credit_cards", "card_number_encrypted")) {
1911 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
1912 "card_number_encrypted BLOB DEFAULT NULL")) {
1913 return false;
1914 }
1915 }
1916
1917 if (!db_->DoesColumnExist("credit_cards", "verification_code_encrypted")) {
1918 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
1919 "verification_code_encrypted BLOB DEFAULT NULL")) {
1920 return false;
1921 }
1922 }
1923
1924 return true;
1925 }
1926
1927 // One-time cleanup for http://crbug.com/38364 - In the presence of
1928 // multi-byte UTF-8 characters, that bug could cause Autofill strings
1929 // to grow larger and more corrupt with each save. The cleanup removes
1930 // any row with a string field larger than a reasonable size. The string
1931 // fields examined here are precisely the ones that were subject to
1932 // corruption by the original bug.
1933 bool AutofillTable::MigrateToVersion24CleanupOversizedStringFields() {
1934 const std::string autofill_is_too_big =
1935 "max(length(name), length(value)) > 500";
1936
1937 const std::string credit_cards_is_too_big =
1938 "max(length(label), length(name_on_card), length(type), "
1939 " length(expiration_month), length(expiration_year), "
1940 " length(billing_address), length(shipping_address) "
1941 ") > 500";
1942
1943 const std::string autofill_profiles_is_too_big =
1944 "max(length(label), length(first_name), "
1945 " length(middle_name), length(last_name), length(email), "
1946 " length(company_name), length(address_line_1), "
1947 " length(address_line_2), length(city), length(state), "
1948 " length(zipcode), length(country), length(phone)) > 500";
1949
1950 std::string query = "DELETE FROM autofill_dates WHERE pair_id IN ("
1951 "SELECT pair_id FROM autofill WHERE " + autofill_is_too_big + ")";
1952
1953 if (!db_->Execute(query.c_str()))
1954 return false;
1955
1956 query = "DELETE FROM autofill WHERE " + autofill_is_too_big;
1957
1958 if (!db_->Execute(query.c_str()))
1959 return false;
1960
1961 // Only delete from legacy credit card tables where specific columns exist.
1962 if (db_->DoesColumnExist("credit_cards", "label") &&
1963 db_->DoesColumnExist("credit_cards", "name_on_card") &&
1964 db_->DoesColumnExist("credit_cards", "type") &&
1965 db_->DoesColumnExist("credit_cards", "expiration_month") &&
1966 db_->DoesColumnExist("credit_cards", "expiration_year") &&
1967 db_->DoesColumnExist("credit_cards", "billing_address") &&
1968 db_->DoesColumnExist("credit_cards", "shipping_address") &&
1969 db_->DoesColumnExist("autofill_profiles", "label")) {
1970 query = "DELETE FROM credit_cards WHERE (" + credit_cards_is_too_big +
1971 ") OR label IN (SELECT label FROM autofill_profiles WHERE " +
1972 autofill_profiles_is_too_big + ")";
1973
1974 if (!db_->Execute(query.c_str()))
1975 return false;
1976 }
1977
1978 if (db_->DoesColumnExist("autofill_profiles", "label")) {
1979 query = "DELETE FROM autofill_profiles WHERE " +
1980 autofill_profiles_is_too_big;
1981
1982 if (!db_->Execute(query.c_str()))
1983 return false;
1984 }
1985
1986 return true;
1987 }
1988
1989 // Change the credit_cards.billing_address column from a string to an
1990 // int. The stored string is the label of an address, so we have to
1991 // select the unique ID of this address using the label as a foreign
1992 // key into the |autofill_profiles| table.
1993 bool AutofillTable::MigrateToVersion27UpdateLegacyCreditCards() {
1994 // Only migrate from legacy credit card tables where specific columns
1995 // exist.
1996 if (!(db_->DoesColumnExist("credit_cards", "unique_id") &&
1997 db_->DoesColumnExist("credit_cards", "billing_address") &&
1998 db_->DoesColumnExist("autofill_profiles", "unique_id"))) {
1999 return true;
2000 }
2001
2002 std::string stmt =
2003 "SELECT credit_cards.unique_id, autofill_profiles.unique_id "
2004 "FROM autofill_profiles, credit_cards "
2005 "WHERE credit_cards.billing_address = autofill_profiles.label";
2006 sql::Statement s(db_->GetUniqueStatement(stmt.c_str()));
2007
2008 std::map<int, int> cc_billing_map;
2009 while (s.Step())
2010 cc_billing_map[s.ColumnInt(0)] = s.ColumnInt(1);
2011 if (!s.Succeeded())
2012 return false;
2013
2014 // Windows already stores the IDs as strings in |billing_address|. Try
2015 // to convert those.
2016 if (cc_billing_map.empty()) {
2017 std::string stmt = "SELECT unique_id,billing_address FROM credit_cards";
2018 sql::Statement s(db_->GetUniqueStatement(stmt.c_str()));
2019
2020 while (s.Step()) {
2021 int id = 0;
2022 if (base::StringToInt(s.ColumnString(1), &id))
2023 cc_billing_map[s.ColumnInt(0)] = id;
2024 }
2025 if (!s.Succeeded())
2026 return false;
2027 }
2028
2029 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
2030 "label VARCHAR, "
2031 "unique_id INTEGER PRIMARY KEY, "
2032 "name_on_card VARCHAR, "
2033 "type VARCHAR, "
2034 "card_number VARCHAR, "
2035 "expiration_month INTEGER, "
2036 "expiration_year INTEGER, "
2037 "verification_code VARCHAR, "
2038 "billing_address INTEGER, "
2039 "shipping_address VARCHAR, "
2040 "card_number_encrypted BLOB, "
2041 "verification_code_encrypted BLOB)")) {
2042 return false;
2043 }
2044
2045 if (!db_->Execute(
2046 "INSERT INTO credit_cards_temp "
2047 "SELECT label,unique_id,name_on_card,type,card_number,"
2048 "expiration_month,expiration_year,verification_code,0,"
2049 "shipping_address,card_number_encrypted,"
2050 "verification_code_encrypted FROM credit_cards")) {
2051 return false;
2052 }
2053
2054 if (!db_->Execute("DROP TABLE credit_cards"))
2055 return false;
2056
2057 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
2058 return false;
2059
2060 for (std::map<int, int>::const_iterator iter = cc_billing_map.begin();
2061 iter != cc_billing_map.end(); ++iter) {
2062 sql::Statement s(db_->GetCachedStatement(
2063 SQL_FROM_HERE,
2064 "UPDATE credit_cards SET billing_address=? WHERE unique_id=?"));
2065 s.BindInt(0, (*iter).second);
2066 s.BindInt(1, (*iter).first);
2067
2068 if (!s.Run())
2069 return false;
2070 }
2071
2072 return true;
2073 }
2074
2075 bool AutofillTable::MigrateToVersion30AddDateModifed() {
2076 // Add date_modified to autofill_profiles.
2077 if (!db_->DoesColumnExist("autofill_profiles", "date_modified")) {
2078 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
2079 "date_modified INTEGER NON NULL DEFAULT 0")) {
2080 return false;
2081 }
2082
2083 sql::Statement s(db_->GetUniqueStatement(
2084 "UPDATE autofill_profiles SET date_modified=?"));
2085 s.BindInt64(0, Time::Now().ToTimeT());
2086
2087 if (!s.Run())
2088 return false;
2089 }
2090
2091 // Add date_modified to credit_cards.
2092 if (!db_->DoesColumnExist("credit_cards", "date_modified")) {
2093 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
2094 "date_modified INTEGER NON NULL DEFAULT 0")) {
2095 return false;
2096 }
2097
2098 sql::Statement s(db_->GetUniqueStatement(
2099 "UPDATE credit_cards SET date_modified=?"));
2100 s.BindInt64(0, Time::Now().ToTimeT());
2101
2102 if (!s.Run())
2103 return false;
2104 }
2105
2106 return true;
2107 }
2108
2109 bool AutofillTable::MigrateToVersion31AddGUIDToCreditCardsAndProfiles() {
2110 // Note that we need to check for the guid column's existence due to the
2111 // fact that for a version 22 database the |autofill_profiles| table
2112 // gets created fresh with |InitAutofillProfilesTable|.
2113 if (!db_->DoesColumnExist("autofill_profiles", "guid")) {
2114 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
2115 "guid VARCHAR NOT NULL DEFAULT \"\"")) {
2116 return false;
2117 }
2118
2119 // Set all the |guid| fields to valid values.
2120
2121 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id "
2122 "FROM autofill_profiles"));
2123
2124 while (s.Step()) {
2125 sql::Statement update_s(
2126 db_->GetUniqueStatement("UPDATE autofill_profiles "
2127 "SET guid=? WHERE unique_id=?"));
2128 update_s.BindString(0, base::GenerateGUID());
2129 update_s.BindInt(1, s.ColumnInt(0));
2130
2131 if (!update_s.Run())
2132 return false;
2133 }
2134 if (!s.Succeeded())
2135 return false;
2136 }
2137
2138 // Note that we need to check for the guid column's existence due to the
2139 // fact that for a version 22 database the |autofill_profiles| table
2140 // gets created fresh with |InitAutofillProfilesTable|.
2141 if (!db_->DoesColumnExist("credit_cards", "guid")) {
2142 if (!db_->Execute("ALTER TABLE credit_cards ADD COLUMN "
2143 "guid VARCHAR NOT NULL DEFAULT \"\"")) {
2144 return false;
2145 }
2146
2147 // Set all the |guid| fields to valid values.
2148
2149 sql::Statement s(db_->GetUniqueStatement("SELECT unique_id "
2150 "FROM credit_cards"));
2151
2152 while (s.Step()) {
2153 sql::Statement update_s(
2154 db_->GetUniqueStatement("UPDATE credit_cards "
2155 "set guid=? WHERE unique_id=?"));
2156 update_s.BindString(0, base::GenerateGUID());
2157 update_s.BindInt(1, s.ColumnInt(0));
2158
2159 if (!update_s.Run())
2160 return false;
2161 }
2162 if (!s.Succeeded())
2163 return false;
2164 }
2165
2166 return true;
2167 }
2168
2169 bool AutofillTable::MigrateToVersion32UpdateProfilesAndCreditCards() {
2170 if (db_->DoesColumnExist("autofill_profiles", "unique_id")) {
2171 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( "
2172 "guid VARCHAR PRIMARY KEY, "
2173 "label VARCHAR, "
2174 "first_name VARCHAR, "
2175 "middle_name VARCHAR, "
2176 "last_name VARCHAR, "
2177 "email VARCHAR, "
2178 "company_name VARCHAR, "
2179 "address_line_1 VARCHAR, "
2180 "address_line_2 VARCHAR, "
2181 "city VARCHAR, "
2182 "state VARCHAR, "
2183 "zipcode VARCHAR, "
2184 "country VARCHAR, "
2185 "phone VARCHAR, "
2186 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
2187 return false;
2188 }
2189
2190 if (!db_->Execute(
2191 "INSERT INTO autofill_profiles_temp "
2192 "SELECT guid, label, first_name, middle_name, last_name, email, "
2193 "company_name, address_line_1, address_line_2, city, state, "
2194 "zipcode, country, phone, date_modified "
2195 "FROM autofill_profiles")) {
2196 return false;
2197 }
2198
2199 if (!db_->Execute("DROP TABLE autofill_profiles"))
2200 return false;
2201
2202 if (!db_->Execute(
2203 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
2204 return false;
2205 }
2206 }
2207
2208 if (db_->DoesColumnExist("credit_cards", "unique_id")) {
2209 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
2210 "guid VARCHAR PRIMARY KEY, "
2211 "label VARCHAR, "
2212 "name_on_card VARCHAR, "
2213 "expiration_month INTEGER, "
2214 "expiration_year INTEGER, "
2215 "card_number_encrypted BLOB, "
2216 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
2217 return false;
2218 }
2219
2220 if (!db_->Execute(
2221 "INSERT INTO credit_cards_temp "
2222 "SELECT guid, label, name_on_card, expiration_month, "
2223 "expiration_year, card_number_encrypted, date_modified "
2224 "FROM credit_cards")) {
2225 return false;
2226 }
2227
2228 if (!db_->Execute("DROP TABLE credit_cards"))
2229 return false;
2230
2231 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
2232 return false;
2233 }
2234
2235 return true;
2236 }
2237
2238 // Test the existence of the |first_name| column as an indication that
2239 // we need a migration. It is possible that the new |autofill_profiles|
2240 // schema is in place because the table was newly created when migrating
2241 // from a pre-version-22 database.
2242 bool AutofillTable::MigrateToVersion33ProfilesBasedOnFirstName() {
2243 if (!db_->DoesTableExist("autofill_profile_names") &&
2244 !db_->Execute("CREATE TABLE autofill_profile_names ( "
2245 "guid VARCHAR, "
2246 "first_name VARCHAR, "
2247 "middle_name VARCHAR, "
2248 "last_name VARCHAR)"))
2249 return false;
2250
2251 if (!db_->DoesTableExist("autofill_profile_emails") &&
2252 !db_->Execute("CREATE TABLE autofill_profile_emails ( "
2253 "guid VARCHAR, "
2254 "email VARCHAR)"))
2255 return false;
2256
2257 if (!db_->DoesTableExist("autofill_profile_phones") &&
2258 !db_->Execute("CREATE TABLE autofill_profile_phones ( "
2259 "guid VARCHAR, "
2260 "type INTEGER DEFAULT 0, "
2261 "number VARCHAR)"))
2262 return false;
2263
2264 if (db_->DoesColumnExist("autofill_profiles", "first_name")) {
2265 // Create autofill_profiles_temp table that will receive the data.
2266 if (!db_->DoesTableExist("autofill_profiles_temp")) {
2267 if (!db_->Execute("CREATE TABLE autofill_profiles_temp ( "
2268 "guid VARCHAR PRIMARY KEY, "
2269 "company_name VARCHAR, "
2270 "address_line_1 VARCHAR, "
2271 "address_line_2 VARCHAR, "
2272 "city VARCHAR, "
2273 "state VARCHAR, "
2274 "zipcode VARCHAR, "
2275 "country VARCHAR, "
2276 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
2277 return false;
2278 }
2279 }
2280
2281 sql::Statement s(db_->GetUniqueStatement(
2282 "SELECT guid, first_name, middle_name, last_name, email, "
2283 "company_name, address_line_1, address_line_2, city, state, "
2284 "zipcode, country, phone, date_modified "
2285 "FROM autofill_profiles"));
2286
2287 while (s.Step()) {
2288 AutofillProfile profile;
2289 int index = 0;
2290 profile.set_guid(s.ColumnString(index++));
2291 DCHECK(base::IsValidGUID(profile.guid()));
2292
2293 profile.SetRawInfo(NAME_FIRST, s.ColumnString16(index++));
2294 profile.SetRawInfo(NAME_MIDDLE, s.ColumnString16(index++));
2295 profile.SetRawInfo(NAME_LAST, s.ColumnString16(index++));
2296 profile.SetRawInfo(EMAIL_ADDRESS, s.ColumnString16(index++));
2297 profile.SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
2298 profile.SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(index++));
2299 profile.SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(index++));
2300 profile.SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++));
2301 profile.SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++));
2302 profile.SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++));
2303 profile.SetInfo(AutofillType(ADDRESS_HOME_COUNTRY),
2304 s.ColumnString16(index++), app_locale_);
2305 profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, s.ColumnString16(index++));
2306 int64 date_modified = s.ColumnInt64(index++);
2307
2308 sql::Statement s_insert(db_->GetUniqueStatement(
2309 "INSERT INTO autofill_profiles_temp"
2310 "(guid, company_name, address_line_1, address_line_2, city,"
2311 " state, zipcode, country, date_modified)"
2312 "VALUES (?,?,?,?,?,?,?,?,?)"));
2313 index = 0;
2314 s_insert.BindString(index++, profile.guid());
2315 s_insert.BindString16(index++, profile.GetRawInfo(COMPANY_NAME));
2316 s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_LINE1));
2317 s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_LINE2));
2318 s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_CITY));
2319 s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_STATE));
2320 s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_ZIP));
2321 s_insert.BindString16(index++, profile.GetRawInfo(ADDRESS_HOME_COUNTRY));
2322 s_insert.BindInt64(index++, date_modified);
2323
2324 if (!s_insert.Run())
2325 return false;
2326
2327 // Add the other bits: names, emails, and phone numbers.
2328 if (!AddAutofillProfileNamesForVersion3x(profile, db_) ||
2329 !AddAutofillProfileEmails(profile, db_) ||
2330 !AddAutofillProfilePhones(profile, db_)) {
2331 return false;
2332 }
2333 } // endwhile
2334 if (!s.Succeeded())
2335 return false;
2336
2337 if (!db_->Execute("DROP TABLE autofill_profiles"))
2338 return false;
2339
2340 if (!db_->Execute(
2341 "ALTER TABLE autofill_profiles_temp RENAME TO autofill_profiles")) {
2342 return false;
2343 }
2344 }
2345
2346 // Remove the labels column from the credit_cards table.
2347 if (db_->DoesColumnExist("credit_cards", "label")) {
2348 if (!db_->Execute("CREATE TABLE credit_cards_temp ( "
2349 "guid VARCHAR PRIMARY KEY, "
2350 "name_on_card VARCHAR, "
2351 "expiration_month INTEGER, "
2352 "expiration_year INTEGER, "
2353 "card_number_encrypted BLOB, "
2354 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
2355 return false;
2356 }
2357
2358 if (!db_->Execute(
2359 "INSERT INTO credit_cards_temp "
2360 "SELECT guid, name_on_card, expiration_month, "
2361 "expiration_year, card_number_encrypted, date_modified "
2362 "FROM credit_cards")) {
2363 return false;
2364 }
2365
2366 if (!db_->Execute("DROP TABLE credit_cards"))
2367 return false;
2368
2369 if (!db_->Execute("ALTER TABLE credit_cards_temp RENAME TO credit_cards"))
2370 return false;
2371 }
2372
2373 return true;
2374 }
2375
2376 // Test the existence of the |country_code| column as an indication that
2377 // we need a migration. It is possible that the new |autofill_profiles|
2378 // schema is in place because the table was newly created when migrating
2379 // from a pre-version-22 database.
2380 bool AutofillTable::MigrateToVersion34ProfilesBasedOnCountryCode() {
2381 if (!db_->DoesColumnExist("autofill_profiles", "country_code")) {
2382 if (!db_->Execute("ALTER TABLE autofill_profiles ADD COLUMN "
2383 "country_code VARCHAR")) {
2384 return false;
2385 }
2386
2387 // Set all the |country_code| fields to match existing |country| values.
2388 sql::Statement s(db_->GetUniqueStatement("SELECT guid, country "
2389 "FROM autofill_profiles"));
2390
2391 while (s.Step()) {
2392 sql::Statement update_s(
2393 db_->GetUniqueStatement("UPDATE autofill_profiles "
2394 "SET country_code=? WHERE guid=?"));
2395
2396 base::string16 country = s.ColumnString16(1);
2397 update_s.BindString(0, AutofillCountry::GetCountryCode(country,
2398 app_locale_));
2399 update_s.BindString(1, s.ColumnString(0));
2400
2401 if (!update_s.Run())
2402 return false;
2403 }
2404 if (!s.Succeeded())
2405 return false;
2406 }
2407
2408 return true;
2409 }
2410
2411 // Correct all country codes with value "UK" to be "GB". This data
2412 // was mistakenly introduced in build 686.0. This migration is to clean
2413 // it up. See http://crbug.com/74511 for details.
2414 bool AutofillTable::MigrateToVersion35GreatBritainCountryCodes() {
2415 sql::Statement s(db_->GetUniqueStatement(
2416 "UPDATE autofill_profiles SET country_code=\"GB\" "
2417 "WHERE country_code=\"UK\""));
2418
2419 return s.Run();
2420 }
2421
2422 // Merge and cull older profiles where possible.
2423 bool AutofillTable::MigrateToVersion37MergeAndCullOlderProfiles() {
2424 if (!db_->DoesTableExist("autofill_profiles_trash") &&
2425 !db_->Execute("CREATE TABLE autofill_profiles_trash (guid VARCHAR)"))
2426 return false;
2427
2428 sql::Statement s(db_->GetUniqueStatement(
2429 "SELECT guid, date_modified FROM autofill_profiles"));
2430
2431 // Accumulate the good profiles.
2432 std::vector<AutofillProfile> accumulated_profiles;
2433 std::vector<AutofillProfile*> accumulated_profiles_p;
2434 std::map<std::string, int64> modification_map;
2435 while (s.Step()) {
2436 std::string guid = s.ColumnString(0);
2437 int64 date_modified = s.ColumnInt64(1);
2438 modification_map.insert(
2439 std::pair<std::string, int64>(guid, date_modified));
2440
2441 sql::Statement s(db_->GetUniqueStatement(
2442 "SELECT guid, company_name, address_line_1, address_line_2, city, "
2443 " state, zipcode, country, country_code, date_modified "
2444 "FROM autofill_profiles "
2445 "WHERE guid=?"));
2446 s.BindString(0, guid);
2447
2448 if (!s.Step())
2449 return false;
2450
2451 scoped_ptr<AutofillProfile> profile(new AutofillProfile);
2452 int index = 0;
2453 profile->set_guid(s.ColumnString(index++));
2454 DCHECK(base::IsValidGUID(profile->guid()));
2455
2456 profile->SetRawInfo(COMPANY_NAME, s.ColumnString16(index++));
2457 profile->SetRawInfo(ADDRESS_HOME_LINE1, s.ColumnString16(index++));
2458 profile->SetRawInfo(ADDRESS_HOME_LINE2, s.ColumnString16(index++));
2459 profile->SetRawInfo(ADDRESS_HOME_CITY, s.ColumnString16(index++));
2460 profile->SetRawInfo(ADDRESS_HOME_STATE, s.ColumnString16(index++));
2461 profile->SetRawInfo(ADDRESS_HOME_ZIP, s.ColumnString16(index++));
2462 // Intentionally skip column 7, which stores the localized country name.
2463 index++;
2464 profile->SetRawInfo(ADDRESS_HOME_COUNTRY, s.ColumnString16(index++));
2465 profile->set_modification_date(
2466 base::Time::FromTimeT(s.ColumnInt64(index++)));
2467 profile->set_origin(s.ColumnString(index++));
2468
2469 // Get associated name info.
2470 AddAutofillProfileNamesToProfileForVersion37(db_, profile.get());
2471
2472 // Get associated email info.
2473 AddAutofillProfileEmailsToProfile(db_, profile.get());
2474
2475 // Get associated phone info.
2476 AddAutofillProfilePhonesToProfile(db_, profile.get());
2477
2478 if (PersonalDataManager::IsValidLearnableProfile(*profile, app_locale_)) {
2479 std::vector<AutofillProfile> merged_profiles;
2480 std::string merged_guid = PersonalDataManager::MergeProfile(
2481 *profile, accumulated_profiles_p, app_locale_, &merged_profiles);
2482
2483 std::swap(accumulated_profiles, merged_profiles);
2484
2485 accumulated_profiles_p.clear();
2486 accumulated_profiles_p.resize(accumulated_profiles.size());
2487 std::transform(accumulated_profiles.begin(),
2488 accumulated_profiles.end(),
2489 accumulated_profiles_p.begin(),
2490 address_of<AutofillProfile>);
2491
2492 // If the profile got merged trash the original.
2493 if (merged_guid != profile->guid())
2494 AddAutofillGUIDToTrash(profile->guid());
2495 } else {
2496 // An invalid profile, so trash it.
2497 AddAutofillGUIDToTrash(profile->guid());
2498 }
2499 } // endwhile
2500 if (!s.Succeeded())
2501 return false;
2502
2503 // Drop the current profiles.
2504 if (!ClearAutofillProfiles())
2505 return false;
2506
2507 // Add the newly merged profiles back in.
2508 for (std::vector<AutofillProfile>::const_iterator
2509 iter = accumulated_profiles.begin();
2510 iter != accumulated_profiles.end();
2511 ++iter) {
2512 // Save the profile with its original modification date.
2513 std::map<std::string, int64>::const_iterator date_item =
2514 modification_map.find(iter->guid());
2515 if (date_item == modification_map.end())
2516 return false;
2517
2518 sql::Statement s(db_->GetUniqueStatement(
2519 "INSERT INTO autofill_profiles"
2520 "(guid, company_name, address_line_1, address_line_2, city, state,"
2521 " zipcode, country, country_code, date_modified)"
2522 "VALUES (?,?,?,?,?,?,?,?,?,?)"));
2523 int index = 0;
2524 s.BindString(index++, iter->guid());
2525 s.BindString16(index++, GetInfo(*iter, COMPANY_NAME));
2526 s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_LINE1));
2527 s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_LINE2));
2528 s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_CITY));
2529 s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_STATE));
2530 s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_ZIP));
2531 s.BindString16(index++, base::string16()); // This column is deprecated.
2532 s.BindString16(index++, GetInfo(*iter, ADDRESS_HOME_COUNTRY));
2533 s.BindInt64(index++, date_item->second);
2534
2535 if (!s.Run())
2536 return false;
2537
2538 if (!AddAutofillProfileNamesForVersion3x(*iter, db_) ||
2539 !AddAutofillProfileEmails(*iter, db_) ||
2540 !AddAutofillProfilePhones(*iter, db_)) {
2541 return false;
2542 }
2543 }
2544
2545 return true;
2546 }
2547
2548 bool AutofillTable::MigrateToVersion51AddOriginColumn() {
2549 sql::Transaction transaction(db_);
2550 if (!transaction.Begin())
2551 return false;
2552
2553 // Add origin to autofill_profiles.
2554 if (!db_->DoesColumnExist("autofill_profiles", "origin") &&
2555 !db_->Execute("ALTER TABLE autofill_profiles "
2556 "ADD COLUMN origin VARCHAR DEFAULT ''")) {
2557 return false;
2558 }
2559
2560 // Add origin to credit_cards.
2561 if (!db_->DoesColumnExist("credit_cards", "origin") &&
2562 !db_->Execute("ALTER TABLE credit_cards "
2563 "ADD COLUMN origin VARCHAR DEFAULT ''")) {
2564 return false;
2565 }
2566
2567 return transaction.Commit();
2568 }
2569
2570 bool AutofillTable::MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields() { 1693 bool AutofillTable::MigrateToVersion54AddI18nFieldsAndRemoveDeprecatedFields() {
2571 sql::Transaction transaction(db_); 1694 sql::Transaction transaction(db_);
2572 if (!transaction.Begin()) 1695 if (!transaction.Begin())
2573 return false; 1696 return false;
2574 1697
2575 // Test the existence of the |address_line_1| column as an indication that a 1698 // Test the existence of the |address_line_1| column as an indication that a
2576 // migration is needed. It is possible that the new |autofill_profile_phones| 1699 // migration is needed. It is possible that the new |autofill_profile_phones|
2577 // schema is in place because the table was newly created when migrating from 1700 // schema is in place because the table was newly created when migrating from
2578 // a pre-version-23 database. 1701 // a pre-version-23 database.
2579 if (db_->DoesColumnExist("autofill_profiles", "address_line_1")) { 1702 if (db_->DoesColumnExist("autofill_profiles", "address_line_1")) {
(...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
2837 if (!db_->DoesColumnExist("unmasked_credit_cards", "use_date") && 1960 if (!db_->DoesColumnExist("unmasked_credit_cards", "use_date") &&
2838 !db_->Execute("ALTER TABLE unmasked_credit_cards ADD COLUMN " 1961 !db_->Execute("ALTER TABLE unmasked_credit_cards ADD COLUMN "
2839 "use_date INTEGER NOT NULL DEFAULT 0")) { 1962 "use_date INTEGER NOT NULL DEFAULT 0")) {
2840 return false; 1963 return false;
2841 } 1964 }
2842 1965
2843 return transaction.Commit(); 1966 return transaction.Commit();
2844 } 1967 }
2845 1968
2846 } // namespace autofill 1969 } // namespace autofill
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698