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/ui/webui/options/content_settings_handler.h"
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/content_settings/content_settings_details.h"
19 #include "chrome/browser/content_settings/content_settings_utils.h"
20 #include "chrome/browser/content_settings/host_content_settings_map.h"
21 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
22 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
23 #include "chrome/browser/extensions/extension_service.h"
24 #include "chrome/browser/extensions/extension_special_storage_policy.h"
25 #include "chrome/browser/google/google_util.h"
26 #include "chrome/browser/notifications/desktop_notification_service.h"
27 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/content_settings.h"
32 #include "chrome/common/content_settings_pattern.h"
33 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/notification_source.h"
38 #include "content/public/browser/notification_types.h"
39 #include "content/public/browser/user_metrics.h"
40 #include "content/public/browser/web_ui.h"
41 #include "content/public/common/content_switches.h"
42 #include "extensions/common/extension_set.h"
43 #include "extensions/common/permissions/api_permission.h"
44 #include "grit/generated_resources.h"
45 #include "grit/locale_settings.h"
46 #include "ui/base/l10n/l10n_util.h"
48 #if defined(OS_CHROMEOS)
49 #include "chrome/browser/chromeos/login/user_manager.h"
52 using base::UserMetricsAction
;
53 using extensions::APIPermission
;
57 struct ContentSettingsTypeNameEntry
{
58 ContentSettingsType type
;
62 // Maps from a secondary pattern to a setting.
63 typedef std::map
<ContentSettingsPattern
, ContentSetting
>
65 // Maps from a primary pattern/source pair to a OnePatternSettings. All the
66 // mappings in OnePatternSettings share the given primary pattern and source.
67 typedef std::map
<std::pair
<ContentSettingsPattern
, std::string
>,
71 // The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
72 // extensions which should have their extent displayed.
73 typedef bool (*AppFilter
)(const extensions::Extension
& app
, Profile
* profile
);
75 const char kExceptionsLearnMoreUrl
[] =
76 "https://support.google.com/chrome/?p=settings_manage_exceptions";
78 const char* kSetting
= "setting";
79 const char* kOrigin
= "origin";
80 const char* kSource
= "source";
81 const char* kAppName
= "appName";
82 const char* kAppId
= "appId";
83 const char* kEmbeddingOrigin
= "embeddingOrigin";
84 const char* kPreferencesSource
= "preference";
85 const char* kVideoSetting
= "video";
87 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames
[] = {
88 {CONTENT_SETTINGS_TYPE_COOKIES
, "cookies"},
89 {CONTENT_SETTINGS_TYPE_IMAGES
, "images"},
90 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, "javascript"},
91 {CONTENT_SETTINGS_TYPE_PLUGINS
, "plugins"},
92 {CONTENT_SETTINGS_TYPE_POPUPS
, "popups"},
93 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, "location"},
94 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, "notifications"},
95 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
, "auto-select-certificate"},
96 {CONTENT_SETTINGS_TYPE_FULLSCREEN
, "fullscreen"},
97 {CONTENT_SETTINGS_TYPE_MOUSELOCK
, "mouselock"},
98 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, "register-protocol-handler"},
99 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, "media-stream"},
100 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, "media-stream-mic"},
101 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, "media-stream-camera"},
102 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, "ppapi-broker"},
103 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, "multiple-automatic-downloads"},
104 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, "midi-sysex"},
105 #if defined(OS_CHROMEOS)
106 {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
, "protectedContent"},
110 ContentSettingsType
ContentSettingsTypeFromGroupName(const std::string
& name
) {
111 for (size_t i
= 0; i
< arraysize(kContentSettingsTypeGroupNames
); ++i
) {
112 if (name
== kContentSettingsTypeGroupNames
[i
].name
)
113 return kContentSettingsTypeGroupNames
[i
].type
;
116 NOTREACHED() << name
<< " is not a recognized content settings type.";
117 return CONTENT_SETTINGS_TYPE_DEFAULT
;
120 std::string
ContentSettingToString(ContentSetting setting
) {
122 case CONTENT_SETTING_ALLOW
:
124 case CONTENT_SETTING_ASK
:
126 case CONTENT_SETTING_BLOCK
:
128 case CONTENT_SETTING_SESSION_ONLY
:
130 case CONTENT_SETTING_DEFAULT
:
132 case CONTENT_SETTING_NUM_SETTINGS
:
136 return std::string();
139 ContentSetting
ContentSettingFromString(const std::string
& name
) {
141 return CONTENT_SETTING_ALLOW
;
143 return CONTENT_SETTING_ASK
;
145 return CONTENT_SETTING_BLOCK
;
146 if (name
== "session")
147 return CONTENT_SETTING_SESSION_ONLY
;
149 NOTREACHED() << name
<< " is not a recognized content setting.";
150 return CONTENT_SETTING_DEFAULT
;
153 // Create a DictionaryValue* that will act as a data source for a single row
154 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
155 // Ownership of the pointer is passed to the caller.
156 base::DictionaryValue
* GetExceptionForPage(
157 const ContentSettingsPattern
& pattern
,
158 const ContentSettingsPattern
& secondary_pattern
,
159 const ContentSetting
& setting
,
160 const std::string
& provider_name
) {
161 base::DictionaryValue
* exception
= new base::DictionaryValue();
162 exception
->SetString(kOrigin
, pattern
.ToString());
163 exception
->SetString(kEmbeddingOrigin
,
164 secondary_pattern
== ContentSettingsPattern::Wildcard()
166 : secondary_pattern
.ToString());
167 exception
->SetString(kSetting
, ContentSettingToString(setting
));
168 exception
->SetString(kSource
, provider_name
);
172 // Create a DictionaryValue* that will act as a data source for a single row
173 // in the Geolocation exceptions table. Ownership of the pointer is passed to
175 base::DictionaryValue
* GetGeolocationExceptionForPage(
176 const ContentSettingsPattern
& origin
,
177 const ContentSettingsPattern
& embedding_origin
,
178 ContentSetting setting
) {
179 base::DictionaryValue
* exception
= new base::DictionaryValue();
180 exception
->SetString(kSetting
, ContentSettingToString(setting
));
181 exception
->SetString(kOrigin
, origin
.ToString());
182 exception
->SetString(kEmbeddingOrigin
, embedding_origin
.ToString());
186 // Create a DictionaryValue* that will act as a data source for a single row
187 // in the desktop notifications exceptions table. Ownership of the pointer is
188 // passed to the caller.
189 base::DictionaryValue
* GetNotificationExceptionForPage(
190 const ContentSettingsPattern
& pattern
,
191 ContentSetting setting
,
192 const std::string
& provider_name
) {
193 base::DictionaryValue
* exception
= new base::DictionaryValue();
194 exception
->SetString(kSetting
, ContentSettingToString(setting
));
195 exception
->SetString(kOrigin
, pattern
.ToString());
196 exception
->SetString(kSource
, provider_name
);
200 // Returns true whenever the |extension| is hosted and has |permission|.
201 // Must have the AppFilter signature.
202 template <APIPermission::ID permission
>
203 bool HostedAppHasPermission(
204 const extensions::Extension
& extension
, Profile
* /*profile*/) {
205 return extension
.is_hosted_app() && extension
.HasAPIPermission(permission
);
208 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
209 // the web extent of a hosted |app|.
210 void AddExceptionForHostedApp(const std::string
& url_pattern
,
211 const extensions::Extension
& app
, base::ListValue
* exceptions
) {
212 base::DictionaryValue
* exception
= new base::DictionaryValue();
213 exception
->SetString(kSetting
, ContentSettingToString(CONTENT_SETTING_ALLOW
));
214 exception
->SetString(kOrigin
, url_pattern
);
215 exception
->SetString(kEmbeddingOrigin
, url_pattern
);
216 exception
->SetString(kSource
, "HostedApp");
217 exception
->SetString(kAppName
, app
.name());
218 exception
->SetString(kAppId
, app
.id());
219 exceptions
->Append(exception
);
222 // Asks the |profile| for hosted apps which have the |permission| set, and
223 // adds their web extent and launch URL to the |exceptions| list.
224 void AddExceptionsGrantedByHostedApps(
225 Profile
* profile
, AppFilter app_filter
, base::ListValue
* exceptions
) {
226 const ExtensionService
* extension_service
= profile
->GetExtensionService();
227 // After ExtensionSystem::Init has been called at the browser's start,
228 // GetExtensionService() should not return NULL, so this is safe:
229 const extensions::ExtensionSet
* extensions
= extension_service
->extensions();
231 for (extensions::ExtensionSet::const_iterator extension
= extensions
->begin();
232 extension
!= extensions
->end(); ++extension
) {
233 if (!app_filter(*extension
->get(), profile
))
236 extensions::URLPatternSet web_extent
= (*extension
)->web_extent();
237 // Add patterns from web extent.
238 for (extensions::URLPatternSet::const_iterator pattern
= web_extent
.begin();
239 pattern
!= web_extent
.end(); ++pattern
) {
240 std::string url_pattern
= pattern
->GetAsString();
241 AddExceptionForHostedApp(url_pattern
, *extension
->get(), exceptions
);
243 // Retrieve the launch URL.
245 extensions::AppLaunchInfo::GetLaunchWebURL(extension
->get());
246 // Skip adding the launch URL if it is part of the web extent.
247 if (web_extent
.MatchesURL(launch_url
))
249 AddExceptionForHostedApp(launch_url
.spec(), *extension
->get(), exceptions
);
257 ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo()
258 : flash_default_setting(CONTENT_SETTING_DEFAULT
),
259 flash_settings_initialized(false),
260 last_flash_refresh_request_id(0),
261 show_flash_default_link(false),
262 show_flash_exceptions_link(false),
263 default_setting(CONTENT_SETTING_DEFAULT
),
264 policy_disable_audio(false),
265 policy_disable_video(false),
266 default_setting_initialized(false),
267 exceptions_initialized(false) {
270 ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
273 ContentSettingsHandler::ContentSettingsHandler() {
276 ContentSettingsHandler::~ContentSettingsHandler() {
279 void ContentSettingsHandler::GetLocalizedValues(
280 base::DictionaryValue
* localized_strings
) {
281 DCHECK(localized_strings
);
283 static OptionsStringResource resources
[] = {
284 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON
},
285 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON
},
286 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON
},
287 { "askException", IDS_EXCEPTIONS_ASK_BUTTON
},
288 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL
},
289 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS
},
290 { "manageExceptions", IDS_EXCEPTIONS_MANAGE
},
291 { "manage_handlers", IDS_HANDLERS_MANAGE
},
292 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER
},
293 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER
},
294 { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST
},
296 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL
},
297 { "cookies_header", IDS_COOKIES_HEADER
},
298 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO
},
299 { "cookies_block", IDS_COOKIES_BLOCK_RADIO
},
300 { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO
},
301 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX
},
302 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX
},
303 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX
},
304 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON
},
305 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS
},
306 { "flash_storage_url", IDS_FLASH_STORAGE_URL
},
307 #if defined(ENABLE_GOOGLE_NOW)
308 { "googleGeolocationAccessEnable",
309 IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX
},
312 { "images_tab_label", IDS_IMAGES_TAB_LABEL
},
313 { "images_header", IDS_IMAGES_HEADER
},
314 { "images_allow", IDS_IMAGES_LOAD_RADIO
},
315 { "images_block", IDS_IMAGES_NOLOAD_RADIO
},
316 // JavaScript filter.
317 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL
},
318 { "javascript_header", IDS_JAVASCRIPT_HEADER
},
319 { "javascript_allow", IDS_JS_ALLOW_RADIO
},
320 { "javascript_block", IDS_JS_DONOTALLOW_RADIO
},
322 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL
},
323 { "plugins_header", IDS_PLUGIN_HEADER
},
324 { "plugins_ask", IDS_PLUGIN_ASK_RADIO
},
325 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO
},
326 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO
},
327 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE
},
329 { "popups_tab_label", IDS_POPUP_TAB_LABEL
},
330 { "popups_header", IDS_POPUP_HEADER
},
331 { "popups_allow", IDS_POPUP_ALLOW_RADIO
},
332 { "popups_block", IDS_POPUP_BLOCK_RADIO
},
334 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL
},
335 { "location_header", IDS_GEOLOCATION_HEADER
},
336 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO
},
337 { "location_ask", IDS_GEOLOCATION_ASK_RADIO
},
338 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO
},
339 { "set_by", IDS_GEOLOCATION_SET_BY_HOVER
},
340 // Notifications filter.
341 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL
},
342 { "notifications_header", IDS_NOTIFICATIONS_HEADER
},
343 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO
},
344 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO
},
345 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO
},
346 // Fullscreen filter.
347 { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL
},
348 { "fullscreen_header", IDS_FULLSCREEN_HEADER
},
349 // Mouse Lock filter.
350 { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL
},
351 { "mouselock_header", IDS_MOUSE_LOCK_HEADER
},
352 { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO
},
353 { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO
},
354 { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO
},
355 #if defined(OS_CHROMEOS) || defined(OS_WIN)
356 // Protected Content filter
357 { "protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL
},
358 { "protectedContentInfo", IDS_PROTECTED_CONTENT_INFO
},
359 { "protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE
},
360 { "protectedContent_header", IDS_PROTECTED_CONTENT_HEADER
},
361 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
362 // Media stream capture device filter.
363 { "mediaStreamTabLabel", IDS_MEDIA_STREAM_TAB_LABEL
},
364 { "media-stream_header", IDS_MEDIA_STREAM_HEADER
},
365 { "mediaStreamAsk", IDS_MEDIA_STREAM_ASK_RADIO
},
366 { "mediaStreamBlock", IDS_MEDIA_STREAM_BLOCK_RADIO
},
367 { "mediaStreamAudioAsk", IDS_MEDIA_STREAM_ASK_AUDIO_ONLY_RADIO
},
368 { "mediaStreamAudioBlock", IDS_MEDIA_STREAM_BLOCK_AUDIO_ONLY_RADIO
},
369 { "mediaStreamVideoAsk", IDS_MEDIA_STREAM_ASK_VIDEO_ONLY_RADIO
},
370 { "mediaStreamVideoBlock", IDS_MEDIA_STREAM_BLOCK_VIDEO_ONLY_RADIO
},
371 { "mediaStreamBubbleAudio", IDS_MEDIA_STREAM_AUDIO_MANAGED
},
372 { "mediaStreamBubbleVideo", IDS_MEDIA_STREAM_VIDEO_MANAGED
},
373 { "mediaAudioExceptionHeader", IDS_MEDIA_AUDIO_EXCEPTION_HEADER
},
374 { "mediaVideoExceptionHeader", IDS_MEDIA_VIDEO_EXCEPTION_HEADER
},
375 { "mediaPepperFlashDefaultDivergedLabel",
376 IDS_MEDIA_PEPPER_FLASH_DEFAULT_DIVERGED_LABEL
},
377 { "mediaPepperFlashExceptionsDivergedLabel",
378 IDS_MEDIA_PEPPER_FLASH_EXCEPTIONS_DIVERGED_LABEL
},
379 { "mediaPepperFlashChangeLink", IDS_MEDIA_PEPPER_FLASH_CHANGE_LINK
},
380 { "mediaPepperFlashGlobalPrivacyURL", IDS_FLASH_GLOBAL_PRIVACY_URL
},
381 { "mediaPepperFlashWebsitePrivacyURL", IDS_FLASH_WEBSITE_PRIVACY_URL
},
382 // PPAPI broker filter.
383 // TODO(bauerb): Use IDS_PPAPI_BROKER_HEADER.
384 { "ppapi-broker_header", IDS_PPAPI_BROKER_TAB_LABEL
},
385 { "ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL
},
386 { "ppapi_broker_allow", IDS_PPAPI_BROKER_ALLOW_RADIO
},
387 { "ppapi_broker_ask", IDS_PPAPI_BROKER_ASK_RADIO
},
388 { "ppapi_broker_block", IDS_PPAPI_BROKER_BLOCK_RADIO
},
389 // Multiple automatic downloads
390 { "multiple-automatic-downloads_header",
391 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL
},
392 { "multiple-automatic-downloads_allow",
393 IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO
},
394 { "multiple-automatic-downloads_ask",
395 IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO
},
396 { "multiple-automatic-downloads_block",
397 IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO
},
398 // MIDI system exclusive messages
399 { "midi-sysex_header", IDS_MIDI_SYSEX_TAB_LABEL
},
400 { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO
},
401 { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO
},
402 { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO
},
405 RegisterStrings(localized_strings
, resources
, arraysize(resources
));
406 RegisterTitle(localized_strings
, "contentSettingsPage",
407 IDS_CONTENT_SETTINGS_TITLE
);
409 // Register titles for each of the individual settings whose exception
410 // dialogs will be processed by |ContentSettingsHandler|.
411 RegisterTitle(localized_strings
, "cookies",
412 IDS_COOKIES_TAB_LABEL
);
413 RegisterTitle(localized_strings
, "images",
414 IDS_IMAGES_TAB_LABEL
);
415 RegisterTitle(localized_strings
, "javascript",
416 IDS_JAVASCRIPT_TAB_LABEL
);
417 RegisterTitle(localized_strings
, "plugins",
418 IDS_PLUGIN_TAB_LABEL
);
419 RegisterTitle(localized_strings
, "popups",
420 IDS_POPUP_TAB_LABEL
);
421 RegisterTitle(localized_strings
, "location",
422 IDS_GEOLOCATION_TAB_LABEL
);
423 RegisterTitle(localized_strings
, "notifications",
424 IDS_NOTIFICATIONS_TAB_LABEL
);
425 RegisterTitle(localized_strings
, "fullscreen",
426 IDS_FULLSCREEN_TAB_LABEL
);
427 RegisterTitle(localized_strings
, "mouselock",
428 IDS_MOUSE_LOCK_TAB_LABEL
);
429 #if defined(OS_CHROMEOS)
430 RegisterTitle(localized_strings
, "protectedContent",
431 IDS_PROTECTED_CONTENT_TAB_LABEL
);
433 RegisterTitle(localized_strings
, "media-stream",
434 IDS_MEDIA_STREAM_TAB_LABEL
);
435 RegisterTitle(localized_strings
, "ppapi-broker",
436 IDS_PPAPI_BROKER_TAB_LABEL
);
437 RegisterTitle(localized_strings
, "multiple-automatic-downloads",
438 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL
);
439 RegisterTitle(localized_strings
, "midi-sysex",
440 IDS_MIDI_SYSEX_TAB_LABEL
);
442 localized_strings
->SetBoolean("newContentSettings",
443 CommandLine::ForCurrentProcess()->HasSwitch(switches::kContentSettings2
));
444 localized_strings
->SetString(
445 "exceptionsLearnMoreUrl",
446 google_util::StringAppendGoogleLocaleParam(
447 kExceptionsLearnMoreUrl
));
450 void ContentSettingsHandler::InitializeHandler() {
451 notification_registrar_
.Add(
452 this, chrome::NOTIFICATION_PROFILE_CREATED
,
453 content::NotificationService::AllSources());
454 notification_registrar_
.Add(
455 this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
456 content::NotificationService::AllSources());
458 notification_registrar_
.Add(
459 this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED
,
460 content::NotificationService::AllSources());
461 notification_registrar_
.Add(
462 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED
,
463 content::NotificationService::AllSources());
464 Profile
* profile
= Profile::FromWebUI(web_ui());
465 notification_registrar_
.Add(
466 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED
,
467 content::Source
<Profile
>(profile
));
469 PrefService
* prefs
= profile
->GetPrefs();
470 pref_change_registrar_
.Init(prefs
);
471 pref_change_registrar_
.Add(
472 prefs::kPepperFlashSettingsEnabled
,
473 base::Bind(&ContentSettingsHandler::OnPepperFlashPrefChanged
,
474 base::Unretained(this)));
475 pref_change_registrar_
.Add(
476 prefs::kAudioCaptureAllowed
,
477 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView
,
478 base::Unretained(this)));
479 pref_change_registrar_
.Add(
480 prefs::kVideoCaptureAllowed
,
481 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView
,
482 base::Unretained(this)));
483 pref_change_registrar_
.Add(
486 &ContentSettingsHandler::UpdateProtectedContentExceptionsButton
,
487 base::Unretained(this)));
489 flash_settings_manager_
.reset(new PepperFlashSettingsManager(this, profile
));
492 void ContentSettingsHandler::InitializePage() {
493 media_settings_
= MediaSettingsInfo();
494 RefreshFlashMediaSettings();
496 UpdateHandlersEnabledRadios();
497 UpdateAllExceptionsViewsFromModel();
498 UpdateProtectedContentExceptionsButton();
501 void ContentSettingsHandler::Observe(
503 const content::NotificationSource
& source
,
504 const content::NotificationDetails
& details
) {
506 case chrome::NOTIFICATION_PROFILE_DESTROYED
: {
507 if (content::Source
<Profile
>(source
).ptr()->IsOffTheRecord()) {
508 web_ui()->CallJavascriptFunction(
509 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
514 case chrome::NOTIFICATION_PROFILE_CREATED
: {
515 if (content::Source
<Profile
>(source
).ptr()->IsOffTheRecord())
516 UpdateAllOTRExceptionsViewsFromModel();
520 case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED
: {
521 // Filter out notifications from other profiles.
522 HostContentSettingsMap
* map
=
523 content::Source
<HostContentSettingsMap
>(source
).ptr();
524 if (map
!= GetContentSettingsMap() &&
525 map
!= GetOTRContentSettingsMap())
528 const ContentSettingsDetails
* settings_details
=
529 content::Details
<const ContentSettingsDetails
>(details
).ptr();
531 // TODO(estade): we pretend update_all() is always true.
532 if (settings_details
->update_all_types())
533 UpdateAllExceptionsViewsFromModel();
535 UpdateExceptionsViewFromModel(settings_details
->type());
539 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED
: {
540 UpdateNotificationExceptionsView();
544 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED
: {
545 UpdateHandlersEnabledRadios();
551 void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
554 PP_Flash_BrowserOperations_Permission default_permission
,
555 const ppapi::FlashSiteSettings
& sites
) {
556 if (success
&& request_id
== media_settings_
.last_flash_refresh_request_id
) {
557 media_settings_
.flash_settings_initialized
= true;
558 media_settings_
.flash_default_setting
=
559 PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
561 PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
562 sites
, &media_settings_
.flash_exceptions
);
563 PepperFlashContentSettingsUtils::SortMediaExceptions(
564 &media_settings_
.flash_exceptions
);
566 UpdateFlashMediaLinksVisibility();
570 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
571 ContentSettingsType type
) {
572 base::DictionaryValue filter_settings
;
573 std::string provider_id
;
574 filter_settings
.SetString(ContentSettingsTypeToGroupName(type
) + ".value",
575 GetSettingDefaultFromModel(type
, &provider_id
));
576 filter_settings
.SetString(
577 ContentSettingsTypeToGroupName(type
) + ".managedBy", provider_id
);
579 web_ui()->CallJavascriptFunction(
580 "ContentSettings.setContentFilterSettingsValue", filter_settings
);
583 void ContentSettingsHandler::UpdateMediaSettingsView() {
584 PrefService
* prefs
= Profile::FromWebUI(web_ui())->GetPrefs();
585 bool audio_disabled
= !prefs
->GetBoolean(prefs::kAudioCaptureAllowed
) &&
586 prefs
->IsManagedPreference(prefs::kAudioCaptureAllowed
);
587 bool video_disabled
= !prefs
->GetBoolean(prefs::kVideoCaptureAllowed
) &&
588 prefs
->IsManagedPreference(prefs::kVideoCaptureAllowed
);
590 media_settings_
.policy_disable_audio
= audio_disabled
;
591 media_settings_
.policy_disable_video
= video_disabled
;
592 media_settings_
.default_setting
=
593 GetContentSettingsMap()->GetDefaultContentSetting(
594 CONTENT_SETTINGS_TYPE_MEDIASTREAM
, NULL
);
595 media_settings_
.default_setting_initialized
= true;
596 UpdateFlashMediaLinksVisibility();
598 base::DictionaryValue media_ui_settings
;
599 media_ui_settings
.SetBoolean("cameraDisabled", video_disabled
);
600 media_ui_settings
.SetBoolean("micDisabled", audio_disabled
);
602 // In case only video is enabled change the text appropriately.
603 if (audio_disabled
&& !video_disabled
) {
604 media_ui_settings
.SetString("askText", "mediaStreamVideoAsk");
605 media_ui_settings
.SetString("blockText", "mediaStreamVideoBlock");
606 media_ui_settings
.SetBoolean("showBubble", true);
607 media_ui_settings
.SetString("bubbleText", "mediaStreamBubbleAudio");
609 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
614 // In case only audio is enabled change the text appropriately.
615 if (video_disabled
&& !audio_disabled
) {
616 base::DictionaryValue media_ui_settings
;
617 media_ui_settings
.SetString("askText", "mediaStreamAudioAsk");
618 media_ui_settings
.SetString("blockText", "mediaStreamAudioBlock");
619 media_ui_settings
.SetBoolean("showBubble", true);
620 media_ui_settings
.SetString("bubbleText", "mediaStreamBubbleVideo");
622 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
627 if (audio_disabled
&& video_disabled
) {
628 // Fake policy controlled default because the user can not change anything
629 // until both audio and video are blocked.
630 base::DictionaryValue filter_settings
;
631 std::string group_name
=
632 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM
);
633 filter_settings
.SetString(group_name
+ ".value",
634 ContentSettingToString(CONTENT_SETTING_BLOCK
));
635 filter_settings
.SetString(group_name
+ ".managedBy", "policy");
636 web_ui()->CallJavascriptFunction(
637 "ContentSettings.setContentFilterSettingsValue", filter_settings
);
640 media_ui_settings
.SetString("askText", "mediaStreamAsk");
641 media_ui_settings
.SetString("blockText", "mediaStreamBlock");
642 media_ui_settings
.SetBoolean("showBubble", false);
643 media_ui_settings
.SetString("bubbleText", std::string());
645 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
649 std::string
ContentSettingsHandler::GetSettingDefaultFromModel(
650 ContentSettingsType type
, std::string
* provider_id
) {
651 Profile
* profile
= Profile::FromWebUI(web_ui());
652 ContentSetting default_setting
;
653 if (type
== CONTENT_SETTINGS_TYPE_NOTIFICATIONS
) {
655 DesktopNotificationServiceFactory::GetForProfile(profile
)->
656 GetDefaultContentSetting(provider_id
);
659 profile
->GetHostContentSettingsMap()->
660 GetDefaultContentSetting(type
, provider_id
);
663 return ContentSettingToString(default_setting
);
666 void ContentSettingsHandler::UpdateHandlersEnabledRadios() {
667 base::FundamentalValue
handlers_enabled(
668 GetProtocolHandlerRegistry()->enabled());
670 web_ui()->CallJavascriptFunction(
671 "ContentSettings.updateHandlersEnabledRadios",
675 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
676 for (int type
= CONTENT_SETTINGS_TYPE_DEFAULT
+ 1;
677 type
< CONTENT_SETTINGS_NUM_TYPES
; ++type
) {
678 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType
>(type
));
682 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
683 for (int type
= CONTENT_SETTINGS_TYPE_DEFAULT
+ 1;
684 type
< CONTENT_SETTINGS_NUM_TYPES
; ++type
) {
685 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType
>(type
));
689 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
690 ContentSettingsType type
) {
692 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
693 UpdateGeolocationExceptionsView();
695 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
696 UpdateNotificationExceptionsView();
698 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
699 UpdateMediaSettingsView();
701 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
702 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
703 UpdateMediaExceptionsView();
705 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
:
706 // We don't yet support exceptions for mixed scripting.
708 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
:
709 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
710 // is supposed to be set by policy only. Hence there is no user facing UI
711 // for this content type and we skip it here.
713 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
:
714 // The RPH settings are retrieved separately.
716 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
717 UpdateMIDISysExExceptionsView();
720 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP
:
724 UpdateExceptionsViewFromHostContentSettingsMap(type
);
729 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
730 ContentSettingsType type
) {
732 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
733 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
734 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
:
735 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
:
737 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP
:
739 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
740 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
741 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
742 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
:
743 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
746 UpdateExceptionsViewFromOTRHostContentSettingsMap(type
);
751 // TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
752 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
753 Profile
* profile
= Profile::FromWebUI(web_ui());
754 HostContentSettingsMap
* map
= profile
->GetHostContentSettingsMap();
756 ContentSettingsForOneType all_settings
;
757 map
->GetSettingsForOneType(
758 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
762 // Group geolocation settings by primary_pattern.
763 AllPatternsSettings all_patterns_settings
;
764 for (ContentSettingsForOneType::iterator i
= all_settings
.begin();
765 i
!= all_settings
.end(); ++i
) {
766 // Don't add default settings.
767 if (i
->primary_pattern
== ContentSettingsPattern::Wildcard() &&
768 i
->secondary_pattern
== ContentSettingsPattern::Wildcard() &&
769 i
->source
!= kPreferencesSource
) {
772 all_patterns_settings
[std::make_pair(i
->primary_pattern
, i
->source
)]
773 [i
->secondary_pattern
] = i
->setting
;
776 base::ListValue exceptions
;
777 AddExceptionsGrantedByHostedApps(
779 HostedAppHasPermission
<APIPermission::kGeolocation
>,
782 for (AllPatternsSettings::iterator i
= all_patterns_settings
.begin();
783 i
!= all_patterns_settings
.end(); ++i
) {
784 const ContentSettingsPattern
& primary_pattern
= i
->first
.first
;
785 const OnePatternSettings
& one_settings
= i
->second
;
787 OnePatternSettings::const_iterator parent
=
788 one_settings
.find(primary_pattern
);
790 // Add the "parent" entry for the non-embedded setting.
791 ContentSetting parent_setting
=
792 parent
== one_settings
.end() ? CONTENT_SETTING_DEFAULT
: parent
->second
;
793 exceptions
.Append(GetGeolocationExceptionForPage(primary_pattern
,
797 // Add the "children" for any embedded settings.
798 for (OnePatternSettings::const_iterator j
= one_settings
.begin();
799 j
!= one_settings
.end();
801 // Skip the non-embedded setting which we already added above.
805 exceptions
.Append(GetGeolocationExceptionForPage(
806 primary_pattern
, j
->first
, j
->second
));
810 base::StringValue
type_string(
811 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION
));
812 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
813 type_string
, exceptions
);
815 // This is mainly here to keep this function ideologically parallel to
816 // UpdateExceptionsViewFromHostContentSettingsMap().
817 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION
);
820 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
821 Profile
* profile
= Profile::FromWebUI(web_ui());
822 DesktopNotificationService
* service
=
823 DesktopNotificationServiceFactory::GetForProfile(profile
);
825 ContentSettingsForOneType settings
;
826 service
->GetNotificationsSettings(&settings
);
828 base::ListValue exceptions
;
829 AddExceptionsGrantedByHostedApps(profile
,
830 HostedAppHasPermission
<APIPermission::kNotification
>,
833 for (ContentSettingsForOneType::const_iterator i
=
837 // Don't add default settings.
838 if (i
->primary_pattern
== ContentSettingsPattern::Wildcard() &&
839 i
->secondary_pattern
== ContentSettingsPattern::Wildcard() &&
840 i
->source
!= kPreferencesSource
) {
845 GetNotificationExceptionForPage(i
->primary_pattern
, i
->setting
,
849 base::StringValue
type_string(
850 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
));
851 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
852 type_string
, exceptions
);
854 // This is mainly here to keep this function ideologically parallel to
855 // UpdateExceptionsViewFromHostContentSettingsMap().
856 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
859 void ContentSettingsHandler::UpdateMediaExceptionsView() {
860 base::ListValue media_exceptions
;
861 GetExceptionsFromHostContentSettingsMap(
862 GetContentSettingsMap(),
863 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
866 base::ListValue video_exceptions
;
867 GetExceptionsFromHostContentSettingsMap(
868 GetContentSettingsMap(),
869 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
872 // Merge the |video_exceptions| list to |media_exceptions| list.
873 std::map
<std::string
, base::DictionaryValue
*> entries_map
;
874 for (base::ListValue::const_iterator
media_entry(media_exceptions
.begin());
875 media_entry
!= media_exceptions
.end(); ++media_entry
) {
876 base::DictionaryValue
* media_dict
= NULL
;
877 if (!(*media_entry
)->GetAsDictionary(&media_dict
))
880 media_dict
->SetString(kVideoSetting
,
881 ContentSettingToString(CONTENT_SETTING_ASK
));
883 std::string media_origin
;
884 media_dict
->GetString(kOrigin
, &media_origin
);
885 entries_map
[media_origin
] = media_dict
;
888 for (base::ListValue::iterator video_entry
= video_exceptions
.begin();
889 video_entry
!= video_exceptions
.end(); ++video_entry
) {
890 base::DictionaryValue
* video_dict
= NULL
;
891 if (!(*video_entry
)->GetAsDictionary(&video_dict
))
894 std::string video_origin
;
895 std::string video_setting
;
896 video_dict
->GetString(kOrigin
, &video_origin
);
897 video_dict
->GetString(kSetting
, &video_setting
);
899 std::map
<std::string
, base::DictionaryValue
*>::iterator iter
=
900 entries_map
.find(video_origin
);
901 if (iter
== entries_map
.end()) {
902 base::DictionaryValue
* exception
= new base::DictionaryValue();
903 exception
->SetString(kOrigin
, video_origin
);
904 exception
->SetString(kSetting
,
905 ContentSettingToString(CONTENT_SETTING_ASK
));
906 exception
->SetString(kVideoSetting
, video_setting
);
907 exception
->SetString(kSource
, kPreferencesSource
);
909 // Append the new entry to the list and map.
910 media_exceptions
.Append(exception
);
911 entries_map
[video_origin
] = exception
;
913 // Modify the existing entry.
914 iter
->second
->SetString(kVideoSetting
, video_setting
);
918 media_settings_
.exceptions
.clear();
919 for (base::ListValue::const_iterator media_entry
= media_exceptions
.begin();
920 media_entry
!= media_exceptions
.end(); ++media_entry
) {
921 base::DictionaryValue
* media_dict
= NULL
;
922 bool result
= (*media_entry
)->GetAsDictionary(&media_dict
);
926 std::string audio_setting
;
927 std::string video_setting
;
928 media_dict
->GetString(kOrigin
, &origin
);
929 media_dict
->GetString(kSetting
, &audio_setting
);
930 media_dict
->GetString(kVideoSetting
, &video_setting
);
931 media_settings_
.exceptions
.push_back(MediaException(
932 ContentSettingsPattern::FromString(origin
),
933 ContentSettingFromString(audio_setting
),
934 ContentSettingFromString(video_setting
)));
936 PepperFlashContentSettingsUtils::SortMediaExceptions(
937 &media_settings_
.exceptions
);
938 media_settings_
.exceptions_initialized
= true;
939 UpdateFlashMediaLinksVisibility();
941 base::StringValue
type_string(
942 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM
));
943 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
944 type_string
, media_exceptions
);
946 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MEDIASTREAM
);
949 void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
950 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebMIDI
)) {
951 web_ui()->CallJavascriptFunction(
952 "ContentSettings.showExperimentalWebMIDISettings",
953 base::FundamentalValue(true));
956 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
);
957 UpdateExceptionsViewFromHostContentSettingsMap(
958 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
);
961 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
962 ContentSettingsType type
) {
963 base::ListValue exceptions
;
964 GetExceptionsFromHostContentSettingsMap(
965 GetContentSettingsMap(), type
, &exceptions
);
966 base::StringValue
type_string(ContentSettingsTypeToGroupName(type
));
967 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string
,
970 UpdateExceptionsViewFromOTRHostContentSettingsMap(type
);
972 // TODO(koz): The default for fullscreen is always 'ask'.
973 // http://crbug.com/104683
974 if (type
== CONTENT_SETTINGS_TYPE_FULLSCREEN
)
977 #if defined(OS_CHROMEOS)
978 // Also the default for protected contents is managed in another place.
979 if (type
== CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
)
983 // The default may also have changed (we won't get a separate notification).
984 // If it hasn't changed, this call will be harmless.
985 UpdateSettingDefaultFromModel(type
);
988 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
989 ContentSettingsType type
) {
990 const HostContentSettingsMap
* otr_settings_map
= GetOTRContentSettingsMap();
991 if (!otr_settings_map
)
993 base::ListValue exceptions
;
994 GetExceptionsFromHostContentSettingsMap(otr_settings_map
, type
, &exceptions
);
995 base::StringValue
type_string(ContentSettingsTypeToGroupName(type
));
996 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
997 type_string
, exceptions
);
1000 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
1001 const HostContentSettingsMap
* map
,
1002 ContentSettingsType type
,
1003 base::ListValue
* exceptions
) {
1004 ContentSettingsForOneType entries
;
1005 map
->GetSettingsForOneType(type
, std::string(), &entries
);
1006 // Group settings by primary_pattern.
1007 AllPatternsSettings all_patterns_settings
;
1008 for (ContentSettingsForOneType::iterator i
= entries
.begin();
1009 i
!= entries
.end(); ++i
) {
1010 // Don't add default settings.
1011 if (i
->primary_pattern
== ContentSettingsPattern::Wildcard() &&
1012 i
->secondary_pattern
== ContentSettingsPattern::Wildcard() &&
1013 i
->source
!= kPreferencesSource
) {
1017 // Off-the-record HostContentSettingsMap contains incognito content settings
1018 // as well as normal content settings. Here, we use the incongnito settings
1020 if (map
->is_off_the_record() && !i
->incognito
)
1023 all_patterns_settings
[std::make_pair(i
->primary_pattern
, i
->source
)]
1024 [i
->secondary_pattern
] = i
->setting
;
1027 // Keep the exceptions sorted by provider so they will be displayed in
1028 // precedence order.
1029 std::vector
<std::vector
<base::Value
*> > all_provider_exceptions
;
1030 all_provider_exceptions
.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES
);
1032 for (AllPatternsSettings::iterator i
= all_patterns_settings
.begin();
1033 i
!= all_patterns_settings
.end();
1035 const ContentSettingsPattern
& primary_pattern
= i
->first
.first
;
1036 const OnePatternSettings
& one_settings
= i
->second
;
1038 // The "parent" entry either has an identical primary and secondary pattern,
1039 // or has a wildcard secondary. The two cases are indistinguishable in the
1041 OnePatternSettings::const_iterator parent
=
1042 one_settings
.find(primary_pattern
);
1043 if (parent
== one_settings
.end())
1044 parent
= one_settings
.find(ContentSettingsPattern::Wildcard());
1046 const std::string
& source
= i
->first
.second
;
1047 std::vector
<base::Value
*>* this_provider_exceptions
=
1048 &all_provider_exceptions
.at(
1049 HostContentSettingsMap::GetProviderTypeFromSource(source
));
1051 // Add the "parent" entry for the non-embedded setting.
1052 ContentSetting parent_setting
=
1053 parent
== one_settings
.end() ? CONTENT_SETTING_DEFAULT
: parent
->second
;
1054 const ContentSettingsPattern
& secondary_pattern
=
1055 parent
== one_settings
.end() ? primary_pattern
: parent
->first
;
1056 this_provider_exceptions
->push_back(GetExceptionForPage(primary_pattern
,
1061 // Add the "children" for any embedded settings.
1062 for (OnePatternSettings::const_iterator j
= one_settings
.begin();
1063 j
!= one_settings
.end(); ++j
) {
1064 // Skip the non-embedded setting which we already added above.
1068 ContentSetting content_setting
= j
->second
;
1069 this_provider_exceptions
->push_back(GetExceptionForPage(
1077 for (size_t i
= 0; i
< all_provider_exceptions
.size(); ++i
) {
1078 for (size_t j
= 0; j
< all_provider_exceptions
[i
].size(); ++j
) {
1079 exceptions
->Append(all_provider_exceptions
[i
][j
]);
1084 void ContentSettingsHandler::RemoveNotificationException(
1085 const base::ListValue
* args
, size_t arg_index
) {
1086 Profile
* profile
= Profile::FromWebUI(web_ui());
1088 std::string setting
;
1089 bool rv
= args
->GetString(arg_index
++, &origin
);
1091 rv
= args
->GetString(arg_index
++, &setting
);
1093 ContentSetting content_setting
= ContentSettingFromString(setting
);
1095 DCHECK(content_setting
== CONTENT_SETTING_ALLOW
||
1096 content_setting
== CONTENT_SETTING_BLOCK
);
1097 DesktopNotificationServiceFactory::GetForProfile(profile
)->
1098 ClearSetting(ContentSettingsPattern::FromString(origin
));
1101 void ContentSettingsHandler::RemoveMediaException(
1102 const base::ListValue
* args
, size_t arg_index
) {
1104 bool rv
= args
->GetString(arg_index
++, &mode
);
1107 std::string pattern
;
1108 rv
= args
->GetString(arg_index
++, &pattern
);
1111 HostContentSettingsMap
* settings_map
=
1112 mode
== "normal" ? GetContentSettingsMap() :
1113 GetOTRContentSettingsMap();
1115 settings_map
->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern
),
1116 ContentSettingsPattern::Wildcard(),
1117 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
1120 settings_map
->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern
),
1121 ContentSettingsPattern::Wildcard(),
1122 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
1128 void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
1129 const base::ListValue
* args
, size_t arg_index
,
1130 ContentSettingsType type
) {
1132 bool rv
= args
->GetString(arg_index
++, &mode
);
1135 std::string pattern
;
1136 rv
= args
->GetString(arg_index
++, &pattern
);
1139 std::string secondary_pattern
;
1140 rv
= args
->GetString(arg_index
++, &secondary_pattern
);
1143 HostContentSettingsMap
* settings_map
=
1144 mode
== "normal" ? GetContentSettingsMap() :
1145 GetOTRContentSettingsMap();
1147 settings_map
->SetWebsiteSetting(
1148 ContentSettingsPattern::FromString(pattern
),
1149 secondary_pattern
.empty()
1150 ? ContentSettingsPattern::Wildcard()
1151 : ContentSettingsPattern::FromString(secondary_pattern
),
1158 void ContentSettingsHandler::RegisterMessages() {
1159 web_ui()->RegisterMessageCallback("setContentFilter",
1160 base::Bind(&ContentSettingsHandler::SetContentFilter
,
1161 base::Unretained(this)));
1162 web_ui()->RegisterMessageCallback("removeException",
1163 base::Bind(&ContentSettingsHandler::RemoveException
,
1164 base::Unretained(this)));
1165 web_ui()->RegisterMessageCallback("setException",
1166 base::Bind(&ContentSettingsHandler::SetException
,
1167 base::Unretained(this)));
1168 web_ui()->RegisterMessageCallback("checkExceptionPatternValidity",
1169 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity
,
1170 base::Unretained(this)));
1173 void ContentSettingsHandler::ApplyWhitelist(ContentSettingsType content_type
,
1174 ContentSetting default_setting
) {
1175 Profile
* profile
= Profile::FromWebUI(web_ui());
1176 HostContentSettingsMap
* map
= GetContentSettingsMap();
1177 if (content_type
!= CONTENT_SETTINGS_TYPE_PLUGINS
)
1179 const int kDefaultWhitelistVersion
= 1;
1180 PrefService
* prefs
= profile
->GetPrefs();
1181 int version
= prefs
->GetInteger(
1182 prefs::kContentSettingsDefaultWhitelistVersion
);
1183 if (version
>= kDefaultWhitelistVersion
)
1185 ContentSetting old_setting
=
1186 map
->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS
, NULL
);
1187 // TODO(bauerb): Remove this once the Google Talk plug-in works nicely with
1188 // click-to-play (b/6090625).
1189 if (old_setting
== CONTENT_SETTING_ALLOW
&&
1190 default_setting
== CONTENT_SETTING_ASK
) {
1191 map
->SetWebsiteSetting(
1192 ContentSettingsPattern::Wildcard(),
1193 ContentSettingsPattern::Wildcard(),
1194 CONTENT_SETTINGS_TYPE_PLUGINS
,
1196 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
1198 prefs
->SetInteger(prefs::kContentSettingsDefaultWhitelistVersion
,
1199 kDefaultWhitelistVersion
);
1202 void ContentSettingsHandler::SetContentFilter(const base::ListValue
* args
) {
1203 DCHECK_EQ(2U, args
->GetSize());
1204 std::string group
, setting
;
1205 if (!(args
->GetString(0, &group
) &&
1206 args
->GetString(1, &setting
))) {
1211 ContentSetting default_setting
= ContentSettingFromString(setting
);
1212 ContentSettingsType content_type
= ContentSettingsTypeFromGroupName(group
);
1213 Profile
* profile
= Profile::FromWebUI(web_ui());
1215 #if defined(OS_CHROMEOS)
1216 // ChromeOS special case : in Guest mode settings are opened in Incognito
1217 // mode, so we need original profile to actually modify settings.
1218 if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
1219 profile
= profile
->GetOriginalProfile();
1222 if (content_type
== CONTENT_SETTINGS_TYPE_NOTIFICATIONS
) {
1223 DesktopNotificationServiceFactory::GetForProfile(profile
)->
1224 SetDefaultContentSetting(default_setting
);
1226 HostContentSettingsMap
* map
= profile
->GetHostContentSettingsMap();
1227 ApplyWhitelist(content_type
, default_setting
);
1228 map
->SetDefaultContentSetting(content_type
, default_setting
);
1230 switch (content_type
) {
1231 case CONTENT_SETTINGS_TYPE_COOKIES
:
1232 content::RecordAction(
1233 UserMetricsAction("Options_DefaultCookieSettingChanged"));
1235 case CONTENT_SETTINGS_TYPE_IMAGES
:
1236 content::RecordAction(
1237 UserMetricsAction("Options_DefaultImagesSettingChanged"));
1239 case CONTENT_SETTINGS_TYPE_JAVASCRIPT
:
1240 content::RecordAction(
1241 UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
1243 case CONTENT_SETTINGS_TYPE_PLUGINS
:
1244 content::RecordAction(
1245 UserMetricsAction("Options_DefaultPluginsSettingChanged"));
1247 case CONTENT_SETTINGS_TYPE_POPUPS
:
1248 content::RecordAction(
1249 UserMetricsAction("Options_DefaultPopupsSettingChanged"));
1251 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
1252 content::RecordAction(
1253 UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
1255 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
1256 content::RecordAction(
1257 UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
1259 case CONTENT_SETTINGS_TYPE_MOUSELOCK
:
1260 content::RecordAction(
1261 UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
1263 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
1264 content::RecordAction(
1265 UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
1267 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
:
1268 content::RecordAction(
1269 UserMetricsAction("Options_DefaultMultipleAutomaticDLSettingChange"));
1271 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
1272 content::RecordAction(
1273 UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
1280 void ContentSettingsHandler::RemoveException(const base::ListValue
* args
) {
1282 std::string type_string
;
1283 CHECK(args
->GetString(arg_i
++, &type_string
));
1285 ContentSettingsType type
= ContentSettingsTypeFromGroupName(type_string
);
1287 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
1288 RemoveNotificationException(args
, arg_i
);
1290 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
1291 RemoveMediaException(args
, arg_i
);
1294 RemoveExceptionFromHostContentSettingsMap(args
, arg_i
, type
);
1299 void ContentSettingsHandler::SetException(const base::ListValue
* args
) {
1301 std::string type_string
;
1302 CHECK(args
->GetString(arg_i
++, &type_string
));
1304 CHECK(args
->GetString(arg_i
++, &mode
));
1305 std::string pattern
;
1306 CHECK(args
->GetString(arg_i
++, &pattern
));
1307 std::string setting
;
1308 CHECK(args
->GetString(arg_i
++, &setting
));
1310 ContentSettingsType type
= ContentSettingsTypeFromGroupName(type_string
);
1311 if (type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
||
1312 type
== CONTENT_SETTINGS_TYPE_NOTIFICATIONS
||
1313 type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
||
1314 type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
||
1315 type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
) {
1318 HostContentSettingsMap
* settings_map
=
1319 mode
== "normal" ? GetContentSettingsMap() :
1320 GetOTRContentSettingsMap();
1322 // The settings map could be null if the mode was OTR but the OTR profile
1323 // got destroyed before we received this message.
1326 settings_map
->SetContentSetting(ContentSettingsPattern::FromString(pattern
),
1327 ContentSettingsPattern::Wildcard(),
1330 ContentSettingFromString(setting
));
1334 void ContentSettingsHandler::CheckExceptionPatternValidity(
1335 const base::ListValue
* args
) {
1337 std::string type_string
;
1338 CHECK(args
->GetString(arg_i
++, &type_string
));
1339 std::string mode_string
;
1340 CHECK(args
->GetString(arg_i
++, &mode_string
));
1341 std::string pattern_string
;
1342 CHECK(args
->GetString(arg_i
++, &pattern_string
));
1344 ContentSettingsPattern pattern
=
1345 ContentSettingsPattern::FromString(pattern_string
);
1347 web_ui()->CallJavascriptFunction(
1348 "ContentSettings.patternValidityCheckComplete",
1349 base::StringValue(type_string
),
1350 base::StringValue(mode_string
),
1351 base::StringValue(pattern_string
),
1352 base::FundamentalValue(pattern
.IsValid()));
1356 std::string
ContentSettingsHandler::ContentSettingsTypeToGroupName(
1357 ContentSettingsType type
) {
1358 for (size_t i
= 0; i
< arraysize(kContentSettingsTypeGroupNames
); ++i
) {
1359 if (type
== kContentSettingsTypeGroupNames
[i
].type
)
1360 return kContentSettingsTypeGroupNames
[i
].name
;
1364 return std::string();
1367 HostContentSettingsMap
* ContentSettingsHandler::GetContentSettingsMap() {
1368 return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap();
1371 ProtocolHandlerRegistry
* ContentSettingsHandler::GetProtocolHandlerRegistry() {
1372 return ProtocolHandlerRegistryFactory::GetForProfile(
1373 Profile::FromWebUI(web_ui()));
1376 HostContentSettingsMap
*
1377 ContentSettingsHandler::GetOTRContentSettingsMap() {
1378 Profile
* profile
= Profile::FromWebUI(web_ui());
1379 if (profile
->HasOffTheRecordProfile())
1380 return profile
->GetOffTheRecordProfile()->GetHostContentSettingsMap();
1384 void ContentSettingsHandler::RefreshFlashMediaSettings() {
1385 media_settings_
.flash_settings_initialized
= false;
1387 media_settings_
.last_flash_refresh_request_id
=
1388 flash_settings_manager_
->GetPermissionSettings(
1389 PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC
);
1392 void ContentSettingsHandler::OnPepperFlashPrefChanged() {
1393 ShowFlashMediaLink(DEFAULT_SETTING
, false);
1394 ShowFlashMediaLink(EXCEPTIONS
, false);
1396 PrefService
* prefs
= Profile::FromWebUI(web_ui())->GetPrefs();
1397 if (prefs
->GetBoolean(prefs::kPepperFlashSettingsEnabled
))
1398 RefreshFlashMediaSettings();
1400 media_settings_
.flash_settings_initialized
= false;
1403 void ContentSettingsHandler::ShowFlashMediaLink(LinkType link_type
, bool show
) {
1404 bool& show_link
= link_type
== DEFAULT_SETTING
?
1405 media_settings_
.show_flash_default_link
:
1406 media_settings_
.show_flash_exceptions_link
;
1407 if (show_link
!= show
) {
1408 web_ui()->CallJavascriptFunction(
1409 link_type
== DEFAULT_SETTING
?
1410 "ContentSettings.showMediaPepperFlashDefaultLink" :
1411 "ContentSettings.showMediaPepperFlashExceptionsLink",
1412 base::FundamentalValue(show
));
1417 void ContentSettingsHandler::UpdateFlashMediaLinksVisibility() {
1418 if (!media_settings_
.flash_settings_initialized
||
1419 !media_settings_
.default_setting_initialized
||
1420 !media_settings_
.exceptions_initialized
) {
1424 // Flash won't send us notifications when its settings get changed, which
1425 // means the Flash settings in |media_settings_| may be out-dated, especially
1426 // after we show links to change Flash settings.
1427 // In order to avoid confusion, we won't hide the links once they are showed.
1428 // One exception is that we will hide them when Pepper Flash is disabled
1429 // (handled in OnPepperFlashPrefChanged()).
1430 if (media_settings_
.show_flash_default_link
&&
1431 media_settings_
.show_flash_exceptions_link
) {
1435 if (!media_settings_
.show_flash_default_link
) {
1436 // If both audio and video capture are disabled by policy, the link
1437 // shouldn't be showed. Flash conforms to the policy in this case because
1438 // it cannot open those devices. We don't have to look at the Flash
1440 if (!(media_settings_
.policy_disable_audio
&&
1441 media_settings_
.policy_disable_video
) &&
1442 media_settings_
.flash_default_setting
!=
1443 media_settings_
.default_setting
) {
1444 ShowFlashMediaLink(DEFAULT_SETTING
, true);
1447 if (!media_settings_
.show_flash_exceptions_link
) {
1448 // If audio or video capture is disabled by policy, we skip comparison of
1449 // exceptions for audio or video capture, respectively.
1450 if (!PepperFlashContentSettingsUtils::AreMediaExceptionsEqual(
1451 media_settings_
.default_setting
,
1452 media_settings_
.exceptions
,
1453 media_settings_
.flash_default_setting
,
1454 media_settings_
.flash_exceptions
,
1455 media_settings_
.policy_disable_audio
,
1456 media_settings_
.policy_disable_video
)) {
1457 ShowFlashMediaLink(EXCEPTIONS
, true);
1462 void ContentSettingsHandler::UpdateProtectedContentExceptionsButton() {
1463 PrefService
* prefs
= Profile::FromWebUI(web_ui())->GetPrefs();
1464 // Exceptions apply only when the feature is enabled.
1465 bool enable_exceptions
= prefs
->GetBoolean(prefs::kEnableDRM
);
1466 web_ui()->CallJavascriptFunction(
1467 "ContentSettings.enableProtectedContentExceptions",
1468 base::FundamentalValue(enable_exceptions
));
1471 } // namespace options