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.h"
13 #include "chrome/browser/search_engines/template_url_service_factory.h"
14 #include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h"
15 #include "chrome/common/pref_names.h"
16 #include "extensions/browser/extension_prefs.h"
17 #include "extensions/browser/extension_prefs_factory.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/common/error_utils.h"
20 #include "extensions/common/manifest_constants.h"
22 namespace extensions
{
26 base::LazyInstance
<BrowserContextKeyedAPIFactory
<SettingsOverridesAPI
> >
27 g_factory
= LAZY_INSTANCE_INITIALIZER
;
29 const char kManyStartupPagesWarning
[] = "* specifies more than 1 startup URL. "
30 "All but the first will be ignored.";
32 using api::manifest_types::ChromeSettingsOverrides
;
34 std::string
SubstituteInstallParam(std::string str
,
35 const std::string
& install_parameter
) {
36 ReplaceSubstringsAfterOffset(&str
, 0, "__PARAM__", install_parameter
);
40 TemplateURLData
ConvertSearchProvider(
41 const ChromeSettingsOverrides::Search_provider
& search_provider
,
42 const std::string
& install_parameter
) {
45 data
.short_name
= base::UTF8ToUTF16(search_provider
.name
);
46 data
.SetKeyword(base::UTF8ToUTF16(search_provider
.keyword
));
48 SubstituteInstallParam(search_provider
.search_url
, install_parameter
));
49 if (search_provider
.suggest_url
) {
50 data
.suggestions_url
=
51 SubstituteInstallParam(*search_provider
.suggest_url
, install_parameter
);
53 if (search_provider
.instant_url
) {
55 SubstituteInstallParam(*search_provider
.instant_url
, install_parameter
);
57 if (search_provider
.image_url
) {
59 SubstituteInstallParam(*search_provider
.image_url
, install_parameter
);
61 if (search_provider
.search_url_post_params
)
62 data
.search_url_post_params
= *search_provider
.search_url_post_params
;
63 if (search_provider
.suggest_url_post_params
)
64 data
.suggestions_url_post_params
= *search_provider
.suggest_url_post_params
;
65 if (search_provider
.instant_url_post_params
)
66 data
.instant_url_post_params
= *search_provider
.instant_url_post_params
;
67 if (search_provider
.image_url_post_params
)
68 data
.image_url_post_params
= *search_provider
.image_url_post_params
;
69 data
.favicon_url
= GURL(
70 SubstituteInstallParam(search_provider
.favicon_url
, install_parameter
));
71 data
.safe_for_autoreplace
= false;
72 data
.input_encodings
.push_back(search_provider
.encoding
);
73 data
.date_created
= base::Time();
74 data
.last_modified
= base::Time();
75 data
.prepopulate_id
= 0;
76 if (search_provider
.alternate_urls
) {
77 for (size_t i
= 0; i
< search_provider
.alternate_urls
->size(); ++i
) {
78 if (!search_provider
.alternate_urls
->at(i
).empty())
79 data
.alternate_urls
.push_back(SubstituteInstallParam(
80 search_provider
.alternate_urls
->at(i
), install_parameter
));
88 SettingsOverridesAPI::SettingsOverridesAPI(content::BrowserContext
* context
)
89 : profile_(Profile::FromBrowserContext(context
)),
90 url_service_(TemplateURLServiceFactory::GetForProfile(profile_
)),
91 extension_registry_observer_(this) {
92 extension_registry_observer_
.Add(ExtensionRegistry::Get(profile_
));
95 SettingsOverridesAPI::~SettingsOverridesAPI() {
98 BrowserContextKeyedAPIFactory
<SettingsOverridesAPI
>*
99 SettingsOverridesAPI::GetFactoryInstance() {
100 return g_factory
.Pointer();
103 void SettingsOverridesAPI::SetPref(const std::string
& extension_id
,
104 const std::string
& pref_key
,
105 base::Value
* value
) {
106 PreferenceAPI
* prefs
= PreferenceAPI::Get(profile_
);
108 return; // Expected in unit tests.
109 prefs
->SetExtensionControlledPref(extension_id
,
111 kExtensionPrefsScopeRegular
,
115 void SettingsOverridesAPI::UnsetPref(const std::string
& extension_id
,
116 const std::string
& pref_key
) {
117 PreferenceAPI
* prefs
= PreferenceAPI::Get(profile_
);
119 return; // Expected in unit tests.
120 prefs
->RemoveExtensionControlledPref(
123 kExtensionPrefsScopeRegular
);
126 void SettingsOverridesAPI::OnExtensionLoaded(
127 content::BrowserContext
* browser_context
,
128 const Extension
* extension
) {
129 const SettingsOverrides
* settings
= SettingsOverrides::Get(extension
);
131 std::string install_parameter
=
132 ExtensionPrefs::Get(profile_
)->GetInstallParam(extension
->id());
133 if (settings
->homepage
) {
134 SetPref(extension
->id(),
136 new base::StringValue(SubstituteInstallParam(
137 settings
->homepage
->spec(), install_parameter
)));
138 SetPref(extension
->id(),
139 prefs::kHomePageIsNewTabPage
,
140 new base::FundamentalValue(false));
142 if (!settings
->startup_pages
.empty()) {
143 SetPref(extension
->id(),
144 prefs::kRestoreOnStartup
,
145 new base::FundamentalValue(SessionStartupPref::kPrefValueURLs
));
146 if (settings
->startup_pages
.size() > 1) {
147 VLOG(1) << extensions::ErrorUtils::FormatErrorMessage(
148 kManyStartupPagesWarning
,
149 manifest_keys::kSettingsOverride
);
151 scoped_ptr
<base::ListValue
> url_list(new base::ListValue
);
152 url_list
->Append(new base::StringValue(SubstituteInstallParam(
153 settings
->startup_pages
[0].spec(), install_parameter
)));
155 extension
->id(), prefs::kURLsToRestoreOnStartup
, url_list
.release());
157 if (settings
->search_engine
) {
158 // Bring the preference to the correct state. Before this code set it
159 // to "true" for all search engines. Thus, we should overwrite it for
160 // all search engines.
161 if (settings
->search_engine
->is_default
) {
162 SetPref(extension
->id(),
163 prefs::kDefaultSearchProviderEnabled
,
164 new base::FundamentalValue(true));
166 UnsetPref(extension
->id(), prefs::kDefaultSearchProviderEnabled
);
168 DCHECK(url_service_
);
169 if (url_service_
->loaded()) {
170 RegisterSearchProvider(extension
);
172 if (!template_url_sub_
) {
173 template_url_sub_
= url_service_
->RegisterOnLoadedCallback(
174 base::Bind(&SettingsOverridesAPI::OnTemplateURLsLoaded
,
175 base::Unretained(this)));
177 url_service_
->Load();
178 pending_extensions_
.insert(extension
);
183 void SettingsOverridesAPI::OnExtensionUnloaded(
184 content::BrowserContext
* browser_context
,
185 const Extension
* extension
,
186 UnloadedExtensionInfo::Reason reason
) {
187 const SettingsOverrides
* settings
= SettingsOverrides::Get(extension
);
189 if (settings
->homepage
) {
190 UnsetPref(extension
->id(), prefs::kHomePage
);
191 UnsetPref(extension
->id(), prefs::kHomePageIsNewTabPage
);
193 if (!settings
->startup_pages
.empty()) {
194 UnsetPref(extension
->id(), prefs::kRestoreOnStartup
);
195 UnsetPref(extension
->id(), prefs::kURLsToRestoreOnStartup
);
197 if (settings
->search_engine
) {
198 DCHECK(url_service_
);
199 if (url_service_
->loaded())
200 url_service_
->RemoveExtensionControlledTURL(extension
->id());
202 pending_extensions_
.erase(extension
);
207 void SettingsOverridesAPI::Shutdown() {
208 template_url_sub_
.reset();
211 void SettingsOverridesAPI::OnTemplateURLsLoaded() {
212 // Register search providers for pending extensions.
213 template_url_sub_
.reset();
214 for (PendingExtensions::const_iterator
i(pending_extensions_
.begin());
215 i
!= pending_extensions_
.end(); ++i
) {
216 RegisterSearchProvider(*i
);
218 pending_extensions_
.clear();
221 void SettingsOverridesAPI::RegisterSearchProvider(
222 const Extension
* extension
) const {
223 DCHECK(url_service_
);
225 const SettingsOverrides
* settings
= SettingsOverrides::Get(extension
);
227 DCHECK(settings
->search_engine
);
228 scoped_ptr
<AssociatedExtensionInfo
> info(new AssociatedExtensionInfo
);
229 info
->extension_id
= extension
->id();
230 info
->wants_to_be_default_engine
= settings
->search_engine
->is_default
;
231 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(profile_
);
232 info
->install_time
= prefs
->GetInstallTime(extension
->id());
233 std::string install_parameter
= prefs
->GetInstallParam(extension
->id());
234 TemplateURLData data
=
235 ConvertSearchProvider(*settings
->search_engine
, install_parameter
);
236 data
.show_in_default_list
= info
->wants_to_be_default_engine
;
237 url_service_
->AddExtensionControlledTURL(new TemplateURL(profile_
, data
),
242 void BrowserContextKeyedAPIFactory
<
243 SettingsOverridesAPI
>::DeclareFactoryDependencies() {
244 DependsOn(ExtensionPrefsFactory::GetInstance());
245 DependsOn(PreferenceAPI::GetFactoryInstance());
246 DependsOn(TemplateURLServiceFactory::GetInstance());
249 } // namespace extensions