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