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/content_settings/host_content_settings_map.h" 6 7 #include <utility> 8 9 #include "base/basictypes.h" 10 #include "base/command_line.h" 11 #include "base/prefs/pref_service.h" 12 #include "base/stl_util.h" 13 #include "base/strings/string_util.h" 14 #include "base/strings/utf_string_conversions.h" 15 #include "base/time/clock.h" 16 #include "chrome/browser/content_settings/content_settings_default_provider.h" 17 #include "chrome/browser/content_settings/content_settings_policy_provider.h" 18 #include "chrome/browser/content_settings/content_settings_pref_provider.h" 19 #include "chrome/browser/content_settings/content_settings_utils.h" 20 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/pref_names.h" 22 #include "chrome/common/url_constants.h" 23 #include "components/content_settings/core/browser/content_settings_details.h" 24 #include "components/content_settings/core/browser/content_settings_observable_provider.h" 25 #include "components/content_settings/core/browser/content_settings_provider.h" 26 #include "components/content_settings/core/browser/content_settings_rule.h" 27 #include "components/content_settings/core/common/content_settings_pattern.h" 28 #include "components/pref_registry/pref_registry_syncable.h" 29 #include "content/public/browser/browser_thread.h" 30 #include "content/public/common/content_switches.h" 31 #include "net/base/net_errors.h" 32 #include "net/base/static_cookie_policy.h" 33 #include "url/gurl.h" 34 35 #if defined(ENABLE_EXTENSIONS) 36 #include "extensions/common/constants.h" 37 #endif 38 39 using content::BrowserThread; 40 41 namespace { 42 43 typedef std::vector<content_settings::Rule> Rules; 44 45 typedef std::pair<std::string, std::string> StringPair; 46 47 // TODO(bauerb): Expose constants. 48 const char* kProviderNames[] = { 49 "platform_app", 50 "policy", 51 "extension", 52 "override", 53 "preference", 54 "default" 55 }; 56 57 content_settings::SettingSource kProviderSourceMap[] = { 58 content_settings::SETTING_SOURCE_EXTENSION, 59 content_settings::SETTING_SOURCE_POLICY, 60 content_settings::SETTING_SOURCE_EXTENSION, 61 content_settings::SETTING_SOURCE_USER, 62 content_settings::SETTING_SOURCE_USER, 63 content_settings::SETTING_SOURCE_USER, 64 }; 65 COMPILE_ASSERT(arraysize(kProviderSourceMap) == 66 HostContentSettingsMap::NUM_PROVIDER_TYPES, 67 kProviderSourceMap_has_incorrect_size); 68 69 // Returns true if the |content_type| supports a resource identifier. 70 // Resource identifiers are supported (but not required) for plug-ins. 71 bool SupportsResourceIdentifier(ContentSettingsType content_type) { 72 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; 73 } 74 75 } // namespace 76 77 HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs, 78 bool incognito) 79 : 80 #ifndef NDEBUG 81 used_from_thread_id_(base::PlatformThread::CurrentId()), 82 #endif 83 prefs_(prefs), 84 is_off_the_record_(incognito) { 85 content_settings::ObservableProvider* policy_provider = 86 new content_settings::PolicyProvider(prefs_); 87 policy_provider->AddObserver(this); 88 content_settings_providers_[POLICY_PROVIDER] = policy_provider; 89 90 content_settings::ObservableProvider* pref_provider = 91 new content_settings::PrefProvider(prefs_, is_off_the_record_); 92 pref_provider->AddObserver(this); 93 content_settings_providers_[PREF_PROVIDER] = pref_provider; 94 95 content_settings::ObservableProvider* default_provider = 96 new content_settings::DefaultProvider(prefs_, is_off_the_record_); 97 default_provider->AddObserver(this); 98 content_settings_providers_[DEFAULT_PROVIDER] = default_provider; 99 100 content_settings_providers_[OVERRIDE_PROVIDER] = 101 new content_settings::OverrideProvider(prefs_, is_off_the_record_); 102 103 if (!is_off_the_record_) { 104 // Migrate obsolete preferences. 105 MigrateObsoleteClearOnExitPref(); 106 } 107 } 108 109 // static 110 void HostContentSettingsMap::RegisterProfilePrefs( 111 user_prefs::PrefRegistrySyncable* registry) { 112 registry->RegisterIntegerPref( 113 prefs::kContentSettingsWindowLastTabIndex, 114 0, 115 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 116 registry->RegisterBooleanPref( 117 prefs::kContentSettingsClearOnExitMigrated, 118 false, 119 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 120 121 // Register the prefs for the content settings providers. 122 content_settings::DefaultProvider::RegisterProfilePrefs(registry); 123 content_settings::PrefProvider::RegisterProfilePrefs(registry); 124 content_settings::PolicyProvider::RegisterProfilePrefs(registry); 125 content_settings::OverrideProvider::RegisterProfilePrefs(registry); 126 } 127 128 void HostContentSettingsMap::RegisterProvider( 129 ProviderType type, 130 scoped_ptr<content_settings::ObservableProvider> provider) { 131 DCHECK(!content_settings_providers_[type]); 132 provider->AddObserver(this); 133 content_settings_providers_[type] = provider.release(); 134 135 #ifndef NDEBUG 136 DCHECK_NE(used_from_thread_id_, base::kInvalidThreadId) 137 << "Used from multiple threads before initialization complete."; 138 #endif 139 140 OnContentSettingChanged(ContentSettingsPattern(), 141 ContentSettingsPattern(), 142 CONTENT_SETTINGS_TYPE_DEFAULT, 143 std::string()); 144 } 145 146 ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider( 147 ContentSettingsType content_type, 148 content_settings::ProviderInterface* provider) const { 149 scoped_ptr<content_settings::RuleIterator> rule_iterator( 150 provider->GetRuleIterator(content_type, std::string(), false)); 151 152 ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard(); 153 while (rule_iterator->HasNext()) { 154 content_settings::Rule rule = rule_iterator->Next(); 155 if (rule.primary_pattern == wildcard && 156 rule.secondary_pattern == wildcard) { 157 return content_settings::ValueToContentSetting(rule.value.get()); 158 } 159 } 160 return CONTENT_SETTING_DEFAULT; 161 } 162 163 ContentSetting HostContentSettingsMap::GetDefaultContentSetting( 164 ContentSettingsType content_type, 165 std::string* provider_id) const { 166 UsedContentSettingsProviders(); 167 168 // Iterate through the list of providers and return the first non-NULL value 169 // that matches |primary_url| and |secondary_url|. 170 for (ConstProviderIterator provider = content_settings_providers_.begin(); 171 provider != content_settings_providers_.end(); 172 ++provider) { 173 if (provider->first == PREF_PROVIDER || 174 provider->first == OVERRIDE_PROVIDER) 175 continue; 176 ContentSetting default_setting = 177 GetDefaultContentSettingFromProvider(content_type, provider->second); 178 if (default_setting != CONTENT_SETTING_DEFAULT) { 179 if (provider_id) 180 *provider_id = kProviderNames[provider->first]; 181 return default_setting; 182 } 183 } 184 185 return CONTENT_SETTING_DEFAULT; 186 } 187 188 ContentSetting HostContentSettingsMap::GetContentSetting( 189 const GURL& primary_url, 190 const GURL& secondary_url, 191 ContentSettingsType content_type, 192 const std::string& resource_identifier) const { 193 DCHECK(!ContentTypeHasCompoundValue(content_type)); 194 scoped_ptr<base::Value> value = GetWebsiteSetting( 195 primary_url, secondary_url, content_type, resource_identifier, NULL); 196 return content_settings::ValueToContentSetting(value.get()); 197 } 198 199 void HostContentSettingsMap::GetSettingsForOneType( 200 ContentSettingsType content_type, 201 const std::string& resource_identifier, 202 ContentSettingsForOneType* settings) const { 203 DCHECK(SupportsResourceIdentifier(content_type) || 204 resource_identifier.empty()); 205 DCHECK(settings); 206 UsedContentSettingsProviders(); 207 208 settings->clear(); 209 for (ConstProviderIterator provider = content_settings_providers_.begin(); 210 provider != content_settings_providers_.end(); 211 ++provider) { 212 if (provider->first == OVERRIDE_PROVIDER) 213 continue; 214 // For each provider, iterate first the incognito-specific rules, then the 215 // normal rules. 216 if (is_off_the_record_) { 217 AddSettingsForOneType(provider->second, 218 provider->first, 219 content_type, 220 resource_identifier, 221 settings, 222 true); 223 } 224 AddSettingsForOneType(provider->second, 225 provider->first, 226 content_type, 227 resource_identifier, 228 settings, 229 false); 230 } 231 } 232 233 void HostContentSettingsMap::SetDefaultContentSetting( 234 ContentSettingsType content_type, 235 ContentSetting setting) { 236 DCHECK(IsSettingAllowedForType(prefs_, setting, content_type)); 237 238 base::Value* value = NULL; 239 if (setting != CONTENT_SETTING_DEFAULT) 240 value = new base::FundamentalValue(setting); 241 SetWebsiteSetting( 242 ContentSettingsPattern::Wildcard(), 243 ContentSettingsPattern::Wildcard(), 244 content_type, 245 std::string(), 246 value); 247 } 248 249 void HostContentSettingsMap::SetWebsiteSetting( 250 const ContentSettingsPattern& primary_pattern, 251 const ContentSettingsPattern& secondary_pattern, 252 ContentSettingsType content_type, 253 const std::string& resource_identifier, 254 base::Value* value) { 255 DCHECK(IsValueAllowedForType(prefs_, value, content_type)); 256 DCHECK(SupportsResourceIdentifier(content_type) || 257 resource_identifier.empty()); 258 UsedContentSettingsProviders(); 259 260 for (ProviderIterator provider = content_settings_providers_.begin(); 261 provider != content_settings_providers_.end(); 262 ++provider) { 263 if (provider->second->SetWebsiteSetting(primary_pattern, 264 secondary_pattern, 265 content_type, 266 resource_identifier, 267 value)) { 268 return; 269 } 270 } 271 NOTREACHED(); 272 } 273 274 void HostContentSettingsMap::SetNarrowestWebsiteSetting( 275 const ContentSettingsPattern& primary_pattern, 276 const ContentSettingsPattern& secondary_pattern, 277 ContentSettingsType content_type, 278 const std::string& resource_identifier, 279 ContentSetting setting, 280 content_settings::SettingInfo existing_info) { 281 ContentSettingsPattern narrow_primary = primary_pattern; 282 ContentSettingsPattern narrow_secondary = secondary_pattern; 283 284 DCHECK_EQ(content_settings::SETTING_SOURCE_USER, existing_info.source); 285 ContentSettingsPattern::Relation r1 = 286 existing_info.primary_pattern.Compare(primary_pattern); 287 if (r1 == ContentSettingsPattern::PREDECESSOR) { 288 narrow_primary = existing_info.primary_pattern; 289 } else if (r1 == ContentSettingsPattern::IDENTITY) { 290 ContentSettingsPattern::Relation r2 = 291 existing_info.secondary_pattern.Compare(secondary_pattern); 292 DCHECK(r2 != ContentSettingsPattern::DISJOINT_ORDER_POST && 293 r2 != ContentSettingsPattern::DISJOINT_ORDER_PRE); 294 if (r2 == ContentSettingsPattern::PREDECESSOR) 295 narrow_secondary = existing_info.secondary_pattern; 296 } 297 298 SetContentSetting( 299 narrow_primary, narrow_secondary, content_type, std::string(), setting); 300 } 301 302 void HostContentSettingsMap::SetContentSetting( 303 const ContentSettingsPattern& primary_pattern, 304 const ContentSettingsPattern& secondary_pattern, 305 ContentSettingsType content_type, 306 const std::string& resource_identifier, 307 ContentSetting setting) { 308 DCHECK(!ContentTypeHasCompoundValue(content_type)); 309 310 if (setting == CONTENT_SETTING_ALLOW && 311 (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 312 content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS)) { 313 UpdateLastUsageByPattern(primary_pattern, secondary_pattern, content_type); 314 } 315 316 base::Value* value = NULL; 317 if (setting != CONTENT_SETTING_DEFAULT) 318 value = new base::FundamentalValue(setting); 319 SetWebsiteSetting(primary_pattern, 320 secondary_pattern, 321 content_type, 322 resource_identifier, 323 value); 324 } 325 326 ContentSetting HostContentSettingsMap::GetContentSettingAndMaybeUpdateLastUsage( 327 const GURL& primary_url, 328 const GURL& secondary_url, 329 ContentSettingsType content_type, 330 const std::string& resource_identifier) { 331 DCHECK_CURRENTLY_ON(BrowserThread::UI); 332 333 ContentSetting setting = GetContentSetting( 334 primary_url, secondary_url, content_type, resource_identifier); 335 if (setting == CONTENT_SETTING_ALLOW) { 336 UpdateLastUsageByPattern( 337 ContentSettingsPattern::FromURLNoWildcard(primary_url), 338 ContentSettingsPattern::FromURLNoWildcard(secondary_url), 339 content_type); 340 } 341 return setting; 342 } 343 344 void HostContentSettingsMap::UpdateLastUsage(const GURL& primary_url, 345 const GURL& secondary_url, 346 ContentSettingsType content_type) { 347 UpdateLastUsageByPattern( 348 ContentSettingsPattern::FromURLNoWildcard(primary_url), 349 ContentSettingsPattern::FromURLNoWildcard(secondary_url), 350 content_type); 351 } 352 353 void HostContentSettingsMap::UpdateLastUsageByPattern( 354 const ContentSettingsPattern& primary_pattern, 355 const ContentSettingsPattern& secondary_pattern, 356 ContentSettingsType content_type) { 357 UsedContentSettingsProviders(); 358 359 GetPrefProvider()->UpdateLastUsage( 360 primary_pattern, secondary_pattern, content_type); 361 362 FOR_EACH_OBSERVER( 363 content_settings::Observer, 364 observers_, 365 OnContentSettingUsed(primary_pattern, secondary_pattern, content_type)); 366 } 367 368 base::Time HostContentSettingsMap::GetLastUsage( 369 const GURL& primary_url, 370 const GURL& secondary_url, 371 ContentSettingsType content_type) { 372 return GetLastUsageByPattern( 373 ContentSettingsPattern::FromURLNoWildcard(primary_url), 374 ContentSettingsPattern::FromURLNoWildcard(secondary_url), 375 content_type); 376 } 377 378 base::Time HostContentSettingsMap::GetLastUsageByPattern( 379 const ContentSettingsPattern& primary_pattern, 380 const ContentSettingsPattern& secondary_pattern, 381 ContentSettingsType content_type) { 382 UsedContentSettingsProviders(); 383 384 return GetPrefProvider()->GetLastUsage( 385 primary_pattern, secondary_pattern, content_type); 386 } 387 388 ContentSetting HostContentSettingsMap::GetContentSettingWithoutOverride( 389 const GURL& primary_url, 390 const GURL& secondary_url, 391 ContentSettingsType content_type, 392 const std::string& resource_identifier) { 393 scoped_ptr<base::Value> value(GetWebsiteSettingWithoutOverride( 394 primary_url, secondary_url, content_type, resource_identifier, NULL)); 395 return content_settings::ValueToContentSetting(value.get()); 396 } 397 398 scoped_ptr<base::Value> 399 HostContentSettingsMap::GetWebsiteSettingWithoutOverride( 400 const GURL& primary_url, 401 const GURL& secondary_url, 402 ContentSettingsType content_type, 403 const std::string& resource_identifier, 404 content_settings::SettingInfo* info) const { 405 return GetWebsiteSettingInternal(primary_url, 406 secondary_url, 407 content_type, 408 resource_identifier, 409 info, 410 false); 411 } 412 413 void HostContentSettingsMap::SetContentSettingOverride( 414 ContentSettingsType content_type, 415 bool is_enabled) { 416 UsedContentSettingsProviders(); 417 418 content_settings::OverrideProvider* override = 419 static_cast<content_settings::OverrideProvider*>( 420 content_settings_providers_[OVERRIDE_PROVIDER]); 421 override->SetOverrideSetting(content_type, is_enabled); 422 } 423 424 bool HostContentSettingsMap::GetContentSettingOverride( 425 ContentSettingsType content_type) { 426 UsedContentSettingsProviders(); 427 428 content_settings::OverrideProvider* override = 429 static_cast<content_settings::OverrideProvider*>( 430 content_settings_providers_[OVERRIDE_PROVIDER]); 431 return override->IsEnabled(content_type); 432 } 433 434 void HostContentSettingsMap::AddObserver(content_settings::Observer* observer) { 435 observers_.AddObserver(observer); 436 } 437 438 void HostContentSettingsMap::RemoveObserver( 439 content_settings::Observer* observer) { 440 observers_.RemoveObserver(observer); 441 } 442 443 void HostContentSettingsMap::SetPrefClockForTesting( 444 scoped_ptr<base::Clock> clock) { 445 UsedContentSettingsProviders(); 446 447 GetPrefProvider()->SetClockForTesting(clock.Pass()); 448 } 449 450 void HostContentSettingsMap::AddExceptionForURL( 451 const GURL& primary_url, 452 const GURL& secondary_url, 453 ContentSettingsType content_type, 454 ContentSetting setting) { 455 // TODO(markusheintz): Until the UI supports pattern pairs, both urls must 456 // match. 457 DCHECK(primary_url == secondary_url); 458 DCHECK(!ContentTypeHasCompoundValue(content_type)); 459 460 // Make sure there is no entry that would override the pattern we are about 461 // to insert for exactly this URL. 462 SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url), 463 ContentSettingsPattern::Wildcard(), 464 content_type, 465 std::string(), 466 CONTENT_SETTING_DEFAULT); 467 468 SetContentSetting(ContentSettingsPattern::FromURL(primary_url), 469 ContentSettingsPattern::Wildcard(), 470 content_type, 471 std::string(), 472 setting); 473 } 474 475 void HostContentSettingsMap::ClearSettingsForOneType( 476 ContentSettingsType content_type) { 477 UsedContentSettingsProviders(); 478 for (ProviderIterator provider = content_settings_providers_.begin(); 479 provider != content_settings_providers_.end(); 480 ++provider) { 481 provider->second->ClearAllContentSettingsRules(content_type); 482 } 483 } 484 485 bool HostContentSettingsMap::IsValueAllowedForType( 486 PrefService* prefs, const base::Value* value, ContentSettingsType type) { 487 return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType( 488 prefs, content_settings::ValueToContentSetting(value), type); 489 } 490 491 // static 492 bool HostContentSettingsMap::IsSettingAllowedForType( 493 PrefService* prefs, 494 ContentSetting setting, 495 ContentSettingsType content_type) { 496 // We don't yet support stored content settings for mixed scripting. 497 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) 498 return false; 499 500 // BLOCK semantics are not implemented for fullscreen. 501 if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN && 502 setting == CONTENT_SETTING_BLOCK) { 503 return false; 504 } 505 506 // We don't support ALLOW for media default setting. 507 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM && 508 setting == CONTENT_SETTING_ALLOW) { 509 return false; 510 } 511 512 #if defined(OS_ANDROID) 513 // App banners store a dictionary. 514 if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER) 515 return false; 516 #endif 517 518 // DEFAULT, ALLOW and BLOCK are always allowed. 519 if (setting == CONTENT_SETTING_DEFAULT || 520 setting == CONTENT_SETTING_ALLOW || 521 setting == CONTENT_SETTING_BLOCK) { 522 return true; 523 } 524 switch (content_type) { 525 case CONTENT_SETTINGS_TYPE_COOKIES: 526 return setting == CONTENT_SETTING_SESSION_ONLY; 527 case CONTENT_SETTINGS_TYPE_PLUGINS: 528 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 529 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 530 case CONTENT_SETTINGS_TYPE_MOUSELOCK: 531 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 532 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 533 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 534 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: 535 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: 536 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: 537 return setting == CONTENT_SETTING_ASK; 538 default: 539 return false; 540 } 541 } 542 543 // static 544 bool HostContentSettingsMap::ContentTypeHasCompoundValue( 545 ContentSettingsType type) { 546 // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE, 547 // CONTENT_SETTINGS_TYPE_MEDIASTREAM, and 548 // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS are of type dictionary/map. 549 // Compound types like dictionaries can't be mapped to the type 550 // |ContentSetting|. 551 #if defined(OS_ANDROID) 552 if (type == CONTENT_SETTINGS_TYPE_APP_BANNER) 553 return true; 554 #endif 555 556 return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE || 557 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM || 558 type == CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); 559 } 560 561 void HostContentSettingsMap::OnContentSettingChanged( 562 const ContentSettingsPattern& primary_pattern, 563 const ContentSettingsPattern& secondary_pattern, 564 ContentSettingsType content_type, 565 std::string resource_identifier) { 566 FOR_EACH_OBSERVER(content_settings::Observer, 567 observers_, 568 OnContentSettingChanged(primary_pattern, 569 secondary_pattern, 570 content_type, 571 resource_identifier)); 572 } 573 574 HostContentSettingsMap::~HostContentSettingsMap() { 575 DCHECK(!prefs_); 576 STLDeleteValues(&content_settings_providers_); 577 } 578 579 void HostContentSettingsMap::ShutdownOnUIThread() { 580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 581 DCHECK(prefs_); 582 prefs_ = NULL; 583 for (ProviderIterator it = content_settings_providers_.begin(); 584 it != content_settings_providers_.end(); 585 ++it) { 586 it->second->ShutdownOnUIThread(); 587 } 588 } 589 590 void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() { 591 // Don't migrate more than once. 592 if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) && 593 prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) { 594 return; 595 } 596 597 if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) { 598 // Nothing to be done 599 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 600 return; 601 } 602 603 // Change the default cookie settings: 604 // old new 605 // ---------------- ---------------- 606 // ALLOW SESSION_ONLY 607 // SESSION_ONLY SESSION_ONLY 608 // BLOCK BLOCK 609 ContentSetting default_setting = GetDefaultContentSettingFromProvider( 610 CONTENT_SETTINGS_TYPE_COOKIES, 611 content_settings_providers_[DEFAULT_PROVIDER]); 612 if (default_setting == CONTENT_SETTING_ALLOW) { 613 SetDefaultContentSetting( 614 CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY); 615 } 616 617 // Change the exceptions using the same rules. 618 ContentSettingsForOneType exceptions; 619 AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER], 620 PREF_PROVIDER, 621 CONTENT_SETTINGS_TYPE_COOKIES, 622 std::string(), 623 &exceptions, 624 false); 625 for (ContentSettingsForOneType::iterator it = exceptions.begin(); 626 it != exceptions.end(); ++it) { 627 if (it->setting != CONTENT_SETTING_ALLOW) 628 continue; 629 SetWebsiteSetting(it->primary_pattern, 630 it->secondary_pattern, 631 CONTENT_SETTINGS_TYPE_COOKIES, 632 std::string(), 633 new base::FundamentalValue(CONTENT_SETTING_SESSION_ONLY)); 634 } 635 636 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 637 } 638 639 void HostContentSettingsMap::AddSettingsForOneType( 640 const content_settings::ProviderInterface* provider, 641 ProviderType provider_type, 642 ContentSettingsType content_type, 643 const std::string& resource_identifier, 644 ContentSettingsForOneType* settings, 645 bool incognito) const { 646 scoped_ptr<content_settings::RuleIterator> rule_iterator( 647 provider->GetRuleIterator(content_type, 648 resource_identifier, 649 incognito)); 650 while (rule_iterator->HasNext()) { 651 const content_settings::Rule& rule = rule_iterator->Next(); 652 ContentSetting setting_value = CONTENT_SETTING_DEFAULT; 653 // TODO(bauerb): Return rules as a list of values, not content settings. 654 // Handle the case using compound values for its exceptions and arbitrary 655 // values for its default setting. Here we assume all the exceptions 656 // are granted as |CONTENT_SETTING_ALLOW|. 657 if (ContentTypeHasCompoundValue(content_type) && 658 rule.value.get() && 659 rule.primary_pattern != ContentSettingsPattern::Wildcard()) { 660 setting_value = CONTENT_SETTING_ALLOW; 661 } else { 662 setting_value = content_settings::ValueToContentSetting(rule.value.get()); 663 } 664 settings->push_back(ContentSettingPatternSource( 665 rule.primary_pattern, rule.secondary_pattern, 666 setting_value, 667 kProviderNames[provider_type], 668 incognito)); 669 } 670 } 671 672 void HostContentSettingsMap::UsedContentSettingsProviders() const { 673 #ifndef NDEBUG 674 if (used_from_thread_id_ == base::kInvalidThreadId) 675 return; 676 677 if (base::PlatformThread::CurrentId() != used_from_thread_id_) 678 used_from_thread_id_ = base::kInvalidThreadId; 679 #endif 680 } 681 682 bool HostContentSettingsMap::ShouldAllowAllContent( 683 const GURL& primary_url, 684 const GURL& secondary_url, 685 ContentSettingsType content_type) { 686 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS || 687 content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 688 content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { 689 return false; 690 } 691 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) 692 if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) { 693 return false; 694 } 695 #endif 696 if (secondary_url.SchemeIs(content::kChromeUIScheme) && 697 content_type == CONTENT_SETTINGS_TYPE_COOKIES && 698 primary_url.SchemeIsSecure()) { 699 return true; 700 } 701 #if defined(ENABLE_EXTENSIONS) 702 if (primary_url.SchemeIs(extensions::kExtensionScheme)) { 703 switch (content_type) { 704 case CONTENT_SETTINGS_TYPE_PLUGINS: 705 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 706 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 707 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 708 return false; 709 case CONTENT_SETTINGS_TYPE_COOKIES: 710 return secondary_url.SchemeIs(extensions::kExtensionScheme); 711 default: 712 return true; 713 } 714 } 715 #endif 716 return primary_url.SchemeIs(content::kChromeDevToolsScheme) || 717 primary_url.SchemeIs(content::kChromeUIScheme); 718 } 719 720 scoped_ptr<base::Value> HostContentSettingsMap::GetWebsiteSetting( 721 const GURL& primary_url, 722 const GURL& secondary_url, 723 ContentSettingsType content_type, 724 const std::string& resource_identifier, 725 content_settings::SettingInfo* info) const { 726 DCHECK(SupportsResourceIdentifier(content_type) || 727 resource_identifier.empty()); 728 729 // Check if the scheme of the requesting url is whitelisted. 730 if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) { 731 if (info) { 732 info->source = content_settings::SETTING_SOURCE_WHITELIST; 733 info->primary_pattern = ContentSettingsPattern::Wildcard(); 734 info->secondary_pattern = ContentSettingsPattern::Wildcard(); 735 } 736 return scoped_ptr<base::Value>( 737 new base::FundamentalValue(CONTENT_SETTING_ALLOW)); 738 } 739 740 return GetWebsiteSettingInternal(primary_url, 741 secondary_url, 742 content_type, 743 resource_identifier, 744 info, 745 true); 746 } 747 748 // static 749 HostContentSettingsMap::ProviderType 750 HostContentSettingsMap::GetProviderTypeFromSource(const std::string& source) { 751 for (size_t i = 0; i < arraysize(kProviderNames); ++i) { 752 if (source == kProviderNames[i]) 753 return static_cast<ProviderType>(i); 754 } 755 756 NOTREACHED(); 757 return DEFAULT_PROVIDER; 758 } 759 760 content_settings::PrefProvider* HostContentSettingsMap::GetPrefProvider() { 761 return static_cast<content_settings::PrefProvider*>( 762 content_settings_providers_[PREF_PROVIDER]); 763 } 764 765 scoped_ptr<base::Value> HostContentSettingsMap::GetWebsiteSettingInternal( 766 const GURL& primary_url, 767 const GURL& secondary_url, 768 ContentSettingsType content_type, 769 const std::string& resource_identifier, 770 content_settings::SettingInfo* info, 771 bool get_override) const { 772 UsedContentSettingsProviders(); 773 ContentSettingsPattern* primary_pattern = NULL; 774 ContentSettingsPattern* secondary_pattern = NULL; 775 if (info) { 776 primary_pattern = &info->primary_pattern; 777 secondary_pattern = &info->secondary_pattern; 778 } 779 780 // The list of |content_settings_providers_| is ordered according to their 781 // precedence. 782 for (ConstProviderIterator provider = content_settings_providers_.begin(); 783 provider != content_settings_providers_.end(); 784 ++provider) { 785 if (!get_override && provider->first == OVERRIDE_PROVIDER) 786 continue; 787 788 scoped_ptr<base::Value> value( 789 content_settings::GetContentSettingValueAndPatterns(provider->second, 790 primary_url, 791 secondary_url, 792 content_type, 793 resource_identifier, 794 is_off_the_record_, 795 primary_pattern, 796 secondary_pattern)); 797 if (value) { 798 if (info) 799 info->source = kProviderSourceMap[provider->first]; 800 return value.Pass(); 801 } 802 } 803 804 if (info) { 805 info->source = content_settings::SETTING_SOURCE_NONE; 806 info->primary_pattern = ContentSettingsPattern(); 807 info->secondary_pattern = ContentSettingsPattern(); 808 } 809 return scoped_ptr<base::Value>(); 810 } 811