content_settings_api.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
1// Copyright (c) 2012 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/content_settings/content_settings_api.h" 6 7#include <set> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/command_line.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/prefs/pref_service.h" 14#include "base/values.h" 15#include "chrome/browser/content_settings/cookie_settings.h" 16#include "chrome/browser/content_settings/host_content_settings_map.h" 17#include "chrome/browser/extensions/api/content_settings/content_settings_api_constants.h" 18#include "chrome/browser/extensions/api/content_settings/content_settings_helpers.h" 19#include "chrome/browser/extensions/api/content_settings/content_settings_store.h" 20#include "chrome/browser/extensions/api/preference/preference_api_constants.h" 21#include "chrome/browser/extensions/api/preference/preference_helpers.h" 22#include "chrome/browser/extensions/extension_service.h" 23#include "chrome/browser/extensions/extension_system.h" 24#include "chrome/browser/plugins/plugin_finder.h" 25#include "chrome/browser/plugins/plugin_installer.h" 26#include "chrome/browser/profiles/profile.h" 27#include "chrome/common/chrome_switches.h" 28#include "chrome/common/extensions/api/content_settings.h" 29#include "content/public/browser/plugin_service.h" 30#include "extensions/common/error_utils.h" 31 32using content::BrowserThread; 33using content::PluginService; 34 35namespace Clear = extensions::api::content_settings::ContentSetting::Clear; 36namespace Get = extensions::api::content_settings::ContentSetting::Get; 37namespace Set = extensions::api::content_settings::ContentSetting::Set; 38namespace pref_helpers = extensions::preference_helpers; 39namespace pref_keys = extensions::preference_api_constants; 40 41namespace { 42 43bool RemoveContentType(base::ListValue* args, 44 ContentSettingsType* content_type) { 45 std::string content_type_str; 46 if (!args->GetString(0, &content_type_str)) 47 return false; 48 // We remove the ContentSettingsType parameter since this is added by the 49 // renderer, and is not part of the JSON schema. 50 args->Remove(0, NULL); 51 *content_type = 52 extensions::content_settings_helpers::StringToContentSettingsType( 53 content_type_str); 54 return *content_type != CONTENT_SETTINGS_TYPE_DEFAULT; 55} 56 57} // namespace 58 59namespace extensions { 60 61namespace helpers = content_settings_helpers; 62namespace keys = content_settings_api_constants; 63 64bool ContentSettingsContentSettingClearFunction::RunImpl() { 65 ContentSettingsType content_type; 66 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type)); 67 68 scoped_ptr<Clear::Params> params(Clear::Params::Create(*args_)); 69 EXTENSION_FUNCTION_VALIDATE(params.get()); 70 71 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; 72 bool incognito = false; 73 if (params->details.scope == 74 Clear::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY) { 75 scope = kExtensionPrefsScopeIncognitoSessionOnly; 76 incognito = true; 77 } 78 79 if (incognito) { 80 // We don't check incognito permissions here, as an extension should be 81 // always allowed to clear its own settings. 82 } else { 83 // Incognito profiles can't access regular mode ever, they only exist in 84 // split mode. 85 if (profile()->IsOffTheRecord()) { 86 error_ = keys::kIncognitoContextError; 87 return false; 88 } 89 } 90 91 ContentSettingsStore* store = extensions::ExtensionSystem::Get(profile_)-> 92 extension_service()->GetContentSettingsStore(); 93 store->ClearContentSettingsForExtension(extension_id(), scope); 94 95 return true; 96} 97 98bool ContentSettingsContentSettingGetFunction::RunImpl() { 99 ContentSettingsType content_type; 100 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type)); 101 102 scoped_ptr<Get::Params> params(Get::Params::Create(*args_)); 103 EXTENSION_FUNCTION_VALIDATE(params.get()); 104 105 GURL primary_url(params->details.primary_url); 106 if (!primary_url.is_valid()) { 107 error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, 108 params->details.primary_url); 109 return false; 110 } 111 112 GURL secondary_url(primary_url); 113 if (params->details.secondary_url.get()) { 114 secondary_url = GURL(*params->details.secondary_url); 115 if (!secondary_url.is_valid()) { 116 error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, 117 *params->details.secondary_url); 118 return false; 119 } 120 } 121 122 std::string resource_identifier; 123 if (params->details.resource_identifier.get()) 124 resource_identifier = params->details.resource_identifier->id; 125 126 bool incognito = false; 127 if (params->details.incognito.get()) 128 incognito = *params->details.incognito; 129 if (incognito && !include_incognito()) { 130 error_ = pref_keys::kIncognitoErrorMessage; 131 return false; 132 } 133 134 HostContentSettingsMap* map; 135 CookieSettings* cookie_settings; 136 if (incognito) { 137 if (!profile()->HasOffTheRecordProfile()) { 138 // TODO(bauerb): Allow reading incognito content settings 139 // outside of an incognito session. 140 error_ = keys::kIncognitoSessionOnlyError; 141 return false; 142 } 143 map = profile()->GetOffTheRecordProfile()->GetHostContentSettingsMap(); 144 cookie_settings = CookieSettings::Factory::GetForProfile( 145 profile()->GetOffTheRecordProfile()).get(); 146 } else { 147 map = profile()->GetHostContentSettingsMap(); 148 cookie_settings = CookieSettings::Factory::GetForProfile(profile()).get(); 149 } 150 151 ContentSetting setting; 152 if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) { 153 // TODO(jochen): Do we return the value for setting or for reading cookies? 154 bool setting_cookie = false; 155 setting = cookie_settings->GetCookieSetting(primary_url, secondary_url, 156 setting_cookie, NULL); 157 } else { 158 setting = map->GetContentSetting(primary_url, secondary_url, content_type, 159 resource_identifier); 160 } 161 162 base::DictionaryValue* result = new base::DictionaryValue(); 163 result->SetString(keys::kContentSettingKey, 164 helpers::ContentSettingToString(setting)); 165 166 SetResult(result); 167 168 return true; 169} 170 171bool ContentSettingsContentSettingSetFunction::RunImpl() { 172 ContentSettingsType content_type; 173 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type)); 174 175 scoped_ptr<Set::Params> params(Set::Params::Create(*args_)); 176 EXTENSION_FUNCTION_VALIDATE(params.get()); 177 178 std::string primary_error; 179 ContentSettingsPattern primary_pattern = 180 helpers::ParseExtensionPattern(params->details.primary_pattern, 181 &primary_error); 182 if (!primary_pattern.IsValid()) { 183 error_ = primary_error; 184 return false; 185 } 186 187 ContentSettingsPattern secondary_pattern = ContentSettingsPattern::Wildcard(); 188 std::string secondary_pattern_str; 189 if (params->details.secondary_pattern.get()) { 190 std::string secondary_error; 191 secondary_pattern = 192 helpers::ParseExtensionPattern(*params->details.secondary_pattern, 193 &secondary_error); 194 if (!secondary_pattern.IsValid()) { 195 error_ = secondary_error; 196 return false; 197 } 198 } 199 200 std::string resource_identifier; 201 if (params->details.resource_identifier.get()) 202 resource_identifier = params->details.resource_identifier->id; 203 204 std::string setting_str; 205 EXTENSION_FUNCTION_VALIDATE( 206 params->details.setting->GetAsString(&setting_str)); 207 ContentSetting setting; 208 EXTENSION_FUNCTION_VALIDATE( 209 helpers::StringToContentSetting(setting_str, &setting)); 210 EXTENSION_FUNCTION_VALIDATE( 211 HostContentSettingsMap::IsSettingAllowedForType(profile()->GetPrefs(), 212 setting, 213 content_type)); 214 215 ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; 216 bool incognito = false; 217 if (params->details.scope == 218 Set::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY) { 219 scope = kExtensionPrefsScopeIncognitoSessionOnly; 220 incognito = true; 221 } 222 223 if (incognito) { 224 // Regular profiles can't access incognito unless include_incognito is true. 225 if (!profile()->IsOffTheRecord() && !include_incognito()) { 226 error_ = pref_keys::kIncognitoErrorMessage; 227 return false; 228 } 229 } else { 230 // Incognito profiles can't access regular mode ever, they only exist in 231 // split mode. 232 if (profile()->IsOffTheRecord()) { 233 error_ = keys::kIncognitoContextError; 234 return false; 235 } 236 } 237 238 if (scope == kExtensionPrefsScopeIncognitoSessionOnly && 239 !profile_->HasOffTheRecordProfile()) { 240 error_ = pref_keys::kIncognitoSessionOnlyErrorMessage; 241 return false; 242 } 243 244 ContentSettingsStore* store = extensions::ExtensionSystem::Get(profile_)-> 245 extension_service()->GetContentSettingsStore(); 246 store->SetExtensionContentSetting(extension_id(), primary_pattern, 247 secondary_pattern, content_type, 248 resource_identifier, setting, scope); 249 return true; 250} 251 252bool ContentSettingsContentSettingGetResourceIdentifiersFunction::RunImpl() { 253 ContentSettingsType content_type; 254 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type)); 255 256 if (content_type != CONTENT_SETTINGS_TYPE_PLUGINS) { 257 SendResponse(true); 258 return true; 259 } 260 261 PluginService::GetInstance()->GetPlugins( 262 base::Bind(&ContentSettingsContentSettingGetResourceIdentifiersFunction:: 263 OnGotPlugins, 264 this)); 265 return true; 266} 267 268void ContentSettingsContentSettingGetResourceIdentifiersFunction::OnGotPlugins( 269 const std::vector<content::WebPluginInfo>& plugins) { 270 PluginFinder* finder = PluginFinder::GetInstance(); 271 std::set<std::string> group_identifiers; 272 base::ListValue* list = new base::ListValue(); 273 for (std::vector<content::WebPluginInfo>::const_iterator it = plugins.begin(); 274 it != plugins.end(); ++it) { 275 scoped_ptr<PluginMetadata> plugin_metadata(finder->GetPluginMetadata(*it)); 276 const std::string& group_identifier = plugin_metadata->identifier(); 277 if (group_identifiers.find(group_identifier) != group_identifiers.end()) 278 continue; 279 280 group_identifiers.insert(group_identifier); 281 base::DictionaryValue* dict = new base::DictionaryValue(); 282 dict->SetString(keys::kIdKey, group_identifier); 283 dict->SetString(keys::kDescriptionKey, plugin_metadata->name()); 284 list->Append(dict); 285 } 286 SetResult(list); 287 BrowserThread::PostTask( 288 BrowserThread::UI, FROM_HERE, base::Bind( 289 &ContentSettingsContentSettingGetResourceIdentifiersFunction:: 290 SendResponse, 291 this, 292 true)); 293} 294 295} // namespace extensions 296