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 3 // found in the LICENSE file. 4 5 #include <string> 6 #include <vector> 7 8 #include "base/files/scoped_temp_dir.h" 9 #include "base/path_service.h" 10 #include "base/stl_util.h" 11 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "base/time/time.h" 14 #include "chrome/browser/search_engines/template_url.h" 15 #include "chrome/browser/webdata/keyword_table.h" 16 #include "components/webdata/common/web_database.h" 17 #include "sql/statement.h" 18 #include "testing/gtest/include/gtest/gtest.h" 19 20 using base::Time; 21 using base::TimeDelta; 22 23 class KeywordTableTest : public testing::Test { 24 public: 25 KeywordTableTest() {} 26 virtual ~KeywordTableTest() {} 27 28 protected: 29 virtual void SetUp() { 30 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 31 file_ = temp_dir_.path().AppendASCII("TestWebDatabase"); 32 33 table_.reset(new KeywordTable); 34 db_.reset(new WebDatabase); 35 db_->AddTable(table_.get()); 36 ASSERT_EQ(sql::INIT_OK, db_->Init(file_)); 37 } 38 39 base::FilePath file_; 40 base::ScopedTempDir temp_dir_; 41 scoped_ptr<KeywordTable> table_; 42 scoped_ptr<WebDatabase> db_; 43 44 private: 45 DISALLOW_COPY_AND_ASSIGN(KeywordTableTest); 46 }; 47 48 49 TEST_F(KeywordTableTest, Keywords) { 50 TemplateURLData keyword; 51 keyword.short_name = ASCIIToUTF16("short_name"); 52 keyword.SetKeyword(ASCIIToUTF16("keyword")); 53 keyword.SetURL("http://url/"); 54 keyword.instant_url = "http://instant/"; 55 keyword.favicon_url = GURL("http://favicon.url/"); 56 keyword.originating_url = GURL("http://google.com/"); 57 keyword.show_in_default_list = true; 58 keyword.safe_for_autoreplace = true; 59 keyword.input_encodings.push_back("UTF-8"); 60 keyword.input_encodings.push_back("UTF-16"); 61 keyword.id = 1; 62 keyword.date_created = Time::Now(); 63 keyword.last_modified = keyword.date_created + TimeDelta::FromSeconds(10); 64 keyword.created_by_policy = true; 65 keyword.usage_count = 32; 66 keyword.prepopulate_id = 10; 67 EXPECT_TRUE(table_->AddKeyword(keyword)); 68 69 KeywordTable::Keywords keywords; 70 EXPECT_TRUE(table_->GetKeywords(&keywords)); 71 EXPECT_EQ(1U, keywords.size()); 72 const TemplateURLData& restored_keyword = keywords.front(); 73 74 EXPECT_EQ(keyword.short_name, restored_keyword.short_name); 75 EXPECT_EQ(keyword.keyword(), restored_keyword.keyword()); 76 EXPECT_EQ(keyword.url(), restored_keyword.url()); 77 EXPECT_EQ(keyword.suggestions_url, restored_keyword.suggestions_url); 78 EXPECT_EQ(keyword.instant_url, restored_keyword.instant_url); 79 EXPECT_EQ(keyword.favicon_url, restored_keyword.favicon_url); 80 EXPECT_EQ(keyword.originating_url, restored_keyword.originating_url); 81 EXPECT_EQ(keyword.show_in_default_list, 82 restored_keyword.show_in_default_list); 83 EXPECT_EQ(keyword.safe_for_autoreplace, 84 restored_keyword.safe_for_autoreplace); 85 EXPECT_EQ(keyword.input_encodings, restored_keyword.input_encodings); 86 EXPECT_EQ(keyword.id, restored_keyword.id); 87 // The database stores time only at the resolution of a second. 88 EXPECT_EQ(keyword.date_created.ToTimeT(), 89 restored_keyword.date_created.ToTimeT()); 90 EXPECT_EQ(keyword.last_modified.ToTimeT(), 91 restored_keyword.last_modified.ToTimeT()); 92 EXPECT_EQ(keyword.created_by_policy, restored_keyword.created_by_policy); 93 EXPECT_EQ(keyword.usage_count, restored_keyword.usage_count); 94 EXPECT_EQ(keyword.prepopulate_id, restored_keyword.prepopulate_id); 95 96 EXPECT_TRUE(table_->RemoveKeyword(restored_keyword.id)); 97 98 KeywordTable::Keywords empty_keywords; 99 EXPECT_TRUE(table_->GetKeywords(&empty_keywords)); 100 EXPECT_EQ(0U, empty_keywords.size()); 101 } 102 103 TEST_F(KeywordTableTest, KeywordMisc) { 104 EXPECT_EQ(kInvalidTemplateURLID, table_->GetDefaultSearchProviderID()); 105 EXPECT_EQ(0, table_->GetBuiltinKeywordVersion()); 106 107 TemplateURLData keyword; 108 keyword.short_name = ASCIIToUTF16("short_name"); 109 keyword.SetKeyword(ASCIIToUTF16("keyword")); 110 keyword.SetURL("http://url/"); 111 keyword.instant_url = "http://instant/"; 112 keyword.favicon_url = GURL("http://favicon.url/"); 113 keyword.originating_url = GURL("http://google.com/"); 114 keyword.show_in_default_list = true; 115 keyword.safe_for_autoreplace = true; 116 keyword.input_encodings.push_back("UTF-8"); 117 keyword.input_encodings.push_back("UTF-16"); 118 keyword.id = 10; 119 keyword.date_created = Time::Now(); 120 keyword.last_modified = keyword.date_created + TimeDelta::FromSeconds(10); 121 keyword.created_by_policy = true; 122 keyword.usage_count = 32; 123 keyword.prepopulate_id = 10; 124 EXPECT_TRUE(table_->AddKeyword(keyword)); 125 126 EXPECT_TRUE(table_->SetDefaultSearchProviderID(10)); 127 EXPECT_TRUE(table_->SetBuiltinKeywordVersion(11)); 128 129 EXPECT_EQ(10, table_->GetDefaultSearchProviderID()); 130 EXPECT_EQ(11, table_->GetBuiltinKeywordVersion()); 131 } 132 133 TEST_F(KeywordTableTest, GetTableContents) { 134 TemplateURLData keyword; 135 keyword.short_name = ASCIIToUTF16("short_name"); 136 keyword.SetKeyword(ASCIIToUTF16("keyword")); 137 keyword.SetURL("http://url/"); 138 keyword.suggestions_url = "url2"; 139 keyword.image_url = "http://image-search-url/"; 140 keyword.new_tab_url = "http://new-tab-url/"; 141 keyword.favicon_url = GURL("http://favicon.url/"); 142 keyword.show_in_default_list = true; 143 keyword.safe_for_autoreplace = true; 144 keyword.id = 1; 145 keyword.date_created = base::Time::UnixEpoch(); 146 keyword.last_modified = base::Time::UnixEpoch(); 147 keyword.sync_guid = "1234-5678-90AB-CDEF"; 148 keyword.alternate_urls.push_back("a_url1"); 149 keyword.alternate_urls.push_back("a_url2"); 150 keyword.search_terms_replacement_key = "espv"; 151 EXPECT_TRUE(table_->AddKeyword(keyword)); 152 153 keyword.SetKeyword(ASCIIToUTF16("url")); 154 keyword.instant_url = "http://instant2/"; 155 keyword.image_url.clear(); 156 keyword.new_tab_url.clear(); 157 keyword.originating_url = GURL("http://originating.url/"); 158 keyword.input_encodings.push_back("Shift_JIS"); 159 keyword.id = 2; 160 keyword.prepopulate_id = 5; 161 keyword.sync_guid = "FEDC-BA09-8765-4321"; 162 keyword.alternate_urls.clear(); 163 keyword.search_terms_replacement_key.clear(); 164 EXPECT_TRUE(table_->AddKeyword(keyword)); 165 166 const char kTestContents[] = "1short_namekeywordhttp://favicon.url/" 167 "http://url/1001url20001234-5678-90AB-CDEF[\"a_url1\",\"a_url2\"]espv" 168 "http://image-search-url/http://new-tab-url/2short_nameurl" 169 "http://favicon.url/http://url/1http://originating.url/00Shift_JIS1url250" 170 "http://instant2/0FEDC-BA09-8765-4321[]"; 171 172 std::string contents; 173 EXPECT_TRUE(table_->GetTableContents("keywords", 174 WebDatabase::kCurrentVersionNumber, &contents)); 175 EXPECT_EQ(kTestContents, contents); 176 } 177 178 TEST_F(KeywordTableTest, GetTableContentsOrdering) { 179 TemplateURLData keyword; 180 keyword.short_name = ASCIIToUTF16("short_name"); 181 keyword.SetKeyword(ASCIIToUTF16("keyword")); 182 keyword.SetURL("http://url/"); 183 keyword.suggestions_url = "url2"; 184 keyword.favicon_url = GURL("http://favicon.url/"); 185 keyword.show_in_default_list = true; 186 keyword.safe_for_autoreplace = true; 187 keyword.id = 2; 188 keyword.date_created = base::Time::UnixEpoch(); 189 keyword.last_modified = base::Time::UnixEpoch(); 190 keyword.sync_guid = "1234-5678-90AB-CDEF"; 191 keyword.alternate_urls.push_back("a_url1"); 192 keyword.alternate_urls.push_back("a_url2"); 193 keyword.search_terms_replacement_key = "espv"; 194 keyword.image_url = "http://image-search-url/"; 195 keyword.search_url_post_params = "ie=utf-8,oe=utf-8"; 196 keyword.image_url_post_params = "name=1,value=2"; 197 keyword.new_tab_url = "http://new-tab-url"; 198 EXPECT_TRUE(table_->AddKeyword(keyword)); 199 200 keyword.SetKeyword(ASCIIToUTF16("url")); 201 keyword.instant_url = "http://instant2/"; 202 keyword.originating_url = GURL("http://originating.url/"); 203 keyword.input_encodings.push_back("Shift_JIS"); 204 keyword.id = 1; 205 keyword.prepopulate_id = 5; 206 keyword.sync_guid = "FEDC-BA09-8765-4321"; 207 keyword.alternate_urls.clear(); 208 keyword.search_terms_replacement_key.clear(); 209 keyword.image_url.clear(); 210 keyword.search_url_post_params.clear(); 211 keyword.image_url_post_params.clear(); 212 keyword.new_tab_url.clear(); 213 EXPECT_TRUE(table_->AddKeyword(keyword)); 214 215 const char kTestContents[] = "1short_nameurlhttp://favicon.url/" 216 "http://url/1http://originating.url/00Shift_JIS1url250http://instant2/" 217 "0FEDC-BA09-8765-4321[]2short_namekeywordhttp://favicon.url/http://url/" 218 "1001url20001234-5678-90AB-CDEF[\"a_url1\",\"a_url2\"]espv" 219 "http://image-search-url/ie=utf-8,oe=utf-8name=1,value=2" 220 "http://new-tab-url"; 221 222 std::string contents; 223 EXPECT_TRUE(table_->GetTableContents("keywords", 224 WebDatabase::kCurrentVersionNumber, &contents)); 225 EXPECT_EQ(kTestContents, contents); 226 } 227 228 TEST_F(KeywordTableTest, UpdateKeyword) { 229 TemplateURLData keyword; 230 keyword.short_name = ASCIIToUTF16("short_name"); 231 keyword.SetKeyword(ASCIIToUTF16("keyword")); 232 keyword.SetURL("http://url/"); 233 keyword.suggestions_url = "url2"; 234 keyword.favicon_url = GURL("http://favicon.url/"); 235 keyword.show_in_default_list = true; 236 keyword.safe_for_autoreplace = true; 237 keyword.id = 1; 238 EXPECT_TRUE(table_->AddKeyword(keyword)); 239 240 keyword.SetKeyword(ASCIIToUTF16("url")); 241 keyword.instant_url = "http://instant2/"; 242 keyword.originating_url = GURL("http://originating.url/"); 243 keyword.input_encodings.push_back("Shift_JIS"); 244 keyword.prepopulate_id = 5; 245 EXPECT_TRUE(table_->UpdateKeyword(keyword)); 246 247 KeywordTable::Keywords keywords; 248 EXPECT_TRUE(table_->GetKeywords(&keywords)); 249 EXPECT_EQ(1U, keywords.size()); 250 const TemplateURLData& restored_keyword = keywords.front(); 251 252 EXPECT_EQ(keyword.short_name, restored_keyword.short_name); 253 EXPECT_EQ(keyword.keyword(), restored_keyword.keyword()); 254 EXPECT_EQ(keyword.suggestions_url, restored_keyword.suggestions_url); 255 EXPECT_EQ(keyword.instant_url, restored_keyword.instant_url); 256 EXPECT_EQ(keyword.favicon_url, restored_keyword.favicon_url); 257 EXPECT_EQ(keyword.originating_url, restored_keyword.originating_url); 258 EXPECT_EQ(keyword.show_in_default_list, 259 restored_keyword.show_in_default_list); 260 EXPECT_EQ(keyword.safe_for_autoreplace, 261 restored_keyword.safe_for_autoreplace); 262 EXPECT_EQ(keyword.input_encodings, restored_keyword.input_encodings); 263 EXPECT_EQ(keyword.id, restored_keyword.id); 264 EXPECT_EQ(keyword.prepopulate_id, restored_keyword.prepopulate_id); 265 } 266 267 TEST_F(KeywordTableTest, KeywordWithNoFavicon) { 268 TemplateURLData keyword; 269 keyword.short_name = ASCIIToUTF16("short_name"); 270 keyword.SetKeyword(ASCIIToUTF16("keyword")); 271 keyword.SetURL("http://url/"); 272 keyword.safe_for_autoreplace = true; 273 keyword.id = -100; 274 EXPECT_TRUE(table_->AddKeyword(keyword)); 275 276 KeywordTable::Keywords keywords; 277 EXPECT_TRUE(table_->GetKeywords(&keywords)); 278 EXPECT_EQ(1U, keywords.size()); 279 const TemplateURLData& restored_keyword = keywords.front(); 280 281 EXPECT_EQ(keyword.short_name, restored_keyword.short_name); 282 EXPECT_EQ(keyword.keyword(), restored_keyword.keyword()); 283 EXPECT_EQ(keyword.favicon_url, restored_keyword.favicon_url); 284 EXPECT_EQ(keyword.safe_for_autoreplace, 285 restored_keyword.safe_for_autoreplace); 286 EXPECT_EQ(keyword.id, restored_keyword.id); 287 } 288 289 TEST_F(KeywordTableTest, SanitizeURLs) { 290 TemplateURLData keyword; 291 keyword.short_name = ASCIIToUTF16("legit"); 292 keyword.SetKeyword(ASCIIToUTF16("legit")); 293 keyword.SetURL("http://url/"); 294 keyword.id = 1000; 295 EXPECT_TRUE(table_->AddKeyword(keyword)); 296 297 keyword.short_name = ASCIIToUTF16("bogus"); 298 keyword.SetKeyword(ASCIIToUTF16("bogus")); 299 keyword.id = 2000; 300 EXPECT_TRUE(table_->AddKeyword(keyword)); 301 302 KeywordTable::Keywords keywords; 303 EXPECT_TRUE(table_->GetKeywords(&keywords)); 304 EXPECT_EQ(2U, keywords.size()); 305 keywords.clear(); 306 307 // Erase the URL field for the second keyword to simulate having bogus data 308 // previously saved into the database. 309 sql::Statement s(table_->db_->GetUniqueStatement( 310 "UPDATE keywords SET url=? WHERE id=?")); 311 s.BindString16(0, base::string16()); 312 s.BindInt64(1, 2000); 313 EXPECT_TRUE(s.Run()); 314 315 // GetKeywords() should erase the entry with the empty URL field. 316 EXPECT_TRUE(table_->GetKeywords(&keywords)); 317 EXPECT_EQ(1U, keywords.size()); 318 } 319