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