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 "chrome/browser/search_engines/default_search_manager.h"
      6 
      7 #include <algorithm>
      8 #include <utility>
      9 
     10 #include "base/bind.h"
     11 #include "base/bind_helpers.h"
     12 #include "base/compiler_specific.h"
     13 #include "base/i18n/case_conversion.h"
     14 #include "base/logging.h"
     15 #include "base/prefs/pref_service.h"
     16 #include "base/prefs/pref_value_map.h"
     17 #include "base/stl_util.h"
     18 #include "base/strings/string_number_conversions.h"
     19 #include "base/strings/string_split.h"
     20 #include "base/strings/string_util.h"
     21 #include "base/strings/utf_string_conversions.h"
     22 #include "base/time/time.h"
     23 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
     24 #include "chrome/common/pref_names.h"
     25 #include "components/pref_registry/pref_registry_syncable.h"
     26 #include "components/search_engines/template_url_data.h"
     27 
     28 namespace {
     29 
     30 bool g_fallback_search_engines_disabled = false;
     31 
     32 }  // namespace
     33 
     34 // A dictionary to hold all data related to the Default Search Engine.
     35 // Eventually, this should replace all the data stored in the
     36 // default_search_provider.* prefs.
     37 const char DefaultSearchManager::kDefaultSearchProviderDataPrefName[] =
     38     "default_search_provider_data.template_url_data";
     39 
     40 const char DefaultSearchManager::kID[] = "id";
     41 const char DefaultSearchManager::kShortName[] = "short_name";
     42 const char DefaultSearchManager::kKeyword[] = "keyword";
     43 const char DefaultSearchManager::kPrepopulateID[] = "prepopulate_id";
     44 const char DefaultSearchManager::kSyncGUID[] = "synced_guid";
     45 
     46 const char DefaultSearchManager::kURL[] = "url";
     47 const char DefaultSearchManager::kSuggestionsURL[] = "suggestions_url";
     48 const char DefaultSearchManager::kInstantURL[] = "instant_url";
     49 const char DefaultSearchManager::kImageURL[] = "image_url";
     50 const char DefaultSearchManager::kNewTabURL[] = "new_tab_url";
     51 const char DefaultSearchManager::kFaviconURL[] = "favicon_url";
     52 const char DefaultSearchManager::kOriginatingURL[] = "originating_url";
     53 
     54 const char DefaultSearchManager::kSearchURLPostParams[] =
     55     "search_url_post_params";
     56 const char DefaultSearchManager::kSuggestionsURLPostParams[] =
     57     "suggestions_url_post_params";
     58 const char DefaultSearchManager::kInstantURLPostParams[] =
     59     "instant_url_post_params";
     60 const char DefaultSearchManager::kImageURLPostParams[] =
     61     "image_url_post_params";
     62 
     63 const char DefaultSearchManager::kSafeForAutoReplace[] = "safe_for_autoreplace";
     64 const char DefaultSearchManager::kInputEncodings[] = "input_encodings";
     65 
     66 const char DefaultSearchManager::kDateCreated[] = "date_created";
     67 const char DefaultSearchManager::kLastModified[] = "last_modified";
     68 
     69 const char DefaultSearchManager::kUsageCount[] = "usage_count";
     70 const char DefaultSearchManager::kAlternateURLs[] = "alternate_urls";
     71 const char DefaultSearchManager::kSearchTermsReplacementKey[] =
     72     "search_terms_replacement_key";
     73 const char DefaultSearchManager::kCreatedByPolicy[] = "created_by_policy";
     74 const char DefaultSearchManager::kDisabledByPolicy[] = "disabled_by_policy";
     75 
     76 DefaultSearchManager::DefaultSearchManager(
     77     PrefService* pref_service,
     78     const ObserverCallback& change_observer)
     79     : pref_service_(pref_service),
     80       change_observer_(change_observer),
     81       default_search_controlled_by_policy_(false) {
     82   if (pref_service_) {
     83     pref_change_registrar_.Init(pref_service_);
     84     pref_change_registrar_.Add(
     85         kDefaultSearchProviderDataPrefName,
     86         base::Bind(&DefaultSearchManager::OnDefaultSearchPrefChanged,
     87                    base::Unretained(this)));
     88     pref_change_registrar_.Add(
     89         prefs::kSearchProviderOverrides,
     90         base::Bind(&DefaultSearchManager::OnOverridesPrefChanged,
     91                    base::Unretained(this)));
     92   }
     93   LoadPrepopulatedDefaultSearch();
     94   LoadDefaultSearchEngineFromPrefs();
     95 }
     96 
     97 DefaultSearchManager::~DefaultSearchManager() {
     98 }
     99 
    100 // static
    101 void DefaultSearchManager::RegisterProfilePrefs(
    102     user_prefs::PrefRegistrySyncable* registry) {
    103   registry->RegisterDictionaryPref(
    104       kDefaultSearchProviderDataPrefName,
    105       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
    106 }
    107 
    108 // static
    109 void DefaultSearchManager::AddPrefValueToMap(base::DictionaryValue* value,
    110                                              PrefValueMap* pref_value_map) {
    111   pref_value_map->SetValue(kDefaultSearchProviderDataPrefName, value);
    112 }
    113 
    114 // static
    115 void DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(
    116     bool disabled) {
    117   g_fallback_search_engines_disabled = disabled;
    118 }
    119 
    120 TemplateURLData* DefaultSearchManager::GetDefaultSearchEngine(
    121     Source* source) const {
    122   if (default_search_controlled_by_policy_) {
    123     if (source)
    124       *source = FROM_POLICY;
    125     return prefs_default_search_.get();
    126   }
    127   if (extension_default_search_) {
    128     if (source)
    129       *source = FROM_EXTENSION;
    130     return extension_default_search_.get();
    131   }
    132   if (prefs_default_search_) {
    133     if (source)
    134       *source = FROM_USER;
    135     return prefs_default_search_.get();
    136   }
    137 
    138   if (source)
    139     *source = FROM_FALLBACK;
    140   return g_fallback_search_engines_disabled ?
    141       NULL : fallback_default_search_.get();
    142 }
    143 
    144 DefaultSearchManager::Source
    145 DefaultSearchManager::GetDefaultSearchEngineSource() const {
    146   Source source;
    147   GetDefaultSearchEngine(&source);
    148   return source;
    149 }
    150 
    151 void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
    152     const TemplateURLData& data) {
    153   if (!pref_service_) {
    154     prefs_default_search_.reset(new TemplateURLData(data));
    155     MergePrefsDataWithPrepopulated();
    156     NotifyObserver();
    157     return;
    158   }
    159 
    160   base::DictionaryValue url_dict;
    161   url_dict.SetString(kID, base::Int64ToString(data.id));
    162   url_dict.SetString(kShortName, data.short_name);
    163   url_dict.SetString(kKeyword, data.keyword());
    164   url_dict.SetInteger(kPrepopulateID, data.prepopulate_id);
    165   url_dict.SetString(kSyncGUID, data.sync_guid);
    166 
    167   url_dict.SetString(kURL, data.url());
    168   url_dict.SetString(kSuggestionsURL, data.suggestions_url);
    169   url_dict.SetString(kInstantURL, data.instant_url);
    170   url_dict.SetString(kImageURL, data.image_url);
    171   url_dict.SetString(kNewTabURL, data.new_tab_url);
    172   url_dict.SetString(kFaviconURL, data.favicon_url.spec());
    173   url_dict.SetString(kOriginatingURL, data.originating_url.spec());
    174 
    175   url_dict.SetString(kSearchURLPostParams, data.search_url_post_params);
    176   url_dict.SetString(kSuggestionsURLPostParams,
    177                      data.suggestions_url_post_params);
    178   url_dict.SetString(kInstantURLPostParams, data.instant_url_post_params);
    179   url_dict.SetString(kImageURLPostParams, data.image_url_post_params);
    180 
    181   url_dict.SetBoolean(kSafeForAutoReplace, data.safe_for_autoreplace);
    182 
    183   url_dict.SetString(kDateCreated,
    184                      base::Int64ToString(data.date_created.ToInternalValue()));
    185   url_dict.SetString(kLastModified,
    186                      base::Int64ToString(data.last_modified.ToInternalValue()));
    187   url_dict.SetInteger(kUsageCount, data.usage_count);
    188 
    189   scoped_ptr<base::ListValue> alternate_urls(new base::ListValue);
    190   for (std::vector<std::string>::const_iterator it =
    191            data.alternate_urls.begin();
    192        it != data.alternate_urls.end(); ++it) {
    193     alternate_urls->AppendString(*it);
    194   }
    195   url_dict.Set(kAlternateURLs, alternate_urls.release());
    196 
    197   scoped_ptr<base::ListValue> encodings(new base::ListValue);
    198   for (std::vector<std::string>::const_iterator it =
    199            data.input_encodings.begin();
    200        it != data.input_encodings.end(); ++it) {
    201     encodings->AppendString(*it);
    202   }
    203   url_dict.Set(kInputEncodings, encodings.release());
    204 
    205   url_dict.SetString(kSearchTermsReplacementKey,
    206                      data.search_terms_replacement_key);
    207 
    208   url_dict.SetBoolean(kCreatedByPolicy, data.created_by_policy);
    209 
    210   pref_service_->Set(kDefaultSearchProviderDataPrefName, url_dict);
    211 }
    212 
    213 void DefaultSearchManager::SetExtensionControlledDefaultSearchEngine(
    214     const TemplateURLData& data) {
    215   extension_default_search_.reset(new TemplateURLData(data));
    216   if (GetDefaultSearchEngineSource() == FROM_EXTENSION)
    217     NotifyObserver();
    218 }
    219 
    220 void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
    221   Source old_source = GetDefaultSearchEngineSource();
    222   extension_default_search_.reset();
    223   if (old_source == FROM_EXTENSION)
    224     NotifyObserver();
    225 }
    226 
    227 void DefaultSearchManager::ClearUserSelectedDefaultSearchEngine() {
    228   if (pref_service_) {
    229     pref_service_->ClearPref(kDefaultSearchProviderDataPrefName);
    230   } else {
    231     prefs_default_search_.reset();
    232     NotifyObserver();
    233   }
    234 }
    235 
    236 void DefaultSearchManager::OnDefaultSearchPrefChanged() {
    237   Source source = GetDefaultSearchEngineSource();
    238   LoadDefaultSearchEngineFromPrefs();
    239 
    240   // If we were/are FROM_USER or FROM_POLICY the effective DSE may have changed.
    241   if (source != FROM_USER && source != FROM_POLICY)
    242     source = GetDefaultSearchEngineSource();
    243   if (source == FROM_USER || source == FROM_POLICY)
    244     NotifyObserver();
    245 }
    246 
    247 void DefaultSearchManager::OnOverridesPrefChanged() {
    248   LoadPrepopulatedDefaultSearch();
    249 
    250   TemplateURLData* effective_data = GetDefaultSearchEngine(NULL);
    251   if (effective_data && effective_data->prepopulate_id) {
    252     // A user-selected, policy-selected or fallback pre-populated engine is
    253     // active and may have changed with this event.
    254     NotifyObserver();
    255   }
    256 }
    257 
    258 void DefaultSearchManager::MergePrefsDataWithPrepopulated() {
    259   if (!prefs_default_search_ || !prefs_default_search_->prepopulate_id)
    260     return;
    261 
    262   size_t default_search_index;
    263   ScopedVector<TemplateURLData> prepopulated_urls =
    264       TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service_,
    265                                                          &default_search_index);
    266 
    267   for (size_t i = 0; i < prepopulated_urls.size(); ++i) {
    268     if (prepopulated_urls[i]->prepopulate_id ==
    269         prefs_default_search_->prepopulate_id) {
    270       if (!prefs_default_search_->safe_for_autoreplace) {
    271         prepopulated_urls[i]->safe_for_autoreplace = false;
    272         prepopulated_urls[i]->SetKeyword(prefs_default_search_->keyword());
    273         prepopulated_urls[i]->short_name = prefs_default_search_->short_name;
    274       }
    275       prepopulated_urls[i]->id = prefs_default_search_->id;
    276       prepopulated_urls[i]->sync_guid = prefs_default_search_->sync_guid;
    277       prepopulated_urls[i]->date_created = prefs_default_search_->date_created;
    278       prepopulated_urls[i]->last_modified =
    279           prefs_default_search_->last_modified;
    280       prefs_default_search_.reset(prepopulated_urls[i]);
    281       prepopulated_urls.weak_erase(prepopulated_urls.begin() + i);
    282       return;
    283     }
    284   }
    285 }
    286 
    287 void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
    288   if (!pref_service_)
    289     return;
    290 
    291   prefs_default_search_.reset();
    292   const PrefService::Preference* pref =
    293       pref_service_->FindPreference(kDefaultSearchProviderDataPrefName);
    294   DCHECK(pref);
    295   default_search_controlled_by_policy_ = pref->IsManaged();
    296 
    297   const base::DictionaryValue* url_dict =
    298       pref_service_->GetDictionary(kDefaultSearchProviderDataPrefName);
    299   if (url_dict->empty())
    300     return;
    301 
    302   if (default_search_controlled_by_policy_) {
    303     bool disabled_by_policy = false;
    304     if (url_dict->GetBoolean(kDisabledByPolicy, &disabled_by_policy) &&
    305         disabled_by_policy)
    306       return;
    307   }
    308 
    309   std::string search_url;
    310   base::string16 keyword;
    311   url_dict->GetString(kURL, &search_url);
    312   url_dict->GetString(kKeyword, &keyword);
    313   if (search_url.empty() || keyword.empty())
    314     return;
    315 
    316   prefs_default_search_.reset(new TemplateURLData);
    317   prefs_default_search_->SetKeyword(keyword);
    318   prefs_default_search_->SetURL(search_url);
    319 
    320   std::string id;
    321   url_dict->GetString(kID, &id);
    322   base::StringToInt64(id, &prefs_default_search_->id);
    323   url_dict->GetString(kShortName, &prefs_default_search_->short_name);
    324   url_dict->GetInteger(kPrepopulateID, &prefs_default_search_->prepopulate_id);
    325   url_dict->GetString(kSyncGUID, &prefs_default_search_->sync_guid);
    326 
    327   url_dict->GetString(kSuggestionsURL, &prefs_default_search_->suggestions_url);
    328   url_dict->GetString(kInstantURL, &prefs_default_search_->instant_url);
    329   url_dict->GetString(kImageURL, &prefs_default_search_->image_url);
    330   url_dict->GetString(kNewTabURL, &prefs_default_search_->new_tab_url);
    331 
    332   std::string favicon_url;
    333   std::string originating_url;
    334   url_dict->GetString(kFaviconURL, &favicon_url);
    335   url_dict->GetString(kOriginatingURL, &originating_url);
    336   prefs_default_search_->favicon_url = GURL(favicon_url);
    337   prefs_default_search_->originating_url = GURL(originating_url);
    338 
    339   url_dict->GetString(kSearchURLPostParams,
    340                       &prefs_default_search_->search_url_post_params);
    341   url_dict->GetString(kSuggestionsURLPostParams,
    342                       &prefs_default_search_->suggestions_url_post_params);
    343   url_dict->GetString(kInstantURLPostParams,
    344                       &prefs_default_search_->instant_url_post_params);
    345   url_dict->GetString(kImageURLPostParams,
    346                       &prefs_default_search_->image_url_post_params);
    347 
    348   url_dict->GetBoolean(kSafeForAutoReplace,
    349                        &prefs_default_search_->safe_for_autoreplace);
    350 
    351   std::string date_created_str;
    352   std::string last_modified_str;
    353   url_dict->GetString(kDateCreated, &date_created_str);
    354   url_dict->GetString(kLastModified, &last_modified_str);
    355 
    356   int64 date_created = 0;
    357   if (base::StringToInt64(date_created_str, &date_created)) {
    358     prefs_default_search_->date_created =
    359         base::Time::FromInternalValue(date_created);
    360   }
    361 
    362   int64 last_modified = 0;
    363   if (base::StringToInt64(date_created_str, &last_modified)) {
    364     prefs_default_search_->last_modified =
    365         base::Time::FromInternalValue(last_modified);
    366   }
    367 
    368   url_dict->GetInteger(kUsageCount, &prefs_default_search_->usage_count);
    369 
    370   const base::ListValue* alternate_urls = NULL;
    371   if (url_dict->GetList(kAlternateURLs, &alternate_urls)) {
    372     for (base::ListValue::const_iterator it = alternate_urls->begin();
    373          it != alternate_urls->end();
    374          ++it) {
    375       std::string alternate_url;
    376       if ((*it)->GetAsString(&alternate_url))
    377         prefs_default_search_->alternate_urls.push_back(alternate_url);
    378     }
    379   }
    380 
    381   const base::ListValue* encodings = NULL;
    382   if (url_dict->GetList(kInputEncodings, &encodings)) {
    383     for (base::ListValue::const_iterator it = encodings->begin();
    384          it != encodings->end();
    385          ++it) {
    386       std::string encoding;
    387       if ((*it)->GetAsString(&encoding))
    388         prefs_default_search_->input_encodings.push_back(encoding);
    389     }
    390   }
    391 
    392   url_dict->GetString(kSearchTermsReplacementKey,
    393                       &prefs_default_search_->search_terms_replacement_key);
    394 
    395   url_dict->GetBoolean(kCreatedByPolicy,
    396                        &prefs_default_search_->created_by_policy);
    397 
    398   prefs_default_search_->show_in_default_list = true;
    399   MergePrefsDataWithPrepopulated();
    400 }
    401 
    402 void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
    403   scoped_ptr<TemplateURLData> data =
    404       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_);
    405   fallback_default_search_ = data.Pass();
    406   MergePrefsDataWithPrepopulated();
    407 }
    408 
    409 void DefaultSearchManager::NotifyObserver() {
    410   if (!change_observer_.is_null()) {
    411     Source source = FROM_FALLBACK;
    412     TemplateURLData* data = GetDefaultSearchEngine(&source);
    413     change_observer_.Run(data, source);
    414   }
    415 }
    416