| // 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 <stddef.h> |
| |
| #include <memory> |
| |
| #include "base/location.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "components/country_codes/country_codes.h" |
| #include "components/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; |
| std::vector<std::unique_ptr<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 engines. At last, in a third |
| // pass, it will add all new engines but google. |
| for (auto* engine : old_engines) { |
| if (engine->prepopulate_id() == kGoogleEnginePrepopulatedId) |
| service->SetUserSelectedDefaultSearchProvider(engine); |
| } |
| for (auto* engine : old_engines) { |
| if (engine->prepopulate_id() != kGoogleEnginePrepopulatedId) |
| service->Remove(engine); |
| } |
| for (const auto& engine : new_engines) { |
| if (engine->prepopulate_id != kGoogleEnginePrepopulatedId) |
| service->Add(std::make_unique<TemplateURL>(*engine)); |
| } |
| } |
| |
| // 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::ThreadTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); |
| } |
| |
| private: |
| TemplateURLService* service_; |
| }; |
| |
| } // namespace |
| |
| namespace search_engines { |
| |
| void UpdateSearchEnginesIfNeeded(PrefService* preferences, |
| TemplateURLService* service) { |
| if (!preferences->HasPrefPath(country_codes::kCountryIDAtInstall)) { |
| // No search engines were ever installed, just return. |
| return; |
| } |
| int old_country_id = |
| preferences->GetInteger(country_codes::kCountryIDAtInstall); |
| int country_id = country_codes::GetCurrentCountryID(); |
| if (country_id == old_country_id) { |
| // User's locale did not change, just return. |
| return; |
| } |
| preferences->SetInteger(country_codes::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. |
| } |
| |
| bool SupportsSearchByImage(TemplateURLService* service) { |
| const TemplateURL* default_url = service->GetDefaultSearchProvider(); |
| return default_url && !default_url->image_url().empty() && |
| default_url->image_url_ref().IsValid(service->search_terms_data()); |
| } |
| |
| } // namespace search_engines |