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