OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 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/options2/content_settings_handler.h" |
| 6 |
| 7 #include <map> |
| 8 #include <string> |
| 9 #include <vector> |
| 10 |
| 11 #include "base/bind.h" |
| 12 #include "base/bind_helpers.h" |
| 13 #include "base/command_line.h" |
| 14 #include "base/utf_string_conversions.h" |
| 15 #include "base/values.h" |
| 16 #include "chrome/browser/browser_process.h" |
| 17 #include "chrome/browser/content_settings/content_settings_details.h" |
| 18 #include "chrome/browser/content_settings/content_settings_utils.h" |
| 19 #include "chrome/browser/content_settings/host_content_settings_map.h" |
| 20 #include "chrome/browser/custom_handlers/protocol_handler_registry.h" |
| 21 #include "chrome/browser/notifications/desktop_notification_service.h" |
| 22 #include "chrome/browser/notifications/desktop_notification_service_factory.h" |
| 23 #include "chrome/browser/profiles/profile.h" |
| 24 #include "chrome/browser/ui/browser_list.h" |
| 25 #include "chrome/common/chrome_notification_types.h" |
| 26 #include "chrome/common/chrome_switches.h" |
| 27 #include "chrome/common/content_settings.h" |
| 28 #include "chrome/common/content_settings_pattern.h" |
| 29 #include "chrome/common/pref_names.h" |
| 30 #include "chrome/common/url_constants.h" |
| 31 #include "content/browser/tab_contents/tab_contents.h" |
| 32 #include "content/public/browser/notification_service.h" |
| 33 #include "content/public/browser/notification_source.h" |
| 34 #include "content/public/browser/notification_types.h" |
| 35 #include "content/public/browser/user_metrics.h" |
| 36 #include "content/public/common/content_switches.h" |
| 37 #include "grit/generated_resources.h" |
| 38 #include "grit/locale_settings.h" |
| 39 #include "ui/base/l10n/l10n_util.h" |
| 40 |
| 41 using content::UserMetricsAction; |
| 42 |
| 43 namespace { |
| 44 |
| 45 struct ContentSettingsTypeNameEntry { |
| 46 ContentSettingsType type; |
| 47 const char* name; |
| 48 }; |
| 49 |
| 50 typedef std::map<ContentSettingsPattern, ContentSetting> OnePatternSettings; |
| 51 typedef std::map<ContentSettingsPattern, OnePatternSettings> |
| 52 AllPatternsSettings; |
| 53 |
| 54 const char* kDisplayPattern = "displayPattern"; |
| 55 const char* kSetting = "setting"; |
| 56 const char* kOrigin = "origin"; |
| 57 const char* kSource = "source"; |
| 58 const char* kEmbeddingOrigin = "embeddingOrigin"; |
| 59 |
| 60 const ContentSettingsTypeNameEntry kContentSettingsTypeGroupNames[] = { |
| 61 {CONTENT_SETTINGS_TYPE_COOKIES, "cookies"}, |
| 62 {CONTENT_SETTINGS_TYPE_IMAGES, "images"}, |
| 63 {CONTENT_SETTINGS_TYPE_JAVASCRIPT, "javascript"}, |
| 64 {CONTENT_SETTINGS_TYPE_PLUGINS, "plugins"}, |
| 65 {CONTENT_SETTINGS_TYPE_POPUPS, "popups"}, |
| 66 {CONTENT_SETTINGS_TYPE_GEOLOCATION, "location"}, |
| 67 {CONTENT_SETTINGS_TYPE_NOTIFICATIONS, "notifications"}, |
| 68 {CONTENT_SETTINGS_TYPE_INTENTS, "intents"}, |
| 69 {CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, "auto-select-certificate"}, |
| 70 {CONTENT_SETTINGS_TYPE_FULLSCREEN, "fullscreen"}, |
| 71 {CONTENT_SETTINGS_TYPE_MOUSELOCK, "mouselock"}, |
| 72 }; |
| 73 COMPILE_ASSERT(arraysize(kContentSettingsTypeGroupNames) == |
| 74 CONTENT_SETTINGS_NUM_TYPES, |
| 75 MISSING_CONTENT_SETTINGS_TYPE); |
| 76 |
| 77 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) { |
| 78 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) { |
| 79 if (name == kContentSettingsTypeGroupNames[i].name) |
| 80 return kContentSettingsTypeGroupNames[i].type; |
| 81 } |
| 82 |
| 83 NOTREACHED() << name << " is not a recognized content settings type."; |
| 84 return CONTENT_SETTINGS_TYPE_DEFAULT; |
| 85 } |
| 86 |
| 87 std::string ContentSettingToString(ContentSetting setting) { |
| 88 switch (setting) { |
| 89 case CONTENT_SETTING_ALLOW: |
| 90 return "allow"; |
| 91 case CONTENT_SETTING_ASK: |
| 92 return "ask"; |
| 93 case CONTENT_SETTING_BLOCK: |
| 94 return "block"; |
| 95 case CONTENT_SETTING_SESSION_ONLY: |
| 96 return "session"; |
| 97 case CONTENT_SETTING_DEFAULT: |
| 98 return "default"; |
| 99 case CONTENT_SETTING_NUM_SETTINGS: |
| 100 NOTREACHED(); |
| 101 } |
| 102 |
| 103 return ""; |
| 104 } |
| 105 |
| 106 ContentSetting ContentSettingFromString(const std::string& name) { |
| 107 if (name == "allow") |
| 108 return CONTENT_SETTING_ALLOW; |
| 109 if (name == "ask") |
| 110 return CONTENT_SETTING_ASK; |
| 111 if (name == "block") |
| 112 return CONTENT_SETTING_BLOCK; |
| 113 if (name == "session") |
| 114 return CONTENT_SETTING_SESSION_ONLY; |
| 115 |
| 116 NOTREACHED() << name << " is not a recognized content setting."; |
| 117 return CONTENT_SETTING_DEFAULT; |
| 118 } |
| 119 |
| 120 std::string GeolocationExceptionToString( |
| 121 const ContentSettingsPattern& origin, |
| 122 const ContentSettingsPattern& embedding_origin) { |
| 123 if (origin == embedding_origin) |
| 124 return origin.ToString(); |
| 125 |
| 126 // TODO(estade): the page needs to use CSS to indent the string. |
| 127 std::string indent(" "); |
| 128 |
| 129 if (embedding_origin == ContentSettingsPattern::Wildcard()) { |
| 130 // NOTE: As long as the user cannot add/edit entries from the exceptions |
| 131 // dialog, it's impossible to actually have a non-default setting for some |
| 132 // origin "embedded on any other site", so this row will never appear. If |
| 133 // we add the ability to add/edit exceptions, we'll need to decide when to |
| 134 // display this and how "removing" it will function. |
| 135 return indent + |
| 136 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ANY_OTHER); |
| 137 } |
| 138 |
| 139 return indent + l10n_util::GetStringFUTF8( |
| 140 IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST, |
| 141 UTF8ToUTF16(embedding_origin.ToString())); |
| 142 } |
| 143 |
| 144 // Create a DictionaryValue* that will act as a data source for a single row |
| 145 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies). |
| 146 // Ownership of the pointer is passed to the caller. |
| 147 DictionaryValue* GetExceptionForPage( |
| 148 const ContentSettingsPattern& pattern, |
| 149 ContentSetting setting, |
| 150 std::string provider_name) { |
| 151 DictionaryValue* exception = new DictionaryValue(); |
| 152 exception->SetString(kDisplayPattern, pattern.ToString()); |
| 153 exception->SetString(kSetting, ContentSettingToString(setting)); |
| 154 exception->SetString(kSource, provider_name); |
| 155 return exception; |
| 156 } |
| 157 |
| 158 // Create a DictionaryValue* that will act as a data source for a single row |
| 159 // in the Geolocation exceptions table. Ownership of the pointer is passed to |
| 160 // the caller. |
| 161 DictionaryValue* GetGeolocationExceptionForPage( |
| 162 const ContentSettingsPattern& origin, |
| 163 const ContentSettingsPattern& embedding_origin, |
| 164 ContentSetting setting) { |
| 165 DictionaryValue* exception = new DictionaryValue(); |
| 166 exception->SetString(kDisplayPattern, |
| 167 GeolocationExceptionToString(origin, embedding_origin)); |
| 168 exception->SetString(kSetting, ContentSettingToString(setting)); |
| 169 exception->SetString(kOrigin, origin.ToString()); |
| 170 exception->SetString(kEmbeddingOrigin, embedding_origin.ToString()); |
| 171 return exception; |
| 172 } |
| 173 |
| 174 // Create a DictionaryValue* that will act as a data source for a single row |
| 175 // in the desktop notifications exceptions table. Ownership of the pointer is |
| 176 // passed to the caller. |
| 177 DictionaryValue* GetNotificationExceptionForPage( |
| 178 const ContentSettingsPattern& pattern, |
| 179 ContentSetting setting, |
| 180 const std::string& provider_name) { |
| 181 DictionaryValue* exception = new DictionaryValue(); |
| 182 exception->SetString(kDisplayPattern, pattern.ToString()); |
| 183 exception->SetString(kSetting, ContentSettingToString(setting)); |
| 184 exception->SetString(kOrigin, pattern.ToString()); |
| 185 exception->SetString(kSource, provider_name); |
| 186 return exception; |
| 187 } |
| 188 |
| 189 } // namespace |
| 190 |
| 191 ContentSettingsHandler::ContentSettingsHandler() { |
| 192 } |
| 193 |
| 194 ContentSettingsHandler::~ContentSettingsHandler() { |
| 195 } |
| 196 |
| 197 void ContentSettingsHandler::GetLocalizedValues( |
| 198 DictionaryValue* localized_strings) { |
| 199 DCHECK(localized_strings); |
| 200 |
| 201 static OptionsStringResource resources[] = { |
| 202 { "content_exceptions", IDS_COOKIES_EXCEPTIONS_BUTTON }, |
| 203 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON }, |
| 204 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON }, |
| 205 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON }, |
| 206 { "askException", IDS_EXCEPTIONS_ASK_BUTTON }, |
| 207 { "addExceptionRow", IDS_EXCEPTIONS_ADD_BUTTON }, |
| 208 { "removeExceptionRow", IDS_EXCEPTIONS_REMOVE_BUTTON }, |
| 209 { "editExceptionRow", IDS_EXCEPTIONS_EDIT_BUTTON }, |
| 210 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL }, |
| 211 { "examplePattern", IDS_EXCEPTIONS_PATTERN_EXAMPLE }, |
| 212 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS }, |
| 213 { "manage_exceptions", IDS_EXCEPTIONS_MANAGE }, |
| 214 { "manage_handlers", IDS_HANDLERS_MANAGE }, |
| 215 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER }, |
| 216 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER }, |
| 217 // Cookies filter. |
| 218 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL }, |
| 219 { "cookies_header", IDS_COOKIES_HEADER }, |
| 220 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO }, |
| 221 { "cookies_block", IDS_COOKIES_BLOCK_RADIO }, |
| 222 { "cookies_session_only", IDS_COOKIES_SESSION_ONLY_RADIO }, |
| 223 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX }, |
| 224 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX }, |
| 225 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX }, |
| 226 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON }, |
| 227 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS }, |
| 228 { "flash_storage_url", IDS_FLASH_STORAGE_URL }, |
| 229 // Image filter. |
| 230 { "images_tab_label", IDS_IMAGES_TAB_LABEL }, |
| 231 { "images_header", IDS_IMAGES_HEADER }, |
| 232 { "images_allow", IDS_IMAGES_LOAD_RADIO }, |
| 233 { "images_block", IDS_IMAGES_NOLOAD_RADIO }, |
| 234 // JavaScript filter. |
| 235 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL }, |
| 236 { "javascript_header", IDS_JAVASCRIPT_HEADER }, |
| 237 { "javascript_allow", IDS_JS_ALLOW_RADIO }, |
| 238 { "javascript_block", IDS_JS_DONOTALLOW_RADIO }, |
| 239 // Plug-ins filter. |
| 240 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL }, |
| 241 { "plugins_header", IDS_PLUGIN_HEADER }, |
| 242 { "plugins_ask", IDS_PLUGIN_ASK_RADIO }, |
| 243 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO }, |
| 244 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO }, |
| 245 { "disableIndividualPlugins", IDS_PLUGIN_SELECTIVE_DISABLE }, |
| 246 // Pop-ups filter. |
| 247 { "popups_tab_label", IDS_POPUP_TAB_LABEL }, |
| 248 { "popups_header", IDS_POPUP_HEADER }, |
| 249 { "popups_allow", IDS_POPUP_ALLOW_RADIO }, |
| 250 { "popups_block", IDS_POPUP_BLOCK_RADIO }, |
| 251 // Location filter. |
| 252 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL }, |
| 253 { "location_header", IDS_GEOLOCATION_HEADER }, |
| 254 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO }, |
| 255 { "location_ask", IDS_GEOLOCATION_ASK_RADIO }, |
| 256 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO }, |
| 257 // Notifications filter. |
| 258 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL }, |
| 259 { "notifications_header", IDS_NOTIFICATIONS_HEADER }, |
| 260 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO }, |
| 261 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO }, |
| 262 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO }, |
| 263 // Intents filter. |
| 264 { "intentsTabLabel", IDS_INTENTS_TAB_LABEL }, |
| 265 { "intentsAllow", IDS_INTENTS_ALLOW_RADIO }, |
| 266 { "intentsAsk", IDS_INTENTS_ASK_RADIO }, |
| 267 { "intentsBlock", IDS_INTENTS_BLOCK_RADIO }, |
| 268 { "intents_header", IDS_INTENTS_HEADER }, |
| 269 // Fullscreen filter. |
| 270 { "fullscreen_tab_label", IDS_FULLSCREEN_TAB_LABEL }, |
| 271 { "fullscreen_header", IDS_FULLSCREEN_HEADER }, |
| 272 // Mouse Lock filter. |
| 273 { "mouselock_tab_label", IDS_MOUSE_LOCK_TAB_LABEL }, |
| 274 { "mouselock_header", IDS_MOUSE_LOCK_HEADER }, |
| 275 { "mouselock_allow", IDS_MOUSE_LOCK_ALLOW_RADIO }, |
| 276 { "mouselock_ask", IDS_MOUSE_LOCK_ASK_RADIO }, |
| 277 { "mouselock_block", IDS_MOUSE_LOCK_BLOCK_RADIO }, |
| 278 }; |
| 279 |
| 280 RegisterStrings(localized_strings, resources, arraysize(resources)); |
| 281 RegisterTitle(localized_strings, "contentSettingsPage", |
| 282 IDS_CONTENT_SETTINGS_TITLE); |
| 283 localized_strings->SetBoolean("enable_click_to_play", |
| 284 CommandLine::ForCurrentProcess()->HasSwitch( |
| 285 switches::kEnableClickToPlay)); |
| 286 localized_strings->SetBoolean("enable_web_intents", |
| 287 CommandLine::ForCurrentProcess()->HasSwitch( |
| 288 switches::kEnableWebIntents)); |
| 289 } |
| 290 |
| 291 void ContentSettingsHandler::Initialize() { |
| 292 notification_registrar_.Add( |
| 293 this, chrome::NOTIFICATION_PROFILE_CREATED, |
| 294 content::NotificationService::AllSources()); |
| 295 notification_registrar_.Add( |
| 296 this, chrome::NOTIFICATION_PROFILE_DESTROYED, |
| 297 content::NotificationService::AllSources()); |
| 298 |
| 299 UpdateHandlersEnabledRadios(); |
| 300 UpdateAllExceptionsViewsFromModel(); |
| 301 notification_registrar_.Add( |
| 302 this, chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED, |
| 303 content::NotificationService::AllSources()); |
| 304 notification_registrar_.Add( |
| 305 this, chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED, |
| 306 content::NotificationService::AllSources()); |
| 307 Profile* profile = Profile::FromWebUI(web_ui_); |
| 308 notification_registrar_.Add( |
| 309 this, chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED, |
| 310 content::Source<Profile>(profile)); |
| 311 |
| 312 PrefService* prefs = profile->GetPrefs(); |
| 313 pref_change_registrar_.Init(prefs); |
| 314 pref_change_registrar_.Add(prefs::kGeolocationContentSettings, this); |
| 315 } |
| 316 |
| 317 void ContentSettingsHandler::Observe( |
| 318 int type, |
| 319 const content::NotificationSource& source, |
| 320 const content::NotificationDetails& details) { |
| 321 switch (type) { |
| 322 case chrome::NOTIFICATION_PROFILE_DESTROYED: { |
| 323 if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) { |
| 324 web_ui_->CallJavascriptFunction( |
| 325 "ContentSettingsExceptionsArea.OTRProfileDestroyed"); |
| 326 } |
| 327 break; |
| 328 } |
| 329 |
| 330 case chrome::NOTIFICATION_PROFILE_CREATED: { |
| 331 if (content::Source<Profile>(source).ptr()->IsOffTheRecord()) |
| 332 UpdateAllOTRExceptionsViewsFromModel(); |
| 333 break; |
| 334 } |
| 335 |
| 336 case chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED: { |
| 337 // Filter out notifications from other profiles. |
| 338 HostContentSettingsMap* map = |
| 339 content::Source<HostContentSettingsMap>(source).ptr(); |
| 340 if (map != GetContentSettingsMap() && |
| 341 map != GetOTRContentSettingsMap()) |
| 342 break; |
| 343 |
| 344 const ContentSettingsDetails* settings_details = |
| 345 content::Details<const ContentSettingsDetails>(details).ptr(); |
| 346 |
| 347 // TODO(estade): we pretend update_all() is always true. |
| 348 if (settings_details->update_all_types()) |
| 349 UpdateAllExceptionsViewsFromModel(); |
| 350 else |
| 351 UpdateExceptionsViewFromModel(settings_details->type()); |
| 352 break; |
| 353 } |
| 354 |
| 355 case chrome::NOTIFICATION_PREF_CHANGED: { |
| 356 const std::string& pref_name = |
| 357 *content::Details<std::string>(details).ptr(); |
| 358 if (pref_name == prefs::kGeolocationContentSettings) |
| 359 UpdateGeolocationExceptionsView(); |
| 360 break; |
| 361 } |
| 362 |
| 363 case chrome::NOTIFICATION_DESKTOP_NOTIFICATION_SETTINGS_CHANGED: { |
| 364 UpdateNotificationExceptionsView(); |
| 365 break; |
| 366 } |
| 367 |
| 368 case chrome::NOTIFICATION_PROTOCOL_HANDLER_REGISTRY_CHANGED: { |
| 369 UpdateHandlersEnabledRadios(); |
| 370 break; |
| 371 } |
| 372 |
| 373 default: |
| 374 OptionsPage2UIHandler::Observe(type, source, details); |
| 375 } |
| 376 } |
| 377 |
| 378 void ContentSettingsHandler::UpdateSettingDefaultFromModel( |
| 379 ContentSettingsType type) { |
| 380 DictionaryValue filter_settings; |
| 381 std::string provider_id; |
| 382 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value", |
| 383 GetSettingDefaultFromModel(type, &provider_id)); |
| 384 filter_settings.SetString( |
| 385 ContentSettingsTypeToGroupName(type) + ".managedBy", |
| 386 provider_id); |
| 387 |
| 388 web_ui_->CallJavascriptFunction( |
| 389 "ContentSettings.setContentFilterSettingsValue", filter_settings); |
| 390 } |
| 391 |
| 392 std::string ContentSettingsHandler::GetSettingDefaultFromModel( |
| 393 ContentSettingsType type, std::string* provider_id) { |
| 394 Profile* profile = Profile::FromWebUI(web_ui_); |
| 395 ContentSetting default_setting; |
| 396 if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { |
| 397 default_setting = |
| 398 DesktopNotificationServiceFactory::GetForProfile(profile)-> |
| 399 GetDefaultContentSetting(provider_id); |
| 400 } else { |
| 401 default_setting = |
| 402 profile->GetHostContentSettingsMap()-> |
| 403 GetDefaultContentSetting(type, provider_id); |
| 404 } |
| 405 |
| 406 return ContentSettingToString(default_setting); |
| 407 } |
| 408 |
| 409 void ContentSettingsHandler::UpdateHandlersEnabledRadios() { |
| 410 #if defined(ENABLE_REGISTER_PROTOCOL_HANDLER) |
| 411 DCHECK(web_ui_); |
| 412 base::FundamentalValue handlers_enabled( |
| 413 GetProtocolHandlerRegistry()->enabled()); |
| 414 |
| 415 web_ui_->CallJavascriptFunction("ContentSettings.updateHandlersEnabledRadios", |
| 416 handlers_enabled); |
| 417 #endif // defined(ENABLE_REGISTER_PROTOCOL_HANDLER) |
| 418 } |
| 419 |
| 420 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() { |
| 421 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1; |
| 422 type < CONTENT_SETTINGS_NUM_TYPES; ++type) { |
| 423 // The content settings type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE |
| 424 // is supposed to be set by policy only. Hence there is no user facing UI |
| 425 // for this content type and we skip it here. |
| 426 if (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE) |
| 427 continue; |
| 428 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type)); |
| 429 } |
| 430 } |
| 431 |
| 432 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() { |
| 433 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1; |
| 434 type < CONTENT_SETTINGS_NUM_TYPES; ++type) { |
| 435 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type)); |
| 436 } |
| 437 } |
| 438 |
| 439 void ContentSettingsHandler::UpdateExceptionsViewFromModel( |
| 440 ContentSettingsType type) { |
| 441 // Skip updating intents unless it's enabled from the command line. |
| 442 if (type == CONTENT_SETTINGS_TYPE_INTENTS && |
| 443 !CommandLine::ForCurrentProcess()->HasSwitch( |
| 444 switches::kEnableWebIntents)) |
| 445 return; |
| 446 |
| 447 switch (type) { |
| 448 case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
| 449 UpdateGeolocationExceptionsView(); |
| 450 break; |
| 451 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
| 452 UpdateNotificationExceptionsView(); |
| 453 break; |
| 454 default: |
| 455 UpdateExceptionsViewFromHostContentSettingsMap(type); |
| 456 break; |
| 457 } |
| 458 } |
| 459 |
| 460 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel( |
| 461 ContentSettingsType type) { |
| 462 switch (type) { |
| 463 case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
| 464 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
| 465 case CONTENT_SETTINGS_TYPE_INTENTS: |
| 466 case CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE: |
| 467 break; |
| 468 default: |
| 469 UpdateExceptionsViewFromOTRHostContentSettingsMap(type); |
| 470 break; |
| 471 } |
| 472 } |
| 473 |
| 474 void ContentSettingsHandler::UpdateGeolocationExceptionsView() { |
| 475 Profile* profile = Profile::FromWebUI(web_ui_); |
| 476 HostContentSettingsMap* map = profile->GetHostContentSettingsMap(); |
| 477 |
| 478 ContentSettingsForOneType all_settings; |
| 479 map->GetSettingsForOneType( |
| 480 CONTENT_SETTINGS_TYPE_GEOLOCATION, |
| 481 std::string(), |
| 482 &all_settings); |
| 483 |
| 484 // Group geolocation settings by primary_pattern. |
| 485 AllPatternsSettings all_patterns_settings; |
| 486 for (ContentSettingsForOneType::iterator i = |
| 487 all_settings.begin(); |
| 488 i != all_settings.end(); |
| 489 ++i) { |
| 490 // Don't add default settings. |
| 491 if (i->primary_pattern == ContentSettingsPattern::Wildcard() && |
| 492 i->secondary_pattern == ContentSettingsPattern::Wildcard() && |
| 493 i->source != "preferences") { |
| 494 continue; |
| 495 } |
| 496 all_patterns_settings[i->primary_pattern][i->secondary_pattern] = |
| 497 i->setting; |
| 498 } |
| 499 |
| 500 ListValue exceptions; |
| 501 for (AllPatternsSettings::iterator i = all_patterns_settings.begin(); |
| 502 i != all_patterns_settings.end(); |
| 503 ++i) { |
| 504 const ContentSettingsPattern& primary_pattern = i->first; |
| 505 const OnePatternSettings& one_settings = i->second; |
| 506 |
| 507 OnePatternSettings::const_iterator parent = |
| 508 one_settings.find(primary_pattern); |
| 509 |
| 510 // Add the "parent" entry for the non-embedded setting. |
| 511 ContentSetting parent_setting = |
| 512 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second; |
| 513 exceptions.Append(GetGeolocationExceptionForPage(primary_pattern, |
| 514 primary_pattern, |
| 515 parent_setting)); |
| 516 |
| 517 // Add the "children" for any embedded settings. |
| 518 for (OnePatternSettings::const_iterator j = one_settings.begin(); |
| 519 j != one_settings.end(); |
| 520 ++j) { |
| 521 // Skip the non-embedded setting which we already added above. |
| 522 if (j == parent) |
| 523 continue; |
| 524 |
| 525 exceptions.Append( |
| 526 GetGeolocationExceptionForPage(primary_pattern, j->first, j->second)); |
| 527 } |
| 528 } |
| 529 |
| 530 StringValue type_string( |
| 531 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION)); |
| 532 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", |
| 533 type_string, exceptions); |
| 534 |
| 535 // This is mainly here to keep this function ideologically parallel to |
| 536 // UpdateExceptionsViewFromHostContentSettingsMap(). |
| 537 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION); |
| 538 } |
| 539 |
| 540 void ContentSettingsHandler::UpdateNotificationExceptionsView() { |
| 541 Profile* profile = Profile::FromWebUI(web_ui_); |
| 542 DesktopNotificationService* service = |
| 543 DesktopNotificationServiceFactory::GetForProfile(profile); |
| 544 |
| 545 ContentSettingsForOneType settings; |
| 546 service->GetNotificationsSettings(&settings); |
| 547 |
| 548 ListValue exceptions; |
| 549 for (ContentSettingsForOneType::const_iterator i = |
| 550 settings.begin(); |
| 551 i != settings.end(); |
| 552 ++i) { |
| 553 // Don't add default settings. |
| 554 if (i->primary_pattern == ContentSettingsPattern::Wildcard() && |
| 555 i->secondary_pattern == ContentSettingsPattern::Wildcard() && |
| 556 i->source != "preferences") { |
| 557 continue; |
| 558 } |
| 559 |
| 560 exceptions.Append( |
| 561 GetNotificationExceptionForPage(i->primary_pattern, i->setting, |
| 562 i->source)); |
| 563 } |
| 564 |
| 565 StringValue type_string( |
| 566 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS)); |
| 567 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", |
| 568 type_string, exceptions); |
| 569 |
| 570 // This is mainly here to keep this function ideologically parallel to |
| 571 // UpdateExceptionsViewFromHostContentSettingsMap(). |
| 572 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); |
| 573 } |
| 574 |
| 575 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap( |
| 576 ContentSettingsType type) { |
| 577 ContentSettingsForOneType entries; |
| 578 GetContentSettingsMap()->GetSettingsForOneType(type, "", &entries); |
| 579 |
| 580 ListValue exceptions; |
| 581 for (size_t i = 0; i < entries.size(); ++i) { |
| 582 // Skip default settings from extensions and policy, and the default content |
| 583 // settings; all of them will affect the default setting UI. |
| 584 if (entries[i].primary_pattern == ContentSettingsPattern::Wildcard() && |
| 585 entries[i].secondary_pattern == ContentSettingsPattern::Wildcard() && |
| 586 entries[i].source != "preference") { |
| 587 continue; |
| 588 } |
| 589 // The content settings UI does not support secondary content settings |
| 590 // pattern yet. For content settings set through the content settings UI the |
| 591 // secondary pattern is by default a wildcard pattern. Hence users are not |
| 592 // able to modify content settings with a secondary pattern other than the |
| 593 // wildcard pattern. So only show settings that the user is able to modify. |
| 594 // TODO(bauerb): Support a read-only view for those patterns. |
| 595 if (entries[i].secondary_pattern == ContentSettingsPattern::Wildcard()) { |
| 596 exceptions.Append( |
| 597 GetExceptionForPage(entries[i].primary_pattern, entries[i].setting, |
| 598 entries[i].source)); |
| 599 } else { |
| 600 LOG(ERROR) << "Secondary content settings patterns are not " |
| 601 << "supported by the content settings UI"; |
| 602 } |
| 603 } |
| 604 |
| 605 StringValue type_string(ContentSettingsTypeToGroupName(type)); |
| 606 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", type_string, |
| 607 exceptions); |
| 608 |
| 609 UpdateExceptionsViewFromOTRHostContentSettingsMap(type); |
| 610 |
| 611 // TODO(koz): The default for fullscreen is always 'ask'. |
| 612 // http://crbug.com/104683 |
| 613 if (type == CONTENT_SETTINGS_TYPE_FULLSCREEN) |
| 614 return; |
| 615 |
| 616 // The default may also have changed (we won't get a separate notification). |
| 617 // If it hasn't changed, this call will be harmless. |
| 618 UpdateSettingDefaultFromModel(type); |
| 619 } |
| 620 |
| 621 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap( |
| 622 ContentSettingsType type) { |
| 623 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap(); |
| 624 if (!otr_settings_map) |
| 625 return; |
| 626 |
| 627 ContentSettingsForOneType otr_entries; |
| 628 otr_settings_map->GetSettingsForOneType(type, "", &otr_entries); |
| 629 |
| 630 ListValue otr_exceptions; |
| 631 for (size_t i = 0; i < otr_entries.size(); ++i) { |
| 632 // Off-the-record HostContentSettingsMap contains incognito content settings |
| 633 // as well as normal content settings. Here, we use the incongnito settings |
| 634 // only. |
| 635 if (!otr_entries[i].incognito) |
| 636 continue; |
| 637 // The content settings UI does not support secondary content settings |
| 638 // pattern yet. For content settings set through the content settings UI the |
| 639 // secondary pattern is by default a wildcard pattern. Hence users are not |
| 640 // able to modify content settings with a secondary pattern other than the |
| 641 // wildcard pattern. So only show settings that the user is able to modify. |
| 642 // TODO(bauerb): Support a read-only view for those patterns. |
| 643 if (otr_entries[i].secondary_pattern == |
| 644 ContentSettingsPattern::Wildcard()) { |
| 645 otr_exceptions.Append( |
| 646 GetExceptionForPage(otr_entries[i].primary_pattern, |
| 647 otr_entries[i].setting, |
| 648 otr_entries[i].source)); |
| 649 } else { |
| 650 LOG(ERROR) << "Secondary content settings patterns are not " |
| 651 << "supported by the content settings UI"; |
| 652 } |
| 653 } |
| 654 |
| 655 StringValue type_string(ContentSettingsTypeToGroupName(type)); |
| 656 web_ui_->CallJavascriptFunction("ContentSettings.setOTRExceptions", |
| 657 type_string, otr_exceptions); |
| 658 } |
| 659 |
| 660 void ContentSettingsHandler::RegisterMessages() { |
| 661 web_ui_->RegisterMessageCallback("setContentFilter", |
| 662 base::Bind(&ContentSettingsHandler::SetContentFilter, |
| 663 base::Unretained(this))); |
| 664 web_ui_->RegisterMessageCallback("removeException", |
| 665 base::Bind(&ContentSettingsHandler::RemoveException, |
| 666 base::Unretained(this))); |
| 667 web_ui_->RegisterMessageCallback("setException", |
| 668 base::Bind(&ContentSettingsHandler::SetException, |
| 669 base::Unretained(this))); |
| 670 web_ui_->RegisterMessageCallback("checkExceptionPatternValidity", |
| 671 base::Bind(&ContentSettingsHandler::CheckExceptionPatternValidity, |
| 672 base::Unretained(this))); |
| 673 } |
| 674 |
| 675 void ContentSettingsHandler::SetContentFilter(const ListValue* args) { |
| 676 DCHECK_EQ(2U, args->GetSize()); |
| 677 std::string group, setting; |
| 678 if (!(args->GetString(0, &group) && |
| 679 args->GetString(1, &setting))) { |
| 680 NOTREACHED(); |
| 681 return; |
| 682 } |
| 683 |
| 684 ContentSetting default_setting = ContentSettingFromString(setting); |
| 685 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group); |
| 686 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { |
| 687 Profile* profile = Profile::FromWebUI(web_ui_); |
| 688 DesktopNotificationServiceFactory::GetForProfile(profile)-> |
| 689 SetDefaultContentSetting(default_setting); |
| 690 } else { |
| 691 GetContentSettingsMap()-> |
| 692 SetDefaultContentSetting(content_type, default_setting); |
| 693 } |
| 694 switch (content_type) { |
| 695 case CONTENT_SETTINGS_TYPE_COOKIES: |
| 696 content::RecordAction( |
| 697 UserMetricsAction("Options_DefaultCookieSettingChanged")); |
| 698 break; |
| 699 case CONTENT_SETTINGS_TYPE_IMAGES: |
| 700 content::RecordAction( |
| 701 UserMetricsAction("Options_DefaultImagesSettingChanged")); |
| 702 break; |
| 703 case CONTENT_SETTINGS_TYPE_JAVASCRIPT: |
| 704 content::RecordAction( |
| 705 UserMetricsAction("Options_DefaultJavaScriptSettingChanged")); |
| 706 break; |
| 707 case CONTENT_SETTINGS_TYPE_PLUGINS: |
| 708 content::RecordAction( |
| 709 UserMetricsAction("Options_DefaultPluginsSettingChanged")); |
| 710 break; |
| 711 case CONTENT_SETTINGS_TYPE_POPUPS: |
| 712 content::RecordAction( |
| 713 UserMetricsAction("Options_DefaultPopupsSettingChanged")); |
| 714 break; |
| 715 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: |
| 716 content::RecordAction( |
| 717 UserMetricsAction("Options_DefaultNotificationsSettingChanged")); |
| 718 break; |
| 719 case CONTENT_SETTINGS_TYPE_GEOLOCATION: |
| 720 content::RecordAction( |
| 721 UserMetricsAction("Options_DefaultGeolocationSettingChanged")); |
| 722 break; |
| 723 case CONTENT_SETTINGS_TYPE_INTENTS: |
| 724 content::RecordAction( |
| 725 UserMetricsAction("Options_DefaultHandlersSettingChanged")); |
| 726 break; |
| 727 case CONTENT_SETTINGS_TYPE_MOUSELOCK: |
| 728 content::RecordAction( |
| 729 UserMetricsAction("Options_DefaultMouseLockSettingChanged")); |
| 730 break; |
| 731 default: |
| 732 break; |
| 733 } |
| 734 } |
| 735 |
| 736 void ContentSettingsHandler::RemoveException(const ListValue* args) { |
| 737 size_t arg_i = 0; |
| 738 std::string type_string; |
| 739 CHECK(args->GetString(arg_i++, &type_string)); |
| 740 |
| 741 Profile* profile = Profile::FromWebUI(web_ui_); |
| 742 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string); |
| 743 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { |
| 744 std::string origin; |
| 745 std::string embedding_origin; |
| 746 bool rv = args->GetString(arg_i++, &origin); |
| 747 DCHECK(rv); |
| 748 rv = args->GetString(arg_i++, &embedding_origin); |
| 749 DCHECK(rv); |
| 750 |
| 751 profile->GetHostContentSettingsMap()-> |
| 752 SetContentSetting(ContentSettingsPattern::FromString(origin), |
| 753 ContentSettingsPattern::FromString(embedding_origin), |
| 754 CONTENT_SETTINGS_TYPE_GEOLOCATION, |
| 755 std::string(), |
| 756 CONTENT_SETTING_DEFAULT); |
| 757 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { |
| 758 std::string origin; |
| 759 std::string setting; |
| 760 bool rv = args->GetString(arg_i++, &origin); |
| 761 DCHECK(rv); |
| 762 rv = args->GetString(arg_i++, &setting); |
| 763 DCHECK(rv); |
| 764 ContentSetting content_setting = ContentSettingFromString(setting); |
| 765 |
| 766 DCHECK(content_setting == CONTENT_SETTING_ALLOW || |
| 767 content_setting == CONTENT_SETTING_BLOCK); |
| 768 DesktopNotificationServiceFactory::GetForProfile(profile)-> |
| 769 ClearSetting(ContentSettingsPattern::FromString(origin)); |
| 770 } else { |
| 771 std::string mode; |
| 772 bool rv = args->GetString(arg_i++, &mode); |
| 773 DCHECK(rv); |
| 774 |
| 775 std::string pattern; |
| 776 rv = args->GetString(arg_i++, &pattern); |
| 777 DCHECK(rv); |
| 778 |
| 779 HostContentSettingsMap* settings_map = |
| 780 mode == "normal" ? GetContentSettingsMap() : |
| 781 GetOTRContentSettingsMap(); |
| 782 // The settings map could be null if the mode was OTR but the OTR profile |
| 783 // got destroyed before we received this message. |
| 784 if (settings_map) { |
| 785 settings_map->SetContentSetting( |
| 786 ContentSettingsPattern::FromString(pattern), |
| 787 ContentSettingsPattern::Wildcard(), |
| 788 ContentSettingsTypeFromGroupName(type_string), |
| 789 "", |
| 790 CONTENT_SETTING_DEFAULT); |
| 791 } |
| 792 } |
| 793 } |
| 794 |
| 795 void ContentSettingsHandler::SetException(const ListValue* args) { |
| 796 size_t arg_i = 0; |
| 797 std::string type_string; |
| 798 CHECK(args->GetString(arg_i++, &type_string)); |
| 799 std::string mode; |
| 800 CHECK(args->GetString(arg_i++, &mode)); |
| 801 std::string pattern; |
| 802 CHECK(args->GetString(arg_i++, &pattern)); |
| 803 std::string setting; |
| 804 CHECK(args->GetString(arg_i++, &setting)); |
| 805 |
| 806 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string); |
| 807 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION || |
| 808 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { |
| 809 NOTREACHED(); |
| 810 return; |
| 811 } |
| 812 |
| 813 HostContentSettingsMap* settings_map = |
| 814 mode == "normal" ? GetContentSettingsMap() : |
| 815 GetOTRContentSettingsMap(); |
| 816 |
| 817 // The settings map could be null if the mode was OTR but the OTR profile |
| 818 // got destroyed before we received this message. |
| 819 if (!settings_map) |
| 820 return; |
| 821 settings_map->SetContentSetting(ContentSettingsPattern::FromString(pattern), |
| 822 ContentSettingsPattern::Wildcard(), |
| 823 type, |
| 824 "", |
| 825 ContentSettingFromString(setting)); |
| 826 } |
| 827 |
| 828 void ContentSettingsHandler::CheckExceptionPatternValidity( |
| 829 const ListValue* args) { |
| 830 size_t arg_i = 0; |
| 831 Value* type; |
| 832 CHECK(args->Get(arg_i++, &type)); |
| 833 std::string mode_string; |
| 834 CHECK(args->GetString(arg_i++, &mode_string)); |
| 835 std::string pattern_string; |
| 836 CHECK(args->GetString(arg_i++, &pattern_string)); |
| 837 |
| 838 ContentSettingsPattern pattern = |
| 839 ContentSettingsPattern::FromString(pattern_string); |
| 840 |
| 841 scoped_ptr<Value> mode_value(Value::CreateStringValue(mode_string)); |
| 842 scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string)); |
| 843 scoped_ptr<Value> valid_value(Value::CreateBooleanValue(pattern.IsValid())); |
| 844 |
| 845 web_ui_->CallJavascriptFunction( |
| 846 "ContentSettings.patternValidityCheckComplete", |
| 847 *type, |
| 848 *mode_value.get(), |
| 849 *pattern_value.get(), |
| 850 *valid_value.get()); |
| 851 } |
| 852 |
| 853 // static |
| 854 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName( |
| 855 ContentSettingsType type) { |
| 856 for (size_t i = 0; i < arraysize(kContentSettingsTypeGroupNames); ++i) { |
| 857 if (type == kContentSettingsTypeGroupNames[i].type) |
| 858 return kContentSettingsTypeGroupNames[i].name; |
| 859 } |
| 860 |
| 861 NOTREACHED(); |
| 862 return std::string(); |
| 863 } |
| 864 |
| 865 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() { |
| 866 return Profile::FromWebUI(web_ui_)->GetHostContentSettingsMap(); |
| 867 } |
| 868 |
| 869 ProtocolHandlerRegistry* ContentSettingsHandler::GetProtocolHandlerRegistry() { |
| 870 return Profile::FromWebUI(web_ui_)->GetProtocolHandlerRegistry(); |
| 871 } |
| 872 |
| 873 HostContentSettingsMap* |
| 874 ContentSettingsHandler::GetOTRContentSettingsMap() { |
| 875 Profile* profile = Profile::FromWebUI(web_ui_); |
| 876 if (profile->HasOffTheRecordProfile()) |
| 877 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap(); |
| 878 return NULL; |
| 879 } |
OLD | NEW |