Home | History | Annotate | Download | only in search_engines
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/bind.h"
      6 #include "base/bind_helpers.h"
      7 #include "base/callback.h"
      8 #include "base/memory/ref_counted.h"
      9 #include "base/memory/scoped_vector.h"
     10 #include "base/run_loop.h"
     11 #include "base/strings/string_split.h"
     12 #include "base/strings/string_util.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "base/test/mock_time_provider.h"
     15 #include "base/threading/thread.h"
     16 #include "base/time/time.h"
     17 #include "chrome/browser/extensions/extension_service_unittest.h"
     18 #include "chrome/browser/history/history_notifications.h"
     19 #include "chrome/browser/history/history_service.h"
     20 #include "chrome/browser/history/history_service_factory.h"
     21 #include "chrome/browser/search_engines/search_host_to_urls_map.h"
     22 #include "chrome/browser/search_engines/search_terms_data.h"
     23 #include "chrome/browser/search_engines/template_url.h"
     24 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
     25 #include "chrome/browser/search_engines/template_url_service.h"
     26 #include "chrome/browser/search_engines/template_url_service_test_util.h"
     27 #include "chrome/browser/webdata/web_data_service_factory.h"
     28 #include "chrome/common/url_constants.h"
     29 #include "chrome/test/base/testing_profile.h"
     30 #include "components/webdata/common/web_database.h"
     31 #include "content/public/test/test_browser_thread.h"
     32 #include "extensions/common/constants.h"
     33 #include "extensions/common/extension.h"
     34 #include "extensions/common/manifest_constants.h"
     35 #include "testing/gtest/include/gtest/gtest.h"
     36 
     37 using base::Time;
     38 using base::TimeDelta;
     39 using content::BrowserThread;
     40 using ::testing::Return;
     41 using ::testing::StrictMock;
     42 
     43 namespace {
     44 
     45 // TestSearchTermsData --------------------------------------------------------
     46 
     47 // Simple implementation of SearchTermsData.
     48 class TestSearchTermsData : public SearchTermsData {
     49  public:
     50   explicit TestSearchTermsData(const char* google_base_url);
     51 
     52   virtual std::string GoogleBaseURLValue() const OVERRIDE;
     53 
     54  private:
     55   std::string google_base_url_;
     56 
     57   DISALLOW_COPY_AND_ASSIGN(TestSearchTermsData);
     58 };
     59 
     60 TestSearchTermsData::TestSearchTermsData(const char* google_base_url)
     61     : google_base_url_(google_base_url)  {
     62 }
     63 
     64 std::string TestSearchTermsData::GoogleBaseURLValue() const {
     65   return google_base_url_;
     66 }
     67 
     68 
     69 // QueryHistoryCallbackImpl ---------------------------------------------------
     70 
     71 struct QueryHistoryCallbackImpl {
     72   QueryHistoryCallbackImpl() : success(false) {}
     73 
     74   void Callback(HistoryService::Handle handle,
     75                 bool success,
     76                 const history::URLRow* row,
     77                 history::VisitVector* visits) {
     78     this->success = success;
     79     if (row)
     80       this->row = *row;
     81     if (visits)
     82       this->visits = *visits;
     83   }
     84 
     85   bool success;
     86   history::URLRow row;
     87   history::VisitVector visits;
     88 };
     89 
     90 TemplateURL* CreateKeywordWithDate(
     91     TemplateURLService* model,
     92     const std::string& short_name,
     93     const std::string& keyword,
     94     const std::string& url,
     95     const std::string& suggest_url,
     96     const std::string& alternate_url,
     97     const std::string& favicon_url,
     98     bool safe_for_autoreplace,
     99     const std::string& encodings,
    100     Time date_created,
    101     Time last_modified) {
    102   TemplateURLData data;
    103   data.short_name = UTF8ToUTF16(short_name);
    104   data.SetKeyword(UTF8ToUTF16(keyword));
    105   data.SetURL(url);
    106   data.suggestions_url = suggest_url;
    107   if (!alternate_url.empty())
    108     data.alternate_urls.push_back(alternate_url);
    109   data.favicon_url = GURL(favicon_url);
    110   data.safe_for_autoreplace = safe_for_autoreplace;
    111   base::SplitString(encodings, ';', &data.input_encodings);
    112   data.date_created = date_created;
    113   data.last_modified = last_modified;
    114   return new TemplateURL(model->profile(), data);
    115 }
    116 
    117 TemplateURL* AddKeywordWithDate(
    118     TemplateURLService* model,
    119     const std::string& short_name,
    120     const std::string& keyword,
    121     const std::string& url,
    122     const std::string& suggest_url,
    123     const std::string& alternate_url,
    124     const std::string& favicon_url,
    125     bool safe_for_autoreplace,
    126     const std::string& encodings,
    127     Time date_created,
    128     Time last_modified) {
    129   TemplateURL* t_url = CreateKeywordWithDate(
    130       model, short_name, keyword, url, suggest_url, alternate_url,favicon_url,
    131       safe_for_autoreplace, encodings, date_created, last_modified);
    132   model->Add(t_url);
    133   EXPECT_NE(0, t_url->id());
    134   return t_url;
    135 }
    136 
    137 // Checks that the two TemplateURLs are similar. It does not check the id, the
    138 // date_created or the last_modified time.  Neither pointer should be NULL.
    139 void ExpectSimilar(const TemplateURL* expected, const TemplateURL* actual) {
    140   ASSERT_TRUE(expected != NULL);
    141   ASSERT_TRUE(actual != NULL);
    142   EXPECT_EQ(expected->short_name(), actual->short_name());
    143   EXPECT_EQ(expected->keyword(), actual->keyword());
    144   EXPECT_EQ(expected->url(), actual->url());
    145   EXPECT_EQ(expected->suggestions_url(), actual->suggestions_url());
    146   EXPECT_EQ(expected->favicon_url(), actual->favicon_url());
    147   EXPECT_EQ(expected->alternate_urls(), actual->alternate_urls());
    148   EXPECT_EQ(expected->show_in_default_list(), actual->show_in_default_list());
    149   EXPECT_EQ(expected->safe_for_autoreplace(), actual->safe_for_autoreplace());
    150   EXPECT_EQ(expected->input_encodings(), actual->input_encodings());
    151   EXPECT_EQ(expected->search_terms_replacement_key(),
    152             actual->search_terms_replacement_key());
    153 }
    154 
    155 }  // namespace
    156 
    157 
    158 // TemplateURLServiceTest -----------------------------------------------------
    159 
    160 class TemplateURLServiceTest : public testing::Test {
    161  public:
    162   TemplateURLServiceTest();
    163 
    164   // testing::Test
    165   virtual void SetUp();
    166   virtual void TearDown();
    167 
    168   TemplateURL* AddKeywordWithDate(const std::string& short_name,
    169                                   const std::string& keyword,
    170                                   const std::string& url,
    171                                   const std::string& suggest_url,
    172                                   const std::string& alternate_url,
    173                                   const std::string& favicon_url,
    174                                   bool safe_for_autoreplace,
    175                                   const std::string& encodings,
    176                                   Time date_created,
    177                                   Time last_modified);
    178 
    179   // Verifies the two TemplateURLs are equal.
    180   void AssertEquals(const TemplateURL& expected, const TemplateURL& actual);
    181 
    182   // Create an URL that appears to have been prepopulated, but won't be in the
    183   // current data. The caller owns the returned TemplateURL*.
    184   TemplateURL* CreatePreloadedTemplateURL(bool safe_for_autoreplace,
    185                                           int prepopulate_id);
    186 
    187   // Creates a TemplateURL with the same prepopulated id as a real prepopulated
    188   // item. The input number determines which prepopulated item. The caller is
    189   // responsible for owning the returned TemplateURL*.
    190   TemplateURL* CreateReplaceablePreloadedTemplateURL(
    191       bool safe_for_autoreplace,
    192       size_t index_offset_from_default,
    193       base::string16* prepopulated_display_url);
    194 
    195   // Verifies the behavior of when a preloaded url later gets changed.
    196   // Since the input is the offset from the default, when one passes in
    197   // 0, it tests the default. Passing in a number > 0 will verify what
    198   // happens when a preloaded url that is not the default gets updated.
    199   void TestLoadUpdatingPreloadedURL(size_t index_offset_from_default);
    200 
    201   // Helper methods to make calling TemplateURLServiceTestUtil methods less
    202   // visually noisy in the test code.
    203   void VerifyObserverCount(int expected_changed_count);
    204   void VerifyObserverFired();
    205   TemplateURLService* model() { return test_util_.model(); }
    206 
    207  protected:
    208   TemplateURLServiceTestUtil test_util_;
    209 
    210   void TestGenerateSearchURL(SearchTermsData* search_terms_data) {
    211     struct GenerateSearchURLCase {
    212       const char* test_name;
    213       const char* url;
    214       const char* expected;
    215     } generate_url_cases[] = {
    216       { "invalid URL", "foo{searchTerms}", "" },
    217       { "URL with no replacements", "http://foo/", "http://foo/" },
    218       { "basic functionality", "http://foo/{searchTerms}",
    219         "http://foo/blah.blah.blah.blah.blah" }
    220     };
    221 
    222     for (size_t i = 0; i < ARRAYSIZE_UNSAFE(generate_url_cases); ++i) {
    223       TemplateURLData data;
    224       data.SetURL(generate_url_cases[i].url);
    225       TemplateURL t_url(NULL, data);
    226       std::string result;
    227       if (search_terms_data) {
    228           result = TemplateURLService::GenerateSearchURLUsingTermsData(
    229               &t_url, *search_terms_data).spec();
    230       } else {
    231           result = TemplateURLService::GenerateSearchURL(&t_url).spec();
    232       }
    233       EXPECT_EQ(result,  generate_url_cases[i].expected)
    234           << generate_url_cases[i].test_name << " failed. Expected "
    235           << generate_url_cases[i].expected << " Actual " << result;
    236     }
    237   }
    238 
    239 
    240   DISALLOW_COPY_AND_ASSIGN(TemplateURLServiceTest);
    241 };
    242 
    243 TemplateURLServiceTest::TemplateURLServiceTest() {
    244 }
    245 
    246 void TemplateURLServiceTest::SetUp() {
    247   test_util_.SetUp();
    248 }
    249 
    250 void TemplateURLServiceTest::TearDown() {
    251   test_util_.TearDown();
    252 }
    253 
    254 TemplateURL* TemplateURLServiceTest::AddKeywordWithDate(
    255     const std::string& short_name,
    256     const std::string& keyword,
    257     const std::string& url,
    258     const std::string& suggest_url,
    259     const std::string& alternate_url,
    260     const std::string& favicon_url,
    261     bool safe_for_autoreplace,
    262     const std::string& encodings,
    263     Time date_created,
    264     Time last_modified) {
    265   return ::AddKeywordWithDate(model(), short_name, keyword, url, suggest_url,
    266                               alternate_url, favicon_url, safe_for_autoreplace,
    267                               encodings, date_created, last_modified);
    268 }
    269 
    270 void TemplateURLServiceTest::AssertEquals(const TemplateURL& expected,
    271                                           const TemplateURL& actual) {
    272   ASSERT_EQ(expected.short_name(), actual.short_name());
    273   ASSERT_EQ(expected.keyword(), actual.keyword());
    274   ASSERT_EQ(expected.url(), actual.url());
    275   ASSERT_EQ(expected.suggestions_url(), actual.suggestions_url());
    276   ASSERT_EQ(expected.favicon_url(), actual.favicon_url());
    277   ASSERT_EQ(expected.alternate_urls(), actual.alternate_urls());
    278   ASSERT_EQ(expected.show_in_default_list(), actual.show_in_default_list());
    279   ASSERT_EQ(expected.safe_for_autoreplace(), actual.safe_for_autoreplace());
    280   ASSERT_EQ(expected.input_encodings(), actual.input_encodings());
    281   ASSERT_EQ(expected.id(), actual.id());
    282   ASSERT_EQ(expected.date_created(), actual.date_created());
    283   ASSERT_EQ(expected.last_modified(), actual.last_modified());
    284   ASSERT_EQ(expected.sync_guid(), actual.sync_guid());
    285   ASSERT_EQ(expected.search_terms_replacement_key(),
    286             actual.search_terms_replacement_key());
    287 }
    288 
    289 TemplateURL* TemplateURLServiceTest::CreatePreloadedTemplateURL(
    290     bool safe_for_autoreplace,
    291     int prepopulate_id) {
    292   TemplateURLData data;
    293   data.short_name = ASCIIToUTF16("unittest");
    294   data.SetKeyword(ASCIIToUTF16("unittest"));
    295   data.SetURL("http://www.unittest.com/{searchTerms}");
    296   data.favicon_url = GURL("http://favicon.url");
    297   data.show_in_default_list = true;
    298   data.safe_for_autoreplace = safe_for_autoreplace;
    299   data.input_encodings.push_back("UTF-8");
    300   data.date_created = Time::FromTimeT(100);
    301   data.last_modified = Time::FromTimeT(100);
    302   data.prepopulate_id = prepopulate_id;
    303   return new TemplateURL(test_util_.profile(), data);
    304 }
    305 
    306 TemplateURL* TemplateURLServiceTest::CreateReplaceablePreloadedTemplateURL(
    307     bool safe_for_autoreplace,
    308     size_t index_offset_from_default,
    309     base::string16* prepopulated_display_url) {
    310   size_t default_search_provider_index = 0;
    311   ScopedVector<TemplateURL> prepopulated_urls =
    312       TemplateURLPrepopulateData::GetPrepopulatedEngines(
    313           test_util_.profile(), &default_search_provider_index);
    314   EXPECT_LT(index_offset_from_default, prepopulated_urls.size());
    315   size_t prepopulated_index = (default_search_provider_index +
    316       index_offset_from_default) % prepopulated_urls.size();
    317   TemplateURL* t_url = CreatePreloadedTemplateURL(safe_for_autoreplace,
    318       prepopulated_urls[prepopulated_index]->prepopulate_id());
    319   *prepopulated_display_url =
    320       prepopulated_urls[prepopulated_index]->url_ref().DisplayURL();
    321   return t_url;
    322 }
    323 
    324 void TemplateURLServiceTest::TestLoadUpdatingPreloadedURL(
    325     size_t index_offset_from_default) {
    326   base::string16 prepopulated_url;
    327   TemplateURL* t_url = CreateReplaceablePreloadedTemplateURL(false,
    328       index_offset_from_default, &prepopulated_url);
    329 
    330   base::string16 original_url = t_url->url_ref().DisplayURL();
    331   std::string original_guid = t_url->sync_guid();
    332   EXPECT_NE(prepopulated_url, original_url);
    333 
    334   // Then add it to the model and save it all.
    335   test_util_.ChangeModelToLoadState();
    336   model()->Add(t_url);
    337   const TemplateURL* keyword_url =
    338       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
    339   ASSERT_TRUE(keyword_url != NULL);
    340   EXPECT_EQ(t_url, keyword_url);
    341   EXPECT_EQ(original_url, keyword_url->url_ref().DisplayURL());
    342   base::RunLoop().RunUntilIdle();
    343 
    344   // Now reload the model and verify that the merge updates the url, and
    345   // preserves the sync GUID.
    346   test_util_.ResetModel(true);
    347   keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
    348   ASSERT_TRUE(keyword_url != NULL);
    349   EXPECT_EQ(prepopulated_url, keyword_url->url_ref().DisplayURL());
    350   EXPECT_EQ(original_guid, keyword_url->sync_guid());
    351 
    352   // Wait for any saves to finish.
    353   base::RunLoop().RunUntilIdle();
    354 
    355   // Reload the model to verify that change was saved correctly.
    356   test_util_.ResetModel(true);
    357   keyword_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
    358   ASSERT_TRUE(keyword_url != NULL);
    359   EXPECT_EQ(prepopulated_url, keyword_url->url_ref().DisplayURL());
    360   EXPECT_EQ(original_guid, keyword_url->sync_guid());
    361 }
    362 
    363 void TemplateURLServiceTest::VerifyObserverCount(int expected_changed_count) {
    364   EXPECT_EQ(expected_changed_count, test_util_.GetObserverCount());
    365   test_util_.ResetObserverCount();
    366 }
    367 
    368 void TemplateURLServiceTest::VerifyObserverFired() {
    369   EXPECT_LE(1, test_util_.GetObserverCount());
    370   test_util_.ResetObserverCount();
    371 }
    372 
    373 
    374 // Actual tests ---------------------------------------------------------------
    375 
    376 TEST_F(TemplateURLServiceTest, Load) {
    377   test_util_.VerifyLoad();
    378 }
    379 
    380 TEST_F(TemplateURLServiceTest, AddUpdateRemove) {
    381   // Add a new TemplateURL.
    382   test_util_.VerifyLoad();
    383   const size_t initial_count = model()->GetTemplateURLs().size();
    384 
    385   TemplateURLData data;
    386   data.short_name = ASCIIToUTF16("google");
    387   data.SetKeyword(ASCIIToUTF16("keyword"));
    388   data.SetURL("http://www.google.com/foo/bar");
    389   data.favicon_url = GURL("http://favicon.url");
    390   data.safe_for_autoreplace = true;
    391   data.date_created = Time::FromTimeT(100);
    392   data.last_modified = Time::FromTimeT(100);
    393   data.sync_guid = "00000000-0000-0000-0000-000000000001";
    394   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
    395   model()->Add(t_url);
    396   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
    397                                          NULL));
    398   VerifyObserverCount(1);
    399   base::RunLoop().RunUntilIdle();
    400   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
    401   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(t_url->keyword()));
    402   // We need to make a second copy as the model takes ownership of |t_url| and
    403   // will delete it.  We have to do this after calling Add() since that gives
    404   // |t_url| its ID.
    405   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
    406                                                      t_url->data()));
    407 
    408   // Reload the model to verify it was actually saved to the database.
    409   test_util_.ResetModel(true);
    410   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
    411   TemplateURL* loaded_url =
    412       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
    413   ASSERT_TRUE(loaded_url != NULL);
    414   AssertEquals(*cloned_url, *loaded_url);
    415   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
    416                                          NULL));
    417 
    418   // We expect the last_modified time to be updated to the present time on an
    419   // explicit reset. We have to set up the expectation here because ResetModel
    420   // resets the TimeProvider in the TemplateURLService.
    421   StrictMock<base::MockTimeProvider> mock_time;
    422   model()->set_time_provider(&base::MockTimeProvider::StaticNow);
    423   EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
    424 
    425   // Mutate an element and verify it succeeded.
    426   model()->ResetTemplateURL(loaded_url, ASCIIToUTF16("a"), ASCIIToUTF16("b"),
    427                             "c");
    428   ASSERT_EQ(ASCIIToUTF16("a"), loaded_url->short_name());
    429   ASSERT_EQ(ASCIIToUTF16("b"), loaded_url->keyword());
    430   ASSERT_EQ("c", loaded_url->url());
    431   ASSERT_FALSE(loaded_url->safe_for_autoreplace());
    432   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("keyword"), GURL(),
    433                                          NULL));
    434   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("b"), GURL(), NULL));
    435   cloned_url.reset(new TemplateURL(loaded_url->profile(), loaded_url->data()));
    436   base::RunLoop().RunUntilIdle();
    437   test_util_.ResetModel(true);
    438   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
    439   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("b"));
    440   ASSERT_TRUE(loaded_url != NULL);
    441   AssertEquals(*cloned_url, *loaded_url);
    442   // We changed a TemplateURL in the service, so ensure that the time was
    443   // updated.
    444   ASSERT_EQ(base::Time::FromDoubleT(1337), loaded_url->last_modified());
    445 
    446   // Remove an element and verify it succeeded.
    447   model()->Remove(loaded_url);
    448   VerifyObserverCount(1);
    449   test_util_.ResetModel(true);
    450   ASSERT_EQ(initial_count, model()->GetTemplateURLs().size());
    451   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("b")) == NULL);
    452 }
    453 
    454 TEST_F(TemplateURLServiceTest, AddSameKeyword) {
    455   test_util_.VerifyLoad();
    456 
    457   AddKeywordWithDate(
    458       "first", "keyword", "http://test1", std::string(), std::string(),
    459       std::string(), true, "UTF-8", Time(), Time());
    460   VerifyObserverCount(1);
    461 
    462   // Test what happens when we try to add a TemplateURL with the same keyword as
    463   // one in the model.
    464   TemplateURLData data;
    465   data.short_name = ASCIIToUTF16("second");
    466   data.SetKeyword(ASCIIToUTF16("keyword"));
    467   data.SetURL("http://test2");
    468   data.safe_for_autoreplace = false;
    469   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
    470   model()->Add(t_url);
    471 
    472   // Because the old TemplateURL was replaceable and the new one wasn't, the new
    473   // one should have replaced the old.
    474   VerifyObserverCount(1);
    475   EXPECT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
    476   EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
    477   EXPECT_EQ(ASCIIToUTF16("keyword"), t_url->keyword());
    478   EXPECT_FALSE(t_url->safe_for_autoreplace());
    479 
    480   // Now try adding a replaceable TemplateURL.  This should just delete the
    481   // passed-in URL.
    482   data.short_name = ASCIIToUTF16("third");
    483   data.SetURL("http://test3");
    484   data.safe_for_autoreplace = true;
    485   model()->Add(new TemplateURL(test_util_.profile(), data));
    486   VerifyObserverCount(0);
    487   EXPECT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
    488   EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
    489   EXPECT_EQ(ASCIIToUTF16("keyword"), t_url->keyword());
    490   EXPECT_FALSE(t_url->safe_for_autoreplace());
    491 
    492   // Now try adding a non-replaceable TemplateURL again.  This should uniquify
    493   // the existing entry's keyword.
    494   data.short_name = ASCIIToUTF16("fourth");
    495   data.SetURL("http://test4");
    496   data.safe_for_autoreplace = false;
    497   TemplateURL* t_url2 = new TemplateURL(test_util_.profile(), data);
    498   model()->Add(t_url2);
    499   VerifyObserverCount(2);
    500   EXPECT_EQ(t_url2, model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
    501   EXPECT_EQ(ASCIIToUTF16("fourth"), t_url2->short_name());
    502   EXPECT_EQ(ASCIIToUTF16("keyword"), t_url2->keyword());
    503   EXPECT_EQ(ASCIIToUTF16("second"), t_url->short_name());
    504   EXPECT_EQ(ASCIIToUTF16("test2"), t_url->keyword());
    505 }
    506 
    507 TEST_F(TemplateURLServiceTest, AddExtensionKeyword) {
    508   test_util_.VerifyLoad();
    509 
    510   TemplateURL* original1 = AddKeywordWithDate(
    511       "replaceable", "keyword1", "http://test1", std::string(), std::string(),
    512       std::string(), true, "UTF-8", Time(), Time());
    513   TemplateURL* original2 = AddKeywordWithDate(
    514       "nonreplaceable", "keyword2", "http://test2", std::string(),
    515       std::string(), std::string(), false, "UTF-8", Time(), Time());
    516   TemplateURL* original3 = AddKeywordWithDate(
    517       "extension", "keyword3",
    518       std::string(extensions::kExtensionScheme) + "://test3", std::string(),
    519       std::string(), std::string(), false, "UTF-8", Time(), Time());
    520 
    521   // Add an extension keyword that conflicts with each of the above three
    522   // keywords.
    523   TemplateURLData data;
    524   data.short_name = ASCIIToUTF16("test");
    525   data.SetKeyword(ASCIIToUTF16("keyword1"));
    526   data.SetURL(std::string(extensions::kExtensionScheme) + "://test4");
    527   data.safe_for_autoreplace = false;
    528 
    529   // Both replaceable and non-replaceable keywords should be uniquified.
    530   TemplateURL* extension1 = new TemplateURL(test_util_.profile(), data);
    531   model()->Add(extension1);
    532   ASSERT_EQ(extension1,
    533             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword1")));
    534   EXPECT_EQ(original1,
    535             model()->GetTemplateURLForKeyword(ASCIIToUTF16("test1")));
    536   data.SetKeyword(ASCIIToUTF16("keyword2"));
    537   TemplateURL* extension2 = new TemplateURL(test_util_.profile(), data);
    538   model()->Add(extension2);
    539   ASSERT_EQ(extension2,
    540             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword2")));
    541   EXPECT_EQ(original2,
    542             model()->GetTemplateURLForKeyword(ASCIIToUTF16("test2")));
    543 
    544   // They should override extension keywords added earlier.
    545   data.SetKeyword(ASCIIToUTF16("keyword3"));
    546   TemplateURL* extension3 = new TemplateURL(test_util_.profile(), data);
    547   model()->Add(extension3);
    548   ASSERT_EQ(extension3,
    549             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3")));
    550   EXPECT_EQ(original3,
    551             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword3_")));
    552 }
    553 
    554 TEST_F(TemplateURLServiceTest, AddSameKeywordWithExtensionPresent) {
    555   test_util_.VerifyLoad();
    556 
    557   // Similar to the AddSameKeyword test, but with an extension keyword masking a
    558   // replaceable TemplateURL.  We should still do correct conflict resolution
    559   // between the non-template URLs.
    560   TemplateURL* extension = AddKeywordWithDate(
    561       "extension", "keyword",
    562       std::string(extensions::kExtensionScheme) + "://test2", std::string(),
    563       std::string(), std::string(), false, "UTF-8", Time(), Time());
    564   // Adding a keyword that matches the extension should cause the extension
    565   // to uniquify.
    566   AddKeywordWithDate(
    567       "replaceable", "keyword", "http://test1", std::string(),  std::string(),
    568       std::string(), true, "UTF-8", Time(), Time());
    569 
    570   // Adding another replaceable keyword should remove the existing one, but
    571   // leave the extension as is.
    572   TemplateURLData data;
    573   data.short_name = ASCIIToUTF16("name1");
    574   data.SetKeyword(ASCIIToUTF16("keyword"));
    575   data.SetURL("http://test3");
    576   data.safe_for_autoreplace = true;
    577   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
    578   model()->Add(t_url);
    579   EXPECT_EQ(extension,
    580             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
    581   EXPECT_TRUE(model()->GetTemplateURLForHost("test1") == NULL);
    582   EXPECT_EQ(t_url, model()->GetTemplateURLForHost("test3"));
    583 
    584   // Adding a nonreplaceable keyword should remove the existing replaceable
    585   // keyword.
    586   data.short_name = ASCIIToUTF16("name2");
    587   data.SetURL("http://test4");
    588   data.safe_for_autoreplace = false;
    589   TemplateURL* t_url2 = new TemplateURL(test_util_.profile(), data);
    590   model()->Add(t_url2);
    591   EXPECT_EQ(t_url2,
    592             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")));
    593   EXPECT_TRUE(model()->GetTemplateURLForHost("test3") == NULL);
    594   EXPECT_EQ(extension,
    595             model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword_")));
    596 }
    597 
    598 TEST_F(TemplateURLServiceTest, GenerateKeyword) {
    599   ASSERT_EQ(ASCIIToUTF16("foo"),
    600             TemplateURLService::GenerateKeyword(GURL("http://foo")));
    601   // www. should be stripped.
    602   ASSERT_EQ(ASCIIToUTF16("foo"),
    603             TemplateURLService::GenerateKeyword(GURL("http://www.foo")));
    604   // Make sure we don't get a trailing '/'.
    605   ASSERT_EQ(ASCIIToUTF16("blah"),
    606             TemplateURLService::GenerateKeyword(GURL("http://blah/")));
    607   // Don't generate the empty string.
    608   ASSERT_EQ(ASCIIToUTF16("www"),
    609             TemplateURLService::GenerateKeyword(GURL("http://www.")));
    610 }
    611 
    612 TEST_F(TemplateURLServiceTest, GenerateSearchURL) {
    613   TestGenerateSearchURL(NULL);
    614 }
    615 
    616 TEST_F(TemplateURLServiceTest, GenerateSearchURLUsingTermsData) {
    617   // Run the test for GenerateSearchURLUsingTermsData on the "IO" thread and
    618   // wait for it to finish.
    619   TestSearchTermsData search_terms_data("http://google.com/");
    620   TestGenerateSearchURL(&search_terms_data);
    621 }
    622 
    623 TEST_F(TemplateURLServiceTest, ClearBrowsingData_Keywords) {
    624   Time now = Time::Now();
    625   TimeDelta one_day = TimeDelta::FromDays(1);
    626   Time month_ago = now - TimeDelta::FromDays(30);
    627 
    628   // Nothing has been added.
    629   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
    630 
    631   // Create one with a 0 time.
    632   AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
    633                      std::string(), "http://icon1", true, "UTF-8;UTF-16",
    634                      Time(), Time());
    635   // Create one for now and +/- 1 day.
    636   AddKeywordWithDate("name2", "key2", "http://foo2", "http://suggest2",
    637                      std::string(),  "http://icon2", true, "UTF-8;UTF-16",
    638                      now - one_day, Time());
    639   AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
    640                      std::string(), std::string(), true, std::string(), now,
    641                      Time());
    642   AddKeywordWithDate("name4", "key4", "http://foo4", std::string(),
    643                      std::string(), std::string(), true, std::string(),
    644                      now + one_day, Time());
    645   // Try the other three states.
    646   AddKeywordWithDate("name5", "key5", "http://foo5", "http://suggest5",
    647                      std::string(), "http://icon5", false, "UTF-8;UTF-16", now,
    648                      Time());
    649   AddKeywordWithDate("name6", "key6", "http://foo6", "http://suggest6",
    650                      std::string(), "http://icon6", false, "UTF-8;UTF-16",
    651                      month_ago, Time());
    652 
    653   // We just added a few items, validate them.
    654   EXPECT_EQ(6U, model()->GetTemplateURLs().size());
    655 
    656   // Try removing from current timestamp. This should delete the one in the
    657   // future and one very recent one.
    658   model()->RemoveAutoGeneratedSince(now);
    659   EXPECT_EQ(4U, model()->GetTemplateURLs().size());
    660 
    661   // Try removing from two months ago. This should only delete items that are
    662   // auto-generated.
    663   model()->RemoveAutoGeneratedBetween(now - TimeDelta::FromDays(60), now);
    664   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
    665 
    666   // Make sure the right values remain.
    667   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
    668   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
    669   EXPECT_EQ(0U,
    670             model()->GetTemplateURLs()[0]->date_created().ToInternalValue());
    671 
    672   EXPECT_EQ(ASCIIToUTF16("key5"), model()->GetTemplateURLs()[1]->keyword());
    673   EXPECT_FALSE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
    674   EXPECT_EQ(now.ToInternalValue(),
    675             model()->GetTemplateURLs()[1]->date_created().ToInternalValue());
    676 
    677   EXPECT_EQ(ASCIIToUTF16("key6"), model()->GetTemplateURLs()[2]->keyword());
    678   EXPECT_FALSE(model()->GetTemplateURLs()[2]->safe_for_autoreplace());
    679   EXPECT_EQ(month_ago.ToInternalValue(),
    680             model()->GetTemplateURLs()[2]->date_created().ToInternalValue());
    681 
    682   // Try removing from Time=0. This should delete one more.
    683   model()->RemoveAutoGeneratedSince(Time());
    684   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
    685 }
    686 
    687 TEST_F(TemplateURLServiceTest, ClearBrowsingData_KeywordsForOrigin) {
    688   Time now = Time::Now();
    689   TimeDelta one_day = TimeDelta::FromDays(1);
    690   Time month_ago = now - TimeDelta::FromDays(30);
    691 
    692   // Nothing has been added.
    693   EXPECT_EQ(0U, model()->GetTemplateURLs().size());
    694 
    695   // Create one for now and +/- 1 day.
    696   AddKeywordWithDate("name1", "key1", "http://foo1", "http://suggest1",
    697                      std::string(), "http://icon2", true, "UTF-8;UTF-16",
    698                      now - one_day, Time());
    699   AddKeywordWithDate("name2", "key2", "http://foo2", std::string(),
    700                      std::string(), std::string(), true, std::string(), now,
    701                      Time());
    702   AddKeywordWithDate("name3", "key3", "http://foo3", std::string(),
    703                      std::string(), std::string(), true, std::string(),
    704                      now + one_day, Time());
    705 
    706   // We just added a few items, validate them.
    707   EXPECT_EQ(3U, model()->GetTemplateURLs().size());
    708 
    709   // Try removing foo2. This should delete foo2, but leave foo1 and 3 untouched.
    710   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo2"), month_ago,
    711       now + one_day);
    712   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
    713   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
    714   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
    715   EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
    716   EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
    717 
    718   // Try removing foo1, but outside the range in which it was modified. It
    719   // should remain untouched.
    720   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo1"), now,
    721       now + one_day);
    722   EXPECT_EQ(2U, model()->GetTemplateURLs().size());
    723   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
    724   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
    725   EXPECT_EQ(ASCIIToUTF16("key3"), model()->GetTemplateURLs()[1]->keyword());
    726   EXPECT_TRUE(model()->GetTemplateURLs()[1]->safe_for_autoreplace());
    727 
    728 
    729   // Try removing foo3. This should delete foo3, but leave foo1 untouched.
    730   model()->RemoveAutoGeneratedForOriginBetween(GURL("http://foo3"), month_ago,
    731       now + one_day + one_day);
    732   EXPECT_EQ(1U, model()->GetTemplateURLs().size());
    733   EXPECT_EQ(ASCIIToUTF16("key1"), model()->GetTemplateURLs()[0]->keyword());
    734   EXPECT_TRUE(model()->GetTemplateURLs()[0]->safe_for_autoreplace());
    735 }
    736 
    737 TEST_F(TemplateURLServiceTest, Reset) {
    738   // Add a new TemplateURL.
    739   test_util_.VerifyLoad();
    740   const size_t initial_count = model()->GetTemplateURLs().size();
    741   TemplateURLData data;
    742   data.short_name = ASCIIToUTF16("google");
    743   data.SetKeyword(ASCIIToUTF16("keyword"));
    744   data.SetURL("http://www.google.com/foo/bar");
    745   data.favicon_url = GURL("http://favicon.url");
    746   data.date_created = Time::FromTimeT(100);
    747   data.last_modified = Time::FromTimeT(100);
    748   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
    749   model()->Add(t_url);
    750 
    751   VerifyObserverCount(1);
    752   base::RunLoop().RunUntilIdle();
    753 
    754   StrictMock<base::MockTimeProvider> mock_time;
    755   model()->set_time_provider(&base::MockTimeProvider::StaticNow);
    756   EXPECT_CALL(mock_time, Now()).WillOnce(Return(base::Time::FromDoubleT(1337)));
    757 
    758   // Reset the short name, keyword, url and make sure it takes.
    759   const base::string16 new_short_name(ASCIIToUTF16("a"));
    760   const base::string16 new_keyword(ASCIIToUTF16("b"));
    761   const std::string new_url("c");
    762   model()->ResetTemplateURL(t_url, new_short_name, new_keyword, new_url);
    763   ASSERT_EQ(new_short_name, t_url->short_name());
    764   ASSERT_EQ(new_keyword, t_url->keyword());
    765   ASSERT_EQ(new_url, t_url->url());
    766 
    767   // Make sure the mappings in the model were updated.
    768   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(new_keyword));
    769   ASSERT_TRUE(
    770       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword")) == NULL);
    771 
    772   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
    773                                                      t_url->data()));
    774 
    775   // Reload the model from the database and make sure the change took.
    776   test_util_.ResetModel(true);
    777   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
    778   const TemplateURL* read_url = model()->GetTemplateURLForKeyword(new_keyword);
    779   ASSERT_TRUE(read_url);
    780   AssertEquals(*cloned_url, *read_url);
    781   ASSERT_EQ(base::Time::FromDoubleT(1337), read_url->last_modified());
    782 }
    783 
    784 TEST_F(TemplateURLServiceTest, DefaultSearchProvider) {
    785   // Add a new TemplateURL.
    786   test_util_.VerifyLoad();
    787   const size_t initial_count = model()->GetTemplateURLs().size();
    788   TemplateURL* t_url = AddKeywordWithDate(
    789       "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
    790       std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
    791   test_util_.ResetObserverCount();
    792 
    793   model()->SetDefaultSearchProvider(t_url);
    794   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
    795   ASSERT_TRUE(t_url->safe_for_autoreplace());
    796   ASSERT_TRUE(t_url->show_in_default_list());
    797 
    798   // Setting the default search provider should have caused notification.
    799   VerifyObserverCount(1);
    800   base::RunLoop().RunUntilIdle();
    801 
    802   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
    803                                                      t_url->data()));
    804 
    805   // Make sure when we reload we get a default search provider.
    806   test_util_.ResetModel(true);
    807   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
    808   ASSERT_TRUE(model()->GetDefaultSearchProvider());
    809   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
    810 }
    811 
    812 TEST_F(TemplateURLServiceTest, CantReplaceWithSameKeyword) {
    813   test_util_.ChangeModelToLoadState();
    814   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"), GURL(), NULL));
    815   TemplateURL* t_url = AddKeywordWithDate(
    816       "name1", "foo", "http://foo1", "http://sugg1", std::string(),
    817       "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
    818 
    819   // Can still replace, newly added template url is marked safe to replace.
    820   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
    821                                          GURL("http://foo2"), NULL));
    822 
    823   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
    824   // no longer be replaceable.
    825   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
    826                             t_url->url());
    827 
    828   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
    829                                           GURL("http://foo2"), NULL));
    830 }
    831 
    832 TEST_F(TemplateURLServiceTest, CantReplaceWithSameHosts) {
    833   test_util_.ChangeModelToLoadState();
    834   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("foo"),
    835                                          GURL("http://foo.com"), NULL));
    836   TemplateURL* t_url = AddKeywordWithDate(
    837       "name1", "foo", "http://foo.com", "http://sugg1", std::string(),
    838       "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
    839 
    840   // Can still replace, newly added template url is marked safe to replace.
    841   ASSERT_TRUE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
    842                                          GURL("http://foo.com"), NULL));
    843 
    844   // ResetTemplateURL marks the TemplateURL as unsafe to replace, so it should
    845   // no longer be replaceable.
    846   model()->ResetTemplateURL(t_url, t_url->short_name(), t_url->keyword(),
    847                             t_url->url());
    848 
    849   ASSERT_FALSE(model()->CanReplaceKeyword(ASCIIToUTF16("bar"),
    850                                           GURL("http://foo.com"), NULL));
    851 }
    852 
    853 TEST_F(TemplateURLServiceTest, HasDefaultSearchProvider) {
    854   // We should have a default search provider even if we haven't loaded.
    855   ASSERT_TRUE(model()->GetDefaultSearchProvider());
    856 
    857   // Now force the model to load and make sure we still have a default.
    858   test_util_.VerifyLoad();
    859 
    860   ASSERT_TRUE(model()->GetDefaultSearchProvider());
    861 }
    862 
    863 TEST_F(TemplateURLServiceTest, DefaultSearchProviderLoadedFromPrefs) {
    864   test_util_.VerifyLoad();
    865 
    866   TemplateURLData data;
    867   data.short_name = ASCIIToUTF16("a");
    868   data.safe_for_autoreplace = true;
    869   data.SetURL("http://url/{searchTerms}");
    870   data.suggestions_url = "http://url2";
    871   data.instant_url = "http://instant";
    872   data.date_created = Time::FromTimeT(100);
    873   data.last_modified = Time::FromTimeT(100);
    874   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
    875   model()->Add(t_url);
    876   const TemplateURLID id = t_url->id();
    877 
    878   model()->SetDefaultSearchProvider(t_url);
    879   base::RunLoop().RunUntilIdle();
    880   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
    881                                                      t_url->data()));
    882 
    883   // Reset the model and don't load it. The template url we set as the default
    884   // should be pulled from prefs now.
    885   test_util_.ResetModel(false);
    886 
    887   // NOTE: This doesn't use AssertEquals as only a subset of the TemplateURLs
    888   // value are persisted to prefs.
    889   const TemplateURL* default_turl = model()->GetDefaultSearchProvider();
    890   ASSERT_TRUE(default_turl);
    891   EXPECT_EQ(ASCIIToUTF16("a"), default_turl->short_name());
    892   EXPECT_EQ("http://url/{searchTerms}", default_turl->url());
    893   EXPECT_EQ("http://url2", default_turl->suggestions_url());
    894   EXPECT_EQ("http://instant", default_turl->instant_url());
    895   EXPECT_EQ(id, default_turl->id());
    896 
    897   // Now do a load and make sure the default search provider really takes.
    898   test_util_.VerifyLoad();
    899 
    900   ASSERT_TRUE(model()->GetDefaultSearchProvider());
    901   AssertEquals(*cloned_url, *model()->GetDefaultSearchProvider());
    902 }
    903 
    904 TEST_F(TemplateURLServiceTest, RepairPrepopulatedSearchEngines) {
    905   test_util_.VerifyLoad();
    906 
    907   // Edit Google search engine.
    908   TemplateURL* google = model()->GetTemplateURLForKeyword(
    909       ASCIIToUTF16("google.com"));
    910   ASSERT_TRUE(google);
    911   model()->ResetTemplateURL(google, ASCIIToUTF16("trash"), ASCIIToUTF16("xxx"),
    912                             "http://www.foo.com/s?q={searchTerms}");
    913   EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
    914   EXPECT_EQ(ASCIIToUTF16("xxx"), google->keyword());
    915 
    916   // Add third-party default search engine.
    917   TemplateURL* user_dse = AddKeywordWithDate(
    918       "malware", "google.com", "http://www.goo.com/s?q={searchTerms}",
    919       std::string(), std::string(), std::string(),
    920       true, "UTF-8", Time(), Time());
    921   model()->SetDefaultSearchProvider(user_dse);
    922   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
    923 
    924   // Remove bing.
    925   TemplateURL* bing = model()->GetTemplateURLForKeyword(
    926       ASCIIToUTF16("bing.com"));
    927   ASSERT_TRUE(bing);
    928   model()->Remove(bing);
    929   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
    930 
    931   // Register an extension with bing keyword.
    932   model()->RegisterOmniboxKeyword("abcdefg", "extension_name", "bing.com");
    933   EXPECT_TRUE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com")));
    934 
    935   model()->RepairPrepopulatedSearchEngines();
    936 
    937   // Google is default.
    938   ASSERT_EQ(google, model()->GetDefaultSearchProvider());
    939   // The keyword wasn't reverted.
    940   EXPECT_EQ(ASCIIToUTF16("trash"), google->short_name());
    941   EXPECT_EQ("www.google.com",
    942             TemplateURLService::GenerateSearchURL(google).host());
    943 
    944   // Bing was repaired.
    945   bing = model()->GetTemplateURLForKeyword(ASCIIToUTF16("bing.com"));
    946   ASSERT_TRUE(bing);
    947   EXPECT_EQ(TemplateURL::NORMAL, bing->GetType());
    948 
    949   // User search engine is preserved.
    950   EXPECT_EQ(user_dse, model()->GetTemplateURLForHost("www.goo.com"));
    951   EXPECT_EQ(ASCIIToUTF16("google.com"), user_dse->keyword());
    952 }
    953 
    954 TEST_F(TemplateURLServiceTest, RepairSearchEnginesWithManagedDefault) {
    955   // Set a managed preference that establishes a default search provider.
    956   const char kName[] = "test1";
    957   const char kKeyword[] = "test.com";
    958   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
    959   const char kIconURL[] = "http://test.com/icon.jpg";
    960   const char kEncodings[] = "UTF-16;UTF-32";
    961   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
    962   const char kSearchTermsReplacementKey[] = "espv";
    963   test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword,
    964                                                 kSearchURL, std::string(),
    965                                                 kIconURL, kEncodings,
    966                                                 kAlternateURL,
    967                                                 kSearchTermsReplacementKey);
    968   test_util_.VerifyLoad();
    969   // Verify that the default manager we are getting is the managed one.
    970   TemplateURLData data;
    971   data.short_name = ASCIIToUTF16(kName);
    972   data.SetKeyword(ASCIIToUTF16(kKeyword));
    973   data.SetURL(kSearchURL);
    974   data.favicon_url = GURL(kIconURL);
    975   data.show_in_default_list = true;
    976   base::SplitString(kEncodings, ';', &data.input_encodings);
    977   data.alternate_urls.push_back(kAlternateURL);
    978   data.search_terms_replacement_key = kSearchTermsReplacementKey;
    979   scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(
    980       test_util_.profile(), data));
    981   EXPECT_TRUE(model()->is_default_search_managed());
    982   const TemplateURL* actual_managed_default =
    983       model()->GetDefaultSearchProvider();
    984   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
    985 
    986   // The following call has no effect on the managed search engine.
    987   model()->RepairPrepopulatedSearchEngines();
    988 
    989   EXPECT_TRUE(model()->is_default_search_managed());
    990   actual_managed_default = model()->GetDefaultSearchProvider();
    991   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
    992 }
    993 
    994 TEST_F(TemplateURLServiceTest, UpdateKeywordSearchTermsForURL) {
    995   struct TestData {
    996     const std::string url;
    997     const base::string16 term;
    998   } data[] = {
    999     { "http://foo/", base::string16() },
   1000     { "http://foo/foo?q=xx", base::string16() },
   1001     { "http://x/bar?q=xx", base::string16() },
   1002     { "http://x/foo?y=xx", base::string16() },
   1003     { "http://x/foo?q=xx", ASCIIToUTF16("xx") },
   1004     { "http://x/foo?a=b&q=xx", ASCIIToUTF16("xx") },
   1005     { "http://x/foo?q=b&q=xx", base::string16() },
   1006     { "http://x/foo#query=xx", ASCIIToUTF16("xx") },
   1007     { "http://x/foo?q=b#query=xx", ASCIIToUTF16("xx") },
   1008     { "http://x/foo?q=b#q=xx", ASCIIToUTF16("b") },
   1009     { "http://x/foo?query=b#q=xx", base::string16() },
   1010   };
   1011 
   1012   test_util_.ChangeModelToLoadState();
   1013   AddKeywordWithDate("name", "x", "http://x/foo?q={searchTerms}",
   1014                      "http://sugg1", "http://x/foo#query={searchTerms}",
   1015                      "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
   1016 
   1017   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
   1018     history::URLVisitedDetails details;
   1019     details.row = history::URLRow(GURL(data[i].url));
   1020     details.transition = content::PageTransitionFromInt(0);
   1021     model()->UpdateKeywordSearchTermsForURL(details);
   1022     EXPECT_EQ(data[i].term, test_util_.GetAndClearSearchTerm());
   1023   }
   1024 }
   1025 
   1026 TEST_F(TemplateURLServiceTest, DontUpdateKeywordSearchForNonReplaceable) {
   1027   struct TestData {
   1028     const std::string url;
   1029   } data[] = {
   1030     { "http://foo/" },
   1031     { "http://x/bar?q=xx" },
   1032     { "http://x/foo?y=xx" },
   1033   };
   1034 
   1035   test_util_.ChangeModelToLoadState();
   1036   AddKeywordWithDate("name", "x", "http://x/foo", "http://sugg1", std::string(),
   1037                      "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
   1038 
   1039   for (size_t i = 0; i < ARRAYSIZE_UNSAFE(data); ++i) {
   1040     history::URLVisitedDetails details;
   1041     details.row = history::URLRow(GURL(data[i].url));
   1042     details.transition = content::PageTransitionFromInt(0);
   1043     model()->UpdateKeywordSearchTermsForURL(details);
   1044     ASSERT_EQ(base::string16(), test_util_.GetAndClearSearchTerm());
   1045   }
   1046 }
   1047 
   1048 TEST_F(TemplateURLServiceTest, ChangeGoogleBaseValue) {
   1049   // NOTE: Do not do a VerifyLoad() here as it will load the prepopulate data,
   1050   // which also has a {google:baseURL} keyword in it, which will confuse this
   1051   // test.
   1052   test_util_.ChangeModelToLoadState();
   1053   test_util_.SetGoogleBaseURL(GURL("http://google.com/"));
   1054   const TemplateURL* t_url = AddKeywordWithDate(
   1055       "name", "google.com", "{google:baseURL}?q={searchTerms}", "http://sugg1",
   1056       std::string(), "http://icon1", false, "UTF-8;UTF-16", Time(), Time());
   1057   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.com"));
   1058   EXPECT_EQ("google.com", t_url->url_ref().GetHost());
   1059   EXPECT_EQ(ASCIIToUTF16("google.com"), t_url->keyword());
   1060 
   1061   // Change the Google base url.
   1062   test_util_.ResetObserverCount();
   1063   test_util_.SetGoogleBaseURL(GURL("http://google.co.uk/"));
   1064   VerifyObserverCount(1);
   1065 
   1066   // Make sure the host->TemplateURL map was updated appropriately.
   1067   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.co.uk"));
   1068   EXPECT_TRUE(model()->GetTemplateURLForHost("google.com") == NULL);
   1069   EXPECT_EQ("google.co.uk", t_url->url_ref().GetHost());
   1070   EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
   1071   EXPECT_EQ("http://google.co.uk/?q=x", t_url->url_ref().ReplaceSearchTerms(
   1072       TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("x"))));
   1073 
   1074   // Now add a manual entry and then change the Google base URL such that the
   1075   // autogenerated Google search keyword would conflict.
   1076   TemplateURL* manual = AddKeywordWithDate(
   1077     "manual", "google.de", "http://google.de/search?q={searchTerms}",
   1078     std::string(), std::string(), std::string(), false, "UTF-8", Time(),
   1079     Time());
   1080   test_util_.SetGoogleBaseURL(GURL("http://google.de"));
   1081 
   1082   // Verify that the manual entry is untouched, and the autogenerated keyword
   1083   // has not changed.
   1084   ASSERT_EQ(manual,
   1085             model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.de")));
   1086   EXPECT_EQ("google.de", manual->url_ref().GetHost());
   1087   ASSERT_EQ(t_url,
   1088             model()->GetTemplateURLForKeyword(ASCIIToUTF16("google.co.uk")));
   1089   EXPECT_EQ("google.de", t_url->url_ref().GetHost());
   1090   EXPECT_EQ(ASCIIToUTF16("google.co.uk"), t_url->keyword());
   1091 
   1092   // Change the base URL again and verify that the autogenerated keyword follows
   1093   // even though it didn't match the base URL, while the manual entry is still
   1094   // untouched.
   1095   test_util_.SetGoogleBaseURL(GURL("http://google.fr/"));
   1096   ASSERT_EQ(manual, model()->GetTemplateURLForHost("google.de"));
   1097   EXPECT_EQ("google.de", manual->url_ref().GetHost());
   1098   EXPECT_EQ(ASCIIToUTF16("google.de"), manual->keyword());
   1099   ASSERT_EQ(t_url, model()->GetTemplateURLForHost("google.fr"));
   1100   EXPECT_TRUE(model()->GetTemplateURLForHost("google.co.uk") == NULL);
   1101   EXPECT_EQ("google.fr", t_url->url_ref().GetHost());
   1102   EXPECT_EQ(ASCIIToUTF16("google.fr"), t_url->keyword());
   1103 }
   1104 
   1105 // Make sure TemplateURLService generates a KEYWORD_GENERATED visit for
   1106 // KEYWORD visits.
   1107 TEST_F(TemplateURLServiceTest, GenerateVisitOnKeyword) {
   1108   test_util_.VerifyLoad();
   1109   ASSERT_TRUE(test_util_.profile()->CreateHistoryService(true, false));
   1110 
   1111   // Create a keyword.
   1112   TemplateURL* t_url = AddKeywordWithDate(
   1113       "keyword", "keyword", "http://foo.com/foo?query={searchTerms}",
   1114       "http://sugg1", std::string(), "http://icon1", true, "UTF-8;UTF-16",
   1115       base::Time::Now(), base::Time::Now());
   1116 
   1117   // Add a visit that matches the url of the keyword.
   1118   HistoryService* history =
   1119       HistoryServiceFactory::GetForProfile(test_util_.profile(),
   1120                                            Profile::EXPLICIT_ACCESS);
   1121   history->AddPage(
   1122       GURL(t_url->url_ref().ReplaceSearchTerms(
   1123           TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("blah")))),
   1124       base::Time::Now(), NULL, 0, GURL(), history::RedirectList(),
   1125       content::PAGE_TRANSITION_KEYWORD, history::SOURCE_BROWSED, false);
   1126 
   1127   // Wait for history to finish processing the request.
   1128   test_util_.profile()->BlockUntilHistoryProcessesPendingRequests();
   1129 
   1130   // Query history for the generated url.
   1131   CancelableRequestConsumer consumer;
   1132   QueryHistoryCallbackImpl callback;
   1133   history->QueryURL(GURL("http://keyword"), true, &consumer,
   1134       base::Bind(&QueryHistoryCallbackImpl::Callback,
   1135                  base::Unretained(&callback)));
   1136 
   1137   // Wait for the request to be processed.
   1138   test_util_.profile()->BlockUntilHistoryProcessesPendingRequests();
   1139 
   1140   // And make sure the url and visit were added.
   1141   EXPECT_TRUE(callback.success);
   1142   EXPECT_NE(0, callback.row.id());
   1143   ASSERT_EQ(1U, callback.visits.size());
   1144   EXPECT_EQ(content::PAGE_TRANSITION_KEYWORD_GENERATED,
   1145       content::PageTransitionStripQualifier(callback.visits[0].transition));
   1146 }
   1147 
   1148 // Make sure that the load routine deletes prepopulated engines that no longer
   1149 // exist in the prepopulate data.
   1150 TEST_F(TemplateURLServiceTest, LoadDeletesUnusedProvider) {
   1151   // Create a preloaded template url. Add it to a loaded model and wait for the
   1152   // saves to finish.
   1153   TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
   1154   test_util_.ChangeModelToLoadState();
   1155   model()->Add(t_url);
   1156   ASSERT_TRUE(
   1157       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
   1158   base::RunLoop().RunUntilIdle();
   1159 
   1160   // Ensure that merging clears this engine.
   1161   test_util_.ResetModel(true);
   1162   ASSERT_TRUE(
   1163       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
   1164 
   1165   // Wait for any saves to finish.
   1166   base::RunLoop().RunUntilIdle();
   1167 
   1168   // Reload the model to verify that the database was updated as a result of the
   1169   // merge.
   1170   test_util_.ResetModel(true);
   1171   ASSERT_TRUE(
   1172       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) == NULL);
   1173 }
   1174 
   1175 // Make sure that load routine doesn't delete prepopulated engines that no
   1176 // longer exist in the prepopulate data if it has been modified by the user.
   1177 TEST_F(TemplateURLServiceTest, LoadRetainsModifiedProvider) {
   1178   // Create a preloaded template url and add it to a loaded model.
   1179   TemplateURL* t_url = CreatePreloadedTemplateURL(false, 999999);
   1180   test_util_.ChangeModelToLoadState();
   1181   model()->Add(t_url);
   1182 
   1183   // Do the copy after t_url is added so that the id is set.
   1184   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
   1185                                                      t_url->data()));
   1186   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
   1187 
   1188   // Wait for any saves to finish.
   1189   base::RunLoop().RunUntilIdle();
   1190 
   1191   // Ensure that merging won't clear it if the user has edited it.
   1192   test_util_.ResetModel(true);
   1193   const TemplateURL* url_for_unittest =
   1194       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   1195   ASSERT_TRUE(url_for_unittest != NULL);
   1196   AssertEquals(*cloned_url, *url_for_unittest);
   1197 
   1198   // Wait for any saves to finish.
   1199   base::RunLoop().RunUntilIdle();
   1200 
   1201   // Reload the model to verify that save/reload retains the item.
   1202   test_util_.ResetModel(true);
   1203   ASSERT_TRUE(
   1204       model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")) != NULL);
   1205 }
   1206 
   1207 // Make sure that load routine doesn't delete
   1208 // prepopulated engines that no longer exist in the prepopulate data if
   1209 // it has been modified by the user.
   1210 TEST_F(TemplateURLServiceTest, LoadSavesPrepopulatedDefaultSearchProvider) {
   1211   test_util_.VerifyLoad();
   1212   // Verify that the default search provider is set to something.
   1213   TemplateURL* default_search = model()->GetDefaultSearchProvider();
   1214   ASSERT_TRUE(default_search != NULL);
   1215   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(default_search->profile(),
   1216                                                      default_search->data()));
   1217 
   1218   // Wait for any saves to finish.
   1219   base::RunLoop().RunUntilIdle();
   1220 
   1221   // Reload the model and check that the default search provider
   1222   // was properly saved.
   1223   test_util_.ResetModel(true);
   1224   default_search = model()->GetDefaultSearchProvider();
   1225   ASSERT_TRUE(default_search != NULL);
   1226   AssertEquals(*cloned_url, *default_search);
   1227 }
   1228 
   1229 TEST_F(TemplateURLServiceTest, FindNewDefaultSearchProvider) {
   1230   // Ensure that if our service is initially empty, we don't initial have a
   1231   // valid new DSP.
   1232   EXPECT_FALSE(model()->FindNewDefaultSearchProvider());
   1233 
   1234   // Add a few entries with searchTerms, but ensure only the last one is in the
   1235   // default list.
   1236   AddKeywordWithDate("name1", "key1", "http://foo1/{searchTerms}",
   1237                      "http://sugg1", std::string(), "http://icon1", true,
   1238                      "UTF-8;UTF-16", Time(), Time());
   1239   AddKeywordWithDate("name2", "key2", "http://foo2/{searchTerms}",
   1240                      "http://sugg2", std::string(), "http://icon1", true,
   1241                      "UTF-8;UTF-16", Time(), Time());
   1242   AddKeywordWithDate("name3", "key3", "http://foo1/{searchTerms}",
   1243                      "http://sugg3", std::string(), "http://icon3", true,
   1244                      "UTF-8;UTF-16", Time(), Time());
   1245   TemplateURLData data;
   1246   data.short_name = ASCIIToUTF16("valid");
   1247   data.SetKeyword(ASCIIToUTF16("validkeyword"));
   1248   data.SetURL("http://valid/{searchTerms}");
   1249   data.favicon_url = GURL("http://validicon");
   1250   data.show_in_default_list = true;
   1251   TemplateURL* valid_turl(new TemplateURL(test_util_.profile(), data));
   1252   model()->Add(valid_turl);
   1253   EXPECT_EQ(4U, model()->GetTemplateURLs().size());
   1254 
   1255   // Request a new DSP from the service and only expect the valid one.
   1256   TemplateURL* new_default = model()->FindNewDefaultSearchProvider();
   1257   ASSERT_TRUE(new_default);
   1258   EXPECT_EQ(valid_turl, new_default);
   1259 
   1260   // Remove the default we received and ensure that the service returns NULL.
   1261   model()->Remove(new_default);
   1262   EXPECT_FALSE(model()->FindNewDefaultSearchProvider());
   1263 }
   1264 
   1265 // Make sure that the load routine doesn't delete
   1266 // prepopulated engines that no longer exist in the prepopulate data if
   1267 // it is the default search provider.
   1268 TEST_F(TemplateURLServiceTest, LoadRetainsDefaultProvider) {
   1269   // Set the default search provider to a preloaded template url which
   1270   // is not in the current set of preloaded template urls and save
   1271   // the result.
   1272   TemplateURL* t_url = CreatePreloadedTemplateURL(true, 999999);
   1273   test_util_.ChangeModelToLoadState();
   1274   model()->Add(t_url);
   1275   model()->SetDefaultSearchProvider(t_url);
   1276   // Do the copy after t_url is added and set as default so that its
   1277   // internal state is correct.
   1278   scoped_ptr<TemplateURL> cloned_url(new TemplateURL(t_url->profile(),
   1279                                                      t_url->data()));
   1280 
   1281   ASSERT_EQ(t_url, model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest")));
   1282   ASSERT_EQ(t_url, model()->GetDefaultSearchProvider());
   1283   base::RunLoop().RunUntilIdle();
   1284 
   1285   // Ensure that merging won't clear the prepopulated template url
   1286   // which is no longer present if it's the default engine.
   1287   test_util_.ResetModel(true);
   1288   {
   1289     const TemplateURL* keyword_url =
   1290         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   1291     ASSERT_TRUE(keyword_url != NULL);
   1292     AssertEquals(*cloned_url, *keyword_url);
   1293     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
   1294   }
   1295 
   1296   // Wait for any saves to finish.
   1297   base::RunLoop().RunUntilIdle();
   1298 
   1299   // Reload the model to verify that the update was saved.
   1300   test_util_.ResetModel(true);
   1301   {
   1302     const TemplateURL* keyword_url =
   1303         model()->GetTemplateURLForKeyword(ASCIIToUTF16("unittest"));
   1304     ASSERT_TRUE(keyword_url != NULL);
   1305     AssertEquals(*cloned_url, *keyword_url);
   1306     ASSERT_EQ(keyword_url, model()->GetDefaultSearchProvider());
   1307   }
   1308 }
   1309 
   1310 // Make sure that the load routine updates the url of a preexisting
   1311 // default search engine provider and that the result is saved correctly.
   1312 TEST_F(TemplateURLServiceTest, LoadUpdatesDefaultSearchURL) {
   1313   TestLoadUpdatingPreloadedURL(0);
   1314 }
   1315 
   1316 // Make sure that the load routine updates the url of a preexisting
   1317 // non-default search engine provider and that the result is saved correctly.
   1318 TEST_F(TemplateURLServiceTest, LoadUpdatesSearchURL) {
   1319   TestLoadUpdatingPreloadedURL(1);
   1320 }
   1321 
   1322 // Make sure that the load routine sets a default search provider if it was
   1323 // missing and not managed.
   1324 TEST_F(TemplateURLServiceTest, LoadEnsuresDefaultSearchProviderExists) {
   1325   // Force the model to load and make sure we have a default search provider.
   1326   test_util_.VerifyLoad();
   1327   TemplateURL* old_default = model()->GetDefaultSearchProvider();
   1328   EXPECT_TRUE(old_default);
   1329 
   1330   // Now remove it.
   1331   model()->SetDefaultSearchProvider(NULL);
   1332   model()->Remove(old_default);
   1333   base::RunLoop().RunUntilIdle();
   1334 
   1335   EXPECT_FALSE(model()->GetDefaultSearchProvider());
   1336 
   1337   // Reset the model and load it. There should be a default search provider.
   1338   test_util_.ResetModel(true);
   1339 
   1340   ASSERT_TRUE(model()->GetDefaultSearchProvider());
   1341   EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement());
   1342 
   1343   // Make default search provider unusable (no search terms).
   1344   model()->ResetTemplateURL(model()->GetDefaultSearchProvider(),
   1345                             ASCIIToUTF16("test"), ASCIIToUTF16("test"),
   1346                             "http://example.com/");
   1347   base::RunLoop().RunUntilIdle();
   1348 
   1349   // Reset the model and load it. There should be a usable default search
   1350   // provider.
   1351   test_util_.ResetModel(true);
   1352 
   1353   ASSERT_TRUE(model()->GetDefaultSearchProvider());
   1354   EXPECT_TRUE(model()->GetDefaultSearchProvider()->SupportsReplacement());
   1355 }
   1356 
   1357 // Simulates failing to load the webdb and makes sure the default search
   1358 // provider is valid.
   1359 TEST_F(TemplateURLServiceTest, FailedInit) {
   1360   test_util_.VerifyLoad();
   1361 
   1362   test_util_.ClearModel();
   1363   scoped_refptr<WebDataService> web_service =
   1364       WebDataService::FromBrowserContext(test_util_.profile());
   1365   web_service->ShutdownDatabase();
   1366 
   1367   test_util_.ResetModel(false);
   1368   model()->Load();
   1369   base::RunLoop().RunUntilIdle();
   1370 
   1371   ASSERT_TRUE(model()->GetDefaultSearchProvider());
   1372 }
   1373 
   1374 // Verifies that if the default search URL preference is managed, we report
   1375 // the default search as managed.  Also check that we are getting the right
   1376 // values.
   1377 TEST_F(TemplateURLServiceTest, TestManagedDefaultSearch) {
   1378   test_util_.VerifyLoad();
   1379   const size_t initial_count = model()->GetTemplateURLs().size();
   1380   test_util_.ResetObserverCount();
   1381 
   1382   // Set a regular default search provider.
   1383   TemplateURL* regular_default = AddKeywordWithDate(
   1384       "name1", "key1", "http://foo1/{searchTerms}", "http://sugg1",
   1385       std::string(), "http://icon1", true, "UTF-8;UTF-16", Time(), Time());
   1386   VerifyObserverCount(1);
   1387   model()->SetDefaultSearchProvider(regular_default);
   1388   // Adding the URL and setting the default search provider should have caused
   1389   // notifications.
   1390   VerifyObserverCount(1);
   1391   EXPECT_FALSE(model()->is_default_search_managed());
   1392   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1393 
   1394   // Set a managed preference that establishes a default search provider.
   1395   const char kName[] = "test1";
   1396   const char kKeyword[] = "test.com";
   1397   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
   1398   const char kIconURL[] = "http://test.com/icon.jpg";
   1399   const char kEncodings[] = "UTF-16;UTF-32";
   1400   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
   1401   const char kSearchTermsReplacementKey[] = "espv";
   1402   test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword,
   1403       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
   1404       kSearchTermsReplacementKey);
   1405   VerifyObserverFired();
   1406   EXPECT_TRUE(model()->is_default_search_managed());
   1407   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
   1408 
   1409   // Verify that the default manager we are getting is the managed one.
   1410   TemplateURLData data;
   1411   data.short_name = ASCIIToUTF16(kName);
   1412   data.SetKeyword(ASCIIToUTF16(kKeyword));
   1413   data.SetURL(kSearchURL);
   1414   data.favicon_url = GURL(kIconURL);
   1415   data.show_in_default_list = true;
   1416   base::SplitString(kEncodings, ';', &data.input_encodings);
   1417   data.alternate_urls.push_back(kAlternateURL);
   1418   data.search_terms_replacement_key = kSearchTermsReplacementKey;
   1419   Profile* profile = test_util_.profile();
   1420   scoped_ptr<TemplateURL> expected_managed_default1(new TemplateURL(profile,
   1421                                                                     data));
   1422   const TemplateURL* actual_managed_default =
   1423       model()->GetDefaultSearchProvider();
   1424   ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
   1425   EXPECT_TRUE(actual_managed_default->show_in_default_list());
   1426 
   1427   // Update the managed preference and check that the model has changed.
   1428   const char kNewName[] = "test2";
   1429   const char kNewKeyword[] = "other.com";
   1430   const char kNewSearchURL[] = "http://other.com/search?t={searchTerms}";
   1431   const char kNewSuggestURL[] = "http://other.com/suggest?t={searchTerms}";
   1432   test_util_.SetManagedDefaultSearchPreferences(true, kNewName, kNewKeyword,
   1433       kNewSearchURL, kNewSuggestURL, std::string(), std::string(),
   1434       std::string(), std::string());
   1435   VerifyObserverFired();
   1436   EXPECT_TRUE(model()->is_default_search_managed());
   1437   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
   1438 
   1439   // Verify that the default manager we are now getting is the correct one.
   1440   TemplateURLData data2;
   1441   data2.short_name = ASCIIToUTF16(kNewName);
   1442   data2.SetKeyword(ASCIIToUTF16(kNewKeyword));
   1443   data2.SetURL(kNewSearchURL);
   1444   data2.suggestions_url = kNewSuggestURL;
   1445   data2.show_in_default_list = true;
   1446   scoped_ptr<TemplateURL> expected_managed_default2(new TemplateURL(profile,
   1447                                                                     data2));
   1448   actual_managed_default = model()->GetDefaultSearchProvider();
   1449   ExpectSimilar(expected_managed_default2.get(), actual_managed_default);
   1450   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
   1451 
   1452   // Remove all the managed prefs and check that we are no longer managed.
   1453   test_util_.RemoveManagedDefaultSearchPreferences();
   1454   VerifyObserverFired();
   1455   EXPECT_FALSE(model()->is_default_search_managed());
   1456   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1457 
   1458   // The default should now be the first URL added
   1459   const TemplateURL* actual_final_managed_default =
   1460       model()->GetDefaultSearchProvider();
   1461   ExpectSimilar(model()->GetTemplateURLs()[0], actual_final_managed_default);
   1462   EXPECT_EQ(actual_final_managed_default->show_in_default_list(), true);
   1463 
   1464   // Disable the default search provider through policy.
   1465   test_util_.SetManagedDefaultSearchPreferences(false, std::string(),
   1466       std::string(), std::string(), std::string(), std::string(),
   1467       std::string(), std::string(), std::string());
   1468   VerifyObserverFired();
   1469   EXPECT_TRUE(model()->is_default_search_managed());
   1470   EXPECT_TRUE(NULL == model()->GetDefaultSearchProvider());
   1471   EXPECT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1472 
   1473   // Re-enable it.
   1474   test_util_.SetManagedDefaultSearchPreferences(true, kName, kKeyword,
   1475       kSearchURL, std::string(), kIconURL, kEncodings, kAlternateURL,
   1476       kSearchTermsReplacementKey);
   1477   VerifyObserverFired();
   1478   EXPECT_TRUE(model()->is_default_search_managed());
   1479   EXPECT_EQ(initial_count + 2, model()->GetTemplateURLs().size());
   1480 
   1481   // Verify that the default manager we are getting is the managed one.
   1482   actual_managed_default = model()->GetDefaultSearchProvider();
   1483   ExpectSimilar(expected_managed_default1.get(), actual_managed_default);
   1484   EXPECT_EQ(actual_managed_default->show_in_default_list(), true);
   1485 
   1486   // Clear the model and disable the default search provider through policy.
   1487   // Verify that there is no default search provider after loading the model.
   1488   // This checks against regressions of http://crbug.com/67180
   1489 
   1490   // First, remove the preferences, reset the model, and set a default.
   1491   test_util_.RemoveManagedDefaultSearchPreferences();
   1492   test_util_.ResetModel(true);
   1493   TemplateURL* new_default =
   1494       model()->GetTemplateURLForKeyword(ASCIIToUTF16("key1"));
   1495   ASSERT_FALSE(new_default == NULL);
   1496   model()->SetDefaultSearchProvider(new_default);
   1497   EXPECT_EQ(new_default, model()->GetDefaultSearchProvider());
   1498 
   1499   // Now reset the model again but load it after setting the preferences.
   1500   test_util_.ResetModel(false);
   1501   test_util_.SetManagedDefaultSearchPreferences(false, std::string(),
   1502       std::string(), std::string(), std::string(), std::string(),
   1503       std::string(), std::string(), std::string());
   1504   test_util_.VerifyLoad();
   1505   EXPECT_TRUE(model()->is_default_search_managed());
   1506   EXPECT_TRUE(model()->GetDefaultSearchProvider() == NULL);
   1507 }
   1508 
   1509 // Test that if we load a TemplateURL with an empty GUID, the load process
   1510 // assigns it a newly generated GUID.
   1511 TEST_F(TemplateURLServiceTest, PatchEmptySyncGUID) {
   1512   // Add a new TemplateURL.
   1513   test_util_.VerifyLoad();
   1514   const size_t initial_count = model()->GetTemplateURLs().size();
   1515 
   1516   TemplateURLData data;
   1517   data.short_name = ASCIIToUTF16("google");
   1518   data.SetKeyword(ASCIIToUTF16("keyword"));
   1519   data.SetURL("http://www.google.com/foo/bar");
   1520   data.sync_guid.clear();
   1521   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
   1522   model()->Add(t_url);
   1523 
   1524   VerifyObserverCount(1);
   1525   base::RunLoop().RunUntilIdle();
   1526   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1527 
   1528   // Reload the model to verify it was actually saved to the database and
   1529   // assigned a new GUID when brought back.
   1530   test_util_.ResetModel(true);
   1531   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1532   const TemplateURL* loaded_url =
   1533       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
   1534   ASSERT_FALSE(loaded_url == NULL);
   1535   ASSERT_FALSE(loaded_url->sync_guid().empty());
   1536 }
   1537 
   1538 // Test that if we load a TemplateURL with duplicate input encodings, the load
   1539 // process de-dupes them.
   1540 TEST_F(TemplateURLServiceTest, DuplicateInputEncodings) {
   1541   // Add a new TemplateURL.
   1542   test_util_.VerifyLoad();
   1543   const size_t initial_count = model()->GetTemplateURLs().size();
   1544 
   1545   TemplateURLData data;
   1546   data.short_name = ASCIIToUTF16("google");
   1547   data.SetKeyword(ASCIIToUTF16("keyword"));
   1548   data.SetURL("http://www.google.com/foo/bar");
   1549   std::vector<std::string> encodings;
   1550   data.input_encodings.push_back("UTF-8");
   1551   data.input_encodings.push_back("UTF-8");
   1552   data.input_encodings.push_back("UTF-16");
   1553   data.input_encodings.push_back("UTF-8");
   1554   data.input_encodings.push_back("Big5");
   1555   data.input_encodings.push_back("UTF-16");
   1556   data.input_encodings.push_back("Big5");
   1557   data.input_encodings.push_back("Windows-1252");
   1558   TemplateURL* t_url = new TemplateURL(test_util_.profile(), data);
   1559   model()->Add(t_url);
   1560 
   1561   VerifyObserverCount(1);
   1562   base::RunLoop().RunUntilIdle();
   1563   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1564   const TemplateURL* loaded_url =
   1565       model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
   1566   ASSERT_TRUE(loaded_url != NULL);
   1567   EXPECT_EQ(8U, loaded_url->input_encodings().size());
   1568 
   1569   // Reload the model to verify it was actually saved to the database and the
   1570   // duplicate encodings were removed.
   1571   test_util_.ResetModel(true);
   1572   ASSERT_EQ(initial_count + 1, model()->GetTemplateURLs().size());
   1573   loaded_url = model()->GetTemplateURLForKeyword(ASCIIToUTF16("keyword"));
   1574   ASSERT_FALSE(loaded_url == NULL);
   1575   EXPECT_EQ(4U, loaded_url->input_encodings().size());
   1576 }
   1577 
   1578 TEST_F(TemplateURLServiceTest, DefaultExtensionEngine) {
   1579   test_util_.VerifyLoad();
   1580   // Add third-party default search engine.
   1581   TemplateURL* user_dse = AddKeywordWithDate(
   1582       "user", "user", "http://www.goo.com/s?q={searchTerms}",
   1583       std::string(), std::string(), std::string(),
   1584       true, "UTF-8", Time(), Time());
   1585   model()->SetDefaultSearchProvider(user_dse);
   1586   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
   1587 
   1588   TemplateURL* ext_dse = CreateKeywordWithDate(
   1589       model(), "ext", "ext", "http://www.search.com/s?q={searchTerms}",
   1590       std::string(), std::string(), std::string(),
   1591       true, "UTF-8", Time(), Time());
   1592   scoped_ptr<AssociatedExtensionInfo> extension_info(
   1593       new AssociatedExtensionInfo);
   1594   extension_info->wants_to_be_default_engine = true;
   1595   extension_info->extension_id = "ext";
   1596   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
   1597   EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
   1598 
   1599   model()->RemoveExtensionControlledTURL("ext");
   1600   ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
   1601 }
   1602 
   1603 TEST_F(TemplateURLServiceTest, ExtensionEnginesNotPersist) {
   1604   test_util_.VerifyLoad();
   1605   // Add third-party default search engine.
   1606   TemplateURL* user_dse = AddKeywordWithDate(
   1607       "user", "user", "http://www.goo.com/s?q={searchTerms}",
   1608       std::string(), std::string(), std::string(),
   1609       true, "UTF-8", Time(), Time());
   1610   model()->SetDefaultSearchProvider(user_dse);
   1611   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
   1612 
   1613   TemplateURL* ext_dse = CreateKeywordWithDate(
   1614       model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
   1615       std::string(), std::string(), std::string(),
   1616       true, "UTF-8", Time(), Time());
   1617   scoped_ptr<AssociatedExtensionInfo> extension_info(
   1618       new AssociatedExtensionInfo);
   1619   extension_info->wants_to_be_default_engine = false;
   1620   extension_info->extension_id = "ext1";
   1621   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
   1622   EXPECT_EQ(user_dse, model()->GetDefaultSearchProvider());
   1623 
   1624   ext_dse = CreateKeywordWithDate(
   1625       model(), "ext2", "ext2", "http://www.ext2.com/s?q={searchTerms}",
   1626       std::string(), std::string(), std::string(),
   1627       true, "UTF-8", Time(), Time());
   1628   extension_info.reset(new AssociatedExtensionInfo);
   1629   extension_info->wants_to_be_default_engine = true;
   1630   extension_info->extension_id = "ext2";
   1631   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
   1632   EXPECT_EQ(ext_dse, model()->GetDefaultSearchProvider());
   1633 
   1634   test_util_.ResetModel(true);
   1635   user_dse = model()->GetTemplateURLForKeyword(ASCIIToUTF16("user"));
   1636   ExpectSimilar(user_dse, model()->GetDefaultSearchProvider());
   1637   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
   1638   EXPECT_FALSE(model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext2")));
   1639 }
   1640 
   1641 TEST_F(TemplateURLServiceTest, ExtensionEngineVsPolicy) {
   1642   // Set a managed preference that establishes a default search provider.
   1643   const char kName[] = "test";
   1644   const char kKeyword[] = "test.com";
   1645   const char kSearchURL[] = "http://test.com/search?t={searchTerms}";
   1646   const char kIconURL[] = "http://test.com/icon.jpg";
   1647   const char kEncodings[] = "UTF-16;UTF-32";
   1648   const char kAlternateURL[] = "http://test.com/search#t={searchTerms}";
   1649   const char kSearchTermsReplacementKey[] = "espv";
   1650   test_util_.SetManagedDefaultSearchPreferences(
   1651       true, kName, kKeyword, kSearchURL, std::string(), kIconURL, kEncodings,
   1652       kAlternateURL, kSearchTermsReplacementKey);
   1653   test_util_.VerifyLoad();
   1654   // Verify that the default manager we are getting is the managed one.
   1655   TemplateURLData data;
   1656   data.short_name = ASCIIToUTF16(kName);
   1657   data.SetKeyword(ASCIIToUTF16(kKeyword));
   1658   data.SetURL(kSearchURL);
   1659   data.favicon_url = GURL(kIconURL);
   1660   data.show_in_default_list = true;
   1661   base::SplitString(kEncodings, ';', &data.input_encodings);
   1662   data.alternate_urls.push_back(kAlternateURL);
   1663   data.search_terms_replacement_key = kSearchTermsReplacementKey;
   1664   scoped_ptr<TemplateURL> expected_managed_default(new TemplateURL(
   1665       test_util_.profile(), data));
   1666   EXPECT_TRUE(model()->is_default_search_managed());
   1667   const TemplateURL* actual_managed_default =
   1668       model()->GetDefaultSearchProvider();
   1669   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
   1670 
   1671   TemplateURL* ext_dse = CreateKeywordWithDate(
   1672       model(), "ext1", "ext1", "http://www.ext1.com/s?q={searchTerms}",
   1673       std::string(), std::string(), std::string(),
   1674       true, "UTF-8", Time(), Time());
   1675   scoped_ptr<AssociatedExtensionInfo> extension_info(
   1676       new AssociatedExtensionInfo);
   1677   extension_info->wants_to_be_default_engine = true;
   1678   extension_info->extension_id = "ext1";
   1679   model()->AddExtensionControlledTURL(ext_dse, extension_info.Pass());
   1680   EXPECT_EQ(ext_dse, model()->GetTemplateURLForKeyword(ASCIIToUTF16("ext1")));
   1681   EXPECT_TRUE(model()->is_default_search_managed());
   1682   actual_managed_default = model()->GetDefaultSearchProvider();
   1683   ExpectSimilar(expected_managed_default.get(), actual_managed_default);
   1684 }
   1685