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.
5 #include "components/search_engines/default_search_manager.h"
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"
30 bool g_fallback_search_engines_disabled
= false;
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";
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";
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";
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";
63 const char DefaultSearchManager::kSafeForAutoReplace
[] = "safe_for_autoreplace";
64 const char DefaultSearchManager::kInputEncodings
[] = "input_encodings";
66 const char DefaultSearchManager::kDateCreated
[] = "date_created";
67 const char DefaultSearchManager::kLastModified
[] = "last_modified";
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";
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) {
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)));
93 LoadPrepopulatedDefaultSearch();
94 LoadDefaultSearchEngineFromPrefs();
97 DefaultSearchManager::~DefaultSearchManager() {
101 void DefaultSearchManager::RegisterProfilePrefs(
102 user_prefs::PrefRegistrySyncable
* registry
) {
103 registry
->RegisterDictionaryPref(
104 kDefaultSearchProviderDataPrefName
,
105 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF
);
109 void DefaultSearchManager::AddPrefValueToMap(base::DictionaryValue
* value
,
110 PrefValueMap
* pref_value_map
) {
111 pref_value_map
->SetValue(kDefaultSearchProviderDataPrefName
, value
);
115 void DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(
117 g_fallback_search_engines_disabled
= disabled
;
120 TemplateURLData
* DefaultSearchManager::GetDefaultSearchEngine(
121 Source
* source
) const {
122 if (default_search_controlled_by_policy_
) {
124 *source
= FROM_POLICY
;
125 return prefs_default_search_
.get();
127 if (extension_default_search_
) {
129 *source
= FROM_EXTENSION
;
130 return extension_default_search_
.get();
132 if (prefs_default_search_
) {
135 return prefs_default_search_
.get();
139 *source
= FROM_FALLBACK
;
140 return g_fallback_search_engines_disabled
?
141 NULL
: fallback_default_search_
.get();
144 DefaultSearchManager::Source
145 DefaultSearchManager::GetDefaultSearchEngineSource() const {
147 GetDefaultSearchEngine(&source
);
151 void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
152 const TemplateURLData
& data
) {
153 if (!pref_service_
) {
154 prefs_default_search_
.reset(new TemplateURLData(data
));
155 MergePrefsDataWithPrepopulated();
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
);
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());
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
);
181 url_dict
.SetBoolean(kSafeForAutoReplace
, data
.safe_for_autoreplace
);
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
);
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
);
195 url_dict
.Set(kAlternateURLs
, alternate_urls
.release());
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
);
203 url_dict
.Set(kInputEncodings
, encodings
.release());
205 url_dict
.SetString(kSearchTermsReplacementKey
,
206 data
.search_terms_replacement_key
);
208 url_dict
.SetBoolean(kCreatedByPolicy
, data
.created_by_policy
);
210 pref_service_
->Set(kDefaultSearchProviderDataPrefName
, url_dict
);
213 void DefaultSearchManager::SetExtensionControlledDefaultSearchEngine(
214 const TemplateURLData
& data
) {
215 extension_default_search_
.reset(new TemplateURLData(data
));
216 if (GetDefaultSearchEngineSource() == FROM_EXTENSION
)
220 void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
221 Source old_source
= GetDefaultSearchEngineSource();
222 extension_default_search_
.reset();
223 if (old_source
== FROM_EXTENSION
)
227 void DefaultSearchManager::ClearUserSelectedDefaultSearchEngine() {
229 pref_service_
->ClearPref(kDefaultSearchProviderDataPrefName
);
231 prefs_default_search_
.reset();
236 void DefaultSearchManager::OnDefaultSearchPrefChanged() {
237 Source source
= GetDefaultSearchEngineSource();
238 LoadDefaultSearchEngineFromPrefs();
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
)
247 void DefaultSearchManager::OnOverridesPrefChanged() {
248 LoadPrepopulatedDefaultSearch();
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.
258 void DefaultSearchManager::MergePrefsDataWithPrepopulated() {
259 if (!prefs_default_search_
|| !prefs_default_search_
->prepopulate_id
)
262 size_t default_search_index
;
263 ScopedVector
<TemplateURLData
> prepopulated_urls
=
264 TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service_
,
265 &default_search_index
);
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
;
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
);
287 void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
291 prefs_default_search_
.reset();
292 const PrefService::Preference
* pref
=
293 pref_service_
->FindPreference(kDefaultSearchProviderDataPrefName
);
295 default_search_controlled_by_policy_
= pref
->IsManaged();
297 const base::DictionaryValue
* url_dict
=
298 pref_service_
->GetDictionary(kDefaultSearchProviderDataPrefName
);
299 if (url_dict
->empty())
302 if (default_search_controlled_by_policy_
) {
303 bool disabled_by_policy
= false;
304 if (url_dict
->GetBoolean(kDisabledByPolicy
, &disabled_by_policy
) &&
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())
316 prefs_default_search_
.reset(new TemplateURLData
);
317 prefs_default_search_
->SetKeyword(keyword
);
318 prefs_default_search_
->SetURL(search_url
);
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
);
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
);
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
);
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
);
348 url_dict
->GetBoolean(kSafeForAutoReplace
,
349 &prefs_default_search_
->safe_for_autoreplace
);
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
);
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
);
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
);
368 url_dict
->GetInteger(kUsageCount
, &prefs_default_search_
->usage_count
);
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();
375 std::string alternate_url
;
376 if ((*it
)->GetAsString(&alternate_url
))
377 prefs_default_search_
->alternate_urls
.push_back(alternate_url
);
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();
386 std::string encoding
;
387 if ((*it
)->GetAsString(&encoding
))
388 prefs_default_search_
->input_encodings
.push_back(encoding
);
392 url_dict
->GetString(kSearchTermsReplacementKey
,
393 &prefs_default_search_
->search_terms_replacement_key
);
395 url_dict
->GetBoolean(kCreatedByPolicy
,
396 &prefs_default_search_
->created_by_policy
);
398 prefs_default_search_
->show_in_default_list
= true;
399 MergePrefsDataWithPrepopulated();
402 void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
403 scoped_ptr
<TemplateURLData
> data
=
404 TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_
);
405 fallback_default_search_
= data
.Pass();
406 MergePrefsDataWithPrepopulated();
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
);