Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / settings_overrides / settings_overrides_api.cc
blobc1cec39f89306b52ff4a802448125488bc7e4b94
1 // Copyright 2013 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 "chrome/browser/extensions/api/settings_overrides/settings_overrides_api.h"
7 #include "base/lazy_instance.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/api/preference/preference_api.h"
10 #include "chrome/browser/prefs/session_startup_pref.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/search_engines/template_url_service_factory.h"
13 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
14 #include "chrome/common/pref_names.h"
15 #include "components/search_engines/search_engines_pref_names.h"
16 #include "components/search_engines/template_url.h"
17 #include "components/search_engines/template_url_prepopulate_data.h"
18 #include "extensions/browser/extension_prefs.h"
19 #include "extensions/browser/extension_prefs_factory.h"
20 #include "extensions/browser/extension_registry.h"
21 #include "extensions/common/error_utils.h"
22 #include "extensions/common/manifest_constants.h"
24 namespace extensions {
26 namespace {
28 base::LazyInstance<BrowserContextKeyedAPIFactory<SettingsOverridesAPI> >
29 g_factory = LAZY_INSTANCE_INITIALIZER;
31 const char kManyStartupPagesWarning[] = "* specifies more than 1 startup URL. "
32 "All but the first will be ignored.";
34 using api::manifest_types::ChromeSettingsOverrides;
36 std::string SubstituteInstallParam(std::string str,
37 const std::string& install_parameter) {
38 base::ReplaceSubstringsAfterOffset(&str, 0, "__PARAM__", install_parameter);
39 return str;
42 // Find the prepopulated search engine with the given id.
43 bool GetPrepopulatedSearchProvider(PrefService* prefs,
44 int prepopulated_id,
45 TemplateURLData* data) {
46 DCHECK(data);
47 size_t default_index;
48 ScopedVector<TemplateURLData> engines =
49 TemplateURLPrepopulateData::GetPrepopulatedEngines(prefs, &default_index);
50 for (ScopedVector<TemplateURLData>::iterator i = engines.begin();
51 i != engines.end();
52 ++i) {
53 if ((*i)->prepopulate_id == prepopulated_id) {
54 *data = **i;
55 return true;
58 return false;
61 TemplateURLData ConvertSearchProvider(
62 PrefService* prefs,
63 const ChromeSettingsOverrides::Search_provider& search_provider,
64 const std::string& install_parameter) {
65 TemplateURLData data;
66 if (search_provider.prepopulated_id) {
67 if (!GetPrepopulatedSearchProvider(prefs, *search_provider.prepopulated_id,
68 &data)) {
69 VLOG(1) << "Settings Overrides API can't recognize prepopulated_id="
70 << *search_provider.prepopulated_id;
74 if (search_provider.name)
75 data.SetShortName(base::UTF8ToUTF16(*search_provider.name));
76 if (search_provider.keyword)
77 data.SetKeyword(base::UTF8ToUTF16(*search_provider.keyword));
78 data.SetURL(SubstituteInstallParam(search_provider.search_url,
79 install_parameter));
80 if (search_provider.suggest_url) {
81 data.suggestions_url =
82 SubstituteInstallParam(*search_provider.suggest_url, install_parameter);
84 if (search_provider.instant_url) {
85 data.instant_url =
86 SubstituteInstallParam(*search_provider.instant_url, install_parameter);
88 if (search_provider.image_url) {
89 data.image_url =
90 SubstituteInstallParam(*search_provider.image_url, install_parameter);
92 if (search_provider.search_url_post_params)
93 data.search_url_post_params = *search_provider.search_url_post_params;
94 if (search_provider.suggest_url_post_params)
95 data.suggestions_url_post_params = *search_provider.suggest_url_post_params;
96 if (search_provider.instant_url_post_params)
97 data.instant_url_post_params = *search_provider.instant_url_post_params;
98 if (search_provider.image_url_post_params)
99 data.image_url_post_params = *search_provider.image_url_post_params;
100 if (search_provider.favicon_url) {
101 data.favicon_url = GURL(SubstituteInstallParam(*search_provider.favicon_url,
102 install_parameter));
104 data.safe_for_autoreplace = false;
105 if (search_provider.encoding) {
106 data.input_encodings.clear();
107 data.input_encodings.push_back(*search_provider.encoding);
109 data.date_created = base::Time();
110 data.last_modified = base::Time();
111 data.prepopulate_id = 0;
112 if (search_provider.alternate_urls) {
113 data.alternate_urls.clear();
114 for (size_t i = 0; i < search_provider.alternate_urls->size(); ++i) {
115 if (!search_provider.alternate_urls->at(i).empty())
116 data.alternate_urls.push_back(SubstituteInstallParam(
117 search_provider.alternate_urls->at(i), install_parameter));
120 return data;
123 } // namespace
125 SettingsOverridesAPI::SettingsOverridesAPI(content::BrowserContext* context)
126 : profile_(Profile::FromBrowserContext(context)),
127 url_service_(TemplateURLServiceFactory::GetForProfile(profile_)),
128 extension_registry_observer_(this) {
129 extension_registry_observer_.Add(ExtensionRegistry::Get(profile_));
132 SettingsOverridesAPI::~SettingsOverridesAPI() {
135 BrowserContextKeyedAPIFactory<SettingsOverridesAPI>*
136 SettingsOverridesAPI::GetFactoryInstance() {
137 return g_factory.Pointer();
140 void SettingsOverridesAPI::SetPref(const std::string& extension_id,
141 const std::string& pref_key,
142 base::Value* value) {
143 PreferenceAPI* prefs = PreferenceAPI::Get(profile_);
144 if (!prefs)
145 return; // Expected in unit tests.
146 prefs->SetExtensionControlledPref(extension_id,
147 pref_key,
148 kExtensionPrefsScopeRegular,
149 value);
152 void SettingsOverridesAPI::UnsetPref(const std::string& extension_id,
153 const std::string& pref_key) {
154 PreferenceAPI* prefs = PreferenceAPI::Get(profile_);
155 if (!prefs)
156 return; // Expected in unit tests.
157 prefs->RemoveExtensionControlledPref(
158 extension_id,
159 pref_key,
160 kExtensionPrefsScopeRegular);
163 void SettingsOverridesAPI::OnExtensionLoaded(
164 content::BrowserContext* browser_context,
165 const Extension* extension) {
166 const SettingsOverrides* settings = SettingsOverrides::Get(extension);
167 if (settings) {
168 std::string install_parameter =
169 ExtensionPrefs::Get(profile_)->GetInstallParam(extension->id());
170 if (settings->homepage) {
171 SetPref(extension->id(),
172 prefs::kHomePage,
173 new base::StringValue(SubstituteInstallParam(
174 settings->homepage->spec(), install_parameter)));
175 SetPref(extension->id(),
176 prefs::kHomePageIsNewTabPage,
177 new base::FundamentalValue(false));
179 if (!settings->startup_pages.empty()) {
180 SetPref(extension->id(),
181 prefs::kRestoreOnStartup,
182 new base::FundamentalValue(SessionStartupPref::kPrefValueURLs));
183 if (settings->startup_pages.size() > 1) {
184 VLOG(1) << extensions::ErrorUtils::FormatErrorMessage(
185 kManyStartupPagesWarning,
186 manifest_keys::kSettingsOverride);
188 scoped_ptr<base::ListValue> url_list(new base::ListValue);
189 url_list->Append(new base::StringValue(SubstituteInstallParam(
190 settings->startup_pages[0].spec(), install_parameter)));
191 SetPref(
192 extension->id(), prefs::kURLsToRestoreOnStartup, url_list.release());
194 if (settings->search_engine) {
195 // Bring the preference to the correct state. Before this code set it
196 // to "true" for all search engines. Thus, we should overwrite it for
197 // all search engines.
198 if (settings->search_engine->is_default) {
199 SetPref(extension->id(),
200 prefs::kDefaultSearchProviderEnabled,
201 new base::FundamentalValue(true));
202 } else {
203 UnsetPref(extension->id(), prefs::kDefaultSearchProviderEnabled);
205 DCHECK(url_service_);
206 if (url_service_->loaded()) {
207 RegisterSearchProvider(extension);
208 } else {
209 if (!template_url_sub_) {
210 template_url_sub_ = url_service_->RegisterOnLoadedCallback(
211 base::Bind(&SettingsOverridesAPI::OnTemplateURLsLoaded,
212 base::Unretained(this)));
214 url_service_->Load();
215 pending_extensions_.insert(extension);
220 void SettingsOverridesAPI::OnExtensionUnloaded(
221 content::BrowserContext* browser_context,
222 const Extension* extension,
223 UnloadedExtensionInfo::Reason reason) {
224 const SettingsOverrides* settings = SettingsOverrides::Get(extension);
225 if (settings) {
226 if (settings->homepage) {
227 UnsetPref(extension->id(), prefs::kHomePage);
228 UnsetPref(extension->id(), prefs::kHomePageIsNewTabPage);
230 if (!settings->startup_pages.empty()) {
231 UnsetPref(extension->id(), prefs::kRestoreOnStartup);
232 UnsetPref(extension->id(), prefs::kURLsToRestoreOnStartup);
234 if (settings->search_engine) {
235 DCHECK(url_service_);
236 if (url_service_->loaded()) {
237 url_service_->RemoveExtensionControlledTURL(
238 extension->id(), TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION);
239 } else {
240 pending_extensions_.erase(extension);
246 void SettingsOverridesAPI::Shutdown() {
247 template_url_sub_.reset();
250 void SettingsOverridesAPI::OnTemplateURLsLoaded() {
251 // Register search providers for pending extensions.
252 template_url_sub_.reset();
253 for (PendingExtensions::const_iterator i(pending_extensions_.begin());
254 i != pending_extensions_.end(); ++i) {
255 RegisterSearchProvider(i->get());
257 pending_extensions_.clear();
260 void SettingsOverridesAPI::RegisterSearchProvider(
261 const Extension* extension) const {
262 DCHECK(url_service_);
263 DCHECK(extension);
264 const SettingsOverrides* settings = SettingsOverrides::Get(extension);
265 DCHECK(settings);
266 DCHECK(settings->search_engine);
267 scoped_ptr<TemplateURL::AssociatedExtensionInfo> info(
268 new TemplateURL::AssociatedExtensionInfo(
269 TemplateURL::NORMAL_CONTROLLED_BY_EXTENSION, extension->id()));
270 info->wants_to_be_default_engine = settings->search_engine->is_default;
271 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
272 info->install_time = prefs->GetInstallTime(extension->id());
273 std::string install_parameter = prefs->GetInstallParam(extension->id());
274 TemplateURLData data = ConvertSearchProvider(
275 profile_->GetPrefs(), *settings->search_engine, install_parameter);
276 data.show_in_default_list = info->wants_to_be_default_engine;
277 url_service_->AddExtensionControlledTURL(new TemplateURL(data), info.Pass());
280 template <>
281 void BrowserContextKeyedAPIFactory<
282 SettingsOverridesAPI>::DeclareFactoryDependencies() {
283 DependsOn(ExtensionPrefsFactory::GetInstance());
284 DependsOn(PreferenceAPI::GetFactoryInstance());
285 DependsOn(TemplateURLServiceFactory::GetInstance());
288 } // namespace extensions