Commit 8abf4df0 authored by sdefresne's avatar sdefresne Committed by Commit bot

[iOS] Upstream UpdateSearchEnginesIfNeeded

On iOS when user chaneg the device locale, we update the list of search
engines keeping the currently selected search engine unchanged. This is
done by removing all other search engines, and then adding the new ones.

BUG=None

Review URL: https://codereview.chromium.org/1149623002

Cr-Commit-Position: refs/heads/master@{#330913}
parent 31b6277f
...@@ -12,6 +12,7 @@ include_rules = [ ...@@ -12,6 +12,7 @@ include_rules = [
"+components/keyed_service/ios", "+components/keyed_service/ios",
"+components/leveldb_proto", "+components/leveldb_proto",
"+components/pref_registry", "+components/pref_registry",
"+components/search_engines",
"+components/suggestions", "+components/suggestions",
"+components/sync_driver", "+components/sync_driver",
"+components/translate/core", "+components/translate/core",
......
// 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
// 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.
#ifndef IOS_CHROME_BROWSER_SEARCH_ENGINES_SEARCH_ENGINES_UTIL_H_
#define IOS_CHROME_BROWSER_SEARCH_ENGINES_SEARCH_ENGINES_UTIL_H_
class PrefService;
class TemplateURLService;
namespace search_engines {
// Updates the current search engine, as well as the list of available search
// engines if the locale of the user changed.
// TODO(ios): Once user can customize search engines ( http://crbug.com/153047 )
// remove this method.
void UpdateSearchEnginesIfNeeded(PrefService* preferences,
TemplateURLService* service);
} // namespace search_engines
#endif // IOS_CHROME_BROWSER_SEARCH_ENGINES_SEARCH_ENGINES_UTIL_H_
...@@ -54,10 +54,11 @@ ...@@ -54,10 +54,11 @@
'../../components/components.gyp:keyed_service_ios', '../../components/components.gyp:keyed_service_ios',
'../../components/components.gyp:leveldb_proto', '../../components/components.gyp:leveldb_proto',
'../../components/components.gyp:pref_registry', '../../components/components.gyp:pref_registry',
'../../components/components.gyp:search_engines',
'../../components/components.gyp:suggestions', '../../components/components.gyp:suggestions',
'../../components/components.gyp:sync_driver',
'../../components/components.gyp:translate_core_browser', '../../components/components.gyp:translate_core_browser',
'../../components/components.gyp:translate_ios_browser', '../../components/components.gyp:translate_ios_browser',
'../../components/components.gyp:sync_driver',
'../../components/components.gyp:web_resource', '../../components/components.gyp:web_resource',
'../../components/components.gyp:webp_transcode', '../../components/components.gyp:webp_transcode',
'../../components/components_strings.gyp:components_strings', '../../components/components_strings.gyp:components_strings',
...@@ -94,6 +95,8 @@ ...@@ -94,6 +95,8 @@
'browser/application_context_impl.h', 'browser/application_context_impl.h',
'browser/arch_util.cc', 'browser/arch_util.cc',
'browser/arch_util.h', 'browser/arch_util.h',
'browser/search_engines/search_engines_util.cc',
'browser/search_engines/search_engines_util.h',
'browser/authentication/constants.h', 'browser/authentication/constants.h',
'browser/authentication/constants.mm', 'browser/authentication/constants.mm',
'browser/autofill/autofill_agent_utils.h', 'browser/autofill/autofill_agent_utils.h',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment