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 "components/search_engines/keyword_table.h" 15 #include "components/search_engines/template_url_data.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::ASCIIToUTF16; 21 using base::Time; 22 using base::TimeDelta; 23 24 class KeywordTableTest : public testing::Test { 25 public: 26 KeywordTableTest() {} 27 virtual ~KeywordTableTest() {} 28 29 protected: 30 virtual void SetUp() { 31 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 32 file_ = temp_dir_.path().AppendASCII("TestWebDatabase"); 33 34 table_.reset(new KeywordTable); 35 db_.reset(new WebDatabase); 36 db_->AddTable(table_.get()); 37 ASSERT_EQ(sql::INIT_OK, db_->Init(file_)); 38 } 39 40 void AddKeyword(const TemplateURLData& keyword) const { 41 EXPECT_TRUE(table_->AddKeyword(keyword)); 42 } 43 44 TemplateURLData CreateAndAddKeyword() const { 45 TemplateURLData keyword; 46 keyword.short_name = ASCIIToUTF16("short_name"); 47 keyword.SetKeyword(ASCIIToUTF16("keyword")); 48 keyword.SetURL("http://url/"); 49 keyword.suggestions_url = "url2"; 50 keyword.instant_url = "http://instant/"; 51 keyword.image_url = "http://image-search-url/"; 52 keyword.new_tab_url = "http://new-tab-url/"; 53 keyword.search_url_post_params = "ie=utf-8,oe=utf-8"; 54 keyword.image_url_post_params = "name=1,value=2"; 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 = base::Time::UnixEpoch(); 63 keyword.last_modified = base::Time::UnixEpoch(); 64 keyword.created_by_policy = true; 65 keyword.usage_count = 32; 66 keyword.prepopulate_id = 10; 67 keyword.sync_guid = "1234-5678-90AB-CDEF"; 68 keyword.alternate_urls.push_back("a_url1"); 69 keyword.alternate_urls.push_back("a_url2"); 70 keyword.search_terms_replacement_key = "espv"; 71 AddKeyword(keyword); 72 return keyword; 73 } 74 75 void RemoveKeyword(TemplateURLID id) const { 76 EXPECT_TRUE(table_->RemoveKeyword(id)); 77 } 78 79 void UpdateKeyword(const TemplateURLData& keyword) const { 80 EXPECT_TRUE(table_->UpdateKeyword(keyword)); 81 } 82 83 KeywordTable::Keywords GetKeywords() const { 84 KeywordTable::Keywords keywords; 85 EXPECT_TRUE(table_->GetKeywords(&keywords)); 86 return keywords; 87 } 88 89 void KeywordMiscTest() const { 90 EXPECT_EQ(kInvalidTemplateURLID, table_->GetDefaultSearchProviderID()); 91 EXPECT_EQ(0, table_->GetBuiltinKeywordVersion()); 92 93 EXPECT_TRUE(table_->SetDefaultSearchProviderID(10)); 94 EXPECT_TRUE(table_->SetBuiltinKeywordVersion(11)); 95 96 EXPECT_EQ(10, table_->GetDefaultSearchProviderID()); 97 EXPECT_EQ(11, table_->GetBuiltinKeywordVersion()); 98 } 99 100 void GetStatement(const char* sql, sql::Statement* statement) const { 101 statement->Assign(table_->db_->GetUniqueStatement(sql)); 102 } 103 104 private: 105 base::FilePath file_; 106 base::ScopedTempDir temp_dir_; 107 scoped_ptr<KeywordTable> table_; 108 scoped_ptr<WebDatabase> db_; 109 110 DISALLOW_COPY_AND_ASSIGN(KeywordTableTest); 111 }; 112 113 114 TEST_F(KeywordTableTest, Keywords) { 115 TemplateURLData keyword(CreateAndAddKeyword()); 116 117 KeywordTable::Keywords keywords(GetKeywords()); 118 EXPECT_EQ(1U, keywords.size()); 119 const TemplateURLData& restored_keyword = keywords.front(); 120 121 EXPECT_EQ(keyword.short_name, restored_keyword.short_name); 122 EXPECT_EQ(keyword.keyword(), restored_keyword.keyword()); 123 EXPECT_EQ(keyword.url(), restored_keyword.url()); 124 EXPECT_EQ(keyword.suggestions_url, restored_keyword.suggestions_url); 125 EXPECT_EQ(keyword.instant_url, restored_keyword.instant_url); 126 EXPECT_EQ(keyword.favicon_url, restored_keyword.favicon_url); 127 EXPECT_EQ(keyword.originating_url, restored_keyword.originating_url); 128 EXPECT_EQ(keyword.show_in_default_list, 129 restored_keyword.show_in_default_list); 130 EXPECT_EQ(keyword.safe_for_autoreplace, 131 restored_keyword.safe_for_autoreplace); 132 EXPECT_EQ(keyword.input_encodings, restored_keyword.input_encodings); 133 EXPECT_EQ(keyword.id, restored_keyword.id); 134 // The database stores time only at the resolution of a second. 135 EXPECT_EQ(keyword.date_created.ToTimeT(), 136 restored_keyword.date_created.ToTimeT()); 137 EXPECT_EQ(keyword.last_modified.ToTimeT(), 138 restored_keyword.last_modified.ToTimeT()); 139 EXPECT_EQ(keyword.created_by_policy, restored_keyword.created_by_policy); 140 EXPECT_EQ(keyword.usage_count, restored_keyword.usage_count); 141 EXPECT_EQ(keyword.prepopulate_id, restored_keyword.prepopulate_id); 142 143 RemoveKeyword(restored_keyword.id); 144 145 EXPECT_EQ(0U, GetKeywords().size()); 146 } 147 148 TEST_F(KeywordTableTest, KeywordMisc) { 149 KeywordMiscTest(); 150 } 151 152 TEST_F(KeywordTableTest, UpdateKeyword) { 153 TemplateURLData keyword(CreateAndAddKeyword()); 154 155 keyword.SetKeyword(ASCIIToUTF16("url")); 156 keyword.instant_url = "http://instant2/"; 157 keyword.originating_url = GURL("http://originating.url/"); 158 keyword.input_encodings.push_back("Shift_JIS"); 159 keyword.prepopulate_id = 5; 160 UpdateKeyword(keyword); 161 162 KeywordTable::Keywords keywords(GetKeywords()); 163 EXPECT_EQ(1U, keywords.size()); 164 const TemplateURLData& restored_keyword = keywords.front(); 165 166 EXPECT_EQ(keyword.short_name, restored_keyword.short_name); 167 EXPECT_EQ(keyword.keyword(), restored_keyword.keyword()); 168 EXPECT_EQ(keyword.suggestions_url, restored_keyword.suggestions_url); 169 EXPECT_EQ(keyword.instant_url, restored_keyword.instant_url); 170 EXPECT_EQ(keyword.favicon_url, restored_keyword.favicon_url); 171 EXPECT_EQ(keyword.originating_url, restored_keyword.originating_url); 172 EXPECT_EQ(keyword.show_in_default_list, 173 restored_keyword.show_in_default_list); 174 EXPECT_EQ(keyword.safe_for_autoreplace, 175 restored_keyword.safe_for_autoreplace); 176 EXPECT_EQ(keyword.input_encodings, restored_keyword.input_encodings); 177 EXPECT_EQ(keyword.id, restored_keyword.id); 178 EXPECT_EQ(keyword.prepopulate_id, restored_keyword.prepopulate_id); 179 } 180 181 TEST_F(KeywordTableTest, KeywordWithNoFavicon) { 182 TemplateURLData keyword; 183 keyword.short_name = ASCIIToUTF16("short_name"); 184 keyword.SetKeyword(ASCIIToUTF16("keyword")); 185 keyword.SetURL("http://url/"); 186 keyword.safe_for_autoreplace = true; 187 keyword.id = -100; 188 AddKeyword(keyword); 189 190 KeywordTable::Keywords keywords(GetKeywords()); 191 EXPECT_EQ(1U, keywords.size()); 192 const TemplateURLData& restored_keyword = keywords.front(); 193 194 EXPECT_EQ(keyword.short_name, restored_keyword.short_name); 195 EXPECT_EQ(keyword.keyword(), restored_keyword.keyword()); 196 EXPECT_EQ(keyword.favicon_url, restored_keyword.favicon_url); 197 EXPECT_EQ(keyword.safe_for_autoreplace, 198 restored_keyword.safe_for_autoreplace); 199 EXPECT_EQ(keyword.id, restored_keyword.id); 200 } 201 202 TEST_F(KeywordTableTest, SanitizeURLs) { 203 TemplateURLData keyword; 204 keyword.short_name = ASCIIToUTF16("legit"); 205 keyword.SetKeyword(ASCIIToUTF16("legit")); 206 keyword.SetURL("http://url/"); 207 keyword.id = 1000; 208 AddKeyword(keyword); 209 210 keyword.short_name = ASCIIToUTF16("bogus"); 211 keyword.SetKeyword(ASCIIToUTF16("bogus")); 212 keyword.id = 2000; 213 AddKeyword(keyword); 214 215 EXPECT_EQ(2U, GetKeywords().size()); 216 217 // Erase the URL field for the second keyword to simulate having bogus data 218 // previously saved into the database. 219 sql::Statement s; 220 GetStatement("UPDATE keywords SET url=? WHERE id=?", &s); 221 s.BindString16(0, base::string16()); 222 s.BindInt64(1, 2000); 223 EXPECT_TRUE(s.Run()); 224 225 // GetKeywords() should erase the entry with the empty URL field. 226 EXPECT_EQ(1U, GetKeywords().size()); 227 } 228