• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
SupportsResourceIdentifier(ContentSettingsType content_type)74 bool SupportsResourceIdentifier(ContentSettingsType content_type) {
75   return content_type == CONTENT_SETTINGS_TYPE_PLUGINS;
76 }
77 
78 }  // namespace
79 
HostContentSettingsMap(PrefService * prefs,bool incognito)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)
RegisterExtensionService(ExtensionService * extension_service)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
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)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 
GetDefaultContentSettingFromProvider(ContentSettingsType content_type,content_settings::ProviderInterface * provider) const165 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 
GetDefaultContentSetting(ContentSettingsType content_type,std::string * provider_id) const182 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 
GetContentSetting(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier) const210 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 
GetSettingsForOneType(ContentSettingsType content_type,const std::string & resource_identifier,ContentSettingsForOneType * settings) const221 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 
SetDefaultContentSetting(ContentSettingsType content_type,ContentSetting setting)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 
SetWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,base::Value * value)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 
SetContentSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,ContentSetting setting)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 
AddExceptionForURL(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,ContentSetting setting)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 
ClearSettingsForOneType(ContentSettingsType content_type)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 
IsValueAllowedForType(PrefService * prefs,const base::Value * value,ContentSettingsType type)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
IsSettingAllowedForType(PrefService * prefs,ContentSetting setting,ContentSettingsType content_type)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
ContentTypeHasCompoundValue(ContentSettingsType type)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 
OnContentSettingChanged(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,std::string resource_identifier)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 
~HostContentSettingsMap()434 HostContentSettingsMap::~HostContentSettingsMap() {
435   DCHECK(!prefs_);
436   STLDeleteValues(&content_settings_providers_);
437 }
438 
ShutdownOnUIThread()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 
MigrateObsoleteClearOnExitPref()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 
AddSettingsForOneType(const content_settings::ProviderInterface * provider,ProviderType provider_type,ContentSettingsType content_type,const std::string & resource_identifier,ContentSettingsForOneType * settings,bool incognito) const500 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 
UsedContentSettingsProviders() const533 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 
ShouldAllowAllContent(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type)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 
GetWebsiteSetting(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,content_settings::SettingInfo * info) const579 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
GetProviderTypeFromSource(const std::string & source)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