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     ContentSetting setting) {
    313   // TODO(markusheintz): Until the UI supports pattern pairs, both urls must
    314   // match.
    315   DCHECK(primary_url == secondary_url);
    316   DCHECK(!ContentTypeHasCompoundValue(content_type));
    317 
    318   // Make sure there is no entry that would override the pattern we are about
    319   // to insert for exactly this URL.
    320   SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url),
    321                     ContentSettingsPattern::Wildcard(),
    322                     content_type,
    323                     std::string(),
    324                     CONTENT_SETTING_DEFAULT);
    325 
    326   SetContentSetting(ContentSettingsPattern::FromURL(primary_url),
    327                     ContentSettingsPattern::Wildcard(),
    328                     content_type,
    329                     std::string(),
    330                     setting);
    331 }
    332 
    333 void HostContentSettingsMap::ClearSettingsForOneType(
    334     ContentSettingsType content_type) {
    335   UsedContentSettingsProviders();
    336   for (ProviderIterator provider = content_settings_providers_.begin();
    337        provider != content_settings_providers_.end();
    338        ++provider) {
    339     provider->second->ClearAllContentSettingsRules(content_type);
    340   }
    341 }
    342 
    343 bool HostContentSettingsMap::IsValueAllowedForType(
    344     PrefService* prefs, const base::Value* value, ContentSettingsType type) {
    345   return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType(
    346       prefs, content_settings::ValueToContentSetting(value), type);
    347 }
    348 
    349 // static
    350 bool HostContentSettingsMap::IsSettingAllowedForType(
    351     PrefService* prefs,
    352     ContentSetting setting,
    353     ContentSettingsType content_type) {
    354   // We don't yet support stored content settings for mixed scripting.
    355   if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT)
    356     return false;
    357 
    358   // BLOCK semantics are not implemented for fullscreen.
    359   if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN &&
    360       setting == CONTENT_SETTING_BLOCK) {
    361     return false;
    362   }
    363 
    364   // We don't support ALLOW for media default setting.
    365   if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM &&
    366       setting == CONTENT_SETTING_ALLOW) {
    367     return false;
    368   }
    369 
    370   // DEFAULT, ALLOW and BLOCK are always allowed.
    371   if (setting == CONTENT_SETTING_DEFAULT ||
    372       setting == CONTENT_SETTING_ALLOW ||
    373       setting == CONTENT_SETTING_BLOCK) {
    374     return true;
    375   }
    376   switch (content_type) {
    377     case CONTENT_SETTINGS_TYPE_COOKIES:
    378       return setting == CONTENT_SETTING_SESSION_ONLY;
    379     case CONTENT_SETTINGS_TYPE_PLUGINS:
    380     case CONTENT_SETTINGS_TYPE_GEOLOCATION:
    381     case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
    382     case CONTENT_SETTINGS_TYPE_MOUSELOCK:
    383     case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
    384     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
    385     case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
    386     case CONTENT_SETTINGS_TYPE_PPAPI_BROKER:
    387     case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
    388     case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
    389       return setting == CONTENT_SETTING_ASK;
    390     default:
    391       return false;
    392   }
    393 }
    394 
    395 // static
    396 bool HostContentSettingsMap::ContentTypeHasCompoundValue(
    397     ContentSettingsType type) {
    398   // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE and
    399   // CONTENT_SETTINGS_TYPE_MEDIASTREAM are of type dictionary/map. Compound
    400   // types like dictionaries can't be mapped to the type |ContentSetting|.
    401   return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
    402           type == CONTENT_SETTINGS_TYPE_MEDIASTREAM);
    403 }
    404 
    405 void HostContentSettingsMap::OnContentSettingChanged(
    406     const ContentSettingsPattern& primary_pattern,
    407     const ContentSettingsPattern& secondary_pattern,
    408     ContentSettingsType content_type,
    409     std::string resource_identifier) {
    410   const ContentSettingsDetails details(primary_pattern,
    411                                        secondary_pattern,
    412                                        content_type,
    413                                        resource_identifier);
    414   content::NotificationService::current()->Notify(
    415       chrome::NOTIFICATION_CONTENT_SETTINGS_CHANGED,
    416       content::Source<HostContentSettingsMap>(this),
    417       content::Details<const ContentSettingsDetails>(&details));
    418 }
    419 
    420 HostContentSettingsMap::~HostContentSettingsMap() {
    421   DCHECK(!prefs_);
    422   STLDeleteValues(&content_settings_providers_);
    423 }
    424 
    425 void HostContentSettingsMap::ShutdownOnUIThread() {
    426   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    427   DCHECK(prefs_);
    428   prefs_ = NULL;
    429   for (ProviderIterator it = content_settings_providers_.begin();
    430        it != content_settings_providers_.end();
    431        ++it) {
    432     it->second->ShutdownOnUIThread();
    433   }
    434 }
    435 
    436 void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() {
    437   // Don't migrate more than once.
    438   if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) &&
    439       prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) {
    440     return;
    441   }
    442 
    443   if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) {
    444     // Nothing to be done
    445     prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
    446     return;
    447   }
    448 
    449   // Change the default cookie settings:
    450   //  old              new
    451   //  ---------------- ----------------
    452   //  ALLOW            SESSION_ONLY
    453   //  SESSION_ONLY     SESSION_ONLY
    454   //  BLOCK            BLOCK
    455   ContentSetting default_setting = GetDefaultContentSettingFromProvider(
    456       CONTENT_SETTINGS_TYPE_COOKIES,
    457       content_settings_providers_[DEFAULT_PROVIDER]);
    458   if (default_setting == CONTENT_SETTING_ALLOW) {
    459     SetDefaultContentSetting(
    460         CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY);
    461   }
    462 
    463   // Change the exceptions using the same rules.
    464   ContentSettingsForOneType exceptions;
    465   AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER],
    466                         PREF_PROVIDER,
    467                         CONTENT_SETTINGS_TYPE_COOKIES,
    468                         std::string(),
    469                         &exceptions,
    470                         false);
    471   for (ContentSettingsForOneType::iterator it = exceptions.begin();
    472        it != exceptions.end(); ++it) {
    473     if (it->setting != CONTENT_SETTING_ALLOW)
    474       continue;
    475     SetWebsiteSetting(it->primary_pattern,
    476                       it->secondary_pattern,
    477                       CONTENT_SETTINGS_TYPE_COOKIES,
    478                       std::string(),
    479                       Value::CreateIntegerValue(CONTENT_SETTING_SESSION_ONLY));
    480   }
    481 
    482   prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
    483 }
    484 
    485 void HostContentSettingsMap::AddSettingsForOneType(
    486     const content_settings::ProviderInterface* provider,
    487     ProviderType provider_type,
    488     ContentSettingsType content_type,
    489     const std::string& resource_identifier,
    490     ContentSettingsForOneType* settings,
    491     bool incognito) const {
    492   scoped_ptr<content_settings::RuleIterator> rule_iterator(
    493       provider->GetRuleIterator(content_type,
    494                                 resource_identifier,
    495                                 incognito));
    496   while (rule_iterator->HasNext()) {
    497     const content_settings::Rule& rule = rule_iterator->Next();
    498     ContentSetting setting_value = CONTENT_SETTING_DEFAULT;
    499     // TODO(bauerb): Return rules as a list of values, not content settings.
    500     // Handle the case using compound values for its exceptions and arbitrary
    501     // values for its default setting. Here we assume all the exceptions
    502     // are granted as |CONTENT_SETTING_ALLOW|.
    503     if (ContentTypeHasCompoundValue(content_type) &&
    504         rule.value.get() &&
    505         rule.primary_pattern != ContentSettingsPattern::Wildcard()) {
    506       setting_value = CONTENT_SETTING_ALLOW;
    507     } else {
    508       setting_value = content_settings::ValueToContentSetting(rule.value.get());
    509     }
    510     settings->push_back(ContentSettingPatternSource(
    511         rule.primary_pattern, rule.secondary_pattern,
    512         setting_value,
    513         kProviderNames[provider_type],
    514         incognito));
    515   }
    516 }
    517 
    518 void HostContentSettingsMap::UsedContentSettingsProviders() const {
    519 #ifndef NDEBUG
    520   if (used_from_thread_id_ == base::kInvalidThreadId)
    521     return;
    522 
    523   if (base::PlatformThread::CurrentId() != used_from_thread_id_)
    524     used_from_thread_id_ = base::kInvalidThreadId;
    525 #endif
    526 }
    527 
    528 bool HostContentSettingsMap::ShouldAllowAllContent(
    529     const GURL& primary_url,
    530     const GURL& secondary_url,
    531     ContentSettingsType content_type) {
    532   if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
    533       content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
    534       content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
    535     return false;
    536   }
    537   if (secondary_url.SchemeIs(chrome::kChromeUIScheme) &&
    538       content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
    539       primary_url.SchemeIsSecure()) {
    540     return true;
    541   }
    542   if (primary_url.SchemeIs(extensions::kExtensionScheme)) {
    543     switch (content_type) {
    544       case CONTENT_SETTINGS_TYPE_PLUGINS:
    545       case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
    546       case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
    547       case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
    548         return false;
    549       case CONTENT_SETTINGS_TYPE_COOKIES:
    550         return secondary_url.SchemeIs(extensions::kExtensionScheme);
    551       default:
    552         return true;
    553     }
    554   }
    555   return primary_url.SchemeIs(chrome::kChromeDevToolsScheme) ||
    556          primary_url.SchemeIs(chrome::kChromeUIScheme);
    557 }
    558 
    559 base::Value* HostContentSettingsMap::GetWebsiteSetting(
    560     const GURL& primary_url,
    561     const GURL& secondary_url,
    562     ContentSettingsType content_type,
    563     const std::string& resource_identifier,
    564     content_settings::SettingInfo* info) const {
    565   DCHECK(SupportsResourceIdentifier(content_type) ||
    566          resource_identifier.empty());
    567 
    568   // Check if the scheme of the requesting url is whitelisted.
    569   if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) {
    570     if (info) {
    571       info->source = content_settings::SETTING_SOURCE_WHITELIST;
    572       info->primary_pattern = ContentSettingsPattern::Wildcard();
    573       info->secondary_pattern = ContentSettingsPattern::Wildcard();
    574     }
    575     return Value::CreateIntegerValue(CONTENT_SETTING_ALLOW);
    576   }
    577 
    578   ContentSettingsPattern* primary_pattern = NULL;
    579   ContentSettingsPattern* secondary_pattern = NULL;
    580   if (info) {
    581     primary_pattern = &info->primary_pattern;
    582     secondary_pattern = &info->secondary_pattern;
    583   }
    584 
    585   // The list of |content_settings_providers_| is ordered according to their
    586   // precedence.
    587   for (ConstProviderIterator provider = content_settings_providers_.begin();
    588        provider != content_settings_providers_.end();
    589        ++provider) {
    590     base::Value* value = content_settings::GetContentSettingValueAndPatterns(
    591         provider->second, primary_url, secondary_url, content_type,
    592         resource_identifier, is_off_the_record_,
    593         primary_pattern, secondary_pattern);
    594     if (value) {
    595       if (info)
    596         info->source = kProviderSourceMap[provider->first];
    597       return value;
    598     }
    599   }
    600 
    601   if (info) {
    602     info->source = content_settings::SETTING_SOURCE_NONE;
    603     info->primary_pattern = ContentSettingsPattern();
    604     info->secondary_pattern = ContentSettingsPattern();
    605   }
    606   return NULL;
    607 }
    608 
    609 // static
    610 HostContentSettingsMap::ProviderType
    611     HostContentSettingsMap::GetProviderTypeFromSource(
    612         const std::string& source) {
    613   for (size_t i = 0; i < arraysize(kProviderNames); ++i) {
    614     if (source == kProviderNames[i])
    615       return static_cast<ProviderType>(i);
    616   }
    617 
    618   NOTREACHED();
    619   return DEFAULT_PROVIDER;
    620 }
    621