1 // Copyright 2012 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 "ios/chrome/browser/search_engines/search_engines_util.h"
7 #include "base/message_loop/message_loop.h"
8 #include "base/prefs/pref_service.h"
9 #include "components/search_engines/search_engines_pref_names.h"
10 #include "components/search_engines/template_url_prepopulate_data.h"
11 #include "components/search_engines/template_url_service.h"
12 #include "components/search_engines/template_url_service_observer.h"
16 // Id of the google id in template_url_prepopulate_data.cc.
17 static const int kGoogleEnginePrepopulatedId
= 1;
19 // Update the search engine of the given service to the default ones for the
21 void UpdateSearchEngine(TemplateURLService
* service
) {
23 DCHECK(service
->loaded());
24 std::vector
<TemplateURL
*> old_engines
= service
->GetTemplateURLs();
25 size_t default_engine
;
26 ScopedVector
<TemplateURLData
> new_engines
=
27 TemplateURLPrepopulateData::GetPrepopulatedEngines(nullptr,
29 DCHECK(default_engine
== 0);
30 DCHECK(new_engines
[0]->prepopulate_id
== kGoogleEnginePrepopulatedId
);
31 // The aim is to replace the old search engines with the new ones.
32 // It is not possible to remove all of them, because removing the current
33 // selected engine is not allowed.
34 // It is not possible to add all the new ones first, because the service gets
35 // confused when a prepopulated engine is there more than once.
36 // Instead, this will in a first pass makes google as the default engine. In
37 // a second pass, it will remove all other search engine. At last, in a third
38 // pass, it will add all new engine but google.
39 for (const auto& engine
: old_engines
) {
40 if (engine
->prepopulate_id() == kGoogleEnginePrepopulatedId
)
41 service
->SetUserSelectedDefaultSearchProvider(engine
);
43 for (const auto& engine
: old_engines
) {
44 if (engine
->prepopulate_id() != kGoogleEnginePrepopulatedId
)
45 service
->Remove(engine
);
47 ScopedVector
<TemplateURLData
>::iterator it
= new_engines
.begin();
48 while (it
!= new_engines
.end()) {
49 if ((*it
)->prepopulate_id
!= kGoogleEnginePrepopulatedId
) {
50 // service->Add takes ownership on Added TemplateURL.
51 service
->Add(new TemplateURL(**it
));
52 it
= new_engines
.weak_erase(it
);
59 // Observer class that allows to wait for the TemplateURLService to be loaded.
60 // This class will delete itself as soon as the TemplateURLService is loaded.
61 class LoadedObserver
: public TemplateURLServiceObserver
{
63 explicit LoadedObserver(TemplateURLService
* service
) : service_(service
) {
65 DCHECK(!service_
->loaded());
66 service_
->AddObserver(this);
70 ~LoadedObserver() override
{ service_
->RemoveObserver(this); }
72 void OnTemplateURLServiceChanged() override
{
73 service_
->RemoveObserver(this);
74 UpdateSearchEngine(service_
);
75 // Only delete this class when this callback is finished.
76 base::MessageLoop::current()->DeleteSoon(FROM_HERE
, this);
80 TemplateURLService
* service_
;
85 namespace search_engines
{
87 void UpdateSearchEnginesIfNeeded(PrefService
* preferences
,
88 TemplateURLService
* service
) {
89 if (!preferences
->HasPrefPath(prefs::kCountryIDAtInstall
)) {
90 // No search engines were ever installed, just return.
93 int old_country_id
= preferences
->GetInteger(prefs::kCountryIDAtInstall
);
94 int country_id
= TemplateURLPrepopulateData::GetCurrentCountryID();
95 if (country_id
== old_country_id
) {
96 // User's locale did not change, just return.
99 preferences
->SetInteger(prefs::kCountryIDAtInstall
, country_id
);
100 // If the current search engine is managed by policy then we can't set the
101 // default search engine, which is required by UpdateSearchEngine(). This
102 // isn't a problem as long as the default search engine is enforced via
103 // policy, because it can't be changed by the user anyway; if the policy is
104 // removed then the engines can be updated again.
105 if (!service
|| service
->is_default_search_managed())
107 if (service
->loaded())
108 UpdateSearchEngine(service
);
110 new LoadedObserver(service
); // The observer manages its own lifetime.
113 } // namespace search_engines