Disable protected content button in Guest mode settings
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / content_settings_handler.cc
blob7a4babbba338d37453bf482a6ef61ca4d5a0a1ab
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 <algorithm>
8 #include <map>
9 #include <vector>
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/command_line.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/strings/string_number_conversions.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/values.h"
18 #include "chrome/browser/browser_process.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/content_settings/content_settings_utils.h"
21 #include "chrome/browser/content_settings/host_content_settings_map.h"
22 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
23 #include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
24 #include "chrome/browser/extensions/extension_special_storage_policy.h"
25 #include "chrome/browser/notifications/desktop_notification_profile_util.h"
26 #include "chrome/browser/profiles/profile.h"
27 #include "chrome/browser/ui/browser_list.h"
28 #include "chrome/common/chrome_switches.h"
29 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
30 #include "chrome/common/pref_names.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/grit/generated_resources.h"
33 #include "chrome/grit/locale_settings.h"
34 #include "components/content_settings/core/browser/content_settings_details.h"
35 #include "components/content_settings/core/common/content_settings.h"
36 #include "components/content_settings/core/common/content_settings_pattern.h"
37 #include "components/google/core/browser/google_util.h"
38 #include "components/user_prefs/user_prefs.h"
39 #include "content/public/browser/notification_service.h"
40 #include "content/public/browser/notification_source.h"
41 #include "content/public/browser/notification_types.h"
42 #include "content/public/browser/user_metrics.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/browser/web_ui.h"
45 #include "content/public/common/content_switches.h"
46 #include "content/public/common/page_zoom.h"
47 #include "extensions/browser/extension_registry.h"
48 #include "extensions/common/extension_set.h"
49 #include "extensions/common/permissions/api_permission.h"
50 #include "extensions/common/permissions/permissions_data.h"
51 #include "ui/base/l10n/l10n_util.h"
53 #if defined(OS_CHROMEOS)
54 #include "components/user_manager/user_manager.h"
55 #endif
57 using base::UserMetricsAction;
58 using content_settings::ContentSettingToString;
59 using content_settings::ContentSettingFromString;
60 using extensions::APIPermission;
62 namespace {
64 struct ContentSettingsTypeNameEntry {
65 ContentSettingsType type;
66 const char* name;
69 // Maps from a secondary pattern to a setting.
70 typedef std::map<ContentSettingsPattern, ContentSetting>
71 OnePatternSettings;
72 // Maps from a primary pattern/source pair to a OnePatternSettings. All the
73 // mappings in OnePatternSettings share the given primary pattern and source.
74 typedef std::map<std::pair<ContentSettingsPattern, std::string>,
75 OnePatternSettings>
76 AllPatternsSettings;
78 // The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
79 // extensions which should have their extent displayed.
80 typedef bool (*AppFilter)(const extensions::Extension& app,
81 content::BrowserContext* profile);
83 const char kExceptionsLearnMoreUrl[] =
84 "https://support.google.com/chrome/?p=settings_manage_exceptions";
86 const char* kSetting = "setting";
87 const char* kOrigin = "origin";
88 const char* kSource = "source";
89 const char* kAppName = "appName";
90 const char* kAppId = "appId";
91 const char* kEmbeddingOrigin = "embeddingOrigin";
92 const char* kPreferencesSource = "preference";
93 const char* kVideoSetting = "video";
94 const char* kZoom = "zoom";
96 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
97 {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
98 {CONTENT_SETTINGS_TYPE_IMAGES, "images"},
99 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"},
100 {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"},
101 {CONTENT_SETTINGS_TYPE_POPUPS, "popups"},
102 {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"},
103 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"},
104 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"},
105 {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"},
106 {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"},
107 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, "register-protocol-handler"},
108 {CONTENT_SETTINGS_TYPE_MEDIASTREAM, "media-stream"},
109 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, "media-stream-mic"},
110 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, "media-stream-camera"},
111 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, "ppapi-broker"},
112 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, "multiple-automatic-downloads"},
113 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, "midi-sysex"},
114 {CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, "push-messaging"},
115 {CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, "ssl-cert-decisions"},
116 #if defined(OS_CHROMEOS)
117 {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, "protectedContent"},
118 #endif
121 // A pseudo content type. We use it to display data like a content setting even
122 // though it is not a real content setting.
123 const char* kZoomContentType = "zoomlevels";
125 content::BrowserContext* GetBrowserContext(content::WebUI* web_ui) {
126 return web_ui->GetWebContents()->GetBrowserContext();
129 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
130 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
131 if (name == kContentSettingsTypeGroupNames[i].name)
132 return kContentSettingsTypeGroupNames[i].type;
135 NOTREACHED() << name << " is not a recognized content settings type.";
136 return CONTENT_SETTINGS_TYPE_DEFAULT;
139 // Create a DictionaryValue* that will act as a data source for a single row
140 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
141 // Ownership of the pointer is passed to the caller.
142 base::DictionaryValue* GetExceptionForPage(
143 const ContentSettingsPattern& pattern,
144 const ContentSettingsPattern& secondary_pattern,
145 const ContentSetting& setting,
146 const std::string& provider_name) {
147 base::DictionaryValue* exception = new base::DictionaryValue();
148 exception->SetString(kOrigin, pattern.ToString());
149 exception->SetString(kEmbeddingOrigin,
150 secondary_pattern == ContentSettingsPattern::Wildcard() ?
151 std::string() :
152 secondary_pattern.ToString());
153 exception->SetString(kSetting, ContentSettingToString(setting));
154 exception->SetString(kSource, provider_name);
155 return exception;
158 // Create a DictionaryValue* that will act as a data source for a single row
159 // in the Geolocation exceptions table. Ownership of the pointer is passed to
160 // the caller.
161 base::DictionaryValue* GetGeolocationExceptionForPage(
162 const ContentSettingsPattern& origin,
163 const ContentSettingsPattern& embedding_origin,
164 ContentSetting setting) {
165 base::DictionaryValue* exception = new base::DictionaryValue();
166 exception->SetString(kSetting, ContentSettingToString(setting));
167 exception->SetString(kOrigin, origin.ToString());
168 exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
169 return exception;
172 // Create a DictionaryValue* that will act as a data source for a single row
173 // in the desktop notifications exceptions table. Ownership of the pointer is
174 // passed to the caller.
175 base::DictionaryValue* GetNotificationExceptionForPage(
176 const ContentSettingsPattern& primary_pattern,
177 const ContentSettingsPattern& secondary_pattern,
178 ContentSetting setting,
179 const std::string& provider_name) {
180 std::string embedding_origin;
181 if (secondary_pattern != ContentSettingsPattern::Wildcard())
182 embedding_origin = secondary_pattern.ToString();
184 base::DictionaryValue* exception = new base::DictionaryValue();
185 exception->SetString(kSetting, ContentSettingToString(setting));
186 exception->SetString(kOrigin, primary_pattern.ToString());
187 exception->SetString(kEmbeddingOrigin, embedding_origin);
188 exception->SetString(kSource, provider_name);
189 return exception;
192 // Returns true whenever the |extension| is hosted and has |permission|.
193 // Must have the AppFilter signature.
194 template <APIPermission::ID permission>
195 bool HostedAppHasPermission(const extensions::Extension& extension,
196 content::BrowserContext* /* context */) {
197 return extension.is_hosted_app() &&
198 extension.permissions_data()->HasAPIPermission(permission);
201 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
202 // the web extent of a hosted |app|.
203 void AddExceptionForHostedApp(const std::string& url_pattern,
204 const extensions::Extension& app, base::ListValue* exceptions) {
205 base::DictionaryValue* exception = new base::DictionaryValue();
206 exception->SetString(kSetting, ContentSettingToString(CONTENT_SETTING_ALLOW));
207 exception->SetString(kOrigin, url_pattern);
208 exception->SetString(kEmbeddingOrigin, url_pattern);
209 exception->SetString(kSource, "HostedApp");
210 exception->SetString(kAppName, app.name());
211 exception->SetString(kAppId, app.id());
212 exceptions->Append(exception);
215 // Asks the |profile| for hosted apps which have the |permission| set, and
216 // adds their web extent and launch URL to the |exceptions| list.
217 void AddExceptionsGrantedByHostedApps(content::BrowserContext* context,
218 AppFilter app_filter,
219 base::ListValue* exceptions) {
220 const extensions::ExtensionSet& extensions =
221 extensions::ExtensionRegistry::Get(context)->enabled_extensions();
222 for (extensions::ExtensionSet::const_iterator extension = extensions.begin();
223 extension != extensions.end(); ++extension) {
224 if (!app_filter(*extension->get(), context))
225 continue;
227 extensions::URLPatternSet web_extent = (*extension)->web_extent();
228 // Add patterns from web extent.
229 for (extensions::URLPatternSet::const_iterator pattern = web_extent.begin();
230 pattern != web_extent.end(); ++pattern) {
231 std::string url_pattern = pattern->GetAsString();
232 AddExceptionForHostedApp(url_pattern, *extension->get(), exceptions);
234 // Retrieve the launch URL.
235 GURL launch_url =
236 extensions::AppLaunchInfo::GetLaunchWebURL(extension->get());
237 // Skip adding the launch URL if it is part of the web extent.
238 if (web_extent.MatchesURL(launch_url))
239 continue;
240 AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions);
244 // Sort ZoomLevelChanges by host and scheme
245 // (a.com < http://a.com < https://a.com < b.com).
246 bool HostZoomSort(const content::HostZoomMap::ZoomLevelChange& a,
247 const content::HostZoomMap::ZoomLevelChange& b) {
248 return a.host == b.host ? a.scheme < b.scheme : a.host < b.host;
251 } // namespace
253 namespace options {
255 ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo()
256 : flash_default_setting(CONTENT_SETTING_DEFAULT),
257 flash_settings_initialized(false),
258 last_flash_refresh_request_id(0),
259 show_flash_default_link(false),
260 show_flash_exceptions_link(false),
261 default_setting(CONTENT_SETTING_DEFAULT),
262 policy_disable_audio(false),
263 policy_disable_video(false),
264 default_setting_initialized(false),
265 exceptions_initialized(false) {
268 ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
271 ContentSettingsHandler::ContentSettingsHandler() : observer_(this) {
274 ContentSettingsHandler::~ContentSettingsHandler() {
277 void ContentSettingsHandler::GetLocalizedValues(
278 base::DictionaryValue* localized_strings) {
279 DCHECK(localized_strings);
281 // TODO(dhnishi): Standardize to lowerCamelCase.
282 static OptionsStringResource resources[] = {
283 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON },
284 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON },
285 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON },
286 { "askException", IDS_EXCEPTIONS_ASK_BUTTON },
287 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL },
288 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS },
289 { "manageExceptions", IDS_EXCEPTIONS_MANAGE },
290 { "manage_handlers", IDS_HANDLERS_MANAGE },
291 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER },
292 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER },
293 { "exceptionZoomHeader", IDS_EXCEPTIONS_ZOOM_HEADER },
294 { "embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST },
295 // Cookies filter.
296 { "cookiesTabLabel", IDS_COOKIES_TAB_LABEL },
297 { "cookies_header", IDS_COOKIES_HEADER },
298 { "cookiesAllow", IDS_COOKIES_ALLOW_RADIO },
299 { "cookiesBlock", IDS_COOKIES_BLOCK_RADIO },
300 { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO },
301 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX },
302 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX },
303 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX },
304 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON },
305 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS },
306 { "flash_storage_url", IDS_FLASH_STORAGE_URL },
307 #if defined(ENABLE_GOOGLE_NOW)
308 { "googleGeolocationAccessEnable",
309 IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX },
310 #endif
311 // Image filter.
312 { "imagesTabLabel", IDS_IMAGES_TAB_LABEL },
313 { "images_header", IDS_IMAGES_HEADER },
314 { "imagesAllow", IDS_IMAGES_LOAD_RADIO },
315 { "imagesBlock", IDS_IMAGES_NOLOAD_RADIO },
316 // JavaScript filter.
317 { "javascriptTabLabel", IDS_JAVASCRIPT_TAB_LABEL },
318 { "javascript_header", IDS_JAVASCRIPT_HEADER },
319 { "javascriptAllow", IDS_JS_ALLOW_RADIO },
320 { "javascriptBlock", IDS_JS_DONOTALLOW_RADIO },
321 // Plug-ins filter.
322 { "pluginsTabLabel", IDS_PLUGIN_TAB_LABEL },
323 { "plugins_header", IDS_PLUGIN_HEADER },
324 { "pluginsAsk", IDS_PLUGIN_ASK_RADIO },
325 { "pluginsAllow", IDS_PLUGIN_LOAD_RADIO },
326 { "pluginsBlock", IDS_PLUGIN_NOLOAD_RADIO },
327 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE },
328 // Pop-ups filter.
329 { "popupsTabLabel", IDS_POPUP_TAB_LABEL },
330 { "popups_header", IDS_POPUP_HEADER },
331 { "popupsAllow", IDS_POPUP_ALLOW_RADIO },
332 { "popupsBlock", IDS_POPUP_BLOCK_RADIO },
333 // Location filter.
334 { "locationTabLabel", IDS_GEOLOCATION_TAB_LABEL },
335 { "location_header", IDS_GEOLOCATION_HEADER },
336 { "locationAllow", IDS_GEOLOCATION_ALLOW_RADIO },
337 { "locationAsk", IDS_GEOLOCATION_ASK_RADIO },
338 { "locationBlock", IDS_GEOLOCATION_BLOCK_RADIO },
339 { "set_by", IDS_GEOLOCATION_SET_BY_HOVER },
340 // Notifications filter.
341 { "notificationsTabLabel", IDS_NOTIFICATIONS_TAB_LABEL },
342 { "notifications_header", IDS_NOTIFICATIONS_HEADER },
343 { "notificationsAllow", IDS_NOTIFICATIONS_ALLOW_RADIO },
344 { "notificationsAsk", IDS_NOTIFICATIONS_ASK_RADIO },
345 { "notificationsBlock", IDS_NOTIFICATIONS_BLOCK_RADIO },
346 // Fullscreen filter.
347 { "fullscreenTabLabel", IDS_FULLSCREEN_TAB_LABEL },
348 { "fullscreen_header", IDS_FULLSCREEN_HEADER },
349 // Mouse Lock filter.
350 { "mouselockTabLabel", IDS_MOUSE_LOCK_TAB_LABEL },
351 { "mouselock_header", IDS_MOUSE_LOCK_HEADER },
352 { "mouselockAllow", IDS_MOUSE_LOCK_ALLOW_RADIO },
353 { "mouselockAsk", IDS_MOUSE_LOCK_ASK_RADIO },
354 { "mouselockBlock", IDS_MOUSE_LOCK_BLOCK_RADIO },
355 #if defined(OS_CHROMEOS) || defined(OS_WIN)
356 // Protected Content filter
357 { "protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL },
358 { "protectedContentInfo", IDS_PROTECTED_CONTENT_INFO },
359 { "protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE },
360 { "protectedContent_header", IDS_PROTECTED_CONTENT_HEADER },
361 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
362 // Media stream capture device filter.
363 { "mediaStreamTabLabel", IDS_MEDIA_STREAM_TAB_LABEL },
364 { "media-stream_header", IDS_MEDIA_STREAM_HEADER },
365 { "mediaStreamAsk", IDS_MEDIA_STREAM_ASK_RADIO },
366 { "mediaStreamBlock", IDS_MEDIA_STREAM_BLOCK_RADIO },
367 { "mediaStreamAudioAsk", IDS_MEDIA_STREAM_ASK_AUDIO_ONLY_RADIO },
368 { "mediaStreamAudioBlock", IDS_MEDIA_STREAM_BLOCK_AUDIO_ONLY_RADIO },
369 { "mediaStreamVideoAsk", IDS_MEDIA_STREAM_ASK_VIDEO_ONLY_RADIO },
370 { "mediaStreamVideoBlock", IDS_MEDIA_STREAM_BLOCK_VIDEO_ONLY_RADIO },
371 { "mediaStreamBubbleAudio", IDS_MEDIA_STREAM_AUDIO_MANAGED },
372 { "mediaStreamBubbleVideo", IDS_MEDIA_STREAM_VIDEO_MANAGED },
373 { "mediaAudioExceptionHeader", IDS_MEDIA_AUDIO_EXCEPTION_HEADER },
374 { "mediaVideoExceptionHeader", IDS_MEDIA_VIDEO_EXCEPTION_HEADER },
375 { "mediaPepperFlashDefaultDivergedLabel",
376 IDS_MEDIA_PEPPER_FLASH_DEFAULT_DIVERGED_LABEL },
377 { "mediaPepperFlashExceptionsDivergedLabel",
378 IDS_MEDIA_PEPPER_FLASH_EXCEPTIONS_DIVERGED_LABEL },
379 { "mediaPepperFlashChangeLink", IDS_MEDIA_PEPPER_FLASH_CHANGE_LINK },
380 { "mediaPepperFlashGlobalPrivacyURL", IDS_FLASH_GLOBAL_PRIVACY_URL },
381 { "mediaPepperFlashWebsitePrivacyURL", IDS_FLASH_WEBSITE_PRIVACY_URL },
382 // PPAPI broker filter.
383 { "ppapi-broker_header", IDS_PPAPI_BROKER_HEADER },
384 { "ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL },
385 { "ppapiBrokerAllow", IDS_PPAPI_BROKER_ALLOW_RADIO },
386 { "ppapiBrokerAsk", IDS_PPAPI_BROKER_ASK_RADIO },
387 { "ppapiBrokerBlock", IDS_PPAPI_BROKER_BLOCK_RADIO },
388 // Multiple automatic downloads
389 { "multipleAutomaticDownloadsTabLabel",
390 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL },
391 { "multipleAutomaticDownloadsAllow",
392 IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO },
393 { "multipleAutomaticDownloadsAsk",
394 IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO },
395 { "multipleAutomaticDownloadsBlock",
396 IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO },
397 // MIDI system exclusive messages
398 { "midi-sysex_header", IDS_MIDI_SYSEX_TAB_LABEL },
399 { "midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO },
400 { "midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO },
401 { "midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO },
402 // Push messaging strings
403 { "push-messaging_header", IDS_PUSH_MESSAGES_TAB_LABEL },
404 { "pushMessagingAllow", IDS_PUSH_MESSSAGING_ALLOW_RADIO },
405 { "pushMessagingAsk", IDS_PUSH_MESSSAGING_ASK_RADIO },
406 { "pushMessagingBlock", IDS_PUSH_MESSSAGING_BLOCK_RADIO },
407 { "zoomlevels_header", IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL },
408 { "zoomLevelsManage", IDS_ZOOMLEVELS_MANAGE_BUTTON },
411 RegisterStrings(localized_strings, resources, arraysize(resources));
412 RegisterTitle(localized_strings, "contentSettingsPage",
413 IDS_CONTENT_SETTINGS_TITLE);
415 // Register titles for each of the individual settings whose exception
416 // dialogs will be processed by |ContentSettingsHandler|.
417 RegisterTitle(localized_strings, "cookies",
418 IDS_COOKIES_TAB_LABEL);
419 RegisterTitle(localized_strings, "images",
420 IDS_IMAGES_TAB_LABEL);
421 RegisterTitle(localized_strings, "javascript",
422 IDS_JAVASCRIPT_TAB_LABEL);
423 RegisterTitle(localized_strings, "plugins",
424 IDS_PLUGIN_TAB_LABEL);
425 RegisterTitle(localized_strings, "popups",
426 IDS_POPUP_TAB_LABEL);
427 RegisterTitle(localized_strings, "location",
428 IDS_GEOLOCATION_TAB_LABEL);
429 RegisterTitle(localized_strings, "notifications",
430 IDS_NOTIFICATIONS_TAB_LABEL);
431 RegisterTitle(localized_strings, "fullscreen",
432 IDS_FULLSCREEN_TAB_LABEL);
433 RegisterTitle(localized_strings, "mouselock",
434 IDS_MOUSE_LOCK_TAB_LABEL);
435 #if defined(OS_CHROMEOS)
436 RegisterTitle(localized_strings, "protectedContent",
437 IDS_PROTECTED_CONTENT_TAB_LABEL);
438 #endif
439 RegisterTitle(localized_strings, "media-stream",
440 IDS_MEDIA_STREAM_TAB_LABEL);
441 RegisterTitle(localized_strings, "ppapi-broker",
442 IDS_PPAPI_BROKER_TAB_LABEL);
443 RegisterTitle(localized_strings, "multiple-automatic-downloads",
444 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
445 RegisterTitle(localized_strings, "midi-sysex",
446 IDS_MIDI_SYSEX_TAB_LABEL);
447 RegisterTitle(localized_strings, "zoomlevels",
448 IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL);
450 localized_strings->SetString("exceptionsLearnMoreUrl",
451 kExceptionsLearnMoreUrl);
454 void ContentSettingsHandler::InitializeHandler() {
455 notification_registrar_.Add(
456 this, chrome::NOTIFICATION_PROFILE_CREATED,
457 content::NotificationService::AllSources());
458 notification_registrar_.Add(
459 this, chrome::NOTIFICATION_PROFILE_DESTROYED,
460 content::NotificationService::AllSources());
462 notification_registrar_.Add(
463 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED,
464 content::NotificationService::AllSources());
465 content::BrowserContext* context = GetBrowserContext(web_ui());
466 notification_registrar_.Add(
467 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
468 content::Source<content::BrowserContext>(context));
470 PrefService* prefs = user_prefs::UserPrefs::Get(context);
471 pref_change_registrar_.Init(prefs);
472 pref_change_registrar_.Add(
473 prefs::kPepperFlashSettingsEnabled,
474 base::Bind(&ContentSettingsHandler::OnPepperFlashPrefChanged,
475 base::Unretained(this)));
476 pref_change_registrar_.Add(
477 prefs::kAudioCaptureAllowed,
478 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
479 base::Unretained(this)));
480 pref_change_registrar_.Add(
481 prefs::kVideoCaptureAllowed,
482 base::Bind(&ContentSettingsHandler::UpdateMediaSettingsView,
483 base::Unretained(this)));
484 pref_change_registrar_.Add(
485 prefs::kEnableDRM,
486 base::Bind(
487 &ContentSettingsHandler::UpdateProtectedContentExceptionsButton,
488 base::Unretained(this)));
490 content::HostZoomMap* host_zoom_map =
491 content::HostZoomMap::GetDefaultForBrowserContext(context);
492 host_zoom_map_subscription_ =
493 host_zoom_map->AddZoomLevelChangedCallback(
494 base::Bind(&ContentSettingsHandler::OnZoomLevelChanged,
495 base::Unretained(this)));
497 flash_settings_manager_.reset(new PepperFlashSettingsManager(this, context));
498 observer_.Add(Profile::FromWebUI(web_ui())->GetHostContentSettingsMap());
501 void ContentSettingsHandler::InitializePage() {
502 media_settings_ = MediaSettingsInfo();
503 RefreshFlashMediaSettings();
505 UpdateHandlersEnabledRadios();
506 UpdateAllExceptionsViewsFromModel();
507 UpdateProtectedContentExceptionsButton();
510 void ContentSettingsHandler::OnContentSettingChanged(
511 const ContentSettingsPattern& primary_pattern,
512 const ContentSettingsPattern& secondary_pattern,
513 ContentSettingsType content_type,
514 std::string resource_identifier) {
515 const ContentSettingsDetails details(
516 primary_pattern, secondary_pattern, content_type, resource_identifier);
517 // TODO(estade): we pretend update_all() is always true.
518 if (details.update_all_types())
519 UpdateAllExceptionsViewsFromModel();
520 else
521 UpdateExceptionsViewFromModel(details.type());
524 void ContentSettingsHandler::Observe(
525 int type,
526 const content::NotificationSource& source,
527 const content::NotificationDetails& details) {
528 switch (type) {
529 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
530 Profile* profile = content::Source<Profile>(source).ptr();
531 if (profile->IsOffTheRecord()) {
532 web_ui()->CallJavascriptFunction(
533 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
534 observer_.Remove(profile->GetHostContentSettingsMap());
536 break;
539 case chrome::NOTIFICATION_PROFILE_CREATED: {
540 Profile* profile = content::Source<Profile>(source).ptr();
541 if (profile->IsOffTheRecord()) {
542 UpdateAllOTRExceptionsViewsFromModel();
543 observer_.Add(profile->GetHostContentSettingsMap());
545 break;
548 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: {
549 UpdateNotificationExceptionsView();
550 break;
553 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: {
554 UpdateHandlersEnabledRadios();
555 break;
560 void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
561 uint32 request_id,
562 bool success,
563 PP_Flash_BrowserOperations_Permission default_permission,
564 const ppapi::FlashSiteSettings& sites) {
565 if (success && request_id == media_settings_.last_flash_refresh_request_id) {
566 media_settings_.flash_settings_initialized = true;
567 media_settings_.flash_default_setting =
568 PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
569 default_permission);
570 PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
571 sites, &media_settings_.flash_exceptions);
572 PepperFlashContentSettingsUtils::SortMediaExceptions(
573 &media_settings_.flash_exceptions);
575 UpdateFlashMediaLinksVisibility();
579 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
580 ContentSettingsType type) {
581 base::DictionaryValue filter_settings;
582 std::string provider_id;
583 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
584 GetSettingDefaultFromModel(type, &provider_id));
585 filter_settings.SetString(
586 ContentSettingsTypeToGroupName(type) + ".managedBy", provider_id);
588 web_ui()->CallJavascriptFunction(
589 "ContentSettings.setContentFilterSettingsValue", filter_settings);
592 void ContentSettingsHandler::UpdateMediaSettingsView() {
593 PrefService* prefs = user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
594 bool audio_disabled = !prefs->GetBoolean(prefs::kAudioCaptureAllowed) &&
595 prefs->IsManagedPreference(prefs::kAudioCaptureAllowed);
596 bool video_disabled = !prefs->GetBoolean(prefs::kVideoCaptureAllowed) &&
597 prefs->IsManagedPreference(prefs::kVideoCaptureAllowed);
599 media_settings_.policy_disable_audio = audio_disabled;
600 media_settings_.policy_disable_video = video_disabled;
601 media_settings_.default_setting =
602 GetContentSettingsMap()->GetDefaultContentSetting(
603 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
604 media_settings_.default_setting_initialized = true;
605 UpdateFlashMediaLinksVisibility();
607 base::DictionaryValue media_ui_settings;
608 media_ui_settings.SetBoolean("cameraDisabled", video_disabled);
609 media_ui_settings.SetBoolean("micDisabled", audio_disabled);
611 // In case only video is enabled change the text appropriately.
612 if (audio_disabled && !video_disabled) {
613 media_ui_settings.SetString("askText", "mediaStreamVideoAsk");
614 media_ui_settings.SetString("blockText", "mediaStreamVideoBlock");
615 media_ui_settings.SetBoolean("showBubble", true);
616 media_ui_settings.SetString("bubbleText", "mediaStreamBubbleAudio");
618 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
619 media_ui_settings);
620 return;
623 // In case only audio is enabled change the text appropriately.
624 if (video_disabled && !audio_disabled) {
625 base::DictionaryValue media_ui_settings;
626 media_ui_settings.SetString("askText", "mediaStreamAudioAsk");
627 media_ui_settings.SetString("blockText", "mediaStreamAudioBlock");
628 media_ui_settings.SetBoolean("showBubble", true);
629 media_ui_settings.SetString("bubbleText", "mediaStreamBubbleVideo");
631 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
632 media_ui_settings);
633 return;
636 if (audio_disabled && video_disabled) {
637 // Fake policy controlled default because the user can not change anything
638 // until both audio and video are blocked.
639 base::DictionaryValue filter_settings;
640 std::string group_name =
641 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
642 filter_settings.SetString(group_name + ".value",
643 ContentSettingToString(CONTENT_SETTING_BLOCK));
644 filter_settings.SetString(group_name + ".managedBy", "policy");
645 web_ui()->CallJavascriptFunction(
646 "ContentSettings.setContentFilterSettingsValue", filter_settings);
649 media_ui_settings.SetString("askText", "mediaStreamAsk");
650 media_ui_settings.SetString("blockText", "mediaStreamBlock");
651 media_ui_settings.SetBoolean("showBubble", false);
652 media_ui_settings.SetString("bubbleText", std::string());
654 web_ui()->CallJavascriptFunction("ContentSettings.updateMediaUI",
655 media_ui_settings);
658 std::string ContentSettingsHandler::GetSettingDefaultFromModel(
659 ContentSettingsType type, std::string* provider_id) {
660 Profile* profile = Profile::FromWebUI(web_ui());
661 ContentSetting default_setting;
662 default_setting =
663 profile->GetHostContentSettingsMap()->GetDefaultContentSetting(
664 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));
683 // Zoom levels are not actually a content type so we need to handle them
684 // separately.
685 UpdateZoomLevelsExceptionsView();
688 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
689 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
690 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
691 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
695 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
696 ContentSettingsType type) {
697 switch (type) {
698 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
699 UpdateGeolocationExceptionsView();
700 break;
701 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
702 UpdateNotificationExceptionsView();
703 break;
704 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
705 UpdateMediaSettingsView();
706 break;
707 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
708 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
709 UpdateMediaExceptionsView();
710 break;
711 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
712 // We don't yet support exceptions for mixed scripting.
713 break;
714 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
715 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
716 // is supposed to be set by policy only. Hence there is no user facing UI
717 // for this content type and we skip it here.
718 break;
719 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
720 // The RPH settings are retrieved separately.
721 break;
722 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
723 UpdateMIDISysExExceptionsView();
724 break;
725 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS:
726 // The content settings type CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS is
727 // supposed to be set by flags and field trials only, thus there is no
728 // user facing UI for this content type and we skip it here.
729 break;
730 #if defined(OS_WIN)
731 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
732 break;
733 #endif
734 default:
735 UpdateExceptionsViewFromHostContentSettingsMap(type);
736 break;
740 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
741 ContentSettingsType type) {
742 switch (type) {
743 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
744 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
745 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
746 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
747 #if defined(OS_WIN)
748 case CONTENT_SETTINGS_TYPE_METRO_SWITCH_TO_DESKTOP:
749 #endif
750 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
751 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
752 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
753 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
754 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
755 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS:
756 break;
757 default:
758 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
759 break;
763 // TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
764 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
765 Profile* profile = Profile::FromWebUI(web_ui());
766 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
768 ContentSettingsForOneType all_settings;
769 map->GetSettingsForOneType(
770 CONTENT_SETTINGS_TYPE_GEOLOCATION,
771 std::string(),
772 &all_settings);
774 // Group geolocation settings by primary_pattern.
775 AllPatternsSettings all_patterns_settings;
776 for (ContentSettingsForOneType::iterator i = all_settings.begin();
777 i != all_settings.end(); ++i) {
778 // Don't add default settings.
779 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
780 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
781 i->source != kPreferencesSource) {
782 continue;
784 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
785 [i->secondary_pattern] = i->setting;
788 base::ListValue exceptions;
789 AddExceptionsGrantedByHostedApps(
790 profile,
791 HostedAppHasPermission<APIPermission::kGeolocation>,
792 &exceptions);
794 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
795 i != all_patterns_settings.end(); ++i) {
796 const ContentSettingsPattern& primary_pattern = i->first.first;
797 const OnePatternSettings& one_settings = i->second;
799 OnePatternSettings::const_iterator parent =
800 one_settings.find(primary_pattern);
802 // Add the "parent" entry for the non-embedded setting.
803 ContentSetting parent_setting =
804 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
805 exceptions.Append(GetGeolocationExceptionForPage(primary_pattern,
806 primary_pattern,
807 parent_setting));
809 // Add the "children" for any embedded settings.
810 for (OnePatternSettings::const_iterator j = one_settings.begin();
811 j != one_settings.end();
812 ++j) {
813 // Skip the non-embedded setting which we already added above.
814 if (j == parent)
815 continue;
817 exceptions.Append(GetGeolocationExceptionForPage(
818 primary_pattern, j->first, j->second));
822 base::StringValue type_string(
823 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
824 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
825 type_string, exceptions);
827 // This is mainly here to keep this function ideologically parallel to
828 // UpdateExceptionsViewFromHostContentSettingsMap().
829 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
832 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
833 Profile* profile = Profile::FromWebUI(web_ui());
834 ContentSettingsForOneType settings;
835 DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
837 base::ListValue exceptions;
838 AddExceptionsGrantedByHostedApps(
839 profile,
840 HostedAppHasPermission<APIPermission::kNotifications>,
841 &exceptions);
843 for (ContentSettingsForOneType::const_iterator i =
844 settings.begin();
845 i != settings.end();
846 ++i) {
847 // Don't add default settings.
848 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
849 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
850 i->source != kPreferencesSource) {
851 continue;
854 exceptions.Append(
855 GetNotificationExceptionForPage(i->primary_pattern,
856 i->secondary_pattern,
857 i->setting,
858 i->source));
861 base::StringValue type_string(
862 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
863 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
864 type_string, exceptions);
866 // This is mainly here to keep this function ideologically parallel to
867 // UpdateExceptionsViewFromHostContentSettingsMap().
868 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
871 void ContentSettingsHandler::UpdateMediaExceptionsView() {
872 base::ListValue media_exceptions;
873 GetExceptionsFromHostContentSettingsMap(
874 GetContentSettingsMap(),
875 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
876 &media_exceptions);
878 base::ListValue video_exceptions;
879 GetExceptionsFromHostContentSettingsMap(
880 GetContentSettingsMap(),
881 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
882 &video_exceptions);
884 // Merge the |video_exceptions| list to |media_exceptions| list.
885 std::map<std::string, base::DictionaryValue*> entries_map;
886 for (base::ListValue::const_iterator media_entry(media_exceptions.begin());
887 media_entry != media_exceptions.end(); ++media_entry) {
888 base::DictionaryValue* media_dict = NULL;
889 if (!(*media_entry)->GetAsDictionary(&media_dict))
890 NOTREACHED();
892 media_dict->SetString(kVideoSetting,
893 ContentSettingToString(CONTENT_SETTING_ASK));
895 std::string media_origin;
896 media_dict->GetString(kOrigin, &media_origin);
897 entries_map[media_origin] = media_dict;
900 for (base::ListValue::iterator video_entry = video_exceptions.begin();
901 video_entry != video_exceptions.end(); ++video_entry) {
902 base::DictionaryValue* video_dict = NULL;
903 if (!(*video_entry)->GetAsDictionary(&video_dict))
904 NOTREACHED();
906 std::string video_origin;
907 std::string video_setting;
908 video_dict->GetString(kOrigin, &video_origin);
909 video_dict->GetString(kSetting, &video_setting);
911 std::map<std::string, base::DictionaryValue*>::iterator iter =
912 entries_map.find(video_origin);
913 if (iter == entries_map.end()) {
914 base::DictionaryValue* exception = new base::DictionaryValue();
915 exception->SetString(kOrigin, video_origin);
916 exception->SetString(kSetting,
917 ContentSettingToString(CONTENT_SETTING_ASK));
918 exception->SetString(kVideoSetting, video_setting);
919 exception->SetString(kSource, kPreferencesSource);
921 // Append the new entry to the list and map.
922 media_exceptions.Append(exception);
923 entries_map[video_origin] = exception;
924 } else {
925 // Modify the existing entry.
926 iter->second->SetString(kVideoSetting, video_setting);
930 media_settings_.exceptions.clear();
931 for (base::ListValue::const_iterator media_entry = media_exceptions.begin();
932 media_entry != media_exceptions.end(); ++media_entry) {
933 base::DictionaryValue* media_dict = NULL;
934 bool result = (*media_entry)->GetAsDictionary(&media_dict);
935 DCHECK(result);
937 std::string origin;
938 std::string audio_setting;
939 std::string video_setting;
940 media_dict->GetString(kOrigin, &origin);
941 media_dict->GetString(kSetting, &audio_setting);
942 media_dict->GetString(kVideoSetting, &video_setting);
943 media_settings_.exceptions.push_back(MediaException(
944 ContentSettingsPattern::FromString(origin),
945 ContentSettingFromString(audio_setting),
946 ContentSettingFromString(video_setting)));
948 PepperFlashContentSettingsUtils::SortMediaExceptions(
949 &media_settings_.exceptions);
950 media_settings_.exceptions_initialized = true;
951 UpdateFlashMediaLinksVisibility();
953 base::StringValue type_string(
954 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_MEDIASTREAM));
955 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
956 type_string, media_exceptions);
958 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MEDIASTREAM);
961 void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
962 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableWebMIDI)) {
963 web_ui()->CallJavascriptFunction(
964 "ContentSettings.showExperimentalWebMIDISettings",
965 base::FundamentalValue(true));
968 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
969 UpdateExceptionsViewFromHostContentSettingsMap(
970 CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
973 void ContentSettingsHandler::UpdateZoomLevelsExceptionsView() {
974 base::ListValue zoom_levels_exceptions;
976 content::HostZoomMap* host_zoom_map =
977 content::HostZoomMap::GetDefaultForBrowserContext(
978 GetBrowserContext(web_ui()));
979 content::HostZoomMap::ZoomLevelVector zoom_levels(
980 host_zoom_map->GetAllZoomLevels());
981 std::sort(zoom_levels.begin(), zoom_levels.end(), HostZoomSort);
983 for (content::HostZoomMap::ZoomLevelVector::const_iterator i =
984 zoom_levels.begin();
985 i != zoom_levels.end();
986 ++i) {
987 scoped_ptr<base::DictionaryValue> exception(new base::DictionaryValue);
988 switch (i->mode) {
989 case content::HostZoomMap::ZOOM_CHANGED_FOR_HOST:
990 exception->SetString(kOrigin, i->host);
991 break;
992 case content::HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
993 // These are not stored in preferences and get cleared on next browser
994 // start. Therefore, we don't care for them.
995 break;
996 case content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
997 NOTREACHED();
999 exception->SetString(kSetting,
1000 ContentSettingToString(CONTENT_SETTING_DEFAULT));
1002 // Calculate the zoom percent from the factor. Round up to the nearest whole
1003 // number.
1004 int zoom_percent = static_cast<int>(
1005 content::ZoomLevelToZoomFactor(i->zoom_level) * 100 + 0.5);
1006 exception->SetString(
1007 kZoom,
1008 l10n_util::GetStringFUTF16(IDS_ZOOM_PERCENT,
1009 base::IntToString16(zoom_percent)));
1010 exception->SetString(kSource, kPreferencesSource);
1011 // Append the new entry to the list and map.
1012 zoom_levels_exceptions.Append(exception.release());
1015 base::StringValue type_string(kZoomContentType);
1016 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
1017 type_string, zoom_levels_exceptions);
1020 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
1021 ContentSettingsType type) {
1022 base::ListValue exceptions;
1023 GetExceptionsFromHostContentSettingsMap(
1024 GetContentSettingsMap(), type, &exceptions);
1025 base::StringValue type_string(ContentSettingsTypeToGroupName(type));
1026 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
1027 exceptions);
1029 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
1031 // TODO(koz): The default for fullscreen is always 'ask'.
1032 // http://crbug.com/104683
1033 if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN)
1034 return;
1036 #if defined(OS_CHROMEOS)
1037 // Also the default for protected contents is managed in another place.
1038 if (type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER)
1039 return;
1040 #endif
1042 // The default may also have changed (we won't get a separate notification).
1043 // If it hasn't changed, this call will be harmless.
1044 UpdateSettingDefaultFromModel(type);
1047 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
1048 ContentSettingsType type) {
1049 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
1050 if (!otr_settings_map)
1051 return;
1052 base::ListValue exceptions;
1053 GetExceptionsFromHostContentSettingsMap(otr_settings_map, type, &exceptions);
1054 base::StringValue type_string(ContentSettingsTypeToGroupName(type));
1055 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
1056 type_string, exceptions);
1059 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
1060 const HostContentSettingsMap* map,
1061 ContentSettingsType type,
1062 base::ListValue* exceptions) {
1063 ContentSettingsForOneType entries;
1064 map->GetSettingsForOneType(type, std::string(), &entries);
1065 // Group settings by primary_pattern.
1066 AllPatternsSettings all_patterns_settings;
1067 for (ContentSettingsForOneType::iterator i = entries.begin();
1068 i != entries.end(); ++i) {
1069 // Don't add default settings.
1070 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
1071 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
1072 i->source != kPreferencesSource) {
1073 continue;
1076 // Off-the-record HostContentSettingsMap contains incognito content settings
1077 // as well as normal content settings. Here, we use the incongnito settings
1078 // only.
1079 if (map->is_off_the_record() && !i->incognito)
1080 continue;
1082 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
1083 [i->secondary_pattern] = i->setting;
1086 // Keep the exceptions sorted by provider so they will be displayed in
1087 // precedence order.
1088 std::vector<std::vector<base::Value*> > all_provider_exceptions;
1089 all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);
1091 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
1092 i != all_patterns_settings.end();
1093 ++i) {
1094 const ContentSettingsPattern& primary_pattern = i->first.first;
1095 const OnePatternSettings& one_settings = i->second;
1097 // The "parent" entry either has an identical primary and secondary pattern,
1098 // or has a wildcard secondary. The two cases are indistinguishable in the
1099 // UI.
1100 OnePatternSettings::const_iterator parent =
1101 one_settings.find(primary_pattern);
1102 if (parent == one_settings.end())
1103 parent = one_settings.find(ContentSettingsPattern::Wildcard());
1105 const std::string& source = i->first.second;
1106 std::vector<base::Value*>* this_provider_exceptions =
1107 &all_provider_exceptions.at(
1108 HostContentSettingsMap::GetProviderTypeFromSource(source));
1110 // Add the "parent" entry for the non-embedded setting.
1111 ContentSetting parent_setting =
1112 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
1113 const ContentSettingsPattern& secondary_pattern =
1114 parent == one_settings.end() ? primary_pattern : parent->first;
1115 this_provider_exceptions->push_back(GetExceptionForPage(primary_pattern,
1116 secondary_pattern,
1117 parent_setting,
1118 source));
1120 // Add the "children" for any embedded settings.
1121 for (OnePatternSettings::const_iterator j = one_settings.begin();
1122 j != one_settings.end(); ++j) {
1123 // Skip the non-embedded setting which we already added above.
1124 if (j == parent)
1125 continue;
1127 ContentSetting content_setting = j->second;
1128 this_provider_exceptions->push_back(GetExceptionForPage(
1129 primary_pattern,
1130 j->first,
1131 content_setting,
1132 source));
1136 for (size_t i = 0; i < all_provider_exceptions.size(); ++i) {
1137 for (size_t j = 0; j < all_provider_exceptions[i].size(); ++j) {
1138 exceptions->Append(all_provider_exceptions[i][j]);
1143 void ContentSettingsHandler::RemoveMediaException(const base::ListValue* args) {
1144 std::string mode;
1145 bool rv = args->GetString(1, &mode);
1146 DCHECK(rv);
1148 std::string pattern;
1149 rv = args->GetString(2, &pattern);
1150 DCHECK(rv);
1152 HostContentSettingsMap* settings_map =
1153 mode == "normal" ? GetContentSettingsMap() :
1154 GetOTRContentSettingsMap();
1155 if (settings_map) {
1156 settings_map->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern),
1157 ContentSettingsPattern::Wildcard(),
1158 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
1159 std::string(),
1160 NULL);
1161 settings_map->SetWebsiteSetting(ContentSettingsPattern::FromString(pattern),
1162 ContentSettingsPattern::Wildcard(),
1163 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
1164 std::string(),
1165 NULL);
1169 void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
1170 const base::ListValue* args,
1171 ContentSettingsType type) {
1172 std::string mode;
1173 bool rv = args->GetString(1, &mode);
1174 DCHECK(rv);
1176 std::string pattern;
1177 rv = args->GetString(2, &pattern);
1178 DCHECK(rv);
1180 // The fourth argument to this handler is optional.
1181 std::string secondary_pattern;
1182 if (args->GetSize() >= 4U) {
1183 rv = args->GetString(3, &secondary_pattern);
1184 DCHECK(rv);
1187 HostContentSettingsMap* settings_map =
1188 mode == "normal" ? GetContentSettingsMap() :
1189 GetOTRContentSettingsMap();
1190 if (settings_map) {
1191 settings_map->SetWebsiteSetting(
1192 ContentSettingsPattern::FromString(pattern),
1193 secondary_pattern.empty() ?
1194 ContentSettingsPattern::Wildcard() :
1195 ContentSettingsPattern::FromString(secondary_pattern),
1196 type,
1197 std::string(),
1198 NULL);
1202 void ContentSettingsHandler::RemoveZoomLevelException(
1203 const base::ListValue* args) {
1204 std::string mode;
1205 bool rv = args->GetString(1, &mode);
1206 DCHECK(rv);
1208 std::string pattern;
1209 rv = args->GetString(2, &pattern);
1210 DCHECK(rv);
1212 content::HostZoomMap* host_zoom_map =
1213 content::HostZoomMap::GetDefaultForBrowserContext(
1214 GetBrowserContext(web_ui()));
1215 double default_level = host_zoom_map->GetDefaultZoomLevel();
1216 host_zoom_map->SetZoomLevelForHost(pattern, default_level);
1219 void ContentSettingsHandler::RegisterMessages() {
1220 web_ui()->RegisterMessageCallback("setContentFilter",
1221 base::Bind(&ContentSettingsHandler::SetContentFilter,
1222 base::Unretained(this)));
1223 web_ui()->RegisterMessageCallback("removeException",
1224 base::Bind(&ContentSettingsHandler::RemoveException,
1225 base::Unretained(this)));
1226 web_ui()->RegisterMessageCallback("setException",
1227 base::Bind(&ContentSettingsHandler::SetException,
1228 base::Unretained(this)));
1229 web_ui()->RegisterMessageCallback("checkExceptionPatternValidity",
1230 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity,
1231 base::Unretained(this)));
1234 void ContentSettingsHandler::SetContentFilter(const base::ListValue* args) {
1235 DCHECK_EQ(2U, args->GetSize());
1236 std::string group, setting;
1237 if (!(args->GetString(0, &group) &&
1238 args->GetString(1, &setting))) {
1239 NOTREACHED();
1240 return;
1243 ContentSetting default_setting = ContentSettingFromString(setting);
1244 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
1245 Profile* profile = Profile::FromWebUI(web_ui());
1247 #if defined(OS_CHROMEOS)
1248 // ChromeOS special case : in Guest mode settings are opened in Incognito
1249 // mode, so we need original profile to actually modify settings.
1250 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
1251 profile = profile->GetOriginalProfile();
1252 #endif
1255 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
1256 map->SetDefaultContentSetting(content_type, default_setting);
1258 switch (content_type) {
1259 case CONTENT_SETTINGS_TYPE_COOKIES:
1260 content::RecordAction(
1261 UserMetricsAction("Options_DefaultCookieSettingChanged"));
1262 break;
1263 case CONTENT_SETTINGS_TYPE_IMAGES:
1264 content::RecordAction(
1265 UserMetricsAction("Options_DefaultImagesSettingChanged"));
1266 break;
1267 case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
1268 content::RecordAction(
1269 UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
1270 break;
1271 case CONTENT_SETTINGS_TYPE_PLUGINS:
1272 content::RecordAction(
1273 UserMetricsAction("Options_DefaultPluginsSettingChanged"));
1274 break;
1275 case CONTENT_SETTINGS_TYPE_POPUPS:
1276 content::RecordAction(
1277 UserMetricsAction("Options_DefaultPopupsSettingChanged"));
1278 break;
1279 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
1280 content::RecordAction(
1281 UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
1282 break;
1283 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
1284 content::RecordAction(
1285 UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
1286 break;
1287 case CONTENT_SETTINGS_TYPE_MOUSELOCK:
1288 content::RecordAction(
1289 UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
1290 break;
1291 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
1292 content::RecordAction(
1293 UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
1294 break;
1295 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
1296 content::RecordAction(
1297 UserMetricsAction("Options_DefaultMultipleAutomaticDLSettingChange"));
1298 break;
1299 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
1300 content::RecordAction(
1301 UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
1302 break;
1303 case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING:
1304 content::RecordAction(
1305 UserMetricsAction("Options_DefaultPushMessagingSettingChanged"));
1306 break;
1307 default:
1308 break;
1312 void ContentSettingsHandler::RemoveException(const base::ListValue* args) {
1313 std::string type_string;
1314 CHECK(args->GetString(0, &type_string));
1316 // Zoom levels are no actual content type so we need to handle them
1317 // separately. They would not be recognized by
1318 // ContentSettingsTypeFromGroupName.
1319 if (type_string == kZoomContentType) {
1320 RemoveZoomLevelException(args);
1321 return;
1324 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
1325 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM)
1326 RemoveMediaException(args);
1327 else
1328 RemoveExceptionFromHostContentSettingsMap(args, type);
1331 void ContentSettingsHandler::SetException(const base::ListValue* args) {
1332 std::string type_string;
1333 CHECK(args->GetString(0, &type_string));
1334 std::string mode;
1335 CHECK(args->GetString(1, &mode));
1336 std::string pattern;
1337 CHECK(args->GetString(2, &pattern));
1338 std::string setting;
1339 CHECK(args->GetString(3, &setting));
1341 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
1342 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
1343 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
1344 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
1345 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
1346 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
1347 NOTREACHED();
1348 } else {
1349 HostContentSettingsMap* settings_map =
1350 mode == "normal" ? GetContentSettingsMap() :
1351 GetOTRContentSettingsMap();
1353 // The settings map could be null if the mode was OTR but the OTR profile
1354 // got destroyed before we received this message.
1355 if (!settings_map)
1356 return;
1357 settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern),
1358 ContentSettingsPattern::Wildcard(),
1359 type,
1360 std::string(),
1361 ContentSettingFromString(setting));
1365 void ContentSettingsHandler::CheckExceptionPatternValidity(
1366 const base::ListValue* args) {
1367 std::string type_string;
1368 CHECK(args->GetString(0, &type_string));
1369 std::string mode_string;
1370 CHECK(args->GetString(1, &mode_string));
1371 std::string pattern_string;
1372 CHECK(args->GetString(2, &pattern_string));
1374 ContentSettingsPattern pattern =
1375 ContentSettingsPattern::FromString(pattern_string);
1377 web_ui()->CallJavascriptFunction(
1378 "ContentSettings.patternValidityCheckComplete",
1379 base::StringValue(type_string),
1380 base::StringValue(mode_string),
1381 base::StringValue(pattern_string),
1382 base::FundamentalValue(pattern.IsValid()));
1385 // static
1386 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
1387 ContentSettingsType type) {
1388 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
1389 if (type == kContentSettingsTypeGroupNames[i].type)
1390 return kContentSettingsTypeGroupNames[i].name;
1393 NOTREACHED();
1394 return std::string();
1397 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
1398 return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap();
1401 ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() {
1402 return ProtocolHandlerRegistryFactory::GetForBrowserContext(
1403 GetBrowserContext(web_ui()));
1406 HostContentSettingsMap*
1407 ContentSettingsHandler::GetOTRContentSettingsMap() {
1408 Profile* profile = Profile::FromWebUI(web_ui());
1409 if (profile->HasOffTheRecordProfile())
1410 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
1411 return NULL;
1414 void ContentSettingsHandler::RefreshFlashMediaSettings() {
1415 media_settings_.flash_settings_initialized = false;
1417 media_settings_.last_flash_refresh_request_id =
1418 flash_settings_manager_->GetPermissionSettings(
1419 PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC);
1422 void ContentSettingsHandler::OnPepperFlashPrefChanged() {
1423 ShowFlashMediaLink(DEFAULT_SETTING, false);
1424 ShowFlashMediaLink(EXCEPTIONS, false);
1426 PrefService* prefs = user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
1427 if (prefs->GetBoolean(prefs::kPepperFlashSettingsEnabled))
1428 RefreshFlashMediaSettings();
1429 else
1430 media_settings_.flash_settings_initialized = false;
1433 void ContentSettingsHandler::OnZoomLevelChanged(
1434 const content::HostZoomMap::ZoomLevelChange& change) {
1435 UpdateZoomLevelsExceptionsView();
1438 void ContentSettingsHandler::ShowFlashMediaLink(LinkType link_type, bool show) {
1439 bool& show_link = link_type == DEFAULT_SETTING ?
1440 media_settings_.show_flash_default_link :
1441 media_settings_.show_flash_exceptions_link;
1442 if (show_link != show) {
1443 web_ui()->CallJavascriptFunction(
1444 link_type == DEFAULT_SETTING ?
1445 "ContentSettings.showMediaPepperFlashDefaultLink" :
1446 "ContentSettings.showMediaPepperFlashExceptionsLink",
1447 base::FundamentalValue(show));
1448 show_link = show;
1452 void ContentSettingsHandler::UpdateFlashMediaLinksVisibility() {
1453 if (!media_settings_.flash_settings_initialized ||
1454 !media_settings_.default_setting_initialized ||
1455 !media_settings_.exceptions_initialized) {
1456 return;
1459 // Flash won't send us notifications when its settings get changed, which
1460 // means the Flash settings in |media_settings_| may be out-dated, especially
1461 // after we show links to change Flash settings.
1462 // In order to avoid confusion, we won't hide the links once they are showed.
1463 // One exception is that we will hide them when Pepper Flash is disabled
1464 // (handled in OnPepperFlashPrefChanged()).
1465 if (media_settings_.show_flash_default_link &&
1466 media_settings_.show_flash_exceptions_link) {
1467 return;
1470 if (!media_settings_.show_flash_default_link) {
1471 // If both audio and video capture are disabled by policy, the link
1472 // shouldn't be showed. Flash conforms to the policy in this case because
1473 // it cannot open those devices. We don't have to look at the Flash
1474 // settings.
1475 if (!(media_settings_.policy_disable_audio &&
1476 media_settings_.policy_disable_video) &&
1477 media_settings_.flash_default_setting !=
1478 media_settings_.default_setting) {
1479 ShowFlashMediaLink(DEFAULT_SETTING, true);
1482 if (!media_settings_.show_flash_exceptions_link) {
1483 // If audio or video capture is disabled by policy, we skip comparison of
1484 // exceptions for audio or video capture, respectively.
1485 if (!PepperFlashContentSettingsUtils::AreMediaExceptionsEqual(
1486 media_settings_.default_setting,
1487 media_settings_.exceptions,
1488 media_settings_.flash_default_setting,
1489 media_settings_.flash_exceptions,
1490 media_settings_.policy_disable_audio,
1491 media_settings_.policy_disable_video)) {
1492 ShowFlashMediaLink(EXCEPTIONS, true);
1497 void ContentSettingsHandler::UpdateProtectedContentExceptionsButton() {
1498 #if defined(OS_CHROMEOS)
1499 // Guests cannot modify exceptions. UIAccountTweaks will disabled the button.
1500 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
1501 return;
1502 #endif
1504 // Exceptions apply only when the feature is enabled.
1505 PrefService* prefs = user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
1506 bool enable_exceptions = prefs->GetBoolean(prefs::kEnableDRM);
1507 web_ui()->CallJavascriptFunction(
1508 "ContentSettings.enableProtectedContentExceptions",
1509 base::FundamentalValue(enable_exceptions));
1512 } // namespace options