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.
5 #include "components/omnibox/browser/shortcuts_backend.h"
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
12 #include "chrome/browser/search_engines/template_url_service_factory.h"
13 #include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
14 #include "chrome/test/base/testing_profile.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "components/omnibox/browser/shortcuts_database.h"
17 #include "components/search_engines/template_url_service.h"
18 #include "content/public/test/test_browser_thread.h"
20 #include "testing/gtest/include/gtest/gtest.h"
23 // ShortcutsBackendTest -------------------------------------------------------
25 class ShortcutsBackendTest
: public testing::Test
,
26 public ShortcutsBackend::ShortcutsBackendObserver
{
28 ShortcutsBackendTest();
30 ShortcutsDatabase::Shortcut::MatchCore
MatchCoreForTesting(
31 const std::string
& url
,
32 const std::string
& contents_class
= std::string(),
33 const std::string
& description_class
= std::string(),
34 AutocompleteMatch::Type type
= AutocompleteMatchType::URL_WHAT_YOU_TYPED
);
35 void SetSearchProvider();
37 void SetUp() override
;
38 void TearDown() override
;
40 void OnShortcutsLoaded() override
;
41 void OnShortcutsChanged() override
;
43 const ShortcutsBackend::ShortcutMap
& shortcuts_map() const {
44 return backend_
->shortcuts_map();
46 bool changed_notified() const { return changed_notified_
; }
47 void set_changed_notified(bool changed_notified
) {
48 changed_notified_
= changed_notified
;
52 bool AddShortcut(const ShortcutsDatabase::Shortcut
& shortcut
);
53 bool UpdateShortcut(const ShortcutsDatabase::Shortcut
& shortcut
);
54 bool DeleteShortcutsWithURL(const GURL
& url
);
55 bool DeleteShortcutsWithIDs(
56 const ShortcutsDatabase::ShortcutIDs
& deleted_ids
);
59 base::MessageLoopForUI ui_message_loop_
;
60 content::TestBrowserThread ui_thread_
;
61 content::TestBrowserThread db_thread_
;
64 TestingProfile profile_
;
65 UIThreadSearchTermsData search_terms_data_
;
68 scoped_refptr
<ShortcutsBackend
> backend_
;
71 bool changed_notified_
;
73 DISALLOW_COPY_AND_ASSIGN(ShortcutsBackendTest
);
76 ShortcutsBackendTest::ShortcutsBackendTest()
77 : ui_thread_(content::BrowserThread::UI
, &ui_message_loop_
),
78 db_thread_(content::BrowserThread::DB
),
79 search_terms_data_(&profile_
),
80 load_notified_(false),
81 changed_notified_(false) {
84 ShortcutsDatabase::Shortcut::MatchCore
85 ShortcutsBackendTest::MatchCoreForTesting(const std::string
& url
,
86 const std::string
& contents_class
,
87 const std::string
& description_class
,
88 AutocompleteMatch::Type type
) {
89 AutocompleteMatch
match(NULL
, 0, 0, type
);
90 match
.destination_url
= GURL(url
);
91 match
.contents
= base::ASCIIToUTF16("test");
92 match
.contents_class
=
93 AutocompleteMatch::ClassificationsFromString(contents_class
);
94 match
.description_class
=
95 AutocompleteMatch::ClassificationsFromString(description_class
);
96 match
.search_terms_args
.reset(
97 new TemplateURLRef::SearchTermsArgs(match
.contents
));
98 return ShortcutsBackend::MatchToMatchCore(
99 match
, TemplateURLServiceFactory::GetForProfile(&profile_
),
100 &search_terms_data_
);
103 void ShortcutsBackendTest::SetSearchProvider() {
104 TemplateURLService
* template_url_service
=
105 TemplateURLServiceFactory::GetForProfile(&profile_
);
106 TemplateURLData data
;
107 data
.SetURL("http://foo.com/search?bar={searchTerms}");
108 data
.SetShortName(base::UTF8ToUTF16("foo"));
109 data
.SetKeyword(base::UTF8ToUTF16("foo"));
111 TemplateURL
* template_url
= new TemplateURL(data
);
112 // Takes ownership of |template_url|.
113 template_url_service
->Add(template_url
);
114 template_url_service
->SetUserSelectedDefaultSearchProvider(template_url
);
117 void ShortcutsBackendTest::SetUp() {
119 ShortcutsBackendFactory::GetInstance()->SetTestingFactoryAndUse(
120 &profile_
, &ShortcutsBackendFactory::BuildProfileForTesting
);
121 backend_
= ShortcutsBackendFactory::GetForProfile(&profile_
);
122 ASSERT_TRUE(backend_
.get());
123 backend_
->AddObserver(this);
125 TemplateURLServiceFactory::GetInstance()->SetTestingFactoryAndUse(
126 &profile_
, &TemplateURLServiceFactory::BuildInstanceFor
);
127 TemplateURLService
* template_url_service
=
128 TemplateURLServiceFactory::GetForProfile(&profile_
);
129 ui_test_utils::WaitForTemplateURLServiceToLoad(template_url_service
);
132 void ShortcutsBackendTest::TearDown() {
133 backend_
->RemoveObserver(this);
137 void ShortcutsBackendTest::OnShortcutsLoaded() {
138 load_notified_
= true;
139 base::MessageLoop::current()->Quit();
142 void ShortcutsBackendTest::OnShortcutsChanged() {
143 changed_notified_
= true;
146 void ShortcutsBackendTest::InitBackend() {
147 ShortcutsBackend
* backend
=
148 ShortcutsBackendFactory::GetForProfile(&profile_
).get();
149 ASSERT_TRUE(backend
);
150 ASSERT_FALSE(load_notified_
);
151 ASSERT_FALSE(backend_
->initialized());
152 base::MessageLoop::current()->Run();
153 EXPECT_TRUE(load_notified_
);
154 EXPECT_TRUE(backend_
->initialized());
157 bool ShortcutsBackendTest::AddShortcut(
158 const ShortcutsDatabase::Shortcut
& shortcut
) {
159 return backend_
->AddShortcut(shortcut
);
162 bool ShortcutsBackendTest::UpdateShortcut(
163 const ShortcutsDatabase::Shortcut
& shortcut
) {
164 return backend_
->UpdateShortcut(shortcut
);
167 bool ShortcutsBackendTest::DeleteShortcutsWithURL(const GURL
& url
) {
168 return backend_
->DeleteShortcutsWithURL(url
);
171 bool ShortcutsBackendTest::DeleteShortcutsWithIDs(
172 const ShortcutsDatabase::ShortcutIDs
& deleted_ids
) {
173 return backend_
->DeleteShortcutsWithIDs(deleted_ids
);
177 // Actual tests ---------------------------------------------------------------
179 // Verifies that creating MatchCores strips classifications and sanitizes match
181 TEST_F(ShortcutsBackendTest
, SanitizeMatchCore
) {
183 std::string input_contents_class
;
184 std::string input_description_class
;
185 AutocompleteMatch::Type input_type
;
186 std::string output_contents_class
;
187 std::string output_description_class
;
188 AutocompleteMatch::Type output_type
;
190 { "0,1,4,0", "0,3,4,1", AutocompleteMatchType::URL_WHAT_YOU_TYPED
,
191 "0,1,4,0", "0,1", AutocompleteMatchType::HISTORY_URL
},
192 { "0,3,5,1", "0,2,5,0", AutocompleteMatchType::NAVSUGGEST
,
193 "0,1", "0,0", AutocompleteMatchType::HISTORY_URL
},
194 { "0,1", "0,0,11,2,15,0",
195 AutocompleteMatchType::SEARCH_WHAT_YOU_TYPED
,
196 "0,1", "0,0", AutocompleteMatchType::SEARCH_HISTORY
},
197 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST
,
198 "0,1", "0,0", AutocompleteMatchType::SEARCH_HISTORY
},
199 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_ENTITY
,
200 "", "", AutocompleteMatchType::SEARCH_HISTORY
},
201 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_TAIL
,
202 "", "", AutocompleteMatchType::SEARCH_HISTORY
},
203 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_PERSONALIZED
,
204 "", "", AutocompleteMatchType::SEARCH_HISTORY
},
205 { "0,1", "0,0", AutocompleteMatchType::SEARCH_SUGGEST_PROFILE
,
206 "", "", AutocompleteMatchType::SEARCH_HISTORY
},
209 for (size_t i
= 0; i
< arraysize(cases
); ++i
) {
210 ShortcutsDatabase::Shortcut::MatchCore
match_core(MatchCoreForTesting(
211 std::string(), cases
[i
].input_contents_class
,
212 cases
[i
].input_description_class
, cases
[i
].input_type
));
213 EXPECT_EQ(cases
[i
].output_contents_class
, match_core
.contents_class
)
214 << ":i:" << i
<< ":type:" << cases
[i
].input_type
;
215 EXPECT_EQ(cases
[i
].output_description_class
, match_core
.description_class
)
216 << ":i:" << i
<< ":type:" << cases
[i
].input_type
;
217 EXPECT_EQ(cases
[i
].output_type
, match_core
.type
)
218 << ":i:" << i
<< ":type:" << cases
[i
].input_type
;
222 TEST_F(ShortcutsBackendTest
, EntitySuggestionTest
) {
224 AutocompleteMatch match
;
225 match
.fill_into_edit
= base::UTF8ToUTF16("franklin d roosevelt");
226 match
.type
= AutocompleteMatchType::SEARCH_SUGGEST_ENTITY
;
227 match
.contents
= base::UTF8ToUTF16("roosevelt");
228 match
.contents_class
=
229 AutocompleteMatch::ClassificationsFromString("0,0,5,2");
230 match
.description
= base::UTF8ToUTF16("Franklin D. Roosevelt");
231 match
.description_class
= AutocompleteMatch::ClassificationsFromString("0,4");
232 match
.destination_url
= GURL(
233 "http://www.foo.com/search?bar=franklin+d+roosevelt&gs_ssp=1234");
234 match
.keyword
= base::UTF8ToUTF16("foo");
235 match
.search_terms_args
.reset(
236 new TemplateURLRef::SearchTermsArgs(match
.fill_into_edit
));
238 ShortcutsDatabase::Shortcut::MatchCore match_core
=
239 ShortcutsBackend::MatchToMatchCore(
240 match
, TemplateURLServiceFactory::GetForProfile(&profile_
),
241 &search_terms_data_
);
242 EXPECT_EQ("http://foo.com/search?bar=franklin+d+roosevelt",
243 match_core
.destination_url
.spec());
244 EXPECT_EQ(match
.fill_into_edit
, match_core
.contents
);
245 EXPECT_EQ("0,0", match_core
.contents_class
);
246 EXPECT_EQ(base::string16(), match_core
.description
);
247 EXPECT_TRUE(match_core
.description_class
.empty());
250 TEST_F(ShortcutsBackendTest
, AddAndUpdateShortcut
) {
252 EXPECT_FALSE(changed_notified());
254 ShortcutsDatabase::Shortcut
shortcut(
255 "BD85DBA2-8C29-49F9-84AE-48E1E90880DF", base::ASCIIToUTF16("goog"),
256 MatchCoreForTesting("http://www.google.com"), base::Time::Now(), 100);
257 EXPECT_TRUE(AddShortcut(shortcut
));
258 EXPECT_TRUE(changed_notified());
259 ShortcutsBackend::ShortcutMap::const_iterator
shortcut_iter(
260 shortcuts_map().find(shortcut
.text
));
261 ASSERT_TRUE(shortcut_iter
!= shortcuts_map().end());
262 EXPECT_EQ(shortcut
.id
, shortcut_iter
->second
.id
);
263 EXPECT_EQ(shortcut
.match_core
.contents
,
264 shortcut_iter
->second
.match_core
.contents
);
266 set_changed_notified(false);
267 shortcut
.match_core
.contents
= base::ASCIIToUTF16("Google Web Search");
268 EXPECT_TRUE(UpdateShortcut(shortcut
));
269 EXPECT_TRUE(changed_notified());
270 shortcut_iter
= shortcuts_map().find(shortcut
.text
);
271 ASSERT_TRUE(shortcut_iter
!= shortcuts_map().end());
272 EXPECT_EQ(shortcut
.id
, shortcut_iter
->second
.id
);
273 EXPECT_EQ(shortcut
.match_core
.contents
,
274 shortcut_iter
->second
.match_core
.contents
);
277 TEST_F(ShortcutsBackendTest
, DeleteShortcuts
) {
279 ShortcutsDatabase::Shortcut
shortcut1(
280 "BD85DBA2-8C29-49F9-84AE-48E1E90880DF", base::ASCIIToUTF16("goog"),
281 MatchCoreForTesting("http://www.google.com"), base::Time::Now(), 100);
282 EXPECT_TRUE(AddShortcut(shortcut1
));
284 ShortcutsDatabase::Shortcut
shortcut2(
285 "BD85DBA2-8C29-49F9-84AE-48E1E90880E0", base::ASCIIToUTF16("gle"),
286 MatchCoreForTesting("http://www.google.com"), base::Time::Now(), 100);
287 EXPECT_TRUE(AddShortcut(shortcut2
));
289 ShortcutsDatabase::Shortcut
shortcut3(
290 "BD85DBA2-8C29-49F9-84AE-48E1E90880E1", base::ASCIIToUTF16("sp"),
291 MatchCoreForTesting("http://www.sport.com"), base::Time::Now(), 10);
292 EXPECT_TRUE(AddShortcut(shortcut3
));
294 ShortcutsDatabase::Shortcut
shortcut4(
295 "BD85DBA2-8C29-49F9-84AE-48E1E90880E2", base::ASCIIToUTF16("mov"),
296 MatchCoreForTesting("http://www.film.com"), base::Time::Now(), 10);
297 EXPECT_TRUE(AddShortcut(shortcut4
));
299 ASSERT_EQ(4U, shortcuts_map().size());
300 EXPECT_EQ(shortcut1
.id
, shortcuts_map().find(shortcut1
.text
)->second
.id
);
301 EXPECT_EQ(shortcut2
.id
, shortcuts_map().find(shortcut2
.text
)->second
.id
);
302 EXPECT_EQ(shortcut3
.id
, shortcuts_map().find(shortcut3
.text
)->second
.id
);
303 EXPECT_EQ(shortcut4
.id
, shortcuts_map().find(shortcut4
.text
)->second
.id
);
305 EXPECT_TRUE(DeleteShortcutsWithURL(shortcut1
.match_core
.destination_url
));
307 ASSERT_EQ(2U, shortcuts_map().size());
308 EXPECT_EQ(0U, shortcuts_map().count(shortcut1
.text
));
309 EXPECT_EQ(0U, shortcuts_map().count(shortcut2
.text
));
310 const ShortcutsBackend::ShortcutMap::const_iterator
shortcut3_iter(
311 shortcuts_map().find(shortcut3
.text
));
312 ASSERT_TRUE(shortcut3_iter
!= shortcuts_map().end());
313 EXPECT_EQ(shortcut3
.id
, shortcut3_iter
->second
.id
);
314 const ShortcutsBackend::ShortcutMap::const_iterator
shortcut4_iter(
315 shortcuts_map().find(shortcut4
.text
));
316 ASSERT_TRUE(shortcut4_iter
!= shortcuts_map().end());
317 EXPECT_EQ(shortcut4
.id
, shortcut4_iter
->second
.id
);
319 ShortcutsDatabase::ShortcutIDs deleted_ids
;
320 deleted_ids
.push_back(shortcut3
.id
);
321 deleted_ids
.push_back(shortcut4
.id
);
322 EXPECT_TRUE(DeleteShortcutsWithIDs(deleted_ids
));
324 ASSERT_EQ(0U, shortcuts_map().size());