Disable TabDragController tests that fail with a real compositor.
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / content_settings_handler.cc
blob76b0d4e50c321144a5772902ee181dc7af47d89d
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"
7 #include <map>
8 #include <vector>
10 #include "base/bind.h"
11 #include "base/bind_helpers.h"
12 #include "base/command_line.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/content_settings/content_settings_details.h"
19 #include "chrome/browser/content_settings/content_settings_utils.h"
20 #include "chrome/browser/content_settings/host_content_settings_map.h"
21 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
22 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
23 #include "chrome/browser/extensions/extension_service.h"
24 #include "chrome/browser/extensions/extension_special_storage_policy.h"
25 #include "chrome/browser/google/google_util.h"
26 #include "chrome/browser/notifications/desktop_notification_service.h"
27 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
28 #include "chrome/browser/profiles/profile.h"
29 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/common/chrome_switches.h"
31 #include "chrome/common/content_settings.h"
32 #include "chrome/common/content_settings_pattern.h"
33 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/notification_source.h"
38 #include "content/public/browser/notification_types.h"
39 #include "content/public/browser/user_metrics.h"
40 #include "content/public/browser/web_ui.h"
41 #include "content/public/common/content_switches.h"
42 #include "extensions/common/extension_set.h"
43 #include "extensions/common/permissions/api_permission.h"
44 #include "grit/generated_resources.h"
45 #include "grit/locale_settings.h"
46 #include "ui/base/l10n/l10n_util.h"
48 #if defined(OS_CHROMEOS)
49 #include "chrome/browser/chromeos/login/user_manager.h"
50 #endif
52 using base::UserMetricsAction;
53 using extensions::APIPermission;
55 namespace {
57 struct ContentSettingsTypeNameEntry {
58 ContentSettingsType type;
59 const char* name;
62 // Maps from a secondary pattern to a setting.
63 typedef std::map<ContentSettingsPattern, ContentSetting>
64 OnePatternSettings;
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>,
68 OnePatternSettings>
69 AllPatternsSettings;
71 // The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
72 // extensions which should have their extent displayed.
73 typedef bool (*AppFilter)(const extensions::Extension& app, Profile* profile);
75 const char kExceptionsLearnMoreUrl[] =
76 "https://support.google.com/chrome/?p=settings_manage_exceptions";
78 const char* kSetting = "setting";
79 const char* kOrigin = "origin";
80 const char* kSource = "source";
81 const char* kAppName = "appName";
82 const char* kAppId = "appId";
83 const char* kEmbeddingOrigin = "embeddingOrigin";
84 const char* kPreferencesSource = "preference";
85 const char* kVideoSetting = "video";
87 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
88 {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
89 {CONTENT_SETTINGS_TYPE_IMAGES, "images"},
90 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"},
91 {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"},
92 {CONTENT_SETTINGS_TYPE_POPUPS, "popups"},
93 {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"},
94 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"},
95 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"},
96 {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"},
97 {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"},
98 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, "register-protocol-handler"},
99 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, "media-stream"},
100 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, "media-stream-mic"},
101 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, "media-stream-camera"},
102 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, "ppapi-broker"},
103 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, "multiple-automatic-downloads"},
104 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, "midi-sysex"},
105 #if defined(OS_CHROMEOS)
106 {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, "protectedContent"},
107 #endif
110 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
111 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
112 if (name == kContentSettingsTypeGroupNames[i].name)
113 return kContentSettingsTypeGroupNames[i].type;
116 NOTREACHED() << name << " is not a recognized content settings type.";
117 return CONTENT_SETTINGS_TYPE_DEFAULT;
120 std::string ContentSettingToString(ContentSetting setting) {
121 switch (setting) {
122 case CONTENT_SETTING_ALLOW:
123 return "allow";
124 case CONTENT_SETTING_ASK:
125 return "ask";
126 case CONTENT_SETTING_BLOCK:
127 return "block";
128 case CONTENT_SETTING_SESSION_ONLY:
129 return "session";
130 case CONTENT_SETTING_DEFAULT:
131 return "default";
132 case CONTENT_SETTING_NUM_SETTINGS:
133 NOTREACHED();
136 return std::string();
139 ContentSetting ContentSettingFromString(const std::string& name) {
140 if (name == "allow")
141 return CONTENT_SETTING_ALLOW;
142 if (name == "ask")
143 return CONTENT_SETTING_ASK;
144 if (name == "block")
145 return CONTENT_SETTING_BLOCK;
146 if (name == "session")
147 return CONTENT_SETTING_SESSION_ONLY;
149 NOTREACHED() << name << " is not a recognized content setting.";
150 return CONTENT_SETTING_DEFAULT;
153 // Create a DictionaryValue* that will act as a data source for a single row
154 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
155 // Ownership of the pointer is passed to the caller.
156 base::DictionaryValue* GetExceptionForPage(
157 const ContentSettingsPattern& pattern,
158 const ContentSettingsPattern& secondary_pattern,
159 const ContentSetting& setting,
160 const std::string& provider_name) {
161 base::DictionaryValue* exception = new base::DictionaryValue();
162 exception->SetString(kOrigin, pattern.ToString());
163 exception->SetString(kEmbeddingOrigin,
164 secondary_pattern == ContentSettingsPattern::Wildcard()
165 ? std::string()
166 : secondary_pattern.ToString());
167 exception->SetString(kSetting, ContentSettingToString(setting));
168 exception->SetString(kSource, provider_name);
169 return exception;
172 // Create a DictionaryValue* that will act as a data source for a single row
173 // in the Geolocation exceptions table. Ownership of the pointer is passed to
174 // the caller.
175 base::DictionaryValue* GetGeolocationExceptionForPage(
176 const ContentSettingsPattern& origin,
177 const ContentSettingsPattern& embedding_origin,
178 ContentSetting setting) {
179 base::DictionaryValue* exception = new base::DictionaryValue();
180 exception->SetString(kSetting, ContentSettingToString(setting));
181 exception->SetString(kOrigin, origin.ToString());
182 exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
183 return exception;
186 // Create a DictionaryValue* that will act as a data source for a single row
187 // in the desktop notifications exceptions table. Ownership of the pointer is
188 // passed to the caller.
189 base::DictionaryValue* GetNotificationExceptionForPage(
190 const ContentSettingsPattern& pattern,
191 ContentSetting setting,
192 const std::string& provider_name) {
193 base::DictionaryValue* exception = new base::DictionaryValue();
194 exception->SetString(kSetting, ContentSettingToString(setting));
195 exception->SetString(kOrigin, pattern.ToString());
196 exception->SetString(kSource, provider_name);
197 return exception;
200 // Returns true whenever the |extension| is hosted and has |permission|.
201 // Must have the AppFilter signature.
202 template <APIPermission::ID permission>
203 bool HostedAppHasPermission(
204 const extensions::Extension& extension, Profile* /*profile*/) {
205 return extension.is_hosted_app() && extension.HasAPIPermission(permission);
208 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
209 // the web extent of a hosted |app|.
210 void AddExceptionForHostedApp(const std::string& url_pattern,
211 const extensions::Extension& app, base::ListValue* exceptions) {
212 base::DictionaryValue* exception = new base::DictionaryValue();
213 exception->SetString(kSetting, ContentSettingToString(CONTENT_SETTING_ALLOW));
214 exception->SetString(kOrigin, url_pattern);
215 exception->SetString(kEmbeddingOrigin, url_pattern);
216 exception->SetString(kSource, "HostedApp");
217 exception->SetString(kAppName, app.name());
218 exception->SetString(kAppId, app.id());
219 exceptions->Append(exception);
222 // Asks the |profile| for hosted apps which have the |permission| set, and
223 // adds their web extent and launch URL to the |exceptions| list.
224 void AddExceptionsGrantedByHostedApps(
225 Profile* profile, AppFilter app_filter, base::ListValue* exceptions) {
226 const ExtensionService* extension_service = profile->GetExtensionService();
227 // After ExtensionSystem::Init has been called at the browser's start,
228 // GetExtensionService() should not return NULL, so this is safe:
229 const extensions::ExtensionSet* extensions = extension_service->extensions();
231 for (extensions::ExtensionSet::const_iterator extension = extensions->begin();
232 extension != extensions->end(); ++extension) {
233 if (!app_filter(*extension->get(), profile))
234 continue;
236 extensions::URLPatternSet web_extent = (*extension)->web_extent();
237 // Add patterns from web extent.
238 for (extensions::URLPatternSet::const_iterator pattern = web_extent.begin();
239 pattern != web_extent.end(); ++pattern) {
240 std::string url_pattern = pattern->GetAsString();
241 AddExceptionForHostedApp(url_pattern, *extension->get(), exceptions);
243 // Retrieve the launch URL.
244 GURL launch_url =
245 extensions::AppLaunchInfo::GetLaunchWebURL(extension->get());
246 // Skip adding the launch URL if it is part of the web extent.
247 if (web_extent.MatchesURL(launch_url))
248 continue;
249 AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions);
253 } // namespace
255 namespace options {
257 ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo()
258 : flash_default_setting(CONTENT_SETTING_DEFAULT),
259 flash_settings_initialized(false),
260 last_flash_refresh_request_id(0),
261 show_flash_default_link(false),
262 show_flash_exceptions_link(false),
263 default_setting(CONTENT_SETTING_DEFAULT),
264 policy_disable_audio(false),
265 policy_disable_video(false),
266 default_setting_initialized(false),
267 exceptions_initialized(false) {
270 ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
273 ContentSettingsHandler::ContentSettingsHandler() {
276 ContentSettingsHandler::~ContentSettingsHandler() {
279 void ContentSettingsHandler::GetLocalizedValues(
280 base::DictionaryValue* localized_strings) {
281 DCHECK(localized_strings);
283 static OptionsStringResource resources[] = {
284 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
285 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
286 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
287 { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
288 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
289 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
290 { "manageExceptions", IDS_EXCEPTIONS_MANAGE },
291 { "manage_handlers", IDS_HANDLERS_MANAGE },
292 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
293 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
294 { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST },
295 // Cookies filter.
296 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL },
297 { "cookies_header", IDS_COOKIES_HEADER },
298 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO },
299 { "cookies_block", IDS_COOKIES_BLOCK_RADIO },
300 { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO },
301 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
302 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX },
303 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX },
304 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
305 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
306 { "flash_storage_url", IDS_FLASH_STORAGE_URL },
307 #if defined(ENABLE_GOOGLE_NOW)
308 { "googleGeolocationAccessEnable",
309 IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX },
310 #endif
311 // Image filter.
312 { "images_tab_label", IDS_IMAGES_TAB_LABEL },
313 { "images_header", IDS_IMAGES_HEADER },
314 { "images_allow", IDS_IMAGES_LOAD_RADIO },
315 { "images_block", IDS_IMAGES_NOLOAD_RADIO },
316 // JavaScript filter.
317 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL },
318 { "javascript_header", IDS_JAVASCRIPT_HEADER },
319 { "javascript_allow", IDS_JS_ALLOW_RADIO },
320 { "javascript_block", IDS_JS_DONOTALLOW_RADIO },
321 // Plug-ins filter.
322 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL },
323 { "plugins_header", IDS_PLUGIN_HEADER },
324 { "plugins_ask", IDS_PLUGIN_ASK_RADIO },
325 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO },
326 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO },
327 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE },
328 // Pop-ups filter.
329 { "popups_tab_label", IDS_POPUP_TAB_LABEL },
330 { "popups_header", IDS_POPUP_HEADER },
331 { "popups_allow", IDS_POPUP_ALLOW_RADIO },
332 { "popups_block", IDS_POPUP_BLOCK_RADIO },
333 // Location filter.
334 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL },
335 { "location_header", IDS_GEOLOCATION_HEADER },
336 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO },
337 { "location_ask", IDS_GEOLOCATION_ASK_RADIO },
338 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO },
339 { "set_by", IDS_GEOLOCATION_SET_BY_HOVER },
340 // Notifications filter.
341 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL },
342 { "notifications_header", IDS_NOTIFICATIONS_HEADER },
343 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO },
344 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO },
345 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO },
346 // Fullscreen filter.
347 { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL },
348 { "fullscreen_header", IDS_FULLSCREEN_HEADER },
349 // Mouse Lock filter.
350 { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL },
351 { "mouselock_header", IDS_MOUSE_LOCK_HEADER },
352 { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO },
353 { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO },
354 { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO },
355 #if defined(OS_CHROMEOS) || defined(OS_WIN)
356 // Protected Content filter
357 { "protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL },
358 { "protectedContentInfo", IDS_PROTECTED_CONTENT_INFO },
359 { "protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE },
360 { "protectedContent_header", IDS_PROTECTED_CONTENT_HEADER },
361 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
362 // Media stream capture device filter.
363 { "mediaStreamTabLabel", IDS_MEDIA_STREAM_TAB_LABEL },
364 { "media-stream_header", IDS_MEDIA_STREAM_HEADER },
365 { "mediaStreamAsk", IDS_MEDIA_STREAM_ASK_RADIO },
366 { "mediaStreamBlock", IDS_MEDIA_STREAM_BLOCK_RADIO },
367 { "mediaStreamAudioAsk", IDS_MEDIA_STREAM_ASK_AUDIO_ONLY_RADIO },
368 { "mediaStreamAudioBlock", IDS_MEDIA_STREAM_BLOCK_AUDIO_ONLY_RADIO },
369 { "mediaStreamVideoAsk", IDS_MEDIA_STREAM_ASK_VIDEO_ONLY_RADIO },
370 { "mediaStreamVideoBlock", IDS_MEDIA_STREAM_BLOCK_VIDEO_ONLY_RADIO },
371 { "mediaStreamBubbleAudio", IDS_MEDIA_STREAM_AUDIO_MANAGED },
372 { "mediaStreamBubbleVideo", IDS_MEDIA_STREAM_VIDEO_MANAGED },
373 { "mediaAudioExceptionHeader", IDS_MEDIA_AUDIO_EXCEPTION_HEADER },
374 { "mediaVideoExceptionHeader", IDS_MEDIA_VIDEO_EXCEPTION_HEADER },
375 { "mediaPepperFlashDefaultDivergedLabel",
376 IDS_MEDIA_PEPPER_FLASH_DEFAULT_DIVERGED_LABEL },
377 { "mediaPepperFlashExceptionsDivergedLabel",
378 IDS_MEDIA_PEPPER_FLASH_EXCEPTIONS_DIVERGED_LABEL },
379 { "mediaPepperFlashChangeLink", IDS_MEDIA_PEPPER_FLASH_CHANGE_LINK },
380 { "mediaPepperFlashGlobalPrivacyURL", IDS_FLASH_GLOBAL_PRIVACY_URL },
381 { "mediaPepperFlashWebsitePrivacyURL", IDS_FLASH_WEBSITE_PRIVACY_URL },
382 // PPAPI broker filter.
383 // TODO(bauerb): Use IDS_PPAPI_BROKER_HEADER.
384 { "ppapi-broker_header", IDS_PPAPI_BROKER_TAB_LABEL },
385 { "ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL },
386 { "ppapi_broker_allow", IDS_PPAPI_BROKER_ALLOW_RADIO },
387 { "ppapi_broker_ask", IDS_PPAPI_BROKER_ASK_RADIO },
388 { "ppapi_broker_block", IDS_PPAPI_BROKER_BLOCK_RADIO },
389 // Multiple automatic downloads
390 { "multiple-automatic-downloads_header",
391 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL },
392 { "multiple-automatic-downloads_allow",
393 IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO },
394 { "multiple-automatic-downloads_ask",
395 IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO },
396 { "multiple-automatic-downloads_block",
397 IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO },
398 // MIDI system exclusive messages
399 { "midi-sysex_header", IDS_MIDI_SYSEX_TAB_LABEL },
400 { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO },
401 { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO },
402 { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO },
405 RegisterStrings(localized_strings, resources, arraysize(resources));
406 RegisterTitle(localized_strings, "contentSettingsPage",
407 IDS_CONTENT_SETTINGS_TITLE);
409 // Register titles for each of the individual settings whose exception
410 // dialogs will be processed by |ContentSettingsHandler|.
411 RegisterTitle(localized_strings, "cookies",
412 IDS_COOKIES_TAB_LABEL);
413 RegisterTitle(localized_strings, "images",
414 IDS_IMAGES_TAB_LABEL);
415 RegisterTitle(localized_strings, "javascript",
416 IDS_JAVASCRIPT_TAB_LABEL);
417 RegisterTitle(localized_strings, "plugins",
418 IDS_PLUGIN_TAB_LABEL);
419 RegisterTitle(localized_strings, "popups",
420 IDS_POPUP_TAB_LABEL);
421 RegisterTitle(localized_strings, "location",
422 IDS_GEOLOCATION_TAB_LABEL);
423 RegisterTitle(localized_strings, "notifications",
424 IDS_NOTIFICATIONS_TAB_LABEL);
425 RegisterTitle(localized_strings, "fullscreen",
426 IDS_FULLSCREEN_TAB_LABEL);
427 RegisterTitle(localized_strings, "mouselock",
428 IDS_MOUSE_LOCK_TAB_LABEL);
429 #if defined(OS_CHROMEOS)
430 RegisterTitle(localized_strings, "protectedContent",
431 IDS_PROTECTED_CONTENT_TAB_LABEL);
432 #endif
433 RegisterTitle(localized_strings, "media-stream",
434 IDS_MEDIA_STREAM_TAB_LABEL);
435 RegisterTitle(localized_strings, "ppapi-broker",
436 IDS_PPAPI_BROKER_TAB_LABEL);
437 RegisterTitle(localized_strings, "multiple-automatic-downloads",
438 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
439 RegisterTitle(localized_strings, "midi-sysex",
440 IDS_MIDI_SYSEX_TAB_LABEL);
442 localized_strings->SetBoolean("newContentSettings",
443 CommandLine::ForCurrentProcess()->HasSwitch(switches::kContentSettings2));
444 localized_strings->SetString(
445 "exceptionsLearnMoreUrl",
446 google_util::StringAppendGoogleLocaleParam(
447 kExceptionsLearnMoreUrl));
450 void ContentSettingsHandler::InitializeHandler() {
451 notification_registrar_.Add(
452 this, chrome::NOTIFICATION_PROFILE_CREATED,
453 content::NotificationService::AllSources());
454 notification_registrar_.Add(
455 this, chrome::NOTIFICATION_PROFILE_DESTROYED,
456 content::NotificationService::AllSources());
458 notification_registrar_.Add(
459 this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
460 content::NotificationService::AllSources());
461 notification_registrar_.Add(
462 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
463 content::NotificationService::AllSources());
464 Profile* profile = Profile::FromWebUI(web_ui());
465 notification_registrar_.Add(
466 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
467 content::Source<Profile>(profile));
469 PrefService* prefs = profile->GetPrefs();
470 pref_change_registrar_.Init(prefs);
471 pref_change_registrar_.Add(
472 prefs::kPepperFlashSettingsEnabled,
473 base::Bind(&ContentSettingsHandler::OnPepperFlashPrefChanged,
474 base::Unretained(this)));
475 pref_change_registrar_.Add(
476 prefs::kAudioCaptureAllowed,
477 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
478 base::Unretained(this)));
479 pref_change_registrar_.Add(
480 prefs::kVideoCaptureAllowed,
481 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
482 base::Unretained(this)));
483 pref_change_registrar_.Add(
484 prefs::kEnableDRM,
485 base::Bind(
486 &ContentSettingsHandler::UpdateProtectedContentExceptionsButton,
487 base::Unretained(this)));
489 flash_settings_manager_.reset(new PepperFlashSettingsManager(this, profile));
492 void ContentSettingsHandler::InitializePage() {
493 media_settings_ = MediaSettingsInfo();
494 RefreshFlashMediaSettings();
496 UpdateHandlersEnabledRadios();
497 UpdateAllExceptionsViewsFromModel();
498 UpdateProtectedContentExceptionsButton();
501 void ContentSettingsHandler::Observe(
502 int type,
503 const content::NotificationSource& source,
504 const content::NotificationDetails& details) {
505 switch (type) {
506 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
507 if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) {
508 web_ui()->CallJavascriptFunction(
509 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
511 break;
514 case chrome::NOTIFICATION_PROFILE_CREATED: {
515 if (content::Source<Profile>(source).ptr()->IsOffTheRecord())
516 UpdateAllOTRExceptionsViewsFromModel();
517 break;
520 case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED: {
521 // Filter out notifications from other profiles.
522 HostContentSettingsMap* map =
523 content::Source<HostContentSettingsMap>(source).ptr();
524 if (map != GetContentSettingsMap() &&
525 map != GetOTRContentSettingsMap())
526 break;
528 const ContentSettingsDetails* settings_details =
529 content::Details<const ContentSettingsDetails>(details).ptr();
531 // TODO(estade): we pretend update_all() is always true.
532 if (settings_details->update_all_types())
533 UpdateAllExceptionsViewsFromModel();
534 else
535 UpdateExceptionsViewFromModel(settings_details->type());
536 break;
539 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: {
540 UpdateNotificationExceptionsView();
541 break;
544 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: {
545 UpdateHandlersEnabledRadios();
546 break;
549 default:
550 OptionsPageUIHandler::Observe(type, source, details);
554 void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
555 uint32 request_id,
556 bool success,
557 PP_Flash_BrowserOperations_Permission default_permission,
558 const ppapi::FlashSiteSettings& sites) {
559 if (success && request_id == media_settings_.last_flash_refresh_request_id) {
560 media_settings_.flash_settings_initialized = true;
561 media_settings_.flash_default_setting =
562 PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
563 default_permission);
564 PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
565 sites, &media_settings_.flash_exceptions);
566 PepperFlashContentSettingsUtils::SortMediaExceptions(
567 &media_settings_.flash_exceptions);
569 UpdateFlashMediaLinksVisibility();
573 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
574 ContentSettingsType type) {
575 base::DictionaryValue filter_settings;
576 std::string provider_id;
577 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
578 GetSettingDefaultFromModel(type, &provider_id));
579 filter_settings.SetString(
580 ContentSettingsTypeToGroupName(type) + ".managedBy", provider_id);
582 web_ui()->CallJavascriptFunction(
583 "ContentSettings.setContentFilterSettingsValue", filter_settings);
586 void ContentSettingsHandler::UpdateMediaSettingsView() {
587 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
588 bool audio_disabled = !prefs->GetBoolean(prefs::kAudioCaptureAllowed) &&
589 prefs->IsManagedPreference(prefs::kAudioCaptureAllowed);
590 bool video_disabled = !prefs->GetBoolean(prefs::kVideoCaptureAllowed) &&
591 prefs->IsManagedPreference(prefs::kVideoCaptureAllowed);
593 media_settings_.policy_disable_audio = audio_disabled;
594 media_settings_.policy_disable_video = video_disabled;
595 media_settings_.default_setting =
596 GetContentSettingsMap()->GetDefaultContentSetting(
597 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
598 media_settings_.default_setting_initialized = true;
599 UpdateFlashMediaLinksVisibility();
601 base::DictionaryValue media_ui_settings;
602 media_ui_settings.SetBoolean("cameraDisabled", video_disabled);
603 media_ui_settings.SetBoolean("micDisabled", audio_disabled);
605 // In case only video is enabled change the text appropriately.
606 if (audio_disabled && !video_disabled) {
607 media_ui_settings.SetString("askText", "mediaStreamVideoAsk");
608 media_ui_settings.SetString("blockText", "mediaStreamVideoBlock");
609 media_ui_settings.SetBoolean("showBubble", true);
610 media_ui_settings.SetString("bubbleText", "mediaStreamBubbleAudio");
612 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
613 media_ui_settings);
614 return;
617 // In case only audio is enabled change the text appropriately.
618 if (video_disabled && !audio_disabled) {
619 base::DictionaryValue media_ui_settings;
620 media_ui_settings.SetString("askText", "mediaStreamAudioAsk");
621 media_ui_settings.SetString("blockText", "mediaStreamAudioBlock");
622 media_ui_settings.SetBoolean("showBubble", true);
623 media_ui_settings.SetString("bubbleText", "mediaStreamBubbleVideo");
625 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
626 media_ui_settings);
627 return;
630 if (audio_disabled && video_disabled) {
631 // Fake policy controlled default because the user can not change anything
632 // until both audio and video are blocked.
633 base::DictionaryValue filter_settings;
634 std::string group_name =
635 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
636 filter_settings.SetString(group_name + ".value",
637 ContentSettingToString(CONTENT_SETTING_BLOCK));
638 filter_settings.SetString(group_name + ".managedBy", "policy");
639 web_ui()->CallJavascriptFunction(
640 "ContentSettings.setContentFilterSettingsValue", filter_settings);
643 media_ui_settings.SetString("askText", "mediaStreamAsk");
644 media_ui_settings.SetString("blockText", "mediaStreamBlock");
645 media_ui_settings.SetBoolean("showBubble", false);
646 media_ui_settings.SetString("bubbleText", std::string());
648 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
649 media_ui_settings);
652 std::string ContentSettingsHandler::GetSettingDefaultFromModel(
653 ContentSettingsType type, std::string* provider_id) {
654 Profile* profile = Profile::FromWebUI(web_ui());
655 ContentSetting default_setting;
656 if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
657 default_setting =
658 DesktopNotificationServiceFactory::GetForProfile(profile)->
659 GetDefaultContentSetting(provider_id);
660 } else {
661 default_setting =
662 profile->GetHostContentSettingsMap()->
663 GetDefaultContentSetting(type, provider_id);
666 return ContentSettingToString(default_setting);
669 void ContentSettingsHandler::UpdateHandlersEnabledRadios() {
670 base::FundamentalValue handlers_enabled(
671 GetProtocolHandlerRegistry()->enabled());
673 web_ui()->CallJavascriptFunction(
674 "ContentSettings.updateHandlersEnabledRadios",
675 handlers_enabled);
678 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
679 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
680 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
681 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
685 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
686 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
687 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
688 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
692 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
693 ContentSettingsType type) {
694 switch (type) {
695 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
696 UpdateGeolocationExceptionsView();
697 break;
698 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
699 UpdateNotificationExceptionsView();
700 break;
701 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
702 UpdateMediaSettingsView();
703 break;
704 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
705 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
706 UpdateMediaExceptionsView();
707 break;
708 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
709 // We don't yet support exceptions for mixed scripting.
710 break;
711 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
712 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
713 // is supposed to be set by policy only. Hence there is no user facing UI
714 // for this content type and we skip it here.
715 break;
716 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
717 // The RPH settings are retrieved separately.
718 break;
719 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
720 UpdateMIDISysExExceptionsView();
721 break;
722 #if defined(OS_WIN)
723 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
724 break;
725 #endif
726 default:
727 UpdateExceptionsViewFromHostContentSettingsMap(type);
728 break;
732 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
733 ContentSettingsType type) {
734 switch (type) {
735 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
736 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
737 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
738 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
739 #if defined(OS_WIN)
740 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
741 #endif
742 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
743 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
744 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
745 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
746 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
747 break;
748 default:
749 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
750 break;
754 // TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
755 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
756 Profile* profile = Profile::FromWebUI(web_ui());
757 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
759 ContentSettingsForOneType all_settings;
760 map->GetSettingsForOneType(
761 CONTENT_SETTINGS_TYPE_GEOLOCATION,
762 std::string(),
763 &all_settings);
765 // Group geolocation settings by primary_pattern.
766 AllPatternsSettings all_patterns_settings;
767 for (ContentSettingsForOneType::iterator i = all_settings.begin();
768 i != all_settings.end(); ++i) {
769 // Don't add default settings.
770 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
771 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
772 i->source != kPreferencesSource) {
773 continue;
775 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
776 [i->secondary_pattern] = i->setting;
779 base::ListValue exceptions;
780 AddExceptionsGrantedByHostedApps(
781 profile,
782 HostedAppHasPermission<APIPermission::kGeolocation>,
783 &exceptions);
785 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
786 i != all_patterns_settings.end(); ++i) {
787 const ContentSettingsPattern& primary_pattern = i->first.first;
788 const OnePatternSettings& one_settings = i->second;
790 OnePatternSettings::const_iterator parent =
791 one_settings.find(primary_pattern);
793 // Add the "parent" entry for the non-embedded setting.
794 ContentSetting parent_setting =
795 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
796 exceptions.Append(GetGeolocationExceptionForPage(primary_pattern,
797 primary_pattern,
798 parent_setting));
800 // Add the "children" for any embedded settings.
801 for (OnePatternSettings::const_iterator j = one_settings.begin();
802 j != one_settings.end();
803 ++j) {
804 // Skip the non-embedded setting which we already added above.
805 if (j == parent)
806 continue;
808 exceptions.Append(GetGeolocationExceptionForPage(
809 primary_pattern, j->first, j->second));
813 base::StringValue type_string(
814 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
815 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
816 type_string, exceptions);
818 // This is mainly here to keep this function ideologically parallel to
819 // UpdateExceptionsViewFromHostContentSettingsMap().
820 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
823 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
824 Profile* profile = Profile::FromWebUI(web_ui());
825 DesktopNotificationService* service =
826 DesktopNotificationServiceFactory::GetForProfile(profile);
828 ContentSettingsForOneType settings;
829 service->GetNotificationsSettings(&settings);
831 base::ListValue exceptions;
832 AddExceptionsGrantedByHostedApps(profile,
833 HostedAppHasPermission<APIPermission::kNotification>,
834 &exceptions);
836 for (ContentSettingsForOneType::const_iterator i =
837 settings.begin();
838 i != settings.end();
839 ++i) {
840 // Don't add default settings.
841 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
842 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
843 i->source != kPreferencesSource) {
844 continue;
847 exceptions.Append(
848 GetNotificationExceptionForPage(i->primary_pattern, i->setting,
849 i->source));
852 base::StringValue type_string(
853 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
854 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
855 type_string, exceptions);
857 // This is mainly here to keep this function ideologically parallel to
858 // UpdateExceptionsViewFromHostContentSettingsMap().
859 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
862 void ContentSettingsHandler::UpdateMediaExceptionsView() {
863 base::ListValue media_exceptions;
864 GetExceptionsFromHostContentSettingsMap(
865 GetContentSettingsMap(),
866 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
867 &media_exceptions);
869 base::ListValue video_exceptions;
870 GetExceptionsFromHostContentSettingsMap(
871 GetContentSettingsMap(),
872 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
873 &video_exceptions);
875 // Merge the |video_exceptions| list to |media_exceptions| list.
876 std::map<std::string, base::DictionaryValue*> entries_map;
877 for (base::ListValue::const_iterator media_entry(media_exceptions.begin());
878 media_entry != media_exceptions.end(); ++media_entry) {
879 base::DictionaryValue* media_dict = NULL;
880 if (!(*media_entry)->GetAsDictionary(&media_dict))
881 NOTREACHED();
883 media_dict->SetString(kVideoSetting,
884 ContentSettingToString(CONTENT_SETTING_ASK));
886 std::string media_origin;
887 media_dict->GetString(kOrigin, &media_origin);
888 entries_map[media_origin] = media_dict;
891 for (base::ListValue::iterator video_entry = video_exceptions.begin();
892 video_entry != video_exceptions.end(); ++video_entry) {
893 base::DictionaryValue* video_dict = NULL;
894 if (!(*video_entry)->GetAsDictionary(&video_dict))
895 NOTREACHED();
897 std::string video_origin;
898 std::string video_setting;
899 video_dict->GetString(kOrigin, &video_origin);
900 video_dict->GetString(kSetting, &video_setting);
902 std::map<std::string, base::DictionaryValue*>::iterator iter =
903 entries_map.find(video_origin);
904 if (iter == entries_map.end()) {
905 base::DictionaryValue* exception = new base::DictionaryValue();
906 exception->SetString(kOrigin, video_origin);
907 exception->SetString(kSetting,
908 ContentSettingToString(CONTENT_SETTING_ASK));
909 exception->SetString(kVideoSetting, video_setting);
910 exception->SetString(kSource, kPreferencesSource);
912 // Append the new entry to the list and map.
913 media_exceptions.Append(exception);
914 entries_map[video_origin] = exception;
915 } else {
916 // Modify the existing entry.
917 iter->second->SetString(kVideoSetting, video_setting);
921 media_settings_.exceptions.clear();
922 for (base::ListValue::const_iterator media_entry = media_exceptions.begin();
923 media_entry != media_exceptions.end(); ++media_entry) {
924 base::DictionaryValue* media_dict = NULL;
925 bool result = (*media_entry)->GetAsDictionary(&media_dict);
926 DCHECK(result);
928 std::string origin;
929 std::string audio_setting;
930 std::string video_setting;
931 media_dict->GetString(kOrigin, &origin);
932 media_dict->GetString(kSetting, &audio_setting);
933 media_dict->GetString(kVideoSetting, &video_setting);
934 media_settings_.exceptions.push_back(MediaException(
935 ContentSettingsPattern::FromString(origin),
936 ContentSettingFromString(audio_setting),
937 ContentSettingFromString(video_setting)));
939 PepperFlashContentSettingsUtils::SortMediaExceptions(
940 &media_settings_.exceptions);
941 media_settings_.exceptions_initialized = true;
942 UpdateFlashMediaLinksVisibility();
944 base::StringValue type_string(
945 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM));
946 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
947 type_string, media_exceptions);
949 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
952 void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
953 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebMIDI)) {
954 web_ui()->CallJavascriptFunction(
955 "ContentSettings.showExperimentalWebMIDISettings",
956 base::FundamentalValue(true));
959 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
960 UpdateExceptionsViewFromHostContentSettingsMap(
961 CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
964 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
965 ContentSettingsType type) {
966 base::ListValue exceptions;
967 GetExceptionsFromHostContentSettingsMap(
968 GetContentSettingsMap(), type, &exceptions);
969 base::StringValue type_string(ContentSettingsTypeToGroupName(type));
970 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
971 exceptions);
973 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
975 // TODO(koz): The default for fullscreen is always 'ask'.
976 // http://crbug.com/104683
977 if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN)
978 return;
980 #if defined(OS_CHROMEOS)
981 // Also the default for protected contents is managed in another place.
982 if (type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER)
983 return;
984 #endif
986 // The default may also have changed (we won't get a separate notification).
987 // If it hasn't changed, this call will be harmless.
988 UpdateSettingDefaultFromModel(type);
991 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
992 ContentSettingsType type) {
993 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
994 if (!otr_settings_map)
995 return;
996 base::ListValue exceptions;
997 GetExceptionsFromHostContentSettingsMap(otr_settings_map, type, &exceptions);
998 base::StringValue type_string(ContentSettingsTypeToGroupName(type));
999 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
1000 type_string, exceptions);
1003 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
1004 const HostContentSettingsMap* map,
1005 ContentSettingsType type,
1006 base::ListValue* exceptions) {
1007 ContentSettingsForOneType entries;
1008 map->GetSettingsForOneType(type, std::string(), &entries);
1009 // Group settings by primary_pattern.
1010 AllPatternsSettings all_patterns_settings;
1011 for (ContentSettingsForOneType::iterator i = entries.begin();
1012 i != entries.end(); ++i) {
1013 // Don't add default settings.
1014 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
1015 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
1016 i->source != kPreferencesSource) {
1017 continue;
1020 // Off-the-record HostContentSettingsMap contains incognito content settings
1021 // as well as normal content settings. Here, we use the incongnito settings
1022 // only.
1023 if (map->is_off_the_record() && !i->incognito)
1024 continue;
1026 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
1027 [i->secondary_pattern] = i->setting;
1030 // Keep the exceptions sorted by provider so they will be displayed in
1031 // precedence order.
1032 std::vector<std::vector<base::Value*> > all_provider_exceptions;
1033 all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);
1035 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
1036 i != all_patterns_settings.end();
1037 ++i) {
1038 const ContentSettingsPattern& primary_pattern = i->first.first;
1039 const OnePatternSettings& one_settings = i->second;
1041 // The "parent" entry either has an identical primary and secondary pattern,
1042 // or has a wildcard secondary. The two cases are indistinguishable in the
1043 // UI.
1044 OnePatternSettings::const_iterator parent =
1045 one_settings.find(primary_pattern);
1046 if (parent == one_settings.end())
1047 parent = one_settings.find(ContentSettingsPattern::Wildcard());
1049 const std::string& source = i->first.second;
1050 std::vector<base::Value*>* this_provider_exceptions =
1051 &all_provider_exceptions.at(
1052 HostContentSettingsMap::GetProviderTypeFromSource(source));
1054 // Add the "parent" entry for the non-embedded setting.
1055 ContentSetting parent_setting =
1056 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
1057 const ContentSettingsPattern& secondary_pattern =
1058 parent == one_settings.end() ? primary_pattern : parent->first;
1059 this_provider_exceptions->push_back(GetExceptionForPage(primary_pattern,
1060 secondary_pattern,
1061 parent_setting,
1062 source));
1064 // Add the "children" for any embedded settings.
1065 for (OnePatternSettings::const_iterator j = one_settings.begin();
1066 j != one_settings.end(); ++j) {
1067 // Skip the non-embedded setting which we already added above.
1068 if (j == parent)
1069 continue;
1071 ContentSetting content_setting = j->second;
1072 this_provider_exceptions->push_back(GetExceptionForPage(
1073 primary_pattern,
1074 j->first,
1075 content_setting,
1076 source));
1080 for (size_t i = 0; i < all_provider_exceptions.size(); ++i) {
1081 for (size_t j = 0; j < all_provider_exceptions[i].size(); ++j) {
1082 exceptions->Append(all_provider_exceptions[i][j]);
1087 void ContentSettingsHandler::RemoveNotificationException(
1088 const base::ListValue* args, size_t arg_index) {
1089 Profile* profile = Profile::FromWebUI(web_ui());
1090 std::string origin;
1091 std::string setting;
1092 bool rv = args->GetString(arg_index++, &origin);
1093 DCHECK(rv);
1094 rv = args->GetString(arg_index++, &setting);
1095 DCHECK(rv);
1096 ContentSetting content_setting = ContentSettingFromString(setting);
1098 DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
1099 content_setting == CONTENT_SETTING_BLOCK);
1100 DesktopNotificationServiceFactory::GetForProfile(profile)->
1101 ClearSetting(ContentSettingsPattern::FromString(origin));
1104 void ContentSettingsHandler::RemoveMediaException(
1105 const base::ListValue* args, size_t arg_index) {
1106 std::string mode;
1107 bool rv = args->GetString(arg_index++, &mode);
1108 DCHECK(rv);
1110 std::string pattern;
1111 rv = args->GetString(arg_index++, &pattern);
1112 DCHECK(rv);
1114 HostContentSettingsMap* settings_map =
1115 mode == "normal" ? GetContentSettingsMap() :
1116 GetOTRContentSettingsMap();
1117 if (settings_map) {
1118 settings_map->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern),
1119 ContentSettingsPattern::Wildcard(),
1120 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
1121 std::string(),
1122 NULL);
1123 settings_map->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern),
1124 ContentSettingsPattern::Wildcard(),
1125 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
1126 std::string(),
1127 NULL);
1131 void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
1132 const base::ListValue* args, size_t arg_index,
1133 ContentSettingsType type) {
1134 std::string mode;
1135 bool rv = args->GetString(arg_index++, &mode);
1136 DCHECK(rv);
1138 std::string pattern;
1139 rv = args->GetString(arg_index++, &pattern);
1140 DCHECK(rv);
1142 std::string secondary_pattern;
1143 rv = args->GetString(arg_index++, &secondary_pattern);
1144 DCHECK(rv);
1146 HostContentSettingsMap* settings_map =
1147 mode == "normal" ? GetContentSettingsMap() :
1148 GetOTRContentSettingsMap();
1149 if (settings_map) {
1150 settings_map->SetWebsiteSetting(
1151 ContentSettingsPattern::FromString(pattern),
1152 secondary_pattern.empty()
1153 ? ContentSettingsPattern::Wildcard()
1154 : ContentSettingsPattern::FromString(secondary_pattern),
1155 type,
1156 std::string(),
1157 NULL);
1161 void ContentSettingsHandler::RegisterMessages() {
1162 web_ui()->RegisterMessageCallback("setContentFilter",
1163 base::Bind(&ContentSettingsHandler::SetContentFilter,
1164 base::Unretained(this)));
1165 web_ui()->RegisterMessageCallback("removeException",
1166 base::Bind(&ContentSettingsHandler::RemoveException,
1167 base::Unretained(this)));
1168 web_ui()->RegisterMessageCallback("setException",
1169 base::Bind(&ContentSettingsHandler::SetException,
1170 base::Unretained(this)));
1171 web_ui()->RegisterMessageCallback("checkExceptionPatternValidity",
1172 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity,
1173 base::Unretained(this)));
1176 void ContentSettingsHandler::ApplyWhitelist(ContentSettingsType content_type,
1177 ContentSetting default_setting) {
1178 Profile* profile = Profile::FromWebUI(web_ui());
1179 HostContentSettingsMap* map = GetContentSettingsMap();
1180 if (content_type != CONTENT_SETTINGS_TYPE_PLUGINS)
1181 return;
1182 const int kDefaultWhitelistVersion = 1;
1183 PrefService* prefs = profile->GetPrefs();
1184 int version = prefs->GetInteger(
1185 prefs::kContentSettingsDefaultWhitelistVersion);
1186 if (version >= kDefaultWhitelistVersion)
1187 return;
1188 ContentSetting old_setting =
1189 map->GetDefaultContentSetting(CONTENT_SETTINGS_TYPE_PLUGINS, NULL);
1190 // TODO(bauerb): Remove this once the Google Talk plug-in works nicely with
1191 // click-to-play (b/6090625).
1192 if (old_setting == CONTENT_SETTING_ALLOW &&
1193 default_setting == CONTENT_SETTING_ASK) {
1194 map->SetWebsiteSetting(
1195 ContentSettingsPattern::Wildcard(),
1196 ContentSettingsPattern::Wildcard(),
1197 CONTENT_SETTINGS_TYPE_PLUGINS,
1198 "google-talk",
1199 new base::FundamentalValue(CONTENT_SETTING_ALLOW));
1201 prefs->SetInteger(prefs::kContentSettingsDefaultWhitelistVersion,
1202 kDefaultWhitelistVersion);
1205 void ContentSettingsHandler::SetContentFilter(const base::ListValue* args) {
1206 DCHECK_EQ(2U, args->GetSize());
1207 std::string group, setting;
1208 if (!(args->GetString(0, &group) &&
1209 args->GetString(1, &setting))) {
1210 NOTREACHED();
1211 return;
1214 ContentSetting default_setting = ContentSettingFromString(setting);
1215 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
1216 Profile* profile = Profile::FromWebUI(web_ui());
1218 #if defined(OS_CHROMEOS)
1219 // ChromeOS special case : in Guest mode settings are opened in Incognito
1220 // mode, so we need original profile to actually modify settings.
1221 if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
1222 profile = profile->GetOriginalProfile();
1223 #endif
1225 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) {
1226 DesktopNotificationServiceFactory::GetForProfile(profile)->
1227 SetDefaultContentSetting(default_setting);
1228 } else {
1229 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
1230 ApplyWhitelist(content_type, default_setting);
1231 map->SetDefaultContentSetting(content_type, default_setting);
1233 switch (content_type) {
1234 case CONTENT_SETTINGS_TYPE_COOKIES:
1235 content::RecordAction(
1236 UserMetricsAction("Options_DefaultCookieSettingChanged"));
1237 break;
1238 case CONTENT_SETTINGS_TYPE_IMAGES:
1239 content::RecordAction(
1240 UserMetricsAction("Options_DefaultImagesSettingChanged"));
1241 break;
1242 case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
1243 content::RecordAction(
1244 UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
1245 break;
1246 case CONTENT_SETTINGS_TYPE_PLUGINS:
1247 content::RecordAction(
1248 UserMetricsAction("Options_DefaultPluginsSettingChanged"));
1249 break;
1250 case CONTENT_SETTINGS_TYPE_POPUPS:
1251 content::RecordAction(
1252 UserMetricsAction("Options_DefaultPopupsSettingChanged"));
1253 break;
1254 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
1255 content::RecordAction(
1256 UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
1257 break;
1258 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
1259 content::RecordAction(
1260 UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
1261 break;
1262 case CONTENT_SETTINGS_TYPE_MOUSELOCK:
1263 content::RecordAction(
1264 UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
1265 break;
1266 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
1267 content::RecordAction(
1268 UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
1269 break;
1270 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
1271 content::RecordAction(
1272 UserMetricsAction("Options_DefaultMultipleAutomaticDLSettingChange"));
1273 break;
1274 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
1275 content::RecordAction(
1276 UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
1277 break;
1278 default:
1279 break;
1283 void ContentSettingsHandler::RemoveException(const base::ListValue* args) {
1284 size_t arg_i = 0;
1285 std::string type_string;
1286 CHECK(args->GetString(arg_i++, &type_string));
1288 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
1289 switch (type) {
1290 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
1291 RemoveNotificationException(args, arg_i);
1292 break;
1293 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
1294 RemoveMediaException(args, arg_i);
1295 break;
1296 default:
1297 RemoveExceptionFromHostContentSettingsMap(args, arg_i, type);
1298 break;
1302 void ContentSettingsHandler::SetException(const base::ListValue* args) {
1303 size_t arg_i = 0;
1304 std::string type_string;
1305 CHECK(args->GetString(arg_i++, &type_string));
1306 std::string mode;
1307 CHECK(args->GetString(arg_i++, &mode));
1308 std::string pattern;
1309 CHECK(args->GetString(arg_i++, &pattern));
1310 std::string setting;
1311 CHECK(args->GetString(arg_i++, &setting));
1313 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
1314 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
1315 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
1316 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
1317 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
1318 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
1319 NOTREACHED();
1320 } else {
1321 HostContentSettingsMap* settings_map =
1322 mode == "normal" ? GetContentSettingsMap() :
1323 GetOTRContentSettingsMap();
1325 // The settings map could be null if the mode was OTR but the OTR profile
1326 // got destroyed before we received this message.
1327 if (!settings_map)
1328 return;
1329 settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern),
1330 ContentSettingsPattern::Wildcard(),
1331 type,
1332 std::string(),
1333 ContentSettingFromString(setting));
1337 void ContentSettingsHandler::CheckExceptionPatternValidity(
1338 const base::ListValue* args) {
1339 size_t arg_i = 0;
1340 std::string type_string;
1341 CHECK(args->GetString(arg_i++, &type_string));
1342 std::string mode_string;
1343 CHECK(args->GetString(arg_i++, &mode_string));
1344 std::string pattern_string;
1345 CHECK(args->GetString(arg_i++, &pattern_string));
1347 ContentSettingsPattern pattern =
1348 ContentSettingsPattern::FromString(pattern_string);
1350 web_ui()->CallJavascriptFunction(
1351 "ContentSettings.patternValidityCheckComplete",
1352 base::StringValue(type_string),
1353 base::StringValue(mode_string),
1354 base::StringValue(pattern_string),
1355 base::FundamentalValue(pattern.IsValid()));
1358 // static
1359 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
1360 ContentSettingsType type) {
1361 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
1362 if (type == kContentSettingsTypeGroupNames[i].type)
1363 return kContentSettingsTypeGroupNames[i].name;
1366 NOTREACHED();
1367 return std::string();
1370 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
1371 return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap();
1374 ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() {
1375 return ProtocolHandlerRegistryFactory::GetForProfile(
1376 Profile::FromWebUI(web_ui()));
1379 HostContentSettingsMap*
1380 ContentSettingsHandler::GetOTRContentSettingsMap() {
1381 Profile* profile = Profile::FromWebUI(web_ui());
1382 if (profile->HasOffTheRecordProfile())
1383 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
1384 return NULL;
1387 void ContentSettingsHandler::RefreshFlashMediaSettings() {
1388 media_settings_.flash_settings_initialized = false;
1390 media_settings_.last_flash_refresh_request_id =
1391 flash_settings_manager_->GetPermissionSettings(
1392 PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC);
1395 void ContentSettingsHandler::OnPepperFlashPrefChanged() {
1396 ShowFlashMediaLink(DEFAULT_SETTING, false);
1397 ShowFlashMediaLink(EXCEPTIONS, false);
1399 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
1400 if (prefs->GetBoolean(prefs::kPepperFlashSettingsEnabled))
1401 RefreshFlashMediaSettings();
1402 else
1403 media_settings_.flash_settings_initialized = false;
1406 void ContentSettingsHandler::ShowFlashMediaLink(LinkType link_type, bool show) {
1407 bool& show_link = link_type == DEFAULT_SETTING ?
1408 media_settings_.show_flash_default_link :
1409 media_settings_.show_flash_exceptions_link;
1410 if (show_link != show) {
1411 web_ui()->CallJavascriptFunction(
1412 link_type == DEFAULT_SETTING ?
1413 "ContentSettings.showMediaPepperFlashDefaultLink" :
1414 "ContentSettings.showMediaPepperFlashExceptionsLink",
1415 base::FundamentalValue(show));
1416 show_link = show;
1420 void ContentSettingsHandler::UpdateFlashMediaLinksVisibility() {
1421 if (!media_settings_.flash_settings_initialized ||
1422 !media_settings_.default_setting_initialized ||
1423 !media_settings_.exceptions_initialized) {
1424 return;
1427 // Flash won't send us notifications when its settings get changed, which
1428 // means the Flash settings in |media_settings_| may be out-dated, especially
1429 // after we show links to change Flash settings.
1430 // In order to avoid confusion, we won't hide the links once they are showed.
1431 // One exception is that we will hide them when Pepper Flash is disabled
1432 // (handled in OnPepperFlashPrefChanged()).
1433 if (media_settings_.show_flash_default_link &&
1434 media_settings_.show_flash_exceptions_link) {
1435 return;
1438 if (!media_settings_.show_flash_default_link) {
1439 // If both audio and video capture are disabled by policy, the link
1440 // shouldn't be showed. Flash conforms to the policy in this case because
1441 // it cannot open those devices. We don't have to look at the Flash
1442 // settings.
1443 if (!(media_settings_.policy_disable_audio &&
1444 media_settings_.policy_disable_video) &&
1445 media_settings_.flash_default_setting !=
1446 media_settings_.default_setting) {
1447 ShowFlashMediaLink(DEFAULT_SETTING, true);
1450 if (!media_settings_.show_flash_exceptions_link) {
1451 // If audio or video capture is disabled by policy, we skip comparison of
1452 // exceptions for audio or video capture, respectively.
1453 if (!PepperFlashContentSettingsUtils::AreMediaExceptionsEqual(
1454 media_settings_.default_setting,
1455 media_settings_.exceptions,
1456 media_settings_.flash_default_setting,
1457 media_settings_.flash_exceptions,
1458 media_settings_.policy_disable_audio,
1459 media_settings_.policy_disable_video)) {
1460 ShowFlashMediaLink(EXCEPTIONS, true);
1465 void ContentSettingsHandler::UpdateProtectedContentExceptionsButton() {
1466 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
1467 // Exceptions apply only when the feature is enabled.
1468 bool enable_exceptions = prefs->GetBoolean(prefs::kEnableDRM);
1469 web_ui()->CallJavascriptFunction(
1470 "ContentSettings.enableProtectedContentExceptions",
1471 base::FundamentalValue(enable_exceptions));
1474 } // namespace options