| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 | 8 |
| 9 #include "chrome/browser/webdata/autofill_table.h" | 9 #include "chrome/browser/webdata/autofill_table.h" |
| 10 #include "chrome/browser/webdata/keyword_table.h" | 10 #include "chrome/browser/webdata/keyword_table.h" |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 | 55 |
| 56 void WebDatabase::BeginTransaction() { | 56 void WebDatabase::BeginTransaction() { |
| 57 db_.BeginTransaction(); | 57 db_.BeginTransaction(); |
| 58 } | 58 } |
| 59 | 59 |
| 60 void WebDatabase::CommitTransaction() { | 60 void WebDatabase::CommitTransaction() { |
| 61 db_.CommitTransaction(); | 61 db_.CommitTransaction(); |
| 62 } | 62 } |
| 63 | 63 |
| 64 AutofillTable* WebDatabase::GetAutofillTable() { | 64 AutofillTable* WebDatabase::GetAutofillTable() { |
| 65 return autofill_table_.get(); | 65 return autofill_table_; |
| 66 } | 66 } |
| 67 | 67 |
| 68 KeywordTable* WebDatabase::GetKeywordTable() { | 68 KeywordTable* WebDatabase::GetKeywordTable() { |
| 69 return keyword_table_.get(); | 69 return keyword_table_; |
| 70 } | 70 } |
| 71 | 71 |
| 72 LoginsTable* WebDatabase::GetLoginsTable() { | 72 LoginsTable* WebDatabase::GetLoginsTable() { |
| 73 return logins_table_.get(); | 73 return logins_table_; |
| 74 } | 74 } |
| 75 | 75 |
| 76 TokenServiceTable* WebDatabase::GetTokenServiceTable() { | 76 TokenServiceTable* WebDatabase::GetTokenServiceTable() { |
| 77 return token_service_table_.get(); | 77 return token_service_table_; |
| 78 } | 78 } |
| 79 | 79 |
| 80 WebAppsTable* WebDatabase::GetWebAppsTable() { | 80 WebAppsTable* WebDatabase::GetWebAppsTable() { |
| 81 return web_apps_table_.get(); | 81 return web_apps_table_; |
| 82 } | 82 } |
| 83 | 83 |
| 84 sql::Connection* WebDatabase::GetSQLConnection() { | 84 sql::Connection* WebDatabase::GetSQLConnection() { |
| 85 return &db_; | 85 return &db_; |
| 86 } | 86 } |
| 87 | 87 |
| 88 sql::InitStatus WebDatabase::Init(const base::FilePath& db_name, | 88 sql::InitStatus WebDatabase::Init(const base::FilePath& db_name, |
| 89 const std::string& app_locale) { | 89 const std::string& app_locale) { |
| 90 // When running in unit tests, there is already a NotificationService object. | 90 // When running in unit tests, there is already a NotificationService object. |
| 91 // Since only one can exist at a time per thread, check first. | 91 // Since only one can exist at a time per thread, check first. |
| (...skipping 24 matching lines...) Expand all Loading... |
| 116 return sql::INIT_FAILURE; | 116 return sql::INIT_FAILURE; |
| 117 | 117 |
| 118 // Version check. | 118 // Version check. |
| 119 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) | 119 if (!meta_table_.Init(&db_, kCurrentVersionNumber, kCompatibleVersionNumber)) |
| 120 return sql::INIT_FAILURE; | 120 return sql::INIT_FAILURE; |
| 121 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { | 121 if (meta_table_.GetCompatibleVersionNumber() > kCurrentVersionNumber) { |
| 122 LOG(WARNING) << "Web database is too new."; | 122 LOG(WARNING) << "Web database is too new."; |
| 123 return sql::INIT_TOO_NEW; | 123 return sql::INIT_TOO_NEW; |
| 124 } | 124 } |
| 125 | 125 |
| 126 // TODO(joi): Table creation should move out of this class; switch |
| 127 // to a two-phase init to accomplish this. |
| 128 |
| 126 // Create the tables. | 129 // Create the tables. |
| 127 autofill_table_.reset(new AutofillTable(&db_, &meta_table_)); | 130 autofill_table_ = new AutofillTable(&db_, &meta_table_); |
| 128 keyword_table_.reset(new KeywordTable(&db_, &meta_table_)); | 131 tables_.push_back(autofill_table_); |
| 132 |
| 133 keyword_table_ = new KeywordTable(&db_, &meta_table_); |
| 134 tables_.push_back(keyword_table_); |
| 135 |
| 129 // TODO(mdm): We only really need the LoginsTable on Windows for IE7 password | 136 // TODO(mdm): We only really need the LoginsTable on Windows for IE7 password |
| 130 // access, but for now, we still create it on all platforms since it deletes | 137 // access, but for now, we still create it on all platforms since it deletes |
| 131 // the old logins table. We can remove this after a while, e.g. in M22 or so. | 138 // the old logins table. We can remove this after a while, e.g. in M22 or so. |
| 132 logins_table_.reset(new LoginsTable(&db_, &meta_table_)); | 139 logins_table_ = new LoginsTable(&db_, &meta_table_); |
| 133 token_service_table_.reset(new TokenServiceTable(&db_, &meta_table_)); | 140 tables_.push_back(logins_table_); |
| 134 web_apps_table_.reset(new WebAppsTable(&db_, &meta_table_)); | 141 |
| 135 web_intents_table_.reset(new WebIntentsTable(&db_, &meta_table_)); | 142 token_service_table_ = new TokenServiceTable(&db_, &meta_table_); |
| 143 tables_.push_back(token_service_table_); |
| 144 |
| 145 web_apps_table_ = new WebAppsTable(&db_, &meta_table_); |
| 146 tables_.push_back(web_apps_table_); |
| 147 |
| 148 web_intents_table_ = new WebIntentsTable(&db_, &meta_table_); |
| 149 tables_.push_back(web_intents_table_); |
| 136 | 150 |
| 137 // Initialize the tables. | 151 // Initialize the tables. |
| 138 if (!keyword_table_->Init() || !autofill_table_->Init() || | 152 for (ScopedVector<WebDatabaseTable>::iterator it = tables_.begin(); |
| 139 !logins_table_->Init() || !web_apps_table_->Init() || | 153 it != tables_.end(); |
| 140 !token_service_table_->Init() || !web_intents_table_->Init()) { | 154 ++it) { |
| 141 LOG(WARNING) << "Unable to initialize the web database."; | 155 if (!(*it)->Init()) { |
| 142 return sql::INIT_FAILURE; | 156 LOG(WARNING) << "Unable to initialize the web database."; |
| 157 return sql::INIT_FAILURE; |
| 158 } |
| 143 } | 159 } |
| 144 | 160 |
| 145 // If the file on disk is an older database version, bring it up to date. | 161 // If the file on disk is an older database version, bring it up to date. |
| 146 // If the migration fails we return an error to caller and do not commit | 162 // If the migration fails we return an error to caller and do not commit |
| 147 // the migration. | 163 // the migration. |
| 148 sql::InitStatus migration_status = MigrateOldVersionsAsNeeded(app_locale); | 164 sql::InitStatus migration_status = MigrateOldVersionsAsNeeded(app_locale); |
| 149 if (migration_status != sql::INIT_OK) | 165 if (migration_status != sql::INIT_OK) |
| 150 return migration_status; | 166 return migration_status; |
| 151 | 167 |
| 152 return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; | 168 return transaction.Commit() ? sql::INIT_OK : sql::INIT_FAILURE; |
| 153 } | 169 } |
| 154 | 170 |
| 155 sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded( | 171 sql::InitStatus WebDatabase::MigrateOldVersionsAsNeeded( |
| 156 const std::string& app_locale) { | 172 const std::string& app_locale) { |
| 157 // Some malware used to lower the version number, causing migration to | 173 // Some malware used to lower the version number, causing migration to |
| 158 // fail. Ensure the version number is at least as high as the compatible | 174 // fail. Ensure the version number is at least as high as the compatible |
| 159 // version number. | 175 // version number. |
| 160 int current_version = std::max(meta_table_.GetVersionNumber(), | 176 int current_version = std::max(meta_table_.GetVersionNumber(), |
| 161 meta_table_.GetCompatibleVersionNumber()); | 177 meta_table_.GetCompatibleVersionNumber()); |
| 162 if (current_version > meta_table_.GetVersionNumber()) | 178 if (current_version > meta_table_.GetVersionNumber()) |
| 163 ChangeVersion(&meta_table_, current_version, false); | 179 ChangeVersion(&meta_table_, current_version, false); |
| 164 | 180 |
| 165 // Migrate if necessary. | 181 if (current_version < 20) { |
| 166 switch (current_version) { | |
| 167 // Versions 1 - 19 are unhandled. Version numbers greater than | 182 // Versions 1 - 19 are unhandled. Version numbers greater than |
| 168 // kCurrentVersionNumber should have already been weeded out by the caller. | 183 // kCurrentVersionNumber should have already been weeded out by the caller. |
| 169 default: | 184 // |
| 170 // When the version is too old, we return failure error code. The schema | 185 // When the version is too old, we return failure error code. The schema |
| 171 // is too out of date to migrate. | 186 // is too out of date to migrate. |
| 172 // There should not be a released product that makes a database too old to | 187 // |
| 173 // migrate. If we do encounter such a legacy database, we will need a | 188 // There should not be a released product that makes a database too old to |
| 174 // better solution to handle it (i.e., pop up a dialog to tell the user, | 189 // migrate. If we do encounter such a legacy database, we will need a |
| 175 // erase all their prefs and start over, etc.). | 190 // better solution to handle it (i.e., pop up a dialog to tell the user, |
| 176 LOG(WARNING) << "Web database version " << current_version << | 191 // erase all their prefs and start over, etc.). |
| 177 " is too old to handle."; | 192 LOG(WARNING) << "Web database version " << current_version << |
| 178 NOTREACHED(); | 193 " is too old to handle."; |
| 179 return sql::INIT_FAILURE; | 194 NOTREACHED(); |
| 195 return sql::INIT_FAILURE; |
| 196 } |
| 180 | 197 |
| 181 case 20: | 198 for (int next_version = current_version + 1; |
| 182 if (!keyword_table_->MigrateToVersion21AutoGenerateKeywordColumn()) | 199 next_version <= kCurrentVersionNumber; |
| 183 return FailedMigrationTo(21); | 200 ++next_version) { |
| 201 // Give each table a chance to migrate to this version. |
| 202 for (ScopedVector<WebDatabaseTable>::iterator it = tables_.begin(); |
| 203 it != tables_.end(); |
| 204 ++it) { |
| 205 // Any of the tables may set this to true, but by default it is false. |
| 206 bool update_compatible_version = false; |
| 207 if (!(*it)->MigrateToVersion(next_version, |
| 208 app_locale, |
| 209 &update_compatible_version)) { |
| 210 return FailedMigrationTo(next_version); |
| 211 } |
| 184 | 212 |
| 185 ChangeVersion(&meta_table_, 21, true); | 213 ChangeVersion(&meta_table_, next_version, update_compatible_version); |
| 186 // FALL THROUGH | 214 } |
| 187 | |
| 188 case 21: | |
| 189 if (!autofill_table_->ClearAutofillEmptyValueElements()) | |
| 190 return FailedMigrationTo(22); | |
| 191 | |
| 192 ChangeVersion(&meta_table_, 22, false); | |
| 193 // FALL THROUGH | |
| 194 | |
| 195 case 22: | |
| 196 if (!autofill_table_->MigrateToVersion23AddCardNumberEncryptedColumn()) | |
| 197 return FailedMigrationTo(23); | |
| 198 | |
| 199 ChangeVersion(&meta_table_, 23, false); | |
| 200 // FALL THROUGH | |
| 201 | |
| 202 case 23: | |
| 203 if (!autofill_table_->MigrateToVersion24CleanupOversizedStringFields()) | |
| 204 return FailedMigrationTo(24); | |
| 205 | |
| 206 ChangeVersion(&meta_table_, 24, false); | |
| 207 // FALL THROUGH | |
| 208 | |
| 209 case 24: | |
| 210 if (!keyword_table_->MigrateToVersion25AddLogoIDColumn()) | |
| 211 return FailedMigrationTo(25); | |
| 212 | |
| 213 ChangeVersion(&meta_table_, 25, true); | |
| 214 // FALL THROUGH | |
| 215 | |
| 216 case 25: | |
| 217 if (!keyword_table_->MigrateToVersion26AddCreatedByPolicyColumn()) | |
| 218 return FailedMigrationTo(26); | |
| 219 | |
| 220 ChangeVersion(&meta_table_, 26, true); | |
| 221 // FALL THROUGH | |
| 222 | |
| 223 case 26: | |
| 224 if (!autofill_table_->MigrateToVersion27UpdateLegacyCreditCards()) | |
| 225 return FailedMigrationTo(27); | |
| 226 | |
| 227 ChangeVersion(&meta_table_, 27, true); | |
| 228 // FALL THROUGH | |
| 229 | |
| 230 case 27: | |
| 231 if (!keyword_table_->MigrateToVersion28SupportsInstantColumn()) | |
| 232 return FailedMigrationTo(28); | |
| 233 | |
| 234 ChangeVersion(&meta_table_, 28, true); | |
| 235 // FALL THROUGH | |
| 236 | |
| 237 case 28: | |
| 238 if (!keyword_table_->MigrateToVersion29InstantURLToSupportsInstant()) | |
| 239 return FailedMigrationTo(29); | |
| 240 | |
| 241 ChangeVersion(&meta_table_, 29, true); | |
| 242 // FALL THROUGH | |
| 243 | |
| 244 case 29: | |
| 245 if (!autofill_table_->MigrateToVersion30AddDateModifed()) | |
| 246 return FailedMigrationTo(30); | |
| 247 | |
| 248 ChangeVersion(&meta_table_, 30, true); | |
| 249 // FALL THROUGH | |
| 250 | |
| 251 case 30: | |
| 252 if (!autofill_table_->MigrateToVersion31AddGUIDToCreditCardsAndProfiles()) | |
| 253 return FailedMigrationTo(31); | |
| 254 | |
| 255 ChangeVersion(&meta_table_, 31, true); | |
| 256 // FALL THROUGH | |
| 257 | |
| 258 case 31: | |
| 259 if (!autofill_table_->MigrateToVersion32UpdateProfilesAndCreditCards()) | |
| 260 return FailedMigrationTo(32); | |
| 261 | |
| 262 ChangeVersion(&meta_table_, 32, true); | |
| 263 // FALL THROUGH | |
| 264 | |
| 265 case 32: | |
| 266 if (!autofill_table_->MigrateToVersion33ProfilesBasedOnFirstName()) | |
| 267 return FailedMigrationTo(33); | |
| 268 | |
| 269 ChangeVersion(&meta_table_, 33, true); | |
| 270 // FALL THROUGH | |
| 271 | |
| 272 case 33: | |
| 273 if (!autofill_table_->MigrateToVersion34ProfilesBasedOnCountryCode( | |
| 274 app_locale)) | |
| 275 return FailedMigrationTo(34); | |
| 276 | |
| 277 ChangeVersion(&meta_table_, 34, true); | |
| 278 // FALL THROUGH | |
| 279 | |
| 280 case 34: | |
| 281 if (!autofill_table_->MigrateToVersion35GreatBritainCountryCodes()) | |
| 282 return FailedMigrationTo(35); | |
| 283 | |
| 284 ChangeVersion(&meta_table_, 35, true); | |
| 285 // FALL THROUGH | |
| 286 | |
| 287 // Combine migrations 35 and 36. This is due to enhancements to the merge | |
| 288 // step when migrating profiles. The original migration from 35 to 36 did | |
| 289 // not merge profiles with identical addresses, but the migration from 36 to | |
| 290 // 37 does. The step from 35 to 36 should only happen on the Chrome 12 dev | |
| 291 // channel. Chrome 12 beta and release users will jump from 35 to 37 | |
| 292 // directly getting the full benefits of the multi-valued merge as well as | |
| 293 // the culling of bad data. | |
| 294 case 35: | |
| 295 case 36: | |
| 296 if (!autofill_table_->MigrateToVersion37MergeAndCullOlderProfiles()) | |
| 297 return FailedMigrationTo(37); | |
| 298 | |
| 299 ChangeVersion(&meta_table_, 37, true); | |
| 300 // FALL THROUGH | |
| 301 | |
| 302 case 37: | |
| 303 if (!keyword_table_->MigrateToVersion38AddLastModifiedColumn()) | |
| 304 return FailedMigrationTo(38); | |
| 305 | |
| 306 ChangeVersion(&meta_table_, 38, true); | |
| 307 // FALL THROUGH | |
| 308 | |
| 309 case 38: | |
| 310 if (!keyword_table_->MigrateToVersion39AddSyncGUIDColumn()) | |
| 311 return FailedMigrationTo(39); | |
| 312 | |
| 313 ChangeVersion(&meta_table_, 39, true); | |
| 314 // FALL THROUGH | |
| 315 | |
| 316 // Subsequent search engine backup migrations are merged into a single one. | |
| 317 case 39: | |
| 318 case 40: | |
| 319 case 41: | |
| 320 case 42: | |
| 321 case 43: | |
| 322 if (!keyword_table_->MigrateToVersion44AddDefaultSearchProviderBackup()) | |
| 323 return FailedMigrationTo(44); | |
| 324 | |
| 325 ChangeVersion(&meta_table_, 44, true); | |
| 326 // FALL THROUGH | |
| 327 | |
| 328 case 44: | |
| 329 if (!keyword_table_-> | |
| 330 MigrateToVersion45RemoveLogoIDAndAutogenerateColumns()) | |
| 331 return FailedMigrationTo(45); | |
| 332 | |
| 333 ChangeVersion(&meta_table_, 45, true); | |
| 334 // FALL THROUGH | |
| 335 | |
| 336 case 45: | |
| 337 if (!web_intents_table_->MigrateToVersion46AddSchemeColumn()) | |
| 338 return FailedMigrationTo(46); | |
| 339 | |
| 340 ChangeVersion(&meta_table_, 46, true); | |
| 341 // FALL THROUGH | |
| 342 | |
| 343 case 46: | |
| 344 if (!keyword_table_->MigrateToVersion47AddAlternateURLsColumn()) | |
| 345 return FailedMigrationTo(47); | |
| 346 | |
| 347 ChangeVersion(&meta_table_, 47, true); | |
| 348 // FALL THROUGH | |
| 349 | |
| 350 case 47: | |
| 351 if (!keyword_table_->MigrateToVersion48RemoveKeywordsBackup()) | |
| 352 return FailedMigrationTo(48); | |
| 353 | |
| 354 ChangeVersion(&meta_table_, 48, true); | |
| 355 // FALL THROUGH | |
| 356 | |
| 357 case 48: | |
| 358 if (!keyword_table_-> | |
| 359 MigrateToVersion49AddSearchTermsReplacementKeyColumn()) | |
| 360 return FailedMigrationTo(49); | |
| 361 | |
| 362 ChangeVersion(&meta_table_, 49, true); | |
| 363 // FALL THROUGH | |
| 364 | |
| 365 // Add successive versions here. Each should set the version number and | |
| 366 // compatible version number as appropriate, then fall through to the next | |
| 367 // case. | |
| 368 | |
| 369 case kCurrentVersionNumber: | |
| 370 // No migration needed. | |
| 371 return sql::INIT_OK; | |
| 372 } | 215 } |
| 216 return sql::INIT_OK; |
| 373 } | 217 } |
| OLD | NEW |