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