Home | History | Annotate | Download | only in content_settings
      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 
     32 using content::BrowserThread;
     33 using content::PluginService;
     34 
     35 namespace Clear = extensions::api::content_settings::ContentSetting::Clear;
     36 namespace Get = extensions::api::content_settings::ContentSetting::Get;
     37 namespace Set = extensions::api::content_settings::ContentSetting::Set;
     38 namespace pref_helpers = extensions::preference_helpers;
     39 namespace pref_keys = extensions::preference_api_constants;
     40 
     41 namespace {
     42 
     43 bool 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 
     59 namespace extensions {
     60 
     61 namespace helpers = content_settings_helpers;
     62 namespace keys = content_settings_api_constants;
     63 
     64 bool 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 
     98 bool 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 
    171 bool 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   if (params->details.secondary_pattern.get()) {
    189     std::string secondary_error;
    190     secondary_pattern =
    191         helpers::ParseExtensionPattern(*params->details.secondary_pattern,
    192                                        &secondary_error);
    193     if (!secondary_pattern.IsValid()) {
    194       error_ = secondary_error;
    195       return false;
    196     }
    197   }
    198 
    199   std::string resource_identifier;
    200   if (params->details.resource_identifier.get())
    201     resource_identifier = params->details.resource_identifier->id;
    202 
    203   std::string setting_str;
    204   EXTENSION_FUNCTION_VALIDATE(
    205       params->details.setting->GetAsString(&setting_str));
    206   ContentSetting setting;
    207   EXTENSION_FUNCTION_VALIDATE(
    208       helpers::StringToContentSetting(setting_str, &setting));
    209   EXTENSION_FUNCTION_VALIDATE(
    210       HostContentSettingsMap::IsSettingAllowedForType(profile()->GetPrefs(),
    211                                                       setting,
    212                                                       content_type));
    213 
    214   ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
    215   bool incognito = false;
    216   if (params->details.scope ==
    217           Set::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY) {
    218     scope = kExtensionPrefsScopeIncognitoSessionOnly;
    219     incognito = true;
    220   }
    221 
    222   if (incognito) {
    223     // Regular profiles can't access incognito unless include_incognito is true.
    224     if (!profile()->IsOffTheRecord() && !include_incognito()) {
    225       error_ = pref_keys::kIncognitoErrorMessage;
    226       return false;
    227     }
    228   } else {
    229     // Incognito profiles can't access regular mode ever, they only exist in
    230     // split mode.
    231     if (profile()->IsOffTheRecord()) {
    232       error_ = keys::kIncognitoContextError;
    233       return false;
    234     }
    235   }
    236 
    237   if (scope == kExtensionPrefsScopeIncognitoSessionOnly &&
    238       !profile_->HasOffTheRecordProfile()) {
    239     error_ = pref_keys::kIncognitoSessionOnlyErrorMessage;
    240     return false;
    241   }
    242 
    243   ContentSettingsStore* store = extensions::ExtensionSystem::Get(profile_)->
    244       extension_service()->GetContentSettingsStore();
    245   store->SetExtensionContentSetting(extension_id(), primary_pattern,
    246                                     secondary_pattern, content_type,
    247                                     resource_identifier, setting, scope);
    248   return true;
    249 }
    250 
    251 bool ContentSettingsContentSettingGetResourceIdentifiersFunction::RunImpl() {
    252   ContentSettingsType content_type;
    253   EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type));
    254 
    255   if (content_type != CONTENT_SETTINGS_TYPE_PLUGINS) {
    256     SendResponse(true);
    257     return true;
    258   }
    259 
    260   PluginService::GetInstance()->GetPlugins(
    261       base::Bind(&ContentSettingsContentSettingGetResourceIdentifiersFunction::
    262                  OnGotPlugins,
    263                  this));
    264   return true;
    265 }
    266 
    267 void ContentSettingsContentSettingGetResourceIdentifiersFunction::OnGotPlugins(
    268     const std::vector<content::WebPluginInfo>& plugins) {
    269   PluginFinder* finder = PluginFinder::GetInstance();
    270   std::set<std::string> group_identifiers;
    271   base::ListValue* list = new base::ListValue();
    272   for (std::vector<content::WebPluginInfo>::const_iterator it = plugins.begin();
    273        it != plugins.end(); ++it) {
    274     scoped_ptr<PluginMetadata> plugin_metadata(finder->GetPluginMetadata(*it));
    275     const std::string& group_identifier = plugin_metadata->identifier();
    276     if (group_identifiers.find(group_identifier) != group_identifiers.end())
    277       continue;
    278 
    279     group_identifiers.insert(group_identifier);
    280     base::DictionaryValue* dict = new base::DictionaryValue();
    281     dict->SetString(keys::kIdKey, group_identifier);
    282     dict->SetString(keys::kDescriptionKey, plugin_metadata->name());
    283     list->Append(dict);
    284   }
    285   SetResult(list);
    286   BrowserThread::PostTask(
    287       BrowserThread::UI, FROM_HERE, base::Bind(
    288           &ContentSettingsContentSettingGetResourceIdentifiersFunction::
    289           SendResponse,
    290           this,
    291           true));
    292 }
    293 
    294 }  // namespace extensions
    295