| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/extensions/extension_content_settings_api.h" |
| |
| #include <vector> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/values.h" |
| #include "chrome/browser/content_settings/host_content_settings_map.h" |
| #include "chrome/browser/extensions/extension_content_settings_api_constants.h" |
| #include "chrome/browser/extensions/extension_content_settings_helpers.h" |
| #include "chrome/browser/extensions/extension_content_settings_store.h" |
| #include "chrome/browser/extensions/extension_preference_api_constants.h" |
| #include "chrome/browser/extensions/extension_preference_helpers.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/extension_error_utils.h" |
| #include "webkit/plugins/npapi/plugin_group.h" |
| #include "webkit/plugins/npapi/plugin_list.h" |
| |
| namespace helpers = extension_content_settings_helpers; |
| namespace keys = extension_content_settings_api_constants; |
| namespace pref_helpers = extension_preference_helpers; |
| namespace pref_keys = extension_preference_api_constants; |
| |
| namespace { |
| |
| webkit::npapi::PluginList* g_plugin_list = NULL; |
| |
| } // namespace |
| |
| bool ClearContentSettingsFunction::RunImpl() { |
| std::string content_type_str; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &content_type_str)); |
| ContentSettingsType content_type = |
| helpers::StringToContentSettingsType(content_type_str); |
| EXTENSION_FUNCTION_VALIDATE(content_type != CONTENT_SETTINGS_TYPE_DEFAULT); |
| |
| DictionaryValue* details = NULL; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); |
| |
| ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; |
| if (details->HasKey(pref_keys::kScopeKey)) { |
| std::string scope_str; |
| EXTENSION_FUNCTION_VALIDATE(details->GetString(pref_keys::kScopeKey, |
| &scope_str)); |
| |
| EXTENSION_FUNCTION_VALIDATE(pref_helpers::StringToScope(scope_str, &scope)); |
| EXTENSION_FUNCTION_VALIDATE( |
| scope != kExtensionPrefsScopeIncognitoPersistent); |
| } |
| |
| bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent || |
| scope == kExtensionPrefsScopeIncognitoSessionOnly); |
| if (incognito) { |
| // We don't check incognito permissions here, as an extension should be |
| // always allowed to clear its own settings. |
| } else { |
| // Incognito profiles can't access regular mode ever, they only exist in |
| // split mode. |
| if (profile()->IsOffTheRecord()) { |
| error_ = keys::kIncognitoContextError; |
| return false; |
| } |
| } |
| |
| ExtensionContentSettingsStore* store = |
| profile_->GetExtensionService()->GetExtensionContentSettingsStore(); |
| store->ClearContentSettingsForExtension(extension_id(), scope); |
| |
| return true; |
| } |
| |
| bool GetContentSettingFunction::RunImpl() { |
| std::string content_type_str; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &content_type_str)); |
| ContentSettingsType content_type = |
| helpers::StringToContentSettingsType(content_type_str); |
| EXTENSION_FUNCTION_VALIDATE(content_type != CONTENT_SETTINGS_TYPE_DEFAULT); |
| |
| DictionaryValue* details = NULL; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); |
| |
| std::string primary_url_spec; |
| EXTENSION_FUNCTION_VALIDATE( |
| details->GetString(keys::kPrimaryUrlKey, &primary_url_spec)); |
| GURL primary_url(primary_url_spec); |
| if (!primary_url.is_valid()) { |
| error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, |
| primary_url_spec); |
| return false; |
| } |
| |
| GURL secondary_url(primary_url); |
| std::string secondary_url_spec; |
| if (details->GetString(keys::kSecondaryUrlKey, &secondary_url_spec)) { |
| secondary_url = GURL(secondary_url_spec); |
| if (!secondary_url.is_valid()) { |
| error_ = ExtensionErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, |
| secondary_url_spec); |
| return false; |
| } |
| } |
| |
| std::string resource_identifier; |
| if (details->HasKey(keys::kResourceIdentifierKey)) { |
| DictionaryValue* resource_identifier_dict = NULL; |
| EXTENSION_FUNCTION_VALIDATE( |
| details->GetDictionary(keys::kResourceIdentifierKey, |
| &resource_identifier_dict)); |
| EXTENSION_FUNCTION_VALIDATE( |
| resource_identifier_dict->GetString(keys::kIdKey, |
| &resource_identifier)); |
| } |
| |
| bool incognito = false; |
| if (details->HasKey(pref_keys::kIncognitoKey)) { |
| EXTENSION_FUNCTION_VALIDATE( |
| details->GetBoolean(pref_keys::kIncognitoKey, &incognito)); |
| } |
| if (incognito && !include_incognito()) { |
| error_ = pref_keys::kIncognitoErrorMessage; |
| return false; |
| } |
| |
| HostContentSettingsMap* map; |
| if (incognito) { |
| if (!profile()->HasOffTheRecordProfile()) { |
| // TODO(bauerb): Allow reading incognito content settings |
| // outside of an incognito session. |
| error_ = keys::kIncognitoSessionOnlyError; |
| return false; |
| } |
| map = profile()->GetOffTheRecordProfile()->GetHostContentSettingsMap(); |
| } else { |
| map = profile()->GetHostContentSettingsMap(); |
| } |
| |
| ContentSetting setting; |
| if (content_type == CONTENT_SETTINGS_TYPE_COOKIES) { |
| // TODO(jochen): Do we return the value for setting or for reading cookies? |
| bool setting_cookie = false; |
| setting = map->GetCookieContentSetting(primary_url, secondary_url, |
| setting_cookie); |
| } else { |
| setting = map->GetContentSetting(primary_url, secondary_url, content_type, |
| resource_identifier); |
| } |
| |
| DictionaryValue* result = new DictionaryValue(); |
| result->SetString(keys::kContentSettingKey, |
| helpers::ContentSettingToString(setting)); |
| |
| result_.reset(result); |
| |
| return true; |
| } |
| |
| bool SetContentSettingFunction::RunImpl() { |
| std::string content_type_str; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &content_type_str)); |
| ContentSettingsType content_type = |
| helpers::StringToContentSettingsType(content_type_str); |
| EXTENSION_FUNCTION_VALIDATE(content_type != CONTENT_SETTINGS_TYPE_DEFAULT); |
| |
| DictionaryValue* details = NULL; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &details)); |
| |
| std::string primary_pattern_str; |
| EXTENSION_FUNCTION_VALIDATE( |
| details->GetString(keys::kPrimaryPatternKey, &primary_pattern_str)); |
| std::string primary_error; |
| ContentSettingsPattern primary_pattern = |
| helpers::ParseExtensionPattern(primary_pattern_str, &primary_error); |
| if (!primary_pattern.IsValid()) { |
| error_ = primary_error; |
| return false; |
| } |
| |
| ContentSettingsPattern secondary_pattern = ContentSettingsPattern::Wildcard(); |
| std::string secondary_pattern_str; |
| if (details->GetString(keys::kSecondaryPatternKey, &secondary_pattern_str)) { |
| std::string secondary_error; |
| secondary_pattern = |
| helpers::ParseExtensionPattern(secondary_pattern_str, &secondary_error); |
| if (!secondary_pattern.IsValid()) { |
| error_ = secondary_error; |
| return false; |
| } |
| } |
| |
| std::string resource_identifier; |
| if (details->HasKey(keys::kResourceIdentifierKey)) { |
| DictionaryValue* resource_identifier_dict = NULL; |
| EXTENSION_FUNCTION_VALIDATE( |
| details->GetDictionary(keys::kResourceIdentifierKey, |
| &resource_identifier_dict)); |
| EXTENSION_FUNCTION_VALIDATE( |
| resource_identifier_dict->GetString(keys::kIdKey, |
| &resource_identifier)); |
| } |
| |
| std::string setting_str; |
| EXTENSION_FUNCTION_VALIDATE( |
| details->GetString(keys::kContentSettingKey, &setting_str)); |
| ContentSetting setting = CONTENT_SETTING_DEFAULT; |
| EXTENSION_FUNCTION_VALIDATE( |
| helpers::StringToContentSetting(setting_str, &setting)); |
| EXTENSION_FUNCTION_VALIDATE( |
| HostContentSettingsMap::IsSettingAllowedForType(setting, content_type)); |
| |
| ExtensionPrefsScope scope = kExtensionPrefsScopeRegular; |
| if (details->HasKey(pref_keys::kScopeKey)) { |
| std::string scope_str; |
| EXTENSION_FUNCTION_VALIDATE(details->GetString(pref_keys::kScopeKey, |
| &scope_str)); |
| |
| EXTENSION_FUNCTION_VALIDATE(pref_helpers::StringToScope(scope_str, &scope)); |
| EXTENSION_FUNCTION_VALIDATE( |
| scope != kExtensionPrefsScopeIncognitoPersistent); |
| } |
| |
| bool incognito = (scope == kExtensionPrefsScopeIncognitoPersistent || |
| scope == kExtensionPrefsScopeIncognitoSessionOnly); |
| if (incognito) { |
| // Regular profiles can't access incognito unless include_incognito is true. |
| if (!profile()->IsOffTheRecord() && !include_incognito()) { |
| error_ = pref_keys::kIncognitoErrorMessage; |
| return false; |
| } |
| } else { |
| // Incognito profiles can't access regular mode ever, they only exist in |
| // split mode. |
| if (profile()->IsOffTheRecord()) { |
| error_ = keys::kIncognitoContextError; |
| return false; |
| } |
| } |
| |
| if (scope == kExtensionPrefsScopeIncognitoSessionOnly && |
| !profile_->HasOffTheRecordProfile()) { |
| error_ = pref_keys::kIncognitoSessionOnlyErrorMessage; |
| return false; |
| } |
| |
| ExtensionContentSettingsStore* store = |
| profile_->GetExtensionService()->GetExtensionContentSettingsStore(); |
| store->SetExtensionContentSetting(extension_id(), primary_pattern, |
| secondary_pattern, content_type, |
| resource_identifier, setting, scope); |
| return true; |
| } |
| |
| bool GetResourceIdentifiersFunction::RunImpl() { |
| std::string content_type_str; |
| EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &content_type_str)); |
| ContentSettingsType content_type = |
| helpers::StringToContentSettingsType(content_type_str); |
| EXTENSION_FUNCTION_VALIDATE(content_type != CONTENT_SETTINGS_TYPE_DEFAULT); |
| |
| if (content_type == CONTENT_SETTINGS_TYPE_PLUGINS && |
| CommandLine::ForCurrentProcess()->HasSwitch( |
| switches::kEnableResourceContentSettings)) { |
| BrowserThread::PostTask( |
| BrowserThread::FILE, FROM_HERE, |
| base::Bind(&GetResourceIdentifiersFunction::GetPluginsOnFileThread, |
| this)); |
| } else { |
| SendResponse(true); |
| } |
| |
| return true; |
| } |
| |
| void GetResourceIdentifiersFunction::GetPluginsOnFileThread() { |
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| webkit::npapi::PluginList* plugin_list = g_plugin_list; |
| if (!plugin_list) { |
| plugin_list = webkit::npapi::PluginList::Singleton(); |
| } |
| |
| std::vector<webkit::npapi::PluginGroup> groups; |
| plugin_list->GetPluginGroups(true, &groups); |
| |
| ListValue* list = new ListValue(); |
| for (std::vector<webkit::npapi::PluginGroup>::iterator it = groups.begin(); |
| it != groups.end(); ++it) { |
| DictionaryValue* dict = new DictionaryValue(); |
| dict->SetString(keys::kIdKey, it->identifier()); |
| dict->SetString(keys::kDescriptionKey, it->GetGroupName()); |
| list->Append(dict); |
| } |
| result_.reset(list); |
| BrowserThread::PostTask( |
| BrowserThread::UI, FROM_HERE, base::Bind( |
| &GetResourceIdentifiersFunction::SendResponse, this, true)); |
| } |
| |
| // static |
| void GetResourceIdentifiersFunction::SetPluginListForTesting( |
| webkit::npapi::PluginList* plugin_list) { |
| g_plugin_list = plugin_list; |
| } |