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 "base/time/clock.h"
16 #include "chrome/browser/content_settings/content_settings_default_provider.h"
17 #include "chrome/browser/content_settings/content_settings_policy_provider.h"
18 #include "chrome/browser/content_settings/content_settings_pref_provider.h"
19 #include "chrome/browser/content_settings/content_settings_utils.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/pref_names.h"
22 #include "chrome/common/url_constants.h"
23 #include "components/content_settings/core/browser/content_settings_details.h"
24 #include "components/content_settings/core/browser/content_settings_observable_provider.h"
25 #include "components/content_settings/core/browser/content_settings_provider.h"
26 #include "components/content_settings/core/browser/content_settings_rule.h"
27 #include "components/content_settings/core/common/content_settings_pattern.h"
28 #include "components/pref_registry/pref_registry_syncable.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/common/content_switches.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/static_cookie_policy.h"
33 #include "url/gurl.h"
34
35 #if defined(ENABLE_EXTENSIONS)
36 #include "extensions/common/constants.h"
37 #endif
38
39 using content::BrowserThread;
40
41 namespace {
42
43 typedef std::vector<content_settings::Rule> Rules;
44
45 typedef std::pair<std::string, std::string> StringPair;
46
47 // TODO(bauerb): Expose constants.
48 const char* kProviderNames[] = {
49 "platform_app",
50 "policy",
51 "extension",
52 "override",
53 "preference",
54 "default"
55 };
56
57 content_settings::SettingSource kProviderSourceMap[] = {
58 content_settings::SETTING_SOURCE_EXTENSION,
59 content_settings::SETTING_SOURCE_POLICY,
60 content_settings::SETTING_SOURCE_EXTENSION,
61 content_settings::SETTING_SOURCE_USER,
62 content_settings::SETTING_SOURCE_USER,
63 content_settings::SETTING_SOURCE_USER,
64 };
65 COMPILE_ASSERT(arraysize(kProviderSourceMap) ==
66 HostContentSettingsMap::NUM_PROVIDER_TYPES,
67 kProviderSourceMap_has_incorrect_size);
68
69 // Returns true if the |content_type| supports a resource identifier.
70 // Resource identifiers are supported (but not required) for plug-ins.
SupportsResourceIdentifier(ContentSettingsType content_type)71 bool SupportsResourceIdentifier(ContentSettingsType content_type) {
72 return content_type == CONTENT_SETTINGS_TYPE_PLUGINS;
73 }
74
75 } // namespace
76
HostContentSettingsMap(PrefService * prefs,bool incognito)77 HostContentSettingsMap::HostContentSettingsMap(PrefService* prefs,
78 bool incognito)
79 :
80 #ifndef NDEBUG
81 used_from_thread_id_(base::PlatformThread::CurrentId()),
82 #endif
83 prefs_(prefs),
84 is_off_the_record_(incognito) {
85 content_settings::ObservableProvider* policy_provider =
86 new content_settings::PolicyProvider(prefs_);
87 policy_provider->AddObserver(this);
88 content_settings_providers_[POLICY_PROVIDER] = policy_provider;
89
90 content_settings::ObservableProvider* pref_provider =
91 new content_settings::PrefProvider(prefs_, is_off_the_record_);
92 pref_provider->AddObserver(this);
93 content_settings_providers_[PREF_PROVIDER] = pref_provider;
94
95 content_settings::ObservableProvider* default_provider =
96 new content_settings::DefaultProvider(prefs_, is_off_the_record_);
97 default_provider->AddObserver(this);
98 content_settings_providers_[DEFAULT_PROVIDER] = default_provider;
99
100 content_settings_providers_[OVERRIDE_PROVIDER] =
101 new content_settings::OverrideProvider(prefs_, is_off_the_record_);
102
103 if (!is_off_the_record_) {
104 // Migrate obsolete preferences.
105 MigrateObsoleteClearOnExitPref();
106 }
107 }
108
109 // static
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)110 void HostContentSettingsMap::RegisterProfilePrefs(
111 user_prefs::PrefRegistrySyncable* registry) {
112 registry->RegisterIntegerPref(
113 prefs::kContentSettingsWindowLastTabIndex,
114 0,
115 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
116 registry->RegisterBooleanPref(
117 prefs::kContentSettingsClearOnExitMigrated,
118 false,
119 user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
120
121 // Register the prefs for the content settings providers.
122 content_settings::DefaultProvider::RegisterProfilePrefs(registry);
123 content_settings::PrefProvider::RegisterProfilePrefs(registry);
124 content_settings::PolicyProvider::RegisterProfilePrefs(registry);
125 content_settings::OverrideProvider::RegisterProfilePrefs(registry);
126 }
127
RegisterProvider(ProviderType type,scoped_ptr<content_settings::ObservableProvider> provider)128 void HostContentSettingsMap::RegisterProvider(
129 ProviderType type,
130 scoped_ptr<content_settings::ObservableProvider> provider) {
131 DCHECK(!content_settings_providers_[type]);
132 provider->AddObserver(this);
133 content_settings_providers_[type] = provider.release();
134
135 #ifndef NDEBUG
136 DCHECK_NE(used_from_thread_id_, base::kInvalidThreadId)
137 << "Used from multiple threads before initialization complete.";
138 #endif
139
140 OnContentSettingChanged(ContentSettingsPattern(),
141 ContentSettingsPattern(),
142 CONTENT_SETTINGS_TYPE_DEFAULT,
143 std::string());
144 }
145
GetDefaultContentSettingFromProvider(ContentSettingsType content_type,content_settings::ProviderInterface * provider) const146 ContentSetting HostContentSettingsMap::GetDefaultContentSettingFromProvider(
147 ContentSettingsType content_type,
148 content_settings::ProviderInterface* provider) const {
149 scoped_ptr<content_settings::RuleIterator> rule_iterator(
150 provider->GetRuleIterator(content_type, std::string(), false));
151
152 ContentSettingsPattern wildcard = ContentSettingsPattern::Wildcard();
153 while (rule_iterator->HasNext()) {
154 content_settings::Rule rule = rule_iterator->Next();
155 if (rule.primary_pattern == wildcard &&
156 rule.secondary_pattern == wildcard) {
157 return content_settings::ValueToContentSetting(rule.value.get());
158 }
159 }
160 return CONTENT_SETTING_DEFAULT;
161 }
162
GetDefaultContentSetting(ContentSettingsType content_type,std::string * provider_id) const163 ContentSetting HostContentSettingsMap::GetDefaultContentSetting(
164 ContentSettingsType content_type,
165 std::string* provider_id) const {
166 UsedContentSettingsProviders();
167
168 // Iterate through the list of providers and return the first non-NULL value
169 // that matches |primary_url| and |secondary_url|.
170 for (ConstProviderIterator provider = content_settings_providers_.begin();
171 provider != content_settings_providers_.end();
172 ++provider) {
173 if (provider->first == PREF_PROVIDER ||
174 provider->first == OVERRIDE_PROVIDER)
175 continue;
176 ContentSetting default_setting =
177 GetDefaultContentSettingFromProvider(content_type, provider->second);
178 if (default_setting != CONTENT_SETTING_DEFAULT) {
179 if (provider_id)
180 *provider_id = kProviderNames[provider->first];
181 return default_setting;
182 }
183 }
184
185 return CONTENT_SETTING_DEFAULT;
186 }
187
GetContentSetting(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier) const188 ContentSetting HostContentSettingsMap::GetContentSetting(
189 const GURL& primary_url,
190 const GURL& secondary_url,
191 ContentSettingsType content_type,
192 const std::string& resource_identifier) const {
193 DCHECK(!ContentTypeHasCompoundValue(content_type));
194 scoped_ptr<base::Value> value = GetWebsiteSetting(
195 primary_url, secondary_url, content_type, resource_identifier, NULL);
196 return content_settings::ValueToContentSetting(value.get());
197 }
198
GetSettingsForOneType(ContentSettingsType content_type,const std::string & resource_identifier,ContentSettingsForOneType * settings) const199 void HostContentSettingsMap::GetSettingsForOneType(
200 ContentSettingsType content_type,
201 const std::string& resource_identifier,
202 ContentSettingsForOneType* settings) const {
203 DCHECK(SupportsResourceIdentifier(content_type) ||
204 resource_identifier.empty());
205 DCHECK(settings);
206 UsedContentSettingsProviders();
207
208 settings->clear();
209 for (ConstProviderIterator provider = content_settings_providers_.begin();
210 provider != content_settings_providers_.end();
211 ++provider) {
212 if (provider->first == OVERRIDE_PROVIDER)
213 continue;
214 // For each provider, iterate first the incognito-specific rules, then the
215 // normal rules.
216 if (is_off_the_record_) {
217 AddSettingsForOneType(provider->second,
218 provider->first,
219 content_type,
220 resource_identifier,
221 settings,
222 true);
223 }
224 AddSettingsForOneType(provider->second,
225 provider->first,
226 content_type,
227 resource_identifier,
228 settings,
229 false);
230 }
231 }
232
SetDefaultContentSetting(ContentSettingsType content_type,ContentSetting setting)233 void HostContentSettingsMap::SetDefaultContentSetting(
234 ContentSettingsType content_type,
235 ContentSetting setting) {
236 DCHECK(IsSettingAllowedForType(prefs_, setting, content_type));
237
238 base::Value* value = NULL;
239 if (setting != CONTENT_SETTING_DEFAULT)
240 value = new base::FundamentalValue(setting);
241 SetWebsiteSetting(
242 ContentSettingsPattern::Wildcard(),
243 ContentSettingsPattern::Wildcard(),
244 content_type,
245 std::string(),
246 value);
247 }
248
SetWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,base::Value * value)249 void HostContentSettingsMap::SetWebsiteSetting(
250 const ContentSettingsPattern& primary_pattern,
251 const ContentSettingsPattern& secondary_pattern,
252 ContentSettingsType content_type,
253 const std::string& resource_identifier,
254 base::Value* value) {
255 DCHECK(IsValueAllowedForType(prefs_, value, content_type));
256 DCHECK(SupportsResourceIdentifier(content_type) ||
257 resource_identifier.empty());
258 UsedContentSettingsProviders();
259
260 for (ProviderIterator provider = content_settings_providers_.begin();
261 provider != content_settings_providers_.end();
262 ++provider) {
263 if (provider->second->SetWebsiteSetting(primary_pattern,
264 secondary_pattern,
265 content_type,
266 resource_identifier,
267 value)) {
268 return;
269 }
270 }
271 NOTREACHED();
272 }
273
SetNarrowestWebsiteSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,ContentSetting setting,content_settings::SettingInfo existing_info)274 void HostContentSettingsMap::SetNarrowestWebsiteSetting(
275 const ContentSettingsPattern& primary_pattern,
276 const ContentSettingsPattern& secondary_pattern,
277 ContentSettingsType content_type,
278 const std::string& resource_identifier,
279 ContentSetting setting,
280 content_settings::SettingInfo existing_info) {
281 ContentSettingsPattern narrow_primary = primary_pattern;
282 ContentSettingsPattern narrow_secondary = secondary_pattern;
283
284 DCHECK_EQ(content_settings::SETTING_SOURCE_USER, existing_info.source);
285 ContentSettingsPattern::Relation r1 =
286 existing_info.primary_pattern.Compare(primary_pattern);
287 if (r1 == ContentSettingsPattern::PREDECESSOR) {
288 narrow_primary = existing_info.primary_pattern;
289 } else if (r1 == ContentSettingsPattern::IDENTITY) {
290 ContentSettingsPattern::Relation r2 =
291 existing_info.secondary_pattern.Compare(secondary_pattern);
292 DCHECK(r2 != ContentSettingsPattern::DISJOINT_ORDER_POST &&
293 r2 != ContentSettingsPattern::DISJOINT_ORDER_PRE);
294 if (r2 == ContentSettingsPattern::PREDECESSOR)
295 narrow_secondary = existing_info.secondary_pattern;
296 }
297
298 SetContentSetting(
299 narrow_primary, narrow_secondary, content_type, std::string(), setting);
300 }
301
SetContentSetting(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,const std::string & resource_identifier,ContentSetting setting)302 void HostContentSettingsMap::SetContentSetting(
303 const ContentSettingsPattern& primary_pattern,
304 const ContentSettingsPattern& secondary_pattern,
305 ContentSettingsType content_type,
306 const std::string& resource_identifier,
307 ContentSetting setting) {
308 DCHECK(!ContentTypeHasCompoundValue(content_type));
309
310 if (setting == CONTENT_SETTING_ALLOW &&
311 (content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
312 content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS)) {
313 UpdateLastUsageByPattern(primary_pattern, secondary_pattern, content_type);
314 }
315
316 base::Value* value = NULL;
317 if (setting != CONTENT_SETTING_DEFAULT)
318 value = new base::FundamentalValue(setting);
319 SetWebsiteSetting(primary_pattern,
320 secondary_pattern,
321 content_type,
322 resource_identifier,
323 value);
324 }
325
GetContentSettingAndMaybeUpdateLastUsage(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier)326 ContentSetting HostContentSettingsMap::GetContentSettingAndMaybeUpdateLastUsage(
327 const GURL& primary_url,
328 const GURL& secondary_url,
329 ContentSettingsType content_type,
330 const std::string& resource_identifier) {
331 DCHECK_CURRENTLY_ON(BrowserThread::UI);
332
333 ContentSetting setting = GetContentSetting(
334 primary_url, secondary_url, content_type, resource_identifier);
335 if (setting == CONTENT_SETTING_ALLOW) {
336 UpdateLastUsageByPattern(
337 ContentSettingsPattern::FromURLNoWildcard(primary_url),
338 ContentSettingsPattern::FromURLNoWildcard(secondary_url),
339 content_type);
340 }
341 return setting;
342 }
343
UpdateLastUsage(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type)344 void HostContentSettingsMap::UpdateLastUsage(const GURL& primary_url,
345 const GURL& secondary_url,
346 ContentSettingsType content_type) {
347 UpdateLastUsageByPattern(
348 ContentSettingsPattern::FromURLNoWildcard(primary_url),
349 ContentSettingsPattern::FromURLNoWildcard(secondary_url),
350 content_type);
351 }
352
UpdateLastUsageByPattern(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type)353 void HostContentSettingsMap::UpdateLastUsageByPattern(
354 const ContentSettingsPattern& primary_pattern,
355 const ContentSettingsPattern& secondary_pattern,
356 ContentSettingsType content_type) {
357 UsedContentSettingsProviders();
358
359 GetPrefProvider()->UpdateLastUsage(
360 primary_pattern, secondary_pattern, content_type);
361
362 FOR_EACH_OBSERVER(
363 content_settings::Observer,
364 observers_,
365 OnContentSettingUsed(primary_pattern, secondary_pattern, content_type));
366 }
367
GetLastUsage(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type)368 base::Time HostContentSettingsMap::GetLastUsage(
369 const GURL& primary_url,
370 const GURL& secondary_url,
371 ContentSettingsType content_type) {
372 return GetLastUsageByPattern(
373 ContentSettingsPattern::FromURLNoWildcard(primary_url),
374 ContentSettingsPattern::FromURLNoWildcard(secondary_url),
375 content_type);
376 }
377
GetLastUsageByPattern(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type)378 base::Time HostContentSettingsMap::GetLastUsageByPattern(
379 const ContentSettingsPattern& primary_pattern,
380 const ContentSettingsPattern& secondary_pattern,
381 ContentSettingsType content_type) {
382 UsedContentSettingsProviders();
383
384 return GetPrefProvider()->GetLastUsage(
385 primary_pattern, secondary_pattern, content_type);
386 }
387
GetContentSettingWithoutOverride(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier)388 ContentSetting HostContentSettingsMap::GetContentSettingWithoutOverride(
389 const GURL& primary_url,
390 const GURL& secondary_url,
391 ContentSettingsType content_type,
392 const std::string& resource_identifier) {
393 scoped_ptr<base::Value> value(GetWebsiteSettingWithoutOverride(
394 primary_url, secondary_url, content_type, resource_identifier, NULL));
395 return content_settings::ValueToContentSetting(value.get());
396 }
397
398 scoped_ptr<base::Value>
GetWebsiteSettingWithoutOverride(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,content_settings::SettingInfo * info) const399 HostContentSettingsMap::GetWebsiteSettingWithoutOverride(
400 const GURL& primary_url,
401 const GURL& secondary_url,
402 ContentSettingsType content_type,
403 const std::string& resource_identifier,
404 content_settings::SettingInfo* info) const {
405 return GetWebsiteSettingInternal(primary_url,
406 secondary_url,
407 content_type,
408 resource_identifier,
409 info,
410 false);
411 }
412
SetContentSettingOverride(ContentSettingsType content_type,bool is_enabled)413 void HostContentSettingsMap::SetContentSettingOverride(
414 ContentSettingsType content_type,
415 bool is_enabled) {
416 UsedContentSettingsProviders();
417
418 content_settings::OverrideProvider* override =
419 static_cast<content_settings::OverrideProvider*>(
420 content_settings_providers_[OVERRIDE_PROVIDER]);
421 override->SetOverrideSetting(content_type, is_enabled);
422 }
423
GetContentSettingOverride(ContentSettingsType content_type)424 bool HostContentSettingsMap::GetContentSettingOverride(
425 ContentSettingsType content_type) {
426 UsedContentSettingsProviders();
427
428 content_settings::OverrideProvider* override =
429 static_cast<content_settings::OverrideProvider*>(
430 content_settings_providers_[OVERRIDE_PROVIDER]);
431 return override->IsEnabled(content_type);
432 }
433
AddObserver(content_settings::Observer * observer)434 void HostContentSettingsMap::AddObserver(content_settings::Observer* observer) {
435 observers_.AddObserver(observer);
436 }
437
RemoveObserver(content_settings::Observer * observer)438 void HostContentSettingsMap::RemoveObserver(
439 content_settings::Observer* observer) {
440 observers_.RemoveObserver(observer);
441 }
442
SetPrefClockForTesting(scoped_ptr<base::Clock> clock)443 void HostContentSettingsMap::SetPrefClockForTesting(
444 scoped_ptr<base::Clock> clock) {
445 UsedContentSettingsProviders();
446
447 GetPrefProvider()->SetClockForTesting(clock.Pass());
448 }
449
AddExceptionForURL(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,ContentSetting setting)450 void HostContentSettingsMap::AddExceptionForURL(
451 const GURL& primary_url,
452 const GURL& secondary_url,
453 ContentSettingsType content_type,
454 ContentSetting setting) {
455 // TODO(markusheintz): Until the UI supports pattern pairs, both urls must
456 // match.
457 DCHECK(primary_url == secondary_url);
458 DCHECK(!ContentTypeHasCompoundValue(content_type));
459
460 // Make sure there is no entry that would override the pattern we are about
461 // to insert for exactly this URL.
462 SetContentSetting(ContentSettingsPattern::FromURLNoWildcard(primary_url),
463 ContentSettingsPattern::Wildcard(),
464 content_type,
465 std::string(),
466 CONTENT_SETTING_DEFAULT);
467
468 SetContentSetting(ContentSettingsPattern::FromURL(primary_url),
469 ContentSettingsPattern::Wildcard(),
470 content_type,
471 std::string(),
472 setting);
473 }
474
ClearSettingsForOneType(ContentSettingsType content_type)475 void HostContentSettingsMap::ClearSettingsForOneType(
476 ContentSettingsType content_type) {
477 UsedContentSettingsProviders();
478 for (ProviderIterator provider = content_settings_providers_.begin();
479 provider != content_settings_providers_.end();
480 ++provider) {
481 provider->second->ClearAllContentSettingsRules(content_type);
482 }
483 }
484
IsValueAllowedForType(PrefService * prefs,const base::Value * value,ContentSettingsType type)485 bool HostContentSettingsMap::IsValueAllowedForType(
486 PrefService* prefs, const base::Value* value, ContentSettingsType type) {
487 return ContentTypeHasCompoundValue(type) || IsSettingAllowedForType(
488 prefs, content_settings::ValueToContentSetting(value), type);
489 }
490
491 // static
IsSettingAllowedForType(PrefService * prefs,ContentSetting setting,ContentSettingsType content_type)492 bool HostContentSettingsMap::IsSettingAllowedForType(
493 PrefService* prefs,
494 ContentSetting setting,
495 ContentSettingsType content_type) {
496 // We don't yet support stored content settings for mixed scripting.
497 if (content_type == CONTENT_SETTINGS_TYPE_MIXEDSCRIPT)
498 return false;
499
500 // BLOCK semantics are not implemented for fullscreen.
501 if (content_type == CONTENT_SETTINGS_TYPE_FULLSCREEN &&
502 setting == CONTENT_SETTING_BLOCK) {
503 return false;
504 }
505
506 // We don't support ALLOW for media default setting.
507 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM &&
508 setting == CONTENT_SETTING_ALLOW) {
509 return false;
510 }
511
512 #if defined(OS_ANDROID)
513 // App banners store a dictionary.
514 if (content_type == CONTENT_SETTINGS_TYPE_APP_BANNER)
515 return false;
516 #endif
517
518 // DEFAULT, ALLOW and BLOCK are always allowed.
519 if (setting == CONTENT_SETTING_DEFAULT ||
520 setting == CONTENT_SETTING_ALLOW ||
521 setting == CONTENT_SETTING_BLOCK) {
522 return true;
523 }
524 switch (content_type) {
525 case CONTENT_SETTINGS_TYPE_COOKIES:
526 return setting == CONTENT_SETTING_SESSION_ONLY;
527 case CONTENT_SETTINGS_TYPE_PLUGINS:
528 case CONTENT_SETTINGS_TYPE_GEOLOCATION:
529 case CONTENT_SETTINGS_TYPE_NOTIFICATIONS:
530 case CONTENT_SETTINGS_TYPE_MOUSELOCK:
531 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
532 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
533 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
534 case CONTENT_SETTINGS_TYPE_PPAPI_BROKER:
535 case CONTENT_SETTINGS_TYPE_AUTOMATIC_DOWNLOADS:
536 case CONTENT_SETTINGS_TYPE_MIDI_SYSEX:
537 return setting == CONTENT_SETTING_ASK;
538 default:
539 return false;
540 }
541 }
542
543 // static
ContentTypeHasCompoundValue(ContentSettingsType type)544 bool HostContentSettingsMap::ContentTypeHasCompoundValue(
545 ContentSettingsType type) {
546 // Values for content type CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
547 // CONTENT_SETTINGS_TYPE_MEDIASTREAM, and
548 // CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS are of type dictionary/map.
549 // Compound types like dictionaries can't be mapped to the type
550 // |ContentSetting|.
551 #if defined(OS_ANDROID)
552 if (type == CONTENT_SETTINGS_TYPE_APP_BANNER)
553 return true;
554 #endif
555
556 return (type == CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE ||
557 type == CONTENT_SETTINGS_TYPE_MEDIASTREAM ||
558 type == CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS);
559 }
560
OnContentSettingChanged(const ContentSettingsPattern & primary_pattern,const ContentSettingsPattern & secondary_pattern,ContentSettingsType content_type,std::string resource_identifier)561 void HostContentSettingsMap::OnContentSettingChanged(
562 const ContentSettingsPattern& primary_pattern,
563 const ContentSettingsPattern& secondary_pattern,
564 ContentSettingsType content_type,
565 std::string resource_identifier) {
566 FOR_EACH_OBSERVER(content_settings::Observer,
567 observers_,
568 OnContentSettingChanged(primary_pattern,
569 secondary_pattern,
570 content_type,
571 resource_identifier));
572 }
573
~HostContentSettingsMap()574 HostContentSettingsMap::~HostContentSettingsMap() {
575 DCHECK(!prefs_);
576 STLDeleteValues(&content_settings_providers_);
577 }
578
ShutdownOnUIThread()579 void HostContentSettingsMap::ShutdownOnUIThread() {
580 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
581 DCHECK(prefs_);
582 prefs_ = NULL;
583 for (ProviderIterator it = content_settings_providers_.begin();
584 it != content_settings_providers_.end();
585 ++it) {
586 it->second->ShutdownOnUIThread();
587 }
588 }
589
MigrateObsoleteClearOnExitPref()590 void HostContentSettingsMap::MigrateObsoleteClearOnExitPref() {
591 // Don't migrate more than once.
592 if (prefs_->HasPrefPath(prefs::kContentSettingsClearOnExitMigrated) &&
593 prefs_->GetBoolean(prefs::kContentSettingsClearOnExitMigrated)) {
594 return;
595 }
596
597 if (!prefs_->GetBoolean(prefs::kClearSiteDataOnExit)) {
598 // Nothing to be done
599 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
600 return;
601 }
602
603 // Change the default cookie settings:
604 // old new
605 // ---------------- ----------------
606 // ALLOW SESSION_ONLY
607 // SESSION_ONLY SESSION_ONLY
608 // BLOCK BLOCK
609 ContentSetting default_setting = GetDefaultContentSettingFromProvider(
610 CONTENT_SETTINGS_TYPE_COOKIES,
611 content_settings_providers_[DEFAULT_PROVIDER]);
612 if (default_setting == CONTENT_SETTING_ALLOW) {
613 SetDefaultContentSetting(
614 CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_SESSION_ONLY);
615 }
616
617 // Change the exceptions using the same rules.
618 ContentSettingsForOneType exceptions;
619 AddSettingsForOneType(content_settings_providers_[PREF_PROVIDER],
620 PREF_PROVIDER,
621 CONTENT_SETTINGS_TYPE_COOKIES,
622 std::string(),
623 &exceptions,
624 false);
625 for (ContentSettingsForOneType::iterator it = exceptions.begin();
626 it != exceptions.end(); ++it) {
627 if (it->setting != CONTENT_SETTING_ALLOW)
628 continue;
629 SetWebsiteSetting(it->primary_pattern,
630 it->secondary_pattern,
631 CONTENT_SETTINGS_TYPE_COOKIES,
632 std::string(),
633 new base::FundamentalValue(CONTENT_SETTING_SESSION_ONLY));
634 }
635
636 prefs_->SetBoolean(prefs::kContentSettingsClearOnExitMigrated, true);
637 }
638
AddSettingsForOneType(const content_settings::ProviderInterface * provider,ProviderType provider_type,ContentSettingsType content_type,const std::string & resource_identifier,ContentSettingsForOneType * settings,bool incognito) const639 void HostContentSettingsMap::AddSettingsForOneType(
640 const content_settings::ProviderInterface* provider,
641 ProviderType provider_type,
642 ContentSettingsType content_type,
643 const std::string& resource_identifier,
644 ContentSettingsForOneType* settings,
645 bool incognito) const {
646 scoped_ptr<content_settings::RuleIterator> rule_iterator(
647 provider->GetRuleIterator(content_type,
648 resource_identifier,
649 incognito));
650 while (rule_iterator->HasNext()) {
651 const content_settings::Rule& rule = rule_iterator->Next();
652 ContentSetting setting_value = CONTENT_SETTING_DEFAULT;
653 // TODO(bauerb): Return rules as a list of values, not content settings.
654 // Handle the case using compound values for its exceptions and arbitrary
655 // values for its default setting. Here we assume all the exceptions
656 // are granted as |CONTENT_SETTING_ALLOW|.
657 if (ContentTypeHasCompoundValue(content_type) &&
658 rule.value.get() &&
659 rule.primary_pattern != ContentSettingsPattern::Wildcard()) {
660 setting_value = CONTENT_SETTING_ALLOW;
661 } else {
662 setting_value = content_settings::ValueToContentSetting(rule.value.get());
663 }
664 settings->push_back(ContentSettingPatternSource(
665 rule.primary_pattern, rule.secondary_pattern,
666 setting_value,
667 kProviderNames[provider_type],
668 incognito));
669 }
670 }
671
UsedContentSettingsProviders() const672 void HostContentSettingsMap::UsedContentSettingsProviders() const {
673 #ifndef NDEBUG
674 if (used_from_thread_id_ == base::kInvalidThreadId)
675 return;
676
677 if (base::PlatformThread::CurrentId() != used_from_thread_id_)
678 used_from_thread_id_ = base::kInvalidThreadId;
679 #endif
680 }
681
ShouldAllowAllContent(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type)682 bool HostContentSettingsMap::ShouldAllowAllContent(
683 const GURL& primary_url,
684 const GURL& secondary_url,
685 ContentSettingsType content_type) {
686 if (content_type == CONTENT_SETTINGS_TYPE_NOTIFICATIONS ||
687 content_type == CONTENT_SETTINGS_TYPE_GEOLOCATION ||
688 content_type == CONTENT_SETTINGS_TYPE_MIDI_SYSEX) {
689 return false;
690 }
691 #if defined(OS_ANDROID) || defined(OS_CHROMEOS)
692 if (content_type == CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER) {
693 return false;
694 }
695 #endif
696 if (secondary_url.SchemeIs(content::kChromeUIScheme) &&
697 content_type == CONTENT_SETTINGS_TYPE_COOKIES &&
698 primary_url.SchemeIsSecure()) {
699 return true;
700 }
701 #if defined(ENABLE_EXTENSIONS)
702 if (primary_url.SchemeIs(extensions::kExtensionScheme)) {
703 switch (content_type) {
704 case CONTENT_SETTINGS_TYPE_PLUGINS:
705 case CONTENT_SETTINGS_TYPE_MEDIASTREAM:
706 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC:
707 case CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA:
708 return false;
709 case CONTENT_SETTINGS_TYPE_COOKIES:
710 return secondary_url.SchemeIs(extensions::kExtensionScheme);
711 default:
712 return true;
713 }
714 }
715 #endif
716 return primary_url.SchemeIs(content::kChromeDevToolsScheme) ||
717 primary_url.SchemeIs(content::kChromeUIScheme);
718 }
719
GetWebsiteSetting(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,content_settings::SettingInfo * info) const720 scoped_ptr<base::Value> HostContentSettingsMap::GetWebsiteSetting(
721 const GURL& primary_url,
722 const GURL& secondary_url,
723 ContentSettingsType content_type,
724 const std::string& resource_identifier,
725 content_settings::SettingInfo* info) const {
726 DCHECK(SupportsResourceIdentifier(content_type) ||
727 resource_identifier.empty());
728
729 // Check if the scheme of the requesting url is whitelisted.
730 if (ShouldAllowAllContent(primary_url, secondary_url, content_type)) {
731 if (info) {
732 info->source = content_settings::SETTING_SOURCE_WHITELIST;
733 info->primary_pattern = ContentSettingsPattern::Wildcard();
734 info->secondary_pattern = ContentSettingsPattern::Wildcard();
735 }
736 return scoped_ptr<base::Value>(
737 new base::FundamentalValue(CONTENT_SETTING_ALLOW));
738 }
739
740 return GetWebsiteSettingInternal(primary_url,
741 secondary_url,
742 content_type,
743 resource_identifier,
744 info,
745 true);
746 }
747
748 // static
749 HostContentSettingsMap::ProviderType
GetProviderTypeFromSource(const std::string & source)750 HostContentSettingsMap::GetProviderTypeFromSource(const std::string& source) {
751 for (size_t i = 0; i < arraysize(kProviderNames); ++i) {
752 if (source == kProviderNames[i])
753 return static_cast<ProviderType>(i);
754 }
755
756 NOTREACHED();
757 return DEFAULT_PROVIDER;
758 }
759
GetPrefProvider()760 content_settings::PrefProvider* HostContentSettingsMap::GetPrefProvider() {
761 return static_cast<content_settings::PrefProvider*>(
762 content_settings_providers_[PREF_PROVIDER]);
763 }
764
GetWebsiteSettingInternal(const GURL & primary_url,const GURL & secondary_url,ContentSettingsType content_type,const std::string & resource_identifier,content_settings::SettingInfo * info,bool get_override) const765 scoped_ptr<base::Value> HostContentSettingsMap::GetWebsiteSettingInternal(
766 const GURL& primary_url,
767 const GURL& secondary_url,
768 ContentSettingsType content_type,
769 const std::string& resource_identifier,
770 content_settings::SettingInfo* info,
771 bool get_override) const {
772 UsedContentSettingsProviders();
773 ContentSettingsPattern* primary_pattern = NULL;
774 ContentSettingsPattern* secondary_pattern = NULL;
775 if (info) {
776 primary_pattern = &info->primary_pattern;
777 secondary_pattern = &info->secondary_pattern;
778 }
779
780 // The list of |content_settings_providers_| is ordered according to their
781 // precedence.
782 for (ConstProviderIterator provider = content_settings_providers_.begin();
783 provider != content_settings_providers_.end();
784 ++provider) {
785 if (!get_override && provider->first == OVERRIDE_PROVIDER)
786 continue;
787
788 scoped_ptr<base::Value> value(
789 content_settings::GetContentSettingValueAndPatterns(provider->second,
790 primary_url,
791 secondary_url,
792 content_type,
793 resource_identifier,
794 is_off_the_record_,
795 primary_pattern,
796 secondary_pattern));
797 if (value) {
798 if (info)
799 info->source = kProviderSourceMap[provider->first];
800 return value.Pass();
801 }
802 }
803
804 if (info) {
805 info->source = content_settings::SETTING_SOURCE_NONE;
806 info->primary_pattern = ContentSettingsPattern();
807 info->secondary_pattern = ContentSettingsPattern();
808 }
809 return scoped_ptr<base::Value>();
810 }
811