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