Home | History | Annotate | Download | only in search_engines
      1 // Copyright 2014 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/files/scoped_temp_dir.h"
      6 #include "base/memory/scoped_ptr.h"
      7 #include "base/strings/string_split.h"
      8 #include "base/strings/string_util.h"
      9 #include "base/strings/utf_string_conversions.h"
     10 #include "base/time/time.h"
     11 #include "chrome/browser/search_engines/default_search_manager.h"
     12 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
     13 #include "chrome/common/pref_names.h"
     14 #include "components/pref_registry/pref_registry_syncable.h"
     15 #include "components/pref_registry/testing_pref_service_syncable.h"
     16 #include "components/search_engines/template_url_data.h"
     17 #include "testing/gtest/include/gtest/gtest.h"
     18 
     19 namespace {
     20 // A dictionary to hold all data related to the Default Search Engine.
     21 // Eventually, this should replace all the data stored in the
     22 // default_search_provider.* prefs.
     23 const char kDefaultSearchProviderData[] =
     24     "default_search_provider_data.template_url_data";
     25 
     26 // Checks that the two TemplateURLs are similar. Does not check the id, the
     27 // date_created or the last_modified time.  Neither pointer should be NULL.
     28 void ExpectSimilar(const TemplateURLData* expected,
     29                    const TemplateURLData* actual) {
     30   ASSERT_TRUE(expected != NULL);
     31   ASSERT_TRUE(actual != NULL);
     32 
     33   EXPECT_EQ(expected->short_name, actual->short_name);
     34   EXPECT_EQ(expected->keyword(), actual->keyword());
     35   EXPECT_EQ(expected->url(), actual->url());
     36   EXPECT_EQ(expected->suggestions_url, actual->suggestions_url);
     37   EXPECT_EQ(expected->favicon_url, actual->favicon_url);
     38   EXPECT_EQ(expected->alternate_urls, actual->alternate_urls);
     39   EXPECT_EQ(expected->show_in_default_list, actual->show_in_default_list);
     40   EXPECT_EQ(expected->safe_for_autoreplace, actual->safe_for_autoreplace);
     41   EXPECT_EQ(expected->input_encodings, actual->input_encodings);
     42   EXPECT_EQ(expected->search_terms_replacement_key,
     43             actual->search_terms_replacement_key);
     44 }
     45 
     46 // TODO(caitkp): TemplateURLData-ify this.
     47 void SetOverrides(user_prefs::TestingPrefServiceSyncable* prefs, bool update) {
     48   prefs->SetUserPref(prefs::kSearchProviderOverridesVersion,
     49                      base::Value::CreateIntegerValue(1));
     50   base::ListValue* overrides = new base::ListValue;
     51   scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
     52 
     53   entry->SetString("name", update ? "new_foo" : "foo");
     54   entry->SetString("keyword", update ? "new_fook" : "fook");
     55   entry->SetString("search_url", "http://foo.com/s?q={searchTerms}");
     56   entry->SetString("favicon_url", "http://foi.com/favicon.ico");
     57   entry->SetString("encoding", "UTF-8");
     58   entry->SetInteger("id", 1001);
     59   entry->SetString("suggest_url", "http://foo.com/suggest?q={searchTerms}");
     60   entry->SetString("instant_url", "http://foo.com/instant?q={searchTerms}");
     61   base::ListValue* alternate_urls = new base::ListValue;
     62   alternate_urls->AppendString("http://foo.com/alternate?q={searchTerms}");
     63   entry->Set("alternate_urls", alternate_urls);
     64   entry->SetString("search_terms_replacement_key", "espv");
     65   overrides->Append(entry->DeepCopy());
     66 
     67   entry.reset(new base::DictionaryValue);
     68   entry->SetInteger("id", 1002);
     69   entry->SetString("name", update ? "new_bar" : "bar");
     70   entry->SetString("keyword", update ? "new_bark" : "bark");
     71   entry->SetString("encoding", std::string());
     72   overrides->Append(entry->DeepCopy());
     73   entry->SetInteger("id", 1003);
     74   entry->SetString("name", "baz");
     75   entry->SetString("keyword", "bazk");
     76   entry->SetString("encoding", "UTF-8");
     77   overrides->Append(entry->DeepCopy());
     78   prefs->SetUserPref(prefs::kSearchProviderOverrides, overrides);
     79 }
     80 
     81 void SetPolicy(user_prefs::TestingPrefServiceSyncable* prefs,
     82                bool enabled,
     83                TemplateURLData* data) {
     84   if (enabled) {
     85     EXPECT_FALSE(data->keyword().empty());
     86     EXPECT_FALSE(data->url().empty());
     87   }
     88   scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
     89   entry->SetString(DefaultSearchManager::kShortName, data->short_name);
     90   entry->SetString(DefaultSearchManager::kKeyword, data->keyword());
     91   entry->SetString(DefaultSearchManager::kURL, data->url());
     92   entry->SetString(DefaultSearchManager::kFaviconURL, data->favicon_url.spec());
     93   entry->SetString(DefaultSearchManager::kSuggestionsURL,
     94                    data->suggestions_url);
     95   entry->SetBoolean(DefaultSearchManager::kSafeForAutoReplace,
     96                     data->safe_for_autoreplace);
     97   scoped_ptr<base::ListValue> alternate_urls(new base::ListValue);
     98   for (std::vector<std::string>::const_iterator it =
     99            data->alternate_urls.begin();
    100        it != data->alternate_urls.end();
    101        ++it) {
    102     alternate_urls->AppendString(*it);
    103   }
    104   entry->Set(DefaultSearchManager::kAlternateURLs, alternate_urls.release());
    105 
    106   scoped_ptr<base::ListValue> encodings(new base::ListValue);
    107   for (std::vector<std::string>::const_iterator it =
    108            data->input_encodings.begin();
    109        it != data->input_encodings.end();
    110        ++it) {
    111     encodings->AppendString(*it);
    112   }
    113   entry->Set(DefaultSearchManager::kInputEncodings, encodings.release());
    114 
    115   entry->SetString(DefaultSearchManager::kSearchTermsReplacementKey,
    116                    data->search_terms_replacement_key);
    117   entry->SetBoolean(DefaultSearchManager::kDisabledByPolicy, !enabled);
    118   prefs->SetManagedPref(kDefaultSearchProviderData, entry.release());
    119 }
    120 
    121 scoped_ptr<TemplateURLData> GenerateDummyTemplateURLData(std::string type) {
    122   scoped_ptr<TemplateURLData> data(new TemplateURLData());
    123   data->short_name = base::UTF8ToUTF16(std::string(type).append("name"));
    124   data->SetKeyword(base::UTF8ToUTF16(std::string(type).append("key")));
    125   data->SetURL(std::string("http://").append(type).append("foo/{searchTerms}"));
    126   data->suggestions_url = std::string("http://").append(type).append("sugg");
    127   data->alternate_urls.push_back(
    128       std::string("http://").append(type).append("foo/alt"));
    129   data->favicon_url = GURL("http://icon1");
    130   data->safe_for_autoreplace = true;
    131   data->show_in_default_list = true;
    132   base::SplitString("UTF-8;UTF-16", ';', &data->input_encodings);
    133   data->date_created = base::Time();
    134   data->last_modified = base::Time();
    135   return data.Pass();
    136 }
    137 
    138 }  // namespace
    139 
    140 class DefaultSearchManagerTest : public testing::Test {
    141  public:
    142   DefaultSearchManagerTest() {};
    143 
    144   virtual void SetUp() OVERRIDE {
    145     pref_service_.reset(new user_prefs::TestingPrefServiceSyncable);
    146     DefaultSearchManager::RegisterProfilePrefs(pref_service_->registry());
    147     TemplateURLPrepopulateData::RegisterProfilePrefs(pref_service_->registry());
    148   }
    149 
    150   user_prefs::TestingPrefServiceSyncable* pref_service() {
    151     return pref_service_.get();
    152   }
    153 
    154  private:
    155   scoped_ptr<user_prefs::TestingPrefServiceSyncable> pref_service_;
    156 
    157   DISALLOW_COPY_AND_ASSIGN(DefaultSearchManagerTest);
    158 };
    159 
    160 // Test that a TemplateURLData object is properly written and read from Prefs.
    161 TEST_F(DefaultSearchManagerTest, ReadAndWritePref) {
    162   DefaultSearchManager manager(pref_service(),
    163                                DefaultSearchManager::ObserverCallback());
    164   TemplateURLData data;
    165   data.short_name = base::UTF8ToUTF16("name1");
    166   data.SetKeyword(base::UTF8ToUTF16("key1"));
    167   data.SetURL("http://foo1/{searchTerms}");
    168   data.suggestions_url = "http://sugg1";
    169   data.alternate_urls.push_back("http://foo1/alt");
    170   data.favicon_url = GURL("http://icon1");
    171   data.safe_for_autoreplace = true;
    172   data.show_in_default_list = true;
    173   base::SplitString("UTF-8;UTF-16", ';', &data.input_encodings);
    174   data.date_created = base::Time();
    175   data.last_modified = base::Time();
    176 
    177   manager.SetUserSelectedDefaultSearchEngine(data);
    178   TemplateURLData* read_data = manager.GetDefaultSearchEngine(NULL);
    179   ExpectSimilar(&data, read_data);
    180 }
    181 
    182 // Test DefaultSearchmanager handles user-selected DSEs correctly.
    183 TEST_F(DefaultSearchManagerTest, DefaultSearchSetByUserPref) {
    184   size_t default_search_index = 0;
    185   DefaultSearchManager manager(pref_service(),
    186                                DefaultSearchManager::ObserverCallback());
    187   ScopedVector<TemplateURLData> prepopulated_urls =
    188       TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service(),
    189                                                          &default_search_index);
    190   DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY;
    191   // If no user pref is set, we should use the pre-populated values.
    192   ExpectSimilar(prepopulated_urls[default_search_index],
    193                 manager.GetDefaultSearchEngine(&source));
    194   EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
    195 
    196   // Setting a user pref overrides the pre-populated values.
    197   scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user");
    198   manager.SetUserSelectedDefaultSearchEngine(*data.get());
    199 
    200   ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
    201   EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
    202 
    203   // Updating the user pref (externally to this instance of
    204   // DefaultSearchManager) triggers an update.
    205   scoped_ptr<TemplateURLData> new_data = GenerateDummyTemplateURLData("user2");
    206   DefaultSearchManager other_manager(pref_service(),
    207                                      DefaultSearchManager::ObserverCallback());
    208   other_manager.SetUserSelectedDefaultSearchEngine(*new_data.get());
    209 
    210   ExpectSimilar(new_data.get(), manager.GetDefaultSearchEngine(&source));
    211   EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
    212 
    213   // Clearing the user pref should cause the default search to revert to the
    214   // prepopulated vlaues.
    215   manager.ClearUserSelectedDefaultSearchEngine();
    216   ExpectSimilar(prepopulated_urls[default_search_index],
    217                 manager.GetDefaultSearchEngine(&source));
    218   EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
    219 }
    220 
    221 // Test that DefaultSearch manager detects changes to kSearchProviderOverrides.
    222 TEST_F(DefaultSearchManagerTest, DefaultSearchSetByOverrides) {
    223   SetOverrides(pref_service(), false);
    224   size_t default_search_index = 0;
    225   DefaultSearchManager manager(pref_service(),
    226                                DefaultSearchManager::ObserverCallback());
    227   ScopedVector<TemplateURLData> prepopulated_urls =
    228       TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service(),
    229                                                          &default_search_index);
    230 
    231   DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY;
    232   TemplateURLData first_default(*manager.GetDefaultSearchEngine(&source));
    233   ExpectSimilar(prepopulated_urls[default_search_index], &first_default);
    234   EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
    235 
    236   // Update the overrides:
    237   SetOverrides(pref_service(), true);
    238   prepopulated_urls = TemplateURLPrepopulateData::GetPrepopulatedEngines(
    239       pref_service(), &default_search_index);
    240 
    241   // Make sure DefaultSearchManager updated:
    242   ExpectSimilar(prepopulated_urls[default_search_index],
    243                 manager.GetDefaultSearchEngine(&source));
    244   EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
    245   EXPECT_NE(manager.GetDefaultSearchEngine(NULL)->short_name,
    246             first_default.short_name);
    247   EXPECT_NE(manager.GetDefaultSearchEngine(NULL)->keyword(),
    248             first_default.keyword());
    249 }
    250 
    251 // Test DefaultSearchManager handles policy-enforced DSEs correctly.
    252 TEST_F(DefaultSearchManagerTest, DefaultSearchSetByPolicy) {
    253   DefaultSearchManager manager(pref_service(),
    254                                DefaultSearchManager::ObserverCallback());
    255   scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user");
    256   manager.SetUserSelectedDefaultSearchEngine(*data.get());
    257 
    258   DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK;
    259   ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
    260   EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
    261 
    262   scoped_ptr<TemplateURLData> policy_data =
    263       GenerateDummyTemplateURLData("policy");
    264   SetPolicy(pref_service(), true, policy_data.get());
    265 
    266   ExpectSimilar(policy_data.get(), manager.GetDefaultSearchEngine(&source));
    267   EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source);
    268 
    269   TemplateURLData null_policy_data;
    270   SetPolicy(pref_service(), false, &null_policy_data);
    271   EXPECT_EQ(NULL, manager.GetDefaultSearchEngine(&source));
    272   EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source);
    273 
    274   pref_service()->RemoveManagedPref(kDefaultSearchProviderData);
    275   ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
    276   EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
    277 }
    278 
    279 // Test DefaultSearchManager handles extension-controlled DSEs correctly.
    280 TEST_F(DefaultSearchManagerTest, DefaultSearchSetByExtension) {
    281   DefaultSearchManager manager(pref_service(),
    282                                DefaultSearchManager::ObserverCallback());
    283   scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user");
    284   manager.SetUserSelectedDefaultSearchEngine(*data);
    285 
    286   DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK;
    287   ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
    288   EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
    289 
    290   // Extension trumps prefs:
    291   scoped_ptr<TemplateURLData> extension_data_1 =
    292       GenerateDummyTemplateURLData("ext1");
    293   manager.SetExtensionControlledDefaultSearchEngine(*extension_data_1);
    294 
    295   ExpectSimilar(extension_data_1.get(),
    296                 manager.GetDefaultSearchEngine(&source));
    297   EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source);
    298 
    299   // Policy trumps extension:
    300   scoped_ptr<TemplateURLData> policy_data =
    301       GenerateDummyTemplateURLData("policy");
    302   SetPolicy(pref_service(), true, policy_data.get());
    303 
    304   ExpectSimilar(policy_data.get(), manager.GetDefaultSearchEngine(&source));
    305   EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source);
    306   pref_service()->RemoveManagedPref(kDefaultSearchProviderData);
    307 
    308   // Extensions trump each other:
    309   scoped_ptr<TemplateURLData> extension_data_2 =
    310       GenerateDummyTemplateURLData("ext2");
    311   scoped_ptr<TemplateURLData> extension_data_3 =
    312       GenerateDummyTemplateURLData("ext3");
    313   manager.SetExtensionControlledDefaultSearchEngine(*extension_data_2);
    314   manager.SetExtensionControlledDefaultSearchEngine(*extension_data_3);
    315 
    316   ExpectSimilar(extension_data_3.get(),
    317                 manager.GetDefaultSearchEngine(&source));
    318   EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source);
    319 
    320   manager.ClearExtensionControlledDefaultSearchEngine();
    321 
    322   ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
    323   EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
    324 }
    325