Chromium Code Reviews| 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/keyword_table.h" | 5 #include "chrome/browser/webdata/keyword_table.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/metrics/histogram.h" | |
| 14 #include "base/metrics/stats_counters.h" | |
| 15 #include "base/string_number_conversions.h" | 13 #include "base/string_number_conversions.h" |
| 16 #include "base/string_split.h" | 14 #include "base/string_split.h" |
| 17 #include "base/string_util.h" | 15 #include "base/string_util.h" |
| 18 #include "base/stringprintf.h" | |
| 19 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
| 20 #include "base/values.h" | 17 #include "base/values.h" |
| 21 #include "chrome/browser/history/history_database.h" | 18 #include "chrome/browser/history/history_database.h" |
| 22 #include "chrome/browser/protector/histograms.h" | |
| 23 #include "chrome/browser/protector/protector_utils.h" | |
| 24 #include "chrome/browser/search_engines/search_terms_data.h" | 19 #include "chrome/browser/search_engines/search_terms_data.h" |
| 25 #include "chrome/browser/search_engines/template_url.h" | 20 #include "chrome/browser/search_engines/template_url.h" |
| 26 #include "chrome/browser/search_engines/template_url_service.h" | 21 #include "chrome/browser/search_engines/template_url_service.h" |
| 27 #include "chrome/browser/webdata/web_database.h" | 22 #include "chrome/browser/webdata/web_database.h" |
| 28 #include "googleurl/src/gurl.h" | 23 #include "googleurl/src/gurl.h" |
| 29 #include "sql/statement.h" | 24 #include "sql/statement.h" |
| 30 #include "sql/transaction.h" | 25 #include "sql/transaction.h" |
| 31 | 26 |
| 32 using base::Time; | 27 using base::Time; |
| 33 | 28 |
| 34 // static | 29 // static |
| 35 const char KeywordTable::kDefaultSearchProviderKey[] = | 30 const char KeywordTable::kDefaultSearchProviderKey[] = |
| 36 "Default Search Provider ID"; | 31 "Default Search Provider ID"; |
| 37 const char KeywordTable::kDefaultSearchIDBackupKey[] = | |
| 38 "Default Search Provider ID Backup"; | |
| 39 const char KeywordTable::kBackupSignatureKey[] = | |
| 40 "Default Search Provider ID Backup Signature"; | |
| 41 | 32 |
| 42 namespace { | 33 namespace { |
| 43 | 34 |
| 44 // Keys used in the meta table. | 35 // Keys used in the meta table. |
| 45 const char kBuiltinKeywordVersion[] = "Builtin Keyword Version"; | 36 const char kBuiltinKeywordVersion[] = "Builtin Keyword Version"; |
| 46 | 37 |
| 47 const std::string ColumnsForVersion(int version, bool concatenated) { | 38 const std::string ColumnsForVersion(int version, bool concatenated) { |
| 48 std::vector<std::string> columns; | 39 std::vector<std::string> columns; |
| 49 | 40 |
| 50 columns.push_back("id"); | 41 columns.push_back("id"); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 s->BindBool(starting_column + 12, data.created_by_policy); | 107 s->BindBool(starting_column + 12, data.created_by_policy); |
| 117 s->BindString(starting_column + 13, data.instant_url); | 108 s->BindString(starting_column + 13, data.instant_url); |
| 118 s->BindInt64(starting_column + 14, data.last_modified.ToTimeT()); | 109 s->BindInt64(starting_column + 14, data.last_modified.ToTimeT()); |
| 119 s->BindString(starting_column + 15, data.sync_guid); | 110 s->BindString(starting_column + 15, data.sync_guid); |
| 120 s->BindString(starting_column + 16, alternate_urls); | 111 s->BindString(starting_column + 16, alternate_urls); |
| 121 } | 112 } |
| 122 | 113 |
| 123 } // anonymous namespace | 114 } // anonymous namespace |
| 124 | 115 |
| 125 KeywordTable::KeywordTable(sql::Connection* db, sql::MetaTable* meta_table) | 116 KeywordTable::KeywordTable(sql::Connection* db, sql::MetaTable* meta_table) |
| 126 : WebDatabaseTable(db, meta_table), | 117 : WebDatabaseTable(db, meta_table) { |
| 127 backup_overwritten_(false) { | |
| 128 } | 118 } |
| 129 | 119 |
| 130 KeywordTable::~KeywordTable() {} | 120 KeywordTable::~KeywordTable() {} |
| 131 | 121 |
| 132 bool KeywordTable::Init() { | 122 bool KeywordTable::Init() { |
| 133 return db_->DoesTableExist("keywords") || | 123 return db_->DoesTableExist("keywords") || |
| 134 (db_->Execute("CREATE TABLE keywords (" | 124 db_->Execute("CREATE TABLE keywords (" |
| 135 "id INTEGER PRIMARY KEY," | 125 "id INTEGER PRIMARY KEY," |
| 136 "short_name VARCHAR NOT NULL," | 126 "short_name VARCHAR NOT NULL," |
| 137 "keyword VARCHAR NOT NULL," | 127 "keyword VARCHAR NOT NULL," |
| 138 "favicon_url VARCHAR NOT NULL," | 128 "favicon_url VARCHAR NOT NULL," |
| 139 "url VARCHAR NOT NULL," | 129 "url VARCHAR NOT NULL," |
| 140 "safe_for_autoreplace INTEGER," | 130 "safe_for_autoreplace INTEGER," |
| 141 "originating_url VARCHAR," | 131 "originating_url VARCHAR," |
| 142 "date_created INTEGER DEFAULT 0," | 132 "date_created INTEGER DEFAULT 0," |
| 143 "usage_count INTEGER DEFAULT 0," | 133 "usage_count INTEGER DEFAULT 0," |
| 144 "input_encodings VARCHAR," | 134 "input_encodings VARCHAR," |
| 145 "show_in_default_list INTEGER," | 135 "show_in_default_list INTEGER," |
| 146 "suggest_url VARCHAR," | 136 "suggest_url VARCHAR," |
| 147 "prepopulate_id INTEGER DEFAULT 0," | 137 "prepopulate_id INTEGER DEFAULT 0," |
| 148 "created_by_policy INTEGER DEFAULT 0," | 138 "created_by_policy INTEGER DEFAULT 0," |
| 149 "instant_url VARCHAR," | 139 "instant_url VARCHAR," |
| 150 "last_modified INTEGER DEFAULT 0," | 140 "last_modified INTEGER DEFAULT 0," |
| 151 "sync_guid VARCHAR," | 141 "sync_guid VARCHAR," |
| 152 "alternate_urls VARCHAR)") && | 142 "alternate_urls VARCHAR)"); |
| 153 UpdateBackupSignature(WebDatabase::kCurrentVersionNumber)); | |
| 154 } | 143 } |
| 155 | 144 |
| 156 bool KeywordTable::IsSyncable() { | 145 bool KeywordTable::IsSyncable() { |
| 157 return true; | 146 return true; |
| 158 } | 147 } |
| 159 | 148 |
| 160 bool KeywordTable::AddKeyword(const TemplateURLData& data) { | 149 bool KeywordTable::AddKeyword(const TemplateURLData& data) { |
| 161 DCHECK(data.id); | 150 DCHECK(data.id); |
| 162 std::string query("INSERT INTO keywords (" + GetKeywordColumns() + | 151 std::string query("INSERT INTO keywords (" + GetKeywordColumns() + |
| 163 ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); | 152 ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); |
| 164 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 153 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
| 165 BindURLToStatement(data, &s, 0, 1); | 154 BindURLToStatement(data, &s, 0, 1); |
| 166 | 155 |
| 167 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 156 return s.Run(); |
| 168 } | 157 } |
| 169 | 158 |
| 170 bool KeywordTable::RemoveKeyword(TemplateURLID id) { | 159 bool KeywordTable::RemoveKeyword(TemplateURLID id) { |
| 171 DCHECK(id); | 160 DCHECK(id); |
| 172 sql::Statement s( | 161 sql::Statement s( |
| 173 db_->GetUniqueStatement("DELETE FROM keywords WHERE id = ?")); | 162 db_->GetUniqueStatement("DELETE FROM keywords WHERE id = ?")); |
| 174 s.BindInt64(0, id); | 163 s.BindInt64(0, id); |
| 175 | 164 |
| 176 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 165 return s.Run(); |
| 177 } | 166 } |
| 178 | 167 |
| 179 bool KeywordTable::GetKeywords(Keywords* keywords) { | 168 bool KeywordTable::GetKeywords(Keywords* keywords) { |
| 180 std::string query("SELECT " + GetKeywordColumns() + | 169 std::string query("SELECT " + GetKeywordColumns() + |
| 181 " FROM keywords ORDER BY id ASC"); | 170 " FROM keywords ORDER BY id ASC"); |
| 182 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 171 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
| 183 | 172 |
| 184 std::set<TemplateURLID> bad_entries; | 173 std::set<TemplateURLID> bad_entries; |
| 185 while (s.Step()) { | 174 while (s.Step()) { |
| 186 keywords->push_back(TemplateURLData()); | 175 keywords->push_back(TemplateURLData()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 199 bool KeywordTable::UpdateKeyword(const TemplateURLData& data) { | 188 bool KeywordTable::UpdateKeyword(const TemplateURLData& data) { |
| 200 DCHECK(data.id); | 189 DCHECK(data.id); |
| 201 sql::Statement s(db_->GetUniqueStatement("UPDATE keywords SET short_name=?, " | 190 sql::Statement s(db_->GetUniqueStatement("UPDATE keywords SET short_name=?, " |
| 202 "keyword=?, favicon_url=?, url=?, safe_for_autoreplace=?, " | 191 "keyword=?, favicon_url=?, url=?, safe_for_autoreplace=?, " |
| 203 "originating_url=?, date_created=?, usage_count=?, input_encodings=?, " | 192 "originating_url=?, date_created=?, usage_count=?, input_encodings=?, " |
| 204 "show_in_default_list=?, suggest_url=?, prepopulate_id=?, " | 193 "show_in_default_list=?, suggest_url=?, prepopulate_id=?, " |
| 205 "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=?, " | 194 "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=?, " |
| 206 "alternate_urls=? WHERE id=?")); | 195 "alternate_urls=? WHERE id=?")); |
| 207 BindURLToStatement(data, &s, 17, 0); // "17" binds id() as the last item. | 196 BindURLToStatement(data, &s, 17, 0); // "17" binds id() as the last item. |
| 208 | 197 |
| 209 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 198 return s.Run(); |
| 210 } | 199 } |
| 211 | 200 |
| 212 bool KeywordTable::SetDefaultSearchProviderID(int64 id) { | 201 bool KeywordTable::SetDefaultSearchProviderID(int64 id) { |
| 213 // Added for http://crbug.com/116952. | 202 return meta_table_->SetValue(kDefaultSearchProviderKey, id); |
| 214 UMA_HISTOGRAM_COUNTS_100("Search.DefaultSearchProviderID", | |
| 215 static_cast<int32>(id)); | |
| 216 return meta_table_->SetValue(kDefaultSearchProviderKey, id) && | |
| 217 UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | |
| 218 } | 203 } |
| 219 | 204 |
| 220 int64 KeywordTable::GetDefaultSearchProviderID() { | 205 int64 KeywordTable::GetDefaultSearchProviderID() { |
| 221 int64 value = kInvalidTemplateURLID; | 206 int64 value = kInvalidTemplateURLID; |
| 222 meta_table_->GetValue(kDefaultSearchProviderKey, &value); | 207 meta_table_->GetValue(kDefaultSearchProviderKey, &value); |
| 223 return value; | 208 return value; |
| 224 } | 209 } |
| 225 | 210 |
| 226 bool KeywordTable::GetDefaultSearchProviderBackup(TemplateURLData* backup) { | |
| 227 if (!IsBackupSignatureValid(WebDatabase::kCurrentVersionNumber)) | |
| 228 return false; | |
| 229 | |
| 230 int64 backup_id = kInvalidTemplateURLID; | |
| 231 if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_id)) { | |
| 232 LOG(ERROR) << "No default search id backup found."; | |
| 233 return false; | |
| 234 } | |
| 235 std::string query("SELECT " + GetKeywordColumns() + | |
| 236 " FROM keywords_backup WHERE id=?"); | |
| 237 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | |
| 238 s.BindInt64(0, backup_id); | |
| 239 | |
| 240 if (!s.Step()) { | |
| 241 LOG_IF(ERROR, s.Succeeded()) | |
| 242 << "No default search provider with backup id."; | |
| 243 return false; | |
| 244 } | |
| 245 | |
| 246 if (!GetKeywordDataFromStatement(s, backup)) | |
| 247 return false; | |
| 248 | |
| 249 // ID has no meaning for the backup and should be kInvalidTemplateURLID in | |
| 250 // case the TemplateURL will be added to keywords if missing. | |
| 251 backup->id = kInvalidTemplateURLID; | |
| 252 return true; | |
| 253 } | |
| 254 | |
| 255 bool KeywordTable::DidDefaultSearchProviderChange() { | |
| 256 if (!IsBackupSignatureValid(WebDatabase::kCurrentVersionNumber)) { | |
| 257 UMA_HISTOGRAM_ENUMERATION( | |
| 258 protector::kProtectorHistogramDefaultSearchProvider, | |
| 259 protector::kProtectorErrorBackupInvalid, | |
| 260 protector::kProtectorErrorCount); | |
| 261 LOG(ERROR) << "Backup signature is invalid."; | |
| 262 return true; | |
| 263 } | |
| 264 | |
| 265 int64 backup_id = kInvalidTemplateURLID; | |
| 266 meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_id); | |
| 267 int64 current_id = GetDefaultSearchProviderID(); | |
| 268 if (backup_id == current_id) { | |
| 269 // Either this is a new profile and both IDs are kInvalidTemplateURLID or | |
| 270 // the search engines with the ids are equal. | |
| 271 if (backup_id == kInvalidTemplateURLID) { | |
| 272 UMA_HISTOGRAM_ENUMERATION( | |
| 273 protector::kProtectorHistogramDefaultSearchProvider, | |
| 274 backup_overwritten_ ? | |
| 275 protector::kProtectorErrorOverwrittenByMigration : | |
| 276 protector::kProtectorErrorValueValidZero, | |
| 277 protector::kProtectorErrorCount); | |
| 278 return false; | |
| 279 } | |
| 280 std::string backup_url; | |
| 281 std::string current_url; | |
| 282 if (GetKeywordAsString(backup_id, "keywords_backup", &backup_url) && | |
| 283 GetKeywordAsString(current_id, "keywords", ¤t_url) && | |
| 284 current_url == backup_url) { | |
| 285 UMA_HISTOGRAM_ENUMERATION( | |
| 286 protector::kProtectorHistogramDefaultSearchProvider, | |
| 287 backup_overwritten_ ? | |
| 288 protector::kProtectorErrorOverwrittenByMigration : | |
| 289 protector::kProtectorErrorValueValid, | |
| 290 protector::kProtectorErrorCount); | |
| 291 return false; | |
| 292 } | |
| 293 } | |
| 294 | |
| 295 UMA_HISTOGRAM_ENUMERATION( | |
| 296 protector::kProtectorHistogramDefaultSearchProvider, | |
| 297 protector::kProtectorErrorValueChanged, | |
| 298 protector::kProtectorErrorCount); | |
| 299 LOG(WARNING) << "Default Search Provider has changed."; | |
| 300 return true; | |
| 301 } | |
| 302 | |
| 303 bool KeywordTable::SetBuiltinKeywordVersion(int version) { | 211 bool KeywordTable::SetBuiltinKeywordVersion(int version) { |
| 304 return meta_table_->SetValue(kBuiltinKeywordVersion, version); | 212 return meta_table_->SetValue(kBuiltinKeywordVersion, version); |
| 305 } | 213 } |
| 306 | 214 |
| 307 int KeywordTable::GetBuiltinKeywordVersion() { | 215 int KeywordTable::GetBuiltinKeywordVersion() { |
| 308 int version = 0; | 216 int version = 0; |
| 309 return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0; | 217 return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0; |
| 310 } | 218 } |
| 311 | 219 |
| 312 // static | 220 // static |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 bool KeywordTable::MigrateToVersion38AddLastModifiedColumn() { | 278 bool KeywordTable::MigrateToVersion38AddLastModifiedColumn() { |
| 371 return db_->Execute( | 279 return db_->Execute( |
| 372 "ALTER TABLE keywords ADD COLUMN last_modified INTEGER DEFAULT 0"); | 280 "ALTER TABLE keywords ADD COLUMN last_modified INTEGER DEFAULT 0"); |
| 373 } | 281 } |
| 374 | 282 |
| 375 bool KeywordTable::MigrateToVersion39AddSyncGUIDColumn() { | 283 bool KeywordTable::MigrateToVersion39AddSyncGUIDColumn() { |
| 376 return db_->Execute("ALTER TABLE keywords ADD COLUMN sync_guid VARCHAR"); | 284 return db_->Execute("ALTER TABLE keywords ADD COLUMN sync_guid VARCHAR"); |
| 377 } | 285 } |
| 378 | 286 |
| 379 bool KeywordTable::MigrateToVersion44AddDefaultSearchProviderBackup() { | 287 bool KeywordTable::MigrateToVersion44AddDefaultSearchProviderBackup() { |
| 380 if (IsBackupSignatureValid(44)) | 288 sql::Transaction transaction(db_); |
| 381 return true; | 289 if (!transaction.Begin()) |
| 382 backup_overwritten_ = true; | 290 return false; |
| 383 return UpdateBackupSignature(44); | 291 |
| 292 int64 default_search_id = GetDefaultSearchProviderID(); | |
| 293 if (!meta_table_->SetValue("Default Search Provider ID Backup", | |
| 294 default_search_id)) { | |
|
Peter Kasting
2012/12/11 20:09:06
Nit: File style: No {} when body is one line (seve
Ivan Korotkov
2012/12/12 17:02:57
Done.
| |
| 295 return false; | |
| 296 } | |
| 297 | |
| 298 // Backup of all keywords. | |
| 299 if (db_->DoesTableExist("keywords_backup") && | |
| 300 !db_->Execute("DROP TABLE keywords_backup")) { | |
| 301 return false; | |
| 302 } | |
| 303 | |
| 304 std::string query("CREATE TABLE keywords_backup AS SELECT " + | |
| 305 ColumnsForVersion(44, false) + " FROM keywords ORDER BY id ASC"); | |
| 306 if (!db_->Execute(query.c_str())) | |
| 307 return false; | |
| 308 | |
| 309 return transaction.Commit(); | |
| 384 } | 310 } |
| 385 | 311 |
| 386 bool KeywordTable::MigrateToVersion45RemoveLogoIDAndAutogenerateColumns() { | 312 bool KeywordTable::MigrateToVersion45RemoveLogoIDAndAutogenerateColumns() { |
| 387 sql::Transaction transaction(db_); | 313 sql::Transaction transaction(db_); |
| 388 if (!transaction.Begin()) | 314 if (!transaction.Begin()) |
| 389 return false; | 315 return false; |
| 390 | 316 |
| 391 // The version 43 migration should have been written to do this, but since it | 317 // The version 43 migration should have been written to do this, but since it |
| 392 // wasn't, we'll do it now. Unfortunately a previous change deleted this for | 318 // wasn't, we'll do it now. Unfortunately a previous change deleted this for |
| 393 // some users, so we can't be sure this will succeed (so don't bail on error). | 319 // some users, so we can't be sure this will succeed (so don't bail on error). |
| 394 meta_table_->DeleteKey("Default Search Provider Backup"); | 320 meta_table_->DeleteKey("Default Search Provider Backup"); |
| 395 | 321 |
| 396 if (!MigrateKeywordsTableForVersion45("keywords")) | 322 if (!MigrateKeywordsTableForVersion45("keywords")) |
| 397 return false; | 323 return false; |
| 398 | 324 |
| 399 if (IsBackupSignatureValid(44)) { | 325 // Migrate the keywords backup table as well. |
| 400 // Migrate the keywords backup table as well. | 326 if (!MigrateKeywordsTableForVersion45("keywords_backup") || |
| 401 if (!MigrateKeywordsTableForVersion45("keywords_backup") || !SignBackup(45)) | 327 !meta_table_->SetValue("Default Search Provider ID Backup Signature", |
| 402 return false; | 328 "")) { |
|
Peter Kasting
2012/12/11 20:09:06
Nit: std::string() (2 palces)
Ivan Korotkov
2012/12/12 17:02:57
Done.
| |
| 403 } else { | 329 return false; |
| 404 // Old backup was invalid; drop the table entirely, which will trigger the | |
| 405 // protector code to prompt the user and recreate the table. | |
| 406 if (db_->DoesTableExist("keywords_backup") && | |
| 407 !db_->Execute("DROP TABLE keywords_backup")) | |
| 408 return false; | |
| 409 } | 330 } |
| 410 | 331 |
| 411 return transaction.Commit(); | 332 return transaction.Commit(); |
| 412 } | 333 } |
| 413 | 334 |
| 414 bool KeywordTable::MigrateToVersion47AddAlternateURLsColumn() { | 335 bool KeywordTable::MigrateToVersion47AddAlternateURLsColumn() { |
| 415 sql::Transaction transaction(db_); | 336 sql::Transaction transaction(db_); |
| 416 | 337 |
| 417 // Fill the |alternate_urls| column with empty strings, otherwise it breaks | 338 // Fill the |alternate_urls| column with empty strings, otherwise it breaks |
| 418 // code relying on GetTableContents that concatenates the strings from all | 339 // code relying on GetTableContents that concatenates the strings from all |
| 419 // the columns. | 340 // the columns. |
| 420 if (!transaction.Begin() || | 341 if (!transaction.Begin() || |
| 421 !db_->Execute("ALTER TABLE keywords ADD COLUMN " | 342 !db_->Execute("ALTER TABLE keywords ADD COLUMN " |
| 422 "alternate_urls VARCHAR DEFAULT ''")) | 343 "alternate_urls VARCHAR DEFAULT ''")) |
| 423 return false; | 344 return false; |
| 424 | 345 |
| 425 if (IsBackupSignatureValid(46)) { | 346 // Migrate the keywords backup table as well. |
| 426 // Migrate the keywords backup table as well. | 347 if (!db_->Execute("ALTER TABLE keywords_backup ADD COLUMN " |
| 427 if (!db_->Execute("ALTER TABLE keywords_backup ADD COLUMN " | 348 "alternate_urls VARCHAR DEFAULT ''") || |
| 428 "alternate_urls VARCHAR DEFAULT ''") || | 349 !meta_table_->SetValue("Default Search Provider ID Backup Signature", |
| 429 !SignBackup(47)) | 350 "")) { |
| 430 return false; | 351 return false; |
| 431 } else { | |
| 432 // Old backup was invalid; drop the table entirely, which will trigger the | |
| 433 // protector code to prompt the user and recreate the table. | |
| 434 if (db_->DoesTableExist("keywords_backup") && | |
| 435 !db_->Execute("DROP TABLE keywords_backup")) | |
| 436 return false; | |
| 437 } | 352 } |
| 438 | 353 |
| 439 return transaction.Commit(); | 354 return transaction.Commit(); |
| 440 } | 355 } |
| 441 | 356 |
| 357 bool KeywordTable::MigrateToVersion48RemoveKeywordsBackup() { | |
| 358 sql::Transaction transaction(db_); | |
| 359 if (!transaction.Begin()) | |
| 360 return false; | |
| 361 | |
| 362 if (!meta_table_->DeleteKey("Default Search Provider ID Backup") || | |
| 363 !meta_table_->DeleteKey("Default Search Provider ID Backup Signature")) { | |
| 364 return false; | |
| 365 } | |
| 366 | |
| 367 if (!db_->Execute("DROP TABLE keywords_backup")) | |
| 368 return false; | |
| 369 | |
| 370 return transaction.Commit(); | |
| 371 } | |
| 372 | |
| 442 // static | 373 // static |
| 443 bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s, | 374 bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s, |
| 444 TemplateURLData* data) { | 375 TemplateURLData* data) { |
| 445 DCHECK(data); | 376 DCHECK(data); |
| 446 | 377 |
| 447 data->short_name = s.ColumnString16(1); | 378 data->short_name = s.ColumnString16(1); |
| 448 data->SetKeyword(s.ColumnString16(2)); | 379 data->SetKeyword(s.ColumnString16(2)); |
| 449 // Due to past bugs, we might have persisted entries with empty URLs. Avoid | 380 // Due to past bugs, we might have persisted entries with empty URLs. Avoid |
| 450 // reading these out. (GetKeywords() will delete these entries on return.) | 381 // reading these out. (GetKeywords() will delete these entries on return.) |
| 451 // NOTE: This code should only be needed as long as we might be reading such | 382 // NOTE: This code should only be needed as long as we might be reading such |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 476 std::string alternate_url; | 407 std::string alternate_url; |
| 477 for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) { | 408 for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) { |
| 478 if (alternate_urls_value->GetString(i, &alternate_url)) | 409 if (alternate_urls_value->GetString(i, &alternate_url)) |
| 479 data->alternate_urls.push_back(alternate_url); | 410 data->alternate_urls.push_back(alternate_url); |
| 480 } | 411 } |
| 481 } | 412 } |
| 482 | 413 |
| 483 return true; | 414 return true; |
| 484 } | 415 } |
| 485 | 416 |
| 486 bool KeywordTable::GetSignatureData(int table_version, std::string* backup) { | |
| 487 DCHECK(backup); | |
| 488 | |
| 489 int64 backup_value = kInvalidTemplateURLID; | |
| 490 if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_value)) { | |
| 491 LOG(ERROR) << "No backup id for signing."; | |
| 492 return false; | |
| 493 } | |
| 494 | |
| 495 std::string keywords_backup_data; | |
| 496 if (!GetTableContents("keywords_backup", table_version, | |
| 497 &keywords_backup_data)) { | |
| 498 LOG(ERROR) << "Can't get keywords backup data"; | |
| 499 return false; | |
| 500 } | |
| 501 *backup = base::Int64ToString(backup_value) + keywords_backup_data; | |
| 502 return true; | |
| 503 } | |
| 504 | |
| 505 bool KeywordTable::GetTableContents(const char* table_name, | 417 bool KeywordTable::GetTableContents(const char* table_name, |
| 506 int table_version, | 418 int table_version, |
| 507 std::string* contents) { | 419 std::string* contents) { |
| 508 DCHECK(contents); | 420 DCHECK(contents); |
| 509 | 421 |
| 510 if (!db_->DoesTableExist(table_name)) | 422 if (!db_->DoesTableExist(table_name)) |
| 511 return false; | 423 return false; |
| 512 | 424 |
| 513 contents->clear(); | 425 contents->clear(); |
| 514 std::string query("SELECT " + ColumnsForVersion(table_version, true) + | 426 std::string query("SELECT " + ColumnsForVersion(table_version, true) + |
| 515 " FROM " + std::string(table_name) + " ORDER BY id ASC"); | 427 " FROM " + std::string(table_name) + " ORDER BY id ASC"); |
| 516 sql::Statement s((table_version == WebDatabase::kCurrentVersionNumber) ? | 428 sql::Statement s((table_version == WebDatabase::kCurrentVersionNumber) ? |
| 517 db_->GetCachedStatement(sql::StatementID(table_name), query.c_str()) : | 429 db_->GetCachedStatement(sql::StatementID(table_name), query.c_str()) : |
| 518 db_->GetUniqueStatement(query.c_str())); | 430 db_->GetUniqueStatement(query.c_str())); |
| 519 while (s.Step()) | 431 while (s.Step()) |
| 520 *contents += s.ColumnString(0); | 432 *contents += s.ColumnString(0); |
| 521 return s.Succeeded(); | 433 return s.Succeeded(); |
| 522 } | 434 } |
| 523 | 435 |
| 524 bool KeywordTable::UpdateBackupSignature(int table_version) { | |
| 525 sql::Transaction transaction(db_); | |
| 526 if (!transaction.Begin()) | |
| 527 return false; | |
| 528 | |
| 529 int64 id = kInvalidTemplateURLID; | |
| 530 if (!UpdateDefaultSearchProviderIDBackup(&id)) { | |
| 531 LOG(ERROR) << "Failed to update default search id backup."; | |
| 532 return false; | |
| 533 } | |
| 534 | |
| 535 // Backup of all keywords. | |
| 536 if (db_->DoesTableExist("keywords_backup") && | |
| 537 !db_->Execute("DROP TABLE keywords_backup")) | |
| 538 return false; | |
| 539 | |
| 540 std::string query("CREATE TABLE keywords_backup AS SELECT " + | |
| 541 ColumnsForVersion(table_version, false) + | |
| 542 " FROM keywords ORDER BY id ASC"); | |
| 543 if (!db_->Execute(query.c_str())) { | |
| 544 LOG(ERROR) << "Failed to create keywords_backup table."; | |
| 545 return false; | |
| 546 } | |
| 547 | |
| 548 return SignBackup(table_version) && transaction.Commit(); | |
| 549 } | |
| 550 | |
| 551 bool KeywordTable::SignBackup(int table_version) { | |
| 552 std::string data_to_sign; | |
| 553 if (!GetSignatureData(table_version, &data_to_sign)) { | |
| 554 LOG(ERROR) << "No data to sign."; | |
| 555 return false; | |
| 556 } | |
| 557 | |
| 558 std::string signature = protector::SignSetting(data_to_sign); | |
| 559 if (signature.empty()) { | |
| 560 LOG(ERROR) << "Signature is empty"; | |
| 561 return false; | |
| 562 } | |
| 563 | |
| 564 return meta_table_->SetValue(kBackupSignatureKey, signature); | |
| 565 } | |
| 566 | |
| 567 bool KeywordTable::IsBackupSignatureValid(int table_version) { | |
| 568 std::string signature; | |
| 569 std::string signature_data; | |
| 570 return meta_table_->GetValue(kBackupSignatureKey, &signature) && | |
| 571 GetSignatureData(table_version, &signature_data) && | |
| 572 protector::IsSettingValid(signature_data, signature); | |
| 573 } | |
| 574 | |
| 575 bool KeywordTable::GetKeywordAsString(TemplateURLID id, | 436 bool KeywordTable::GetKeywordAsString(TemplateURLID id, |
| 576 const std::string& table_name, | 437 const std::string& table_name, |
| 577 std::string* result) { | 438 std::string* result) { |
| 578 std::string query("SELECT " + | 439 std::string query("SELECT " + |
| 579 ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) + | 440 ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) + |
| 580 " FROM " + table_name + " WHERE id=?"); | 441 " FROM " + table_name + " WHERE id=?"); |
| 581 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 442 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
| 582 s.BindInt64(0, id); | 443 s.BindInt64(0, id); |
| 583 | 444 |
| 584 if (!s.Step()) { | 445 if (!s.Step()) { |
| 585 LOG_IF(WARNING, s.Succeeded()) << "No keyword with id: " << id | 446 LOG_IF(WARNING, s.Succeeded()) << "No keyword with id: " << id |
| 586 << ", ignoring."; | 447 << ", ignoring."; |
| 587 return true; | 448 return true; |
| 588 } | 449 } |
| 589 | 450 |
| 590 if (!s.Succeeded()) | 451 if (!s.Succeeded()) |
| 591 return false; | 452 return false; |
| 592 | 453 |
| 593 *result = s.ColumnString(0); | 454 *result = s.ColumnString(0); |
| 594 return true; | 455 return true; |
| 595 } | 456 } |
| 596 | 457 |
| 597 bool KeywordTable::UpdateDefaultSearchProviderIDBackup(TemplateURLID* id) { | |
| 598 DCHECK(id); | |
| 599 int64 default_search_id = GetDefaultSearchProviderID(); | |
| 600 if (!meta_table_->SetValue(kDefaultSearchIDBackupKey, | |
| 601 default_search_id)) { | |
| 602 LOG(ERROR) << "Can't write default search id backup."; | |
| 603 return false; | |
| 604 } | |
| 605 | |
| 606 *id = default_search_id; | |
| 607 return true; | |
| 608 } | |
| 609 | |
| 610 bool KeywordTable::MigrateKeywordsTableForVersion45(const std::string& name) { | 458 bool KeywordTable::MigrateKeywordsTableForVersion45(const std::string& name) { |
| 611 // Create a new table without the columns we're dropping. | 459 // Create a new table without the columns we're dropping. |
| 612 if (!db_->Execute("CREATE TABLE keywords_temp (" | 460 if (!db_->Execute("CREATE TABLE keywords_temp (" |
| 613 "id INTEGER PRIMARY KEY," | 461 "id INTEGER PRIMARY KEY," |
| 614 "short_name VARCHAR NOT NULL," | 462 "short_name VARCHAR NOT NULL," |
| 615 "keyword VARCHAR NOT NULL," | 463 "keyword VARCHAR NOT NULL," |
| 616 "favicon_url VARCHAR NOT NULL," | 464 "favicon_url VARCHAR NOT NULL," |
| 617 "url VARCHAR NOT NULL," | 465 "url VARCHAR NOT NULL," |
| 618 "safe_for_autoreplace INTEGER," | 466 "safe_for_autoreplace INTEGER," |
| 619 "originating_url VARCHAR," | 467 "originating_url VARCHAR," |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 684 } | 532 } |
| 685 } | 533 } |
| 686 | 534 |
| 687 // Replace the old table with the new one. | 535 // Replace the old table with the new one. |
| 688 sql = "DROP TABLE " + name; | 536 sql = "DROP TABLE " + name; |
| 689 if (!db_->Execute(sql.c_str())) | 537 if (!db_->Execute(sql.c_str())) |
| 690 return false; | 538 return false; |
| 691 sql = "ALTER TABLE keywords_temp RENAME TO " + name; | 539 sql = "ALTER TABLE keywords_temp RENAME TO " + name; |
| 692 return db_->Execute(sql.c_str()); | 540 return db_->Execute(sql.c_str()); |
| 693 } | 541 } |
| OLD | NEW |