• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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 "base/callback.h"
6 #include "base/memory/ref_counted.h"
7 #include "base/memory/scoped_vector.h"
8 #include "base/string_split.h"
9 #include "base/string_util.h"
10 #include "base/threading/thread.h"
11 #include "base/utf_string_conversions.h"
12 #include "chrome/browser/history/history.h"
13 #include "chrome/browser/history/history_notifications.h"
14 #include "chrome/browser/search_engines/search_host_to_urls_map.h"
15 #include "chrome/browser/search_engines/search_terms_data.h"
16 #include "chrome/browser/search_engines/template_url.h"
17 #include "chrome/browser/search_engines/template_url_model.h"
18 #include "chrome/browser/search_engines/template_url_model_test_util.h"
19 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
20 #include "chrome/browser/webdata/web_database.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/test/testing_pref_service.h"
23 #include "chrome/test/testing_profile.h"
24 #include "content/browser/browser_thread.h"
25 #include "content/common/notification_details.h"
26 #include "content/common/notification_source.h"
27 #include "testing/gtest/include/gtest/gtest.h"
28 
29 using base::Time;
30 using base::TimeDelta;
31 
32 #if defined(OS_LINUX)
33 // Timed out on Chromium Linux.  http://crbug.com/53607
34 #define MAYBE_Load DISABLED_Load
35 #else
36 #define MAYBE_Load Load
37 #endif
38 
39 // Test the GenerateSearchURL on a thread or the main thread.
40 class TestGenerateSearchURL
41     : public base::RefCountedThreadSafe<TestGenerateSearchURL> {
42  public:
TestGenerateSearchURL(SearchTermsData * search_terms_data)43   explicit TestGenerateSearchURL(SearchTermsData* search_terms_data)
44       : search_terms_data_(search_terms_data),
45         passed_(false) {
46   }
47 
48   // Run the test cases for GenerateSearchURL.
49   void RunTest();
50 
51   // Did the test pass?
passed() const52   bool passed() const { return passed_; }
53 
54  private:
55   friend class base::RefCountedThreadSafe<TestGenerateSearchURL>;
~TestGenerateSearchURL()56   ~TestGenerateSearchURL() {}
57 
58   SearchTermsData* search_terms_data_;
59   bool passed_;
60 
61   DISALLOW_COPY_AND_ASSIGN(TestGenerateSearchURL);
62 };
63 
64 // Simple implementation of SearchTermsData.
65 class TestSearchTermsData : public SearchTermsData {
66  public:
TestSearchTermsData(const char * google_base_url)67   explicit TestSearchTermsData(const char* google_base_url)
68       : google_base_url_(google_base_url)  {
69   }
70 
GoogleBaseURLValue() const71   virtual std::string GoogleBaseURLValue() const {
72     return google_base_url_;
73   }
74 
GetApplicationLocale() const75   virtual std::string GetApplicationLocale() const {
76     return "yy";
77   }
78 
79 #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
80   // Returns the value for the Chrome Omnibox rlz.
GetRlzParameterValue() const81   virtual string16 GetRlzParameterValue() const {
82     return string16();
83   }
84 #endif
85 
86  private:
87   std::string google_base_url_;
88 
89   DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData);
90 };
91 
92 // Create an URL that appears to have been prepopulated, but won't be in the
93 // current data. The caller owns the returned TemplateURL*.
CreatePreloadedTemplateURL()94 static TemplateURL* CreatePreloadedTemplateURL() {
95   TemplateURL* t_url = new TemplateURL();
96   t_url->SetURL("http://www.unittest.com/", 0, 0);
97   t_url->set_keyword(ASCIIToUTF16("unittest"));
98   t_url->set_short_name(ASCIIToUTF16("unittest"));
99   t_url->set_safe_for_autoreplace(true);
100   GURL favicon_url("http://favicon.url");
101   t_url->SetFaviconURL(favicon_url);
102   t_url->set_date_created(Time::FromTimeT(100));
103   t_url->set_prepopulate_id(999999);
104   return t_url;
105 }
106 
107 class TemplateURLModelTest : public testing::Test {
108  public:
TemplateURLModelTest()109   TemplateURLModelTest() {}
110 
SetUp()111   virtual void SetUp() {
112     test_util_.SetUp();
113   }
114 
TearDown()115   virtual void TearDown() {
116     test_util_.TearDown();
117   }
118 
AddKeywordWithDate(const std::string & keyword,bool autogenerate_keyword,const std::string & url,const std::string & suggest_url,const std::string & favicon_url,const std::string & encodings,const std::string & short_name,bool safe_for_autoreplace,Time created_date)119   TemplateURL* AddKeywordWithDate(const std::string& keyword,
120                                   bool autogenerate_keyword,
121                                   const std::string& url,
122                                   const std::string& suggest_url,
123                                   const std::string& favicon_url,
124                                   const std::string& encodings,
125                                   const std::string& short_name,
126                                   bool safe_for_autoreplace,
127                                   Time created_date) {
128     TemplateURL* template_url = new TemplateURL();
129     template_url->SetURL(url, 0, 0);
130     template_url->SetSuggestionsURL(suggest_url, 0, 0);
131     template_url->SetFaviconURL(GURL(favicon_url));
132     template_url->set_keyword(UTF8ToUTF16(keyword));
133     template_url->set_autogenerate_keyword(autogenerate_keyword);
134     template_url->set_short_name(UTF8ToUTF16(short_name));
135     std::vector<std::string> encodings_vector;
136     base::SplitString(encodings, ';', &encodings_vector);
137     template_url->set_input_encodings(encodings_vector);
138     template_url->set_date_created(created_date);
139     template_url->set_safe_for_autoreplace(safe_for_autoreplace);
140     model()->Add(template_url);
141     EXPECT_NE(0, template_url->id());
142     return template_url;
143   }
144 
145   // Simulate firing by the prefs service specifying that the managed
146   // preferences have changed.
NotifyManagedPrefsHaveChanged()147   void NotifyManagedPrefsHaveChanged() {
148     model()->Observe(
149         NotificationType::PREF_CHANGED,
150         Source<PrefService>(profile()->GetTestingPrefService()),
151         Details<std::string>(NULL));
152   }
153 
154   // Verifies the two TemplateURLs are equal.
AssertEquals(const TemplateURL & expected,const TemplateURL & actual)155   void AssertEquals(const TemplateURL& expected, const TemplateURL& actual) {
156     ASSERT_TRUE(TemplateURLRef::SameUrlRefs(expected.url(), actual.url()));
157     ASSERT_TRUE(TemplateURLRef::SameUrlRefs(expected.suggestions_url(),
158                                             actual.suggestions_url()));
159     ASSERT_EQ(expected.keyword(), actual.keyword());
160     ASSERT_EQ(expected.short_name(), actual.short_name());
161     ASSERT_EQ(JoinString(expected.input_encodings(), ';'),
162               JoinString(actual.input_encodings(), ';'));
163     ASSERT_TRUE(expected.GetFaviconURL() == actual.GetFaviconURL());
164     ASSERT_EQ(expected.id(), actual.id());
165     ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
166     ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
167     ASSERT_TRUE(expected.date_created() == actual.date_created());
168   }
169 
170   // Checks that the two TemplateURLs are similar. It does not check the id
171   // and the date_created.  Neither pointer should be NULL.
ExpectSimilar(const TemplateURL * expected,const TemplateURL * actual)172   void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) {
173     ASSERT_TRUE(expected != NULL);
174     ASSERT_TRUE(actual != NULL);
175     EXPECT_TRUE(TemplateURLRef::SameUrlRefs(expected->url(), actual->url()));
176     EXPECT_TRUE(TemplateURLRef::SameUrlRefs(expected->suggestions_url(),
177                                             actual->suggestions_url()));
178     EXPECT_EQ(expected->keyword(), actual->keyword());
179     EXPECT_EQ(expected->short_name(), actual->short_name());
180     EXPECT_EQ(JoinString(expected->input_encodings(), ';'),
181               JoinString(actual->input_encodings(), ';'));
182     EXPECT_TRUE(expected->GetFaviconURL() == actual->GetFaviconURL());
183     EXPECT_EQ(expected->safe_for_autoreplace(), actual->safe_for_autoreplace());
184     EXPECT_EQ(expected->show_in_default_list(), actual->show_in_default_list());
185   }
186 
187   // Set the managed preferences for the default search provider and trigger
188   // notification.
SetManagedDefaultSearchPreferences(bool enabled,const char * name,const char * search_url,const char * suggest_url,const char * icon_url,const char * encodings,const char * keyword)189   void SetManagedDefaultSearchPreferences(bool enabled,
190                                           const char* name,
191                                           const char* search_url,
192                                           const char* suggest_url,
193                                           const char* icon_url,
194                                           const char* encodings,
195                                           const char* keyword) {
196     TestingPrefService* service = profile()->GetTestingPrefService();
197     service->SetManagedPref(
198         prefs::kDefaultSearchProviderEnabled,
199         Value::CreateBooleanValue(enabled));
200     service->SetManagedPref(
201         prefs::kDefaultSearchProviderName,
202         Value::CreateStringValue(name));
203     service->SetManagedPref(
204         prefs::kDefaultSearchProviderSearchURL,
205         Value::CreateStringValue(search_url));
206     service->SetManagedPref(
207         prefs::kDefaultSearchProviderSuggestURL,
208         Value::CreateStringValue(suggest_url));
209     service->SetManagedPref(
210         prefs::kDefaultSearchProviderIconURL,
211         Value::CreateStringValue(icon_url));
212     service->SetManagedPref(
213         prefs::kDefaultSearchProviderEncodings,
214         Value::CreateStringValue(encodings));
215     service->SetManagedPref(
216         prefs::kDefaultSearchProviderKeyword,
217         Value::CreateStringValue(keyword));
218   }
219 
220   // Remove all the managed preferences for the default search provider and
221   // trigger notification.
RemoveManagedDefaultSearchPreferences()222   void RemoveManagedDefaultSearchPreferences() {
223     TestingPrefService* service = profile()->GetTestingPrefService();
224     service->RemoveManagedPref(
225         prefs::kDefaultSearchProviderSearchURL);
226     service->RemoveManagedPref(
227         prefs::kDefaultSearchProviderEnabled);
228     service->RemoveManagedPref(
229         prefs::kDefaultSearchProviderName);
230     service->RemoveManagedPref(
231         prefs::kDefaultSearchProviderSuggestURL);
232     service->RemoveManagedPref(
233         prefs::kDefaultSearchProviderIconURL);
234     service->RemoveManagedPref(
235         prefs::kDefaultSearchProviderEncodings);
236     service->RemoveManagedPref(
237         prefs::kDefaultSearchProviderKeyword);
238     service->RemoveManagedPref(
239         prefs::kDefaultSearchProviderID);
240     service->RemoveManagedPref(
241         prefs::kDefaultSearchProviderPrepopulateID);
242   }
243 
244   // Creates a TemplateURL with the same prepopulated id as a real prepopulated
245   // item. The input number determines which prepopulated item. The caller is
246   // responsible for owning the returned TemplateURL*.
247   TemplateURL* CreateReplaceablePreloadedTemplateURL(
248       size_t index_offset_from_default,
249       string16* prepopulated_display_url);
250 
251   // Verifies the behavior of when a preloaded url later gets changed.
252   // Since the input is the offset from the default, when one passes in
253   // 0, it tests the default. Passing in a number > 0 will verify what
254   // happens when a preloaded url that is not the default gets updated.
255   void TestLoadUpdatingPreloadedURL(size_t index_offset_from_default);
256 
257   // Helper methods to make calling TemplateURLModelTestUtil methods less
258   // visually noisy in the test code.
VerifyObserverCount(int expected_changed_count)259   void VerifyObserverCount(int expected_changed_count) {
260     EXPECT_EQ(expected_changed_count, test_util_.GetObserverCount());
261     test_util_.ResetObserverCount();
262   }
VerifyObserverFired()263   void VerifyObserverFired() {
264     EXPECT_LE(1, test_util_.GetObserverCount());
265     test_util_.ResetObserverCount();
266   }
BlockTillServiceProcessesRequests()267   void BlockTillServiceProcessesRequests() {
268     TemplateURLModelTestUtil::BlockTillServiceProcessesRequests();
269   }
VerifyLoad()270   void VerifyLoad() { test_util_.VerifyLoad(); }
ChangeModelToLoadState()271   void ChangeModelToLoadState() { test_util_.ChangeModelToLoadState(); }
ResetModel(bool verify_load)272   void ResetModel(bool verify_load) { test_util_.ResetModel(verify_load); }
GetAndClearSearchTerm()273   string16 GetAndClearSearchTerm() {
274     return test_util_.GetAndClearSearchTerm();
275   }
SetGoogleBaseURL(const std::string & base_url) const276   void SetGoogleBaseURL(const std::string& base_url) const {
277     test_util_.SetGoogleBaseURL(base_url);
278   }
GetWebDataService()279   WebDataService* GetWebDataService() { return test_util_.GetWebDataService(); }
model()280   TemplateURLModel* model() { return test_util_.model(); }
profile()281   TestingProfile* profile() { return test_util_.profile(); }
282 
283  protected:
284   TemplateURLModelTestUtil test_util_;
285 
286   DISALLOW_COPY_AND_ASSIGN(TemplateURLModelTest);
287 };
288 
RunTest()289 void TestGenerateSearchURL::RunTest() {
290   struct GenerateSearchURLCase {
291     const char* test_name;
292     const char* url;
293     const char* expected;
294   } generate_url_cases[] = {
295     { "empty TemplateURLRef", NULL, "" },
296     { "invalid URL", "foo{searchTerms}", "" },
297     { "URL with no replacements", "http://foo/", "http://foo/" },
298     { "basic functionality", "http://foo/{searchTerms}",
299       "http://foo/blah.blah.blah.blah.blah" }
300   };
301 
302   // Don't use ASSERT/EXPECT since this is run on a thread in one test
303   // and those macros aren't meant for threads at this time according to
304   // gtest documentation.
305   bool everything_passed = true;
306   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) {
307     TemplateURL t_url;
308     if (generate_url_cases[i].url)
309       t_url.SetURL(generate_url_cases[i].url, 0, 0);
310 
311     std::string result = search_terms_data_ ?
312         TemplateURLModel::GenerateSearchURLUsingTermsData(
313             &t_url, *search_terms_data_).spec() :
314         TemplateURLModel::GenerateSearchURL(&t_url).spec();
315     if (strcmp(generate_url_cases[i].expected, result.c_str())) {
316       LOG(ERROR) << generate_url_cases[i].test_name << " failed. Expected " <<
317           generate_url_cases[i].expected << " Actual " << result;
318 
319       everything_passed = false;
320     }
321   }
322   passed_ = everything_passed;
323 }
324 
CreateReplaceablePreloadedTemplateURL(size_t index_offset_from_default,string16 * prepopulated_display_url)325 TemplateURL* TemplateURLModelTest::CreateReplaceablePreloadedTemplateURL(
326     size_t index_offset_from_default,
327     string16* prepopulated_display_url) {
328   TemplateURL* t_url = CreatePreloadedTemplateURL();
329   ScopedVector<TemplateURL> prepopulated_urls;
330   size_t default_search_provider_index = 0;
331   TemplateURLPrepopulateData::GetPrepopulatedEngines(
332       profile()->GetPrefs(),
333       &prepopulated_urls.get(),
334       &default_search_provider_index);
335   EXPECT_LT(index_offset_from_default, prepopulated_urls.size());
336   size_t prepopulated_index =
337       (default_search_provider_index + index_offset_from_default) %
338       prepopulated_urls.size();
339   t_url->set_prepopulate_id(
340       prepopulated_urls[prepopulated_index]->prepopulate_id());
341   *prepopulated_display_url =
342       prepopulated_urls[prepopulated_index]->url()->DisplayURL();
343   return t_url;
344 }
345 
TestLoadUpdatingPreloadedURL(size_t index_offset_from_default)346 void TemplateURLModelTest::TestLoadUpdatingPreloadedURL(
347     size_t index_offset_from_default) {
348   string16 prepopulated_url;
349   TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL(
350       index_offset_from_default, &prepopulated_url);
351   t_url->set_safe_for_autoreplace(false);
352 
353   string16 original_url = t_url->url()->DisplayURL();
354   ASSERT_NE(prepopulated_url, original_url);
355 
356   // Then add it to the model and save it all.
357   ChangeModelToLoadState();
358   model()->Add(t_url);
359   const TemplateURL* keyword_url =
360       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
361   ASSERT_EQ(t_url, keyword_url);
362   ASSERT_EQ(original_url, keyword_url->url()->DisplayURL());
363   BlockTillServiceProcessesRequests();
364 
365   // Now reload the model and verify that the merge updates the url.
366   ResetModel(true);
367   keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
368   ASSERT_TRUE(keyword_url != NULL);
369   ASSERT_EQ(prepopulated_url, keyword_url->url()->DisplayURL());
370 
371   // Wait for any saves to finish.
372   BlockTillServiceProcessesRequests();
373 
374   // Reload the model to verify that change was saved correctly.
375   ResetModel(true);
376   keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
377   ASSERT_TRUE(keyword_url != NULL);
378   ASSERT_EQ(prepopulated_url, keyword_url->url()->DisplayURL());
379 }
380 
TEST_F(TemplateURLModelTest,MAYBE_Load)381 TEST_F(TemplateURLModelTest, MAYBE_Load) {
382   VerifyLoad();
383 }
384 
TEST_F(TemplateURLModelTest,AddUpdateRemove)385 TEST_F(TemplateURLModelTest, AddUpdateRemove) {
386   // Add a new TemplateURL.
387   VerifyLoad();
388   const size_t initial_count = model()->GetTemplateURLs().size();
389 
390   TemplateURL* t_url = new TemplateURL();
391   t_url->SetURL("http://www.google.com/foo/bar", 0, 0);
392   t_url->set_keyword(ASCIIToUTF16("keyword"));
393   t_url->set_short_name(ASCIIToUTF16("google"));
394   GURL favicon_url("http://favicon.url");
395   t_url->SetFaviconURL(favicon_url);
396   t_url->set_date_created(Time::FromTimeT(100));
397   t_url->set_safe_for_autoreplace(true);
398   model()->Add(t_url);
399   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
400                                          GURL(), NULL));
401   VerifyObserverCount(1);
402   BlockTillServiceProcessesRequests();
403   // We need to clone as model takes ownership of TemplateURL and will
404   // delete it.
405   TemplateURL cloned_url(*t_url);
406   ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
407   ASSERT_TRUE(model()->GetTemplateURLForKeyword(t_url->keyword()) == t_url);
408   ASSERT_TRUE(t_url->date_created() == cloned_url.date_created());
409 
410   // Reload the model to verify it was actually saved to the database.
411   ResetModel(true);
412   ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
413   const TemplateURL* loaded_url =
414       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
415   ASSERT_TRUE(loaded_url != NULL);
416   AssertEquals(cloned_url, *loaded_url);
417   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
418                                          GURL(), NULL));
419 
420   // Mutate an element and verify it succeeded.
421   model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"),
422                             ASCIIToUTF16("b"), "c");
423   ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name());
424   ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword());
425   ASSERT_EQ("c", loaded_url->url()->url());
426   ASSERT_FALSE(loaded_url->safe_for_autoreplace());
427   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"),
428                                          GURL(), NULL));
429   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL));
430   cloned_url = *loaded_url;
431   BlockTillServiceProcessesRequests();
432   ResetModel(true);
433   ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
434   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
435   ASSERT_TRUE(loaded_url != NULL);
436   AssertEquals(cloned_url, *loaded_url);
437 
438   // Remove an element and verify it succeeded.
439   model()->Remove(loaded_url);
440   VerifyObserverCount(1);
441   ResetModel(true);
442   ASSERT_EQ(initial_count, model()->GetTemplateURLs().size());
443   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL);
444 }
445 
TEST_F(TemplateURLModelTest,GenerateKeyword)446 TEST_F(TemplateURLModelTest, GenerateKeyword) {
447   ASSERT_EQ(string16(), TemplateURLModel::GenerateKeyword(GURL(), true));
448   // Shouldn't generate keywords for https.
449   ASSERT_EQ(string16(),
450             TemplateURLModel::GenerateKeyword(GURL("https://blah"), true));
451   ASSERT_EQ(ASCIIToUTF16("foo"),
452             TemplateURLModel::GenerateKeyword(GURL("http://foo"), true));
453   // www. should be stripped.
454   ASSERT_EQ(ASCIIToUTF16("foo"),
455             TemplateURLModel::GenerateKeyword(GURL("http://www.foo"), true));
456   // Shouldn't generate keywords with paths, if autodetected.
457   ASSERT_EQ(string16(),
458             TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), true));
459   ASSERT_EQ(ASCIIToUTF16("blah"),
460             TemplateURLModel::GenerateKeyword(GURL("http://blah/foo"), false));
461   // FTP shouldn't generate a keyword.
462   ASSERT_EQ(string16(),
463             TemplateURLModel::GenerateKeyword(GURL("ftp://blah/"), true));
464   // Make sure we don't get a trailing /
465   ASSERT_EQ(ASCIIToUTF16("blah"),
466             TemplateURLModel::GenerateKeyword(GURL("http://blah/"), true));
467 }
468 
TEST_F(TemplateURLModelTest,GenerateSearchURL)469 TEST_F(TemplateURLModelTest, GenerateSearchURL) {
470   scoped_refptr<TestGenerateSearchURL> test_generate_search_url(
471       new TestGenerateSearchURL(NULL));
472   test_generate_search_url->RunTest();
473   EXPECT_TRUE(test_generate_search_url->passed());
474 }
475 
TEST_F(TemplateURLModelTest,GenerateSearchURLUsingTermsData)476 TEST_F(TemplateURLModelTest, GenerateSearchURLUsingTermsData) {
477   // Run the test for GenerateSearchURLUsingTermsData on the "IO" thread and
478   // wait for it to finish.
479   TestSearchTermsData search_terms_data("http://google.com/");
480   scoped_refptr<TestGenerateSearchURL> test_generate_search_url(
481       new TestGenerateSearchURL(&search_terms_data));
482 
483   test_util_.StartIOThread();
484   BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO)->PostTask(
485           FROM_HERE,
486           NewRunnableMethod(test_generate_search_url.get(),
487                             &TestGenerateSearchURL::RunTest));
488   TemplateURLModelTestUtil::BlockTillIOThreadProcessesRequests();
489   EXPECT_TRUE(test_generate_search_url->passed());
490 }
491 
TEST_F(TemplateURLModelTest,ClearBrowsingData_Keywords)492 TEST_F(TemplateURLModelTest, ClearBrowsingData_Keywords) {
493   Time now = Time::Now();
494   TimeDelta one_day = TimeDelta::FromDays(1);
495   Time month_ago = now - TimeDelta::FromDays(30);
496 
497   // Nothing has been added.
498   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
499 
500   // Create one with a 0 time.
501   AddKeywordWithDate("key1", false, "http://foo1", "http://suggest1",
502                      "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
503   // Create one for now and +/- 1 day.
504   AddKeywordWithDate("key2", false, "http://foo2", "http://suggest2",
505                      "http://icon2", "UTF-8;UTF-16", "name2", true,
506                      now - one_day);
507   AddKeywordWithDate("key3", false, "http://foo3", "", "", "", "name3",
508                      true, now);
509   AddKeywordWithDate("key4", false, "http://foo4", "", "", "", "name4",
510                      true, now + one_day);
511   // Try the other three states.
512   AddKeywordWithDate("key5", false, "http://foo5", "http://suggest5",
513                      "http://icon5", "UTF-8;UTF-16", "name5", false, now);
514   AddKeywordWithDate("key6", false, "http://foo6", "http://suggest6",
515                      "http://icon6", "UTF-8;UTF-16", "name6", false,
516                      month_ago);
517 
518   // We just added a few items, validate them.
519   EXPECT_EQ(6U, model()->GetTemplateURLs().size());
520 
521   // Try removing from current timestamp. This should delete the one in the
522   // future and one very recent one.
523   model()->RemoveAutoGeneratedSince(now);
524   EXPECT_EQ(4U, model()->GetTemplateURLs().size());
525 
526   // Try removing from two months ago. This should only delete items that are
527   // auto-generated.
528   model()->RemoveAutoGeneratedSince(now - TimeDelta::FromDays(60));
529   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
530 
531   // Make sure the right values remain.
532   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
533   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
534   EXPECT_EQ(0U,
535             model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
536 
537   EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
538   EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
539   EXPECT_EQ(now.ToInternalValue(),
540             model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
541 
542   EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
543   EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
544   EXPECT_EQ(month_ago.ToInternalValue(),
545             model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
546 
547   // Try removing from Time=0. This should delete one more.
548   model()->RemoveAutoGeneratedSince(Time());
549   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
550 }
551 
TEST_F(TemplateURLModelTest,Reset)552 TEST_F(TemplateURLModelTest, Reset) {
553   // Add a new TemplateURL.
554   VerifyLoad();
555   const size_t initial_count = model()->GetTemplateURLs().size();
556   TemplateURL* t_url = new TemplateURL();
557   t_url->SetURL("http://www.google.com/foo/bar", 0, 0);
558   t_url->set_keyword(ASCIIToUTF16("keyword"));
559   t_url->set_short_name(ASCIIToUTF16("google"));
560   GURL favicon_url("http://favicon.url");
561   t_url->SetFaviconURL(favicon_url);
562   t_url->set_date_created(Time::FromTimeT(100));
563   model()->Add(t_url);
564 
565   VerifyObserverCount(1);
566   BlockTillServiceProcessesRequests();
567 
568   // Reset the short name, keyword, url and make sure it takes.
569   const string16 new_short_name(ASCIIToUTF16("a"));
570   const string16 new_keyword(ASCIIToUTF16("b"));
571   const std::string new_url("c");
572   model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
573   ASSERT_EQ(new_short_name, t_url->short_name());
574   ASSERT_EQ(new_keyword, t_url->keyword());
575   ASSERT_EQ(new_url, t_url->url()->url());
576 
577   // Make sure the mappings in the model were updated.
578   ASSERT_TRUE(model()->GetTemplateURLForKeyword(new_keyword) == t_url);
579   ASSERT_TRUE(
580       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
581 
582   TemplateURL last_url = *t_url;
583 
584   // Reload the model from the database and make sure the change took.
585   ResetModel(true);
586   t_url = NULL;
587   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
588   const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword);
589   ASSERT_TRUE(read_url);
590   AssertEquals(last_url, *read_url);
591 }
592 
TEST_F(TemplateURLModelTest,DefaultSearchProvider)593 TEST_F(TemplateURLModelTest, DefaultSearchProvider) {
594   // Add a new TemplateURL.
595   VerifyLoad();
596   const size_t initial_count = model()->GetTemplateURLs().size();
597   TemplateURL* t_url = AddKeywordWithDate("key1", false, "http://foo1",
598       "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
599 
600   test_util_.ResetObserverCount();
601   model()->SetDefaultSearchProvider(t_url);
602 
603   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
604 
605   ASSERT_TRUE(t_url->safe_for_autoreplace());
606   ASSERT_TRUE(t_url->show_in_default_list());
607 
608   // Setting the default search provider should have caused notification.
609   VerifyObserverCount(1);
610 
611   BlockTillServiceProcessesRequests();
612 
613   TemplateURL cloned_url = *t_url;
614 
615   ResetModel(true);
616   t_url = NULL;
617 
618   // Make sure when we reload we get a default search provider.
619   EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
620   ASSERT_TRUE(model()->GetDefaultSearchProvider());
621   AssertEquals(cloned_url, *model()->GetDefaultSearchProvider());
622 }
623 
TEST_F(TemplateURLModelTest,TemplateURLWithNoKeyword)624 TEST_F(TemplateURLModelTest, TemplateURLWithNoKeyword) {
625   VerifyLoad();
626 
627   const size_t initial_count = model()->GetTemplateURLs().size();
628 
629   AddKeywordWithDate("", false, "http://foo1", "http://sugg1",
630       "http://icon1", "UTF-8;UTF-16", "name1", true, Time());
631 
632   // We just added a few items, validate them.
633   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
634 
635   // Reload the model from the database and make sure we get the url back.
636   ResetModel(true);
637 
638   ASSERT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
639 
640   bool found_keyword = false;
641   for (size_t i = 0; i < initial_count + 1; ++i) {
642     if (model()->GetTemplateURLs()[i]->keyword().empty()) {
643       found_keyword = true;
644       break;
645     }
646   }
647   ASSERT_TRUE(found_keyword);
648 }
649 
TEST_F(TemplateURLModelTest,CantReplaceWithSameKeyword)650 TEST_F(TemplateURLModelTest, CantReplaceWithSameKeyword) {
651   ChangeModelToLoadState();
652   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
653   TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo1",
654       "http://sugg1", "http://icon1", "UTF-8;UTF-16",  "name1", true, Time());
655 
656   // Can still replace, newly added template url is marked safe to replace.
657   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
658                                          GURL("http://foo2"), NULL));
659 
660   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
661   // no longer be replaceable.
662   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
663                            t_url->url()->url());
664 
665   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
666                                           GURL("http://foo2"), NULL));
667 }
668 
TEST_F(TemplateURLModelTest,CantReplaceWithSameHosts)669 TEST_F(TemplateURLModelTest, CantReplaceWithSameHosts) {
670   ChangeModelToLoadState();
671   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
672                                          GURL("http://foo.com"), NULL));
673   TemplateURL* t_url = AddKeywordWithDate("foo", false, "http://foo.com",
674       "http://sugg1", "http://icon1", "UTF-8;UTF-16",  "name1", true, Time());
675 
676   // Can still replace, newly added template url is marked safe to replace.
677   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
678                                          GURL("http://foo.com"), NULL));
679 
680   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
681   // no longer be replaceable.
682   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
683                            t_url->url()->url());
684 
685   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
686                                           GURL("http://foo.com"), NULL));
687 }
688 
TEST_F(TemplateURLModelTest,HasDefaultSearchProvider)689 TEST_F(TemplateURLModelTest, HasDefaultSearchProvider) {
690   // We should have a default search provider even if we haven't loaded.
691   ASSERT_TRUE(model()->GetDefaultSearchProvider());
692 
693   // Now force the model to load and make sure we still have a default.
694   VerifyLoad();
695 
696   ASSERT_TRUE(model()->GetDefaultSearchProvider());
697 }
698 
TEST_F(TemplateURLModelTest,DefaultSearchProviderLoadedFromPrefs)699 TEST_F(TemplateURLModelTest, DefaultSearchProviderLoadedFromPrefs) {
700   VerifyLoad();
701 
702   TemplateURL* template_url = new TemplateURL();
703   template_url->SetURL("http://url", 0, 0);
704   template_url->SetSuggestionsURL("http://url2", 0, 0);
705   template_url->SetInstantURL("http://instant", 0, 0);
706   template_url->set_short_name(ASCIIToUTF16("a"));
707   template_url->set_safe_for_autoreplace(true);
708   template_url->set_date_created(Time::FromTimeT(100));
709 
710   model()->Add(template_url);
711 
712   const TemplateURLID id = template_url->id();
713 
714   model()->SetDefaultSearchProvider(template_url);
715 
716   BlockTillServiceProcessesRequests();
717 
718   TemplateURL first_default_search_provider = *template_url;
719 
720   template_url = NULL;
721 
722   // Reset the model and don't load it. The template url we set as the default
723   // should be pulled from prefs now.
724   ResetModel(false);
725 
726   // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
727   // value are persisted to prefs.
728   const TemplateURL* default_turl = model()->GetDefaultSearchProvider();
729   ASSERT_TRUE(default_turl);
730   ASSERT_TRUE(default_turl->url());
731   ASSERT_EQ("http://url", default_turl->url()->url());
732   ASSERT_TRUE(default_turl->suggestions_url());
733   ASSERT_EQ("http://url2", default_turl->suggestions_url()->url());
734   ASSERT_TRUE(default_turl->instant_url());
735   EXPECT_EQ("http://instant", default_turl->instant_url()->url());
736   ASSERT_EQ(ASCIIToUTF16("a"), default_turl->short_name());
737   ASSERT_EQ(id, default_turl->id());
738 
739   // Now do a load and make sure the default search provider really takes.
740   VerifyLoad();
741 
742   ASSERT_TRUE(model()->GetDefaultSearchProvider());
743   AssertEquals(first_default_search_provider,
744                *model()->GetDefaultSearchProvider());
745 }
746 
TEST_F(TemplateURLModelTest,BuildQueryTerms)747 TEST_F(TemplateURLModelTest, BuildQueryTerms) {
748   struct TestData {
749     const std::string url;
750     const bool result;
751     // Keys and values are a semicolon separated list of expected values in the
752     // map.
753     const std::string keys;
754     const std::string values;
755   } data[] = {
756     // No query should return false.
757     { "http://blah/", false, "", "" },
758 
759     // Query with empty key should return false.
760     { "http://blah/foo?=y", false, "", "" },
761 
762     // Query with key occurring multiple times should return false.
763     { "http://blah/foo?x=y&x=z", false, "", "" },
764 
765     { "http://blah/foo?x=y", true, "x", "y" },
766     { "http://blah/foo?x=y&y=z", true, "x;y", "y;z" },
767 
768     // Key occurring multiple times should get an empty string.
769     { "http://blah/foo?x=y&x=z&y=z", true, "x;y", ";z" },
770   };
771 
772   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
773     TemplateURLModel::QueryTerms terms;
774     ASSERT_EQ(data[i].result,
775               TemplateURLModel::BuildQueryTerms(GURL(data[i].url), &terms));
776     if (data[i].result) {
777       std::vector<std::string> keys;
778       std::vector<std::string> values;
779       base::SplitString(data[i].keys, ';', &keys);
780       base::SplitString(data[i].values, ';', &values);
781       ASSERT_TRUE(keys.size() == values.size());
782       ASSERT_EQ(keys.size(), terms.size());
783       for (size_t j = 0; j < keys.size(); ++j) {
784         TemplateURLModel::QueryTerms::iterator term_iterator =
785             terms.find(keys[j]);
786         ASSERT_TRUE(term_iterator != terms.end());
787         ASSERT_EQ(values[j], term_iterator->second);
788       }
789     }
790   }
791 }
792 
TEST_F(TemplateURLModelTest,UpdateKeywordSearchTermsForURL)793 TEST_F(TemplateURLModelTest, UpdateKeywordSearchTermsForURL) {
794   struct TestData {
795     const std::string url;
796     const string16 term;
797   } data[] = {
798     { "http://foo/", string16() },
799     { "http://foo/foo?q=xx", string16() },
800     { "http://x/bar?q=xx", string16() },
801     { "http://x/foo?y=xx", string16() },
802     { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
803     { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
804     { "http://x/foo?q=b&q=xx", string16() },
805   };
806 
807   ChangeModelToLoadState();
808   AddKeywordWithDate("x", false, "http://x/foo?q={searchTerms}",
809       "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name", false, Time());
810 
811   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
812     history::URLVisitedDetails details;
813     details.row = history::URLRow(GURL(data[i].url));
814     details.transition = 0;
815     model()->UpdateKeywordSearchTermsForURL(details);
816     EXPECT_EQ(data[i].term, GetAndClearSearchTerm());
817   }
818 }
819 
TEST_F(TemplateURLModelTest,DontUpdateKeywordSearchForNonReplaceable)820 TEST_F(TemplateURLModelTest, DontUpdateKeywordSearchForNonReplaceable) {
821   struct TestData {
822     const std::string url;
823   } data[] = {
824     { "http://foo/" },
825     { "http://x/bar?q=xx" },
826     { "http://x/foo?y=xx" },
827   };
828 
829   ChangeModelToLoadState();
830   AddKeywordWithDate("x", false, "http://x/foo", "http://sugg1",
831       "http://icon1", "UTF-8;UTF-16", "name", false, Time());
832 
833   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
834     history::URLVisitedDetails details;
835     details.row = history::URLRow(GURL(data[i].url));
836     details.transition = 0;
837     model()->UpdateKeywordSearchTermsForURL(details);
838     ASSERT_EQ(string16(), GetAndClearSearchTerm());
839   }
840 }
841 
TEST_F(TemplateURLModelTest,ChangeGoogleBaseValue)842 TEST_F(TemplateURLModelTest, ChangeGoogleBaseValue) {
843   // NOTE: Do not do a VerifyLoad() here as it will load the prepopulate data,
844   // which also has a {google:baseURL} keyword in it, which will confuse this
845   // test.
846   ChangeModelToLoadState();
847   SetGoogleBaseURL("http://google.com/");
848   const TemplateURL* t_url = AddKeywordWithDate("", true,
849       "{google:baseURL}?q={searchTerms}", "http://sugg1", "http://icon1",
850       "UTF-8;UTF-16", "name", false, Time());
851   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
852   EXPECT_EQ("google.com", t_url->url()->GetHost());
853   EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
854 
855   // Change the Google base url.
856   test_util_.ResetObserverCount();
857   SetGoogleBaseURL("http://foo.com/");
858   VerifyObserverCount(1);
859 
860   // Make sure the host->TemplateURL map was updated appropriately.
861   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("foo.com"));
862   EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL);
863   EXPECT_EQ("foo.com", t_url->url()->GetHost());
864   EXPECT_EQ(ASCIIToUTF16("foo.com"), t_url->keyword());
865   EXPECT_EQ("http://foo.com/?q=x", t_url->url()->ReplaceSearchTerms(*t_url,
866       ASCIIToUTF16("x"), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, string16()));
867 }
868 
869 struct QueryHistoryCallbackImpl {
QueryHistoryCallbackImplQueryHistoryCallbackImpl870   QueryHistoryCallbackImpl() : success(false) {}
871 
CallbackQueryHistoryCallbackImpl872   void Callback(HistoryService::Handle handle,
873                 bool success, const history::URLRow* row,
874                 history::VisitVector* visits) {
875     this->success = success;
876     if (row)
877       this->row = *row;
878     if (visits)
879       this->visits = *visits;
880   }
881 
882   bool success;
883   history::URLRow row;
884   history::VisitVector visits;
885 };
886 
887 // Make sure TemplateURLModel generates a KEYWORD_GENERATED visit for
888 // KEYWORD visits.
TEST_F(TemplateURLModelTest,GenerateVisitOnKeyword)889 TEST_F(TemplateURLModelTest, GenerateVisitOnKeyword) {
890   VerifyLoad();
891   profile()->CreateHistoryService(true, false);
892 
893   // Create a keyword.
894   TemplateURL* t_url = AddKeywordWithDate(
895       "keyword", false, "http://foo.com/foo?query={searchTerms}",
896       "http://sugg1", "http://icon1", "UTF-8;UTF-16", "keyword",
897       true, base::Time::Now());
898 
899   // Add a visit that matches the url of the keyword.
900   HistoryService* history =
901       profile()->GetHistoryService(Profile::EXPLICIT_ACCESS);
902   history->AddPage(
903       GURL(t_url->url()->ReplaceSearchTerms(*t_url, ASCIIToUTF16("blah"), 0,
904                                             string16())),
905       NULL, 0, GURL(), PageTransition::KEYWORD, history::RedirectList(),
906       history::SOURCE_BROWSED, false);
907 
908   // Wait for history to finish processing the request.
909   profile()->BlockUntilHistoryProcessesPendingRequests();
910 
911   // Query history for the generated url.
912   CancelableRequestConsumer consumer;
913   QueryHistoryCallbackImpl callback;
914   history->QueryURL(GURL("http://keyword"), true, &consumer,
915       NewCallback(&callback, &QueryHistoryCallbackImpl::Callback));
916 
917   // Wait for the request to be processed.
918   profile()->BlockUntilHistoryProcessesPendingRequests();
919 
920   // And make sure the url and visit were added.
921   EXPECT_TRUE(callback.success);
922   EXPECT_NE(0, callback.row.id());
923   ASSERT_EQ(1U, callback.visits.size());
924   EXPECT_EQ(PageTransition::KEYWORD_GENERATED,
925             PageTransition::StripQualifier(callback.visits[0].transition));
926 }
927 
928 // Make sure that the load routine deletes prepopulated engines that no longer
929 // exist in the prepopulate data.
TEST_F(TemplateURLModelTest,LoadDeletesUnusedProvider)930 TEST_F(TemplateURLModelTest, LoadDeletesUnusedProvider) {
931   // Create a preloaded template url. Add it to a loaded model and wait for the
932   // saves to finish.
933   TemplateURL* t_url = CreatePreloadedTemplateURL();
934   ChangeModelToLoadState();
935   model()->Add(t_url);
936   ASSERT_TRUE(
937       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
938   BlockTillServiceProcessesRequests();
939 
940   // Ensure that merging clears this engine.
941   ResetModel(true);
942   ASSERT_TRUE(
943       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
944 
945   // Wait for any saves to finish.
946   BlockTillServiceProcessesRequests();
947 
948   // Reload the model to verify that the database was updated as a result of the
949   // merge.
950   ResetModel(true);
951   ASSERT_TRUE(
952       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
953 }
954 
955 // Make sure that load routine doesn't delete prepopulated engines that no
956 // longer exist in the prepopulate data if it has been modified by the user.
TEST_F(TemplateURLModelTest,LoadRetainsModifiedProvider)957 TEST_F(TemplateURLModelTest, LoadRetainsModifiedProvider) {
958   // Create a preloaded template url and add it to a loaded model.
959   TemplateURL* t_url = CreatePreloadedTemplateURL();
960   t_url->set_safe_for_autoreplace(false);
961   ChangeModelToLoadState();
962   model()->Add(t_url);
963 
964   // Do the copy after t_url is added so that the id is set.
965   TemplateURL copy_t_url = *t_url;
966   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
967 
968   // Wait for any saves to finish.
969   BlockTillServiceProcessesRequests();
970 
971   // Ensure that merging won't clear it if the user has edited it.
972   ResetModel(true);
973   const TemplateURL* url_for_unittest =
974       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
975   ASSERT_TRUE(url_for_unittest != NULL);
976   AssertEquals(copy_t_url, *url_for_unittest);
977 
978   // Wait for any saves to finish.
979   BlockTillServiceProcessesRequests();
980 
981   // Reload the model to verify that save/reload retains the item.
982   ResetModel(true);
983   ASSERT_TRUE(
984       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
985 }
986 
987 // Make sure that load routine doesn't delete
988 // prepopulated engines that no longer exist in the prepopulate data if
989 // it has been modified by the user.
TEST_F(TemplateURLModelTest,LoadSavesPrepopulatedDefaultSearchProvider)990 TEST_F(TemplateURLModelTest, LoadSavesPrepopulatedDefaultSearchProvider) {
991   VerifyLoad();
992   // Verify that the default search provider is set to something.
993   ASSERT_TRUE(model()->GetDefaultSearchProvider() != NULL);
994   TemplateURL default_url = *model()->GetDefaultSearchProvider();
995 
996   // Wait for any saves to finish.
997   BlockTillServiceProcessesRequests();
998 
999   // Reload the model and check that the default search provider
1000   // was properly saved.
1001   ResetModel(true);
1002   ASSERT_TRUE(model()->GetDefaultSearchProvider() != NULL);
1003   AssertEquals(default_url, *model()->GetDefaultSearchProvider());
1004 }
1005 
1006 // Make sure that the load routine doesn't delete
1007 // prepopulated engines that no longer exist in the prepopulate data if
1008 // it is the default search provider.
TEST_F(TemplateURLModelTest,LoadRetainsDefaultProvider)1009 TEST_F(TemplateURLModelTest, LoadRetainsDefaultProvider) {
1010   // Set the default search provider to a preloaded template url which
1011   // is not in the current set of preloaded template urls and save
1012   // the result.
1013   TemplateURL* t_url = CreatePreloadedTemplateURL();
1014   ChangeModelToLoadState();
1015   model()->Add(t_url);
1016   model()->SetDefaultSearchProvider(t_url);
1017   // Do the copy after t_url is added and set as default so that its
1018   // internal state is correct.
1019   TemplateURL copy_t_url = *t_url;
1020 
1021   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
1022   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
1023   BlockTillServiceProcessesRequests();
1024 
1025   // Ensure that merging won't clear the prepopulated template url
1026   // which is no longer present if it's the default engine.
1027   ResetModel(true);
1028   {
1029     const TemplateURL* keyword_url =
1030         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1031     ASSERT_TRUE(keyword_url != NULL);
1032     AssertEquals(copy_t_url, *keyword_url);
1033     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1034   }
1035 
1036   // Wait for any saves to finish.
1037   BlockTillServiceProcessesRequests();
1038 
1039   // Reload the model to verify that the update was saved.
1040   ResetModel(true);
1041   {
1042     const TemplateURL* keyword_url =
1043         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
1044     ASSERT_TRUE(keyword_url != NULL);
1045     AssertEquals(copy_t_url, *keyword_url);
1046     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
1047   }
1048 }
1049 
1050 // Make sure that the load routine updates the url of a preexisting
1051 // default search engine provider and that the result is saved correctly.
TEST_F(TemplateURLModelTest,LoadUpdatesDefaultSearchURL)1052 TEST_F(TemplateURLModelTest, LoadUpdatesDefaultSearchURL) {
1053   TestLoadUpdatingPreloadedURL(0);
1054 }
1055 
1056 // Make sure that the load routine updates the url of a preexisting
1057 // non-default search engine provider and that the result is saved correctly.
TEST_F(TemplateURLModelTest,LoadUpdatesSearchURL)1058 TEST_F(TemplateURLModelTest, LoadUpdatesSearchURL) {
1059   TestLoadUpdatingPreloadedURL(1);
1060 }
1061 
1062 // Make sure that the load does update of auto-keywords correctly.
1063 // This test basically verifies that no asserts or crashes occur
1064 // during this operation.
TEST_F(TemplateURLModelTest,LoadDoesAutoKeywordUpdate)1065 TEST_F(TemplateURLModelTest, LoadDoesAutoKeywordUpdate) {
1066   string16 prepopulated_url;
1067   TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL(
1068       0, &prepopulated_url);
1069   t_url->set_safe_for_autoreplace(false);
1070   t_url->SetURL("{google:baseURL}?q={searchTerms}", 0, 0);
1071   t_url->set_autogenerate_keyword(true);
1072 
1073   // Then add it to the model and save it all.
1074   ChangeModelToLoadState();
1075   model()->Add(t_url);
1076   BlockTillServiceProcessesRequests();
1077 
1078   // Now reload the model and verify that the merge updates the url.
1079   ResetModel(true);
1080 
1081   // Wait for any saves to finish.
1082   BlockTillServiceProcessesRequests();
1083 }
1084 
1085 // Simulates failing to load the webdb and makes sure the default search
1086 // provider is valid.
TEST_F(TemplateURLModelTest,FailedInit)1087 TEST_F(TemplateURLModelTest, FailedInit) {
1088   VerifyLoad();
1089 
1090   test_util_.ClearModel();
1091   test_util_.GetWebDataService()->UnloadDatabase();
1092   test_util_.GetWebDataService()->set_failed_init(true);
1093 
1094   ResetModel(false);
1095   model()->Load();
1096   BlockTillServiceProcessesRequests();
1097 
1098   ASSERT_TRUE(model()->GetDefaultSearchProvider());
1099 }
1100 
1101 // Verifies that if the default search URL preference is managed, we report
1102 // the default search as managed.  Also check that we are getting the right
1103 // values.
TEST_F(TemplateURLModelTest,TestManagedDefaultSearch)1104 TEST_F(TemplateURLModelTest, TestManagedDefaultSearch) {
1105   VerifyLoad();
1106   const size_t initial_count = model()->GetTemplateURLs().size();
1107   test_util_.ResetObserverCount();
1108 
1109   // Set a regular default search provider.
1110   TemplateURL* regular_default = AddKeywordWithDate("key1", false,
1111       "http://foo1", "http://sugg1", "http://icon1", "UTF-8;UTF-16", "name1",
1112       true, Time());
1113   VerifyObserverCount(1);
1114   model()->SetDefaultSearchProvider(regular_default);
1115   // Adding the URL and setting the default search provider should have caused
1116   // notifications.
1117   VerifyObserverCount(1);
1118   EXPECT_FALSE(model()->is_default_search_managed());
1119   EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
1120 
1121   // Set a managed preference that establishes a default search provider.
1122   const char kName[] = "test1";
1123   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
1124   const char kIconURL[] = "http://test.com/icon.jpg";
1125   const char kEncodings[] = "UTF-16;UTF-32";
1126   SetManagedDefaultSearchPreferences(true, kName, kSearchURL, "", kIconURL,
1127                                      kEncodings, "");
1128   VerifyObserverFired();
1129   EXPECT_TRUE(model()->is_default_search_managed());
1130   EXPECT_EQ(2 + initial_count, model()->GetTemplateURLs().size());
1131 
1132   // Verify that the default manager we are getting is the managed one.
1133   scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL());
1134   expected_managed_default1->SetURL(kSearchURL, 0, 0);
1135   expected_managed_default1->SetFaviconURL(GURL(kIconURL));
1136   expected_managed_default1->set_short_name(ASCIIToUTF16("test1"));
1137   std::vector<std::string> encodings_vector;
1138   base::SplitString(kEncodings, ';', &encodings_vector);
1139   expected_managed_default1->set_input_encodings(encodings_vector);
1140   expected_managed_default1->set_show_in_default_list(true);
1141   const TemplateURL* actual_managed_default =
1142       model()->GetDefaultSearchProvider();
1143   ExpectSimilar(actual_managed_default, expected_managed_default1.get());
1144   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1145 
1146   // Update the managed preference and check that the model has changed.
1147   const char kNewName[] = "test2";
1148   const char kNewSearchURL[] = "http://other.com/search?t={searchTerms}";
1149   const char kNewSuggestURL[] = "http://other.com/suggest?t={searchTerms}";
1150   SetManagedDefaultSearchPreferences(true, kNewName, kNewSearchURL,
1151                                      kNewSuggestURL, "", "", "");
1152   VerifyObserverFired();
1153   EXPECT_TRUE(model()->is_default_search_managed());
1154   EXPECT_EQ(2 + initial_count, model()->GetTemplateURLs().size());
1155 
1156   // Verify that the default manager we are now getting is the correct one.
1157   scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL());
1158   expected_managed_default2->SetURL(kNewSearchURL, 0, 0);
1159   expected_managed_default2->SetSuggestionsURL(kNewSuggestURL, 0, 0);
1160   expected_managed_default2->set_short_name(ASCIIToUTF16("test2"));
1161   expected_managed_default2->set_show_in_default_list(true);
1162   actual_managed_default = model()->GetDefaultSearchProvider();
1163   ExpectSimilar(actual_managed_default, expected_managed_default2.get());
1164   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1165 
1166   // Remove all the managed prefs and check that we are no longer managed.
1167   RemoveManagedDefaultSearchPreferences();
1168   VerifyObserverFired();
1169   EXPECT_FALSE(model()->is_default_search_managed());
1170   EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
1171 
1172   // The default should now be the first URL added
1173   const TemplateURL* actual_final_managed_default =
1174       model()->GetDefaultSearchProvider();
1175   ExpectSimilar(actual_final_managed_default,
1176       model()->GetTemplateURLs()[0]);
1177   EXPECT_EQ(actual_final_managed_default->show_in_default_list(), true);
1178 
1179   // Disable the default search provider through policy.
1180   SetManagedDefaultSearchPreferences(false, "", "", "", "", "", "");
1181   VerifyObserverFired();
1182   EXPECT_TRUE(model()->is_default_search_managed());
1183   EXPECT_TRUE(NULL == model()->GetDefaultSearchProvider());
1184   EXPECT_EQ(1 + initial_count, model()->GetTemplateURLs().size());
1185 
1186   // Re-enable it.
1187   SetManagedDefaultSearchPreferences(true, kName, kSearchURL, "", kIconURL,
1188                                      kEncodings, "");
1189   VerifyObserverFired();
1190   EXPECT_TRUE(model()->is_default_search_managed());
1191   EXPECT_EQ(2 + initial_count, model()->GetTemplateURLs().size());
1192 
1193   // Verify that the default manager we are getting is the managed one.
1194   actual_managed_default = model()->GetDefaultSearchProvider();
1195   ExpectSimilar(actual_managed_default, expected_managed_default1.get());
1196   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
1197 }
1198