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.
5 #include "chrome/browser/extensions/api/content_settings/content_settings_api.h"
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"
31 using content::BrowserThread
;
32 using content::PluginService
;
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
;
42 bool RemoveContentType(base::ListValue
* args
,
43 ContentSettingsType
* content_type
) {
44 std::string content_type_str
;
45 if (!args
->GetString(0, &content_type_str
))
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
);
51 extensions::content_settings_helpers::StringToContentSettingsType(
53 return *content_type
!= CONTENT_SETTINGS_TYPE_DEFAULT
;
58 namespace extensions
{
60 namespace helpers
= content_settings_helpers
;
61 namespace keys
= content_settings_api_constants
;
63 bool ContentSettingsContentSettingClearFunction::RunSync() {
64 ContentSettingsType content_type
;
65 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_
.get(), &content_type
));
67 scoped_ptr
<Clear::Params
> params(Clear::Params::Create(*args_
));
68 EXTENSION_FUNCTION_VALIDATE(params
.get());
70 ExtensionPrefsScope scope
= kExtensionPrefsScopeRegular
;
71 bool incognito
= false;
72 if (params
->details
.scope
==
73 Clear::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY
) {
74 scope
= kExtensionPrefsScopeIncognitoSessionOnly
;
79 // We don't check incognito permissions here, as an extension should be
80 // always allowed to clear its own settings.
82 // Incognito profiles can't access regular mode ever, they only exist in
84 if (GetProfile()->IsOffTheRecord()) {
85 error_
= keys::kIncognitoContextError
;
90 ContentSettingsStore
* store
=
91 ContentSettingsService::Get(GetProfile())->content_settings_store();
92 store
->ClearContentSettingsForExtension(extension_id(), scope
);
97 bool ContentSettingsContentSettingGetFunction::RunSync() {
98 ContentSettingsType content_type
;
99 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_
.get(), &content_type
));
101 scoped_ptr
<Get::Params
> params(Get::Params::Create(*args_
));
102 EXTENSION_FUNCTION_VALIDATE(params
.get());
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
);
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
);
121 std::string resource_identifier
;
122 if (params
->details
.resource_identifier
.get())
123 resource_identifier
= params
->details
.resource_identifier
->id
;
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
;
133 HostContentSettingsMap
* map
;
134 CookieSettings
* cookie_settings
;
136 if (!GetProfile()->HasOffTheRecordProfile()) {
137 // TODO(bauerb): Allow reading incognito content settings
138 // outside of an incognito session.
139 error_
= keys::kIncognitoSessionOnlyError
;
142 map
= GetProfile()->GetOffTheRecordProfile()->GetHostContentSettingsMap();
143 cookie_settings
= CookieSettings::Factory::GetForProfile(
144 GetProfile()->GetOffTheRecordProfile()).get();
146 map
= GetProfile()->GetHostContentSettingsMap();
148 CookieSettings::Factory::GetForProfile(GetProfile()).get();
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
);
158 setting
= map
->GetContentSetting(primary_url
, secondary_url
, content_type
,
159 resource_identifier
);
162 base::DictionaryValue
* result
= new base::DictionaryValue();
163 result
->SetString(keys::kContentSettingKey
,
164 helpers::ContentSettingToString(setting
));
171 bool ContentSettingsContentSettingSetFunction::RunSync() {
172 ContentSettingsType content_type
;
173 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_
.get(), &content_type
));
175 scoped_ptr
<Set::Params
> params(Set::Params::Create(*args_
));
176 EXTENSION_FUNCTION_VALIDATE(params
.get());
178 std::string primary_error
;
179 ContentSettingsPattern primary_pattern
=
180 helpers::ParseExtensionPattern(params
->details
.primary_pattern
,
182 if (!primary_pattern
.IsValid()) {
183 error_
= primary_error
;
187 ContentSettingsPattern secondary_pattern
= ContentSettingsPattern::Wildcard();
188 if (params
->details
.secondary_pattern
.get()) {
189 std::string secondary_error
;
191 helpers::ParseExtensionPattern(*params
->details
.secondary_pattern
,
193 if (!secondary_pattern
.IsValid()) {
194 error_
= secondary_error
;
199 std::string resource_identifier
;
200 if (params
->details
.resource_identifier
.get())
201 resource_identifier
= params
->details
.resource_identifier
->id
;
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
));
212 ExtensionPrefsScope scope
= kExtensionPrefsScopeRegular
;
213 bool incognito
= false;
214 if (params
->details
.scope
==
215 Set::Params::Details::SCOPE_INCOGNITO_SESSION_ONLY
) {
216 scope
= kExtensionPrefsScopeIncognitoSessionOnly
;
221 // Regular profiles can't access incognito unless include_incognito is true.
222 if (!GetProfile()->IsOffTheRecord() && !include_incognito()) {
223 error_
= pref_keys::kIncognitoErrorMessage
;
227 // Incognito profiles can't access regular mode ever, they only exist in
229 if (GetProfile()->IsOffTheRecord()) {
230 error_
= keys::kIncognitoContextError
;
235 if (scope
== kExtensionPrefsScopeIncognitoSessionOnly
&&
236 !GetProfile()->HasOffTheRecordProfile()) {
237 error_
= pref_keys::kIncognitoSessionOnlyErrorMessage
;
241 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
);
249 bool ContentSettingsContentSettingGetResourceIdentifiersFunction::RunAsync() {
250 ContentSettingsType content_type
;
251 EXTENSION_FUNCTION_VALIDATE(RemoveContentType(args_
.get(), &content_type
));
253 if (content_type
!= CONTENT_SETTINGS_TYPE_PLUGINS
) {
258 PluginService::GetInstance()->GetPlugins(
259 base::Bind(&ContentSettingsContentSettingGetResourceIdentifiersFunction::
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())
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());
284 BrowserThread::PostTask(
285 BrowserThread::UI
, FROM_HERE
, base::Bind(
286 &ContentSettingsContentSettingGetResourceIdentifiersFunction::
292 } // namespace extensions