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

Side by Side Diff: chrome/browser/webdata/web_database.cc

Issue 6676031: Autofill database migration to clean up bogus profiles. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 "chrome/browser/webdata/web_database.h" 5 #include "chrome/browser/webdata/web_database.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <set> 9 #include <set>
10 #include <string> 10 #include <string>
11 11
12 #include "app/sql/statement.h" 12 #include "app/sql/statement.h"
13 #include "app/sql/transaction.h" 13 #include "app/sql/transaction.h"
14 #include "base/string_number_conversions.h" 14 #include "base/string_number_conversions.h"
15 #include "base/string_split.h" 15 #include "base/string_split.h"
16 #include "base/string_util.h" 16 #include "base/string_util.h"
17 #include "base/tuple.h" 17 #include "base/tuple.h"
18 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "chrome/browser/autofill/autofill_country.h" 19 #include "chrome/browser/autofill/autofill_country.h"
20 #include "chrome/browser/autofill/autofill_profile.h" 20 #include "chrome/browser/autofill/autofill_profile.h"
21 #include "chrome/browser/autofill/autofill_type.h" 21 #include "chrome/browser/autofill/autofill_type.h"
22 #include "chrome/browser/autofill/credit_card.h" 22 #include "chrome/browser/autofill/credit_card.h"
23 #include "chrome/browser/autofill/personal_data_manager.h"
23 #include "chrome/browser/diagnostics/sqlite_diagnostics.h" 24 #include "chrome/browser/diagnostics/sqlite_diagnostics.h"
24 #include "chrome/browser/history/history_database.h" 25 #include "chrome/browser/history/history_database.h"
25 #include "chrome/browser/password_manager/encryptor.h" 26 #include "chrome/browser/password_manager/encryptor.h"
26 #include "chrome/browser/search_engines/template_url.h" 27 #include "chrome/browser/search_engines/template_url.h"
27 #include "chrome/browser/webdata/autofill_change.h" 28 #include "chrome/browser/webdata/autofill_change.h"
28 #include "chrome/common/guid.h" 29 #include "chrome/common/guid.h"
29 #include "content/common/notification_service.h" 30 #include "content/common/notification_service.h"
30 #include "third_party/skia/include/core/SkBitmap.h" 31 #include "third_party/skia/include/core/SkBitmap.h"
31 #include "ui/base/l10n/l10n_util.h" 32 #include "ui/base/l10n/l10n_util.h"
32 #include "ui/gfx/codec/png_codec.h" 33 #include "ui/gfx/codec/png_codec.h"
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 // autofill_profile_phones 152 // autofill_profile_phones
152 // This table contains the multi-valued phone fields 153 // This table contains the multi-valued phone fields
153 // associated with a profile. 154 // associated with a profile.
154 // 155 //
155 // guid The guid string that identifies the profile to which 156 // guid The guid string that identifies the profile to which
156 // the phone or fax number belongs. 157 // the phone or fax number belongs.
157 // type An integer constant designating either phone or fax type 158 // type An integer constant designating either phone or fax type
158 // of the number. 159 // of the number.
159 // number 160 // number
160 // 161 //
162 // autofill_profiles_trash
163 // This table contains guids of "trashed" autofill
164 // profiles. When a profile is removed its guid is added
165 // to this table so that Sync can perform deferred removal.
166 //
167 // guid The guid string that identifies the profile to which
168 // the phone or fax number belongs.
Ilya Sherman 2011/03/16 04:58:57 nit: phone/fax is unrelated ;)
dhollowa 2011/03/16 16:13:35 Done.
169 //
161 // credit_cards This table contains credit card data added by the user 170 // credit_cards This table contains credit card data added by the user
162 // with the AutoFill dialog. Most of the columns are 171 // with the AutoFill dialog. Most of the columns are
163 // standard entries in a credit card form. 172 // standard entries in a credit card form.
164 // 173 //
165 // guid A guid string to uniquely identify the profile. 174 // guid A guid string to uniquely identify the profile.
166 // Added in version 31. 175 // Added in version 31.
167 // name_on_card 176 // name_on_card
168 // expiration_month 177 // expiration_month
169 // expiration_year 178 // expiration_year
170 // card_number_encrypted Stores encrypted credit card number. 179 // card_number_encrypted Stores encrypted credit card number.
(...skipping 14 matching lines...) Expand all
185 194
186 using base::Time; 195 using base::Time;
187 196
188 namespace { 197 namespace {
189 198
190 typedef std::vector<Tuple3<int64, string16, string16> > AutofillElementList; 199 typedef std::vector<Tuple3<int64, string16, string16> > AutofillElementList;
191 200
192 // Current version number. Note: when changing the current version number, 201 // Current version number. Note: when changing the current version number,
193 // corresponding changes must happen in the unit tests, and new migration test 202 // corresponding changes must happen in the unit tests, and new migration test
194 // added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|. 203 // added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
195 const int kCurrentVersionNumber = 35; 204 const int kCurrentVersionNumber = 36;
196 const int kCompatibleVersionNumber = 35; 205 const int kCompatibleVersionNumber = 36;
197 206
198 // ID of the url column in keywords. 207 // ID of the url column in keywords.
199 const int kUrlIdPosition = 16; 208 const int kUrlIdPosition = 16;
200 209
201 // Keys used in the meta table. 210 // Keys used in the meta table.
202 const char* kDefaultSearchProviderKey = "Default Search Provider ID"; 211 const char* kDefaultSearchProviderKey = "Default Search Provider ID";
203 const char* kBuiltinKeywordVersion = "Builtin Keyword Version"; 212 const char* kBuiltinKeywordVersion = "Builtin Keyword Version";
204 213
205 // The maximum length allowed for form data. 214 // The maximum length allowed for form data.
206 const size_t kMaxDataLength = 1024; 215 const size_t kMaxDataLength = 1024;
(...skipping 378 matching lines...) Expand 10 before | Expand all | Expand 10 after
585 "DELETE FROM autofill_profile_phones WHERE guid = ?")); 594 "DELETE FROM autofill_profile_phones WHERE guid = ?"));
586 if (!s3) { 595 if (!s3) {
587 NOTREACHED() << "Statement prepare failed"; 596 NOTREACHED() << "Statement prepare failed";
588 return false; 597 return false;
589 } 598 }
590 599
591 s3.BindString(0, guid); 600 s3.BindString(0, guid);
592 return s3.Run(); 601 return s3.Run();
593 } 602 }
594 603
604 // TODO(dhollowa): Find a common place for this. It is duplicated in
605 // personal_data_manager.cc.
606 template<typename T>
607 T* address_of(T& v) {
608 return &v;
609 }
610
595 } // namespace 611 } // namespace
596 612
597 WebDatabase::WebDatabase() { 613 WebDatabase::WebDatabase() {
598 } 614 }
599 615
600 WebDatabase::~WebDatabase() { 616 WebDatabase::~WebDatabase() {
601 } 617 }
602 618
603 void WebDatabase::BeginTransaction() { 619 void WebDatabase::BeginTransaction() {
604 db_.BeginTransaction(); 620 db_.BeginTransaction();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { 660 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) {
645 LOG(WARNING) << "Web database is too new."; 661 LOG(WARNING) << "Web database is too new.";
646 return sql::INIT_TOO_NEW; 662 return sql::INIT_TOO_NEW;
647 } 663 }
648 664
649 // Initialize the tables. 665 // Initialize the tables.
650 if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() || 666 if (!InitKeywordsTable() || !InitLoginsTable() || !InitWebAppIconsTable() ||
651 !InitWebAppsTable() || !InitAutofillTable() || 667 !InitWebAppsTable() || !InitAutofillTable() ||
652 !InitAutofillDatesTable() || !InitAutofillProfilesTable() || 668 !InitAutofillDatesTable() || !InitAutofillProfilesTable() ||
653 !InitAutofillProfileNamesTable() || !InitAutofillProfileEmailsTable() || 669 !InitAutofillProfileNamesTable() || !InitAutofillProfileEmailsTable() ||
654 !InitAutofillProfilePhonesTable() || !InitCreditCardsTable() || 670 !InitAutofillProfilePhonesTable() || !InitAutofillProfileTrashTable() ||
655 !InitTokenServiceTable()) { 671 !InitCreditCardsTable() || !InitTokenServiceTable()) {
656 LOG(WARNING) << "Unable to initialize the web database."; 672 LOG(WARNING) << "Unable to initialize the web database.";
657 return sql::INIT_FAILURE; 673 return sql::INIT_FAILURE;
658 } 674 }
659 675
660 // If the file on disk is an older database version, bring it up to date. 676 // If the file on disk is an older database version, bring it up to date.
661 // If the migration fails we return an error to caller and do not commit 677 // If the migration fails we return an error to caller and do not commit
662 // the migration. 678 // the migration.
663 sql::InitStatus migration_status = MigrateOldVersionsAsNeeded(); 679 sql::InitStatus migration_status = MigrateOldVersionsAsNeeded();
664 if (migration_status != sql::INIT_OK) 680 if (migration_status != sql::INIT_OK)
665 return migration_status; 681 return migration_status;
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 "guid VARCHAR, " 1006 "guid VARCHAR, "
991 "type INTEGER DEFAULT 0, " 1007 "type INTEGER DEFAULT 0, "
992 "number VARCHAR)")) { 1008 "number VARCHAR)")) {
993 NOTREACHED(); 1009 NOTREACHED();
994 return false; 1010 return false;
995 } 1011 }
996 } 1012 }
997 return true; 1013 return true;
998 } 1014 }
999 1015
1016 bool WebDatabase::InitAutofillProfileTrashTable() {
1017 if (!db_.DoesTableExist("autofill_profiles_trash")) {
1018 if (!db_.Execute("CREATE TABLE autofill_profiles_trash ( "
1019 "guid VARCHAR)")) {
1020 NOTREACHED();
1021 return false;
1022 }
1023 }
1024 return true;
1025 }
1026
1000 bool WebDatabase::InitCreditCardsTable() { 1027 bool WebDatabase::InitCreditCardsTable() {
1001 if (!db_.DoesTableExist("credit_cards")) { 1028 if (!db_.DoesTableExist("credit_cards")) {
1002 if (!db_.Execute("CREATE TABLE credit_cards ( " 1029 if (!db_.Execute("CREATE TABLE credit_cards ( "
1003 "guid VARCHAR PRIMARY KEY, " 1030 "guid VARCHAR PRIMARY KEY, "
1004 "name_on_card VARCHAR, " 1031 "name_on_card VARCHAR, "
1005 "expiration_month INTEGER, " 1032 "expiration_month INTEGER, "
1006 "expiration_year INTEGER, " 1033 "expiration_year INTEGER, "
1007 "card_number_encrypted BLOB, " 1034 "card_number_encrypted BLOB, "
1008 "date_modified INTEGER NOT NULL DEFAULT 0)")) { 1035 "date_modified INTEGER NOT NULL DEFAULT 0)")) {
1009 NOTREACHED(); 1036 NOTREACHED();
(...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after
1840 } 1867 }
1841 s.BindString16(0, name); 1868 s.BindString16(0, name);
1842 s.BindString16(1, value); 1869 s.BindString16(1, value);
1843 1870
1844 if (s.Step()) 1871 if (s.Step())
1845 return RemoveFormElementForID(s.ColumnInt64(0)); 1872 return RemoveFormElementForID(s.ColumnInt64(0));
1846 return false; 1873 return false;
1847 } 1874 }
1848 1875
1849 bool WebDatabase::AddAutofillProfile(const AutofillProfile& profile) { 1876 bool WebDatabase::AddAutofillProfile(const AutofillProfile& profile) {
1877 if (IsAutofillGUIDInTrash(profile.guid()))
1878 return true;
1879
1850 sql::Statement s(db_.GetUniqueStatement( 1880 sql::Statement s(db_.GetUniqueStatement(
1851 "INSERT INTO autofill_profiles" 1881 "INSERT INTO autofill_profiles"
1852 "(guid, company_name, address_line_1, address_line_2, city, state," 1882 "(guid, company_name, address_line_1, address_line_2, city, state,"
1853 " zipcode, country, country_code, date_modified)" 1883 " zipcode, country, country_code, date_modified)"
1854 "VALUES (?,?,?,?,?,?,?,?,?,?)")); 1884 "VALUES (?,?,?,?,?,?,?,?,?,?)"));
1855 if (!s) { 1885 if (!s) {
1856 NOTREACHED() << "Statement prepare failed"; 1886 NOTREACHED() << "Statement prepare failed";
1857 return false; 1887 return false;
1858 } 1888 }
1859 1889
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
1979 return false; 2009 return false;
1980 profiles->push_back(profile); 2010 profiles->push_back(profile);
1981 } 2011 }
1982 2012
1983 return s.Succeeded(); 2013 return s.Succeeded();
1984 } 2014 }
1985 2015
1986 bool WebDatabase::UpdateAutofillProfile(const AutofillProfile& profile) { 2016 bool WebDatabase::UpdateAutofillProfile(const AutofillProfile& profile) {
1987 DCHECK(guid::IsValidGUID(profile.guid())); 2017 DCHECK(guid::IsValidGUID(profile.guid()));
1988 2018
2019 if (IsAutofillGUIDInTrash(profile.guid()))
2020 return true;
2021
1989 AutofillProfile* tmp_profile = NULL; 2022 AutofillProfile* tmp_profile = NULL;
1990 if (!GetAutofillProfile(profile.guid(), &tmp_profile)) 2023 if (!GetAutofillProfile(profile.guid(), &tmp_profile))
1991 return false; 2024 return false;
1992 2025
1993 // Preserve appropriate modification dates by not updating unchanged profiles. 2026 // Preserve appropriate modification dates by not updating unchanged profiles.
1994 scoped_ptr<AutofillProfile> old_profile(tmp_profile); 2027 scoped_ptr<AutofillProfile> old_profile(tmp_profile);
1995 if (*old_profile == profile) 2028 if (*old_profile == profile)
1996 return true; 2029 return true;
1997 2030
1998 sql::Statement s(db_.GetUniqueStatement( 2031 sql::Statement s(db_.GetUniqueStatement(
(...skipping 16 matching lines...) Expand all
2015 2048
2016 // Remove the old names, emails, and phone/fax numbers. 2049 // Remove the old names, emails, and phone/fax numbers.
2017 if (!RemoveAutofillProfilePieces(profile.guid(), &db_)) 2050 if (!RemoveAutofillProfilePieces(profile.guid(), &db_))
2018 return false; 2051 return false;
2019 2052
2020 return AddAutofillProfilePieces(profile.guid(), profile, &db_); 2053 return AddAutofillProfilePieces(profile.guid(), profile, &db_);
2021 } 2054 }
2022 2055
2023 bool WebDatabase::RemoveAutofillProfile(const std::string& guid) { 2056 bool WebDatabase::RemoveAutofillProfile(const std::string& guid) {
2024 DCHECK(guid::IsValidGUID(guid)); 2057 DCHECK(guid::IsValidGUID(guid));
2058
2059 if (IsAutofillGUIDInTrash(guid))
2060 return true;
Ilya Sherman 2011/03/16 04:58:57 Shouldn't we remove the profile from the trash her
dhollowa 2011/03/16 16:13:35 The trash is emptied by the WDS. This should be s
2061
2025 sql::Statement s(db_.GetUniqueStatement( 2062 sql::Statement s(db_.GetUniqueStatement(
2026 "DELETE FROM autofill_profiles WHERE guid = ?")); 2063 "DELETE FROM autofill_profiles WHERE guid = ?"));
2027 if (!s) { 2064 if (!s) {
2028 NOTREACHED() << "Statement prepare failed"; 2065 NOTREACHED() << "Statement prepare failed";
2029 return false; 2066 return false;
2030 } 2067 }
2031 2068
2032 s.BindString(0, guid); 2069 s.BindString(0, guid);
2033 if (!s.Run()) 2070 if (!s.Run())
2034 return false; 2071 return false;
2035 2072
2036 return RemoveAutofillProfilePieces(guid, &db_); 2073 return RemoveAutofillProfilePieces(guid, &db_);
2037 } 2074 }
2038 2075
2076 bool WebDatabase::ClearAutofillProfiles() {
2077 sql::Statement s1(db_.GetUniqueStatement(
2078 "DELETE FROM autofill_profiles"));
2079 if (!s1) {
2080 NOTREACHED() << "Statement prepare failed";
2081 return false;
2082 }
2083
2084 if (!s1.Run())
2085 return false;
2086
2087 sql::Statement s2(db_.GetUniqueStatement(
2088 "DELETE FROM autofill_profile_names"));
2089 if (!s2) {
2090 NOTREACHED() << "Statement prepare failed";
2091 return false;
2092 }
2093
2094 if (!s2.Run())
2095 return false;
2096
2097 sql::Statement s3(db_.GetUniqueStatement(
2098 "DELETE FROM autofill_profile_emails"));
2099 if (!s3) {
2100 NOTREACHED() << "Statement prepare failed";
2101 return false;
2102 }
2103
2104 if (!s3.Run())
2105 return false;
2106
2107 sql::Statement s4(db_.GetUniqueStatement(
2108 "DELETE FROM autofill_profile_phones"));
2109 if (!s4) {
2110 NOTREACHED() << "Statement prepare failed";
2111 return false;
2112 }
2113
2114 if (!s4.Run())
2115 return false;
2116
2117 return true;
2118 }
2119
2039 bool WebDatabase::AddCreditCard(const CreditCard& credit_card) { 2120 bool WebDatabase::AddCreditCard(const CreditCard& credit_card) {
2040 sql::Statement s(db_.GetUniqueStatement( 2121 sql::Statement s(db_.GetUniqueStatement(
2041 "INSERT INTO credit_cards" 2122 "INSERT INTO credit_cards"
2042 "(guid, name_on_card, expiration_month, expiration_year, " 2123 "(guid, name_on_card, expiration_month, expiration_year, "
2043 "card_number_encrypted, date_modified)" 2124 "card_number_encrypted, date_modified)"
2044 "VALUES (?,?,?,?,?,?)")); 2125 "VALUES (?,?,?,?,?,?)"));
2045 if (!s) { 2126 if (!s) {
2046 NOTREACHED() << "Statement prepare failed"; 2127 NOTREACHED() << "Statement prepare failed";
2047 return false; 2128 return false;
2048 } 2129 }
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
2188 s_credit_cards.Run(); 2269 s_credit_cards.Run();
2189 2270
2190 if (!s_credit_cards.Succeeded()) { 2271 if (!s_credit_cards.Succeeded()) {
2191 NOTREACHED(); 2272 NOTREACHED();
2192 return false; 2273 return false;
2193 } 2274 }
2194 2275
2195 return true; 2276 return true;
2196 } 2277 }
2197 2278
2279 bool WebDatabase::GetAutofillProfilesInTrash(std::vector<std::string>* guids) {
2280 guids->clear();
2281
2282 sql::Statement s(db_.GetUniqueStatement(
2283 "SELECT guid "
2284 "FROM autofill_profiles_trash"));
2285 if (!s) {
2286 NOTREACHED() << "Statement prepare failed";
2287 return false;
2288 }
2289
2290 while (s.Step()) {
2291 std::string guid = s.ColumnString(0);
2292 guids->push_back(guid);
2293 }
2294
2295 return s.Succeeded();
2296 }
2297
2298 bool WebDatabase::EmptyAutofillProfilesTrash() {
2299 sql::Statement s(db_.GetUniqueStatement(
2300 "DELETE FROM autofill_profiles_trash"));
2301 if (!s) {
2302 NOTREACHED() << "Statement prepare failed";
2303 return false;
2304 }
2305
2306 return s.Run();
2307 }
2308
2198 bool WebDatabase::AddToCountOfFormElement(int64 pair_id, 2309 bool WebDatabase::AddToCountOfFormElement(int64 pair_id,
2199 int delta, 2310 int delta,
2200 bool* was_removed) { 2311 bool* was_removed) {
2201 DCHECK(was_removed); 2312 DCHECK(was_removed);
2202 int count = 0; 2313 int count = 0;
2203 *was_removed = false; 2314 *was_removed = false;
2204 2315
2205 if (!GetCountOfFormElement(pair_id, &count)) 2316 if (!GetCountOfFormElement(pair_id, &count))
2206 return false; 2317 return false;
2207 2318
(...skipping 16 matching lines...) Expand all
2224 return false; 2335 return false;
2225 } 2336 }
2226 s.BindInt64(0, pair_id); 2337 s.BindInt64(0, pair_id);
2227 if (s.Run()) { 2338 if (s.Run()) {
2228 return RemoveFormElementForTimeRange(pair_id, base::Time(), base::Time(), 2339 return RemoveFormElementForTimeRange(pair_id, base::Time(), base::Time(),
2229 NULL); 2340 NULL);
2230 } 2341 }
2231 return false; 2342 return false;
2232 } 2343 }
2233 2344
2345 bool WebDatabase::AddAutofillGUIDToTrash(const std::string& guid) {
2346 sql::Statement s(db_.GetUniqueStatement(
2347 "INSERT INTO autofill_profiles_trash"
2348 " (guid) "
2349 "VALUES (?)"));
2350 if (!s) {
2351 NOTREACHED();
2352 return sql::INIT_FAILURE;
2353 }
2354
2355 s.BindString(0, guid);
2356 if (!s.Run()) {
2357 NOTREACHED();
2358 return false;
2359 }
2360 return true;
2361 }
2362
2363 bool WebDatabase::IsAutofillGUIDInTrash(const std::string& guid) {
2364 sql::Statement s(db_.GetUniqueStatement(
2365 "SELECT guid "
2366 "FROM autofill_profiles_trash "
2367 "WHERE guid = ?"));
2368 if (!s) {
2369 NOTREACHED() << "Statement prepare failed";
2370 return false;
2371 }
2372
2373 s.BindString(0, guid);
2374 return s.Step();
2375 }
2376
2234 sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){ 2377 sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded(){
2235 // Migrate if necessary. 2378 // Migrate if necessary.
2236 int current_version = meta_table_.GetVersionNumber(); 2379 int current_version = meta_table_.GetVersionNumber();
2237 switch (current_version) { 2380 switch (current_version) {
2238 // Versions 1 - 19 are unhandled. Version numbers greater than 2381 // Versions 1 - 19 are unhandled. Version numbers greater than
2239 // kCurrentVersionNumber should have already been weeded out by the caller. 2382 // kCurrentVersionNumber should have already been weeded out by the caller.
2240 default: 2383 default:
2241 // When the version is too old, we return failure error code. The schema 2384 // When the version is too old, we return failure error code. The schema
2242 // is too out of date to migrate. 2385 // is too out of date to migrate.
2243 // There should not be a released product that makes a database too old to 2386 // There should not be a released product that makes a database too old to
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
3085 return sql::INIT_FAILURE; 3228 return sql::INIT_FAILURE;
3086 } 3229 }
3087 } 3230 }
3088 3231
3089 meta_table_.SetVersionNumber(35); 3232 meta_table_.SetVersionNumber(35);
3090 meta_table_.SetCompatibleVersionNumber( 3233 meta_table_.SetCompatibleVersionNumber(
3091 std::min(35, kCompatibleVersionNumber)); 3234 std::min(35, kCompatibleVersionNumber));
3092 3235
3093 // FALL THROUGH 3236 // FALL THROUGH
3094 3237
3238 case 35:
3239 // Merge and cull older profiles where possible.
3240 {
3241 sql::Statement s(db_.GetUniqueStatement(
3242 "SELECT guid, date_modified "
3243 "FROM autofill_profiles"));
3244 if (!s) {
3245 NOTREACHED() << "Statement prepare failed";
3246 return sql::INIT_FAILURE;
3247 }
3248
3249 // Accumulate the good profiles.
3250 std::vector<AutofillProfile> accumulated_profiles;
3251 std::vector<AutofillProfile*> accumulated_profiles_p;
3252 std::map<std::string, int64> modification_map;
3253 while (s.Step()) {
3254 std::string guid = s.ColumnString(0);
3255 int64 date_modified = s.ColumnInt64(1);
3256 modification_map.insert(
3257 std::pair<std::string, int64>(guid, date_modified));
3258 AutofillProfile* profile = NULL;
3259 if (!GetAutofillProfile(guid, &profile)) {
3260 NOTREACHED() << "Bad read of profile.";
3261 return sql::INIT_FAILURE;
3262 }
3263 scoped_ptr<AutofillProfile> p(profile);
3264
3265 if (PersonalDataManager::IsSuitableMergeProfile(*p)) {
3266 std::vector<AutofillProfile> merged_profiles;
3267 bool merged = PersonalDataManager::MergeProfile(
3268 *p, accumulated_profiles_p, &merged_profiles);
3269
3270 std::swap(accumulated_profiles, merged_profiles);
3271
3272 accumulated_profiles_p.clear();
3273 accumulated_profiles_p.resize(accumulated_profiles.size());
3274 std::transform(accumulated_profiles.begin(),
3275 accumulated_profiles.end(),
3276 accumulated_profiles_p.begin(),
3277 address_of<AutofillProfile>);
3278
3279 // If the profile got merged trash the original.
3280 if (merged)
3281 AddAutofillGUIDToTrash(p->guid());
3282 } else {
3283 // An invalid profile, so trash it.
3284 AddAutofillGUIDToTrash(p->guid());
3285 }
3286 }
3287
3288 // Drop the current profiles.
3289 if (!ClearAutofillProfiles()) {
3290 LOG(WARNING) << "Unable to update web database to version 36.";
3291 NOTREACHED();
3292 return sql::INIT_FAILURE;
3293 }
3294
3295 // Add the newly merged profiles back in.
3296 for (std::vector<AutofillProfile>::const_iterator
3297 iter = accumulated_profiles.begin();
3298 iter != accumulated_profiles.end();
3299 ++iter) {
3300 if (!AddAutofillProfile(*iter)) {
3301 LOG(WARNING) << "Unable to update web database to version 36.";
3302 NOTREACHED();
3303 return sql::INIT_FAILURE;
3304 }
3305
3306 // Fix up the original modification date.
3307 std::map<std::string, int64>::const_iterator date_item =
3308 modification_map.find(iter->guid());
3309 if (date_item == modification_map.end()) {
3310 LOG(WARNING) << "Unable to update web database to version 36.";
3311 NOTREACHED();
3312 return sql::INIT_FAILURE;
3313 }
3314 sql::Statement s_date(db_.GetUniqueStatement(
3315 "UPDATE autofill_profiles SET date_modified=? "
3316 "WHERE guid=?"));
3317 s_date.BindInt64(0, date_item->second);
3318 s_date.BindString(1, iter->guid());
3319 if (!s_date.Run()) {
3320 LOG(WARNING) << "Unable to update web database to version 36.";
3321 NOTREACHED();
3322 return sql::INIT_FAILURE;
3323 }
3324 }
3325 }
3326
3327 meta_table_.SetVersionNumber(36);
3328 meta_table_.SetCompatibleVersionNumber(
3329 std::min(36, kCompatibleVersionNumber));
3330
3331 // FALL THROUGH
3332
3095 // Add successive versions here. Each should set the version number and 3333 // Add successive versions here. Each should set the version number and
3096 // compatible version number as appropriate, then fall through to the next 3334 // compatible version number as appropriate, then fall through to the next
3097 // case. 3335 // case.
3098 3336
3099 case kCurrentVersionNumber: 3337 case kCurrentVersionNumber:
3100 // No migration needed. 3338 // No migration needed.
3101 return sql::INIT_OK; 3339 return sql::INIT_OK;
3102 } 3340 }
3103 } 3341 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698