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
{
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
);
42 TemplateURLData
ConvertSearchProvider(
43 const ChromeSettingsOverrides::Search_provider
& search_provider
,
44 const std::string
& install_parameter
) {
47 data
.short_name
= base::UTF8ToUTF16(search_provider
.name
);
48 data
.SetKeyword(base::UTF8ToUTF16(search_provider
.keyword
));
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
) {
57 SubstituteInstallParam(*search_provider
.instant_url
, install_parameter
);
59 if (search_provider
.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
));
91 SettingsOverridesAPI::SettingsOverridesAPI(content::BrowserContext
* context
)
92 : profile_(Profile::FromBrowserContext(context
)),
93 url_service_(TemplateURLServiceFactory::GetForProfile(profile_
)) {
96 chrome::NOTIFICATION_EXTENSION_LOADED
,
97 content::Source
<Profile
>(profile_
));
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_
);
116 return; // Expected in unit tests.
117 prefs
->SetExtensionControlledPref(extension_id
,
119 kExtensionPrefsScopeRegular
,
123 void SettingsOverridesAPI::UnsetPref(const std::string
& extension_id
,
124 const std::string
& pref_key
) {
125 PreferenceAPI
* prefs
= PreferenceAPI::Get(profile_
);
127 return; // Expected in unit tests.
128 prefs
->RemoveExtensionControlledPref(
131 kExtensionPrefsScopeRegular
);
134 void SettingsOverridesAPI::Observe(
136 const content::NotificationSource
& source
,
137 const content::NotificationDetails
& details
) {
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
);
145 std::string install_parameter
=
146 ExtensionPrefs::Get(profile_
)->GetInstallParam(extension
->id());
147 if (settings
->homepage
) {
148 SetPref(extension
->id(),
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
,
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
);
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
);
188 case chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED
: {
189 const Extension
* extension
=
190 content::Details
<UnloadedExtensionInfo
>(details
)->extension
;
191 const SettingsOverrides
* settings
= SettingsOverrides::Get(extension
);
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());
207 pending_extensions_
.erase(extension
);
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_
);
237 const SettingsOverrides
* settings
= SettingsOverrides::Get(extension
);
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
),
253 void BrowserContextKeyedAPIFactory
<
254 SettingsOverridesAPI
>::DeclareFactoryDependencies() {
255 DependsOn(ExtensionPrefsFactory::GetInstance());
256 DependsOn(PreferenceAPI::GetFactoryInstance());
257 DependsOn(TemplateURLServiceFactory::GetInstance());
260 } // namespace extensions