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