[email protected] | eaee4df | 2014-07-04 05:00:12 | [diff] [blame] | 1 | // Copyright 2014 The Chromium Authors. All rights reserved. |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 5 | #include "components/search_engines/keyword_table.h" |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 6 | |
avi | f57136c1 | 2015-12-25 23:27:45 | [diff] [blame] | 7 | #include <stddef.h> |
| 8 | |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 9 | #include <memory> |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 10 | #include <set> |
| 11 | |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 12 | #include "base/json/json_reader.h" |
| 13 | #include "base/json/json_writer.h" |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 14 | #include "base/logging.h" |
[email protected] | 3ea1b18 | 2013-02-08 22:38:41 | [diff] [blame] | 15 | #include "base/strings/string_number_conversions.h" |
mgiuca | 30f7588 | 2017-03-28 02:07:19 | [diff] [blame] | 16 | #include "base/strings/string_piece.h" |
[email protected] | 1988e1c | 2013-02-28 20:27:42 | [diff] [blame] | 17 | #include "base/strings/string_split.h" |
[email protected] | 9f0abdb | 2013-06-10 21:49:34 | [diff] [blame] | 18 | #include "base/strings/string_util.h" |
[email protected] | e309f31 | 2013-06-07 21:50:08 | [diff] [blame] | 19 | #include "base/strings/utf_string_conversions.h" |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 20 | #include "base/values.h" |
[email protected] | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 21 | #include "components/history/core/browser/url_database.h" |
[email protected] | eb7c2e2 | 2014-06-12 16:26:07 | [diff] [blame] | 22 | #include "components/search_engines/search_terms_data.h" |
[email protected] | d550cb0 | 2014-06-25 06:48:11 | [diff] [blame] | 23 | #include "components/search_engines/template_url.h" |
[email protected] | 06d54841 | 2013-04-03 21:24:08 | [diff] [blame] | 24 | #include "components/webdata/common/web_database.h" |
[email protected] | f0a54b2 | 2011-07-19 18:40:21 | [diff] [blame] | 25 | #include "sql/statement.h" |
[email protected] | 67bb274 | 2011-12-03 08:45:24 | [diff] [blame] | 26 | #include "sql/transaction.h" |
[email protected] | 761fa470 | 2013-07-02 15:25:15 | [diff] [blame] | 27 | #include "url/gurl.h" |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 28 | |
| 29 | using base::Time; |
| 30 | |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 31 | // static |
| 32 | const char KeywordTable::kDefaultSearchProviderKey[] = |
| 33 | "Default Search Provider ID"; |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 34 | |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 35 | namespace { |
| 36 | |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 37 | // Keys used in the meta table. |
[email protected] | 43276157 | 2011-10-19 05:19:26 | [diff] [blame] | 38 | const char kBuiltinKeywordVersion[] = "Builtin Keyword Version"; |
| 39 | |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 40 | const std::string ColumnsForVersion(int version, bool concatenated) { |
mgiuca | 30f7588 | 2017-03-28 02:07:19 | [diff] [blame] | 41 | std::vector<base::StringPiece> columns; |
[email protected] | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 42 | |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 43 | columns.push_back("id"); |
| 44 | columns.push_back("short_name"); |
| 45 | columns.push_back("keyword"); |
| 46 | columns.push_back("favicon_url"); |
| 47 | columns.push_back("url"); |
| 48 | columns.push_back("safe_for_autoreplace"); |
| 49 | columns.push_back("originating_url"); |
| 50 | columns.push_back("date_created"); |
| 51 | columns.push_back("usage_count"); |
| 52 | columns.push_back("input_encodings"); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 53 | if (version <= 67) { |
| 54 | // Column removed after version 67. |
| 55 | columns.push_back("show_in_default_list"); |
| 56 | } |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 57 | columns.push_back("suggest_url"); |
| 58 | columns.push_back("prepopulate_id"); |
| 59 | if (version <= 44) { |
| 60 | // Columns removed after version 44. |
| 61 | columns.push_back("autogenerate_keyword"); |
| 62 | columns.push_back("logo_id"); |
| 63 | } |
| 64 | columns.push_back("created_by_policy"); |
| 65 | columns.push_back("instant_url"); |
| 66 | columns.push_back("last_modified"); |
| 67 | columns.push_back("sync_guid"); |
| 68 | if (version >= 47) { |
| 69 | // Column added in version 47. |
| 70 | columns.push_back("alternate_urls"); |
| 71 | } |
[email protected] | 008987b0 | 2013-01-03 21:22:43 | [diff] [blame] | 72 | if (version >= 49) { |
| 73 | // Column added in version 49. |
| 74 | columns.push_back("search_terms_replacement_key"); |
| 75 | } |
[email protected] | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 76 | if (version >= 52) { |
| 77 | // Column added in version 52. |
| 78 | columns.push_back("image_url"); |
| 79 | columns.push_back("search_url_post_params"); |
| 80 | columns.push_back("suggest_url_post_params"); |
| 81 | columns.push_back("instant_url_post_params"); |
| 82 | columns.push_back("image_url_post_params"); |
| 83 | } |
[email protected] | 041238dd | 2013-08-19 21:05:12 | [diff] [blame] | 84 | if (version >= 53) { |
| 85 | // Column added in version 53. |
| 86 | columns.push_back("new_tab_url"); |
| 87 | } |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 88 | if (version >= 69) { |
| 89 | // Column added in version 69. |
| 90 | columns.push_back("last_visited"); |
| 91 | } |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 92 | |
brettw | d94a2214 | 2015-07-15 05:19:26 | [diff] [blame] | 93 | return base::JoinString(columns, std::string(concatenated ? " || " : ", ")); |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 94 | } |
| 95 | |
[email protected] | 764d0b8b | 2011-12-14 13:26:22 | [diff] [blame] | 96 | |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 97 | // Inserts the data from |data| into |s|. |s| is assumed to have slots for all |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 98 | // the columns in the keyword table. |id_column| is the slot number to bind |
[email protected] | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 99 | // |data|'s |id| to; |starting_column| is the slot number of the first of a |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 100 | // contiguous set of slots to bind all the other fields to. |
[email protected] | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 101 | void BindURLToStatement(const TemplateURLData& data, |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 102 | sql::Statement* s, |
| 103 | int id_column, |
| 104 | int starting_column) { |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 105 | // Serialize |alternate_urls| to JSON. |
| 106 | // TODO(beaudoin): Check what it would take to use a new table to store |
| 107 | // alternate_urls while keeping backups and table signature in a good state. |
| 108 | // See: crbug.com/153520 |
[email protected] | e53a7f29 | 2013-12-23 21:43:38 | [diff] [blame] | 109 | base::ListValue alternate_urls_value; |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 110 | for (size_t i = 0; i < data.alternate_urls.size(); ++i) |
| 111 | alternate_urls_value.AppendString(data.alternate_urls[i]); |
| 112 | std::string alternate_urls; |
estade | 8d04646 | 2015-05-16 01:02:34 | [diff] [blame] | 113 | base::JSONWriter::Write(alternate_urls_value, &alternate_urls); |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 114 | |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 115 | s->BindInt64(id_column, data.id); |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 116 | s->BindString16(starting_column, data.short_name()); |
[email protected] | 7b596f6 | 2012-05-08 01:34:25 | [diff] [blame] | 117 | s->BindString16(starting_column + 1, data.keyword()); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 118 | s->BindString(starting_column + 2, data.favicon_url.is_valid() ? |
[email protected] | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 119 | history::URLDatabase::GURLToDatabaseURL(data.favicon_url) : |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 120 | std::string()); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 121 | s->BindString(starting_column + 3, data.url()); |
| 122 | s->BindBool(starting_column + 4, data.safe_for_autoreplace); |
| 123 | s->BindString(starting_column + 5, data.originating_url.is_valid() ? |
[email protected] | bf5c532d | 2014-07-05 00:29:53 | [diff] [blame] | 124 | history::URLDatabase::GURLToDatabaseURL(data.originating_url) : |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 125 | std::string()); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 126 | s->BindInt64(starting_column + 6, data.date_created.ToTimeT()); |
| 127 | s->BindInt(starting_column + 7, data.usage_count); |
brettw | d94a2214 | 2015-07-15 05:19:26 | [diff] [blame] | 128 | s->BindString(starting_column + 8, |
| 129 | base::JoinString(data.input_encodings, ";")); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 130 | s->BindString(starting_column + 9, data.suggestions_url); |
| 131 | s->BindInt(starting_column + 10, data.prepopulate_id); |
| 132 | s->BindBool(starting_column + 11, data.created_by_policy); |
| 133 | s->BindString(starting_column + 12, data.instant_url); |
| 134 | s->BindInt64(starting_column + 13, data.last_modified.ToTimeT()); |
| 135 | s->BindString(starting_column + 14, data.sync_guid); |
| 136 | s->BindString(starting_column + 15, alternate_urls); |
| 137 | s->BindString(starting_column + 16, data.search_terms_replacement_key); |
| 138 | s->BindString(starting_column + 17, data.image_url); |
| 139 | s->BindString(starting_column + 18, data.search_url_post_params); |
| 140 | s->BindString(starting_column + 19, data.suggestions_url_post_params); |
| 141 | s->BindString(starting_column + 20, data.instant_url_post_params); |
| 142 | s->BindString(starting_column + 21, data.image_url_post_params); |
| 143 | s->BindString(starting_column + 22, data.new_tab_url); |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 144 | s->BindInt64(starting_column + 23, data.last_visited.ToTimeT()); |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 145 | } |
[email protected] | 43276157 | 2011-10-19 05:19:26 | [diff] [blame] | 146 | |
[email protected] | 3e95f4d | 2013-03-20 23:21:01 | [diff] [blame] | 147 | WebDatabaseTable::TypeKey GetKey() { |
[email protected] | 56be8f5 | 2013-04-10 19:43:30 | [diff] [blame] | 148 | // We just need a unique constant. Use the address of a static that |
| 149 | // COMDAT folding won't touch in an optimizing linker. |
| 150 | static int table_key = 0; |
[email protected] | 3e95f4d | 2013-03-20 23:21:01 | [diff] [blame] | 151 | return reinterpret_cast<void*>(&table_key); |
| 152 | } |
| 153 | |
| 154 | } // namespace |
| 155 | |
| 156 | KeywordTable::KeywordTable() { |
[email protected] | 2adf7df | 2012-07-14 19:16:55 | [diff] [blame] | 157 | } |
| 158 | |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 159 | KeywordTable::~KeywordTable() {} |
| 160 | |
[email protected] | 3e95f4d | 2013-03-20 23:21:01 | [diff] [blame] | 161 | KeywordTable* KeywordTable::FromWebDatabase(WebDatabase* db) { |
| 162 | return static_cast<KeywordTable*>(db->GetTable(GetKey())); |
| 163 | } |
| 164 | |
| 165 | WebDatabaseTable::TypeKey KeywordTable::GetTypeKey() const { |
| 166 | return GetKey(); |
| 167 | } |
| 168 | |
[email protected] | 942cd28 | 2014-03-25 06:38:47 | [diff] [blame] | 169 | bool KeywordTable::CreateTablesIfNecessary() { |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 170 | return db_->DoesTableExist("keywords") || |
[email protected] | 102253f | 2012-12-14 17:00:58 | [diff] [blame] | 171 | db_->Execute("CREATE TABLE keywords (" |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 172 | "id INTEGER PRIMARY KEY," |
| 173 | "short_name VARCHAR NOT NULL," |
| 174 | "keyword VARCHAR NOT NULL," |
| 175 | "favicon_url VARCHAR NOT NULL," |
| 176 | "url VARCHAR NOT NULL," |
| 177 | "safe_for_autoreplace INTEGER," |
| 178 | "originating_url VARCHAR," |
| 179 | "date_created INTEGER DEFAULT 0," |
| 180 | "usage_count INTEGER DEFAULT 0," |
| 181 | "input_encodings VARCHAR," |
| 182 | "suggest_url VARCHAR," |
| 183 | "prepopulate_id INTEGER DEFAULT 0," |
| 184 | "created_by_policy INTEGER DEFAULT 0," |
| 185 | "instant_url VARCHAR," |
| 186 | "last_modified INTEGER DEFAULT 0," |
| 187 | "sync_guid VARCHAR," |
| 188 | "alternate_urls VARCHAR," |
| 189 | "search_terms_replacement_key VARCHAR," |
| 190 | "image_url VARCHAR," |
| 191 | "search_url_post_params VARCHAR," |
| 192 | "suggest_url_post_params VARCHAR," |
| 193 | "instant_url_post_params VARCHAR," |
| 194 | "image_url_post_params VARCHAR," |
| 195 | "new_tab_url VARCHAR," |
| 196 | " last_visited INTEGER DEFAULT 0)"); |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 197 | } |
| 198 | |
[email protected] | 4db2dd8d | 2011-03-30 16:11:26 | [diff] [blame] | 199 | bool KeywordTable::IsSyncable() { |
| 200 | return true; |
| 201 | } |
| 202 | |
[email protected] | ad52b77 | 2013-03-12 22:24:08 | [diff] [blame] | 203 | bool KeywordTable::MigrateToVersion(int version, |
[email protected] | ad52b77 | 2013-03-12 22:24:08 | [diff] [blame] | 204 | bool* update_compatible_version) { |
| 205 | // Migrate if necessary. |
| 206 | switch (version) { |
[email protected] | 041238dd | 2013-08-19 21:05:12 | [diff] [blame] | 207 | case 53: |
| 208 | *update_compatible_version = true; |
| 209 | return MigrateToVersion53AddNewTabURLColumn(); |
vasilii | 1fb8425 | 2014-11-06 11:59:09 | [diff] [blame] | 210 | case 59: |
| 211 | *update_compatible_version = true; |
| 212 | return MigrateToVersion59RemoveExtensionKeywords(); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 213 | case 68: |
| 214 | *update_compatible_version = true; |
| 215 | return MigrateToVersion68RemoveShowInDefaultListColumn(); |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 216 | case 69: |
| 217 | return MigrateToVersion69AddLastVisitedColumn(); |
[email protected] | ad52b77 | 2013-03-12 22:24:08 | [diff] [blame] | 218 | } |
| 219 | |
| 220 | return true; |
| 221 | } |
| 222 | |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 223 | bool KeywordTable::PerformOperations(const Operations& operations) { |
| 224 | sql::Transaction transaction(db_); |
| 225 | if (!transaction.Begin()) |
| 226 | return false; |
[email protected] | bed29d94 | 2011-12-22 19:25:51 | [diff] [blame] | 227 | |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 228 | for (Operations::const_iterator i(operations.begin()); i != operations.end(); |
| 229 | ++i) { |
| 230 | switch (i->first) { |
| 231 | case ADD: |
| 232 | if (!AddKeyword(i->second)) |
| 233 | return false; |
| 234 | break; |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 235 | |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 236 | case REMOVE: |
| 237 | if (!RemoveKeyword(i->second.id)) |
| 238 | return false; |
| 239 | break; |
[email protected] | bed29d94 | 2011-12-22 19:25:51 | [diff] [blame] | 240 | |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 241 | case UPDATE: |
| 242 | if (!UpdateKeyword(i->second)) |
| 243 | return false; |
| 244 | break; |
| 245 | } |
| 246 | } |
| 247 | |
| 248 | return transaction.Commit(); |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 249 | } |
| 250 | |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 251 | bool KeywordTable::GetKeywords(Keywords* keywords) { |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 252 | std::string query("SELECT " + GetKeywordColumns() + |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 253 | " FROM keywords ORDER BY id ASC"); |
| 254 | sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
[email protected] | bed29d94 | 2011-12-22 19:25:51 | [diff] [blame] | 255 | |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 256 | std::set<TemplateURLID> bad_entries; |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 257 | while (s.Step()) { |
| 258 | keywords->push_back(TemplateURLData()); |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 259 | if (!GetKeywordDataFromStatement(s, &keywords->back())) { |
| 260 | bad_entries.insert(s.ColumnInt64(0)); |
| 261 | keywords->pop_back(); |
| 262 | } |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 263 | } |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 264 | bool succeeded = s.Succeeded(); |
| 265 | for (std::set<TemplateURLID>::const_iterator i(bad_entries.begin()); |
| 266 | i != bad_entries.end(); ++i) |
| 267 | succeeded &= RemoveKeyword(*i); |
| 268 | return succeeded; |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 269 | } |
| 270 | |
avi | f57136c1 | 2015-12-25 23:27:45 | [diff] [blame] | 271 | bool KeywordTable::SetDefaultSearchProviderID(int64_t id) { |
[email protected] | 102253f | 2012-12-14 17:00:58 | [diff] [blame] | 272 | return meta_table_->SetValue(kDefaultSearchProviderKey, id); |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 273 | } |
| 274 | |
avi | f57136c1 | 2015-12-25 23:27:45 | [diff] [blame] | 275 | int64_t KeywordTable::GetDefaultSearchProviderID() { |
| 276 | int64_t value = kInvalidTemplateURLID; |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 277 | meta_table_->GetValue(kDefaultSearchProviderKey, &value); |
[email protected] | 75a4eca | 2011-10-26 20:40:09 | [diff] [blame] | 278 | return value; |
| 279 | } |
| 280 | |
[email protected] | 43276157 | 2011-10-19 05:19:26 | [diff] [blame] | 281 | bool KeywordTable::SetBuiltinKeywordVersion(int version) { |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 282 | return meta_table_->SetValue(kBuiltinKeywordVersion, version); |
| 283 | } |
| 284 | |
[email protected] | 43276157 | 2011-10-19 05:19:26 | [diff] [blame] | 285 | int KeywordTable::GetBuiltinKeywordVersion() { |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 286 | int version = 0; |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 287 | return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0; |
[email protected] | 23e152e9 | 2011-03-30 15:52:34 | [diff] [blame] | 288 | } |
[email protected] | d8a9943 | 2011-04-05 15:48:34 | [diff] [blame] | 289 | |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 290 | // static |
| 291 | std::string KeywordTable::GetKeywordColumns() { |
| 292 | return ColumnsForVersion(WebDatabase::kCurrentVersionNumber, false); |
| 293 | } |
| 294 | |
[email protected] | 041238dd | 2013-08-19 21:05:12 | [diff] [blame] | 295 | bool KeywordTable::MigrateToVersion53AddNewTabURLColumn() { |
[email protected] | 6aa2df5c | 2014-04-02 01:39:15 | [diff] [blame] | 296 | return db_->Execute("ALTER TABLE keywords ADD COLUMN new_tab_url " |
| 297 | "VARCHAR DEFAULT ''"); |
[email protected] | 39682d1 | 2013-07-31 23:02:05 | [diff] [blame] | 298 | } |
| 299 | |
vasilii | 1fb8425 | 2014-11-06 11:59:09 | [diff] [blame] | 300 | bool KeywordTable::MigrateToVersion59RemoveExtensionKeywords() { |
| 301 | return db_->Execute("DELETE FROM keywords " |
| 302 | "WHERE url LIKE 'chrome-extension://%'"); |
| 303 | } |
| 304 | |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 305 | // SQLite does not support DROP COLUMN operation. So A new table is created |
| 306 | // without the show_in_default_list column. Data from all but the dropped column |
| 307 | // of the old table is copied into it. After that, the old table is dropped and |
| 308 | // the new table is renamed to it. |
| 309 | bool KeywordTable::MigrateToVersion68RemoveShowInDefaultListColumn() { |
| 310 | sql::Transaction transaction(db_); |
| 311 | std::string query_str = |
| 312 | std::string("INSERT INTO temp_keywords SELECT " + |
| 313 | ColumnsForVersion(68, false) + " FROM keywords"); |
| 314 | const char* clone_query = query_str.c_str(); |
| 315 | return transaction.Begin() && |
| 316 | db_->Execute( |
| 317 | "CREATE TABLE temp_keywords (" |
| 318 | "id INTEGER PRIMARY KEY," |
| 319 | "short_name VARCHAR NOT NULL," |
| 320 | "keyword VARCHAR NOT NULL," |
| 321 | "favicon_url VARCHAR NOT NULL," |
| 322 | "url VARCHAR NOT NULL," |
| 323 | "safe_for_autoreplace INTEGER," |
| 324 | "originating_url VARCHAR," |
| 325 | "date_created INTEGER DEFAULT 0," |
| 326 | "usage_count INTEGER DEFAULT 0," |
| 327 | "input_encodings VARCHAR," |
| 328 | "suggest_url VARCHAR," |
| 329 | "prepopulate_id INTEGER DEFAULT 0," |
| 330 | "created_by_policy INTEGER DEFAULT 0," |
| 331 | "instant_url VARCHAR," |
| 332 | "last_modified INTEGER DEFAULT 0," |
| 333 | "sync_guid VARCHAR," |
| 334 | "alternate_urls VARCHAR," |
| 335 | "search_terms_replacement_key VARCHAR," |
| 336 | "image_url VARCHAR," |
| 337 | "search_url_post_params VARCHAR," |
| 338 | "suggest_url_post_params VARCHAR," |
| 339 | "instant_url_post_params VARCHAR," |
| 340 | "image_url_post_params VARCHAR," |
| 341 | "new_tab_url VARCHAR)") && |
| 342 | db_->Execute(clone_query) && db_->Execute("DROP TABLE keywords") && |
| 343 | db_->Execute("ALTER TABLE temp_keywords RENAME TO keywords") && |
| 344 | transaction.Commit(); |
| 345 | } |
| 346 | |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 347 | bool KeywordTable::MigrateToVersion69AddLastVisitedColumn() { |
| 348 | return db_->Execute("ALTER TABLE keywords ADD COLUMN last_visited " |
| 349 | "INTEGER DEFAULT 0"); |
| 350 | } |
| 351 | |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 352 | // static |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 353 | bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s, |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 354 | TemplateURLData* data) { |
| 355 | DCHECK(data); |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 356 | |
mpearson | 3c6d7af | 2015-05-13 23:59:53 | [diff] [blame] | 357 | data->SetShortName(s.ColumnString16(1)); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 358 | data->SetKeyword(s.ColumnString16(2)); |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 359 | // Due to past bugs, we might have persisted entries with empty URLs. Avoid |
| 360 | // reading these out. (GetKeywords() will delete these entries on return.) |
| 361 | // NOTE: This code should only be needed as long as we might be reading such |
| 362 | // potentially-old data and can be removed afterward. |
| 363 | if (s.ColumnString(4).empty()) |
| 364 | return false; |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 365 | data->SetURL(s.ColumnString(4)); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 366 | data->suggestions_url = s.ColumnString(10); |
| 367 | data->instant_url = s.ColumnString(13); |
| 368 | data->image_url = s.ColumnString(18); |
| 369 | data->new_tab_url = s.ColumnString(23); |
| 370 | data->search_url_post_params = s.ColumnString(19); |
| 371 | data->suggestions_url_post_params = s.ColumnString(20); |
| 372 | data->instant_url_post_params = s.ColumnString(21); |
| 373 | data->image_url_post_params = s.ColumnString(22); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 374 | data->favicon_url = GURL(s.ColumnString(3)); |
| 375 | data->originating_url = GURL(s.ColumnString(6)); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 376 | data->safe_for_autoreplace = s.ColumnBool(5); |
brettw | 8be197d1 | 2015-07-23 23:23:31 | [diff] [blame] | 377 | data->input_encodings = base::SplitString( |
| 378 | s.ColumnString(9), ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 379 | data->id = s.ColumnInt64(0); |
| 380 | data->date_created = Time::FromTimeT(s.ColumnInt64(7)); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 381 | data->last_modified = Time::FromTimeT(s.ColumnInt64(14)); |
| 382 | data->created_by_policy = s.ColumnBool(12); |
[email protected] | 573889f2 | 2012-04-07 01:31:54 | [diff] [blame] | 383 | data->usage_count = s.ColumnInt(8); |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 384 | data->prepopulate_id = s.ColumnInt(11); |
| 385 | data->sync_guid = s.ColumnString(15); |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 386 | |
| 387 | data->alternate_urls.clear(); |
| 388 | base::JSONReader json_reader; |
dcheng | d967d950 | 2016-04-21 22:36:51 | [diff] [blame] | 389 | std::unique_ptr<base::Value> value( |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 390 | json_reader.ReadToValue(s.ColumnString(16))); |
[email protected] | e53a7f29 | 2013-12-23 21:43:38 | [diff] [blame] | 391 | base::ListValue* alternate_urls_value; |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 392 | if (value.get() && value->GetAsList(&alternate_urls_value)) { |
| 393 | std::string alternate_url; |
| 394 | for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) { |
| 395 | if (alternate_urls_value->GetString(i, &alternate_url)) |
| 396 | data->alternate_urls.push_back(alternate_url); |
| 397 | } |
| 398 | } |
| 399 | |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 400 | data->search_terms_replacement_key = s.ColumnString(17); |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 401 | data->last_visited = Time::FromTimeT(s.ColumnInt64(24)); |
[email protected] | 008987b0 | 2013-01-03 21:22:43 | [diff] [blame] | 402 | |
[email protected] | 4e40f59bb | 2012-04-19 01:07:08 | [diff] [blame] | 403 | return true; |
[email protected] | fbfc372 | 2012-01-16 11:58:38 | [diff] [blame] | 404 | } |
| 405 | |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 406 | bool KeywordTable::AddKeyword(const TemplateURLData& data) { |
| 407 | DCHECK(data.id); |
| 408 | std::string query("INSERT INTO keywords (" + GetKeywordColumns() + ") " |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 409 | "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?," |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 410 | " ?,?)"); |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 411 | sql::Statement s(db_->GetCachedStatement(SQL_FROM_HERE, query.c_str())); |
| 412 | BindURLToStatement(data, &s, 0, 1); |
| 413 | |
| 414 | return s.Run(); |
| 415 | } |
| 416 | |
| 417 | bool KeywordTable::RemoveKeyword(TemplateURLID id) { |
| 418 | DCHECK(id); |
| 419 | sql::Statement s(db_->GetCachedStatement( |
| 420 | SQL_FROM_HERE, "DELETE FROM keywords WHERE id = ?")); |
| 421 | s.BindInt64(0, id); |
| 422 | |
| 423 | return s.Run(); |
| 424 | } |
| 425 | |
| 426 | bool KeywordTable::UpdateKeyword(const TemplateURLData& data) { |
| 427 | DCHECK(data.id); |
| 428 | sql::Statement s(db_->GetCachedStatement( |
| 429 | SQL_FROM_HERE, |
| 430 | "UPDATE keywords SET short_name=?, keyword=?, favicon_url=?, url=?, " |
| 431 | "safe_for_autoreplace=?, originating_url=?, date_created=?, " |
ltian | cf06dd01 | 2016-11-18 08:49:12 | [diff] [blame] | 432 | "usage_count=?, input_encodings=?, suggest_url=?, " |
| 433 | "prepopulate_id=?, created_by_policy=?, instant_url=?, " |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 434 | "last_modified=?, sync_guid=?, alternate_urls=?, " |
| 435 | "search_terms_replacement_key=?, image_url=?, search_url_post_params=?, " |
| 436 | "suggest_url_post_params=?, instant_url_post_params=?, " |
ltian | 8b5fc83 | 2016-12-02 23:43:35 | [diff] [blame] | 437 | "image_url_post_params=?, new_tab_url=?, last_visited=? WHERE id=?")); |
| 438 | BindURLToStatement(data, &s, 24, 0); // "24" binds id() as the last item. |
[email protected] | ad94ea3 | 2014-04-02 01:40:47 | [diff] [blame] | 439 | |
| 440 | return s.Run(); |
| 441 | } |
| 442 | |
[email protected] | 764d0b8b | 2011-12-14 13:26:22 | [diff] [blame] | 443 | bool KeywordTable::GetKeywordAsString(TemplateURLID id, |
| 444 | const std::string& table_name, |
| 445 | std::string* result) { |
[email protected] | 5b307875 | 2012-10-09 18:54:16 | [diff] [blame] | 446 | std::string query("SELECT " + |
| 447 | ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) + |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 448 | " FROM " + table_name + " WHERE id=?"); |
[email protected] | 764d0b8b | 2011-12-14 13:26:22 | [diff] [blame] | 449 | sql::Statement s(db_->GetUniqueStatement(query.c_str())); |
[email protected] | 67bb274 | 2011-12-03 08:45:24 | [diff] [blame] | 450 | s.BindInt64(0, id); |
[email protected] | ae6c59c | 2012-01-18 23:43:25 | [diff] [blame] | 451 | |
[email protected] | 67bb274 | 2011-12-03 08:45:24 | [diff] [blame] | 452 | if (!s.Step()) { |
[email protected] | e5f908e1 | 2012-03-13 21:10:14 | [diff] [blame] | 453 | LOG_IF(WARNING, s.Succeeded()) << "No keyword with id: " << id |
| 454 | << ", ignoring."; |
[email protected] | 67bb274 | 2011-12-03 08:45:24 | [diff] [blame] | 455 | return true; |
| 456 | } |
| 457 | |
[email protected] | ae6c59c | 2012-01-18 23:43:25 | [diff] [blame] | 458 | if (!s.Succeeded()) |
[email protected] | 67bb274 | 2011-12-03 08:45:24 | [diff] [blame] | 459 | return false; |
[email protected] | 67bb274 | 2011-12-03 08:45:24 | [diff] [blame] | 460 | |
| 461 | *result = s.ColumnString(0); |
| 462 | return true; |
| 463 | } |