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/values.h"
     14 #include "chrome/browser/content_settings/cookie_settings.h"
     15 #include "chrome/browser/content_settings/host_content_settings_map.h"
     16 #include "chrome/browser/extensions/api/content_settings/content_settings_api_constants.h"
     17 #include "chrome/browser/extensions/api/content_settings/content_settings_helpers.h"
     18 #include "chrome/browser/extensions/api/content_settings/content_settings_service.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/plugins/plugin_finder.h"
     23 #include "chrome/browser/plugins/plugin_installer.h"
     24 #include "chrome/browser/profiles/profile.h"
     25 #include "chrome/common/chrome_switches.h"
     26 #include "chrome/common/extensions/api/content_settings.h"
     27 #include "content/public/browser/plugin_service.h"
     28 #include "extensions/browser/extension_prefs_scope.h"
     29 #include "extensions/common/error_utils.h"
     30 
     31 using content::BrowserThread;
     32 using content::PluginService;
     33 
     34 namespace Clear = extensions::api::content_settings::ContentSetting::Clear;
     35 namespace Get = extensions::api::content_settings::ContentSetting::Get;
     36 namespace Set = extensions::api::content_settings::ContentSetting::Set;
     37 namespace pref_helpers = extensions::preference_helpers;
     38 namespace pref_keys = extensions::preference_api_constants;
     39 
     40 namespace {
     41 
     42 bool RemoveContentType(base::ListValue* args,
     43                        ContentSettingsType* content_type) {
     44   std::string content_type_str;
     45   if (!args->GetString(0, &content_type_str))
     46     return false;
     47   // We remove the ContentSettingsType parameter since this is added by the
     48   // renderer, and is not part of the JSON schema.
     49   args->Remove(0, NULL);
     50   *content_type =
     51       extensions::content_settings_helpers::StringToContentSettingsType(
     52           content_type_str);
     53   return *content_type != CONTENT_SETTINGS_TYPE_DEFAULT;
     54 }
     55 
     56 }  // namespace
     57 
     58 namespace extensions {
     59 
     60 namespace helpers = content_settings_helpers;
     61 namespace keys = content_settings_api_constants;
     62 
     63 bool ContentSettingsContentSettingClearFunction::RunSync() {
     64   ContentSettingsType content_type;
     65   EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type));
     66 
     67   scoped_ptr<Clear::Params> params(Clear::Params::Create(*args_));
     68   EXTENSION_FUNCTION_VALIDATE(params.get());
     69 
     70   ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
     71   bool incognito = false;
     72   if (params->details.scope ==
     73           Clear::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY) {
     74     scope = kExtensionPrefsScopeIncognitoSessionOnly;
     75     incognito = true;
     76   }
     77 
     78   if (incognito) {
     79     // We don't check incognito permissions here, as an extension should be
     80     // always allowed to clear its own settings.
     81   } else {
     82     // Incognito profiles can't access regular mode ever, they only exist in
     83     // split mode.
     84     if (GetProfile()->IsOffTheRecord()) {
     85       error_ = keys::kIncognitoContextError;
     86       return false;
     87     }
     88   }
     89 
     90   scoped_refptr<ContentSettingsStore> store =
     91       ContentSettingsService::Get(GetProfile())->content_settings_store();
     92   store->ClearContentSettingsForExtension(extension_id(), scope);
     93 
     94   return true;
     95 }
     96 
     97 bool ContentSettingsContentSettingGetFunction::RunSync() {
     98   ContentSettingsType content_type;
     99   EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type));
    100 
    101   scoped_ptr<Get::Params> params(Get::Params::Create(*args_));
    102   EXTENSION_FUNCTION_VALIDATE(params.get());
    103 
    104   GURL primary_url(params->details.primary_url);
    105   if (!primary_url.is_valid()) {
    106     error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
    107         params->details.primary_url);
    108     return false;
    109   }
    110 
    111   GURL secondary_url(primary_url);
    112   if (params->details.secondary_url.get()) {
    113     secondary_url = GURL(*params->details.secondary_url);
    114     if (!secondary_url.is_valid()) {
    115       error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
    116         *params->details.secondary_url);
    117       return false;
    118     }
    119   }
    120 
    121   std::string resource_identifier;
    122   if (params->details.resource_identifier.get())
    123     resource_identifier = params->details.resource_identifier->id;
    124 
    125   bool incognito = false;
    126   if (params->details.incognito.get())
    127     incognito = *params->details.incognito;
    128   if (incognito && !include_incognito()) {
    129     error_ = pref_keys::kIncognitoErrorMessage;
    130     return false;
    131   }
    132 
    133   HostContentSettingsMap* map;
    134   CookieSettings* cookie_settings;
    135   if (incognito) {
    136     if (!GetProfile()->HasOffTheRecordProfile()) {
    137       // TODO(bauerb): Allow reading incognito content settings
    138       // outside of an incognito session.
    139       error_ = keys::kIncognitoSessionOnlyError;
    140       return false;
    141     }
    142     map = GetProfile()->GetOffTheRecordProfile()->GetHostContentSettingsMap();
    143     cookie_settings = CookieSettings::Factory::GetForProfile(
    144         GetProfile()->GetOffTheRecordProfile()).get();
    145   } else {
    146     map = GetProfile()->GetHostContentSettingsMap();
    147     cookie_settings =
    148         CookieSettings::Factory::GetForProfile(GetProfile()).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::RunSync() {
    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(HostContentSettingsMap::IsSettingAllowedForType(
    210       GetProfile()->GetPrefs(), setting, content_type));
    211 
    212   ExtensionPrefsScope scope = kExtensionPrefsScopeRegular;
    213   bool incognito = false;
    214   if (params->details.scope ==
    215           Set::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY) {
    216     scope = kExtensionPrefsScopeIncognitoSessionOnly;
    217     incognito = true;
    218   }
    219 
    220   if (incognito) {
    221     // Regular profiles can't access incognito unless include_incognito is true.
    222     if (!GetProfile()->IsOffTheRecord() && !include_incognito()) {
    223       error_ = pref_keys::kIncognitoErrorMessage;
    224       return false;
    225     }
    226   } else {
    227     // Incognito profiles can't access regular mode ever, they only exist in
    228     // split mode.
    229     if (GetProfile()->IsOffTheRecord()) {
    230       error_ = keys::kIncognitoContextError;
    231       return false;
    232     }
    233   }
    234 
    235   if (scope == kExtensionPrefsScopeIncognitoSessionOnly &&
    236       !GetProfile()->HasOffTheRecordProfile()) {
    237     error_ = pref_keys::kIncognitoSessionOnlyErrorMessage;
    238     return false;
    239   }
    240 
    241   scoped_refptr<ContentSettingsStore> store =
    242       ContentSettingsService::Get(GetProfile())->content_settings_store();
    243   store->SetExtensionContentSetting(extension_id(), primary_pattern,
    244                                     secondary_pattern, content_type,
    245                                     resource_identifier, setting, scope);
    246   return true;
    247 }
    248 
    249 bool ContentSettingsContentSettingGetResourceIdentifiersFunction::RunAsync() {
    250   ContentSettingsType content_type;
    251   EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_.get(), &content_type));
    252 
    253   if (content_type != CONTENT_SETTINGS_TYPE_PLUGINS) {
    254     SendResponse(true);
    255     return true;
    256   }
    257 
    258   PluginService::GetInstance()->GetPlugins(
    259       base::Bind(&ContentSettingsContentSettingGetResourceIdentifiersFunction::
    260                  OnGotPlugins,
    261                  this));
    262   return true;
    263 }
    264 
    265 void ContentSettingsContentSettingGetResourceIdentifiersFunction::OnGotPlugins(
    266     const std::vector<content::WebPluginInfo>& plugins) {
    267   PluginFinder* finder = PluginFinder::GetInstance();
    268   std::set<std::string> group_identifiers;
    269   base::ListValue* list = new base::ListValue();
    270   for (std::vector<content::WebPluginInfo>::const_iterator it = plugins.begin();
    271        it != plugins.end(); ++it) {
    272     scoped_ptr<PluginMetadata> plugin_metadata(finder->GetPluginMetadata(*it));
    273     const std::string& group_identifier = plugin_metadata->identifier();
    274     if (group_identifiers.find(group_identifier) != group_identifiers.end())
    275       continue;
    276 
    277     group_identifiers.insert(group_identifier);
    278     base::DictionaryValue* dict = new base::DictionaryValue();
    279     dict->SetString(keys::kIdKey, group_identifier);
    280     dict->SetString(keys::kDescriptionKey, plugin_metadata->name());
    281     list->Append(dict);
    282   }
    283   SetResult(list);
    284   BrowserThread::PostTask(
    285       BrowserThread::UI, FROM_HERE, base::Bind(
    286           &ContentSettingsContentSettingGetResourceIdentifiersFunction::
    287           SendResponse,
    288           this,
    289           true));
    290 }
    291 
    292 }  // namespace extensions
    293