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" | |
10 #include "base/json/json_writer.h" | |
9 #include "base/logging.h" | 11 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
11 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
12 #include "base/metrics/stats_counters.h" | 14 #include "base/metrics/stats_counters.h" |
13 #include "base/string_number_conversions.h" | 15 #include "base/string_number_conversions.h" |
14 #include "base/string_split.h" | 16 #include "base/string_split.h" |
15 #include "base/string_util.h" | 17 #include "base/string_util.h" |
16 #include "base/stringprintf.h" | 18 #include "base/stringprintf.h" |
17 #include "base/utf_string_conversions.h" | 19 #include "base/utf_string_conversions.h" |
20 #include "base/values.h" | |
18 #include "chrome/browser/history/history_database.h" | 21 #include "chrome/browser/history/history_database.h" |
19 #include "chrome/browser/protector/histograms.h" | 22 #include "chrome/browser/protector/histograms.h" |
20 #include "chrome/browser/protector/protector_utils.h" | 23 #include "chrome/browser/protector/protector_utils.h" |
21 #include "chrome/browser/search_engines/search_terms_data.h" | 24 #include "chrome/browser/search_engines/search_terms_data.h" |
22 #include "chrome/browser/search_engines/template_url.h" | 25 #include "chrome/browser/search_engines/template_url.h" |
23 #include "chrome/browser/search_engines/template_url_service.h" | 26 #include "chrome/browser/search_engines/template_url_service.h" |
24 #include "chrome/browser/webdata/web_database.h" | 27 #include "chrome/browser/webdata/web_database.h" |
25 #include "googleurl/src/gurl.h" | 28 #include "googleurl/src/gurl.h" |
26 #include "sql/statement.h" | 29 #include "sql/statement.h" |
27 #include "sql/transaction.h" | 30 #include "sql/transaction.h" |
28 | 31 |
29 using base::Time; | 32 using base::Time; |
30 | 33 |
31 // static | 34 // static |
32 const char KeywordTable::kDefaultSearchProviderKey[] = | 35 const char KeywordTable::kDefaultSearchProviderKey[] = |
33 "Default Search Provider ID"; | 36 "Default Search Provider ID"; |
34 const char KeywordTable::kDefaultSearchIDBackupKey[] = | 37 const char KeywordTable::kDefaultSearchIDBackupKey[] = |
35 "Default Search Provider ID Backup"; | 38 "Default Search Provider ID Backup"; |
36 const char KeywordTable::kBackupSignatureKey[] = | 39 const char KeywordTable::kBackupSignatureKey[] = |
37 "Default Search Provider ID Backup Signature"; | 40 "Default Search Provider ID Backup Signature"; |
38 const char KeywordTable::kKeywordColumns[] = "id, short_name, keyword, " | |
39 "favicon_url, url, safe_for_autoreplace, originating_url, date_created, " | |
40 "usage_count, input_encodings, show_in_default_list, suggest_url, " | |
41 "prepopulate_id, created_by_policy, instant_url, last_modified, sync_guid"; | |
42 | 41 |
43 namespace { | 42 namespace { |
44 | 43 |
45 // Keys used in the meta table. | 44 // Keys used in the meta table. |
46 const char kBuiltinKeywordVersion[] = "Builtin Keyword Version"; | 45 const char kBuiltinKeywordVersion[] = "Builtin Keyword Version"; |
47 | 46 |
48 // The set of columns up through version 44. (There were different columns | 47 const std::string ColumnsForVersion(int version, bool concatenated) { |
49 // below version 29 but none of the code below needs to worry about that case.) | 48 std::vector<std::string> columns; |
50 const char kKeywordColumnsVersion44Concatenated[] = "id || short_name || " | |
51 "keyword || favicon_url || url || safe_for_autoreplace || " | |
52 "originating_url || date_created || usage_count || input_encodings || " | |
53 "show_in_default_list || suggest_url || prepopulate_id || " | |
54 "autogenerate_keyword || logo_id || created_by_policy || instant_url || " | |
55 "last_modified || sync_guid"; | |
56 const char kKeywordColumnsVersion44[] = "id, short_name, keyword, favicon_url, " | |
57 "url, safe_for_autoreplace, originating_url, date_created, usage_count, " | |
58 "input_encodings, show_in_default_list, suggest_url, prepopulate_id, " | |
59 "autogenerate_keyword, logo_id, created_by_policy, instant_url, " | |
60 "last_modified, sync_guid"; | |
61 // NOTE: Remember to change what |kKeywordColumnsVersion45| says if the column | |
62 // set in |kKeywordColumns| changes, and update any code that needs to switch | |
63 // column sets based on a version number! | |
64 const char* const kKeywordColumnsVersion45 = KeywordTable::kKeywordColumns; | |
65 | 49 |
66 // The current columns. | 50 columns.push_back("id"); |
67 const char kKeywordColumnsConcatenated[] = "id || short_name || keyword || " | 51 columns.push_back("short_name"); |
68 "favicon_url || url || safe_for_autoreplace || originating_url || " | 52 columns.push_back("keyword"); |
69 "date_created || usage_count || input_encodings || show_in_default_list || " | 53 columns.push_back("favicon_url"); |
70 "suggest_url || prepopulate_id || created_by_policy || instant_url || " | 54 columns.push_back("url"); |
71 "last_modified || sync_guid"; | 55 columns.push_back("safe_for_autoreplace"); |
56 columns.push_back("originating_url"); | |
57 columns.push_back("date_created"); | |
58 columns.push_back("usage_count"); | |
59 columns.push_back("input_encodings"); | |
60 columns.push_back("show_in_default_list"); | |
61 columns.push_back("suggest_url"); | |
62 columns.push_back("prepopulate_id"); | |
63 if (version <= 44) { | |
64 // Columns removed after version 44. | |
65 columns.push_back("autogenerate_keyword"); | |
66 columns.push_back("logo_id"); | |
67 } | |
68 columns.push_back("created_by_policy"); | |
69 columns.push_back("instant_url"); | |
70 columns.push_back("last_modified"); | |
71 columns.push_back("sync_guid"); | |
72 if (version >= 47) { | |
73 // Column added in version 47. | |
74 columns.push_back("alternate_urls"); | |
75 } | |
76 | |
77 return JoinString(columns, std::string(concatenated ? " || " : ", ")); | |
Peter Kasting
2012/10/04 19:32:43
Good idea! Wish I'd thought of it back when I was
beaudoin
2012/10/04 23:10:45
:)
Ack.
| |
78 } | |
79 | |
72 | 80 |
73 // Inserts the data from |data| into |s|. |s| is assumed to have slots for all | 81 // Inserts the data from |data| into |s|. |s| is assumed to have slots for all |
74 // the columns in the keyword table. |id_column| is the slot number to bind | 82 // the columns in the keyword table. |id_column| is the slot number to bind |
75 // |data|'s |id| to; |starting_column| is the slot number of the first of a | 83 // |data|'s |id| to; |starting_column| is the slot number of the first of a |
76 // contiguous set of slots to bind all the other fields to. | 84 // contiguous set of slots to bind all the other fields to. |
77 void BindURLToStatement(const TemplateURLData& data, | 85 void BindURLToStatement(const TemplateURLData& data, |
78 sql::Statement* s, | 86 sql::Statement* s, |
79 int id_column, | 87 int id_column, |
80 int starting_column) { | 88 int starting_column) { |
89 // Serialize |alternate_urls| to JSON. | |
90 // TODO(beaudoin): Check what it would take to use a new table to store | |
91 // alternate_urls while keeping backups and table signature in a good state. | |
92 // See: crbug.com/153520 | |
93 ListValue alternate_urls_value; | |
94 for (size_t i = 0; i < data.alternate_urls.size(); ++i) | |
95 alternate_urls_value.AppendString(data.alternate_urls[i]); | |
96 std::string alternate_urls; | |
97 base::JSONWriter::Write(&alternate_urls_value, &alternate_urls); | |
98 | |
81 s->BindInt64(id_column, data.id); | 99 s->BindInt64(id_column, data.id); |
82 s->BindString16(starting_column, data.short_name); | 100 s->BindString16(starting_column, data.short_name); |
83 s->BindString16(starting_column + 1, data.keyword()); | 101 s->BindString16(starting_column + 1, data.keyword()); |
84 s->BindString(starting_column + 2, data.favicon_url.is_valid() ? | 102 s->BindString(starting_column + 2, data.favicon_url.is_valid() ? |
85 history::HistoryDatabase::GURLToDatabaseURL(data.favicon_url) : | 103 history::HistoryDatabase::GURLToDatabaseURL(data.favicon_url) : |
86 std::string()); | 104 std::string()); |
87 s->BindString(starting_column + 3, data.url()); | 105 s->BindString(starting_column + 3, data.url()); |
88 s->BindBool(starting_column + 4, data.safe_for_autoreplace); | 106 s->BindBool(starting_column + 4, data.safe_for_autoreplace); |
89 s->BindString(starting_column + 5, data.originating_url.is_valid() ? | 107 s->BindString(starting_column + 5, data.originating_url.is_valid() ? |
90 history::HistoryDatabase::GURLToDatabaseURL(data.originating_url) : | 108 history::HistoryDatabase::GURLToDatabaseURL(data.originating_url) : |
91 std::string()); | 109 std::string()); |
92 s->BindInt64(starting_column + 6, data.date_created.ToTimeT()); | 110 s->BindInt64(starting_column + 6, data.date_created.ToTimeT()); |
93 s->BindInt(starting_column + 7, data.usage_count); | 111 s->BindInt(starting_column + 7, data.usage_count); |
94 s->BindString(starting_column + 8, JoinString(data.input_encodings, ';')); | 112 s->BindString(starting_column + 8, JoinString(data.input_encodings, ';')); |
95 s->BindBool(starting_column + 9, data.show_in_default_list); | 113 s->BindBool(starting_column + 9, data.show_in_default_list); |
96 s->BindString(starting_column + 10, data.suggestions_url); | 114 s->BindString(starting_column + 10, data.suggestions_url); |
97 s->BindInt(starting_column + 11, data.prepopulate_id); | 115 s->BindInt(starting_column + 11, data.prepopulate_id); |
98 s->BindBool(starting_column + 12, data.created_by_policy); | 116 s->BindBool(starting_column + 12, data.created_by_policy); |
99 s->BindString(starting_column + 13, data.instant_url); | 117 s->BindString(starting_column + 13, data.instant_url); |
100 s->BindInt64(starting_column + 14, data.last_modified.ToTimeT()); | 118 s->BindInt64(starting_column + 14, data.last_modified.ToTimeT()); |
101 s->BindString(starting_column + 15, data.sync_guid); | 119 s->BindString(starting_column + 15, data.sync_guid); |
120 s->BindString(starting_column + 16, alternate_urls); | |
102 } | 121 } |
103 | 122 |
104 } // anonymous namespace | 123 } // anonymous namespace |
105 | 124 |
106 KeywordTable::KeywordTable(sql::Connection* db, sql::MetaTable* meta_table) | 125 KeywordTable::KeywordTable(sql::Connection* db, sql::MetaTable* meta_table) |
107 : WebDatabaseTable(db, meta_table), | 126 : WebDatabaseTable(db, meta_table), |
108 backup_overwritten_(false) { | 127 backup_overwritten_(false) { |
109 } | 128 } |
110 | 129 |
111 KeywordTable::~KeywordTable() {} | 130 KeywordTable::~KeywordTable() {} |
(...skipping 10 matching lines...) Expand all Loading... | |
122 "originating_url VARCHAR," | 141 "originating_url VARCHAR," |
123 "date_created INTEGER DEFAULT 0," | 142 "date_created INTEGER DEFAULT 0," |
124 "usage_count INTEGER DEFAULT 0," | 143 "usage_count INTEGER DEFAULT 0," |
125 "input_encodings VARCHAR," | 144 "input_encodings VARCHAR," |
126 "show_in_default_list INTEGER," | 145 "show_in_default_list INTEGER," |
127 "suggest_url VARCHAR," | 146 "suggest_url VARCHAR," |
128 "prepopulate_id INTEGER DEFAULT 0," | 147 "prepopulate_id INTEGER DEFAULT 0," |
129 "created_by_policy INTEGER DEFAULT 0," | 148 "created_by_policy INTEGER DEFAULT 0," |
130 "instant_url VARCHAR," | 149 "instant_url VARCHAR," |
131 "last_modified INTEGER DEFAULT 0," | 150 "last_modified INTEGER DEFAULT 0," |
132 "sync_guid VARCHAR)") && | 151 "sync_guid VARCHAR," |
152 "alternate_urls VARCHAR)") && | |
133 UpdateBackupSignature(WebDatabase::kCurrentVersionNumber)); | 153 UpdateBackupSignature(WebDatabase::kCurrentVersionNumber)); |
134 } | 154 } |
135 | 155 |
136 bool KeywordTable::IsSyncable() { | 156 bool KeywordTable::IsSyncable() { |
137 return true; | 157 return true; |
138 } | 158 } |
139 | 159 |
140 bool KeywordTable::AddKeyword(const TemplateURLData& data) { | 160 bool KeywordTable::AddKeyword(const TemplateURLData& data) { |
141 DCHECK(data.id); | 161 DCHECK(data.id); |
142 std::string query("INSERT INTO keywords (" + std::string(kKeywordColumns) + | 162 std::string query("INSERT INTO keywords (" + GetKeywordColumns() + |
143 ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); | 163 ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); |
144 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 164 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
145 BindURLToStatement(data, &s, 0, 1); | 165 BindURLToStatement(data, &s, 0, 1); |
146 | 166 |
147 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 167 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); |
148 } | 168 } |
149 | 169 |
150 bool KeywordTable::RemoveKeyword(TemplateURLID id) { | 170 bool KeywordTable::RemoveKeyword(TemplateURLID id) { |
151 DCHECK(id); | 171 DCHECK(id); |
152 sql::Statement s( | 172 sql::Statement s( |
153 db_->GetUniqueStatement("DELETE FROM keywords WHERE id = ?")); | 173 db_->GetUniqueStatement("DELETE FROM keywords WHERE id = ?")); |
154 s.BindInt64(0, id); | 174 s.BindInt64(0, id); |
155 | 175 |
156 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 176 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); |
157 } | 177 } |
158 | 178 |
159 bool KeywordTable::GetKeywords(Keywords* keywords) { | 179 bool KeywordTable::GetKeywords(Keywords* keywords) { |
160 std::string query("SELECT " + std::string(kKeywordColumns) + | 180 std::string query("SELECT " + GetKeywordColumns() + |
161 " FROM keywords ORDER BY id ASC"); | 181 " FROM keywords ORDER BY id ASC"); |
162 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 182 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
163 | 183 |
164 std::set<TemplateURLID> bad_entries; | 184 std::set<TemplateURLID> bad_entries; |
165 while (s.Step()) { | 185 while (s.Step()) { |
166 keywords->push_back(TemplateURLData()); | 186 keywords->push_back(TemplateURLData()); |
167 if (!GetKeywordDataFromStatement(s, &keywords->back())) { | 187 if (!GetKeywordDataFromStatement(s, &keywords->back())) { |
168 bad_entries.insert(s.ColumnInt64(0)); | 188 bad_entries.insert(s.ColumnInt64(0)); |
169 keywords->pop_back(); | 189 keywords->pop_back(); |
170 } | 190 } |
171 } | 191 } |
172 bool succeeded = s.Succeeded(); | 192 bool succeeded = s.Succeeded(); |
173 for (std::set<TemplateURLID>::const_iterator i(bad_entries.begin()); | 193 for (std::set<TemplateURLID>::const_iterator i(bad_entries.begin()); |
174 i != bad_entries.end(); ++i) | 194 i != bad_entries.end(); ++i) |
175 succeeded &= RemoveKeyword(*i); | 195 succeeded &= RemoveKeyword(*i); |
176 return succeeded; | 196 return succeeded; |
177 } | 197 } |
178 | 198 |
179 bool KeywordTable::UpdateKeyword(const TemplateURLData& data) { | 199 bool KeywordTable::UpdateKeyword(const TemplateURLData& data) { |
180 DCHECK(data.id); | 200 DCHECK(data.id); |
181 sql::Statement s(db_->GetUniqueStatement("UPDATE keywords SET short_name=?, " | 201 sql::Statement s(db_->GetUniqueStatement("UPDATE keywords SET short_name=?, " |
182 "keyword=?, favicon_url=?, url=?, safe_for_autoreplace=?, " | 202 "keyword=?, favicon_url=?, url=?, safe_for_autoreplace=?, " |
183 "originating_url=?, date_created=?, usage_count=?, input_encodings=?, " | 203 "originating_url=?, date_created=?, usage_count=?, input_encodings=?, " |
184 "show_in_default_list=?, suggest_url=?, prepopulate_id=?, " | 204 "show_in_default_list=?, suggest_url=?, prepopulate_id=?, " |
185 "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=? WHERE " | 205 "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=?, " |
186 "id=?")); | 206 "alternate_urls=? WHERE id=?")); |
187 BindURLToStatement(data, &s, 16, 0); // "16" binds id() as the last item. | 207 BindURLToStatement(data, &s, 17, 0); // "17" binds id() as the last item. |
188 | 208 |
189 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 209 return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); |
190 } | 210 } |
191 | 211 |
192 bool KeywordTable::SetDefaultSearchProviderID(int64 id) { | 212 bool KeywordTable::SetDefaultSearchProviderID(int64 id) { |
193 // Added for http://crbug.com/116952. | 213 // Added for http://crbug.com/116952. |
194 UMA_HISTOGRAM_COUNTS_100("Search.DefaultSearchProviderID", | 214 UMA_HISTOGRAM_COUNTS_100("Search.DefaultSearchProviderID", |
195 static_cast<int32>(id)); | 215 static_cast<int32>(id)); |
196 return meta_table_->SetValue(kDefaultSearchProviderKey, id) && | 216 return meta_table_->SetValue(kDefaultSearchProviderKey, id) && |
197 UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); | 217 UpdateBackupSignature(WebDatabase::kCurrentVersionNumber); |
198 } | 218 } |
199 | 219 |
200 int64 KeywordTable::GetDefaultSearchProviderID() { | 220 int64 KeywordTable::GetDefaultSearchProviderID() { |
201 int64 value = kInvalidTemplateURLID; | 221 int64 value = kInvalidTemplateURLID; |
202 meta_table_->GetValue(kDefaultSearchProviderKey, &value); | 222 meta_table_->GetValue(kDefaultSearchProviderKey, &value); |
203 return value; | 223 return value; |
204 } | 224 } |
205 | 225 |
206 bool KeywordTable::GetDefaultSearchProviderBackup(TemplateURLData* backup) { | 226 bool KeywordTable::GetDefaultSearchProviderBackup(TemplateURLData* backup) { |
207 if (!IsBackupSignatureValid(WebDatabase::kCurrentVersionNumber)) | 227 if (!IsBackupSignatureValid(WebDatabase::kCurrentVersionNumber)) |
208 return false; | 228 return false; |
209 | 229 |
210 int64 backup_id = kInvalidTemplateURLID; | 230 int64 backup_id = kInvalidTemplateURLID; |
211 if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_id)) { | 231 if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_id)) { |
212 LOG(ERROR) << "No default search id backup found."; | 232 LOG(ERROR) << "No default search id backup found."; |
213 return false; | 233 return false; |
214 } | 234 } |
215 std::string query("SELECT " + std::string(kKeywordColumns) + | 235 std::string query("SELECT " + GetKeywordColumns() + |
216 " FROM keywords_backup WHERE id=?"); | 236 " FROM keywords_backup WHERE id=?"); |
217 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 237 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
218 s.BindInt64(0, backup_id); | 238 s.BindInt64(0, backup_id); |
219 | 239 |
220 if (!s.Step()) { | 240 if (!s.Step()) { |
221 LOG_IF(ERROR, s.Succeeded()) | 241 LOG_IF(ERROR, s.Succeeded()) |
222 << "No default search provider with backup id."; | 242 << "No default search provider with backup id."; |
223 return false; | 243 return false; |
224 } | 244 } |
225 | 245 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
302 bool KeywordTable::MigrateToVersion26AddCreatedByPolicyColumn() { | 322 bool KeywordTable::MigrateToVersion26AddCreatedByPolicyColumn() { |
303 return db_->Execute("ALTER TABLE keywords ADD COLUMN created_by_policy " | 323 return db_->Execute("ALTER TABLE keywords ADD COLUMN created_by_policy " |
304 "INTEGER DEFAULT 0"); | 324 "INTEGER DEFAULT 0"); |
305 } | 325 } |
306 | 326 |
307 bool KeywordTable::MigrateToVersion28SupportsInstantColumn() { | 327 bool KeywordTable::MigrateToVersion28SupportsInstantColumn() { |
308 return db_->Execute("ALTER TABLE keywords ADD COLUMN supports_instant " | 328 return db_->Execute("ALTER TABLE keywords ADD COLUMN supports_instant " |
309 "INTEGER DEFAULT 0"); | 329 "INTEGER DEFAULT 0"); |
310 } | 330 } |
311 | 331 |
312 bool KeywordTable::MigrateToVersion29InstantUrlToSupportsInstant() { | 332 bool KeywordTable::MigrateToVersion29InstantURLToSupportsInstant() { |
313 sql::Transaction transaction(db_); | 333 sql::Transaction transaction(db_); |
314 return transaction.Begin() && | 334 return transaction.Begin() && |
315 db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url VARCHAR") && | 335 db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url VARCHAR") && |
316 db_->Execute("CREATE TABLE keywords_temp (" | 336 db_->Execute("CREATE TABLE keywords_temp (" |
317 "id INTEGER PRIMARY KEY," | 337 "id INTEGER PRIMARY KEY," |
318 "short_name VARCHAR NOT NULL," | 338 "short_name VARCHAR NOT NULL," |
319 "keyword VARCHAR NOT NULL," | 339 "keyword VARCHAR NOT NULL," |
320 "favicon_url VARCHAR NOT NULL," | 340 "favicon_url VARCHAR NOT NULL," |
321 "url VARCHAR NOT NULL," | 341 "url VARCHAR NOT NULL," |
322 "safe_for_autoreplace INTEGER," | 342 "safe_for_autoreplace INTEGER," |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
379 // Old backup was invalid; drop the table entirely, which will trigger the | 399 // Old backup was invalid; drop the table entirely, which will trigger the |
380 // protector code to prompt the user and recreate the table. | 400 // protector code to prompt the user and recreate the table. |
381 if (db_->DoesTableExist("keywords_backup") && | 401 if (db_->DoesTableExist("keywords_backup") && |
382 !db_->Execute("DROP TABLE keywords_backup")) | 402 !db_->Execute("DROP TABLE keywords_backup")) |
383 return false; | 403 return false; |
384 } | 404 } |
385 | 405 |
386 return transaction.Commit(); | 406 return transaction.Commit(); |
387 } | 407 } |
388 | 408 |
409 bool KeywordTable::MigrateToVersion47AddAlternateURLsColumn() { | |
410 sql::Transaction transaction(db_); | |
411 | |
412 // Fill the |alternate_urls| column with empty strings, otherwise it breaks | |
413 // code relying on GetTableContents that concatenates the strings from all | |
414 // the columns. | |
415 if (!transaction.Begin() || | |
416 !db_->Execute("ALTER TABLE keywords ADD COLUMN " | |
417 "alternate_urls VARCHAR DEFAULT ''")) | |
418 return false; | |
419 | |
420 if (IsBackupSignatureValid(46)) { | |
421 // Migrate the keywords backup table as well. | |
422 if (!db_->Execute("ALTER TABLE keywords_backup ADD COLUMN " | |
423 "alternate_urls VARCHAR DEFAULT ''") || | |
424 !SignBackup(47)) | |
425 return false; | |
426 } else { | |
427 // Old backup was invalid; drop the table entirely, which will trigger the | |
428 // protector code to prompt the user and recreate the table. | |
429 if (db_->DoesTableExist("keywords_backup") && | |
430 !db_->Execute("DROP TABLE keywords_backup")) | |
431 return false; | |
432 } | |
433 | |
434 return transaction.Commit(); | |
435 } | |
436 | |
437 // static | |
438 std::string KeywordTable::GetKeywordColumns() { | |
439 return ColumnsForVersion(WebDatabase::kCurrentVersionNumber, false); | |
440 } | |
441 | |
389 // static | 442 // static |
390 bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s, | 443 bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s, |
391 TemplateURLData* data) { | 444 TemplateURLData* data) { |
392 DCHECK(data); | 445 DCHECK(data); |
446 | |
393 data->short_name = s.ColumnString16(1); | 447 data->short_name = s.ColumnString16(1); |
394 data->SetKeyword(s.ColumnString16(2)); | 448 data->SetKeyword(s.ColumnString16(2)); |
395 // Due to past bugs, we might have persisted entries with empty URLs. Avoid | 449 // Due to past bugs, we might have persisted entries with empty URLs. Avoid |
396 // reading these out. (GetKeywords() will delete these entries on return.) | 450 // reading these out. (GetKeywords() will delete these entries on return.) |
397 // NOTE: This code should only be needed as long as we might be reading such | 451 // NOTE: This code should only be needed as long as we might be reading such |
398 // potentially-old data and can be removed afterward. | 452 // potentially-old data and can be removed afterward. |
399 if (s.ColumnString(4).empty()) | 453 if (s.ColumnString(4).empty()) |
400 return false; | 454 return false; |
401 data->SetURL(s.ColumnString(4)); | 455 data->SetURL(s.ColumnString(4)); |
402 data->suggestions_url = s.ColumnString(11); | 456 data->suggestions_url = s.ColumnString(11); |
403 data->instant_url = s.ColumnString(14); | 457 data->instant_url = s.ColumnString(14); |
404 data->favicon_url = GURL(s.ColumnString(3)); | 458 data->favicon_url = GURL(s.ColumnString(3)); |
405 data->originating_url = GURL(s.ColumnString(6)); | 459 data->originating_url = GURL(s.ColumnString(6)); |
406 data->show_in_default_list = s.ColumnBool(10); | 460 data->show_in_default_list = s.ColumnBool(10); |
407 data->safe_for_autoreplace = s.ColumnBool(5); | 461 data->safe_for_autoreplace = s.ColumnBool(5); |
408 base::SplitString(s.ColumnString(9), ';', &data->input_encodings); | 462 base::SplitString(s.ColumnString(9), ';', &data->input_encodings); |
409 data->id = s.ColumnInt64(0); | 463 data->id = s.ColumnInt64(0); |
410 data->date_created = Time::FromTimeT(s.ColumnInt64(7)); | 464 data->date_created = Time::FromTimeT(s.ColumnInt64(7)); |
411 data->last_modified = Time::FromTimeT(s.ColumnInt64(15)); | 465 data->last_modified = Time::FromTimeT(s.ColumnInt64(15)); |
412 data->created_by_policy = s.ColumnBool(13); | 466 data->created_by_policy = s.ColumnBool(13); |
413 data->usage_count = s.ColumnInt(8); | 467 data->usage_count = s.ColumnInt(8); |
414 data->prepopulate_id = s.ColumnInt(12); | 468 data->prepopulate_id = s.ColumnInt(12); |
415 data->sync_guid = s.ColumnString(16); | 469 data->sync_guid = s.ColumnString(16); |
470 | |
471 data->alternate_urls.clear(); | |
472 base::JSONReader json_reader; | |
473 scoped_ptr<Value> value(json_reader.ReadToValue(s.ColumnString(17))); | |
474 ListValue* alternate_urls_value; | |
475 if (value.get() && value->GetAsList(&alternate_urls_value)) { | |
476 std::string alternate_url; | |
477 for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) { | |
478 if (alternate_urls_value->GetString(i, &alternate_url)) | |
479 data->alternate_urls.push_back(alternate_url); | |
480 } | |
481 } | |
482 | |
416 return true; | 483 return true; |
417 } | 484 } |
418 | 485 |
419 bool KeywordTable::GetSignatureData(int table_version, std::string* backup) { | 486 bool KeywordTable::GetSignatureData(int table_version, std::string* backup) { |
420 DCHECK(backup); | 487 DCHECK(backup); |
421 | 488 |
422 int64 backup_value = kInvalidTemplateURLID; | 489 int64 backup_value = kInvalidTemplateURLID; |
423 if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_value)) { | 490 if (!meta_table_->GetValue(kDefaultSearchIDBackupKey, &backup_value)) { |
424 LOG(ERROR) << "No backup id for signing."; | 491 LOG(ERROR) << "No backup id for signing."; |
425 return false; | 492 return false; |
(...skipping 11 matching lines...) Expand all Loading... | |
437 | 504 |
438 bool KeywordTable::GetTableContents(const char* table_name, | 505 bool KeywordTable::GetTableContents(const char* table_name, |
439 int table_version, | 506 int table_version, |
440 std::string* contents) { | 507 std::string* contents) { |
441 DCHECK(contents); | 508 DCHECK(contents); |
442 | 509 |
443 if (!db_->DoesTableExist(table_name)) | 510 if (!db_->DoesTableExist(table_name)) |
444 return false; | 511 return false; |
445 | 512 |
446 contents->clear(); | 513 contents->clear(); |
447 std::string query("SELECT " + | 514 std::string query("SELECT " + ColumnsForVersion(table_version, true) + |
448 std::string((table_version <= 44) ? | |
449 kKeywordColumnsVersion44Concatenated : kKeywordColumnsConcatenated) + | |
450 " FROM " + std::string(table_name) + " ORDER BY id ASC"); | 515 " FROM " + std::string(table_name) + " ORDER BY id ASC"); |
451 sql::Statement s((table_version == WebDatabase::kCurrentVersionNumber) ? | 516 sql::Statement s((table_version == WebDatabase::kCurrentVersionNumber) ? |
452 db_->GetCachedStatement(sql::StatementID(table_name), query.c_str()) : | 517 db_->GetCachedStatement(sql::StatementID(table_name), query.c_str()) : |
453 db_->GetUniqueStatement(query.c_str())); | 518 db_->GetUniqueStatement(query.c_str())); |
454 while (s.Step()) | 519 while (s.Step()) |
455 *contents += s.ColumnString(0); | 520 *contents += s.ColumnString(0); |
456 return s.Succeeded(); | 521 return s.Succeeded(); |
457 } | 522 } |
458 | 523 |
459 bool KeywordTable::UpdateBackupSignature(int table_version) { | 524 bool KeywordTable::UpdateBackupSignature(int table_version) { |
460 sql::Transaction transaction(db_); | 525 sql::Transaction transaction(db_); |
461 if (!transaction.Begin()) | 526 if (!transaction.Begin()) |
462 return false; | 527 return false; |
463 | 528 |
464 int64 id = kInvalidTemplateURLID; | 529 int64 id = kInvalidTemplateURLID; |
465 if (!UpdateDefaultSearchProviderIDBackup(&id)) { | 530 if (!UpdateDefaultSearchProviderIDBackup(&id)) { |
466 LOG(ERROR) << "Failed to update default search id backup."; | 531 LOG(ERROR) << "Failed to update default search id backup."; |
467 return false; | 532 return false; |
468 } | 533 } |
469 | 534 |
470 // Backup of all keywords. | 535 // Backup of all keywords. |
471 if (db_->DoesTableExist("keywords_backup") && | 536 if (db_->DoesTableExist("keywords_backup") && |
472 !db_->Execute("DROP TABLE keywords_backup")) | 537 !db_->Execute("DROP TABLE keywords_backup")) |
473 return false; | 538 return false; |
474 | 539 |
475 std::string query("CREATE TABLE keywords_backup AS SELECT " + | 540 std::string query("CREATE TABLE keywords_backup AS SELECT " + |
476 std::string((table_version <= 44) ? | 541 ColumnsForVersion(table_version, false) + |
477 kKeywordColumnsVersion44 : kKeywordColumns) + | |
478 " FROM keywords ORDER BY id ASC"); | 542 " FROM keywords ORDER BY id ASC"); |
479 if (!db_->Execute(query.c_str())) { | 543 if (!db_->Execute(query.c_str())) { |
480 LOG(ERROR) << "Failed to create keywords_backup table."; | 544 LOG(ERROR) << "Failed to create keywords_backup table."; |
481 return false; | 545 return false; |
482 } | 546 } |
483 | 547 |
484 return SignBackup(table_version) && transaction.Commit(); | 548 return SignBackup(table_version) && transaction.Commit(); |
485 } | 549 } |
486 | 550 |
487 bool KeywordTable::SignBackup(int table_version) { | 551 bool KeywordTable::SignBackup(int table_version) { |
(...skipping 16 matching lines...) Expand all Loading... | |
504 std::string signature; | 568 std::string signature; |
505 std::string signature_data; | 569 std::string signature_data; |
506 return meta_table_->GetValue(kBackupSignatureKey, &signature) && | 570 return meta_table_->GetValue(kBackupSignatureKey, &signature) && |
507 GetSignatureData(table_version, &signature_data) && | 571 GetSignatureData(table_version, &signature_data) && |
508 protector::IsSettingValid(signature_data, signature); | 572 protector::IsSettingValid(signature_data, signature); |
509 } | 573 } |
510 | 574 |
511 bool KeywordTable::GetKeywordAsString(TemplateURLID id, | 575 bool KeywordTable::GetKeywordAsString(TemplateURLID id, |
512 const std::string& table_name, | 576 const std::string& table_name, |
513 std::string* result) { | 577 std::string* result) { |
514 std::string query("SELECT " + std::string(kKeywordColumnsConcatenated) + | 578 std::string query("SELECT " + |
579 ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) + | |
515 " FROM " + table_name + " WHERE id=?"); | 580 " FROM " + table_name + " WHERE id=?"); |
516 sql::Statement s(db_->GetUniqueStatement(query.c_str())); | 581 sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
517 s.BindInt64(0, id); | 582 s.BindInt64(0, id); |
518 | 583 |
519 if (!s.Step()) { | 584 if (!s.Step()) { |
520 LOG_IF(WARNING, s.Succeeded()) << "No keyword with id: " << id | 585 LOG_IF(WARNING, s.Succeeded()) << "No keyword with id: " << id |
521 << ", ignoring."; | 586 << ", ignoring."; |
522 return true; | 587 return true; |
523 } | 588 } |
524 | 589 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
557 "input_encodings VARCHAR," | 622 "input_encodings VARCHAR," |
558 "show_in_default_list INTEGER," | 623 "show_in_default_list INTEGER," |
559 "suggest_url VARCHAR," | 624 "suggest_url VARCHAR," |
560 "prepopulate_id INTEGER DEFAULT 0," | 625 "prepopulate_id INTEGER DEFAULT 0," |
561 "created_by_policy INTEGER DEFAULT 0," | 626 "created_by_policy INTEGER DEFAULT 0," |
562 "instant_url VARCHAR," | 627 "instant_url VARCHAR," |
563 "last_modified INTEGER DEFAULT 0," | 628 "last_modified INTEGER DEFAULT 0," |
564 "sync_guid VARCHAR)")) | 629 "sync_guid VARCHAR)")) |
565 return false; | 630 return false; |
566 std::string sql("INSERT INTO keywords_temp SELECT " + | 631 std::string sql("INSERT INTO keywords_temp SELECT " + |
567 std::string(kKeywordColumnsVersion45) + " FROM " + name); | 632 ColumnsForVersion(46, false) + " FROM " + name); |
568 if (!db_->Execute(sql.c_str())) | 633 if (!db_->Execute(sql.c_str())) |
569 return false; | 634 return false; |
570 | 635 |
571 // NOTE: The ORDER BY here ensures that the uniquing process for keywords will | 636 // NOTE: The ORDER BY here ensures that the uniquing process for keywords will |
572 // happen identically on both the normal and backup tables. | 637 // happen identically on both the normal and backup tables. |
573 sql = "SELECT id, keyword, url, autogenerate_keyword FROM " + name + | 638 sql = "SELECT id, keyword, url, autogenerate_keyword FROM " + name + |
574 " ORDER BY id ASC"; | 639 " ORDER BY id ASC"; |
575 sql::Statement s(db_->GetUniqueStatement(sql.c_str())); | 640 sql::Statement s(db_->GetUniqueStatement(sql.c_str())); |
576 string16 placeholder_keyword(ASCIIToUTF16("dummy")); | 641 string16 placeholder_keyword(ASCIIToUTF16("dummy")); |
577 std::set<string16> keywords; | 642 std::set<string16> keywords; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
619 } | 684 } |
620 } | 685 } |
621 | 686 |
622 // Replace the old table with the new one. | 687 // Replace the old table with the new one. |
623 sql = "DROP TABLE " + name; | 688 sql = "DROP TABLE " + name; |
624 if (!db_->Execute(sql.c_str())) | 689 if (!db_->Execute(sql.c_str())) |
625 return false; | 690 return false; |
626 sql = "ALTER TABLE keywords_temp RENAME TO " + name; | 691 sql = "ALTER TABLE keywords_temp RENAME TO " + name; |
627 return db_->Execute(sql.c_str()); | 692 return db_->Execute(sql.c_str()); |
628 } | 693 } |
OLD | NEW |