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/extension_set.h"
34 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
35 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h"
37 #include "content/public/browser/notification_service.h"
38 #include "content/public/browser/notification_source.h"
39 #include "content/public/browser/notification_types.h"
40 #include "content/public/browser/user_metrics.h"
41 #include "content/public/browser/web_ui.h"
42 #include "content/public/common/content_switches.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 content::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 {CONTENT_SETTINGS_TYPE_SAVE_PASSWORD, "save-password"},
106 #if defined(OS_CHROMEOS)
107 {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, "protectedContent"},
111 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
112 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
113 if (name == kContentSettingsTypeGroupNames[i].name)
114 return kContentSettingsTypeGroupNames[i].type;
117 NOTREACHED() << name << " is not a recognized content settings type.";
118 return CONTENT_SETTINGS_TYPE_DEFAULT;
121 std::string ContentSettingToString(ContentSetting setting) {
123 case CONTENT_SETTING_ALLOW:
125 case CONTENT_SETTING_ASK:
127 case CONTENT_SETTING_BLOCK:
129 case CONTENT_SETTING_SESSION_ONLY:
131 case CONTENT_SETTING_DEFAULT:
133 case CONTENT_SETTING_NUM_SETTINGS:
137 return std::string();
140 ContentSetting ContentSettingFromString(const std::string& name) {
142 return CONTENT_SETTING_ALLOW;
144 return CONTENT_SETTING_ASK;
146 return CONTENT_SETTING_BLOCK;
147 if (name == "session")
148 return CONTENT_SETTING_SESSION_ONLY;
150 NOTREACHED() << name << " is not a recognized content setting.";
151 return CONTENT_SETTING_DEFAULT;
154 // Create a DictionaryValue* that will act as a data source for a single row
155 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
156 // Ownership of the pointer is passed to the caller.
157 DictionaryValue* GetExceptionForPage(
158 const ContentSettingsPattern& pattern,
159 const ContentSettingsPattern& secondary_pattern,
160 const ContentSetting& setting,
161 const std::string& provider_name) {
162 DictionaryValue* exception = new DictionaryValue();
163 exception->SetString(kOrigin, pattern.ToString());
164 exception->SetString(kEmbeddingOrigin,
165 secondary_pattern == ContentSettingsPattern::Wildcard()
167 : secondary_pattern.ToString());
168 exception->SetString(kSetting, ContentSettingToString(setting));
169 exception->SetString(kSource, provider_name);
173 // Create a DictionaryValue* that will act as a data source for a single row
174 // in the Geolocation exceptions table. Ownership of the pointer is passed to
176 DictionaryValue* GetGeolocationExceptionForPage(
177 const ContentSettingsPattern& origin,
178 const ContentSettingsPattern& embedding_origin,
179 ContentSetting setting) {
180 DictionaryValue* exception = new DictionaryValue();
181 exception->SetString(kSetting, ContentSettingToString(setting));
182 exception->SetString(kOrigin, origin.ToString());
183 exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
187 // Create a DictionaryValue* that will act as a data source for a single row
188 // in the desktop notifications exceptions table. Ownership of the pointer is
189 // passed to the caller.
190 DictionaryValue* GetNotificationExceptionForPage(
191 const ContentSettingsPattern& pattern,
192 ContentSetting setting,
193 const std::string& provider_name) {
194 DictionaryValue* exception = new DictionaryValue();
195 exception->SetString(kSetting, ContentSettingToString(setting));
196 exception->SetString(kOrigin, pattern.ToString());
197 exception->SetString(kSource, provider_name);
201 // Returns true whenever the |extension| is hosted and has |permission|.
202 // Must have the AppFilter signature.
203 template <APIPermission::ID permission>
204 bool HostedAppHasPermission(
205 const extensions::Extension& extension, Profile* /*profile*/) {
206 return extension.is_hosted_app() && extension.HasAPIPermission(permission);
209 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
210 // the web extent of a hosted |app|.
211 void AddExceptionForHostedApp(const std::string& url_pattern,
212 const extensions::Extension& app, ListValue* exceptions) {
213 DictionaryValue* exception = new DictionaryValue();
214 exception->SetString(kSetting, ContentSettingToString(CONTENT_SETTING_ALLOW));
215 exception->SetString(kOrigin, url_pattern);
216 exception->SetString(kEmbeddingOrigin, url_pattern);
217 exception->SetString(kSource, "HostedApp");
218 exception->SetString(kAppName, app.name());
219 exception->SetString(kAppId, app.id());
220 exceptions->Append(exception);
223 // Asks the |profile| for hosted apps which have the |permission| set, and
224 // adds their web extent and launch URL to the |exceptions| list.
225 void AddExceptionsGrantedByHostedApps(
226 Profile* profile, AppFilter app_filter, ListValue* exceptions) {
227 const ExtensionService* extension_service = profile->GetExtensionService();
228 // After ExtensionSystem::Init has been called at the browser's start,
229 // GetExtensionService() should not return NULL, so this is safe:
230 const ExtensionSet* extensions = extension_service->extensions();
232 for (ExtensionSet::const_iterator extension = extensions->begin();
233 extension != extensions->end(); ++extension) {
234 if (!app_filter(*extension->get(), profile))
237 extensions::URLPatternSet web_extent = (*extension)->web_extent();
238 // Add patterns from web extent.
239 for (extensions::URLPatternSet::const_iterator pattern = web_extent.begin();
240 pattern != web_extent.end(); ++pattern) {
241 std::string url_pattern = pattern->GetAsString();
242 AddExceptionForHostedApp(url_pattern, *extension->get(), exceptions);
244 // Retrieve the launch URL.
246 extensions::AppLaunchInfo::GetLaunchWebURL(extension->get());
247 // Skip adding the launch URL if it is part of the web extent.
248 if (web_extent.MatchesURL(launch_url))
250 AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions);
258 ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo()
259 : flash_default_setting(CONTENT_SETTING_DEFAULT),
260 flash_settings_initialized(false),
261 last_flash_refresh_request_id(0),
262 show_flash_default_link(false),
263 show_flash_exceptions_link(false),
264 default_setting(CONTENT_SETTING_DEFAULT),
265 policy_disable_audio(false),
266 policy_disable_video(false),
267 default_setting_initialized(false),
268 exceptions_initialized(false) {
271 ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
274 ContentSettingsHandler::ContentSettingsHandler() {
277 ContentSettingsHandler::~ContentSettingsHandler() {
280 void ContentSettingsHandler::GetLocalizedValues(
281 DictionaryValue* localized_strings) {
282 DCHECK(localized_strings);
284 static OptionsStringResource resources[] = {
285 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
286 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
287 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
288 { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
289 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
290 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
291 { "manageExceptions", IDS_EXCEPTIONS_MANAGE },
292 { "manage_handlers", IDS_HANDLERS_MANAGE },
293 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
294 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
295 { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST },
297 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
298 { "cookies_header", IDS_COOKIES_HEADER },
299 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO },
300 { "cookies_block", IDS_COOKIES_BLOCK_RADIO },
301 { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO },
302 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
303 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX },
304 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX },
305 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
306 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
307 { "flash_storage_url", IDS_FLASH_STORAGE_URL },
308 #if defined(ENABLE_GOOGLE_NOW)
309 { "googleGeolocationAccessEnable",
310 IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX },
313 { "images_tab_label", IDS_IMAGES_TAB_LABEL },
314 { "images_header", IDS_IMAGES_HEADER },
315 { "images_allow", IDS_IMAGES_LOAD_RADIO },
316 { "images_block", IDS_IMAGES_NOLOAD_RADIO },
317 // JavaScript filter.
318 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL },
319 { "javascript_header", IDS_JAVASCRIPT_HEADER },
320 { "javascript_allow", IDS_JS_ALLOW_RADIO },
321 { "javascript_block", IDS_JS_DONOTALLOW_RADIO },
323 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL },
324 { "plugins_header", IDS_PLUGIN_HEADER },
325 { "plugins_ask", IDS_PLUGIN_ASK_RADIO },
326 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO },
327 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO },
328 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE },
330 { "popups_tab_label", IDS_POPUP_TAB_LABEL },
331 { "popups_header", IDS_POPUP_HEADER },
332 { "popups_allow", IDS_POPUP_ALLOW_RADIO },
333 { "popups_block", IDS_POPUP_BLOCK_RADIO },
335 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL },
336 { "location_header", IDS_GEOLOCATION_HEADER },
337 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO },
338 { "location_ask", IDS_GEOLOCATION_ASK_RADIO },
339 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO },
340 { "set_by", IDS_GEOLOCATION_SET_BY_HOVER },
341 // Notifications filter.
342 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL },
343 { "notifications_header", IDS_NOTIFICATIONS_HEADER },
344 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO },
345 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO },
346 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO },
347 // Fullscreen filter.
348 { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL },
349 { "fullscreen_header", IDS_FULLSCREEN_HEADER },
350 // Mouse Lock filter.
351 { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL },
352 { "mouselock_header", IDS_MOUSE_LOCK_HEADER },
353 { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO },
354 { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO },
355 { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO },
356 #if defined(OS_CHROMEOS) || defined(OS_WIN)
357 // Protected Content filter
358 { "protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL },
359 { "protectedContentInfo", IDS_PROTECTED_CONTENT_INFO },
360 { "protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE },
361 { "protectedContent_header", IDS_PROTECTED_CONTENT_HEADER },
362 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
363 // Media stream capture device filter.
364 { "mediaStreamTabLabel", IDS_MEDIA_STREAM_TAB_LABEL },
365 { "media-stream_header", IDS_MEDIA_STREAM_HEADER },
366 { "mediaStreamAsk", IDS_MEDIA_STREAM_ASK_RADIO },
367 { "mediaStreamBlock", IDS_MEDIA_STREAM_BLOCK_RADIO },
368 { "mediaStreamAudioAsk", IDS_MEDIA_STREAM_ASK_AUDIO_ONLY_RADIO },
369 { "mediaStreamAudioBlock", IDS_MEDIA_STREAM_BLOCK_AUDIO_ONLY_RADIO },
370 { "mediaStreamVideoAsk", IDS_MEDIA_STREAM_ASK_VIDEO_ONLY_RADIO },
371 { "mediaStreamVideoBlock", IDS_MEDIA_STREAM_BLOCK_VIDEO_ONLY_RADIO },
372 { "mediaStreamBubbleAudio", IDS_MEDIA_STREAM_AUDIO_MANAGED },
373 { "mediaStreamBubbleVideo", IDS_MEDIA_STREAM_VIDEO_MANAGED },
374 { "mediaAudioExceptionHeader", IDS_MEDIA_AUDIO_EXCEPTION_HEADER },
375 { "mediaVideoExceptionHeader", IDS_MEDIA_VIDEO_EXCEPTION_HEADER },
376 { "mediaPepperFlashDefaultDivergedLabel",
377 IDS_MEDIA_PEPPER_FLASH_DEFAULT_DIVERGED_LABEL },
378 { "mediaPepperFlashExceptionsDivergedLabel",
379 IDS_MEDIA_PEPPER_FLASH_EXCEPTIONS_DIVERGED_LABEL },
380 { "mediaPepperFlashChangeLink", IDS_MEDIA_PEPPER_FLASH_CHANGE_LINK },
381 { "mediaPepperFlashGlobalPrivacyURL", IDS_FLASH_GLOBAL_PRIVACY_URL },
382 { "mediaPepperFlashWebsitePrivacyURL", IDS_FLASH_WEBSITE_PRIVACY_URL },
383 // PPAPI broker filter.
384 // TODO(bauerb): Use IDS_PPAPI_BROKER_HEADER.
385 { "ppapi-broker_header", IDS_PPAPI_BROKER_TAB_LABEL },
386 { "ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL },
387 { "ppapi_broker_allow", IDS_PPAPI_BROKER_ALLOW_RADIO },
388 { "ppapi_broker_ask", IDS_PPAPI_BROKER_ASK_RADIO },
389 { "ppapi_broker_block", IDS_PPAPI_BROKER_BLOCK_RADIO },
390 // Multiple automatic downloads
391 { "multiple-automatic-downloads_header",
392 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL },
393 { "multiple-automatic-downloads_allow",
394 IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO },
395 { "multiple-automatic-downloads_ask",
396 IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO },
397 { "multiple-automatic-downloads_block",
398 IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO },
399 // MIDI system exclusive messages
400 { "midi-sysex_header", IDS_MIDI_SYSEX_TAB_LABEL },
401 { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO },
402 { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO },
403 { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO },
406 RegisterStrings(localized_strings, resources, arraysize(resources));
407 RegisterTitle(localized_strings, "contentSettingsPage",
408 IDS_CONTENT_SETTINGS_TITLE);
410 // Register titles for each of the individual settings whose exception
411 // dialogs will be processed by |ContentSettingsHandler|.
412 RegisterTitle(localized_strings, "cookies",
413 IDS_COOKIES_TAB_LABEL);
414 RegisterTitle(localized_strings, "images",
415 IDS_IMAGES_TAB_LABEL);
416 RegisterTitle(localized_strings, "javascript",
417 IDS_JAVASCRIPT_TAB_LABEL);
418 RegisterTitle(localized_strings, "plugins",
419 IDS_PLUGIN_TAB_LABEL);
420 RegisterTitle(localized_strings, "popups",
421 IDS_POPUP_TAB_LABEL);
422 RegisterTitle(localized_strings, "location",
423 IDS_GEOLOCATION_TAB_LABEL);
424 RegisterTitle(localized_strings, "notifications",
425 IDS_NOTIFICATIONS_TAB_LABEL);
426 RegisterTitle(localized_strings, "fullscreen",
427 IDS_FULLSCREEN_TAB_LABEL);
428 RegisterTitle(localized_strings, "mouselock",
429 IDS_MOUSE_LOCK_TAB_LABEL);
430 #if defined(OS_CHROMEOS)
431 RegisterTitle(localized_strings, "protectedContent",
432 IDS_PROTECTED_CONTENT_TAB_LABEL);
434 RegisterTitle(localized_strings, "media-stream",
435 IDS_MEDIA_STREAM_TAB_LABEL);
436 RegisterTitle(localized_strings, "ppapi-broker",
437 IDS_PPAPI_BROKER_TAB_LABEL);
438 RegisterTitle(localized_strings, "multiple-automatic-downloads",
439 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
440 RegisterTitle(localized_strings, "midi-sysex",
441 IDS_MIDI_SYSEX_TAB_LABEL);
443 localized_strings->SetBoolean("newContentSettings",
444 CommandLine::ForCurrentProcess()->HasSwitch(switches::kContentSettings2));
445 localized_strings->SetString(
446 "exceptionsLearnMoreUrl",
447 google_util::StringAppendGoogleLocaleParam(
448 kExceptionsLearnMoreUrl));
451 void ContentSettingsHandler::InitializeHandler() {
452 notification_registrar_.Add(
453 this, chrome::NOTIFICATION_PROFILE_CREATED,
454 content::NotificationService::AllSources());
455 notification_registrar_.Add(
456 this, chrome::NOTIFICATION_PROFILE_DESTROYED,
457 content::NotificationService::AllSources());
459 notification_registrar_.Add(
460 this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
461 content::NotificationService::AllSources());
462 notification_registrar_.Add(
463 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
464 content::NotificationService::AllSources());
465 Profile* profile = Profile::FromWebUI(web_ui());
466 notification_registrar_.Add(
467 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
468 content::Source<Profile>(profile));
470 PrefService* prefs = profile->GetPrefs();
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)));
485 flash_settings_manager_.reset(new PepperFlashSettingsManager(this, profile));
488 void ContentSettingsHandler::InitializePage() {
489 media_settings_ = MediaSettingsInfo();
490 RefreshFlashMediaSettings();
492 UpdateHandlersEnabledRadios();
493 UpdateAllExceptionsViewsFromModel();
496 void ContentSettingsHandler::Observe(
498 const content::NotificationSource& source,
499 const content::NotificationDetails& details) {
501 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
502 if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) {
503 web_ui()->CallJavascriptFunction(
504 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
509 case chrome::NOTIFICATION_PROFILE_CREATED: {
510 if (content::Source<Profile>(source).ptr()->IsOffTheRecord())
511 UpdateAllOTRExceptionsViewsFromModel();
515 case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED: {
516 // Filter out notifications from other profiles.
517 HostContentSettingsMap* map =
518 content::Source<HostContentSettingsMap>(source).ptr();
519 if (map != GetContentSettingsMap() &&
520 map != GetOTRContentSettingsMap())
523 const ContentSettingsDetails* settings_details =
524 content::Details<const ContentSettingsDetails>(details).ptr();
526 // TODO(estade): we pretend update_all() is always true.
527 if (settings_details->update_all_types())
528 UpdateAllExceptionsViewsFromModel();
530 UpdateExceptionsViewFromModel(settings_details->type());
534 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: {
535 UpdateNotificationExceptionsView();
539 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: {
540 UpdateHandlersEnabledRadios();
545 OptionsPageUIHandler::Observe(type, source, details);
549 void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
552 PP_Flash_BrowserOperations_Permission default_permission,
553 const ppapi::FlashSiteSettings& sites) {
554 if (success && request_id == media_settings_.last_flash_refresh_request_id) {
555 media_settings_.flash_settings_initialized = true;
556 media_settings_.flash_default_setting =
557 PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
559 PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
560 sites, &media_settings_.flash_exceptions);
561 PepperFlashContentSettingsUtils::SortMediaExceptions(
562 &media_settings_.flash_exceptions);
564 UpdateFlashMediaLinksVisibility();
568 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
569 ContentSettingsType type) {
570 DictionaryValue filter_settings;
571 std::string provider_id;
572 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
573 GetSettingDefaultFromModel(type, &provider_id));
574 filter_settings.SetString(
575 ContentSettingsTypeToGroupName(type) + ".managedBy", provider_id);
577 web_ui()->CallJavascriptFunction(
578 "ContentSettings.setContentFilterSettingsValue", filter_settings);
581 void ContentSettingsHandler::UpdateMediaSettingsView() {
582 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
583 bool audio_disabled = !prefs->GetBoolean(prefs::kAudioCaptureAllowed) &&
584 prefs->IsManagedPreference(prefs::kAudioCaptureAllowed);
585 bool video_disabled = !prefs->GetBoolean(prefs::kVideoCaptureAllowed) &&
586 prefs->IsManagedPreference(prefs::kVideoCaptureAllowed);
588 media_settings_.policy_disable_audio = audio_disabled;
589 media_settings_.policy_disable_video = video_disabled;
590 media_settings_.default_setting =
591 GetContentSettingsMap()->GetDefaultContentSetting(
592 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
593 media_settings_.default_setting_initialized = true;
594 UpdateFlashMediaLinksVisibility();
596 DictionaryValue media_ui_settings;
597 media_ui_settings.SetBoolean("cameraDisabled", video_disabled);
598 media_ui_settings.SetBoolean("micDisabled", audio_disabled);
600 // In case only video is enabled change the text appropriately.
601 if (audio_disabled && !video_disabled) {
602 media_ui_settings.SetString("askText", "mediaStreamVideoAsk");
603 media_ui_settings.SetString("blockText", "mediaStreamVideoBlock");
604 media_ui_settings.SetBoolean("showBubble", true);
605 media_ui_settings.SetString("bubbleText", "mediaStreamBubbleAudio");
607 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
612 // In case only audio is enabled change the text appropriately.
613 if (video_disabled && !audio_disabled) {
614 DictionaryValue media_ui_settings;
615 media_ui_settings.SetString("askText", "mediaStreamAudioAsk");
616 media_ui_settings.SetString("blockText", "mediaStreamAudioBlock");
617 media_ui_settings.SetBoolean("showBubble", true);
618 media_ui_settings.SetString("bubbleText", "mediaStreamBubbleVideo");
620 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
625 if (audio_disabled && video_disabled) {
626 // Fake policy controlled default because the user can not change anything
627 // until both audio and video are blocked.
628 DictionaryValue filter_settings;
629 std::string group_name =
630 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
631 filter_settings.SetString(group_name + ".value",
632 ContentSettingToString(CONTENT_SETTING_BLOCK));
633 filter_settings.SetString(group_name + ".managedBy", "policy");
634 web_ui()->CallJavascriptFunction(
635 "ContentSettings.setContentFilterSettingsValue", filter_settings);
638 media_ui_settings.SetString("askText", "mediaStreamAsk");
639 media_ui_settings.SetString("blockText", "mediaStreamBlock");
640 media_ui_settings.SetBoolean("showBubble", false);
641 media_ui_settings.SetString("bubbleText", std::string());
643 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
647 std::string ContentSettingsHandler::GetSettingDefaultFromModel(
648 ContentSettingsType type, std::string* provider_id) {
649 Profile* profile = Profile::FromWebUI(web_ui());
650 ContentSetting default_setting;
651 if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
653 DesktopNotificationServiceFactory::GetForProfile(profile)->
654 GetDefaultContentSetting(provider_id);
657 profile->GetHostContentSettingsMap()->
658 GetDefaultContentSetting(type, provider_id);
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));
680 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
681 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
682 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
683 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
687 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
688 ContentSettingsType type) {
690 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
691 UpdateGeolocationExceptionsView();
693 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
694 UpdateNotificationExceptionsView();
696 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
697 UpdateMediaSettingsView();
699 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
700 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
701 UpdateMediaExceptionsView();
703 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
704 // We don't yet support exceptions for mixed scripting.
706 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
707 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
708 // is supposed to be set by policy only. Hence there is no user facing UI
709 // for this content type and we skip it here.
711 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
712 // The RPH settings are retrieved separately.
714 case CONTENT_SETTINGS_TYPE_SAVE_PASSWORD:
715 // There is no user facing UI for this content type and we skip it here.
717 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
718 UpdateMIDISysExExceptionsView();
721 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
725 UpdateExceptionsViewFromHostContentSettingsMap(type);
730 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
731 ContentSettingsType type) {
733 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
734 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
735 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
736 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
738 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
740 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
741 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
742 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
743 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
744 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
747 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
752 // TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
753 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
754 Profile* profile = Profile::FromWebUI(web_ui());
755 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
757 ContentSettingsForOneType all_settings;
758 map->GetSettingsForOneType(
759 CONTENT_SETTINGS_TYPE_GEOLOCATION,
763 // Group geolocation settings by primary_pattern.
764 AllPatternsSettings all_patterns_settings;
765 for (ContentSettingsForOneType::iterator i = all_settings.begin();
766 i != all_settings.end(); ++i) {
767 // Don't add default settings.
768 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
769 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
770 i->source != kPreferencesSource) {
773 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
774 [i->secondary_pattern] = i->setting;
777 ListValue exceptions;
778 AddExceptionsGrantedByHostedApps(
780 HostedAppHasPermission<APIPermission::kGeolocation>,
783 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
784 i != all_patterns_settings.end(); ++i) {
785 const ContentSettingsPattern& primary_pattern = i->first.first;
786 const OnePatternSettings& one_settings = i->second;
788 OnePatternSettings::const_iterator parent =
789 one_settings.find(primary_pattern);
791 // Add the "parent" entry for the non-embedded setting.
792 ContentSetting parent_setting =
793 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
794 exceptions.Append(GetGeolocationExceptionForPage(primary_pattern,
798 // Add the "children" for any embedded settings.
799 for (OnePatternSettings::const_iterator j = one_settings.begin();
800 j != one_settings.end();
802 // Skip the non-embedded setting which we already added above.
806 exceptions.Append(GetGeolocationExceptionForPage(
807 primary_pattern, j->first, j->second));
811 StringValue type_string(
812 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
813 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
814 type_string, exceptions);
816 // This is mainly here to keep this function ideologically parallel to
817 // UpdateExceptionsViewFromHostContentSettingsMap().
818 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
821 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
822 Profile* profile = Profile::FromWebUI(web_ui());
823 DesktopNotificationService* service =
824 DesktopNotificationServiceFactory::GetForProfile(profile);
826 ContentSettingsForOneType settings;
827 service->GetNotificationsSettings(&settings);
829 ListValue exceptions;
830 AddExceptionsGrantedByHostedApps(profile,
831 HostedAppHasPermission<APIPermission::kNotification>,
834 for (ContentSettingsForOneType::const_iterator i =
838 // Don't add default settings.
839 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
840 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
841 i->source != kPreferencesSource) {
846 GetNotificationExceptionForPage(i->primary_pattern, i->setting,
850 StringValue type_string(
851 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
852 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
853 type_string, exceptions);
855 // This is mainly here to keep this function ideologically parallel to
856 // UpdateExceptionsViewFromHostContentSettingsMap().
857 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
860 void ContentSettingsHandler::UpdateMediaExceptionsView() {
861 ListValue media_exceptions;
862 GetExceptionsFromHostContentSettingsMap(
863 GetContentSettingsMap(),
864 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
867 ListValue video_exceptions;
868 GetExceptionsFromHostContentSettingsMap(
869 GetContentSettingsMap(),
870 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
873 // Merge the |video_exceptions| list to |media_exceptions| list.
874 std::map<std::string, base::DictionaryValue*> entries_map;
875 for (ListValue::const_iterator media_entry(media_exceptions.begin());
876 media_entry != media_exceptions.end(); ++media_entry) {
877 DictionaryValue* media_dict = NULL;
878 if (!(*media_entry)->GetAsDictionary(&media_dict))
881 media_dict->SetString(kVideoSetting,
882 ContentSettingToString(CONTENT_SETTING_ASK));
884 std::string media_origin;
885 media_dict->GetString(kOrigin, &media_origin);
886 entries_map[media_origin] = media_dict;
889 for (ListValue::iterator video_entry = video_exceptions.begin();
890 video_entry != video_exceptions.end(); ++video_entry) {
891 DictionaryValue* video_dict = NULL;
892 if (!(*video_entry)->GetAsDictionary(&video_dict))
895 std::string video_origin;
896 std::string video_setting;
897 video_dict->GetString(kOrigin, &video_origin);
898 video_dict->GetString(kSetting, &video_setting);
900 std::map<std::string, base::DictionaryValue*>::iterator iter =
901 entries_map.find(video_origin);
902 if (iter == entries_map.end()) {
903 DictionaryValue* exception = new DictionaryValue();
904 exception->SetString(kOrigin, video_origin);
905 exception->SetString(kSetting,
906 ContentSettingToString(CONTENT_SETTING_ASK));
907 exception->SetString(kVideoSetting, video_setting);
908 exception->SetString(kSource, kPreferencesSource);
910 // Append the new entry to the list and map.
911 media_exceptions.Append(exception);
912 entries_map[video_origin] = exception;
914 // Modify the existing entry.
915 iter->second->SetString(kVideoSetting, video_setting);
919 media_settings_.exceptions.clear();
920 for (ListValue::const_iterator media_entry = media_exceptions.begin();
921 media_entry != media_exceptions.end(); ++media_entry) {
922 DictionaryValue* media_dict = NULL;
923 bool result = (*media_entry)->GetAsDictionary(&media_dict);
927 std::string audio_setting;
928 std::string video_setting;
929 media_dict->GetString(kOrigin, &origin);
930 media_dict->GetString(kSetting, &audio_setting);
931 media_dict->GetString(kVideoSetting, &video_setting);
932 media_settings_.exceptions.push_back(MediaException(
933 ContentSettingsPattern::FromString(origin),
934 ContentSettingFromString(audio_setting),
935 ContentSettingFromString(video_setting)));
937 PepperFlashContentSettingsUtils::SortMediaExceptions(
938 &media_settings_.exceptions);
939 media_settings_.exceptions_initialized = true;
940 UpdateFlashMediaLinksVisibility();
942 StringValue type_string(
943 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM));
944 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
945 type_string, media_exceptions);
947 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
950 void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
951 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebMIDI)) {
952 web_ui()->CallJavascriptFunction(
953 "ContentSettings.showExperimentalWebMIDISettings",
954 base::FundamentalValue(true));
957 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
958 UpdateExceptionsViewFromHostContentSettingsMap(
959 CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
962 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
963 ContentSettingsType type) {
964 ListValue exceptions;
965 GetExceptionsFromHostContentSettingsMap(
966 GetContentSettingsMap(), type, &exceptions);
967 StringValue type_string(ContentSettingsTypeToGroupName(type));
968 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
971 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
973 // TODO(koz): The default for fullscreen is always 'ask'.
974 // http://crbug.com/104683
975 if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN)
978 #if defined(OS_CHROMEOS)
979 // Also the default for protected contents is managed in another place.
980 if (type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER)
984 // The default may also have changed (we won't get a separate notification).
985 // If it hasn't changed, this call will be harmless.
986 UpdateSettingDefaultFromModel(type);
989 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
990 ContentSettingsType type) {
991 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
992 if (!otr_settings_map)
994 ListValue exceptions;
995 GetExceptionsFromHostContentSettingsMap(otr_settings_map, type, &exceptions);
996 StringValue type_string(ContentSettingsTypeToGroupName(type));
997 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
998 type_string, exceptions);
1001 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
1002 const HostContentSettingsMap* map,
1003 ContentSettingsType type,
1004 ListValue* exceptions) {
1005 ContentSettingsForOneType entries;
1006 map->GetSettingsForOneType(type, std::string(), &entries);
1007 // Group settings by primary_pattern.
1008 AllPatternsSettings all_patterns_settings;
1009 for (ContentSettingsForOneType::iterator i = entries.begin();
1010 i != entries.end(); ++i) {
1011 // Don't add default settings.
1012 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
1013 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
1014 i->source != kPreferencesSource) {
1018 // Off-the-record HostContentSettingsMap contains incognito content settings
1019 // as well as normal content settings. Here, we use the incongnito settings
1021 if (map->is_off_the_record() && !i->incognito)
1024 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
1025 [i->secondary_pattern] = i->setting;
1028 // Keep the exceptions sorted by provider so they will be displayed in
1029 // precedence order.
1030 std::vector<std::vector<Value*> > all_provider_exceptions;
1031 all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);
1033 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
1034 i != all_patterns_settings.end();
1036 const ContentSettingsPattern& primary_pattern = i->first.first;
1037 const OnePatternSettings& one_settings = i->second;
1039 // The "parent" entry either has an identical primary and secondary pattern,
1040 // or has a wildcard secondary. The two cases are indistinguishable in the
1042 OnePatternSettings::const_iterator parent =
1043 one_settings.find(primary_pattern);
1044 if (parent == one_settings.end())
1045 parent = one_settings.find(ContentSettingsPattern::Wildcard());
1047 const std::string& source = i->first.second;
1048 std::vector<Value*>* this_provider_exceptions = &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 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 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 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 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(UserMetricsAction(
1269 "Options_DefaultMultipleAutomaticDownloadsSettingChanged"));
1271 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
1272 content::RecordAction(
1273 UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
1280 void ContentSettingsHandler::RemoveException(const 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 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 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 } // namespace options