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(kDefaultSearchProviderDataPrefName
);
107 void DefaultSearchManager::AddPrefValueToMap(
108 scoped_ptr
<base::DictionaryValue
> value
,
109 PrefValueMap
* pref_value_map
) {
110 pref_value_map
->SetValue(kDefaultSearchProviderDataPrefName
, value
.Pass());
114 void DefaultSearchManager::SetFallbackSearchEnginesDisabledForTesting(
116 g_fallback_search_engines_disabled
= disabled
;
119 TemplateURLData
* DefaultSearchManager::GetDefaultSearchEngine(
120 Source
* source
) const {
121 if (default_search_controlled_by_policy_
) {
123 *source
= FROM_POLICY
;
124 return prefs_default_search_
.get();
126 if (extension_default_search_
) {
128 *source
= FROM_EXTENSION
;
129 return extension_default_search_
.get();
131 if (prefs_default_search_
) {
134 return prefs_default_search_
.get();
138 *source
= FROM_FALLBACK
;
139 return g_fallback_search_engines_disabled
?
140 NULL
: fallback_default_search_
.get();
143 DefaultSearchManager::Source
144 DefaultSearchManager::GetDefaultSearchEngineSource() const {
146 GetDefaultSearchEngine(&source
);
150 void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
151 const TemplateURLData
& data
) {
152 if (!pref_service_
) {
153 prefs_default_search_
.reset(new TemplateURLData(data
));
154 MergePrefsDataWithPrepopulated();
159 base::DictionaryValue url_dict
;
160 url_dict
.SetString(kID
, base::Int64ToString(data
.id
));
161 url_dict
.SetString(kShortName
, data
.short_name());
162 url_dict
.SetString(kKeyword
, data
.keyword());
163 url_dict
.SetInteger(kPrepopulateID
, data
.prepopulate_id
);
164 url_dict
.SetString(kSyncGUID
, data
.sync_guid
);
166 url_dict
.SetString(kURL
, data
.url());
167 url_dict
.SetString(kSuggestionsURL
, data
.suggestions_url
);
168 url_dict
.SetString(kInstantURL
, data
.instant_url
);
169 url_dict
.SetString(kImageURL
, data
.image_url
);
170 url_dict
.SetString(kNewTabURL
, data
.new_tab_url
);
171 url_dict
.SetString(kFaviconURL
, data
.favicon_url
.spec());
172 url_dict
.SetString(kOriginatingURL
, data
.originating_url
.spec());
174 url_dict
.SetString(kSearchURLPostParams
, data
.search_url_post_params
);
175 url_dict
.SetString(kSuggestionsURLPostParams
,
176 data
.suggestions_url_post_params
);
177 url_dict
.SetString(kInstantURLPostParams
, data
.instant_url_post_params
);
178 url_dict
.SetString(kImageURLPostParams
, data
.image_url_post_params
);
180 url_dict
.SetBoolean(kSafeForAutoReplace
, data
.safe_for_autoreplace
);
182 url_dict
.SetString(kDateCreated
,
183 base::Int64ToString(data
.date_created
.ToInternalValue()));
184 url_dict
.SetString(kLastModified
,
185 base::Int64ToString(data
.last_modified
.ToInternalValue()));
186 url_dict
.SetInteger(kUsageCount
, data
.usage_count
);
188 scoped_ptr
<base::ListValue
> alternate_urls(new base::ListValue
);
189 for (std::vector
<std::string
>::const_iterator it
=
190 data
.alternate_urls
.begin();
191 it
!= data
.alternate_urls
.end(); ++it
) {
192 alternate_urls
->AppendString(*it
);
194 url_dict
.Set(kAlternateURLs
, alternate_urls
.release());
196 scoped_ptr
<base::ListValue
> encodings(new base::ListValue
);
197 for (std::vector
<std::string
>::const_iterator it
=
198 data
.input_encodings
.begin();
199 it
!= data
.input_encodings
.end(); ++it
) {
200 encodings
->AppendString(*it
);
202 url_dict
.Set(kInputEncodings
, encodings
.release());
204 url_dict
.SetString(kSearchTermsReplacementKey
,
205 data
.search_terms_replacement_key
);
207 url_dict
.SetBoolean(kCreatedByPolicy
, data
.created_by_policy
);
209 pref_service_
->Set(kDefaultSearchProviderDataPrefName
, url_dict
);
212 void DefaultSearchManager::SetExtensionControlledDefaultSearchEngine(
213 const TemplateURLData
& data
) {
214 extension_default_search_
.reset(new TemplateURLData(data
));
215 if (GetDefaultSearchEngineSource() == FROM_EXTENSION
)
219 void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
220 Source old_source
= GetDefaultSearchEngineSource();
221 extension_default_search_
.reset();
222 if (old_source
== FROM_EXTENSION
)
226 void DefaultSearchManager::ClearUserSelectedDefaultSearchEngine() {
228 pref_service_
->ClearPref(kDefaultSearchProviderDataPrefName
);
230 prefs_default_search_
.reset();
235 void DefaultSearchManager::OnDefaultSearchPrefChanged() {
236 Source source
= GetDefaultSearchEngineSource();
237 LoadDefaultSearchEngineFromPrefs();
239 // If we were/are FROM_USER or FROM_POLICY the effective DSE may have changed.
240 if (source
!= FROM_USER
&& source
!= FROM_POLICY
)
241 source
= GetDefaultSearchEngineSource();
242 if (source
== FROM_USER
|| source
== FROM_POLICY
)
246 void DefaultSearchManager::OnOverridesPrefChanged() {
247 LoadPrepopulatedDefaultSearch();
249 TemplateURLData
* effective_data
= GetDefaultSearchEngine(NULL
);
250 if (effective_data
&& effective_data
->prepopulate_id
) {
251 // A user-selected, policy-selected or fallback pre-populated engine is
252 // active and may have changed with this event.
257 void DefaultSearchManager::MergePrefsDataWithPrepopulated() {
258 if (!prefs_default_search_
|| !prefs_default_search_
->prepopulate_id
)
261 size_t default_search_index
;
262 ScopedVector
<TemplateURLData
> prepopulated_urls
=
263 TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service_
,
264 &default_search_index
);
266 for (size_t i
= 0; i
< prepopulated_urls
.size(); ++i
) {
267 if (prepopulated_urls
[i
]->prepopulate_id
==
268 prefs_default_search_
->prepopulate_id
) {
269 if (!prefs_default_search_
->safe_for_autoreplace
) {
270 prepopulated_urls
[i
]->safe_for_autoreplace
= false;
271 prepopulated_urls
[i
]->SetKeyword(prefs_default_search_
->keyword());
272 prepopulated_urls
[i
]->SetShortName(prefs_default_search_
->short_name());
274 prepopulated_urls
[i
]->id
= prefs_default_search_
->id
;
275 prepopulated_urls
[i
]->sync_guid
= prefs_default_search_
->sync_guid
;
276 prepopulated_urls
[i
]->date_created
= prefs_default_search_
->date_created
;
277 prepopulated_urls
[i
]->last_modified
=
278 prefs_default_search_
->last_modified
;
279 prefs_default_search_
.reset(prepopulated_urls
[i
]);
280 prepopulated_urls
.weak_erase(prepopulated_urls
.begin() + i
);
286 void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
290 prefs_default_search_
.reset();
291 const PrefService::Preference
* pref
=
292 pref_service_
->FindPreference(kDefaultSearchProviderDataPrefName
);
294 default_search_controlled_by_policy_
= pref
->IsManaged();
296 const base::DictionaryValue
* url_dict
=
297 pref_service_
->GetDictionary(kDefaultSearchProviderDataPrefName
);
298 if (url_dict
->empty())
301 if (default_search_controlled_by_policy_
) {
302 bool disabled_by_policy
= false;
303 if (url_dict
->GetBoolean(kDisabledByPolicy
, &disabled_by_policy
) &&
308 std::string search_url
;
309 base::string16 keyword
;
310 url_dict
->GetString(kURL
, &search_url
);
311 url_dict
->GetString(kKeyword
, &keyword
);
312 if (search_url
.empty() || keyword
.empty())
315 prefs_default_search_
.reset(new TemplateURLData
);
316 prefs_default_search_
->SetKeyword(keyword
);
317 prefs_default_search_
->SetURL(search_url
);
320 url_dict
->GetString(kID
, &id
);
321 base::StringToInt64(id
, &prefs_default_search_
->id
);
322 base::string16 short_name
;
323 url_dict
->GetString(kShortName
, &short_name
);
324 prefs_default_search_
->SetShortName(short_name
);
325 url_dict
->GetInteger(kPrepopulateID
, &prefs_default_search_
->prepopulate_id
);
326 url_dict
->GetString(kSyncGUID
, &prefs_default_search_
->sync_guid
);
328 url_dict
->GetString(kSuggestionsURL
, &prefs_default_search_
->suggestions_url
);
329 url_dict
->GetString(kInstantURL
, &prefs_default_search_
->instant_url
);
330 url_dict
->GetString(kImageURL
, &prefs_default_search_
->image_url
);
331 url_dict
->GetString(kNewTabURL
, &prefs_default_search_
->new_tab_url
);
333 std::string favicon_url
;
334 std::string originating_url
;
335 url_dict
->GetString(kFaviconURL
, &favicon_url
);
336 url_dict
->GetString(kOriginatingURL
, &originating_url
);
337 prefs_default_search_
->favicon_url
= GURL(favicon_url
);
338 prefs_default_search_
->originating_url
= GURL(originating_url
);
340 url_dict
->GetString(kSearchURLPostParams
,
341 &prefs_default_search_
->search_url_post_params
);
342 url_dict
->GetString(kSuggestionsURLPostParams
,
343 &prefs_default_search_
->suggestions_url_post_params
);
344 url_dict
->GetString(kInstantURLPostParams
,
345 &prefs_default_search_
->instant_url_post_params
);
346 url_dict
->GetString(kImageURLPostParams
,
347 &prefs_default_search_
->image_url_post_params
);
349 url_dict
->GetBoolean(kSafeForAutoReplace
,
350 &prefs_default_search_
->safe_for_autoreplace
);
352 std::string date_created_str
;
353 std::string last_modified_str
;
354 url_dict
->GetString(kDateCreated
, &date_created_str
);
355 url_dict
->GetString(kLastModified
, &last_modified_str
);
357 int64 date_created
= 0;
358 if (base::StringToInt64(date_created_str
, &date_created
)) {
359 prefs_default_search_
->date_created
=
360 base::Time::FromInternalValue(date_created
);
363 int64 last_modified
= 0;
364 if (base::StringToInt64(date_created_str
, &last_modified
)) {
365 prefs_default_search_
->last_modified
=
366 base::Time::FromInternalValue(last_modified
);
369 url_dict
->GetInteger(kUsageCount
, &prefs_default_search_
->usage_count
);
371 const base::ListValue
* alternate_urls
= NULL
;
372 if (url_dict
->GetList(kAlternateURLs
, &alternate_urls
)) {
373 for (base::ListValue::const_iterator it
= alternate_urls
->begin();
374 it
!= alternate_urls
->end();
376 std::string alternate_url
;
377 if ((*it
)->GetAsString(&alternate_url
))
378 prefs_default_search_
->alternate_urls
.push_back(alternate_url
);
382 const base::ListValue
* encodings
= NULL
;
383 if (url_dict
->GetList(kInputEncodings
, &encodings
)) {
384 for (base::ListValue::const_iterator it
= encodings
->begin();
385 it
!= encodings
->end();
387 std::string encoding
;
388 if ((*it
)->GetAsString(&encoding
))
389 prefs_default_search_
->input_encodings
.push_back(encoding
);
393 url_dict
->GetString(kSearchTermsReplacementKey
,
394 &prefs_default_search_
->search_terms_replacement_key
);
396 url_dict
->GetBoolean(kCreatedByPolicy
,
397 &prefs_default_search_
->created_by_policy
);
399 prefs_default_search_
->show_in_default_list
= true;
400 MergePrefsDataWithPrepopulated();
403 void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
404 scoped_ptr
<TemplateURLData
> data
=
405 TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_
);
406 fallback_default_search_
= data
.Pass();
407 MergePrefsDataWithPrepopulated();
410 void DefaultSearchManager::NotifyObserver() {
411 if (!change_observer_
.is_null()) {
412 Source source
= FROM_FALLBACK
;
413 TemplateURLData
* data
= GetDefaultSearchEngine(&source
);
414 change_observer_
.Run(data
, source
);