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 "chrome/browser/chrome_notification_types.h" 16 #include "chrome/browser/content_settings/content_settings_custom_extension_provider.h" 17 #include "chrome/browser/content_settings/content_settings_default_provider.h" 18 #include "chrome/browser/content_settings/content_settings_details.h" 19 #include "chrome/browser/content_settings/content_settings_internal_extension_provider.h" 20 #include "chrome/browser/content_settings/content_settings_observable_provider.h" 21 #include "chrome/browser/content_settings/content_settings_policy_provider.h" 22 #include "chrome/browser/content_settings/content_settings_pref_provider.h" 23 #include "chrome/browser/content_settings/content_settings_provider.h" 24 #include "chrome/browser/content_settings/content_settings_rule.h" 25 #include "chrome/browser/content_settings/content_settings_utils.h" 26 #include "chrome/browser/extensions/api/content_settings/content_settings_service.h" 27 #include "chrome/browser/extensions/extension_service.h" 28 #include "chrome/common/chrome_switches.h" 29 #include "chrome/common/content_settings_pattern.h" 30 #include "chrome/common/pref_names.h" 31 #include "chrome/common/url_constants.h" 32 #include "components/pref_registry/pref_registry_syncable.h" 33 #include "content/public/browser/browser_thread.h" 34 #include "content/public/browser/notification_service.h" 35 #include "content/public/browser/notification_source.h" 36 #include "content/public/browser/user_metrics.h" 37 #include "content/public/common/content_switches.h" 38 #include "extensions/browser/extension_prefs.h" 39 #include "extensions/common/constants.h" 40 #include "net/base/net_errors.h" 41 #include "net/base/static_cookie_policy.h" 42 #include "url/gurl.h" 43 44 using base::UserMetricsAction; 45 using content::BrowserThread; 46 47 namespace { 48 49 typedef std::vector<content_settings::Rule> Rules; 50 51 typedef std::pair<std::string, std::string> StringPair; 52 53 const char* kProviderNames[] = { 54 "platform_app", 55 "policy", 56 "extension", 57 "preference", 58 "default" 59 }; 60 61 content_settings::SettingSource kProviderSourceMap[] = { 62 content_settings::SETTING_SOURCE_EXTENSION, 63 content_settings::SETTING_SOURCE_POLICY, 64 content_settings::SETTING_SOURCE_EXTENSION, 65 content_settings::SETTING_SOURCE_USER, 66 content_settings::SETTING_SOURCE_USER, 67 }; 68 COMPILE_ASSERT(arraysize(kProviderSourceMap) == 69 HostContentSettingsMap::NUM_PROVIDER_TYPES, 70 kProviderSourceMap_has_incorrect_size); 71 72 // Returns true if the |content_type| supports a resource identifier. 73 // Resource identifiers are supported (but not required) for plug-ins. 74 bool SupportsResourceIdentifier(ContentSettingsType content_type) { 75 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; 76 } 77 78 } // namespace 79 80 HostContentSettingsMap::HostContentSettingsMap( 81 PrefService* prefs, 82 bool incognito) : 83 #ifndef NDEBUG 84 used_from_thread_id_(base::PlatformThread::CurrentId()), 85 #endif 86 prefs_(prefs), 87 is_off_the_record_(incognito) { 88 content_settings::ObservableProvider* policy_provider = 89 new content_settings::PolicyProvider(prefs_); 90 policy_provider->AddObserver(this); 91 content_settings_providers_[POLICY_PROVIDER] = policy_provider; 92 93 content_settings::ObservableProvider* pref_provider = 94 new content_settings::PrefProvider(prefs_, is_off_the_record_); 95 pref_provider->AddObserver(this); 96 content_settings_providers_[PREF_PROVIDER] = pref_provider; 97 98 content_settings::ObservableProvider* default_provider = 99 new content_settings::DefaultProvider(prefs_, is_off_the_record_); 100 default_provider->AddObserver(this); 101 content_settings_providers_[DEFAULT_PROVIDER] = default_provider; 102 103 if (!is_off_the_record_) { 104 // Migrate obsolete preferences. 105 MigrateObsoleteClearOnExitPref(); 106 } 107 } 108 109 #if defined(ENABLE_EXTENSIONS) 110 void HostContentSettingsMap::RegisterExtensionService( 111 ExtensionService* extension_service) { 112 DCHECK(extension_service); 113 DCHECK(!content_settings_providers_[INTERNAL_EXTENSION_PROVIDER]); 114 DCHECK(!content_settings_providers_[CUSTOM_EXTENSION_PROVIDER]); 115 116 content_settings::InternalExtensionProvider* internal_extension_provider = 117 new content_settings::InternalExtensionProvider(extension_service); 118 internal_extension_provider->AddObserver(this); 119 content_settings_providers_[INTERNAL_EXTENSION_PROVIDER] = 120 internal_extension_provider; 121 122 content_settings::ObservableProvider* custom_extension_provider = 123 new content_settings::CustomExtensionProvider( 124 extensions::ContentSettingsService::Get( 125 extension_service->GetBrowserContext())->content_settings_store(), 126 is_off_the_record_); 127 custom_extension_provider->AddObserver(this); 128 content_settings_providers_[CUSTOM_EXTENSION_PROVIDER] = 129 custom_extension_provider; 130 131 #ifndef NDEBUG 132 DCHECK(used_from_thread_id_ != base::kInvalidThreadId) 133 << "Used from multiple threads before initialization complete."; 134 #endif 135 136 OnContentSettingChanged(ContentSettingsPattern(), 137 ContentSettingsPattern(), 138 CONTENT_SETTINGS_TYPE_DEFAULT, 139 std::string()); 140 } 141 #endif 142 143 // static 144 void HostContentSettingsMap::RegisterProfilePrefs( 145 user_prefs::PrefRegistrySyncable* registry) { 146 registry->RegisterIntegerPref( 147 prefs::kContentSettingsWindowLastTabIndex, 148 0, 149 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 150 registry->RegisterIntegerPref( 151 prefs::kContentSettingsDefaultWhitelistVersion, 152 0, 153 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 154 registry->RegisterBooleanPref( 155 prefs::kContentSettingsClearOnExitMigrated, 156 false, 157 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF); 158 159 // Register the prefs for the content settings providers. 160 content_settings::DefaultProvider::RegisterProfilePrefs(registry); 161 content_settings::PrefProvider::RegisterProfilePrefs(registry); 162 content_settings::PolicyProvider::RegisterProfilePrefs(registry); 163 } 164 165 ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider( 166 ContentSettingsType content_type, 167 content_settings::ProviderInterface* provider) const { 168 scoped_ptr<content_settings::RuleIterator> rule_iterator( 169 provider->GetRuleIterator(content_type, std::string(), false)); 170 171 ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard(); 172 while (rule_iterator->HasNext()) { 173 content_settings::Rule rule = rule_iterator->Next(); 174 if (rule.primary_pattern == wildcard && 175 rule.secondary_pattern == wildcard) { 176 return content_settings::ValueToContentSetting(rule.value.get()); 177 } 178 } 179 return CONTENT_SETTING_DEFAULT; 180 } 181 182 ContentSetting HostContentSettingsMap::GetDefaultContentSetting( 183 ContentSettingsType content_type, 184 std::string* provider_id) const { 185 UsedContentSettingsProviders(); 186 187 // Iterate through the list of providers and return the first non-NULL value 188 // that matches |primary_url| and |secondary_url|. 189 for (ConstProviderIterator provider = content_settings_providers_.begin(); 190 provider != content_settings_providers_.end(); 191 ++provider) { 192 if (provider->first == PREF_PROVIDER) 193 continue; 194 ContentSetting default_setting = 195 GetDefaultContentSettingFromProvider(content_type, provider->second); 196 if (default_setting != CONTENT_SETTING_DEFAULT) { 197 if (provider_id) 198 *provider_id = kProviderNames[provider->first]; 199 return default_setting; 200 } 201 } 202 203 // The method GetDefaultContentSetting always has to return an explicit 204 // value that is to be used as default. We here rely on the 205 // DefaultProvider to always provide a value. 206 NOTREACHED(); 207 return CONTENT_SETTING_DEFAULT; 208 } 209 210 ContentSetting HostContentSettingsMap::GetContentSetting( 211 const GURL& primary_url, 212 const GURL& secondary_url, 213 ContentSettingsType content_type, 214 const std::string& resource_identifier) const { 215 DCHECK(!ContentTypeHasCompoundValue(content_type)); 216 scoped_ptr<base::Value> value(GetWebsiteSetting( 217 primary_url, secondary_url, content_type, resource_identifier, NULL)); 218 return content_settings::ValueToContentSetting(value.get()); 219 } 220 221 void HostContentSettingsMap::GetSettingsForOneType( 222 ContentSettingsType content_type, 223 const std::string& resource_identifier, 224 ContentSettingsForOneType* settings) const { 225 DCHECK(SupportsResourceIdentifier(content_type) || 226 resource_identifier.empty()); 227 DCHECK(settings); 228 UsedContentSettingsProviders(); 229 230 settings->clear(); 231 for (ConstProviderIterator provider = content_settings_providers_.begin(); 232 provider != content_settings_providers_.end(); 233 ++provider) { 234 // For each provider, iterate first the incognito-specific rules, then the 235 // normal rules. 236 if (is_off_the_record_) { 237 AddSettingsForOneType(provider->second, 238 provider->first, 239 content_type, 240 resource_identifier, 241 settings, 242 true); 243 } 244 AddSettingsForOneType(provider->second, 245 provider->first, 246 content_type, 247 resource_identifier, 248 settings, 249 false); 250 } 251 } 252 253 void HostContentSettingsMap::SetDefaultContentSetting( 254 ContentSettingsType content_type, 255 ContentSetting setting) { 256 DCHECK(IsSettingAllowedForType(prefs_, setting, content_type)); 257 258 base::Value* value = NULL; 259 if (setting != CONTENT_SETTING_DEFAULT) 260 value = base::Value::CreateIntegerValue(setting); 261 SetWebsiteSetting( 262 ContentSettingsPattern::Wildcard(), 263 ContentSettingsPattern::Wildcard(), 264 content_type, 265 std::string(), 266 value); 267 } 268 269 void HostContentSettingsMap::SetWebsiteSetting( 270 const ContentSettingsPattern& primary_pattern, 271 const ContentSettingsPattern& secondary_pattern, 272 ContentSettingsType content_type, 273 const std::string& resource_identifier, 274 base::Value* value) { 275 DCHECK(IsValueAllowedForType(prefs_, value, content_type)); 276 DCHECK(SupportsResourceIdentifier(content_type) || 277 resource_identifier.empty()); 278 UsedContentSettingsProviders(); 279 280 for (ProviderIterator provider = content_settings_providers_.begin(); 281 provider != content_settings_providers_.end(); 282 ++provider) { 283 if (provider->second->SetWebsiteSetting(primary_pattern, 284 secondary_pattern, 285 content_type, 286 resource_identifier, 287 value)) { 288 return; 289 } 290 } 291 NOTREACHED(); 292 } 293 294 void HostContentSettingsMap::SetContentSetting( 295 const ContentSettingsPattern& primary_pattern, 296 const ContentSettingsPattern& secondary_pattern, 297 ContentSettingsType content_type, 298 const std::string& resource_identifier, 299 ContentSetting setting) { 300 DCHECK(!ContentTypeHasCompoundValue(content_type)); 301 base::Value* value = NULL; 302 if (setting != CONTENT_SETTING_DEFAULT) 303 value = base::Value::CreateIntegerValue(setting); 304 SetWebsiteSetting(primary_pattern, 305 secondary_pattern, 306 content_type, 307 resource_identifier, 308 value); 309 } 310 311 void HostContentSettingsMap::AddExceptionForURL( 312 const GURL& primary_url, 313 const GURL& secondary_url, 314 ContentSettingsType content_type, 315 ContentSetting setting) { 316 // TODO(markusheintz): Until the UI supports pattern pairs, both urls must 317 // match. 318 DCHECK(primary_url == secondary_url); 319 DCHECK(!ContentTypeHasCompoundValue(content_type)); 320 321 // Make sure there is no entry that would override the pattern we are about 322 // to insert for exactly this URL. 323 SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url), 324 ContentSettingsPattern::Wildcard(), 325 content_type, 326 std::string(), 327 CONTENT_SETTING_DEFAULT); 328 329 SetContentSetting(ContentSettingsPattern::FromURL(primary_url), 330 ContentSettingsPattern::Wildcard(), 331 content_type, 332 std::string(), 333 setting); 334 } 335 336 void HostContentSettingsMap::ClearSettingsForOneType( 337 ContentSettingsType content_type) { 338 UsedContentSettingsProviders(); 339 for (ProviderIterator provider = content_settings_providers_.begin(); 340 provider != content_settings_providers_.end(); 341 ++provider) { 342 provider->second->ClearAllContentSettingsRules(content_type); 343 } 344 } 345 346 bool HostContentSettingsMap::IsValueAllowedForType( 347 PrefService* prefs, const base::Value* value, ContentSettingsType type) { 348 return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType( 349 prefs, content_settings::ValueToContentSetting(value), type); 350 } 351 352 // static 353 bool HostContentSettingsMap::IsSettingAllowedForType( 354 PrefService* prefs, 355 ContentSetting setting, 356 ContentSettingsType content_type) { 357 // We don't yet support stored content settings for mixed scripting. 358 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT) 359 return false; 360 361 // BLOCK semantics are not implemented for fullscreen. 362 if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN && 363 setting == CONTENT_SETTING_BLOCK) { 364 return false; 365 } 366 367 // We don't support ALLOW for media default setting. 368 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM && 369 setting == CONTENT_SETTING_ALLOW) { 370 return false; 371 } 372 373 #if defined(OS_ANDROID) 374 // App banners store a dictionary. 375 if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER) 376 return false; 377 #endif 378 379 // DEFAULT, ALLOW and BLOCK are always allowed. 380 if (setting == CONTENT_SETTING_DEFAULT || 381 setting == CONTENT_SETTING_ALLOW || 382 setting == CONTENT_SETTING_BLOCK) { 383 return true; 384 } 385 switch (content_type) { 386 case CONTENT_SETTINGS_TYPE_COOKIES: 387 return setting == CONTENT_SETTING_SESSION_ONLY; 388 case CONTENT_SETTINGS_TYPE_PLUGINS: 389 case CONTENT_SETTINGS_TYPE_GEOLOCATION: 390 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS: 391 case CONTENT_SETTINGS_TYPE_MOUSELOCK: 392 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 393 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 394 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 395 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER: 396 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS: 397 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX: 398 return setting == CONTENT_SETTING_ASK; 399 default: 400 return false; 401 } 402 } 403 404 // static 405 bool HostContentSettingsMap::ContentTypeHasCompoundValue( 406 ContentSettingsType type) { 407 // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE and 408 // CONTENT_SETTINGS_TYPE_MEDIASTREAM are of type dictionary/map. Compound 409 // types like dictionaries can't be mapped to the type |ContentSetting|. 410 #if defined(OS_ANDROID) 411 if (type == CONTENT_SETTINGS_TYPE_APP_BANNER) 412 return true; 413 #endif 414 415 return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE || 416 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM); 417 } 418 419 void HostContentSettingsMap::OnContentSettingChanged( 420 const ContentSettingsPattern& primary_pattern, 421 const ContentSettingsPattern& secondary_pattern, 422 ContentSettingsType content_type, 423 std::string resource_identifier) { 424 const ContentSettingsDetails details(primary_pattern, 425 secondary_pattern, 426 content_type, 427 resource_identifier); 428 content::NotificationService::current()->Notify( 429 chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED, 430 content::Source<HostContentSettingsMap>(this), 431 content::Details<const ContentSettingsDetails>(&details)); 432 } 433 434 HostContentSettingsMap::~HostContentSettingsMap() { 435 DCHECK(!prefs_); 436 STLDeleteValues(&content_settings_providers_); 437 } 438 439 void HostContentSettingsMap::ShutdownOnUIThread() { 440 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 441 DCHECK(prefs_); 442 prefs_ = NULL; 443 for (ProviderIterator it = content_settings_providers_.begin(); 444 it != content_settings_providers_.end(); 445 ++it) { 446 it->second->ShutdownOnUIThread(); 447 } 448 } 449 450 void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() { 451 // Don't migrate more than once. 452 if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) && 453 prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) { 454 return; 455 } 456 457 if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) { 458 // Nothing to be done 459 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 460 return; 461 } 462 463 // Change the default cookie settings: 464 // old new 465 // ---------------- ---------------- 466 // ALLOW SESSION_ONLY 467 // SESSION_ONLY SESSION_ONLY 468 // BLOCK BLOCK 469 ContentSetting default_setting = GetDefaultContentSettingFromProvider( 470 CONTENT_SETTINGS_TYPE_COOKIES, 471 content_settings_providers_[DEFAULT_PROVIDER]); 472 if (default_setting == CONTENT_SETTING_ALLOW) { 473 SetDefaultContentSetting( 474 CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY); 475 } 476 477 // Change the exceptions using the same rules. 478 ContentSettingsForOneType exceptions; 479 AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER], 480 PREF_PROVIDER, 481 CONTENT_SETTINGS_TYPE_COOKIES, 482 std::string(), 483 &exceptions, 484 false); 485 for (ContentSettingsForOneType::iterator it = exceptions.begin(); 486 it != exceptions.end(); ++it) { 487 if (it->setting != CONTENT_SETTING_ALLOW) 488 continue; 489 SetWebsiteSetting(it->primary_pattern, 490 it->secondary_pattern, 491 CONTENT_SETTINGS_TYPE_COOKIES, 492 std::string(), 493 base::Value::CreateIntegerValue( 494 CONTENT_SETTING_SESSION_ONLY)); 495 } 496 497 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true); 498 } 499 500 void HostContentSettingsMap::AddSettingsForOneType( 501 const content_settings::ProviderInterface* provider, 502 ProviderType provider_type, 503 ContentSettingsType content_type, 504 const std::string& resource_identifier, 505 ContentSettingsForOneType* settings, 506 bool incognito) const { 507 scoped_ptr<content_settings::RuleIterator> rule_iterator( 508 provider->GetRuleIterator(content_type, 509 resource_identifier, 510 incognito)); 511 while (rule_iterator->HasNext()) { 512 const content_settings::Rule& rule = rule_iterator->Next(); 513 ContentSetting setting_value = CONTENT_SETTING_DEFAULT; 514 // TODO(bauerb): Return rules as a list of values, not content settings. 515 // Handle the case using compound values for its exceptions and arbitrary 516 // values for its default setting. Here we assume all the exceptions 517 // are granted as |CONTENT_SETTING_ALLOW|. 518 if (ContentTypeHasCompoundValue(content_type) && 519 rule.value.get() && 520 rule.primary_pattern != ContentSettingsPattern::Wildcard()) { 521 setting_value = CONTENT_SETTING_ALLOW; 522 } else { 523 setting_value = content_settings::ValueToContentSetting(rule.value.get()); 524 } 525 settings->push_back(ContentSettingPatternSource( 526 rule.primary_pattern, rule.secondary_pattern, 527 setting_value, 528 kProviderNames[provider_type], 529 incognito)); 530 } 531 } 532 533 void HostContentSettingsMap::UsedContentSettingsProviders() const { 534 #ifndef NDEBUG 535 if (used_from_thread_id_ == base::kInvalidThreadId) 536 return; 537 538 if (base::PlatformThread::CurrentId() != used_from_thread_id_) 539 used_from_thread_id_ = base::kInvalidThreadId; 540 #endif 541 } 542 543 bool HostContentSettingsMap::ShouldAllowAllContent( 544 const GURL& primary_url, 545 const GURL& secondary_url, 546 ContentSettingsType content_type) { 547 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS || 548 content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION || 549 content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) { 550 return false; 551 } 552 #if defined(OS_ANDROID) || defined(OS_CHROMEOS) 553 if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) { 554 return false; 555 } 556 #endif 557 if (secondary_url.SchemeIs(content::kChromeUIScheme) && 558 content_type == CONTENT_SETTINGS_TYPE_COOKIES && 559 primary_url.SchemeIsSecure()) { 560 return true; 561 } 562 if (primary_url.SchemeIs(extensions::kExtensionScheme)) { 563 switch (content_type) { 564 case CONTENT_SETTINGS_TYPE_PLUGINS: 565 case CONTENT_SETTINGS_TYPE_MEDIASTREAM: 566 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC: 567 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA: 568 return false; 569 case CONTENT_SETTINGS_TYPE_COOKIES: 570 return secondary_url.SchemeIs(extensions::kExtensionScheme); 571 default: 572 return true; 573 } 574 } 575 return primary_url.SchemeIs(content::kChromeDevToolsScheme) || 576 primary_url.SchemeIs(content::kChromeUIScheme); 577 } 578 579 base::Value* HostContentSettingsMap::GetWebsiteSetting( 580 const GURL& primary_url, 581 const GURL& secondary_url, 582 ContentSettingsType content_type, 583 const std::string& resource_identifier, 584 content_settings::SettingInfo* info) const { 585 DCHECK(SupportsResourceIdentifier(content_type) || 586 resource_identifier.empty()); 587 588 // Check if the scheme of the requesting url is whitelisted. 589 if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) { 590 if (info) { 591 info->source = content_settings::SETTING_SOURCE_WHITELIST; 592 info->primary_pattern = ContentSettingsPattern::Wildcard(); 593 info->secondary_pattern = ContentSettingsPattern::Wildcard(); 594 } 595 return base::Value::CreateIntegerValue(CONTENT_SETTING_ALLOW); 596 } 597 598 ContentSettingsPattern* primary_pattern = NULL; 599 ContentSettingsPattern* secondary_pattern = NULL; 600 if (info) { 601 primary_pattern = &info->primary_pattern; 602 secondary_pattern = &info->secondary_pattern; 603 } 604 605 // The list of |content_settings_providers_| is ordered according to their 606 // precedence. 607 for (ConstProviderIterator provider = content_settings_providers_.begin(); 608 provider != content_settings_providers_.end(); 609 ++provider) { 610 base::Value* value = content_settings::GetContentSettingValueAndPatterns( 611 provider->second, primary_url, secondary_url, content_type, 612 resource_identifier, is_off_the_record_, 613 primary_pattern, secondary_pattern); 614 if (value) { 615 if (info) 616 info->source = kProviderSourceMap[provider->first]; 617 return value; 618 } 619 } 620 621 if (info) { 622 info->source = content_settings::SETTING_SOURCE_NONE; 623 info->primary_pattern = ContentSettingsPattern(); 624 info->secondary_pattern = ContentSettingsPattern(); 625 } 626 return NULL; 627 } 628 629 // static 630 HostContentSettingsMap::ProviderType 631 HostContentSettingsMap::GetProviderTypeFromSource( 632 const std::string& source) { 633 for (size_t i = 0; i < arraysize(kProviderNames); ++i) { 634 if (source == kProviderNames[i]) 635 return static_cast<ProviderType>(i); 636 } 637 638 NOTREACHED(); 639 return DEFAULT_PROVIDER; 640 } 641