| Index: ios/chrome/browser/search_engines/search_engines_util.cc
|
| diff --git a/ios/chrome/browser/search_engines/search_engines_util.cc b/ios/chrome/browser/search_engines/search_engines_util.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..b7ef3160e63873333d48a535e558dc34fdd07066
|
| --- /dev/null
|
| +++ b/ios/chrome/browser/search_engines/search_engines_util.cc
|
| @@ -0,0 +1,113 @@
|
| +// Copyright 2012 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ios/chrome/browser/search_engines/search_engines_util.h"
|
| +
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "base/prefs/pref_service.h"
|
| +#include "components/search_engines/search_engines_pref_names.h"
|
| +#include "components/search_engines/template_url_prepopulate_data.h"
|
| +#include "components/search_engines/template_url_service.h"
|
| +#include "components/search_engines/template_url_service_observer.h"
|
| +
|
| +namespace {
|
| +
|
| +// Id of the google id in template_url_prepopulate_data.cc.
|
| +static const int kGoogleEnginePrepopulatedId = 1;
|
| +
|
| +// Update the search engine of the given service to the default ones for the
|
| +// current locale.
|
| +void UpdateSearchEngine(TemplateURLService* service) {
|
| + DCHECK(service);
|
| + DCHECK(service->loaded());
|
| + std::vector<TemplateURL*> old_engines = service->GetTemplateURLs();
|
| + size_t default_engine;
|
| + ScopedVector<TemplateURLData> new_engines =
|
| + TemplateURLPrepopulateData::GetPrepopulatedEngines(nullptr,
|
| + &default_engine);
|
| + DCHECK(default_engine == 0);
|
| + DCHECK(new_engines[0]->prepopulate_id == kGoogleEnginePrepopulatedId);
|
| + // The aim is to replace the old search engines with the new ones.
|
| + // It is not possible to remove all of them, because removing the current
|
| + // selected engine is not allowed.
|
| + // It is not possible to add all the new ones first, because the service gets
|
| + // confused when a prepopulated engine is there more than once.
|
| + // Instead, this will in a first pass makes google as the default engine. In
|
| + // a second pass, it will remove all other search engine. At last, in a third
|
| + // pass, it will add all new engine but google.
|
| + for (const auto& engine : old_engines) {
|
| + if (engine->prepopulate_id() == kGoogleEnginePrepopulatedId)
|
| + service->SetUserSelectedDefaultSearchProvider(engine);
|
| + }
|
| + for (const auto& engine : old_engines) {
|
| + if (engine->prepopulate_id() != kGoogleEnginePrepopulatedId)
|
| + service->Remove(engine);
|
| + }
|
| + ScopedVector<TemplateURLData>::iterator it = new_engines.begin();
|
| + while (it != new_engines.end()) {
|
| + if ((*it)->prepopulate_id != kGoogleEnginePrepopulatedId) {
|
| + // service->Add takes ownership on Added TemplateURL.
|
| + service->Add(new TemplateURL(**it));
|
| + it = new_engines.weak_erase(it);
|
| + } else {
|
| + ++it;
|
| + }
|
| + }
|
| +}
|
| +
|
| +// Observer class that allows to wait for the TemplateURLService to be loaded.
|
| +// This class will delete itself as soon as the TemplateURLService is loaded.
|
| +class LoadedObserver : public TemplateURLServiceObserver {
|
| + public:
|
| + explicit LoadedObserver(TemplateURLService* service) : service_(service) {
|
| + DCHECK(service_);
|
| + DCHECK(!service_->loaded());
|
| + service_->AddObserver(this);
|
| + service_->Load();
|
| + }
|
| +
|
| + ~LoadedObserver() override { service_->RemoveObserver(this); }
|
| +
|
| + void OnTemplateURLServiceChanged() override {
|
| + service_->RemoveObserver(this);
|
| + UpdateSearchEngine(service_);
|
| + // Only delete this class when this callback is finished.
|
| + base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
|
| + }
|
| +
|
| + private:
|
| + TemplateURLService* service_;
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +namespace search_engines {
|
| +
|
| +void UpdateSearchEnginesIfNeeded(PrefService* preferences,
|
| + TemplateURLService* service) {
|
| + if (!preferences->HasPrefPath(prefs::kCountryIDAtInstall)) {
|
| + // No search engines were ever installed, just return.
|
| + return;
|
| + }
|
| + int old_country_id = preferences->GetInteger(prefs::kCountryIDAtInstall);
|
| + int country_id = TemplateURLPrepopulateData::GetCurrentCountryID();
|
| + if (country_id == old_country_id) {
|
| + // User's locale did not change, just return.
|
| + return;
|
| + }
|
| + preferences->SetInteger(prefs::kCountryIDAtInstall, country_id);
|
| + // If the current search engine is managed by policy then we can't set the
|
| + // default search engine, which is required by UpdateSearchEngine(). This
|
| + // isn't a problem as long as the default search engine is enforced via
|
| + // policy, because it can't be changed by the user anyway; if the policy is
|
| + // removed then the engines can be updated again.
|
| + if (!service || service->is_default_search_managed())
|
| + return;
|
| + if (service->loaded())
|
| + UpdateSearchEngine(service);
|
| + else
|
| + new LoadedObserver(service); // The observer manages its own lifetime.
|
| +}
|
| +
|
| +} // namespace search_engines
|
|
|