Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / content_settings_handler.cc
blobb5eccc44f0ae983e8a8b730908016182e2c40c52
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/logging.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/values.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/chrome_notification_types.h"
21 #include "chrome/browser/content_settings/web_site_settings_uma_util.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/browser/content_settings_utils.h"
36 #include "components/content_settings/core/browser/host_content_settings_map.h"
37 #include "components/content_settings/core/browser/plugins_field_trial.h"
38 #include "components/content_settings/core/browser/website_settings_info.h"
39 #include "components/content_settings/core/browser/website_settings_registry.h"
40 #include "components/content_settings/core/common/content_settings.h"
41 #include "components/content_settings/core/common/content_settings_pattern.h"
42 #include "components/google/core/browser/google_util.h"
43 #include "components/signin/core/common/profile_management_switches.h"
44 #include "components/user_prefs/user_prefs.h"
45 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/notification_source.h"
47 #include "content/public/browser/notification_types.h"
48 #include "content/public/browser/storage_partition.h"
49 #include "content/public/browser/user_metrics.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/browser/web_ui.h"
52 #include "content/public/common/content_switches.h"
53 #include "content/public/common/page_zoom.h"
54 #include "content/public/common/url_constants.h"
55 #include "extensions/browser/extension_registry.h"
56 #include "extensions/common/extension_set.h"
57 #include "extensions/common/permissions/api_permission.h"
58 #include "extensions/common/permissions/permissions_data.h"
59 #include "ui/base/l10n/l10n_util.h"
61 #if defined(OS_CHROMEOS)
62 #include "components/user_manager/user_manager.h"
63 #endif
65 using base::UserMetricsAction;
66 using content_settings::ContentSettingToString;
67 using content_settings::ContentSettingFromString;
68 using extensions::APIPermission;
70 namespace {
72 struct ContentSettingsTypeNameEntry {
73 ContentSettingsType type;
74 const char* name;
77 // Maps from a secondary pattern to a setting.
78 typedef std::map<ContentSettingsPattern, ContentSetting>
79 OnePatternSettings;
80 // Maps from a primary pattern/source pair to a OnePatternSettings. All the
81 // mappings in OnePatternSettings share the given primary pattern and source.
82 typedef std::map<std::pair<ContentSettingsPattern, std::string>,
83 OnePatternSettings>
84 AllPatternsSettings;
86 // The AppFilter is used in AddExceptionsGrantedByHostedApps() to choose
87 // extensions which should have their extent displayed.
88 typedef bool (*AppFilter)(const extensions::Extension& app,
89 content::BrowserContext* profile);
91 const char kExceptionsLearnMoreUrl[] =
92 "https://support.google.com/chrome/?p=settings_manage_exceptions";
94 const char kSetting[] = "setting";
95 const char kOrigin[] = "origin";
96 const char kPolicyProviderId[] = "policy";
97 const char kSource[] = "source";
98 const char kAppName[] = "appName";
99 const char kAppId[] = "appId";
100 const char kEmbeddingOrigin[] = "embeddingOrigin";
101 const char kPreferencesSource[] = "preference";
102 const char kZoom[] = "zoom";
104 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = {
105 {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"},
106 {CONTENT_SETTINGS_TYPE_IMAGES, "images"},
107 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"},
108 {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"},
109 {CONTENT_SETTINGS_TYPE_POPUPS, "popups"},
110 {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"},
111 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"},
112 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"},
113 {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"},
114 {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"},
115 {CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS, "register-protocol-handler"},
116 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, "media-stream-mic"},
117 {CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, "media-stream-camera"},
118 {CONTENT_SETTINGS_TYPE_PPAPI_BROKER, "ppapi-broker"},
119 {CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS, "multiple-automatic-downloads"},
120 {CONTENT_SETTINGS_TYPE_MIDI_SYSEX, "midi-sysex"},
121 {CONTENT_SETTINGS_TYPE_PUSH_MESSAGING, "push-messaging"},
122 {CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, "ssl-cert-decisions"},
123 #if defined(OS_CHROMEOS)
124 {CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER, "protectedContent"},
125 #endif
128 // A pseudo content type. We use it to display data like a content setting even
129 // though it is not a real content setting.
130 const char kZoomContentType[] = "zoomlevels";
132 content::BrowserContext* GetBrowserContext(content::WebUI* web_ui) {
133 return web_ui->GetWebContents()->GetBrowserContext();
136 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) {
137 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
138 if (name == kContentSettingsTypeGroupNames[i].name)
139 return kContentSettingsTypeGroupNames[i].type;
142 NOTREACHED() << name << " is not a recognized content settings type.";
143 return CONTENT_SETTINGS_TYPE_DEFAULT;
146 // Create a DictionaryValue* that will act as a data source for a single row
147 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies).
148 scoped_ptr<base::DictionaryValue> GetExceptionForPage(
149 const ContentSettingsPattern& pattern,
150 const ContentSettingsPattern& secondary_pattern,
151 const ContentSetting& setting,
152 const std::string& provider_name) {
153 base::DictionaryValue* exception = new base::DictionaryValue();
154 exception->SetString(kOrigin, pattern.ToString());
155 exception->SetString(kEmbeddingOrigin,
156 secondary_pattern == ContentSettingsPattern::Wildcard() ?
157 std::string() :
158 secondary_pattern.ToString());
159 exception->SetString(kSetting, ContentSettingToString(setting));
160 exception->SetString(kSource, provider_name);
161 return make_scoped_ptr(exception);
164 // Create a DictionaryValue* that will act as a data source for a single row
165 // in the Geolocation exceptions table.
166 scoped_ptr<base::DictionaryValue> GetGeolocationExceptionForPage(
167 const ContentSettingsPattern& origin,
168 const ContentSettingsPattern& embedding_origin,
169 ContentSetting setting) {
170 base::DictionaryValue* exception = new base::DictionaryValue();
171 exception->SetString(kSetting, ContentSettingToString(setting));
172 exception->SetString(kOrigin, origin.ToString());
173 exception->SetString(kEmbeddingOrigin, embedding_origin.ToString());
174 return make_scoped_ptr(exception);
177 // Create a DictionaryValue* that will act as a data source for a single row
178 // in the desktop notifications exceptions table.
179 scoped_ptr<base::DictionaryValue> GetNotificationExceptionForPage(
180 const ContentSettingsPattern& primary_pattern,
181 const ContentSettingsPattern& secondary_pattern,
182 ContentSetting setting,
183 const std::string& provider_name) {
184 std::string embedding_origin;
185 if (secondary_pattern != ContentSettingsPattern::Wildcard())
186 embedding_origin = secondary_pattern.ToString();
188 base::DictionaryValue* exception = new base::DictionaryValue();
189 exception->SetString(kSetting, ContentSettingToString(setting));
190 exception->SetString(kOrigin, primary_pattern.ToString());
191 exception->SetString(kEmbeddingOrigin, embedding_origin);
192 exception->SetString(kSource, provider_name);
193 return make_scoped_ptr(exception);
196 // Returns true whenever the |extension| is hosted and has |permission|.
197 // Must have the AppFilter signature.
198 template <APIPermission::ID permission>
199 bool HostedAppHasPermission(const extensions::Extension& extension,
200 content::BrowserContext* /* context */) {
201 return extension.is_hosted_app() &&
202 extension.permissions_data()->HasAPIPermission(permission);
205 // Add an "Allow"-entry to the list of |exceptions| for a |url_pattern| from
206 // the web extent of a hosted |app|.
207 void AddExceptionForHostedApp(const std::string& url_pattern,
208 const extensions::Extension& app, base::ListValue* exceptions) {
209 base::DictionaryValue* exception = new base::DictionaryValue();
210 exception->SetString(kSetting, ContentSettingToString(CONTENT_SETTING_ALLOW));
211 exception->SetString(kOrigin, url_pattern);
212 exception->SetString(kEmbeddingOrigin, url_pattern);
213 exception->SetString(kSource, "HostedApp");
214 exception->SetString(kAppName, app.name());
215 exception->SetString(kAppId, app.id());
216 exceptions->Append(exception);
219 // Asks the |profile| for hosted apps which have the |permission| set, and
220 // adds their web extent and launch URL to the |exceptions| list.
221 void AddExceptionsGrantedByHostedApps(content::BrowserContext* context,
222 AppFilter app_filter,
223 base::ListValue* exceptions) {
224 const extensions::ExtensionSet& extensions =
225 extensions::ExtensionRegistry::Get(context)->enabled_extensions();
226 for (extensions::ExtensionSet::const_iterator extension = extensions.begin();
227 extension != extensions.end(); ++extension) {
228 if (!app_filter(*extension->get(), context))
229 continue;
231 extensions::URLPatternSet web_extent = (*extension)->web_extent();
232 // Add patterns from web extent.
233 for (extensions::URLPatternSet::const_iterator pattern = web_extent.begin();
234 pattern != web_extent.end(); ++pattern) {
235 std::string url_pattern = pattern->GetAsString();
236 AddExceptionForHostedApp(url_pattern, *extension->get(), exceptions);
238 // Retrieve the launch URL.
239 GURL launch_url =
240 extensions::AppLaunchInfo::GetLaunchWebURL(extension->get());
241 // Skip adding the launch URL if it is part of the web extent.
242 if (web_extent.MatchesURL(launch_url))
243 continue;
244 AddExceptionForHostedApp(launch_url.spec(), *extension->get(), exceptions);
248 } // namespace
250 namespace options {
252 ContentSettingsHandler::MediaSettingsInfo::MediaSettingsInfo() {
255 ContentSettingsHandler::MediaSettingsInfo::~MediaSettingsInfo() {
258 ContentSettingsHandler::MediaSettingsInfo::ForFlash::ForFlash()
259 : default_setting(CONTENT_SETTING_DEFAULT),
260 initialized(false),
261 last_refresh_request_id(0) {
264 ContentSettingsHandler::MediaSettingsInfo::ForFlash::~ForFlash() {
267 ContentSettingsHandler::MediaSettingsInfo::ForFlash&
268 ContentSettingsHandler::MediaSettingsInfo::forFlash() {
269 return flash_settings_;
272 ContentSettingsHandler::MediaSettingsInfo::ForOneType&
273 ContentSettingsHandler::MediaSettingsInfo::forType(
274 ContentSettingsType type) {
275 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)
276 return mic_settings_;
277 else if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)
278 return camera_settings_;
280 NOTREACHED();
281 return mic_settings_;
284 ContentSettingsHandler::MediaSettingsInfo::ForOneType::ForOneType()
285 : show_flash_default_link(false),
286 show_flash_exceptions_link(false),
287 default_setting(CONTENT_SETTING_DEFAULT),
288 policy_disable(false),
289 default_setting_initialized(false),
290 exceptions_initialized(false) {
293 ContentSettingsHandler::MediaSettingsInfo::ForOneType::~ForOneType() {
296 ContentSettingsHandler::ContentSettingsHandler() : observer_(this) {
299 ContentSettingsHandler::~ContentSettingsHandler() {
302 void ContentSettingsHandler::GetLocalizedValues(
303 base::DictionaryValue* localized_strings) {
304 DCHECK(localized_strings);
306 static OptionsStringResource resources[] = {
307 {"allowException", IDS_EXCEPTIONS_ALLOW_BUTTON},
308 {"blockException", IDS_EXCEPTIONS_BLOCK_BUTTON},
309 {"sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON},
310 {"detectException", IDS_EXCEPTIONS_DETECT_IMPORTANT_CONTENT_BUTTON},
311 {"askException", IDS_EXCEPTIONS_ASK_BUTTON},
312 {"otrExceptionsExplanation", IDS_EXCEPTIONS_OTR_LABEL},
313 {"addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS},
314 {"manageExceptions", IDS_EXCEPTIONS_MANAGE},
315 {"manageHandlers", IDS_HANDLERS_MANAGE},
316 {"exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER},
317 {"exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER},
318 {"exceptionZoomHeader", IDS_EXCEPTIONS_ZOOM_HEADER},
319 {"embeddedOnHost", IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST},
320 // Cookies filter.
321 {"cookiesTabLabel", IDS_COOKIES_TAB_LABEL},
322 {"cookiesHeader", IDS_COOKIES_HEADER},
323 {"cookiesAllow", IDS_COOKIES_ALLOW_RADIO},
324 {"cookiesBlock", IDS_COOKIES_BLOCK_RADIO},
325 {"cookiesSession", IDS_COOKIES_SESSION_ONLY_RADIO},
326 {"cookiesBlock3rdParty", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX},
327 {"cookiesShowCookies", IDS_COOKIES_SHOW_COOKIES_BUTTON},
328 {"flashStorageSettings", IDS_FLASH_STORAGE_SETTINGS},
329 {"flashStorageUrl", IDS_FLASH_STORAGE_URL},
330 #if defined(ENABLE_GOOGLE_NOW)
331 {"googleGeolocationAccessEnable",
332 IDS_GEOLOCATION_GOOGLE_ACCESS_ENABLE_CHKBOX},
333 #endif
334 // Image filter.
335 {"imagesTabLabel", IDS_IMAGES_TAB_LABEL},
336 {"imagesHeader", IDS_IMAGES_HEADER},
337 {"imagesAllow", IDS_IMAGES_LOAD_RADIO},
338 {"imagesBlock", IDS_IMAGES_NOLOAD_RADIO},
339 // JavaScript filter.
340 {"javascriptTabLabel", IDS_JAVASCRIPT_TAB_LABEL},
341 {"javascriptHeader", IDS_JAVASCRIPT_HEADER},
342 {"javascriptAllow", IDS_JS_ALLOW_RADIO},
343 {"javascriptBlock", IDS_JS_DONOTALLOW_RADIO},
344 // Plugins filter.
345 {"pluginsTabLabel", IDS_PLUGIN_TAB_LABEL},
346 {"pluginsHeader", IDS_PLUGIN_HEADER},
347 {"pluginsAllow", IDS_PLUGIN_ALLOW_RADIO},
348 {"pluginsBlock", IDS_PLUGIN_BLOCK_RADIO},
349 {"manageIndividualPlugins", IDS_PLUGIN_MANAGE_INDIVIDUAL},
350 // Pop-ups filter.
351 {"popupsTabLabel", IDS_POPUP_TAB_LABEL},
352 {"popupsHeader", IDS_POPUP_HEADER},
353 {"popupsAllow", IDS_POPUP_ALLOW_RADIO},
354 {"popupsBlock", IDS_POPUP_BLOCK_RADIO},
355 // Location filter.
356 {"locationTabLabel", IDS_GEOLOCATION_TAB_LABEL},
357 {"locationHeader", IDS_GEOLOCATION_HEADER},
358 {"locationAllow", IDS_GEOLOCATION_ALLOW_RADIO},
359 {"locationAsk", IDS_GEOLOCATION_ASK_RADIO},
360 {"locationBlock", IDS_GEOLOCATION_BLOCK_RADIO},
361 {"setBy", IDS_GEOLOCATION_SET_BY_HOVER},
362 // Notifications filter.
363 {"notificationsTabLabel", IDS_NOTIFICATIONS_TAB_LABEL},
364 {"notificationsHeader", IDS_NOTIFICATIONS_HEADER},
365 {"notificationsAllow", IDS_NOTIFICATIONS_ALLOW_RADIO},
366 {"notificationsAsk", IDS_NOTIFICATIONS_ASK_RADIO},
367 {"notificationsBlock", IDS_NOTIFICATIONS_BLOCK_RADIO},
368 // Fullscreen filter.
369 {"fullscreenTabLabel", IDS_FULLSCREEN_TAB_LABEL},
370 {"fullscreenHeader", IDS_FULLSCREEN_HEADER},
371 // Mouse Lock filter.
372 {"mouselockTabLabel", IDS_MOUSE_LOCK_TAB_LABEL},
373 {"mouselockHeader", IDS_MOUSE_LOCK_HEADER},
374 {"mouselockAllow", IDS_MOUSE_LOCK_ALLOW_RADIO},
375 {"mouselockAsk", IDS_MOUSE_LOCK_ASK_RADIO},
376 {"mouselockBlock", IDS_MOUSE_LOCK_BLOCK_RADIO},
377 #if defined(OS_CHROMEOS) || defined(OS_WIN)
378 // Protected Content filter
379 {"protectedContentTabLabel", IDS_PROTECTED_CONTENT_TAB_LABEL},
380 {"protectedContentInfo", IDS_PROTECTED_CONTENT_INFO},
381 {"protectedContentEnable", IDS_PROTECTED_CONTENT_ENABLE},
382 {"protectedContentHeader", IDS_PROTECTED_CONTENT_HEADER},
383 #endif // defined(OS_CHROMEOS) || defined(OS_WIN)
384 // Microphone filter.
385 {"mediaStreamMicTabLabel", IDS_MEDIA_STREAM_MIC_TAB_LABEL},
386 {"mediaStreamMicHeader", IDS_MEDIA_STREAM_MIC_HEADER},
387 {"mediaStreamMicAsk", IDS_MEDIA_STREAM_ASK_AUDIO_ONLY_RADIO},
388 {"mediaStreamMicBlock", IDS_MEDIA_STREAM_BLOCK_AUDIO_ONLY_RADIO},
389 // Camera filter.
390 {"mediaStreamCameraTabLabel", IDS_MEDIA_STREAM_CAMERA_TAB_LABEL},
391 {"mediaStreamCameraHeader", IDS_MEDIA_STREAM_CAMERA_HEADER},
392 {"mediaStreamCameraAsk", IDS_MEDIA_STREAM_ASK_VIDEO_ONLY_RADIO},
393 {"mediaStreamCameraBlock", IDS_MEDIA_STREAM_BLOCK_VIDEO_ONLY_RADIO},
394 // Flash media settings.
395 {"mediaPepperFlashMicDefaultDivergedLabel",
396 IDS_MEDIA_PEPPER_FLASH_MIC_DEFAULT_DIVERGED_LABEL},
397 {"mediaPepperFlashCameraDefaultDivergedLabel",
398 IDS_MEDIA_PEPPER_FLASH_CAMERA_DEFAULT_DIVERGED_LABEL},
399 {"mediaPepperFlashMicExceptionsDivergedLabel",
400 IDS_MEDIA_PEPPER_FLASH_MIC_EXCEPTIONS_DIVERGED_LABEL},
401 {"mediaPepperFlashCameraExceptionsDivergedLabel",
402 IDS_MEDIA_PEPPER_FLASH_CAMERA_EXCEPTIONS_DIVERGED_LABEL},
403 {"mediaPepperFlashChangeLink", IDS_MEDIA_PEPPER_FLASH_CHANGE_LINK},
404 {"mediaPepperFlashGlobalPrivacyURL", IDS_FLASH_GLOBAL_PRIVACY_URL},
405 {"mediaPepperFlashWebsitePrivacyURL", IDS_FLASH_WEBSITE_PRIVACY_URL},
406 // PPAPI broker filter.
407 {"ppapiBrokerHeader", IDS_PPAPI_BROKER_HEADER},
408 {"ppapiBrokerTabLabel", IDS_PPAPI_BROKER_TAB_LABEL},
409 {"ppapiBrokerAllow", IDS_PPAPI_BROKER_ALLOW_RADIO},
410 {"ppapiBrokerAsk", IDS_PPAPI_BROKER_ASK_RADIO},
411 {"ppapiBrokerBlock", IDS_PPAPI_BROKER_BLOCK_RADIO},
412 // Multiple automatic downloads
413 {"multipleAutomaticDownloadsTabLabel", IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL},
414 {"multipleAutomaticDownloadsHeader", IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL},
415 {"multipleAutomaticDownloadsAllow", IDS_AUTOMATIC_DOWNLOADS_ALLOW_RADIO},
416 {"multipleAutomaticDownloadsAsk", IDS_AUTOMATIC_DOWNLOADS_ASK_RADIO},
417 {"multipleAutomaticDownloadsBlock", IDS_AUTOMATIC_DOWNLOADS_BLOCK_RADIO},
418 // MIDI system exclusive messages
419 {"midiSysexHeader", IDS_MIDI_SYSEX_TAB_LABEL},
420 {"midiSysExAllow", IDS_MIDI_SYSEX_ALLOW_RADIO},
421 {"midiSysExAsk", IDS_MIDI_SYSEX_ASK_RADIO},
422 {"midiSysExBlock", IDS_MIDI_SYSEX_BLOCK_RADIO},
423 // Push messaging strings
424 {"pushMessagingHeader", IDS_PUSH_MESSAGES_TAB_LABEL},
425 {"pushMessagingAllow", IDS_PUSH_MESSSAGING_ALLOW_RADIO},
426 {"pushMessagingAsk", IDS_PUSH_MESSSAGING_ASK_RADIO},
427 {"pushMessagingBlock", IDS_PUSH_MESSSAGING_BLOCK_RADIO},
428 {"zoomlevelsHeader", IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL},
429 {"zoomLevelsManage", IDS_ZOOMLEVELS_MANAGE_BUTTON},
432 RegisterStrings(localized_strings, resources, arraysize(resources));
434 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
435 const base::Value* default_pref = prefs->GetDefaultPrefValue(
436 content_settings::WebsiteSettingsRegistry::GetInstance()
437 ->Get(CONTENT_SETTINGS_TYPE_PLUGINS)
438 ->default_value_pref_name());
440 int default_value = CONTENT_SETTING_DEFAULT;
441 bool success = default_pref->GetAsInteger(&default_value);
442 DCHECK(success);
443 DCHECK_NE(default_value, CONTENT_SETTING_DEFAULT);
445 int plugin_ids = default_value == CONTENT_SETTING_DETECT_IMPORTANT_CONTENT ?
446 IDS_PLUGIN_DETECT_RECOMMENDED_RADIO : IDS_PLUGIN_DETECT_RADIO;
447 localized_strings->SetString("pluginsDetect",
448 l10n_util::GetStringUTF16(plugin_ids));
450 RegisterTitle(localized_strings, "contentSettingsPage",
451 IDS_CONTENT_SETTINGS_TITLE);
453 // Register titles for each of the individual settings whose exception
454 // dialogs will be processed by |ContentSettingsHandler|.
455 RegisterTitle(localized_strings, "cookies",
456 IDS_COOKIES_TAB_LABEL);
457 RegisterTitle(localized_strings, "images",
458 IDS_IMAGES_TAB_LABEL);
459 RegisterTitle(localized_strings, "javascript",
460 IDS_JAVASCRIPT_TAB_LABEL);
461 RegisterTitle(localized_strings, "plugins",
462 IDS_PLUGIN_TAB_LABEL);
463 RegisterTitle(localized_strings, "popups",
464 IDS_POPUP_TAB_LABEL);
465 RegisterTitle(localized_strings, "location",
466 IDS_GEOLOCATION_TAB_LABEL);
467 RegisterTitle(localized_strings, "notifications",
468 IDS_NOTIFICATIONS_TAB_LABEL);
469 RegisterTitle(localized_strings, "fullscreen",
470 IDS_FULLSCREEN_TAB_LABEL);
471 RegisterTitle(localized_strings, "mouselock",
472 IDS_MOUSE_LOCK_TAB_LABEL);
473 #if defined(OS_CHROMEOS)
474 RegisterTitle(localized_strings, "protectedContent",
475 IDS_PROTECTED_CONTENT_TAB_LABEL);
476 #endif
477 RegisterTitle(localized_strings, "media-stream-mic",
478 IDS_MEDIA_STREAM_MIC_TAB_LABEL);
479 RegisterTitle(localized_strings, "media-stream-camera",
480 IDS_MEDIA_STREAM_CAMERA_TAB_LABEL);
481 RegisterTitle(localized_strings, "ppapi-broker",
482 IDS_PPAPI_BROKER_TAB_LABEL);
483 RegisterTitle(localized_strings, "multiple-automatic-downloads",
484 IDS_AUTOMATIC_DOWNLOADS_TAB_LABEL);
485 RegisterTitle(localized_strings, "midi-sysex",
486 IDS_MIDI_SYSEX_TAB_LABEL);
487 RegisterTitle(localized_strings, "zoomlevels",
488 IDS_ZOOMLEVELS_HEADER_AND_TAB_LABEL);
490 localized_strings->SetString("exceptionsLearnMoreUrl",
491 kExceptionsLearnMoreUrl);
494 void ContentSettingsHandler::InitializeHandler() {
495 notification_registrar_.Add(
496 this, chrome::NOTIFICATION_PROFILE_CREATED,
497 content::NotificationService::AllSources());
498 notification_registrar_.Add(
499 this, chrome::NOTIFICATION_PROFILE_DESTROYED,
500 content::NotificationService::AllSources());
502 content::BrowserContext* context = GetBrowserContext(web_ui());
503 notification_registrar_.Add(
504 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED,
505 content::Source<content::BrowserContext>(context));
507 PrefService* prefs = user_prefs::UserPrefs::Get(context);
508 pref_change_registrar_.Init(prefs);
509 pref_change_registrar_.Add(
510 prefs::kPepperFlashSettingsEnabled,
511 base::Bind(&ContentSettingsHandler::OnPepperFlashPrefChanged,
512 base::Unretained(this)));
513 pref_change_registrar_.Add(
514 prefs::kAudioCaptureAllowed,
515 base::Bind(&ContentSettingsHandler::UpdateSettingDefaultFromModel,
516 base::Unretained(this),
517 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC));
518 pref_change_registrar_.Add(
519 prefs::kAudioCaptureAllowedUrls,
520 base::Bind(&ContentSettingsHandler::UpdateExceptionsViewFromModel,
521 base::Unretained(this),
522 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC));
523 pref_change_registrar_.Add(
524 prefs::kVideoCaptureAllowed,
525 base::Bind(&ContentSettingsHandler::UpdateSettingDefaultFromModel,
526 base::Unretained(this),
527 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA));
528 pref_change_registrar_.Add(
529 prefs::kVideoCaptureAllowedUrls,
530 base::Bind(&ContentSettingsHandler::UpdateExceptionsViewFromModel,
531 base::Unretained(this),
532 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA));
533 pref_change_registrar_.Add(
534 prefs::kEnableDRM,
535 base::Bind(
536 &ContentSettingsHandler::UpdateProtectedContentExceptionsButton,
537 base::Unretained(this)));
539 // Here we only subscribe to the HostZoomMap for the default storage partition
540 // since we don't allow the user to manage the zoom levels for apps.
541 // We're only interested in zoom-levels that are persisted, since the user
542 // is given the opportunity to view/delete these in the content-settings page.
543 host_zoom_map_subscription_ =
544 content::HostZoomMap::GetDefaultForBrowserContext(context)
545 ->AddZoomLevelChangedCallback(
546 base::Bind(&ContentSettingsHandler::OnZoomLevelChanged,
547 base::Unretained(this)));
549 if (!switches::IsEnableWebviewBasedSignin()) {
550 // The legacy signin page uses a different storage partition, so we need to
551 // add a subscription for its HostZoomMap separately.
552 GURL signin_url(chrome::kChromeUIChromeSigninURL);
553 content::StoragePartition* signin_partition =
554 content::BrowserContext::GetStoragePartitionForSite(
555 GetBrowserContext(web_ui()), signin_url);
556 content::HostZoomMap* signin_host_zoom_map =
557 signin_partition->GetHostZoomMap();
558 signin_host_zoom_map_subscription_ =
559 signin_host_zoom_map->AddZoomLevelChangedCallback(
560 base::Bind(&ContentSettingsHandler::OnZoomLevelChanged,
561 base::Unretained(this)));
564 flash_settings_manager_.reset(new PepperFlashSettingsManager(this, context));
566 Profile* profile = Profile::FromWebUI(web_ui());
567 observer_.Add(profile->GetHostContentSettingsMap());
568 if (profile->HasOffTheRecordProfile()) {
569 auto map = profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
570 if (!observer_.IsObserving(map))
571 observer_.Add(map);
575 void ContentSettingsHandler::InitializePage() {
576 media_settings_.reset(new MediaSettingsInfo());
577 RefreshFlashMediaSettings();
579 UpdateHandlersEnabledRadios();
580 UpdateAllExceptionsViewsFromModel();
581 UpdateProtectedContentExceptionsButton();
584 void ContentSettingsHandler::OnContentSettingChanged(
585 const ContentSettingsPattern& primary_pattern,
586 const ContentSettingsPattern& secondary_pattern,
587 ContentSettingsType content_type,
588 std::string resource_identifier) {
589 const ContentSettingsDetails details(
590 primary_pattern, secondary_pattern, content_type, resource_identifier);
591 // TODO(estade): we pretend update_all() is always true.
592 if (details.update_all_types())
593 UpdateAllExceptionsViewsFromModel();
594 else
595 UpdateExceptionsViewFromModel(details.type());
598 void ContentSettingsHandler::Observe(
599 int type,
600 const content::NotificationSource& source,
601 const content::NotificationDetails& details) {
602 switch (type) {
603 case chrome::NOTIFICATION_PROFILE_DESTROYED: {
604 Profile* profile = content::Source<Profile>(source).ptr();
605 if (profile->IsOffTheRecord() &&
606 observer_.IsObserving(profile->GetHostContentSettingsMap())) {
607 web_ui()->CallJavascriptFunction(
608 "ContentSettingsExceptionsArea.OTRProfileDestroyed");
609 observer_.Remove(profile->GetHostContentSettingsMap());
611 break;
614 case chrome::NOTIFICATION_PROFILE_CREATED: {
615 Profile* profile = content::Source<Profile>(source).ptr();
616 if (profile->IsOffTheRecord()) {
617 UpdateAllOTRExceptionsViewsFromModel();
618 observer_.Add(profile->GetHostContentSettingsMap());
620 break;
623 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: {
624 UpdateHandlersEnabledRadios();
625 break;
630 void ContentSettingsHandler::OnGetPermissionSettingsCompleted(
631 uint32 request_id,
632 bool success,
633 PP_Flash_BrowserOperations_Permission default_permission,
634 const ppapi::FlashSiteSettings& sites) {
635 MediaSettingsInfo::ForFlash& settings = media_settings_->forFlash();
636 if (success && request_id == settings.last_refresh_request_id) {
637 settings.initialized = true;
638 settings.default_setting =
639 PepperFlashContentSettingsUtils::FlashPermissionToContentSetting(
640 default_permission);
641 PepperFlashContentSettingsUtils::FlashSiteSettingsToMediaExceptions(
642 sites, &settings.exceptions);
643 PepperFlashContentSettingsUtils::SortMediaExceptions(
644 &settings.exceptions);
646 UpdateFlashMediaLinksVisibility(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
647 UpdateFlashMediaLinksVisibility(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
651 void ContentSettingsHandler::UpdateSettingDefaultFromModel(
652 ContentSettingsType type) {
653 std::string provider_id;
654 ContentSetting default_setting =
655 GetContentSettingsMap()->GetDefaultContentSetting(type, &provider_id);
657 #if defined(ENABLE_PLUGINS)
658 default_setting =
659 content_settings::PluginsFieldTrial::EffectiveContentSetting(
660 type, default_setting);
661 #endif
663 // Camera and microphone default content settings cannot be set by the policy.
664 // However, the policy can disable them. Treat this case visually in the same
665 // way as if the policy set the default setting to BLOCK. Furthermore, compare
666 // the settings with Flash settings and show links to the Flash settings site
667 // if they differ.
668 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
669 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
670 UpdateMediaSettingsFromPrefs(type);
671 if (media_settings_->forType(type).policy_disable) {
672 default_setting = CONTENT_SETTING_BLOCK;
673 provider_id = kPolicyProviderId;
677 base::DictionaryValue filter_settings;
678 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value",
679 ContentSettingToString(default_setting));
680 filter_settings.SetString(
681 ContentSettingsTypeToGroupName(type) + ".managedBy", provider_id);
683 web_ui()->CallJavascriptFunction(
684 "ContentSettings.setContentFilterSettingsValue", filter_settings);
687 void ContentSettingsHandler::UpdateMediaSettingsFromPrefs(
688 ContentSettingsType type) {
689 PrefService* prefs = user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
690 MediaSettingsInfo::ForOneType& settings = media_settings_->forType(type);
691 std::string policy_pref = (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)
692 ? prefs::kAudioCaptureAllowed
693 : prefs::kVideoCaptureAllowed;
695 settings.policy_disable = !prefs->GetBoolean(policy_pref) &&
696 prefs->IsManagedPreference(policy_pref);
697 settings.default_setting =
698 GetContentSettingsMap()->GetDefaultContentSetting(type, NULL);
699 settings.default_setting_initialized = true;
701 UpdateFlashMediaLinksVisibility(type);
702 UpdateMediaDeviceDropdownVisibility(type);
705 void ContentSettingsHandler::UpdateHandlersEnabledRadios() {
706 base::FundamentalValue handlers_enabled(
707 GetProtocolHandlerRegistry()->enabled());
709 web_ui()->CallJavascriptFunction(
710 "ContentSettings.updateHandlersEnabledRadios",
711 handlers_enabled);
714 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() {
715 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
716 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
717 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
719 // Zoom levels are not actually a content type so we need to handle them
720 // separately.
721 UpdateZoomLevelsExceptionsView();
724 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() {
725 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1;
726 type < CONTENT_SETTINGS_NUM_TYPES; ++type) {
727 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type));
731 void ContentSettingsHandler::UpdateExceptionsViewFromModel(
732 ContentSettingsType type) {
733 switch (type) {
734 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
735 UpdateGeolocationExceptionsView();
736 break;
737 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
738 UpdateNotificationExceptionsView();
739 break;
740 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
741 // The content settings type CONTENT_SETTINGS_TYPE_MEDIASSTREAM
742 // is deprecated.
743 break;
744 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
745 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
746 CompareMediaExceptionsWithFlash(type);
747 UpdateExceptionsViewFromHostContentSettingsMap(type);
748 break;
749 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
750 // We don't yet support exceptions for mixed scripting.
751 break;
752 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
753 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
754 // is supposed to be set by policy only. Hence there is no user facing UI
755 // for this content type and we skip it here.
756 break;
757 case CONTENT_SETTINGS_TYPE_PROTOCOL_HANDLERS:
758 // The RPH settings are retrieved separately.
759 break;
760 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
761 UpdateMIDISysExExceptionsView();
762 break;
763 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS:
764 // The content settings type CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS is
765 // supposed to be set by flags and field trials only, thus there is no
766 // user facing UI for this content type and we skip it here.
767 break;
768 case CONTENT_SETTINGS_TYPE_APP_BANNER:
769 // The content settings type CONTENT_SETTINGS_TYPE_APP_BANNER is used to
770 // track whether app banners should be shown or not, and is not a user
771 // visible content setting.
772 break;
773 case CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT:
774 // The content settings type CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT is used
775 // to track engagement with various origins, and is not a user visible
776 // content setting.
777 break;
778 case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE:
779 // Durable storage is not yet user visible. TODO(dgrogan): Make it so.
780 // https://crbug.com/482814
781 break;
782 default:
783 UpdateExceptionsViewFromHostContentSettingsMap(type);
784 break;
788 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel(
789 ContentSettingsType type) {
790 switch (type) {
791 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
792 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
793 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE:
794 case CONTENT_SETTINGS_TYPE_MIXEDSCRIPT:
795 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
796 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
797 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
798 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
799 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
800 case CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS:
801 case CONTENT_SETTINGS_TYPE_APP_BANNER:
802 case CONTENT_SETTINGS_TYPE_SITE_ENGAGEMENT:
803 case CONTENT_SETTINGS_TYPE_DURABLE_STORAGE:
804 break;
805 default:
806 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
807 break;
811 // TODO(estade): merge with GetExceptionsFromHostContentSettingsMap.
812 void ContentSettingsHandler::UpdateGeolocationExceptionsView() {
813 Profile* profile = Profile::FromWebUI(web_ui());
814 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
816 ContentSettingsForOneType all_settings;
817 map->GetSettingsForOneType(
818 CONTENT_SETTINGS_TYPE_GEOLOCATION,
819 std::string(),
820 &all_settings);
822 // Group geolocation settings by primary_pattern.
823 AllPatternsSettings all_patterns_settings;
824 for (ContentSettingsForOneType::iterator i = all_settings.begin();
825 i != all_settings.end(); ++i) {
826 // Don't add default settings.
827 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
828 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
829 i->source != kPreferencesSource) {
830 continue;
832 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
833 [i->secondary_pattern] = i->setting;
836 base::ListValue exceptions;
837 AddExceptionsGrantedByHostedApps(
838 profile,
839 HostedAppHasPermission<APIPermission::kGeolocation>,
840 &exceptions);
842 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
843 i != all_patterns_settings.end(); ++i) {
844 const ContentSettingsPattern& primary_pattern = i->first.first;
845 const OnePatternSettings& one_settings = i->second;
847 OnePatternSettings::const_iterator parent =
848 one_settings.find(primary_pattern);
850 // Add the "parent" entry for the non-embedded setting.
851 ContentSetting parent_setting =
852 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
853 exceptions.Append(GetGeolocationExceptionForPage(primary_pattern,
854 primary_pattern,
855 parent_setting));
857 // Add the "children" for any embedded settings.
858 for (OnePatternSettings::const_iterator j = one_settings.begin();
859 j != one_settings.end();
860 ++j) {
861 // Skip the non-embedded setting which we already added above.
862 if (j == parent)
863 continue;
865 exceptions.Append(GetGeolocationExceptionForPage(
866 primary_pattern, j->first, j->second));
870 base::StringValue type_string(
871 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION));
872 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
873 type_string, exceptions);
875 // This is mainly here to keep this function ideologically parallel to
876 // UpdateExceptionsViewFromHostContentSettingsMap().
877 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION);
880 void ContentSettingsHandler::UpdateNotificationExceptionsView() {
881 Profile* profile = Profile::FromWebUI(web_ui());
882 ContentSettingsForOneType settings;
883 DesktopNotificationProfileUtil::GetNotificationsSettings(profile, &settings);
885 base::ListValue exceptions;
886 AddExceptionsGrantedByHostedApps(
887 profile,
888 HostedAppHasPermission<APIPermission::kNotifications>,
889 &exceptions);
891 for (ContentSettingsForOneType::const_iterator i =
892 settings.begin();
893 i != settings.end();
894 ++i) {
895 // Don't add default settings.
896 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
897 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
898 i->source != kPreferencesSource) {
899 continue;
902 exceptions.Append(
903 GetNotificationExceptionForPage(i->primary_pattern,
904 i->secondary_pattern,
905 i->setting,
906 i->source));
909 base::StringValue type_string(
910 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS));
911 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
912 type_string, exceptions);
914 // This is mainly here to keep this function ideologically parallel to
915 // UpdateExceptionsViewFromHostContentSettingsMap().
916 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS);
919 void ContentSettingsHandler::CompareMediaExceptionsWithFlash(
920 ContentSettingsType type) {
921 MediaSettingsInfo::ForOneType& settings = media_settings_->forType(type);
923 base::ListValue exceptions;
924 GetExceptionsFromHostContentSettingsMap(
925 GetContentSettingsMap(),
926 type,
927 &exceptions);
929 settings.exceptions.clear();
930 for (base::ListValue::const_iterator entry = exceptions.begin();
931 entry != exceptions.end(); ++entry) {
932 base::DictionaryValue* dict = nullptr;
933 bool valid_dict = (*entry)->GetAsDictionary(&dict);
934 DCHECK(valid_dict);
936 std::string origin;
937 std::string setting;
938 dict->GetString(kOrigin, &origin);
939 dict->GetString(kSetting, &setting);
941 settings.exceptions.push_back(MediaException(
942 ContentSettingsPattern::FromString(origin),
943 ContentSettingFromString(setting)));
946 PepperFlashContentSettingsUtils::SortMediaExceptions(
947 &settings.exceptions);
949 settings.exceptions_initialized = true;
950 UpdateFlashMediaLinksVisibility(type);
953 void ContentSettingsHandler::UpdateMIDISysExExceptionsView() {
954 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
955 UpdateExceptionsViewFromHostContentSettingsMap(
956 CONTENT_SETTINGS_TYPE_MIDI_SYSEX);
959 void ContentSettingsHandler::AdjustZoomLevelsListForSigninPageIfNecessary(
960 content::HostZoomMap::ZoomLevelVector* zoom_levels) {
961 if (switches::IsEnableWebviewBasedSignin())
962 return;
964 GURL signin_url(chrome::kChromeUIChromeSigninURL);
965 content::HostZoomMap* signin_host_zoom_map =
966 content::BrowserContext::GetStoragePartitionForSite(
967 GetBrowserContext(web_ui()), signin_url)->GetHostZoomMap();
969 // Since zoom levels set for scheme + host are not persisted, and since the
970 // signin page zoom levels need to be persisted, they are stored without
971 // a scheme. We use an empty scheme string to indicate this.
972 std::string scheme;
973 std::string host = signin_url.host();
975 // If there's a WebView signin zoom level, remove it.
976 content::HostZoomMap::ZoomLevelVector::iterator it =
977 std::find_if(zoom_levels->begin(), zoom_levels->end(),
978 [&host](content::HostZoomMap::ZoomLevelChange change) {
979 return change.host == host;
981 if (it != zoom_levels->end())
982 zoom_levels->erase(it);
984 // If there's a non-WebView signin zoom level, add it.
985 if (signin_host_zoom_map->HasZoomLevel(scheme, host)) {
986 content::HostZoomMap::ZoomLevelChange change = {
987 content::HostZoomMap::ZOOM_CHANGED_FOR_HOST,
988 host,
989 scheme,
990 signin_host_zoom_map->GetZoomLevelForHostAndScheme(scheme, host)};
991 zoom_levels->push_back(change);
995 void ContentSettingsHandler::UpdateZoomLevelsExceptionsView() {
996 base::ListValue zoom_levels_exceptions;
998 content::HostZoomMap* host_zoom_map =
999 content::HostZoomMap::GetDefaultForBrowserContext(
1000 GetBrowserContext(web_ui()));
1001 content::HostZoomMap::ZoomLevelVector zoom_levels(
1002 host_zoom_map->GetAllZoomLevels());
1004 AdjustZoomLevelsListForSigninPageIfNecessary(&zoom_levels);
1006 // Sort ZoomLevelChanges by host and scheme
1007 // (a.com < http://a.com < https://a.com < b.com).
1008 std::sort(zoom_levels.begin(), zoom_levels.end(),
1009 [](const content::HostZoomMap::ZoomLevelChange& a,
1010 const content::HostZoomMap::ZoomLevelChange& b) {
1011 return a.host == b.host ? a.scheme < b.scheme : a.host < b.host;
1014 for (content::HostZoomMap::ZoomLevelVector::const_iterator i =
1015 zoom_levels.begin();
1016 i != zoom_levels.end();
1017 ++i) {
1018 scoped_ptr<base::DictionaryValue> exception(new base::DictionaryValue);
1019 switch (i->mode) {
1020 case content::HostZoomMap::ZOOM_CHANGED_FOR_HOST: {
1021 exception->SetString(kOrigin, i->host);
1022 std::string host = i->host;
1023 if (host == content::kUnreachableWebDataURL) {
1024 host =
1025 l10n_util::GetStringUTF8(IDS_ZOOMLEVELS_CHROME_ERROR_PAGES_LABEL);
1027 exception->SetString(kOrigin, host);
1028 break;
1030 case content::HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
1031 // These are not stored in preferences and get cleared on next browser
1032 // start. Therefore, we don't care for them.
1033 continue;
1034 case content::HostZoomMap::PAGE_SCALE_IS_ONE_CHANGED:
1035 continue;
1036 case content::HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
1037 NOTREACHED();
1039 exception->SetString(kSetting,
1040 ContentSettingToString(CONTENT_SETTING_DEFAULT));
1042 // Calculate the zoom percent from the factor. Round up to the nearest whole
1043 // number.
1044 int zoom_percent = static_cast<int>(
1045 content::ZoomLevelToZoomFactor(i->zoom_level) * 100 + 0.5);
1046 exception->SetString(
1047 kZoom,
1048 l10n_util::GetStringFUTF16(IDS_ZOOM_PERCENT,
1049 base::IntToString16(zoom_percent)));
1050 exception->SetString(kSource, kPreferencesSource);
1051 // Append the new entry to the list and map.
1052 zoom_levels_exceptions.Append(exception.release());
1055 base::StringValue type_string(kZoomContentType);
1056 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions",
1057 type_string, zoom_levels_exceptions);
1060 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap(
1061 ContentSettingsType type) {
1062 base::ListValue exceptions;
1063 GetExceptionsFromHostContentSettingsMap(
1064 GetContentSettingsMap(), type, &exceptions);
1065 base::StringValue type_string(ContentSettingsTypeToGroupName(type));
1066 web_ui()->CallJavascriptFunction("ContentSettings.setExceptions", type_string,
1067 exceptions);
1069 UpdateExceptionsViewFromOTRHostContentSettingsMap(type);
1071 // TODO(koz): The default for fullscreen is always 'ask'.
1072 // http://crbug.com/104683
1073 if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN)
1074 return;
1076 #if defined(OS_CHROMEOS)
1077 // Also the default for protected contents is managed in another place.
1078 if (type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER)
1079 return;
1080 #endif
1082 // The default may also have changed (we won't get a separate notification).
1083 // If it hasn't changed, this call will be harmless.
1084 UpdateSettingDefaultFromModel(type);
1087 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap(
1088 ContentSettingsType type) {
1089 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap();
1090 if (!otr_settings_map)
1091 return;
1092 base::ListValue exceptions;
1093 GetExceptionsFromHostContentSettingsMap(otr_settings_map, type, &exceptions);
1094 base::StringValue type_string(ContentSettingsTypeToGroupName(type));
1095 web_ui()->CallJavascriptFunction("ContentSettings.setOTRExceptions",
1096 type_string, exceptions);
1099 scoped_ptr<base::ListValue> ContentSettingsHandler::GetPolicyAllowedUrls(
1100 ContentSettingsType type) {
1101 DCHECK(type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
1102 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
1104 PrefService* prefs = Profile::FromWebUI(web_ui())->GetPrefs();
1105 const base::ListValue* policy_urls = prefs->GetList(
1106 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
1107 ? prefs::kAudioCaptureAllowedUrls
1108 : prefs::kVideoCaptureAllowedUrls);
1110 // Convert the URLs to |ContentSettingsPattern|s. Ignore any invalid ones.
1111 std::vector<ContentSettingsPattern> patterns;
1112 for (const base::Value* entry : *policy_urls) {
1113 std::string url;
1114 bool valid_string = entry->GetAsString(&url);
1115 if (!valid_string)
1116 continue;
1118 ContentSettingsPattern pattern = ContentSettingsPattern::FromString(url);
1119 if (!pattern.IsValid())
1120 continue;
1122 patterns.push_back(pattern);
1125 std::sort(patterns.begin(), patterns.end());
1127 scoped_ptr<base::ListValue> exceptions(new base::ListValue());
1128 for (const ContentSettingsPattern& pattern : patterns) {
1129 exceptions->Append(GetExceptionForPage(
1130 pattern,
1131 ContentSettingsPattern(),
1132 CONTENT_SETTING_ALLOW,
1133 kPolicyProviderId));
1136 return exceptions.Pass();
1139 void ContentSettingsHandler::GetExceptionsFromHostContentSettingsMap(
1140 const HostContentSettingsMap* map,
1141 ContentSettingsType type,
1142 base::ListValue* exceptions) {
1143 ContentSettingsForOneType entries;
1144 map->GetSettingsForOneType(type, std::string(), &entries);
1145 // Group settings by primary_pattern.
1146 AllPatternsSettings all_patterns_settings;
1147 for (ContentSettingsForOneType::iterator i = entries.begin();
1148 i != entries.end(); ++i) {
1149 // Don't add default settings.
1150 if (i->primary_pattern == ContentSettingsPattern::Wildcard() &&
1151 i->secondary_pattern == ContentSettingsPattern::Wildcard() &&
1152 i->source != kPreferencesSource) {
1153 continue;
1156 // Off-the-record HostContentSettingsMap contains incognito content settings
1157 // as well as normal content settings. Here, we use the incongnito settings
1158 // only.
1159 if (map->is_off_the_record() && !i->incognito)
1160 continue;
1162 all_patterns_settings[std::make_pair(i->primary_pattern, i->source)]
1163 [i->secondary_pattern] = i->setting;
1166 // Keep the exceptions sorted by provider so they will be displayed in
1167 // precedence order.
1168 ScopedVector<base::ListValue> all_provider_exceptions;
1169 all_provider_exceptions.resize(HostContentSettingsMap::NUM_PROVIDER_TYPES);
1170 for (auto& one_provider_exceptions : all_provider_exceptions)
1171 one_provider_exceptions = new base::ListValue();
1173 for (AllPatternsSettings::iterator i = all_patterns_settings.begin();
1174 i != all_patterns_settings.end();
1175 ++i) {
1176 const ContentSettingsPattern& primary_pattern = i->first.first;
1177 const OnePatternSettings& one_settings = i->second;
1179 // The "parent" entry either has an identical primary and secondary pattern,
1180 // or has a wildcard secondary. The two cases are indistinguishable in the
1181 // UI.
1182 OnePatternSettings::const_iterator parent =
1183 one_settings.find(primary_pattern);
1184 if (parent == one_settings.end())
1185 parent = one_settings.find(ContentSettingsPattern::Wildcard());
1187 const std::string& source = i->first.second;
1188 base::ListValue* this_provider_exceptions =
1189 all_provider_exceptions[
1190 HostContentSettingsMap::GetProviderTypeFromSource(source)];
1192 // Add the "parent" entry for the non-embedded setting.
1193 ContentSetting parent_setting =
1194 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second;
1195 const ContentSettingsPattern& secondary_pattern =
1196 parent == one_settings.end() ? primary_pattern : parent->first;
1197 this_provider_exceptions->Append(GetExceptionForPage(primary_pattern,
1198 secondary_pattern,
1199 parent_setting,
1200 source));
1202 // Add the "children" for any embedded settings.
1203 for (OnePatternSettings::const_iterator j = one_settings.begin();
1204 j != one_settings.end(); ++j) {
1205 // Skip the non-embedded setting which we already added above.
1206 if (j == parent)
1207 continue;
1209 ContentSetting content_setting = j->second;
1210 this_provider_exceptions->Append(GetExceptionForPage(
1211 primary_pattern,
1212 j->first,
1213 content_setting,
1214 source));
1218 // For camera and microphone, we do not have policy exceptions, but we do have
1219 // the policy-set allowed URLs, which should be displayed in the same manner.
1220 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
1221 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
1222 base::ListValue* policy_exceptions = all_provider_exceptions[
1223 HostContentSettingsMap::GetProviderTypeFromSource(kPolicyProviderId)];
1224 DCHECK(policy_exceptions->empty());
1225 policy_exceptions->Swap(GetPolicyAllowedUrls(type).get());
1228 for (const auto& one_provider_exceptions : all_provider_exceptions) {
1229 // Append the patterns in reverse order, so the ones with the highest
1230 // precedence (the more specific ones) are on the top.
1231 while (!one_provider_exceptions->empty()) {
1232 scoped_ptr<base::Value> exception;
1233 one_provider_exceptions->Remove(
1234 one_provider_exceptions->GetSize() - 1, &exception);
1235 exceptions->Append(exception.release());
1240 void ContentSettingsHandler::RemoveExceptionFromHostContentSettingsMap(
1241 const base::ListValue* args,
1242 ContentSettingsType type) {
1243 std::string mode;
1244 bool rv = args->GetString(1, &mode);
1245 DCHECK(rv);
1247 std::string pattern;
1248 rv = args->GetString(2, &pattern);
1249 DCHECK(rv);
1251 // The fourth argument to this handler is optional.
1252 std::string secondary_pattern;
1253 if (args->GetSize() >= 4U) {
1254 rv = args->GetString(3, &secondary_pattern);
1255 DCHECK(rv);
1258 HostContentSettingsMap* settings_map =
1259 mode == "normal" ? GetContentSettingsMap() :
1260 GetOTRContentSettingsMap();
1261 if (settings_map) {
1262 settings_map->SetWebsiteSetting(
1263 ContentSettingsPattern::FromString(pattern),
1264 secondary_pattern.empty() ?
1265 ContentSettingsPattern::Wildcard() :
1266 ContentSettingsPattern::FromString(secondary_pattern),
1267 type,
1268 std::string(),
1269 NULL);
1273 void ContentSettingsHandler::RemoveZoomLevelException(
1274 const base::ListValue* args) {
1275 std::string mode;
1276 bool rv = args->GetString(1, &mode);
1277 DCHECK(rv);
1279 std::string pattern;
1280 rv = args->GetString(2, &pattern);
1281 DCHECK(rv);
1283 if (pattern ==
1284 l10n_util::GetStringUTF8(IDS_ZOOMLEVELS_CHROME_ERROR_PAGES_LABEL)) {
1285 pattern = content::kUnreachableWebDataURL;
1288 content::HostZoomMap* host_zoom_map;
1289 if (switches::IsEnableWebviewBasedSignin() ||
1290 pattern != chrome::kChromeUIChromeSigninHost) {
1291 host_zoom_map =
1292 content::HostZoomMap::GetDefaultForBrowserContext(
1293 GetBrowserContext(web_ui()));
1294 } else {
1295 host_zoom_map =
1296 content::BrowserContext::GetStoragePartitionForSite(
1297 GetBrowserContext(web_ui()), GURL(chrome::kChromeUIChromeSigninURL))
1298 ->GetHostZoomMap();
1300 double default_level = host_zoom_map->GetDefaultZoomLevel();
1301 host_zoom_map->SetZoomLevelForHost(pattern, default_level);
1304 void ContentSettingsHandler::RegisterMessages() {
1305 web_ui()->RegisterMessageCallback("setContentFilter",
1306 base::Bind(&ContentSettingsHandler::SetContentFilter,
1307 base::Unretained(this)));
1308 web_ui()->RegisterMessageCallback("removeException",
1309 base::Bind(&ContentSettingsHandler::RemoveException,
1310 base::Unretained(this)));
1311 web_ui()->RegisterMessageCallback("setException",
1312 base::Bind(&ContentSettingsHandler::SetException,
1313 base::Unretained(this)));
1314 web_ui()->RegisterMessageCallback("checkExceptionPatternValidity",
1315 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity,
1316 base::Unretained(this)));
1319 void ContentSettingsHandler::SetContentFilter(const base::ListValue* args) {
1320 DCHECK_EQ(2U, args->GetSize());
1321 std::string group, setting;
1322 if (!(args->GetString(0, &group) &&
1323 args->GetString(1, &setting))) {
1324 NOTREACHED();
1325 return;
1328 ContentSetting default_setting = ContentSettingFromString(setting);
1329 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group);
1330 Profile* profile = Profile::FromWebUI(web_ui());
1332 #if defined(OS_CHROMEOS)
1333 // ChromeOS special case : in Guest mode settings are opened in Incognito
1334 // mode, so we need original profile to actually modify settings.
1335 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
1336 profile = profile->GetOriginalProfile();
1337 #endif
1339 HostContentSettingsMap* map = profile->GetHostContentSettingsMap();
1341 // MEDIASTREAM is deprecated and the two separate settings MEDIASTREAM_CAMERA
1342 // and MEDIASTREAM_MIC should be used instead. However, we still only have
1343 // one pair of radio buttons that sets both settings.
1344 // TODO(msramek): Clean this up once we have the new UI for media.
1345 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM) {
1346 map->SetDefaultContentSetting(
1347 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, default_setting);
1348 map->SetDefaultContentSetting(
1349 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, default_setting);
1350 } else {
1351 map->SetDefaultContentSetting(content_type, default_setting);
1354 switch (content_type) {
1355 case CONTENT_SETTINGS_TYPE_COOKIES:
1356 content::RecordAction(
1357 UserMetricsAction("Options_DefaultCookieSettingChanged"));
1358 break;
1359 case CONTENT_SETTINGS_TYPE_IMAGES:
1360 content::RecordAction(
1361 UserMetricsAction("Options_DefaultImagesSettingChanged"));
1362 break;
1363 case CONTENT_SETTINGS_TYPE_JAVASCRIPT:
1364 content::RecordAction(
1365 UserMetricsAction("Options_DefaultJavaScriptSettingChanged"));
1366 break;
1367 case CONTENT_SETTINGS_TYPE_PLUGINS:
1368 content::RecordAction(
1369 UserMetricsAction("Options_DefaultPluginsSettingChanged"));
1370 break;
1371 case CONTENT_SETTINGS_TYPE_POPUPS:
1372 content::RecordAction(
1373 UserMetricsAction("Options_DefaultPopupsSettingChanged"));
1374 break;
1375 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
1376 content::RecordAction(
1377 UserMetricsAction("Options_DefaultNotificationsSettingChanged"));
1378 break;
1379 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
1380 content::RecordAction(
1381 UserMetricsAction("Options_DefaultGeolocationSettingChanged"));
1382 break;
1383 case CONTENT_SETTINGS_TYPE_MOUSELOCK:
1384 content::RecordAction(
1385 UserMetricsAction("Options_DefaultMouseLockSettingChanged"));
1386 break;
1387 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
1388 content::RecordAction(
1389 UserMetricsAction("Options_DefaultMediaStreamMicSettingChanged"));
1390 break;
1391 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
1392 content::RecordAction(
1393 UserMetricsAction("Options_DefaultMultipleAutomaticDLSettingChange"));
1394 break;
1395 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
1396 content::RecordAction(
1397 UserMetricsAction("Options_DefaultMIDISysExSettingChanged"));
1398 break;
1399 case CONTENT_SETTINGS_TYPE_PUSH_MESSAGING:
1400 content::RecordAction(
1401 UserMetricsAction("Options_DefaultPushMessagingSettingChanged"));
1402 break;
1403 default:
1404 break;
1408 void ContentSettingsHandler::RemoveException(const base::ListValue* args) {
1409 std::string type_string;
1410 CHECK(args->GetString(0, &type_string));
1412 // Zoom levels are no actual content type so we need to handle them
1413 // separately. They would not be recognized by
1414 // ContentSettingsTypeFromGroupName.
1415 if (type_string == kZoomContentType) {
1416 RemoveZoomLevelException(args);
1417 return;
1420 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
1421 RemoveExceptionFromHostContentSettingsMap(args, type);
1423 WebSiteSettingsUmaUtil::LogPermissionChange(
1424 type, ContentSetting::CONTENT_SETTING_DEFAULT);
1427 void ContentSettingsHandler::SetException(const base::ListValue* args) {
1428 std::string type_string;
1429 CHECK(args->GetString(0, &type_string));
1430 std::string mode;
1431 CHECK(args->GetString(1, &mode));
1432 std::string pattern;
1433 CHECK(args->GetString(2, &pattern));
1434 std::string setting;
1435 CHECK(args->GetString(3, &setting));
1437 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string);
1438 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
1439 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
1440 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
1441 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
1442 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) {
1443 NOTREACHED();
1444 } else {
1445 HostContentSettingsMap* settings_map =
1446 mode == "normal" ? GetContentSettingsMap() :
1447 GetOTRContentSettingsMap();
1449 // The settings map could be null if the mode was OTR but the OTR profile
1450 // got destroyed before we received this message.
1451 if (!settings_map)
1452 return;
1453 settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern),
1454 ContentSettingsPattern::Wildcard(),
1455 type,
1456 std::string(),
1457 ContentSettingFromString(setting));
1461 void ContentSettingsHandler::CheckExceptionPatternValidity(
1462 const base::ListValue* args) {
1463 std::string type_string;
1464 CHECK(args->GetString(0, &type_string));
1465 std::string mode_string;
1466 CHECK(args->GetString(1, &mode_string));
1467 std::string pattern_string;
1468 CHECK(args->GetString(2, &pattern_string));
1470 ContentSettingsPattern pattern =
1471 ContentSettingsPattern::FromString(pattern_string);
1473 web_ui()->CallJavascriptFunction(
1474 "ContentSettings.patternValidityCheckComplete",
1475 base::StringValue(type_string),
1476 base::StringValue(mode_string),
1477 base::StringValue(pattern_string),
1478 base::FundamentalValue(pattern.IsValid()));
1481 // static
1482 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName(
1483 ContentSettingsType type) {
1484 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) {
1485 if (type == kContentSettingsTypeGroupNames[i].type)
1486 return kContentSettingsTypeGroupNames[i].name;
1489 NOTREACHED();
1490 return std::string();
1493 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() {
1494 return Profile::FromWebUI(web_ui())->GetHostContentSettingsMap();
1497 ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() {
1498 return ProtocolHandlerRegistryFactory::GetForBrowserContext(
1499 GetBrowserContext(web_ui()));
1502 HostContentSettingsMap*
1503 ContentSettingsHandler::GetOTRContentSettingsMap() {
1504 Profile* profile = Profile::FromWebUI(web_ui());
1505 if (profile->HasOffTheRecordProfile())
1506 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap();
1507 return NULL;
1510 void ContentSettingsHandler::RefreshFlashMediaSettings() {
1511 MediaSettingsInfo::ForFlash& settings = media_settings_->forFlash();
1512 settings.initialized = false;
1514 settings.last_refresh_request_id =
1515 flash_settings_manager_->GetPermissionSettings(
1516 PP_FLASH_BROWSEROPERATIONS_SETTINGTYPE_CAMERAMIC);
1519 void ContentSettingsHandler::OnPepperFlashPrefChanged() {
1520 ShowFlashMediaLink(
1521 DEFAULT_SETTING, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, false);
1522 ShowFlashMediaLink(
1523 DEFAULT_SETTING, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, false);
1524 ShowFlashMediaLink(
1525 EXCEPTIONS, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, false);
1526 ShowFlashMediaLink(
1527 EXCEPTIONS, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, false);
1529 PrefService* prefs = user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
1530 if (prefs->GetBoolean(prefs::kPepperFlashSettingsEnabled))
1531 RefreshFlashMediaSettings();
1532 else
1533 media_settings_->forFlash().initialized = false;
1536 void ContentSettingsHandler::OnZoomLevelChanged(
1537 const content::HostZoomMap::ZoomLevelChange& change) {
1538 UpdateZoomLevelsExceptionsView();
1541 void ContentSettingsHandler::ShowFlashMediaLink(
1542 LinkType link_type, ContentSettingsType content_type, bool show) {
1543 MediaSettingsInfo::ForOneType& settings =
1544 media_settings_->forType(content_type);
1546 bool& show_link = link_type == DEFAULT_SETTING ?
1547 settings.show_flash_default_link :
1548 settings.show_flash_exceptions_link;
1550 if (show_link != show) {
1551 web_ui()->CallJavascriptFunction(
1552 "ContentSettings.showMediaPepperFlashLink",
1553 base::StringValue(
1554 link_type == DEFAULT_SETTING ? "default" : "exceptions"),
1555 base::StringValue(
1556 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC
1557 ? "mic"
1558 : "camera"),
1559 base::FundamentalValue(show));
1560 show_link = show;
1564 void ContentSettingsHandler::UpdateFlashMediaLinksVisibility(
1565 ContentSettingsType type) {
1566 MediaSettingsInfo::ForOneType& settings = media_settings_->forType(type);
1567 MediaSettingsInfo::ForFlash& flash_settings = media_settings_->forFlash();
1569 if (!flash_settings.initialized)
1570 return;
1572 // We handle four cases - default settings and exceptions for microphone
1573 // and camera. We use the following criteria to determine whether to show
1574 // the links.
1576 // 1. Flash won't send us notifications when its settings get changed, which
1577 // means the Flash settings in |media_settings_| may be out-dated, especially
1578 // after we show links to change Flash settings.
1579 // In order to avoid confusion, we won't hide the links once they are showed.
1580 // One exception is that we will hide them when Pepper Flash is disabled
1581 // (handled in OnPepperFlashPrefChanged()).
1583 // 2. If audio or video capture are disabled by policy, the respective link
1584 // shouldn't be showed. Flash conforms to the policy in this case because
1585 // it cannot open those devices.
1587 // 3. Otherwise, we show the link if the corresponding setting is different
1588 // in HostContentSettingsMap than it is in Flash.
1589 if (settings.policy_disable)
1590 return;
1592 if (settings.default_setting_initialized &&
1593 !settings.show_flash_default_link &&
1594 (flash_settings.default_setting !=
1595 settings.default_setting)) {
1596 ShowFlashMediaLink(DEFAULT_SETTING, type, true);
1599 if (settings.exceptions_initialized &&
1600 !settings.show_flash_exceptions_link &&
1601 !PepperFlashContentSettingsUtils::AreMediaExceptionsEqual(
1602 settings.default_setting,
1603 settings.exceptions,
1604 flash_settings.default_setting,
1605 flash_settings.exceptions)) {
1606 ShowFlashMediaLink(EXCEPTIONS, type, true);
1610 void ContentSettingsHandler::UpdateMediaDeviceDropdownVisibility(
1611 ContentSettingsType type) {
1612 MediaSettingsInfo::ForOneType& settings = media_settings_->forType(type);
1614 web_ui()->CallJavascriptFunction(
1615 "ContentSettings.setDevicesMenuVisibility",
1616 base::StringValue(ContentSettingsTypeToGroupName(type)),
1617 base::FundamentalValue(!settings.policy_disable));
1620 void ContentSettingsHandler::UpdateProtectedContentExceptionsButton() {
1621 #if defined(OS_CHROMEOS)
1622 // Guests cannot modify exceptions. UIAccountTweaks will disabled the button.
1623 if (user_manager::UserManager::Get()->IsLoggedInAsGuest())
1624 return;
1625 #endif
1627 // Exceptions apply only when the feature is enabled.
1628 PrefService* prefs = user_prefs::UserPrefs::Get(GetBrowserContext(web_ui()));
1629 bool enable_exceptions = prefs->GetBoolean(prefs::kEnableDRM);
1630 web_ui()->CallJavascriptFunction(
1631 "ContentSettings.enableProtectedContentExceptions",
1632 base::FundamentalValue(enable_exceptions));
1635 } // namespace options