Add unit test for the Settings API Bubble.
[chromium-blink-merge.git] / chrome / browser / extensions / api / settings_overrides / settings_overrides_api.cc
blobfe310902c66b0ac84178b11c22f0ebfa097aa5a5
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/chrome_notification_types.h"
10 #include "chrome/browser/extensions/api/preference/preference_api.h"
11 #include "chrome/browser/prefs/session_startup_pref.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/search_engines/template_url.h"
14 #include "chrome/browser/search_engines/template_url_service_factory.h"
15 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
16 #include "chrome/common/pref_names.h"
17 #include "content/public/browser/notification_details.h"
18 #include "content/public/browser/notification_source.h"
19 #include "extensions/browser/extension_prefs.h"
20 #include "extensions/browser/extension_prefs_factory.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 ReplaceSubstringsAfterOffset(&str, 0, "__PARAM__", install_parameter);
39 return str;
42 TemplateURLData ConvertSearchProvider(
43 const ChromeSettingsOverrides::Search_provider& search_provider,
44 const std::string& install_parameter) {
45 TemplateURLData data;
47 data.short_name = base::UTF8ToUTF16(search_provider.name);
48 data.SetKeyword(base::UTF8ToUTF16(search_provider.keyword));
49 data.SetURL(
50 SubstituteInstallParam(search_provider.search_url, install_parameter));
51 if (search_provider.suggest_url) {
52 data.suggestions_url =
53 SubstituteInstallParam(*search_provider.suggest_url, install_parameter);
55 if (search_provider.instant_url) {
56 data.instant_url =
57 SubstituteInstallParam(*search_provider.instant_url, install_parameter);
59 if (search_provider.image_url) {
60 data.image_url =
61 SubstituteInstallParam(*search_provider.image_url, install_parameter);
63 if (search_provider.search_url_post_params)
64 data.search_url_post_params = *search_provider.search_url_post_params;
65 if (search_provider.suggest_url_post_params)
66 data.suggestions_url_post_params = *search_provider.suggest_url_post_params;
67 if (search_provider.instant_url_post_params)
68 data.instant_url_post_params = *search_provider.instant_url_post_params;
69 if (search_provider.image_url_post_params)
70 data.image_url_post_params = *search_provider.image_url_post_params;
71 data.favicon_url = GURL(
72 SubstituteInstallParam(search_provider.favicon_url, install_parameter));
73 data.show_in_default_list = true;
74 data.safe_for_autoreplace = false;
75 data.input_encodings.push_back(search_provider.encoding);
76 data.date_created = base::Time();
77 data.last_modified = base::Time();
78 data.prepopulate_id = 0;
79 if (search_provider.alternate_urls) {
80 for (size_t i = 0; i < search_provider.alternate_urls->size(); ++i) {
81 if (!search_provider.alternate_urls->at(i).empty())
82 data.alternate_urls.push_back(SubstituteInstallParam(
83 search_provider.alternate_urls->at(i), install_parameter));
86 return data;
89 } // namespace
91 SettingsOverridesAPI::SettingsOverridesAPI(content::BrowserContext* context)
92 : profile_(Profile::FromBrowserContext(context)),
93 url_service_(TemplateURLServiceFactory::GetForProfile(profile_)) {
94 DCHECK(profile_);
95 registrar_.Add(this,
96 chrome::NOTIFICATION_EXTENSION_LOADED,
97 content::Source<Profile>(profile_));
98 registrar_.Add(this,
99 chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
100 content::Source<Profile>(profile_));
103 SettingsOverridesAPI::~SettingsOverridesAPI() {
106 BrowserContextKeyedAPIFactory<SettingsOverridesAPI>*
107 SettingsOverridesAPI::GetFactoryInstance() {
108 return g_factory.Pointer();
111 void SettingsOverridesAPI::SetPref(const std::string& extension_id,
112 const std::string& pref_key,
113 base::Value* value) {
114 PreferenceAPI* prefs = PreferenceAPI::Get(profile_);
115 if (!prefs)
116 return; // Expected in unit tests.
117 prefs->SetExtensionControlledPref(extension_id,
118 pref_key,
119 kExtensionPrefsScopeRegular,
120 value);
123 void SettingsOverridesAPI::UnsetPref(const std::string& extension_id,
124 const std::string& pref_key) {
125 PreferenceAPI* prefs = PreferenceAPI::Get(profile_);
126 if (!prefs)
127 return; // Expected in unit tests.
128 prefs->RemoveExtensionControlledPref(
129 extension_id,
130 pref_key,
131 kExtensionPrefsScopeRegular);
134 void SettingsOverridesAPI::Observe(
135 int type,
136 const content::NotificationSource& source,
137 const content::NotificationDetails& details) {
138 switch (type) {
139 case chrome::NOTIFICATION_EXTENSION_LOADED: {
140 const Extension* extension =
141 content::Details<const Extension>(details).ptr();
142 const SettingsOverrides* settings =
143 SettingsOverrides::Get(extension);
144 if (settings) {
145 std::string install_parameter =
146 ExtensionPrefs::Get(profile_)->GetInstallParam(extension->id());
147 if (settings->homepage) {
148 SetPref(extension->id(),
149 prefs::kHomePage,
150 new base::StringValue(SubstituteInstallParam(
151 settings->homepage->spec(), install_parameter)));
152 SetPref(extension->id(), prefs::kHomePageIsNewTabPage,
153 new base::FundamentalValue(false));
155 if (!settings->startup_pages.empty()) {
156 SetPref(extension->id(), prefs::kRestoreOnStartup,
157 new base::FundamentalValue(
158 SessionStartupPref::kPrefValueURLs));
159 if (settings->startup_pages.size() > 1) {
160 VLOG(1) << extensions::ErrorUtils::FormatErrorMessage(
161 kManyStartupPagesWarning, manifest_keys::kSettingsOverride);
163 scoped_ptr<base::ListValue> url_list(new base::ListValue);
164 url_list->Append(new base::StringValue(SubstituteInstallParam(
165 settings->startup_pages[0].spec(), install_parameter)));
166 SetPref(extension->id(), prefs::kURLsToRestoreOnStartup,
167 url_list.release());
169 if (settings->search_engine) {
170 SetPref(extension->id(), prefs::kDefaultSearchProviderEnabled,
171 new base::FundamentalValue(true));
172 DCHECK(url_service_);
173 if (url_service_->loaded()) {
174 RegisterSearchProvider(extension);
175 } else {
176 if (!template_url_sub_) {
177 template_url_sub_ = url_service_->RegisterOnLoadedCallback(
178 base::Bind(&SettingsOverridesAPI::OnTemplateURLsLoaded,
179 base::Unretained(this)));
181 url_service_->Load();
182 pending_extensions_.insert(extension);
186 break;
188 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED: {
189 const Extension* extension =
190 content::Details<UnloadedExtensionInfo>(details)->extension;
191 const SettingsOverrides* settings = SettingsOverrides::Get(extension);
192 if (settings) {
193 if (settings->homepage) {
194 UnsetPref(extension->id(), prefs::kHomePage);
195 UnsetPref(extension->id(), prefs::kHomePageIsNewTabPage);
197 if (!settings->startup_pages.empty()) {
198 UnsetPref(extension->id(), prefs::kRestoreOnStartup);
199 UnsetPref(extension->id(), prefs::kURLsToRestoreOnStartup);
201 if (settings->search_engine) {
202 UnsetPref(extension->id(), prefs::kDefaultSearchProviderEnabled);
203 DCHECK(url_service_);
204 if (url_service_->loaded())
205 url_service_->RemoveExtensionControlledTURL(extension->id());
206 else
207 pending_extensions_.erase(extension);
210 break;
212 default: {
213 NOTREACHED();
214 break;
219 void SettingsOverridesAPI::Shutdown() {
220 template_url_sub_.reset();
223 void SettingsOverridesAPI::OnTemplateURLsLoaded() {
224 // Register search providers for pending extensions.
225 template_url_sub_.reset();
226 for (PendingExtensions::const_iterator i(pending_extensions_.begin());
227 i != pending_extensions_.end(); ++i) {
228 RegisterSearchProvider(*i);
230 pending_extensions_.clear();
233 void SettingsOverridesAPI::RegisterSearchProvider(
234 const Extension* extension) const {
235 DCHECK(url_service_);
236 DCHECK(extension);
237 const SettingsOverrides* settings = SettingsOverrides::Get(extension);
238 DCHECK(settings);
239 DCHECK(settings->search_engine);
240 scoped_ptr<AssociatedExtensionInfo> info(new AssociatedExtensionInfo);
241 info->extension_id = extension->id();
242 info->wants_to_be_default_engine = settings->search_engine->is_default;
243 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_);
244 info->install_time = prefs->GetInstallTime(extension->id());
245 std::string install_parameter = prefs->GetInstallParam(extension->id());
246 TemplateURLData data =
247 ConvertSearchProvider(*settings->search_engine, install_parameter);
248 url_service_->AddExtensionControlledTURL(new TemplateURL(profile_, data),
249 info.Pass());
252 template <>
253 void BrowserContextKeyedAPIFactory<
254 SettingsOverridesAPI>::DeclareFactoryDependencies() {
255 DependsOn(ExtensionPrefsFactory::GetInstance());
256 DependsOn(PreferenceAPI::GetFactoryInstance());
257 DependsOn(TemplateURLServiceFactory::GetInstance());
260 } // namespace extensions