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