• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "components/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 "components/pref_registry/pref_registry_syncable.h"
24 #include "components/search_engines/search_engines_pref_names.h"
25 #include "components/search_engines/template_url_data.h"
26 #include "components/search_engines/template_url_prepopulate_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 
DefaultSearchManager(PrefService * pref_service,const ObserverCallback & change_observer)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 
~DefaultSearchManager()97 DefaultSearchManager::~DefaultSearchManager() {
98 }
99 
100 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)101 void DefaultSearchManager::RegisterProfilePrefs(
102     user_prefs::PrefRegistrySyncable* registry) {
103   registry->RegisterDictionaryPref(
104       kDefaultSearchProviderDataPrefName,
105       user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
106 }
107 
108 // static
AddPrefValueToMap(base::DictionaryValue * value,PrefValueMap * pref_value_map)109 void DefaultSearchManager::AddPrefValueToMap(base::DictionaryValue* value,
110                                              PrefValueMap* pref_value_map) {
111   pref_value_map->SetValue(kDefaultSearchProviderDataPrefName, value);
112 }
113 
114 // static
SetFallbackSearchEnginesDisabledForTesting(bool disabled)115 void DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(
116     bool disabled) {
117   g_fallback_search_engines_disabled = disabled;
118 }
119 
GetDefaultSearchEngine(Source * source) const120 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
GetDefaultSearchEngineSource() const145 DefaultSearchManager::GetDefaultSearchEngineSource() const {
146   Source source;
147   GetDefaultSearchEngine(&source);
148   return source;
149 }
150 
SetUserSelectedDefaultSearchEngine(const TemplateURLData & data)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 
SetExtensionControlledDefaultSearchEngine(const TemplateURLData & data)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 
ClearExtensionControlledDefaultSearchEngine()220 void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
221   Source old_source = GetDefaultSearchEngineSource();
222   extension_default_search_.reset();
223   if (old_source == FROM_EXTENSION)
224     NotifyObserver();
225 }
226 
ClearUserSelectedDefaultSearchEngine()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 
OnDefaultSearchPrefChanged()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 
OnOverridesPrefChanged()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 
MergePrefsDataWithPrepopulated()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 
LoadDefaultSearchEngineFromPrefs()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 
LoadPrepopulatedDefaultSearch()402 void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
403   scoped_ptr<TemplateURLData> data =
404       TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_);
405   fallback_default_search_ = data.Pass();
406   MergePrefsDataWithPrepopulated();
407 }
408 
NotifyObserver()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