host_content_settings_map.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 44using base::UserMetricsAction; 45using content::BrowserThread; 46 47namespace { 48 49typedef std::vector<content_settings::Rule> Rules; 50 51typedef std::pair<std::string, std::string> StringPair; 52 53const char* kProviderNames[] = { 54 "platform_app", 55 "policy", 56 "extension", 57 "preference", 58 "default" 59}; 60 61content_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}; 68COMPILE_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. 74bool SupportsResourceIdentifier(ContentSettingsType content_type) { 75 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS; 76} 77 78} // namespace 79 80HostContentSettingsMap::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) 110void 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 144void 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 165ContentSetting 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 182ContentSetting 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 210ContentSetting 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 221void 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 253void 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 269void 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 294void 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 311void 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 336void 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 346bool 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 353bool 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 405bool 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 419void 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 434HostContentSettingsMap::~HostContentSettingsMap() { 435 DCHECK(!prefs_); 436 STLDeleteValues(&content_settings_providers_); 437} 438 439void 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 450void 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 500void 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 533void 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 543bool 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 579base::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 630HostContentSettingsMap::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