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/options/content_settings_handler.h" 6 7 #include "base/callback.h" 8 #include "base/command_line.h" 9 #include "base/utf_string_conversions.h" 10 #include "base/values.h" 11 #include "chrome/browser/browser_process.h" 12 #include "chrome/browser/content_settings/content_settings_details.h" 13 #include "chrome/browser/content_settings/host_content_settings_map.h" 14 #include "chrome/browser/geolocation/geolocation_content_settings_map.h" 15 #include "chrome/browser/notifications/desktop_notification_service.h" 16 #include "chrome/browser/notifications/desktop_notification_service_factory.h" 17 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/ui/browser_list.h" 19 #include "chrome/common/chrome_switches.h" 20 #include "chrome/common/content_settings_helper.h" 21 #include "chrome/common/pref_names.h" 22 #include "chrome/common/url_constants.h" 23 #include "content/common/notification_service.h" 24 #include "content/common/notification_source.h" 25 #include "content/common/notification_type.h" 26 #include "grit/generated_resources.h" 27 #include "grit/locale_settings.h" 28 #include "ui/base/l10n/l10n_util.h" 29 30 namespace { 31 32 const char* kDisplayPattern = "displayPattern"; 33 const char* kSetting = "setting"; 34 const char* kOrigin = "origin"; 35 const char* kEmbeddingOrigin = "embeddingOrigin"; 36 37 const char* const kContentSettingsTypeGroupNames[] = { 38 "cookies", 39 "images", 40 "javascript", 41 "plugins", 42 "popups", 43 "location", 44 "notifications", 45 "prerender", 46 }; 47 COMPILE_ASSERT(arraysize(kContentSettingsTypeGroupNames) == 48 CONTENT_SETTINGS_NUM_TYPES, 49 invalid_content_settings_type_group_names_size); 50 51 52 ContentSettingsType ContentSettingsTypeFromGroupName(const std::string& name) { 53 54 for (int content_settings_type = CONTENT_SETTINGS_TYPE_COOKIES; 55 content_settings_type < CONTENT_SETTINGS_NUM_TYPES; 56 ++content_settings_type) { 57 if (name == kContentSettingsTypeGroupNames[content_settings_type]) 58 return static_cast<ContentSettingsType>(content_settings_type); 59 } 60 61 NOTREACHED() << name << " is not a recognized content settings type."; 62 return CONTENT_SETTINGS_TYPE_DEFAULT; 63 } 64 65 std::string ContentSettingToString(ContentSetting setting) { 66 switch (setting) { 67 case CONTENT_SETTING_ALLOW: 68 return "allow"; 69 case CONTENT_SETTING_ASK: 70 return "ask"; 71 case CONTENT_SETTING_BLOCK: 72 return "block"; 73 case CONTENT_SETTING_SESSION_ONLY: 74 return "session"; 75 case CONTENT_SETTING_DEFAULT: 76 return "default"; 77 case CONTENT_SETTING_NUM_SETTINGS: 78 NOTREACHED(); 79 } 80 81 return ""; 82 } 83 84 ContentSetting ContentSettingFromString(const std::string& name) { 85 if (name == "allow") 86 return CONTENT_SETTING_ALLOW; 87 if (name == "ask") 88 return CONTENT_SETTING_ASK; 89 if (name == "block") 90 return CONTENT_SETTING_BLOCK; 91 if (name == "session") 92 return CONTENT_SETTING_SESSION_ONLY; 93 94 NOTREACHED() << name << " is not a recognized content setting."; 95 return CONTENT_SETTING_DEFAULT; 96 } 97 98 std::string GeolocationExceptionToString(const GURL& origin, 99 const GURL& embedding_origin) { 100 if (origin == embedding_origin) 101 return content_settings_helper::OriginToString(origin); 102 103 // TODO(estade): the page needs to use CSS to indent the string. 104 std::string indent(" "); 105 if (embedding_origin.is_empty()) { 106 // NOTE: As long as the user cannot add/edit entries from the exceptions 107 // dialog, it's impossible to actually have a non-default setting for some 108 // origin "embedded on any other site", so this row will never appear. If 109 // we add the ability to add/edit exceptions, we'll need to decide when to 110 // display this and how "removing" it will function. 111 return indent + 112 l10n_util::GetStringUTF8(IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ANY_OTHER); 113 } 114 115 return indent + l10n_util::GetStringFUTF8( 116 IDS_EXCEPTIONS_GEOLOCATION_EMBEDDED_ON_HOST, 117 UTF8ToUTF16(content_settings_helper::OriginToString(embedding_origin))); 118 } 119 120 // Create a DictionaryValue* that will act as a data source for a single row 121 // in a HostContentSettingsMap-controlled exceptions table (e.g., cookies). 122 // Ownership of the pointer is passed to the caller. 123 DictionaryValue* GetExceptionForPage( 124 const ContentSettingsPattern& pattern, 125 ContentSetting setting) { 126 DictionaryValue* exception = new DictionaryValue(); 127 exception->Set( 128 kDisplayPattern, 129 new StringValue(pattern.AsString())); 130 exception->Set( 131 kSetting, 132 new StringValue(ContentSettingToString(setting))); 133 return exception; 134 } 135 136 // Create a DictionaryValue* that will act as a data source for a single row 137 // in the Geolocation exceptions table. Ownership of the pointer is passed to 138 // the caller. 139 DictionaryValue* GetGeolocationExceptionForPage(const GURL& origin, 140 const GURL& embedding_origin, 141 ContentSetting setting) { 142 DictionaryValue* exception = new DictionaryValue(); 143 exception->Set( 144 kDisplayPattern, 145 new StringValue(GeolocationExceptionToString(origin, embedding_origin))); 146 exception->Set( 147 kSetting, 148 new StringValue(ContentSettingToString(setting))); 149 exception->Set( 150 kOrigin, 151 new StringValue(origin.spec())); 152 exception->Set( 153 kEmbeddingOrigin, 154 new StringValue(embedding_origin.spec())); 155 return exception; 156 } 157 158 // Create a DictionaryValue* that will act as a data source for a single row 159 // in the desktop notifications exceptions table. Ownership of the pointer is 160 // passed to the caller. 161 DictionaryValue* GetNotificationExceptionForPage( 162 const GURL& url, 163 ContentSetting setting) { 164 DictionaryValue* exception = new DictionaryValue(); 165 exception->Set( 166 kDisplayPattern, 167 new StringValue(content_settings_helper::OriginToString(url))); 168 exception->Set( 169 kSetting, 170 new StringValue(ContentSettingToString(setting))); 171 exception->Set( 172 kOrigin, 173 new StringValue(url.spec())); 174 return exception; 175 } 176 177 } // namespace 178 179 ContentSettingsHandler::ContentSettingsHandler() { 180 } 181 182 ContentSettingsHandler::~ContentSettingsHandler() { 183 } 184 185 void ContentSettingsHandler::GetLocalizedValues( 186 DictionaryValue* localized_strings) { 187 DCHECK(localized_strings); 188 189 static OptionsStringResource resources[] = { 190 { "content_exceptions", IDS_COOKIES_EXCEPTIONS_BUTTON }, 191 { "allowException", IDS_EXCEPTIONS_ALLOW_BUTTON }, 192 { "blockException", IDS_EXCEPTIONS_BLOCK_BUTTON }, 193 { "sessionException", IDS_EXCEPTIONS_SESSION_ONLY_BUTTON }, 194 { "askException", IDS_EXCEPTIONS_ASK_BUTTON }, 195 { "addExceptionRow", IDS_EXCEPTIONS_ADD_BUTTON }, 196 { "removeExceptionRow", IDS_EXCEPTIONS_REMOVE_BUTTON }, 197 { "editExceptionRow", IDS_EXCEPTIONS_EDIT_BUTTON }, 198 { "otr_exceptions_explanation", IDS_EXCEPTIONS_OTR_LABEL }, 199 { "examplePattern", IDS_EXCEPTIONS_PATTERN_EXAMPLE }, 200 { "addNewExceptionInstructions", IDS_EXCEPTIONS_ADD_NEW_INSTRUCTIONS }, 201 { "manage_exceptions", IDS_EXCEPTIONS_MANAGE }, 202 { "exceptionPatternHeader", IDS_EXCEPTIONS_PATTERN_HEADER }, 203 { "exceptionBehaviorHeader", IDS_EXCEPTIONS_ACTION_HEADER }, 204 // Cookies filter. 205 { "cookies_tab_label", IDS_COOKIES_TAB_LABEL }, 206 { "cookies_header", IDS_COOKIES_HEADER }, 207 { "cookies_allow", IDS_COOKIES_ALLOW_RADIO }, 208 { "cookies_ask", IDS_COOKIES_ASK_EVERY_TIME_RADIO }, 209 { "cookies_block", IDS_COOKIES_BLOCK_RADIO }, 210 { "cookies_block_3rd_party", IDS_COOKIES_BLOCK_3RDPARTY_CHKBOX }, 211 { "cookies_clear_when_close", IDS_COOKIES_CLEAR_WHEN_CLOSE_CHKBOX }, 212 { "cookies_lso_clear_when_close", IDS_COOKIES_LSO_CLEAR_WHEN_CLOSE_CHKBOX }, 213 { "cookies_show_cookies", IDS_COOKIES_SHOW_COOKIES_BUTTON }, 214 { "flash_storage_settings", IDS_FLASH_STORAGE_SETTINGS }, 215 { "flash_storage_url", IDS_FLASH_STORAGE_URL }, 216 // Image filter. 217 { "images_tab_label", IDS_IMAGES_TAB_LABEL }, 218 { "images_header", IDS_IMAGES_HEADER }, 219 { "images_allow", IDS_IMAGES_LOAD_RADIO }, 220 { "images_block", IDS_IMAGES_NOLOAD_RADIO }, 221 // JavaScript filter. 222 { "javascript_tab_label", IDS_JAVASCRIPT_TAB_LABEL }, 223 { "javascript_header", IDS_JAVASCRIPT_HEADER }, 224 { "javascript_allow", IDS_JS_ALLOW_RADIO }, 225 { "javascript_block", IDS_JS_DONOTALLOW_RADIO }, 226 // Plug-ins filter. 227 { "plugins_tab_label", IDS_PLUGIN_TAB_LABEL }, 228 { "plugins_header", IDS_PLUGIN_HEADER }, 229 { "plugins_ask", IDS_PLUGIN_ASK_RADIO }, 230 { "plugins_allow", IDS_PLUGIN_LOAD_RADIO }, 231 { "plugins_block", IDS_PLUGIN_NOLOAD_RADIO }, 232 { "disable_individual_plugins", IDS_PLUGIN_SELECTIVE_DISABLE }, 233 // Pop-ups filter. 234 { "popups_tab_label", IDS_POPUP_TAB_LABEL }, 235 { "popups_header", IDS_POPUP_HEADER }, 236 { "popups_allow", IDS_POPUP_ALLOW_RADIO }, 237 { "popups_block", IDS_POPUP_BLOCK_RADIO }, 238 // Location filter. 239 { "location_tab_label", IDS_GEOLOCATION_TAB_LABEL }, 240 { "location_header", IDS_GEOLOCATION_HEADER }, 241 { "location_allow", IDS_GEOLOCATION_ALLOW_RADIO }, 242 { "location_ask", IDS_GEOLOCATION_ASK_RADIO }, 243 { "location_block", IDS_GEOLOCATION_BLOCK_RADIO }, 244 // Notifications filter. 245 { "notifications_tab_label", IDS_NOTIFICATIONS_TAB_LABEL }, 246 { "notifications_header", IDS_NOTIFICATIONS_HEADER }, 247 { "notifications_allow", IDS_NOTIFICATIONS_ALLOW_RADIO }, 248 { "notifications_ask", IDS_NOTIFICATIONS_ASK_RADIO }, 249 { "notifications_block", IDS_NOTIFICATIONS_BLOCK_RADIO }, 250 }; 251 252 RegisterStrings(localized_strings, resources, arraysize(resources)); 253 RegisterTitle(localized_strings, "contentSettingsPage", 254 IDS_CONTENT_SETTINGS_TITLE); 255 localized_strings->SetBoolean("enable_click_to_play", 256 CommandLine::ForCurrentProcess()->HasSwitch( 257 switches::kEnableClickToPlay)); 258 } 259 260 void ContentSettingsHandler::Initialize() { 261 const HostContentSettingsMap* settings_map = GetContentSettingsMap(); 262 scoped_ptr<Value> block_3rd_party(Value::CreateBooleanValue( 263 settings_map->BlockThirdPartyCookies())); 264 web_ui_->CallJavascriptFunction("ContentSettings.setBlockThirdPartyCookies", 265 *block_3rd_party.get()); 266 267 notification_registrar_.Add( 268 this, NotificationType::OTR_PROFILE_CREATED, 269 NotificationService::AllSources()); 270 notification_registrar_.Add( 271 this, NotificationType::PROFILE_DESTROYED, 272 NotificationService::AllSources()); 273 274 UpdateAllExceptionsViewsFromModel(); 275 notification_registrar_.Add( 276 this, NotificationType::CONTENT_SETTINGS_CHANGED, 277 NotificationService::AllSources()); 278 notification_registrar_.Add( 279 this, NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED, 280 NotificationService::AllSources()); 281 notification_registrar_.Add( 282 this, NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED, 283 NotificationService::AllSources()); 284 285 PrefService* prefs = web_ui_->GetProfile()->GetPrefs(); 286 pref_change_registrar_.Init(prefs); 287 pref_change_registrar_.Add(prefs::kGeolocationDefaultContentSetting, this); 288 pref_change_registrar_.Add(prefs::kGeolocationContentSettings, this); 289 } 290 291 void ContentSettingsHandler::Observe(NotificationType type, 292 const NotificationSource& source, 293 const NotificationDetails& details) { 294 switch (type.value) { 295 case NotificationType::PROFILE_DESTROYED: { 296 Profile* profile = static_cast<Source<Profile> >(source).ptr(); 297 if (profile->IsOffTheRecord()) { 298 web_ui_->CallJavascriptFunction( 299 "ContentSettingsExceptionsArea.OTRProfileDestroyed"); 300 } 301 break; 302 } 303 304 case NotificationType::OTR_PROFILE_CREATED: { 305 UpdateAllOTRExceptionsViewsFromModel(); 306 break; 307 } 308 309 case NotificationType::CONTENT_SETTINGS_CHANGED: { 310 const ContentSettingsDetails* settings_details = 311 Details<const ContentSettingsDetails>(details).ptr(); 312 313 // TODO(estade): we pretend update_all() is always true. 314 if (settings_details->update_all_types()) 315 UpdateAllExceptionsViewsFromModel(); 316 else 317 UpdateExceptionsViewFromModel(settings_details->type()); 318 break; 319 } 320 321 case NotificationType::PREF_CHANGED: { 322 const std::string& pref_name = *Details<std::string>(details).ptr(); 323 if (pref_name == prefs::kGeolocationDefaultContentSetting) 324 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION); 325 else if (pref_name == prefs::kGeolocationContentSettings) 326 UpdateGeolocationExceptionsView(); 327 break; 328 } 329 330 case NotificationType::DESKTOP_NOTIFICATION_DEFAULT_CHANGED: { 331 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); 332 break; 333 } 334 335 case NotificationType::DESKTOP_NOTIFICATION_SETTINGS_CHANGED: { 336 UpdateNotificationExceptionsView(); 337 break; 338 } 339 340 default: 341 OptionsPageUIHandler::Observe(type, source, details); 342 } 343 } 344 345 void ContentSettingsHandler::UpdateSettingDefaultFromModel( 346 ContentSettingsType type) { 347 DictionaryValue filter_settings; 348 filter_settings.SetString(ContentSettingsTypeToGroupName(type) + ".value", 349 GetSettingDefaultFromModel(type)); 350 filter_settings.SetBoolean(ContentSettingsTypeToGroupName(type) + ".managed", 351 GetDefaultSettingManagedFromModel(type)); 352 353 web_ui_->CallJavascriptFunction( 354 "ContentSettings.setContentFilterSettingsValue", filter_settings); 355 } 356 357 std::string ContentSettingsHandler::GetSettingDefaultFromModel( 358 ContentSettingsType type) { 359 ContentSetting default_setting; 360 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { 361 default_setting = web_ui_->GetProfile()-> 362 GetGeolocationContentSettingsMap()->GetDefaultContentSetting(); 363 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { 364 default_setting = DesktopNotificationServiceFactory::GetForProfile( 365 web_ui_->GetProfile())->GetDefaultContentSetting(); 366 } else { 367 default_setting = GetContentSettingsMap()->GetDefaultContentSetting(type); 368 } 369 370 return ContentSettingToString(default_setting); 371 } 372 373 bool ContentSettingsHandler::GetDefaultSettingManagedFromModel( 374 ContentSettingsType type) { 375 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { 376 return web_ui_->GetProfile()-> 377 GetGeolocationContentSettingsMap()->IsDefaultContentSettingManaged(); 378 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { 379 return DesktopNotificationServiceFactory::GetForProfile( 380 web_ui_->GetProfile())->IsDefaultContentSettingManaged(); 381 } else { 382 return GetContentSettingsMap()->IsDefaultContentSettingManaged(type); 383 } 384 } 385 386 void ContentSettingsHandler::UpdateAllExceptionsViewsFromModel() { 387 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1; 388 type < CONTENT_SETTINGS_NUM_TYPES; ++type) { 389 UpdateExceptionsViewFromModel(static_cast<ContentSettingsType>(type)); 390 } 391 } 392 393 void ContentSettingsHandler::UpdateAllOTRExceptionsViewsFromModel() { 394 for (int type = CONTENT_SETTINGS_TYPE_DEFAULT + 1; 395 type < CONTENT_SETTINGS_NUM_TYPES; ++type) { 396 UpdateOTRExceptionsViewFromModel(static_cast<ContentSettingsType>(type)); 397 } 398 } 399 400 void ContentSettingsHandler::UpdateExceptionsViewFromModel( 401 ContentSettingsType type) { 402 switch (type) { 403 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 404 UpdateGeolocationExceptionsView(); 405 break; 406 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 407 UpdateNotificationExceptionsView(); 408 break; 409 case CONTENT_SETTINGS_TYPE_PRERENDER: 410 // Prerender is currently (02/24/2011) an experimental feature which is 411 // only turned on via about:flags. There is intentionally no UI in 412 // chrome://preferences for CONTENT_SETTINGS_TYPE_PRERENDER. 413 // TODO(cbentzel): Change once prerender moves out of about:flags. 414 break; 415 default: 416 UpdateExceptionsViewFromHostContentSettingsMap(type); 417 break; 418 } 419 } 420 421 void ContentSettingsHandler::UpdateOTRExceptionsViewFromModel( 422 ContentSettingsType type) { 423 switch (type) { 424 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 425 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 426 case CONTENT_SETTINGS_TYPE_PRERENDER: 427 break; 428 default: 429 UpdateExceptionsViewFromOTRHostContentSettingsMap(type); 430 break; 431 } 432 } 433 434 void ContentSettingsHandler::UpdateGeolocationExceptionsView() { 435 GeolocationContentSettingsMap* map = 436 web_ui_->GetProfile()->GetGeolocationContentSettingsMap(); 437 GeolocationContentSettingsMap::AllOriginsSettings all_settings = 438 map->GetAllOriginsSettings(); 439 GeolocationContentSettingsMap::AllOriginsSettings::const_iterator i; 440 441 ListValue exceptions; 442 for (i = all_settings.begin(); i != all_settings.end(); ++i) { 443 const GURL& origin = i->first; 444 const GeolocationContentSettingsMap::OneOriginSettings& one_settings = 445 i->second; 446 447 GeolocationContentSettingsMap::OneOriginSettings::const_iterator parent = 448 one_settings.find(origin); 449 450 // Add the "parent" entry for the non-embedded setting. 451 ContentSetting parent_setting = 452 parent == one_settings.end() ? CONTENT_SETTING_DEFAULT : parent->second; 453 exceptions.Append( 454 GetGeolocationExceptionForPage(origin, origin, parent_setting)); 455 456 // Add the "children" for any embedded settings. 457 GeolocationContentSettingsMap::OneOriginSettings::const_iterator j; 458 for (j = one_settings.begin(); j != one_settings.end(); ++j) { 459 // Skip the non-embedded setting which we already added above. 460 if (j == parent) 461 continue; 462 463 exceptions.Append( 464 GetGeolocationExceptionForPage(origin, j->first, j->second)); 465 } 466 } 467 468 StringValue type_string( 469 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_GEOLOCATION)); 470 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", 471 type_string, exceptions); 472 473 // This is mainly here to keep this function ideologically parallel to 474 // UpdateExceptionsViewFromHostContentSettingsMap(). 475 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_GEOLOCATION); 476 } 477 478 void ContentSettingsHandler::UpdateNotificationExceptionsView() { 479 DesktopNotificationService* service = 480 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile()); 481 482 std::vector<GURL> allowed(service->GetAllowedOrigins()); 483 std::vector<GURL> blocked(service->GetBlockedOrigins()); 484 485 ListValue exceptions; 486 for (size_t i = 0; i < allowed.size(); ++i) { 487 exceptions.Append( 488 GetNotificationExceptionForPage(allowed[i], CONTENT_SETTING_ALLOW)); 489 } 490 for (size_t i = 0; i < blocked.size(); ++i) { 491 exceptions.Append( 492 GetNotificationExceptionForPage(blocked[i], CONTENT_SETTING_BLOCK)); 493 } 494 495 StringValue type_string( 496 ContentSettingsTypeToGroupName(CONTENT_SETTINGS_TYPE_NOTIFICATIONS)); 497 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", 498 type_string, exceptions); 499 500 // This is mainly here to keep this function ideologically parallel to 501 // UpdateExceptionsViewFromHostContentSettingsMap(). 502 UpdateSettingDefaultFromModel(CONTENT_SETTINGS_TYPE_NOTIFICATIONS); 503 } 504 505 void ContentSettingsHandler::UpdateExceptionsViewFromHostContentSettingsMap( 506 ContentSettingsType type) { 507 HostContentSettingsMap::SettingsForOneType entries; 508 GetContentSettingsMap()->GetSettingsForOneType(type, "", &entries); 509 510 ListValue exceptions; 511 for (size_t i = 0; i < entries.size(); ++i) { 512 exceptions.Append(GetExceptionForPage(entries[i].first, entries[i].second)); 513 } 514 515 StringValue type_string(ContentSettingsTypeToGroupName(type)); 516 web_ui_->CallJavascriptFunction("ContentSettings.setExceptions", type_string, 517 exceptions); 518 519 UpdateExceptionsViewFromOTRHostContentSettingsMap(type); 520 521 // The default may also have changed (we won't get a separate notification). 522 // If it hasn't changed, this call will be harmless. 523 UpdateSettingDefaultFromModel(type); 524 } 525 526 void ContentSettingsHandler::UpdateExceptionsViewFromOTRHostContentSettingsMap( 527 ContentSettingsType type) { 528 const HostContentSettingsMap* otr_settings_map = GetOTRContentSettingsMap(); 529 if (!otr_settings_map) 530 return; 531 532 HostContentSettingsMap::SettingsForOneType otr_entries; 533 otr_settings_map->GetSettingsForOneType(type, "", &otr_entries); 534 535 ListValue otr_exceptions; 536 for (size_t i = 0; i < otr_entries.size(); ++i) { 537 otr_exceptions.Append(GetExceptionForPage(otr_entries[i].first, 538 otr_entries[i].second)); 539 } 540 541 StringValue type_string(ContentSettingsTypeToGroupName(type)); 542 web_ui_->CallJavascriptFunction("ContentSettings.setOTRExceptions", 543 type_string, otr_exceptions); 544 } 545 546 void ContentSettingsHandler::RegisterMessages() { 547 web_ui_->RegisterMessageCallback("setContentFilter", 548 NewCallback(this, 549 &ContentSettingsHandler::SetContentFilter)); 550 web_ui_->RegisterMessageCallback("setAllowThirdPartyCookies", 551 NewCallback(this, 552 &ContentSettingsHandler::SetAllowThirdPartyCookies)); 553 web_ui_->RegisterMessageCallback("removeException", 554 NewCallback(this, 555 &ContentSettingsHandler::RemoveException)); 556 web_ui_->RegisterMessageCallback("setException", 557 NewCallback(this, 558 &ContentSettingsHandler::SetException)); 559 web_ui_->RegisterMessageCallback("checkExceptionPatternValidity", 560 NewCallback(this, 561 &ContentSettingsHandler::CheckExceptionPatternValidity)); 562 } 563 564 void ContentSettingsHandler::SetContentFilter(const ListValue* args) { 565 DCHECK_EQ(2U, args->GetSize()); 566 std::string group, setting; 567 if (!(args->GetString(0, &group) && 568 args->GetString(1, &setting))) { 569 NOTREACHED(); 570 return; 571 } 572 573 ContentSetting default_setting = ContentSettingFromString(setting); 574 ContentSettingsType content_type = ContentSettingsTypeFromGroupName(group); 575 if (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { 576 web_ui_->GetProfile()->GetGeolocationContentSettingsMap()-> 577 SetDefaultContentSetting(default_setting); 578 } else if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { 579 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile())-> 580 SetDefaultContentSetting(default_setting); 581 } else { 582 GetContentSettingsMap()-> 583 SetDefaultContentSetting(content_type, default_setting); 584 } 585 } 586 587 void ContentSettingsHandler::SetAllowThirdPartyCookies(const ListValue* args) { 588 string16 allow = ExtractStringValue(args); 589 590 GetContentSettingsMap()->SetBlockThirdPartyCookies( 591 LowerCaseEqualsASCII(allow, "true")); 592 } 593 594 void ContentSettingsHandler::RemoveException(const ListValue* args) { 595 size_t arg_i = 0; 596 std::string type_string; 597 CHECK(args->GetString(arg_i++, &type_string)); 598 599 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string); 600 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION) { 601 std::string origin; 602 std::string embedding_origin; 603 bool rv = args->GetString(arg_i++, &origin); 604 DCHECK(rv); 605 rv = args->GetString(arg_i++, &embedding_origin); 606 DCHECK(rv); 607 608 web_ui_->GetProfile()->GetGeolocationContentSettingsMap()-> 609 SetContentSetting(GURL(origin), 610 GURL(embedding_origin), 611 CONTENT_SETTING_DEFAULT); 612 } else if (type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { 613 std::string origin; 614 std::string setting; 615 bool rv = args->GetString(arg_i++, &origin); 616 DCHECK(rv); 617 rv = args->GetString(arg_i++, &setting); 618 DCHECK(rv); 619 ContentSetting content_setting = ContentSettingFromString(setting); 620 if (content_setting == CONTENT_SETTING_ALLOW) { 621 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile())-> 622 ResetAllowedOrigin(GURL(origin)); 623 } else { 624 DCHECK_EQ(content_setting, CONTENT_SETTING_BLOCK); 625 DesktopNotificationServiceFactory::GetForProfile(web_ui_->GetProfile())-> 626 ResetBlockedOrigin(GURL(origin)); 627 } 628 } else { 629 std::string mode; 630 bool rv = args->GetString(arg_i++, &mode); 631 DCHECK(rv); 632 633 std::string pattern; 634 rv = args->GetString(arg_i++, &pattern); 635 DCHECK(rv); 636 637 HostContentSettingsMap* settings_map = 638 mode == "normal" ? GetContentSettingsMap() : 639 GetOTRContentSettingsMap(); 640 // The settings map could be null if the mode was OTR but the OTR profile 641 // got destroyed before we received this message. 642 if (settings_map) { 643 settings_map->SetContentSetting( 644 ContentSettingsPattern(pattern), 645 ContentSettingsTypeFromGroupName(type_string), 646 "", 647 CONTENT_SETTING_DEFAULT); 648 } 649 } 650 } 651 652 void ContentSettingsHandler::SetException(const ListValue* args) { 653 size_t arg_i = 0; 654 std::string type_string; 655 CHECK(args->GetString(arg_i++, &type_string)); 656 std::string mode; 657 CHECK(args->GetString(arg_i++, &mode)); 658 std::string pattern; 659 CHECK(args->GetString(arg_i++, &pattern)); 660 std::string setting; 661 CHECK(args->GetString(arg_i++, &setting)); 662 663 ContentSettingsType type = ContentSettingsTypeFromGroupName(type_string); 664 if (type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 665 type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS) { 666 NOTREACHED(); 667 return; 668 } 669 670 HostContentSettingsMap* settings_map = 671 mode == "normal" ? GetContentSettingsMap() : 672 GetOTRContentSettingsMap(); 673 674 // The settings map could be null if the mode was OTR but the OTR profile 675 // got destroyed before we received this message. 676 if (!settings_map) 677 return; 678 679 settings_map->SetContentSetting(ContentSettingsPattern(pattern), 680 type, 681 "", 682 ContentSettingFromString(setting)); 683 } 684 685 void ContentSettingsHandler::CheckExceptionPatternValidity( 686 const ListValue* args) { 687 size_t arg_i = 0; 688 Value* type; 689 CHECK(args->Get(arg_i++, &type)); 690 std::string mode_string; 691 CHECK(args->GetString(arg_i++, &mode_string)); 692 std::string pattern_string; 693 CHECK(args->GetString(arg_i++, &pattern_string)); 694 695 ContentSettingsPattern pattern(pattern_string); 696 697 scoped_ptr<Value> mode_value(Value::CreateStringValue(mode_string)); 698 scoped_ptr<Value> pattern_value(Value::CreateStringValue(pattern_string)); 699 scoped_ptr<Value> valid_value(Value::CreateBooleanValue(pattern.IsValid())); 700 701 web_ui_->CallJavascriptFunction( 702 "ContentSettings.patternValidityCheckComplete", 703 *type, 704 *mode_value.get(), 705 *pattern_value.get(), 706 *valid_value.get()); 707 } 708 709 // static 710 std::string ContentSettingsHandler::ContentSettingsTypeToGroupName( 711 ContentSettingsType type) { 712 if (type < CONTENT_SETTINGS_TYPE_COOKIES || 713 type >= CONTENT_SETTINGS_NUM_TYPES) { 714 NOTREACHED(); 715 return ""; 716 } 717 return kContentSettingsTypeGroupNames[type]; 718 } 719 720 HostContentSettingsMap* ContentSettingsHandler::GetContentSettingsMap() { 721 return web_ui_->GetProfile()->GetHostContentSettingsMap(); 722 } 723 724 HostContentSettingsMap* 725 ContentSettingsHandler::GetOTRContentSettingsMap() { 726 Profile* profile = web_ui_->GetProfile(); 727 if (profile->HasOffTheRecordProfile()) 728 return profile->GetOffTheRecordProfile()->GetHostContentSettingsMap(); 729 return NULL; 730 } 731