Home | History | Annotate | Download | only in search_engines
      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:
     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?
     52   bool passed() const { return passed_; }
     53 
     54  private:
     55   friend class base::RefCountedThreadSafe<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:
     67   explicit TestSearchTermsData(const char* google_base_url)
     68       : google_base_url_(google_base_url)  {
     69   }
     70 
     71   virtual std::string GoogleBaseURLValue() const {
     72     return google_base_url_;
     73   }
     74 
     75   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.
     81   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*.
     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:
    109   TemplateURLModelTest() {}
    110 
    111   virtual void SetUp() {
    112     test_util_.SetUp();
    113   }
    114 
    115   virtual void TearDown() {
    116     test_util_.TearDown();
    117   }
    118 
    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.
    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.
    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.
    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.
    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.
    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.
    259   void VerifyObserverCount(int expected_changed_count) {
    260     EXPECT_EQ(expected_changed_count, test_util_.GetObserverCount());
    261     test_util_.ResetObserverCount();
    262   }
    263   void VerifyObserverFired() {
    264     EXPECT_LE(1, test_util_.GetObserverCount());
    265     test_util_.ResetObserverCount();
    266   }
    267   void BlockTillServiceProcessesRequests() {
    268     TemplateURLModelTestUtil::BlockTillServiceProcessesRequests();
    269   }
    270   void VerifyLoad() { test_util_.VerifyLoad(); }
    271   void ChangeModelToLoadState() { test_util_.ChangeModelToLoadState(); }
    272   void ResetModel(bool verify_load) { test_util_.ResetModel(verify_load); }
    273   string16 GetAndClearSearchTerm() {
    274     return test_util_.GetAndClearSearchTerm();
    275   }
    276   void SetGoogleBaseURL(const std::string& base_url) const {
    277     test_util_.SetGoogleBaseURL(base_url);
    278   }
    279   WebDataService* GetWebDataService() { return test_util_.GetWebDataService(); }
    280   TemplateURLModel* model() { return test_util_.model(); }
    281   TestingProfile* profile() { return test_util_.profile(); }
    282 
    283  protected:
    284   TemplateURLModelTestUtil test_util_;
    285 
    286   DISALLOW_COPY_AND_ASSIGN(TemplateURLModelTest);
    287 };
    288 
    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 
    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 
    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 
    381 TEST_F(TemplateURLModelTest, MAYBE_Load) {
    382   VerifyLoad();
    383 }
    384 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 {
    870   QueryHistoryCallbackImpl() : success(false) {}
    871 
    872   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.
    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.
    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.
    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.
    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.
   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.
   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.
   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.
   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.
   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.
   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