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 "chrome/browser/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 "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/search_engines/template_url.h"
25 #include "chrome/browser/search_engines/template_url_prepopulate_data.h"
26 #include "chrome/browser/search_engines/template_url_service.h"
27 #include "chrome/browser/search_engines/util.h"
28 #include "chrome/common/pref_names.h"
29 #include "components/user_prefs/pref_registry_syncable.h"
31 // A dictionary to hold all data related to the Default Search Engine.
32 // Eventually, this should replace all the data stored in the
33 // default_search_provider.* prefs.
34 const char DefaultSearchManager::kDefaultSearchProviderDataPrefName
[] =
35 "default_search_provider_data.template_url_data";
37 const char DefaultSearchManager::kID
[] = "id";
38 const char DefaultSearchManager::kShortName
[] = "short_name";
39 const char DefaultSearchManager::kKeyword
[] = "keyword";
40 const char DefaultSearchManager::kPrepopulateID
[] = "prepopulate_id";
41 const char DefaultSearchManager::kSyncGUID
[] = "synced_guid";
43 const char DefaultSearchManager::kURL
[] = "url";
44 const char DefaultSearchManager::kSuggestionsURL
[] = "suggestions_url";
45 const char DefaultSearchManager::kInstantURL
[] = "instant_url";
46 const char DefaultSearchManager::kImageURL
[] = "image_url";
47 const char DefaultSearchManager::kNewTabURL
[] = "new_tab_url";
48 const char DefaultSearchManager::kFaviconURL
[] = "favicon_url";
49 const char DefaultSearchManager::kOriginatingURL
[] = "originating_url";
51 const char DefaultSearchManager::kSearchURLPostParams
[] =
52 "search_url_post_params";
53 const char DefaultSearchManager::kSuggestionsURLPostParams
[] =
54 "suggestions_url_post_params";
55 const char DefaultSearchManager::kInstantURLPostParams
[] =
56 "instant_url_post_params";
57 const char DefaultSearchManager::kImageURLPostParams
[] =
58 "image_url_post_params";
60 const char DefaultSearchManager::kSafeForAutoReplace
[] = "safe_for_autoreplace";
61 const char DefaultSearchManager::kInputEncodings
[] = "input_encodings";
63 const char DefaultSearchManager::kDateCreated
[] = "date_created";
64 const char DefaultSearchManager::kLastModified
[] = "last_modified";
66 const char DefaultSearchManager::kUsageCount
[] = "usage_count";
67 const char DefaultSearchManager::kAlternateURLs
[] = "alternate_urls";
68 const char DefaultSearchManager::kSearchTermsReplacementKey
[] =
69 "search_terms_replacement_key";
70 const char DefaultSearchManager::kCreatedByPolicy
[] = "created_by_policy";
71 const char DefaultSearchManager::kDisabledByPolicy
[] = "disabled_by_policy";
73 DefaultSearchManager::DefaultSearchManager(
74 PrefService
* pref_service
,
75 const ObserverCallback
& change_observer
)
76 : pref_service_(pref_service
),
77 change_observer_(change_observer
),
78 default_search_controlled_by_policy_(false) {
80 pref_change_registrar_
.Init(pref_service_
);
81 pref_change_registrar_
.Add(
82 kDefaultSearchProviderDataPrefName
,
83 base::Bind(&DefaultSearchManager::OnDefaultSearchPrefChanged
,
84 base::Unretained(this)));
85 pref_change_registrar_
.Add(
86 prefs::kSearchProviderOverrides
,
87 base::Bind(&DefaultSearchManager::OnOverridesPrefChanged
,
88 base::Unretained(this)));
90 LoadPrepopulatedDefaultSearch();
91 LoadDefaultSearchEngineFromPrefs();
94 DefaultSearchManager::~DefaultSearchManager() {
98 void DefaultSearchManager::RegisterProfilePrefs(
99 user_prefs::PrefRegistrySyncable
* registry
) {
100 registry
->RegisterDictionaryPref(
101 kDefaultSearchProviderDataPrefName
,
102 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF
);
106 void DefaultSearchManager::AddPrefValueToMap(base::DictionaryValue
* value
,
107 PrefValueMap
* pref_value_map
) {
108 pref_value_map
->SetValue(kDefaultSearchProviderDataPrefName
, value
);
111 TemplateURLData
* DefaultSearchManager::GetDefaultSearchEngine(
112 Source
* source
) const {
113 if (default_search_controlled_by_policy_
) {
115 *source
= FROM_POLICY
;
116 return prefs_default_search_
.get();
118 if (extension_default_search_
) {
120 *source
= FROM_EXTENSION
;
121 return extension_default_search_
.get();
123 if (prefs_default_search_
) {
126 return prefs_default_search_
.get();
130 *source
= FROM_FALLBACK
;
131 return fallback_default_search_
.get();
134 DefaultSearchManager::Source
135 DefaultSearchManager::GetDefaultSearchEngineSource() const {
137 GetDefaultSearchEngine(&source
);
141 void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
142 const TemplateURLData
& data
) {
143 if (!pref_service_
) {
144 prefs_default_search_
.reset(new TemplateURLData(data
));
145 MergePrefsDataWithPrepopulated();
150 base::DictionaryValue url_dict
;
151 url_dict
.SetString(kID
, base::Int64ToString(data
.id
));
152 url_dict
.SetString(kShortName
, data
.short_name
);
153 url_dict
.SetString(kKeyword
, data
.keyword());
154 url_dict
.SetInteger(kPrepopulateID
, data
.prepopulate_id
);
155 url_dict
.SetString(kSyncGUID
, data
.sync_guid
);
157 url_dict
.SetString(kURL
, data
.url());
158 url_dict
.SetString(kSuggestionsURL
, data
.suggestions_url
);
159 url_dict
.SetString(kInstantURL
, data
.instant_url
);
160 url_dict
.SetString(kImageURL
, data
.image_url
);
161 url_dict
.SetString(kNewTabURL
, data
.new_tab_url
);
162 url_dict
.SetString(kFaviconURL
, data
.favicon_url
.spec());
163 url_dict
.SetString(kOriginatingURL
, data
.originating_url
.spec());
165 url_dict
.SetString(kSearchURLPostParams
, data
.search_url_post_params
);
166 url_dict
.SetString(kSuggestionsURLPostParams
,
167 data
.suggestions_url_post_params
);
168 url_dict
.SetString(kInstantURLPostParams
, data
.instant_url_post_params
);
169 url_dict
.SetString(kImageURLPostParams
, data
.image_url_post_params
);
171 url_dict
.SetBoolean(kSafeForAutoReplace
, data
.safe_for_autoreplace
);
173 url_dict
.SetString(kDateCreated
,
174 base::Int64ToString(data
.date_created
.ToInternalValue()));
175 url_dict
.SetString(kLastModified
,
176 base::Int64ToString(data
.last_modified
.ToInternalValue()));
177 url_dict
.SetInteger(kUsageCount
, data
.usage_count
);
179 scoped_ptr
<base::ListValue
> alternate_urls(new base::ListValue
);
180 for (std::vector
<std::string
>::const_iterator it
=
181 data
.alternate_urls
.begin();
182 it
!= data
.alternate_urls
.end(); ++it
) {
183 alternate_urls
->AppendString(*it
);
185 url_dict
.Set(kAlternateURLs
, alternate_urls
.release());
187 scoped_ptr
<base::ListValue
> encodings(new base::ListValue
);
188 for (std::vector
<std::string
>::const_iterator it
=
189 data
.input_encodings
.begin();
190 it
!= data
.input_encodings
.end(); ++it
) {
191 encodings
->AppendString(*it
);
193 url_dict
.Set(kInputEncodings
, encodings
.release());
195 url_dict
.SetString(kSearchTermsReplacementKey
,
196 data
.search_terms_replacement_key
);
198 url_dict
.SetBoolean(kCreatedByPolicy
, data
.created_by_policy
);
200 pref_service_
->Set(kDefaultSearchProviderDataPrefName
, url_dict
);
203 void DefaultSearchManager::SetExtensionControlledDefaultSearchEngine(
204 const TemplateURLData
& data
) {
205 extension_default_search_
.reset(new TemplateURLData(data
));
206 if (GetDefaultSearchEngineSource() == FROM_EXTENSION
)
210 void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
211 Source old_source
= GetDefaultSearchEngineSource();
212 extension_default_search_
.reset();
213 if (old_source
== FROM_EXTENSION
)
217 void DefaultSearchManager::ClearUserSelectedDefaultSearchEngine() {
219 pref_service_
->ClearPref(kDefaultSearchProviderDataPrefName
);
221 prefs_default_search_
.reset();
226 void DefaultSearchManager::OnDefaultSearchPrefChanged() {
227 Source source
= GetDefaultSearchEngineSource();
228 LoadDefaultSearchEngineFromPrefs();
230 // If we were/are FROM_USER or FROM_POLICY the effective DSE may have changed.
231 if (source
!= FROM_USER
&& source
!= FROM_POLICY
)
232 source
= GetDefaultSearchEngineSource();
233 if (source
== FROM_USER
|| source
== FROM_POLICY
)
237 void DefaultSearchManager::OnOverridesPrefChanged() {
238 LoadPrepopulatedDefaultSearch();
240 TemplateURLData
* effective_data
= GetDefaultSearchEngine(NULL
);
241 if (effective_data
&& effective_data
->prepopulate_id
) {
242 // A user-selected, policy-selected or fallback pre-populated engine is
243 // active and may have changed with this event.
248 void DefaultSearchManager::MergePrefsDataWithPrepopulated() {
249 if (!prefs_default_search_
|| !prefs_default_search_
->prepopulate_id
)
252 size_t default_search_index
;
253 ScopedVector
<TemplateURLData
> prepopulated_urls
=
254 TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service_
,
255 &default_search_index
);
257 for (size_t i
= 0; i
< prepopulated_urls
.size(); ++i
) {
258 if (prepopulated_urls
[i
]->prepopulate_id
==
259 prefs_default_search_
->prepopulate_id
) {
260 if (!prefs_default_search_
->safe_for_autoreplace
) {
261 prepopulated_urls
[i
]->safe_for_autoreplace
= false;
262 prepopulated_urls
[i
]->SetKeyword(prefs_default_search_
->keyword());
263 prepopulated_urls
[i
]->short_name
= prefs_default_search_
->short_name
;
265 prepopulated_urls
[i
]->id
= prefs_default_search_
->id
;
266 prepopulated_urls
[i
]->sync_guid
= prefs_default_search_
->sync_guid
;
267 prepopulated_urls
[i
]->date_created
= prefs_default_search_
->date_created
;
268 prepopulated_urls
[i
]->last_modified
=
269 prefs_default_search_
->last_modified
;
270 prefs_default_search_
.reset(prepopulated_urls
[i
]);
271 prepopulated_urls
.weak_erase(prepopulated_urls
.begin() + i
);
277 void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
281 prefs_default_search_
.reset();
282 const PrefService::Preference
* pref
=
283 pref_service_
->FindPreference(kDefaultSearchProviderDataPrefName
);
285 default_search_controlled_by_policy_
= pref
->IsManaged();
287 const base::DictionaryValue
* url_dict
=
288 pref_service_
->GetDictionary(kDefaultSearchProviderDataPrefName
);
289 if (url_dict
->empty())
292 if (default_search_controlled_by_policy_
) {
293 bool disabled_by_policy
= false;
294 if (url_dict
->GetBoolean(kDisabledByPolicy
, &disabled_by_policy
) &&
299 std::string search_url
;
300 base::string16 keyword
;
301 url_dict
->GetString(kURL
, &search_url
);
302 url_dict
->GetString(kKeyword
, &keyword
);
303 if (search_url
.empty() || keyword
.empty())
306 prefs_default_search_
.reset(new TemplateURLData
);
307 prefs_default_search_
->SetKeyword(keyword
);
308 prefs_default_search_
->SetURL(search_url
);
311 url_dict
->GetString(kID
, &id
);
312 base::StringToInt64(id
, &prefs_default_search_
->id
);
313 url_dict
->GetString(kShortName
, &prefs_default_search_
->short_name
);
314 url_dict
->GetInteger(kPrepopulateID
, &prefs_default_search_
->prepopulate_id
);
315 url_dict
->GetString(kSyncGUID
, &prefs_default_search_
->sync_guid
);
317 url_dict
->GetString(kSuggestionsURL
, &prefs_default_search_
->suggestions_url
);
318 url_dict
->GetString(kInstantURL
, &prefs_default_search_
->instant_url
);
319 url_dict
->GetString(kImageURL
, &prefs_default_search_
->image_url
);
320 url_dict
->GetString(kNewTabURL
, &prefs_default_search_
->new_tab_url
);
322 std::string favicon_url
;
323 std::string originating_url
;
324 url_dict
->GetString(kFaviconURL
, &favicon_url
);
325 url_dict
->GetString(kOriginatingURL
, &originating_url
);
326 prefs_default_search_
->favicon_url
= GURL(favicon_url
);
327 prefs_default_search_
->originating_url
= GURL(originating_url
);
329 url_dict
->GetString(kSearchURLPostParams
,
330 &prefs_default_search_
->search_url_post_params
);
331 url_dict
->GetString(kSuggestionsURLPostParams
,
332 &prefs_default_search_
->suggestions_url_post_params
);
333 url_dict
->GetString(kInstantURLPostParams
,
334 &prefs_default_search_
->instant_url_post_params
);
335 url_dict
->GetString(kImageURLPostParams
,
336 &prefs_default_search_
->image_url_post_params
);
338 url_dict
->GetBoolean(kSafeForAutoReplace
,
339 &prefs_default_search_
->safe_for_autoreplace
);
341 std::string date_created_str
;
342 std::string last_modified_str
;
343 url_dict
->GetString(kDateCreated
, &date_created_str
);
344 url_dict
->GetString(kLastModified
, &last_modified_str
);
346 int64 date_created
= 0;
347 if (base::StringToInt64(date_created_str
, &date_created
)) {
348 prefs_default_search_
->date_created
=
349 base::Time::FromInternalValue(date_created
);
352 int64 last_modified
= 0;
353 if (base::StringToInt64(date_created_str
, &last_modified
)) {
354 prefs_default_search_
->last_modified
=
355 base::Time::FromInternalValue(last_modified
);
358 url_dict
->GetInteger(kUsageCount
, &prefs_default_search_
->usage_count
);
360 const base::ListValue
* alternate_urls
= NULL
;
361 if (url_dict
->GetList(kAlternateURLs
, &alternate_urls
)) {
362 for (base::ListValue::const_iterator it
= alternate_urls
->begin();
363 it
!= alternate_urls
->end();
365 std::string alternate_url
;
366 if ((*it
)->GetAsString(&alternate_url
))
367 prefs_default_search_
->alternate_urls
.push_back(alternate_url
);
371 const base::ListValue
* encodings
= NULL
;
372 if (url_dict
->GetList(kInputEncodings
, &encodings
)) {
373 for (base::ListValue::const_iterator it
= encodings
->begin();
374 it
!= encodings
->end();
376 std::string encoding
;
377 if ((*it
)->GetAsString(&encoding
))
378 prefs_default_search_
->input_encodings
.push_back(encoding
);
382 url_dict
->GetString(kSearchTermsReplacementKey
,
383 &prefs_default_search_
->search_terms_replacement_key
);
385 url_dict
->GetBoolean(kCreatedByPolicy
,
386 &prefs_default_search_
->created_by_policy
);
388 prefs_default_search_
->show_in_default_list
= true;
389 MergePrefsDataWithPrepopulated();
392 void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
393 scoped_ptr
<TemplateURLData
> data
=
394 TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_
);
395 fallback_default_search_
= data
.Pass();
396 MergePrefsDataWithPrepopulated();
399 void DefaultSearchManager::NotifyObserver() {
400 if (!change_observer_
.is_null()) {
401 Source source
= FROM_FALLBACK
;
402 TemplateURLData
* data
= GetDefaultSearchEngine(&source
);
403 change_observer_
.Run(data
, source
);