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"
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/command_line.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/content_settings/content_settings_utils.h"
21 #include "chrome/browser/content_settings/host_content_settings_map.h"
22 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
23 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
24 #include "chrome/browser/extensions/extension_special_storage_policy.h"
25 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/ui/browser_list.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/grit/generated_resources.h"
33 #include "chrome/grit/locale_settings.h"
34 #include "components/content_settings/core/browser/content_settings_details.h"
35 #include "components/content_settings/core/common/content_settings.h"
36 #include "components/content_settings/core/common/content_settings_pattern.h"
37 #include "components/google/core/browser/google_util.h"
38 #include "components/user_prefs/user_prefs.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/notification_source.h"
41 #include "content/public/browser/notification_types.h"
42 #include "content/public/browser/user_metrics.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/browser/web_ui.h"
45 #include "content/public/common/content_switches.h"
46 #include "content/public/common/page_zoom.h"
47 #include "extensions/browser/extension_registry.h"
48 #include "extensions/common/extension_set.h"
49 #include "extensions/common/permissions/api_permission.h"
50 #include "extensions/common/permissions/permissions_data.h"
51 #include "ui/base/l10n/l10n_util.h"
53 #if defined(OS_CHROMEOS)
54 #include "components/user_manager/user_manager.h"
57 using base::UserMetricsAction
;
58 using content_settings::ContentSettingToString
;
59 using content_settings::ContentSettingFromString
;
60 using extensions::APIPermission
;
64 struct ContentSettingsTypeNameEntry
{
65 ContentSettingsType type
;
69 // Maps from a secondary pattern to a setting.
70 typedef std::map
<ContentSettingsPattern
, ContentSetting
>
72 // Maps from a primary pattern/source pair to a OnePatternSettings. All the
73 // mappings in OnePatternSettings share the given primary pattern and source.
74 typedef std::map
<std::pair
<ContentSettingsPattern
, std::string
>,
78 // The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
79 // extensions which should have their extent displayed.
80 typedef bool (*AppFilter
)(const extensions::Extension
& app
,
81 content::BrowserContext
* profile
);
83 const char kExceptionsLearnMoreUrl
[] =
84 "https://support.google.com/chrome/?p=settings_manage_exceptions";
86 const char* kSetting
= "setting";
87 const char* kOrigin
= "origin";
88 const char* kSource
= "source";
89 const char* kAppName
= "appName";
90 const char* kAppId
= "appId";
91 const char* kEmbeddingOrigin
= "embeddingOrigin";
92 const char* kPreferencesSource
= "preference";
93 const char* kVideoSetting
= "video";
94 const char* kZoom
= "zoom";
96 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames
[] = {
97 {CONTENT_SETTINGS_TYPE_COOKIES
, "cookies"},
98 {CONTENT_SETTINGS_TYPE_IMAGES
, "images"},
99 {CONTENT_SETTINGS_TYPE_JAVASCRIPT
, "javascript"},
100 {CONTENT_SETTINGS_TYPE_PLUGINS
, "plugins"},
101 {CONTENT_SETTINGS_TYPE_POPUPS
, "popups"},
102 {CONTENT_SETTINGS_TYPE_GEOLOCATION
, "location"},
103 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS
, "notifications"},
104 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
, "auto-select-certificate"},
105 {CONTENT_SETTINGS_TYPE_FULLSCREEN
, "fullscreen"},
106 {CONTENT_SETTINGS_TYPE_MOUSELOCK
, "mouselock"},
107 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
, "register-protocol-handler"},
108 {CONTENT_SETTINGS_TYPE_MEDIASTREAM
, "media-stream"},
109 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
, "media-stream-mic"},
110 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
, "media-stream-camera"},
111 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER
, "ppapi-broker"},
112 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
, "multiple-automatic-downloads"},
113 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX
, "midi-sysex"},
114 {CONTENT_SETTINGS_TYPE_PUSH_MESSAGING
, "push-messaging"},
115 {CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS
, "ssl-cert-decisions"},
116 #if defined(OS_CHROMEOS)
117 {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
, "protectedContent"},
121 // A pseudo content type. We use it to display data like a content setting even
122 // though it is not a real content setting.
123 const char* kZoomContentType
= "zoomlevels";
125 content::BrowserContext
* GetBrowserContext(content::WebUI
* web_ui
) {
126 return web_ui
->GetWebContents()->GetBrowserContext();
129 ContentSettingsType
ContentSettingsTypeFromGroupName(const std::string
& name
) {
130 for (size_t i
= 0; i
< arraysize(kContentSettingsTypeGroupNames
); ++i
) {
131 if (name
== kContentSettingsTypeGroupNames
[i
].name
)
132 return kContentSettingsTypeGroupNames
[i
].type
;
135 NOTREACHED() << name
<< " is not a recognized content settings type.";
136 return CONTENT_SETTINGS_TYPE_DEFAULT
;
139 // Create a DictionaryValue* that will act as a data source for a single row
140 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
141 // Ownership of the pointer is passed to the caller.
142 base::DictionaryValue
* GetExceptionForPage(
143 const ContentSettingsPattern
& pattern
,
144 const ContentSettingsPattern
& secondary_pattern
,
145 const ContentSetting
& setting
,
146 const std::string
& provider_name
) {
147 base::DictionaryValue
* exception
= new base::DictionaryValue();
148 exception
->SetString(kOrigin
, pattern
.ToString());
149 exception
->SetString(kEmbeddingOrigin
,
150 secondary_pattern
== ContentSettingsPattern::Wildcard() ?
152 secondary_pattern
.ToString());
153 exception
->SetString(kSetting
, ContentSettingToString(setting
));
154 exception
->SetString(kSource
, provider_name
);
158 // Create a DictionaryValue* that will act as a data source for a single row
159 // in the Geolocation exceptions table. Ownership of the pointer is passed to
161 base::DictionaryValue
* GetGeolocationExceptionForPage(
162 const ContentSettingsPattern
& origin
,
163 const ContentSettingsPattern
& embedding_origin
,
164 ContentSetting setting
) {
165 base::DictionaryValue
* exception
= new base::DictionaryValue();
166 exception
->SetString(kSetting
, ContentSettingToString(setting
));
167 exception
->SetString(kOrigin
, origin
.ToString());
168 exception
->SetString(kEmbeddingOrigin
, embedding_origin
.ToString());
172 // Create a DictionaryValue* that will act as a data source for a single row
173 // in the desktop notifications exceptions table. Ownership of the pointer is
174 // passed to the caller.
175 base::DictionaryValue
* GetNotificationExceptionForPage(
176 const ContentSettingsPattern
& primary_pattern
,
177 const ContentSettingsPattern
& secondary_pattern
,
178 ContentSetting setting
,
179 const std::string
& provider_name
) {
180 std::string embedding_origin
;
181 if (secondary_pattern
!= ContentSettingsPattern::Wildcard())
182 embedding_origin
= secondary_pattern
.ToString();
184 base::DictionaryValue
* exception
= new base::DictionaryValue();
185 exception
->SetString(kSetting
, ContentSettingToString(setting
));
186 exception
->SetString(kOrigin
, primary_pattern
.ToString());
187 exception
->SetString(kEmbeddingOrigin
, embedding_origin
);
188 exception
->SetString(kSource
, provider_name
);
192 // Returns true whenever the |extension| is hosted and has |permission|.
193 // Must have the AppFilter signature.
194 template <APIPermission::ID permission
>
195 bool HostedAppHasPermission(const extensions::Extension
& extension
,
196 content::BrowserContext
* /* context */) {
197 return extension
.is_hosted_app() &&
198 extension
.permissions_data()->HasAPIPermission(permission
);
201 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
202 // the web extent of a hosted |app|.
203 void AddExceptionForHostedApp(const std::string
& url_pattern
,
204 const extensions::Extension
& app
, base::ListValue
* exceptions
) {
205 base::DictionaryValue
* exception
= new base::DictionaryValue();
206 exception
->SetString(kSetting
, ContentSettingToString(CONTENT_SETTING_ALLOW
));
207 exception
->SetString(kOrigin
, url_pattern
);
208 exception
->SetString(kEmbeddingOrigin
, url_pattern
);
209 exception
->SetString(kSource
, "HostedApp");
210 exception
->SetString(kAppName
, app
.name());
211 exception
->SetString(kAppId
, app
.id());
212 exceptions
->Append(exception
);
215 // Asks the |profile| for hosted apps which have the |permission| set, and
216 // adds their web extent and launch URL to the |exceptions| list.
217 void AddExceptionsGrantedByHostedApps(content::BrowserContext
* context
,
218 AppFilter app_filter
,
219 base::ListValue
* exceptions
) {
220 const extensions::ExtensionSet
& extensions
=
221 extensions::ExtensionRegistry::Get(context
)->enabled_extensions();
222 for (extensions::ExtensionSet::const_iterator extension
= extensions
.begin();
223 extension
!= extensions
.end(); ++extension
) {
224 if (!app_filter(*extension
->get(), context
))
227 extensions::URLPatternSet web_extent
= (*extension
)->web_extent();
228 // Add patterns from web extent.
229 for (extensions::URLPatternSet::const_iterator pattern
= web_extent
.begin();
230 pattern
!= web_extent
.end(); ++pattern
) {
231 std::string url_pattern
= pattern
->GetAsString();
232 AddExceptionForHostedApp(url_pattern
, *extension
->get(), exceptions
);
234 // Retrieve the launch URL.
236 extensions::AppLaunchInfo::GetLaunchWebURL(extension
->get());
237 // Skip adding the launch URL if it is part of the web extent.
238 if (web_extent
.MatchesURL(launch_url
))
240 AddExceptionForHostedApp(launch_url
.spec(), *extension
->get(), exceptions
);
244 // Sort ZoomLevelChanges by host and scheme
245 // (a.com < http://a.com < https://a.com < b.com).
246 bool HostZoomSort(const content::HostZoomMap::ZoomLevelChange
& a
,
247 const content::HostZoomMap::ZoomLevelChange
& b
) {
248 return a
.host
== b
.host
? a
.scheme
< b
.scheme
: a
.host
< b
.host
;
255 ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo()
256 : flash_default_setting(CONTENT_SETTING_DEFAULT
),
257 flash_settings_initialized(false),
258 last_flash_refresh_request_id(0),
259 show_flash_default_link(false),
260 show_flash_exceptions_link(false),
261 default_setting(CONTENT_SETTING_DEFAULT
),
262 policy_disable_audio(false),
263 policy_disable_video(false),
264 default_setting_initialized(false),
265 exceptions_initialized(false) {
268 ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
271 ContentSettingsHandler::ContentSettingsHandler() : observer_(this) {
274 ContentSettingsHandler::~ContentSettingsHandler() {
277 void ContentSettingsHandler::GetLocalizedValues(
278 base::DictionaryValue
* localized_strings
) {
279 DCHECK(localized_strings
);
281 // TODO(dhnishi): Standardize to lowerCamelCase.
282 static OptionsStringResource resources
[] = {
283 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON
},
284 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON
},
285 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON
},
286 { "askException", IDS_EXCEPTIONS_ASK_BUTTON
},
287 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL
},
288 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS
},
289 { "manageExceptions", IDS_EXCEPTIONS_MANAGE
},
290 { "manage_handlers", IDS_HANDLERS_MANAGE
},
291 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER
},
292 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER
},
293 { "exceptionZoomHeader", IDS_EXCEPTIONS_ZOOM_HEADER
},
294 { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST
},
296 { "cookiesTabLabel", IDS_COOKIES_TAB_LABEL
},
297 { "cookies_header", IDS_COOKIES_HEADER
},
298 { "cookiesAllow", IDS_COOKIES_ALLOW_RADIO
},
299 { "cookiesBlock", 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 { "imagesTabLabel", IDS_IMAGES_TAB_LABEL
},
313 { "images_header", IDS_IMAGES_HEADER
},
314 { "imagesAllow", IDS_IMAGES_LOAD_RADIO
},
315 { "imagesBlock", IDS_IMAGES_NOLOAD_RADIO
},
316 // JavaScript filter.
317 { "javascriptTabLabel", IDS_JAVASCRIPT_TAB_LABEL
},
318 { "javascript_header", IDS_JAVASCRIPT_HEADER
},
319 { "javascriptAllow", IDS_JS_ALLOW_RADIO
},
320 { "javascriptBlock", IDS_JS_DONOTALLOW_RADIO
},
322 { "pluginsTabLabel", IDS_PLUGIN_TAB_LABEL
},
323 { "plugins_header", IDS_PLUGIN_HEADER
},
324 { "pluginsAsk", IDS_PLUGIN_ASK_RADIO
},
325 { "pluginsAllow", IDS_PLUGIN_LOAD_RADIO
},
326 { "pluginsBlock", IDS_PLUGIN_NOLOAD_RADIO
},
327 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE
},
329 { "popupsTabLabel", IDS_POPUP_TAB_LABEL
},
330 { "popups_header", IDS_POPUP_HEADER
},
331 { "popupsAllow", IDS_POPUP_ALLOW_RADIO
},
332 { "popupsBlock", IDS_POPUP_BLOCK_RADIO
},
334 { "locationTabLabel", IDS_GEOLOCATION_TAB_LABEL
},
335 { "location_header", IDS_GEOLOCATION_HEADER
},
336 { "locationAllow", IDS_GEOLOCATION_ALLOW_RADIO
},
337 { "locationAsk", IDS_GEOLOCATION_ASK_RADIO
},
338 { "locationBlock", IDS_GEOLOCATION_BLOCK_RADIO
},
339 { "set_by", IDS_GEOLOCATION_SET_BY_HOVER
},
340 // Notifications filter.
341 { "notificationsTabLabel", IDS_NOTIFICATIONS_TAB_LABEL
},
342 { "notifications_header", IDS_NOTIFICATIONS_HEADER
},
343 { "notificationsAllow", IDS_NOTIFICATIONS_ALLOW_RADIO
},
344 { "notificationsAsk", IDS_NOTIFICATIONS_ASK_RADIO
},
345 { "notificationsBlock", IDS_NOTIFICATIONS_BLOCK_RADIO
},
346 // Fullscreen filter.
347 { "fullscreenTabLabel", IDS_FULLSCREEN_TAB_LABEL
},
348 { "fullscreen_header", IDS_FULLSCREEN_HEADER
},
349 // Mouse Lock filter.
350 { "mouselockTabLabel", IDS_MOUSE_LOCK_TAB_LABEL
},
351 { "mouselock_header", IDS_MOUSE_LOCK_HEADER
},
352 { "mouselockAllow", IDS_MOUSE_LOCK_ALLOW_RADIO
},
353 { "mouselockAsk", IDS_MOUSE_LOCK_ASK_RADIO
},
354 { "mouselockBlock", 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 { "ppapi-broker_header", IDS_PPAPI_BROKER_HEADER
},
384 { "ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL
},
385 { "ppapiBrokerAllow", IDS_PPAPI_BROKER_ALLOW_RADIO
},
386 { "ppapiBrokerAsk", IDS_PPAPI_BROKER_ASK_RADIO
},
387 { "ppapiBrokerBlock", IDS_PPAPI_BROKER_BLOCK_RADIO
},
388 // Multiple automatic downloads
389 { "multipleAutomaticDownloadsTabLabel",
390 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL
},
391 { "multipleAutomaticDownloadsAllow",
392 IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO
},
393 { "multipleAutomaticDownloadsAsk",
394 IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO
},
395 { "multipleAutomaticDownloadsBlock",
396 IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO
},
397 // MIDI system exclusive messages
398 { "midi-sysex_header", IDS_MIDI_SYSEX_TAB_LABEL
},
399 { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO
},
400 { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO
},
401 { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO
},
402 // Push messaging strings
403 { "push-messaging_header", IDS_PUSH_MESSAGES_TAB_LABEL
},
404 { "pushMessagingAllow", IDS_PUSH_MESSSAGING_ALLOW_RADIO
},
405 { "pushMessagingAsk", IDS_PUSH_MESSSAGING_ASK_RADIO
},
406 { "pushMessagingBlock", IDS_PUSH_MESSSAGING_BLOCK_RADIO
},
407 { "zoomlevels_header", IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL
},
408 { "zoomLevelsManage", IDS_ZOOMLEVELS_MANAGE_BUTTON
},
411 RegisterStrings(localized_strings
, resources
, arraysize(resources
));
412 RegisterTitle(localized_strings
, "contentSettingsPage",
413 IDS_CONTENT_SETTINGS_TITLE
);
415 // Register titles for each of the individual settings whose exception
416 // dialogs will be processed by |ContentSettingsHandler|.
417 RegisterTitle(localized_strings
, "cookies",
418 IDS_COOKIES_TAB_LABEL
);
419 RegisterTitle(localized_strings
, "images",
420 IDS_IMAGES_TAB_LABEL
);
421 RegisterTitle(localized_strings
, "javascript",
422 IDS_JAVASCRIPT_TAB_LABEL
);
423 RegisterTitle(localized_strings
, "plugins",
424 IDS_PLUGIN_TAB_LABEL
);
425 RegisterTitle(localized_strings
, "popups",
426 IDS_POPUP_TAB_LABEL
);
427 RegisterTitle(localized_strings
, "location",
428 IDS_GEOLOCATION_TAB_LABEL
);
429 RegisterTitle(localized_strings
, "notifications",
430 IDS_NOTIFICATIONS_TAB_LABEL
);
431 RegisterTitle(localized_strings
, "fullscreen",
432 IDS_FULLSCREEN_TAB_LABEL
);
433 RegisterTitle(localized_strings
, "mouselock",
434 IDS_MOUSE_LOCK_TAB_LABEL
);
435 #if defined(OS_CHROMEOS)
436 RegisterTitle(localized_strings
, "protectedContent",
437 IDS_PROTECTED_CONTENT_TAB_LABEL
);
439 RegisterTitle(localized_strings
, "media-stream",
440 IDS_MEDIA_STREAM_TAB_LABEL
);
441 RegisterTitle(localized_strings
, "ppapi-broker",
442 IDS_PPAPI_BROKER_TAB_LABEL
);
443 RegisterTitle(localized_strings
, "multiple-automatic-downloads",
444 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL
);
445 RegisterTitle(localized_strings
, "midi-sysex",
446 IDS_MIDI_SYSEX_TAB_LABEL
);
447 RegisterTitle(localized_strings
, "zoomlevels",
448 IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL
);
450 localized_strings
->SetString("exceptionsLearnMoreUrl",
451 kExceptionsLearnMoreUrl
);
454 void ContentSettingsHandler::InitializeHandler() {
455 notification_registrar_
.Add(
456 this, chrome::NOTIFICATION_PROFILE_CREATED
,
457 content::NotificationService::AllSources());
458 notification_registrar_
.Add(
459 this, chrome::NOTIFICATION_PROFILE_DESTROYED
,
460 content::NotificationService::AllSources());
462 notification_registrar_
.Add(
463 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED
,
464 content::NotificationService::AllSources());
465 content::BrowserContext
* context
= GetBrowserContext(web_ui());
466 notification_registrar_
.Add(
467 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED
,
468 content::Source
<content::BrowserContext
>(context
));
470 PrefService
* prefs
= user_prefs::UserPrefs::Get(context
);
471 pref_change_registrar_
.Init(prefs
);
472 pref_change_registrar_
.Add(
473 prefs::kPepperFlashSettingsEnabled
,
474 base::Bind(&ContentSettingsHandler::OnPepperFlashPrefChanged
,
475 base::Unretained(this)));
476 pref_change_registrar_
.Add(
477 prefs::kAudioCaptureAllowed
,
478 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView
,
479 base::Unretained(this)));
480 pref_change_registrar_
.Add(
481 prefs::kVideoCaptureAllowed
,
482 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView
,
483 base::Unretained(this)));
484 pref_change_registrar_
.Add(
487 &ContentSettingsHandler::UpdateProtectedContentExceptionsButton
,
488 base::Unretained(this)));
490 content::HostZoomMap
* host_zoom_map
=
491 content::HostZoomMap::GetDefaultForBrowserContext(context
);
492 host_zoom_map_subscription_
=
493 host_zoom_map
->AddZoomLevelChangedCallback(
494 base::Bind(&ContentSettingsHandler::OnZoomLevelChanged
,
495 base::Unretained(this)));
497 flash_settings_manager_
.reset(new PepperFlashSettingsManager(this, context
));
498 observer_
.Add(Profile::FromWebUI(web_ui())->GetHostContentSettingsMap());
501 void ContentSettingsHandler::InitializePage() {
502 media_settings_
= MediaSettingsInfo();
503 RefreshFlashMediaSettings();
505 UpdateHandlersEnabledRadios();
506 UpdateAllExceptionsViewsFromModel();
507 UpdateProtectedContentExceptionsButton();
510 void ContentSettingsHandler::OnContentSettingChanged(
511 const ContentSettingsPattern
& primary_pattern
,
512 const ContentSettingsPattern
& secondary_pattern
,
513 ContentSettingsType content_type
,
514 std::string resource_identifier
) {
515 const ContentSettingsDetails
details(
516 primary_pattern
, secondary_pattern
, content_type
, resource_identifier
);
517 // TODO(estade): we pretend update_all() is always true.
518 if (details
.update_all_types())
519 UpdateAllExceptionsViewsFromModel();
521 UpdateExceptionsViewFromModel(details
.type());
524 void ContentSettingsHandler::Observe(
526 const content::NotificationSource
& source
,
527 const content::NotificationDetails
& details
) {
529 case chrome::NOTIFICATION_PROFILE_DESTROYED
: {
530 if (content::Source
<Profile
>(source
).ptr()->IsOffTheRecord()) {
531 web_ui()->CallJavascriptFunction(
532 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
537 case chrome::NOTIFICATION_PROFILE_CREATED
: {
538 if (content::Source
<Profile
>(source
).ptr()->IsOffTheRecord())
539 UpdateAllOTRExceptionsViewsFromModel();
543 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED
: {
544 UpdateNotificationExceptionsView();
548 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED
: {
549 UpdateHandlersEnabledRadios();
555 void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
558 PP_Flash_BrowserOperations_Permission default_permission
,
559 const ppapi::FlashSiteSettings
& sites
) {
560 if (success
&& request_id
== media_settings_
.last_flash_refresh_request_id
) {
561 media_settings_
.flash_settings_initialized
= true;
562 media_settings_
.flash_default_setting
=
563 PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
565 PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
566 sites
, &media_settings_
.flash_exceptions
);
567 PepperFlashContentSettingsUtils::SortMediaExceptions(
568 &media_settings_
.flash_exceptions
);
570 UpdateFlashMediaLinksVisibility();
574 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
575 ContentSettingsType type
) {
576 base::DictionaryValue filter_settings
;
577 std::string provider_id
;
578 filter_settings
.SetString(ContentSettingsTypeToGroupName(type
) + ".value",
579 GetSettingDefaultFromModel(type
, &provider_id
));
580 filter_settings
.SetString(
581 ContentSettingsTypeToGroupName(type
) + ".managedBy", provider_id
);
583 web_ui()->CallJavascriptFunction(
584 "ContentSettings.setContentFilterSettingsValue", filter_settings
);
587 void ContentSettingsHandler::UpdateMediaSettingsView() {
588 PrefService
* prefs
= user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
589 bool audio_disabled
= !prefs
->GetBoolean(prefs::kAudioCaptureAllowed
) &&
590 prefs
->IsManagedPreference(prefs::kAudioCaptureAllowed
);
591 bool video_disabled
= !prefs
->GetBoolean(prefs::kVideoCaptureAllowed
) &&
592 prefs
->IsManagedPreference(prefs::kVideoCaptureAllowed
);
594 media_settings_
.policy_disable_audio
= audio_disabled
;
595 media_settings_
.policy_disable_video
= video_disabled
;
596 media_settings_
.default_setting
=
597 GetContentSettingsMap()->GetDefaultContentSetting(
598 CONTENT_SETTINGS_TYPE_MEDIASTREAM
, NULL
);
599 media_settings_
.default_setting_initialized
= true;
600 UpdateFlashMediaLinksVisibility();
602 base::DictionaryValue media_ui_settings
;
603 media_ui_settings
.SetBoolean("cameraDisabled", video_disabled
);
604 media_ui_settings
.SetBoolean("micDisabled", audio_disabled
);
606 // In case only video is enabled change the text appropriately.
607 if (audio_disabled
&& !video_disabled
) {
608 media_ui_settings
.SetString("askText", "mediaStreamVideoAsk");
609 media_ui_settings
.SetString("blockText", "mediaStreamVideoBlock");
610 media_ui_settings
.SetBoolean("showBubble", true);
611 media_ui_settings
.SetString("bubbleText", "mediaStreamBubbleAudio");
613 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
618 // In case only audio is enabled change the text appropriately.
619 if (video_disabled
&& !audio_disabled
) {
620 base::DictionaryValue media_ui_settings
;
621 media_ui_settings
.SetString("askText", "mediaStreamAudioAsk");
622 media_ui_settings
.SetString("blockText", "mediaStreamAudioBlock");
623 media_ui_settings
.SetBoolean("showBubble", true);
624 media_ui_settings
.SetString("bubbleText", "mediaStreamBubbleVideo");
626 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
631 if (audio_disabled
&& video_disabled
) {
632 // Fake policy controlled default because the user can not change anything
633 // until both audio and video are blocked.
634 base::DictionaryValue filter_settings
;
635 std::string group_name
=
636 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM
);
637 filter_settings
.SetString(group_name
+ ".value",
638 ContentSettingToString(CONTENT_SETTING_BLOCK
));
639 filter_settings
.SetString(group_name
+ ".managedBy", "policy");
640 web_ui()->CallJavascriptFunction(
641 "ContentSettings.setContentFilterSettingsValue", filter_settings
);
644 media_ui_settings
.SetString("askText", "mediaStreamAsk");
645 media_ui_settings
.SetString("blockText", "mediaStreamBlock");
646 media_ui_settings
.SetBoolean("showBubble", false);
647 media_ui_settings
.SetString("bubbleText", std::string());
649 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
653 std::string
ContentSettingsHandler::GetSettingDefaultFromModel(
654 ContentSettingsType type
, std::string
* provider_id
) {
655 Profile
* profile
= Profile::FromWebUI(web_ui());
656 ContentSetting default_setting
;
658 profile
->GetHostContentSettingsMap()->GetDefaultContentSetting(
661 return ContentSettingToString(default_setting
);
664 void ContentSettingsHandler::UpdateHandlersEnabledRadios() {
665 base::FundamentalValue
handlers_enabled(
666 GetProtocolHandlerRegistry()->enabled());
668 web_ui()->CallJavascriptFunction(
669 "ContentSettings.updateHandlersEnabledRadios",
673 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
674 for (int type
= CONTENT_SETTINGS_TYPE_DEFAULT
+ 1;
675 type
< CONTENT_SETTINGS_NUM_TYPES
; ++type
) {
676 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType
>(type
));
678 // Zoom levels are not actually a content type so we need to handle them
680 UpdateZoomLevelsExceptionsView();
683 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
684 for (int type
= CONTENT_SETTINGS_TYPE_DEFAULT
+ 1;
685 type
< CONTENT_SETTINGS_NUM_TYPES
; ++type
) {
686 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType
>(type
));
690 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
691 ContentSettingsType type
) {
693 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
694 UpdateGeolocationExceptionsView();
696 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
697 UpdateNotificationExceptionsView();
699 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
700 UpdateMediaSettingsView();
702 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
703 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
704 UpdateMediaExceptionsView();
706 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
:
707 // We don't yet support exceptions for mixed scripting.
709 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
:
710 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
711 // is supposed to be set by policy only. Hence there is no user facing UI
712 // for this content type and we skip it here.
714 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS
:
715 // The RPH settings are retrieved separately.
717 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
718 UpdateMIDISysExExceptionsView();
720 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS
:
721 // The content settings type CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS is
722 // supposed to be set by flags and field trials only, thus there is no
723 // user facing UI for this content type and we skip it here.
726 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP
:
730 UpdateExceptionsViewFromHostContentSettingsMap(type
);
735 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
736 ContentSettingsType type
) {
738 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
739 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
740 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
:
741 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT
:
743 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP
:
745 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
746 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
:
747 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
:
748 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
:
749 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
750 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS
:
753 UpdateExceptionsViewFromOTRHostContentSettingsMap(type
);
758 // TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
759 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
760 Profile
* profile
= Profile::FromWebUI(web_ui());
761 HostContentSettingsMap
* map
= profile
->GetHostContentSettingsMap();
763 ContentSettingsForOneType all_settings
;
764 map
->GetSettingsForOneType(
765 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
769 // Group geolocation settings by primary_pattern.
770 AllPatternsSettings all_patterns_settings
;
771 for (ContentSettingsForOneType::iterator i
= all_settings
.begin();
772 i
!= all_settings
.end(); ++i
) {
773 // Don't add default settings.
774 if (i
->primary_pattern
== ContentSettingsPattern::Wildcard() &&
775 i
->secondary_pattern
== ContentSettingsPattern::Wildcard() &&
776 i
->source
!= kPreferencesSource
) {
779 all_patterns_settings
[std::make_pair(i
->primary_pattern
, i
->source
)]
780 [i
->secondary_pattern
] = i
->setting
;
783 base::ListValue exceptions
;
784 AddExceptionsGrantedByHostedApps(
786 HostedAppHasPermission
<APIPermission::kGeolocation
>,
789 for (AllPatternsSettings::iterator i
= all_patterns_settings
.begin();
790 i
!= all_patterns_settings
.end(); ++i
) {
791 const ContentSettingsPattern
& primary_pattern
= i
->first
.first
;
792 const OnePatternSettings
& one_settings
= i
->second
;
794 OnePatternSettings::const_iterator parent
=
795 one_settings
.find(primary_pattern
);
797 // Add the "parent" entry for the non-embedded setting.
798 ContentSetting parent_setting
=
799 parent
== one_settings
.end() ? CONTENT_SETTING_DEFAULT
: parent
->second
;
800 exceptions
.Append(GetGeolocationExceptionForPage(primary_pattern
,
804 // Add the "children" for any embedded settings.
805 for (OnePatternSettings::const_iterator j
= one_settings
.begin();
806 j
!= one_settings
.end();
808 // Skip the non-embedded setting which we already added above.
812 exceptions
.Append(GetGeolocationExceptionForPage(
813 primary_pattern
, j
->first
, j
->second
));
817 base::StringValue
type_string(
818 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION
));
819 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
820 type_string
, exceptions
);
822 // This is mainly here to keep this function ideologically parallel to
823 // UpdateExceptionsViewFromHostContentSettingsMap().
824 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION
);
827 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
828 Profile
* profile
= Profile::FromWebUI(web_ui());
829 ContentSettingsForOneType settings
;
830 DesktopNotificationProfileUtil::GetNotificationsSettings(profile
, &settings
);
832 base::ListValue exceptions
;
833 AddExceptionsGrantedByHostedApps(
835 HostedAppHasPermission
<APIPermission::kNotifications
>,
838 for (ContentSettingsForOneType::const_iterator i
=
842 // Don't add default settings.
843 if (i
->primary_pattern
== ContentSettingsPattern::Wildcard() &&
844 i
->secondary_pattern
== ContentSettingsPattern::Wildcard() &&
845 i
->source
!= kPreferencesSource
) {
850 GetNotificationExceptionForPage(i
->primary_pattern
,
851 i
->secondary_pattern
,
856 base::StringValue
type_string(
857 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
));
858 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
859 type_string
, exceptions
);
861 // This is mainly here to keep this function ideologically parallel to
862 // UpdateExceptionsViewFromHostContentSettingsMap().
863 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
);
866 void ContentSettingsHandler::UpdateMediaExceptionsView() {
867 base::ListValue media_exceptions
;
868 GetExceptionsFromHostContentSettingsMap(
869 GetContentSettingsMap(),
870 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
873 base::ListValue video_exceptions
;
874 GetExceptionsFromHostContentSettingsMap(
875 GetContentSettingsMap(),
876 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
879 // Merge the |video_exceptions| list to |media_exceptions| list.
880 std::map
<std::string
, base::DictionaryValue
*> entries_map
;
881 for (base::ListValue::const_iterator
media_entry(media_exceptions
.begin());
882 media_entry
!= media_exceptions
.end(); ++media_entry
) {
883 base::DictionaryValue
* media_dict
= NULL
;
884 if (!(*media_entry
)->GetAsDictionary(&media_dict
))
887 media_dict
->SetString(kVideoSetting
,
888 ContentSettingToString(CONTENT_SETTING_ASK
));
890 std::string media_origin
;
891 media_dict
->GetString(kOrigin
, &media_origin
);
892 entries_map
[media_origin
] = media_dict
;
895 for (base::ListValue::iterator video_entry
= video_exceptions
.begin();
896 video_entry
!= video_exceptions
.end(); ++video_entry
) {
897 base::DictionaryValue
* video_dict
= NULL
;
898 if (!(*video_entry
)->GetAsDictionary(&video_dict
))
901 std::string video_origin
;
902 std::string video_setting
;
903 video_dict
->GetString(kOrigin
, &video_origin
);
904 video_dict
->GetString(kSetting
, &video_setting
);
906 std::map
<std::string
, base::DictionaryValue
*>::iterator iter
=
907 entries_map
.find(video_origin
);
908 if (iter
== entries_map
.end()) {
909 base::DictionaryValue
* exception
= new base::DictionaryValue();
910 exception
->SetString(kOrigin
, video_origin
);
911 exception
->SetString(kSetting
,
912 ContentSettingToString(CONTENT_SETTING_ASK
));
913 exception
->SetString(kVideoSetting
, video_setting
);
914 exception
->SetString(kSource
, kPreferencesSource
);
916 // Append the new entry to the list and map.
917 media_exceptions
.Append(exception
);
918 entries_map
[video_origin
] = exception
;
920 // Modify the existing entry.
921 iter
->second
->SetString(kVideoSetting
, video_setting
);
925 media_settings_
.exceptions
.clear();
926 for (base::ListValue::const_iterator media_entry
= media_exceptions
.begin();
927 media_entry
!= media_exceptions
.end(); ++media_entry
) {
928 base::DictionaryValue
* media_dict
= NULL
;
929 bool result
= (*media_entry
)->GetAsDictionary(&media_dict
);
933 std::string audio_setting
;
934 std::string video_setting
;
935 media_dict
->GetString(kOrigin
, &origin
);
936 media_dict
->GetString(kSetting
, &audio_setting
);
937 media_dict
->GetString(kVideoSetting
, &video_setting
);
938 media_settings_
.exceptions
.push_back(MediaException(
939 ContentSettingsPattern::FromString(origin
),
940 ContentSettingFromString(audio_setting
),
941 ContentSettingFromString(video_setting
)));
943 PepperFlashContentSettingsUtils::SortMediaExceptions(
944 &media_settings_
.exceptions
);
945 media_settings_
.exceptions_initialized
= true;
946 UpdateFlashMediaLinksVisibility();
948 base::StringValue
type_string(
949 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM
));
950 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
951 type_string
, media_exceptions
);
953 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MEDIASTREAM
);
956 void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
957 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebMIDI
)) {
958 web_ui()->CallJavascriptFunction(
959 "ContentSettings.showExperimentalWebMIDISettings",
960 base::FundamentalValue(true));
963 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX
);
964 UpdateExceptionsViewFromHostContentSettingsMap(
965 CONTENT_SETTINGS_TYPE_MIDI_SYSEX
);
968 void ContentSettingsHandler::UpdateZoomLevelsExceptionsView() {
969 base::ListValue zoom_levels_exceptions
;
971 content::HostZoomMap
* host_zoom_map
=
972 content::HostZoomMap::GetDefaultForBrowserContext(
973 GetBrowserContext(web_ui()));
974 content::HostZoomMap::ZoomLevelVector
zoom_levels(
975 host_zoom_map
->GetAllZoomLevels());
976 std::sort(zoom_levels
.begin(), zoom_levels
.end(), HostZoomSort
);
978 for (content::HostZoomMap::ZoomLevelVector::const_iterator i
=
980 i
!= zoom_levels
.end();
982 scoped_ptr
<base::DictionaryValue
> exception(new base::DictionaryValue
);
984 case content::HostZoomMap::ZOOM_CHANGED_FOR_HOST
:
985 exception
->SetString(kOrigin
, i
->host
);
987 case content::HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST
:
988 // These are not stored in preferences and get cleared on next browser
989 // start. Therefore, we don't care for them.
991 case content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM
:
994 exception
->SetString(kSetting
,
995 ContentSettingToString(CONTENT_SETTING_DEFAULT
));
997 // Calculate the zoom percent from the factor. Round up to the nearest whole
999 int zoom_percent
= static_cast<int>(
1000 content::ZoomLevelToZoomFactor(i
->zoom_level
) * 100 + 0.5);
1001 exception
->SetString(
1003 l10n_util::GetStringFUTF16(IDS_ZOOM_PERCENT
,
1004 base::IntToString16(zoom_percent
)));
1005 exception
->SetString(kSource
, kPreferencesSource
);
1006 // Append the new entry to the list and map.
1007 zoom_levels_exceptions
.Append(exception
.release());
1010 base::StringValue
type_string(kZoomContentType
);
1011 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
1012 type_string
, zoom_levels_exceptions
);
1015 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
1016 ContentSettingsType type
) {
1017 base::ListValue exceptions
;
1018 GetExceptionsFromHostContentSettingsMap(
1019 GetContentSettingsMap(), type
, &exceptions
);
1020 base::StringValue
type_string(ContentSettingsTypeToGroupName(type
));
1021 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string
,
1024 UpdateExceptionsViewFromOTRHostContentSettingsMap(type
);
1026 // TODO(koz): The default for fullscreen is always 'ask'.
1027 // http://crbug.com/104683
1028 if (type
== CONTENT_SETTINGS_TYPE_FULLSCREEN
)
1031 #if defined(OS_CHROMEOS)
1032 // Also the default for protected contents is managed in another place.
1033 if (type
== CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER
)
1037 // The default may also have changed (we won't get a separate notification).
1038 // If it hasn't changed, this call will be harmless.
1039 UpdateSettingDefaultFromModel(type
);
1042 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
1043 ContentSettingsType type
) {
1044 const HostContentSettingsMap
* otr_settings_map
= GetOTRContentSettingsMap();
1045 if (!otr_settings_map
)
1047 base::ListValue exceptions
;
1048 GetExceptionsFromHostContentSettingsMap(otr_settings_map
, type
, &exceptions
);
1049 base::StringValue
type_string(ContentSettingsTypeToGroupName(type
));
1050 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
1051 type_string
, exceptions
);
1054 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
1055 const HostContentSettingsMap
* map
,
1056 ContentSettingsType type
,
1057 base::ListValue
* exceptions
) {
1058 ContentSettingsForOneType entries
;
1059 map
->GetSettingsForOneType(type
, std::string(), &entries
);
1060 // Group settings by primary_pattern.
1061 AllPatternsSettings all_patterns_settings
;
1062 for (ContentSettingsForOneType::iterator i
= entries
.begin();
1063 i
!= entries
.end(); ++i
) {
1064 // Don't add default settings.
1065 if (i
->primary_pattern
== ContentSettingsPattern::Wildcard() &&
1066 i
->secondary_pattern
== ContentSettingsPattern::Wildcard() &&
1067 i
->source
!= kPreferencesSource
) {
1071 // Off-the-record HostContentSettingsMap contains incognito content settings
1072 // as well as normal content settings. Here, we use the incongnito settings
1074 if (map
->is_off_the_record() && !i
->incognito
)
1077 all_patterns_settings
[std::make_pair(i
->primary_pattern
, i
->source
)]
1078 [i
->secondary_pattern
] = i
->setting
;
1081 // Keep the exceptions sorted by provider so they will be displayed in
1082 // precedence order.
1083 std::vector
<std::vector
<base::Value
*> > all_provider_exceptions
;
1084 all_provider_exceptions
.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES
);
1086 for (AllPatternsSettings::iterator i
= all_patterns_settings
.begin();
1087 i
!= all_patterns_settings
.end();
1089 const ContentSettingsPattern
& primary_pattern
= i
->first
.first
;
1090 const OnePatternSettings
& one_settings
= i
->second
;
1092 // The "parent" entry either has an identical primary and secondary pattern,
1093 // or has a wildcard secondary. The two cases are indistinguishable in the
1095 OnePatternSettings::const_iterator parent
=
1096 one_settings
.find(primary_pattern
);
1097 if (parent
== one_settings
.end())
1098 parent
= one_settings
.find(ContentSettingsPattern::Wildcard());
1100 const std::string
& source
= i
->first
.second
;
1101 std::vector
<base::Value
*>* this_provider_exceptions
=
1102 &all_provider_exceptions
.at(
1103 HostContentSettingsMap::GetProviderTypeFromSource(source
));
1105 // Add the "parent" entry for the non-embedded setting.
1106 ContentSetting parent_setting
=
1107 parent
== one_settings
.end() ? CONTENT_SETTING_DEFAULT
: parent
->second
;
1108 const ContentSettingsPattern
& secondary_pattern
=
1109 parent
== one_settings
.end() ? primary_pattern
: parent
->first
;
1110 this_provider_exceptions
->push_back(GetExceptionForPage(primary_pattern
,
1115 // Add the "children" for any embedded settings.
1116 for (OnePatternSettings::const_iterator j
= one_settings
.begin();
1117 j
!= one_settings
.end(); ++j
) {
1118 // Skip the non-embedded setting which we already added above.
1122 ContentSetting content_setting
= j
->second
;
1123 this_provider_exceptions
->push_back(GetExceptionForPage(
1131 for (size_t i
= 0; i
< all_provider_exceptions
.size(); ++i
) {
1132 for (size_t j
= 0; j
< all_provider_exceptions
[i
].size(); ++j
) {
1133 exceptions
->Append(all_provider_exceptions
[i
][j
]);
1138 void ContentSettingsHandler::RemoveMediaException(const base::ListValue
* args
) {
1140 bool rv
= args
->GetString(1, &mode
);
1143 std::string pattern
;
1144 rv
= args
->GetString(2, &pattern
);
1147 HostContentSettingsMap
* settings_map
=
1148 mode
== "normal" ? GetContentSettingsMap() :
1149 GetOTRContentSettingsMap();
1151 settings_map
->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern
),
1152 ContentSettingsPattern::Wildcard(),
1153 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
,
1156 settings_map
->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern
),
1157 ContentSettingsPattern::Wildcard(),
1158 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
,
1164 void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
1165 const base::ListValue
* args
,
1166 ContentSettingsType type
) {
1168 bool rv
= args
->GetString(1, &mode
);
1171 std::string pattern
;
1172 rv
= args
->GetString(2, &pattern
);
1175 // The fourth argument to this handler is optional.
1176 std::string secondary_pattern
;
1177 if (args
->GetSize() >= 4U) {
1178 rv
= args
->GetString(3, &secondary_pattern
);
1182 HostContentSettingsMap
* settings_map
=
1183 mode
== "normal" ? GetContentSettingsMap() :
1184 GetOTRContentSettingsMap();
1186 settings_map
->SetWebsiteSetting(
1187 ContentSettingsPattern::FromString(pattern
),
1188 secondary_pattern
.empty() ?
1189 ContentSettingsPattern::Wildcard() :
1190 ContentSettingsPattern::FromString(secondary_pattern
),
1197 void ContentSettingsHandler::RemoveZoomLevelException(
1198 const base::ListValue
* args
) {
1200 bool rv
= args
->GetString(1, &mode
);
1203 std::string pattern
;
1204 rv
= args
->GetString(2, &pattern
);
1207 content::HostZoomMap
* host_zoom_map
=
1208 content::HostZoomMap::GetDefaultForBrowserContext(
1209 GetBrowserContext(web_ui()));
1210 double default_level
= host_zoom_map
->GetDefaultZoomLevel();
1211 host_zoom_map
->SetZoomLevelForHost(pattern
, default_level
);
1214 void ContentSettingsHandler::RegisterMessages() {
1215 web_ui()->RegisterMessageCallback("setContentFilter",
1216 base::Bind(&ContentSettingsHandler::SetContentFilter
,
1217 base::Unretained(this)));
1218 web_ui()->RegisterMessageCallback("removeException",
1219 base::Bind(&ContentSettingsHandler::RemoveException
,
1220 base::Unretained(this)));
1221 web_ui()->RegisterMessageCallback("setException",
1222 base::Bind(&ContentSettingsHandler::SetException
,
1223 base::Unretained(this)));
1224 web_ui()->RegisterMessageCallback("checkExceptionPatternValidity",
1225 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity
,
1226 base::Unretained(this)));
1229 void ContentSettingsHandler::SetContentFilter(const base::ListValue
* args
) {
1230 DCHECK_EQ(2U, args
->GetSize());
1231 std::string group
, setting
;
1232 if (!(args
->GetString(0, &group
) &&
1233 args
->GetString(1, &setting
))) {
1238 ContentSetting default_setting
= ContentSettingFromString(setting
);
1239 ContentSettingsType content_type
= ContentSettingsTypeFromGroupName(group
);
1240 Profile
* profile
= Profile::FromWebUI(web_ui());
1242 #if defined(OS_CHROMEOS)
1243 // ChromeOS special case : in Guest mode settings are opened in Incognito
1244 // mode, so we need original profile to actually modify settings.
1245 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
1246 profile
= profile
->GetOriginalProfile();
1250 HostContentSettingsMap
* map
= profile
->GetHostContentSettingsMap();
1251 map
->SetDefaultContentSetting(content_type
, default_setting
);
1253 switch (content_type
) {
1254 case CONTENT_SETTINGS_TYPE_COOKIES
:
1255 content::RecordAction(
1256 UserMetricsAction("Options_DefaultCookieSettingChanged"));
1258 case CONTENT_SETTINGS_TYPE_IMAGES
:
1259 content::RecordAction(
1260 UserMetricsAction("Options_DefaultImagesSettingChanged"));
1262 case CONTENT_SETTINGS_TYPE_JAVASCRIPT
:
1263 content::RecordAction(
1264 UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
1266 case CONTENT_SETTINGS_TYPE_PLUGINS
:
1267 content::RecordAction(
1268 UserMetricsAction("Options_DefaultPluginsSettingChanged"));
1270 case CONTENT_SETTINGS_TYPE_POPUPS
:
1271 content::RecordAction(
1272 UserMetricsAction("Options_DefaultPopupsSettingChanged"));
1274 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS
:
1275 content::RecordAction(
1276 UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
1278 case CONTENT_SETTINGS_TYPE_GEOLOCATION
:
1279 content::RecordAction(
1280 UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
1282 case CONTENT_SETTINGS_TYPE_MOUSELOCK
:
1283 content::RecordAction(
1284 UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
1286 case CONTENT_SETTINGS_TYPE_MEDIASTREAM
:
1287 content::RecordAction(
1288 UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
1290 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS
:
1291 content::RecordAction(
1292 UserMetricsAction("Options_DefaultMultipleAutomaticDLSettingChange"));
1294 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX
:
1295 content::RecordAction(
1296 UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
1298 case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING
:
1299 content::RecordAction(
1300 UserMetricsAction("Options_DefaultPushMessagingSettingChanged"));
1307 void ContentSettingsHandler::RemoveException(const base::ListValue
* args
) {
1308 std::string type_string
;
1309 CHECK(args
->GetString(0, &type_string
));
1311 // Zoom levels are no actual content type so we need to handle them
1312 // separately. They would not be recognized by
1313 // ContentSettingsTypeFromGroupName.
1314 if (type_string
== kZoomContentType
) {
1315 RemoveZoomLevelException(args
);
1319 ContentSettingsType type
= ContentSettingsTypeFromGroupName(type_string
);
1320 if (type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
)
1321 RemoveMediaException(args
);
1323 RemoveExceptionFromHostContentSettingsMap(args
, type
);
1326 void ContentSettingsHandler::SetException(const base::ListValue
* args
) {
1327 std::string type_string
;
1328 CHECK(args
->GetString(0, &type_string
));
1330 CHECK(args
->GetString(1, &mode
));
1331 std::string pattern
;
1332 CHECK(args
->GetString(2, &pattern
));
1333 std::string setting
;
1334 CHECK(args
->GetString(3, &setting
));
1336 ContentSettingsType type
= ContentSettingsTypeFromGroupName(type_string
);
1337 if (type
== CONTENT_SETTINGS_TYPE_GEOLOCATION
||
1338 type
== CONTENT_SETTINGS_TYPE_NOTIFICATIONS
||
1339 type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM
||
1340 type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
||
1341 type
== CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA
) {
1344 HostContentSettingsMap
* settings_map
=
1345 mode
== "normal" ? GetContentSettingsMap() :
1346 GetOTRContentSettingsMap();
1348 // The settings map could be null if the mode was OTR but the OTR profile
1349 // got destroyed before we received this message.
1352 settings_map
->SetContentSetting(ContentSettingsPattern::FromString(pattern
),
1353 ContentSettingsPattern::Wildcard(),
1356 ContentSettingFromString(setting
));
1360 void ContentSettingsHandler::CheckExceptionPatternValidity(
1361 const base::ListValue
* args
) {
1362 std::string type_string
;
1363 CHECK(args
->GetString(0, &type_string
));
1364 std::string mode_string
;
1365 CHECK(args
->GetString(1, &mode_string
));
1366 std::string pattern_string
;
1367 CHECK(args
->GetString(2, &pattern_string
));
1369 ContentSettingsPattern pattern
=
1370 ContentSettingsPattern::FromString(pattern_string
);
1372 web_ui()->CallJavascriptFunction(
1373 "ContentSettings.patternValidityCheckComplete",
1374 base::StringValue(type_string
),
1375 base::StringValue(mode_string
),
1376 base::StringValue(pattern_string
),
1377 base::FundamentalValue(pattern
.IsValid()));
1381 std::string
ContentSettingsHandler::ContentSettingsTypeToGroupName(
1382 ContentSettingsType type
) {
1383 for (size_t i
= 0; i
< arraysize(kContentSettingsTypeGroupNames
); ++i
) {
1384 if (type
== kContentSettingsTypeGroupNames
[i
].type
)
1385 return kContentSettingsTypeGroupNames
[i
].name
;
1389 return std::string();
1392 HostContentSettingsMap
* ContentSettingsHandler::GetContentSettingsMap() {
1393 return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap();
1396 ProtocolHandlerRegistry
* ContentSettingsHandler::GetProtocolHandlerRegistry() {
1397 return ProtocolHandlerRegistryFactory::GetForBrowserContext(
1398 GetBrowserContext(web_ui()));
1401 HostContentSettingsMap
*
1402 ContentSettingsHandler::GetOTRContentSettingsMap() {
1403 Profile
* profile
= Profile::FromWebUI(web_ui());
1404 if (profile
->HasOffTheRecordProfile())
1405 return profile
->GetOffTheRecordProfile()->GetHostContentSettingsMap();
1409 void ContentSettingsHandler::RefreshFlashMediaSettings() {
1410 media_settings_
.flash_settings_initialized
= false;
1412 media_settings_
.last_flash_refresh_request_id
=
1413 flash_settings_manager_
->GetPermissionSettings(
1414 PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC
);
1417 void ContentSettingsHandler::OnPepperFlashPrefChanged() {
1418 ShowFlashMediaLink(DEFAULT_SETTING
, false);
1419 ShowFlashMediaLink(EXCEPTIONS
, false);
1421 PrefService
* prefs
= user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
1422 if (prefs
->GetBoolean(prefs::kPepperFlashSettingsEnabled
))
1423 RefreshFlashMediaSettings();
1425 media_settings_
.flash_settings_initialized
= false;
1428 void ContentSettingsHandler::OnZoomLevelChanged(
1429 const content::HostZoomMap::ZoomLevelChange
& change
) {
1430 UpdateZoomLevelsExceptionsView();
1433 void ContentSettingsHandler::ShowFlashMediaLink(LinkType link_type
, bool show
) {
1434 bool& show_link
= link_type
== DEFAULT_SETTING
?
1435 media_settings_
.show_flash_default_link
:
1436 media_settings_
.show_flash_exceptions_link
;
1437 if (show_link
!= show
) {
1438 web_ui()->CallJavascriptFunction(
1439 link_type
== DEFAULT_SETTING
?
1440 "ContentSettings.showMediaPepperFlashDefaultLink" :
1441 "ContentSettings.showMediaPepperFlashExceptionsLink",
1442 base::FundamentalValue(show
));
1447 void ContentSettingsHandler::UpdateFlashMediaLinksVisibility() {
1448 if (!media_settings_
.flash_settings_initialized
||
1449 !media_settings_
.default_setting_initialized
||
1450 !media_settings_
.exceptions_initialized
) {
1454 // Flash won't send us notifications when its settings get changed, which
1455 // means the Flash settings in |media_settings_| may be out-dated, especially
1456 // after we show links to change Flash settings.
1457 // In order to avoid confusion, we won't hide the links once they are showed.
1458 // One exception is that we will hide them when Pepper Flash is disabled
1459 // (handled in OnPepperFlashPrefChanged()).
1460 if (media_settings_
.show_flash_default_link
&&
1461 media_settings_
.show_flash_exceptions_link
) {
1465 if (!media_settings_
.show_flash_default_link
) {
1466 // If both audio and video capture are disabled by policy, the link
1467 // shouldn't be showed. Flash conforms to the policy in this case because
1468 // it cannot open those devices. We don't have to look at the Flash
1470 if (!(media_settings_
.policy_disable_audio
&&
1471 media_settings_
.policy_disable_video
) &&
1472 media_settings_
.flash_default_setting
!=
1473 media_settings_
.default_setting
) {
1474 ShowFlashMediaLink(DEFAULT_SETTING
, true);
1477 if (!media_settings_
.show_flash_exceptions_link
) {
1478 // If audio or video capture is disabled by policy, we skip comparison of
1479 // exceptions for audio or video capture, respectively.
1480 if (!PepperFlashContentSettingsUtils::AreMediaExceptionsEqual(
1481 media_settings_
.default_setting
,
1482 media_settings_
.exceptions
,
1483 media_settings_
.flash_default_setting
,
1484 media_settings_
.flash_exceptions
,
1485 media_settings_
.policy_disable_audio
,
1486 media_settings_
.policy_disable_video
)) {
1487 ShowFlashMediaLink(EXCEPTIONS
, true);
1492 void ContentSettingsHandler::UpdateProtectedContentExceptionsButton() {
1493 #if defined(OS_CHROMEOS)
1494 // Guests cannot modify exceptions. UIAccountTweaks will disabled the button.
1495 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
1499 // Exceptions apply only when the feature is enabled.
1500 PrefService
* prefs
= user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
1501 bool enable_exceptions
= prefs
->GetBoolean(prefs::kEnableDRM
);
1502 web_ui()->CallJavascriptFunction(
1503 "ContentSettings.enableProtectedContentExceptions",
1504 base::FundamentalValue(enable_exceptions
));
1507 } // namespace options