settings_overrides_api.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/chrome_notification_types.h" 10#include "chrome/browser/extensions/api/preference/preference_api.h" 11#include "chrome/browser/extensions/extension_prefs.h" 12#include "chrome/browser/extensions/extension_prefs_factory.h" 13#include "chrome/browser/prefs/session_startup_pref.h" 14#include "chrome/browser/search_engines/template_url.h" 15#include "chrome/browser/search_engines/template_url_service_factory.h" 16#include "chrome/common/extensions/manifest_handlers/settings_overrides_handler.h" 17#include "chrome/common/pref_names.h" 18#include "content/public/browser/notification_details.h" 19#include "content/public/browser/notification_source.h" 20#include "extensions/common/error_utils.h" 21#include "extensions/common/manifest_constants.h" 22 23namespace extensions { 24 25namespace { 26base::LazyInstance<ProfileKeyedAPIFactory<SettingsOverridesAPI> > 27 g_factory = LAZY_INSTANCE_INITIALIZER; 28 29const char kManyStartupPagesWarning[] = "* specifies more than 1 startup URL. " 30 "All but the first will be ignored."; 31 32using api::manifest_types::ChromeSettingsOverrides; 33 34TemplateURLData ConvertSearchProvider( 35 const ChromeSettingsOverrides::Search_provider& search_provider) { 36 TemplateURLData data; 37 38 data.short_name = UTF8ToUTF16(search_provider.name); 39 data.SetKeyword(UTF8ToUTF16(search_provider.keyword)); 40 data.SetURL(search_provider.search_url); 41 if (search_provider.suggest_url) 42 data.suggestions_url = *search_provider.suggest_url; 43 if (search_provider.instant_url) 44 data.instant_url = *search_provider.instant_url; 45 if (search_provider.image_url) 46 data.image_url = *search_provider.image_url; 47 if (search_provider.search_url_post_params) 48 data.search_url_post_params = *search_provider.search_url_post_params; 49 if (search_provider.suggest_url_post_params) 50 data.suggestions_url_post_params = *search_provider.suggest_url_post_params; 51 if (search_provider.instant_url_post_params) 52 data.instant_url_post_params = *search_provider.instant_url_post_params; 53 if (search_provider.image_url_post_params) 54 data.image_url_post_params = *search_provider.image_url_post_params; 55 data.favicon_url = GURL(search_provider.favicon_url); 56 data.show_in_default_list = true; 57 data.safe_for_autoreplace = false; 58 data.input_encodings.push_back(search_provider.encoding); 59 data.date_created = base::Time(); 60 data.last_modified = base::Time(); 61 data.prepopulate_id = 0; 62 if (search_provider.alternate_urls) { 63 for (size_t i = 0; i < search_provider.alternate_urls->size(); ++i) { 64 if (!search_provider.alternate_urls->at(i).empty()) 65 data.alternate_urls.push_back(search_provider.alternate_urls->at(i)); 66 } 67 } 68 return data; 69} 70} // namespace 71 72SettingsOverridesAPI::SettingsOverridesAPI(Profile* profile) 73 : profile_(profile), 74 url_service_(TemplateURLServiceFactory::GetForProfile(profile)) { 75 DCHECK(profile); 76 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 77 content::Source<Profile>(profile)); 78 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 79 content::Source<Profile>(profile)); 80} 81 82SettingsOverridesAPI::~SettingsOverridesAPI() { 83} 84 85ProfileKeyedAPIFactory<SettingsOverridesAPI>* 86 SettingsOverridesAPI::GetFactoryInstance() { 87 return &g_factory.Get(); 88} 89 90void SettingsOverridesAPI::SetPref(const std::string& extension_id, 91 const std::string& pref_key, 92 base::Value* value) { 93 PreferenceAPI::Get(profile_)->SetExtensionControlledPref( 94 extension_id, 95 pref_key, 96 kExtensionPrefsScopeRegular, 97 value); 98} 99 100void SettingsOverridesAPI::UnsetPref(const std::string& extension_id, 101 const std::string& pref_key) { 102 PreferenceAPI::Get(profile_)->RemoveExtensionControlledPref( 103 extension_id, 104 pref_key, 105 kExtensionPrefsScopeRegular); 106} 107 108void SettingsOverridesAPI::Observe( 109 int type, 110 const content::NotificationSource& source, 111 const content::NotificationDetails& details) { 112 switch (type) { 113 case chrome::NOTIFICATION_EXTENSION_LOADED: { 114 const Extension* extension = 115 content::Details<const Extension>(details).ptr(); 116 const SettingsOverrides* settings = 117 SettingsOverrides::Get(extension); 118 if (settings) { 119 if (settings->homepage) { 120 SetPref(extension->id(), prefs::kHomePage, 121 new base::StringValue(settings->homepage->spec())); 122 SetPref(extension->id(), prefs::kHomePageIsNewTabPage, 123 new base::FundamentalValue(false)); 124 } 125 if (!settings->startup_pages.empty()) { 126 SetPref(extension->id(), prefs::kRestoreOnStartup, 127 new base::FundamentalValue( 128 SessionStartupPref::kPrefValueURLs)); 129 if (settings->startup_pages.size() > 1) { 130 VLOG(1) << extensions::ErrorUtils::FormatErrorMessage( 131 kManyStartupPagesWarning, manifest_keys::kSettingsOverride); 132 } 133 scoped_ptr<ListValue> url_list(new ListValue); 134 url_list->Append(new StringValue(settings->startup_pages[0].spec())); 135 SetPref(extension->id(), prefs::kURLsToRestoreOnStartup, 136 url_list.release()); 137 } 138 if (settings->search_engine) { 139 SetPref(extension->id(), prefs::kDefaultSearchProviderEnabled, 140 new base::FundamentalValue(true)); 141 DCHECK(url_service_); 142 if (url_service_->loaded()) { 143 RegisterSearchProvider(extension); 144 } else { 145 if (!template_url_sub_) { 146 template_url_sub_ = url_service_->RegisterOnLoadedCallback( 147 base::Bind(&SettingsOverridesAPI::OnTemplateURLsLoaded, 148 base::Unretained(this))); 149 } 150 url_service_->Load(); 151 pending_extensions_.insert(extension); 152 } 153 } 154 } 155 break; 156 } 157 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 158 const Extension* extension = 159 content::Details<UnloadedExtensionInfo>(details)->extension; 160 const SettingsOverrides* settings = SettingsOverrides::Get(extension); 161 if (settings) { 162 if (settings->homepage) { 163 UnsetPref(extension->id(), prefs::kHomePage); 164 UnsetPref(extension->id(), prefs::kHomePageIsNewTabPage); 165 } 166 if (!settings->startup_pages.empty()) { 167 UnsetPref(extension->id(), prefs::kRestoreOnStartup); 168 UnsetPref(extension->id(), prefs::kURLsToRestoreOnStartup); 169 } 170 if (settings->search_engine) { 171 UnsetPref(extension->id(), prefs::kDefaultSearchProviderEnabled); 172 DCHECK(url_service_); 173 if (url_service_->loaded()) 174 url_service_->RemoveExtensionControlledTURL(extension->id()); 175 else 176 pending_extensions_.erase(extension); 177 } 178 } 179 break; 180 } 181 default: { 182 NOTREACHED(); 183 break; 184 } 185 } 186} 187 188void SettingsOverridesAPI::Shutdown() { 189 template_url_sub_.reset(); 190} 191 192void SettingsOverridesAPI::OnTemplateURLsLoaded() { 193 // Register search providers for pending extensions. 194 template_url_sub_.reset(); 195 for (PendingExtensions::const_iterator i(pending_extensions_.begin()); 196 i != pending_extensions_.end(); ++i) { 197 RegisterSearchProvider(*i); 198 } 199 pending_extensions_.clear(); 200} 201 202void SettingsOverridesAPI::RegisterSearchProvider( 203 const Extension* extension) const { 204 DCHECK(url_service_); 205 DCHECK(extension); 206 const SettingsOverrides* settings = SettingsOverrides::Get(extension); 207 DCHECK(settings); 208 DCHECK(settings->search_engine); 209 scoped_ptr<AssociatedExtensionInfo> info(new AssociatedExtensionInfo); 210 info->extension_id = extension->id(); 211 info->wants_to_be_default_engine = settings->search_engine->is_default; 212 info->install_time = 213 ExtensionPrefs::Get(profile_)->GetInstallTime(extension->id()); 214 TemplateURLData data = ConvertSearchProvider(*settings->search_engine); 215 url_service_->AddExtensionControlledTURL(new TemplateURL(profile_, data), 216 info.Pass()); 217} 218 219template <> 220void ProfileKeyedAPIFactory<SettingsOverridesAPI>:: 221 DeclareFactoryDependencies() { 222 DependsOn(ExtensionPrefsFactory::GetInstance()); 223 DependsOn(PreferenceAPI::GetFactoryInstance()); 224 DependsOn(TemplateURLServiceFactory::GetInstance()); 225} 226 227} // namespace extensions 228