Home | History | Annotate | Download | only in settings_overrides
      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_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"
     23 
     24 namespace extensions {
     25 
     26 namespace {
     27 
     28 base::LazyInstance<BrowserContextKeyedAPIFactory<SettingsOverridesAPI> >
     29     g_factory = LAZY_INSTANCE_INITIALIZER;
     30 
     31 const char kManyStartupPagesWarning[] = "* specifies more than 1 startup URL. "
     32     "All but the first will be ignored.";
     33 
     34 using api::manifest_types::ChromeSettingsOverrides;
     35 
     36 std::string SubstituteInstallParam(std::string str,
     37                                    const std::string& install_parameter) {
     38   ReplaceSubstringsAfterOffset(&str, 0, "__PARAM__", install_parameter);
     39   return str;
     40 }
     41 
     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;
     56     }
     57   }
     58   return false;
     59 }
     60 
     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;
     71     }
     72   }
     73 
     74   if (search_provider.name)
     75     data.short_name = 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);
     83   }
     84   if (search_provider.instant_url) {
     85     data.instant_url =
     86         SubstituteInstallParam(*search_provider.instant_url, install_parameter);
     87   }
     88   if (search_provider.image_url) {
     89     data.image_url =
     90         SubstituteInstallParam(*search_provider.image_url, install_parameter);
     91   }
     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));
    103   }
    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);
    108   }
    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));
    118     }
    119   }
    120   return data;
    121 }
    122 
    123 }  // namespace
    124 
    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_));
    130 }
    131 
    132 SettingsOverridesAPI::~SettingsOverridesAPI() {
    133 }
    134 
    135 BrowserContextKeyedAPIFactory<SettingsOverridesAPI>*
    136 SettingsOverridesAPI::GetFactoryInstance() {
    137   return g_factory.Pointer();
    138 }
    139 
    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);
    150 }
    151 
    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);
    161 }
    162 
    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));
    178     }
    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);
    187       }
    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());
    193     }
    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);
    204       }
    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)));
    213         }
    214         url_service_->Load();
    215         pending_extensions_.insert(extension);
    216       }
    217     }
    218   }
    219 }
    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);
    229     }
    230     if (!settings->startup_pages.empty()) {
    231       UnsetPref(extension->id(), prefs::kRestoreOnStartup);
    232       UnsetPref(extension->id(), prefs::kURLsToRestoreOnStartup);
    233     }
    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);
    241       }
    242     }
    243   }
    244 }
    245 
    246 void SettingsOverridesAPI::Shutdown() {
    247   template_url_sub_.reset();
    248 }
    249 
    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());
    256   }
    257   pending_extensions_.clear();
    258 }
    259 
    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());
    278 }
    279 
    280 template <>
    281 void BrowserContextKeyedAPIFactory<
    282     SettingsOverridesAPI>::DeclareFactoryDependencies() {
    283   DependsOn(ExtensionPrefsFactory::GetInstance());
    284   DependsOn(PreferenceAPI::GetFactoryInstance());
    285   DependsOn(TemplateURLServiceFactory::GetInstance());
    286 }
    287 
    288 }  // namespace extensions
    289