Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / ios / chrome / browser / search_engines / search_engines_util.cc
blobb7ef3160e63873333d48a535e558dc34fdd07066
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"
14 namespace {
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
20 // current locale.
21 void UpdateSearchEngine(TemplateURLService* service) {
22 DCHECK(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,
28 &default_engine);
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);
53 } else {
54 ++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 {
62 public:
63 explicit LoadedObserver(TemplateURLService* service) : service_(service) {
64 DCHECK(service_);
65 DCHECK(!service_->loaded());
66 service_->AddObserver(this);
67 service_->Load();
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);
79 private:
80 TemplateURLService* service_;
83 } // namespace
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.
91 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.
97 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())
106 return;
107 if (service->loaded())
108 UpdateSearchEngine(service);
109 else
110 new LoadedObserver(service); // The observer manages its own lifetime.
113 } // namespace search_engines