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.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 
     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.
     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 
     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 
    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 
    131 SettingsOverridesAPI::~SettingsOverridesAPI() {
    132 }
    133 
    134 BrowserContextKeyedAPIFactory<SettingsOverridesAPI>*
    135 SettingsOverridesAPI::GetFactoryInstance() {
    136   return g_factory.Pointer();
    137 }
    138 
    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 
    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 
    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 }
    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 
    243 void SettingsOverridesAPI::Shutdown() {
    244   template_url_sub_.reset();
    245 }
    246 
    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 
    257 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<
    278     SettingsOverridesAPI>::DeclareFactoryDependencies() {
    279   DependsOn(ExtensionPrefsFactory::GetInstance());
    280   DependsOn(PreferenceAPI::GetFactoryInstance());
    281   DependsOn(TemplateURLServiceFactory::GetInstance());
    282 }
    283 
    284 }  // namespace extensions
    285