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.
5 #include "components/content_settings/core/browser/content_settings_pref_provider.h"
7 #include "base/auto_reset.h"
8 #include "base/command_line.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/prefs/default_pref_store.h"
12 #include "base/prefs/overlay_user_pref_store.h"
13 #include "base/prefs/pref_change_registrar.h"
14 #include "base/prefs/pref_service.h"
15 #include "base/prefs/scoped_user_pref_update.h"
16 #include "base/prefs/testing_pref_store.h"
17 #include "base/test/simple_test_clock.h"
18 #include "base/threading/platform_thread.h"
19 #include "base/values.h"
20 #include "chrome/browser/content_settings/content_settings_mock_observer.h"
21 #include "chrome/browser/prefs/browser_prefs.h"
22 #include "chrome/browser/prefs/pref_service_mock_factory.h"
23 #include "chrome/browser/prefs/pref_service_syncable.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/url_constants.h"
27 #include "chrome/test/base/testing_pref_service_syncable.h"
28 #include "chrome/test/base/testing_profile.h"
29 #include "components/content_settings/core/browser/content_settings_pref.h"
30 #include "components/content_settings/core/browser/content_settings_rule.h"
31 #include "components/content_settings/core/browser/content_settings_utils.h"
32 #include "components/content_settings/core/browser/website_settings_info.h"
33 #include "components/content_settings/core/browser/website_settings_registry.h"
34 #include "components/content_settings/core/test/content_settings_test_utils.h"
35 #include "components/pref_registry/pref_registry_syncable.h"
36 #include "content/public/test/test_browser_thread_bundle.h"
37 #include "testing/gtest/include/gtest/gtest.h"
42 namespace content_settings
{
44 class DeadlockCheckerThread
: public base::PlatformThread::Delegate
{
46 explicit DeadlockCheckerThread(const ContentSettingsPref
* pref
)
49 void ThreadMain() override
{
50 EXPECT_TRUE(pref_
->TryLockForTesting());
53 const ContentSettingsPref
* pref_
;
54 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerThread
);
57 // A helper for observing an preference changes and testing whether
58 // |PrefProvider| holds a lock when the preferences change.
59 class DeadlockCheckerObserver
{
61 // |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
63 DeadlockCheckerObserver(PrefService
* prefs
, PrefProvider
* provider
)
64 : provider_(provider
),
65 notification_received_(false) {
66 pref_change_registrar_
.Init(prefs
);
67 for (size_t i
= 0; i
< CONTENT_SETTINGS_NUM_TYPES
; ++i
) {
68 pref_change_registrar_
.Add(
69 provider_
->content_settings_prefs_
[i
]->pref_name_
,
71 &DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged
,
72 base::Unretained(this),
73 base::Unretained(provider_
->content_settings_prefs_
[i
])));
76 virtual ~DeadlockCheckerObserver() {}
78 bool notification_received() const {
79 return notification_received_
;
83 void OnContentSettingsPatternPairsChanged(const ContentSettingsPref
* pref
) {
84 // Check whether |provider_| holds its lock. For this, we need a
86 DeadlockCheckerThread
thread(pref
);
87 base::PlatformThreadHandle handle
;
88 ASSERT_TRUE(base::PlatformThread::Create(0, &thread
, &handle
));
89 base::PlatformThread::Join(handle
);
90 notification_received_
= true;
93 PrefProvider
* provider_
;
94 PrefChangeRegistrar pref_change_registrar_
;
95 bool notification_received_
;
96 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerObserver
);
99 class PrefProviderTest
: public testing::Test
{
100 content::TestBrowserThreadBundle thread_bundle_
;
103 TEST_F(PrefProviderTest
, Observer
) {
104 TestingProfile profile
;
105 PrefProvider
pref_content_settings_provider(profile
.GetPrefs(), false);
107 ContentSettingsPattern pattern
=
108 ContentSettingsPattern::FromString("[*.]example.com");
109 MockObserver mock_observer
;
110 EXPECT_CALL(mock_observer
,
111 OnContentSettingChanged(pattern
,
112 ContentSettingsPattern::Wildcard(),
113 CONTENT_SETTINGS_TYPE_IMAGES
,
116 pref_content_settings_provider
.AddObserver(&mock_observer
);
118 pref_content_settings_provider
.SetWebsiteSetting(
120 ContentSettingsPattern::Wildcard(),
121 CONTENT_SETTINGS_TYPE_IMAGES
,
123 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
125 pref_content_settings_provider
.ShutdownOnUIThread();
128 // Test for regression in which the PrefProvider modified the user pref store
129 // of the OTR unintentionally: http://crbug.com/74466.
130 TEST_F(PrefProviderTest
, Incognito
) {
131 PersistentPrefStore
* user_prefs
= new TestingPrefStore();
132 OverlayUserPrefStore
* otr_user_prefs
=
133 new OverlayUserPrefStore(user_prefs
);
135 PrefServiceMockFactory factory
;
136 factory
.set_user_prefs(make_scoped_refptr(user_prefs
));
137 scoped_refptr
<user_prefs::PrefRegistrySyncable
> registry(
138 new user_prefs::PrefRegistrySyncable
);
139 PrefServiceSyncable
* regular_prefs
=
140 factory
.CreateSyncable(registry
.get()).release();
142 chrome::RegisterUserProfilePrefs(registry
.get());
144 PrefServiceMockFactory otr_factory
;
145 otr_factory
.set_user_prefs(make_scoped_refptr(otr_user_prefs
));
146 scoped_refptr
<user_prefs::PrefRegistrySyncable
> otr_registry(
147 new user_prefs::PrefRegistrySyncable
);
148 PrefServiceSyncable
* otr_prefs
=
149 otr_factory
.CreateSyncable(otr_registry
.get()).release();
151 chrome::RegisterUserProfilePrefs(otr_registry
.get());
153 TestingProfile::Builder profile_builder
;
154 profile_builder
.SetPrefService(make_scoped_ptr(regular_prefs
));
155 scoped_ptr
<TestingProfile
> profile
= profile_builder
.Build();
157 TestingProfile::Builder otr_profile_builder
;
158 otr_profile_builder
.SetPrefService(make_scoped_ptr(otr_prefs
));
159 otr_profile_builder
.BuildIncognito(profile
.get());
161 PrefProvider
pref_content_settings_provider(regular_prefs
, false);
162 PrefProvider
pref_content_settings_provider_incognito(otr_prefs
, true);
163 ContentSettingsPattern pattern
=
164 ContentSettingsPattern::FromString("[*.]example.com");
165 pref_content_settings_provider
.SetWebsiteSetting(
168 CONTENT_SETTINGS_TYPE_IMAGES
,
170 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
172 GURL
host("http://example.com/");
173 // The value should of course be visible in the regular PrefProvider.
174 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
175 GetContentSetting(&pref_content_settings_provider
,
178 CONTENT_SETTINGS_TYPE_IMAGES
,
181 // And also in the OTR version.
182 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
183 GetContentSetting(&pref_content_settings_provider_incognito
,
186 CONTENT_SETTINGS_TYPE_IMAGES
,
189 const WebsiteSettingsInfo
* info
=
190 WebsiteSettingsRegistry::GetInstance()->Get(CONTENT_SETTINGS_TYPE_IMAGES
);
191 // But the value should not be overridden in the OTR user prefs accidentally.
192 EXPECT_FALSE(otr_user_prefs
->IsSetInOverlay(info
->pref_name()));
194 pref_content_settings_provider
.ShutdownOnUIThread();
195 pref_content_settings_provider_incognito
.ShutdownOnUIThread();
198 TEST_F(PrefProviderTest
, GetContentSettingsValue
) {
199 TestingProfile testing_profile
;
200 PrefProvider
provider(testing_profile
.GetPrefs(), false);
202 GURL
primary_url("http://example.com/");
203 ContentSettingsPattern primary_pattern
=
204 ContentSettingsPattern::FromString("[*.]example.com");
206 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
207 GetContentSetting(&provider
,
210 CONTENT_SETTINGS_TYPE_IMAGES
,
215 GetContentSettingValue(&provider
,
218 CONTENT_SETTINGS_TYPE_IMAGES
,
222 provider
.SetWebsiteSetting(primary_pattern
,
224 CONTENT_SETTINGS_TYPE_IMAGES
,
226 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
227 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
228 GetContentSetting(&provider
,
231 CONTENT_SETTINGS_TYPE_IMAGES
,
234 scoped_ptr
<base::Value
> value_ptr(
235 GetContentSettingValue(&provider
,
238 CONTENT_SETTINGS_TYPE_IMAGES
,
242 value_ptr
->GetAsInteger(&int_value
);
243 EXPECT_EQ(CONTENT_SETTING_BLOCK
, IntToContentSetting(int_value
));
245 provider
.SetWebsiteSetting(primary_pattern
,
247 CONTENT_SETTINGS_TYPE_IMAGES
,
251 GetContentSettingValue(&provider
,
254 CONTENT_SETTINGS_TYPE_IMAGES
,
257 provider
.ShutdownOnUIThread();
260 TEST_F(PrefProviderTest
, Patterns
) {
261 TestingProfile testing_profile
;
262 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
265 GURL
host1("http://example.com/");
266 GURL
host2("http://www.example.com/");
267 GURL
host3("http://example.org/");
268 GURL
host4("file:///tmp/test.html");
269 ContentSettingsPattern pattern1
=
270 ContentSettingsPattern::FromString("[*.]example.com");
271 ContentSettingsPattern pattern2
=
272 ContentSettingsPattern::FromString("example.org");
273 ContentSettingsPattern pattern3
=
274 ContentSettingsPattern::FromString("file:///tmp/test.html");
276 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
277 GetContentSetting(&pref_content_settings_provider
,
280 CONTENT_SETTINGS_TYPE_IMAGES
,
283 pref_content_settings_provider
.SetWebsiteSetting(
286 CONTENT_SETTINGS_TYPE_IMAGES
,
288 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
289 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
290 GetContentSetting(&pref_content_settings_provider
,
293 CONTENT_SETTINGS_TYPE_IMAGES
,
296 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
297 GetContentSetting(&pref_content_settings_provider
,
300 CONTENT_SETTINGS_TYPE_IMAGES
,
304 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
305 GetContentSetting(&pref_content_settings_provider
,
308 CONTENT_SETTINGS_TYPE_IMAGES
,
311 pref_content_settings_provider
.SetWebsiteSetting(
314 CONTENT_SETTINGS_TYPE_IMAGES
,
316 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
317 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
318 GetContentSetting(&pref_content_settings_provider
,
321 CONTENT_SETTINGS_TYPE_IMAGES
,
325 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
326 GetContentSetting(&pref_content_settings_provider
,
329 CONTENT_SETTINGS_TYPE_IMAGES
,
332 pref_content_settings_provider
.SetWebsiteSetting(
335 CONTENT_SETTINGS_TYPE_IMAGES
,
337 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
338 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
339 GetContentSetting(&pref_content_settings_provider
,
342 CONTENT_SETTINGS_TYPE_IMAGES
,
346 pref_content_settings_provider
.ShutdownOnUIThread();
349 TEST_F(PrefProviderTest
, ResourceIdentifier
) {
350 TestingProfile testing_profile
;
351 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
354 GURL
host("http://example.com/");
355 ContentSettingsPattern pattern
=
356 ContentSettingsPattern::FromString("[*.]example.com");
357 std::string
resource1("someplugin");
358 std::string
resource2("otherplugin");
360 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
362 &pref_content_settings_provider
,
363 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
365 pref_content_settings_provider
.SetWebsiteSetting(
368 CONTENT_SETTINGS_TYPE_PLUGINS
,
370 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
371 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
373 &pref_content_settings_provider
,
374 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
376 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
378 &pref_content_settings_provider
,
379 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
382 pref_content_settings_provider
.ShutdownOnUIThread();
385 TEST_F(PrefProviderTest
, AutoSubmitCertificateContentSetting
) {
386 TestingProfile profile
;
387 TestingPrefServiceSyncable
* prefs
= profile
.GetTestingPrefService();
388 GURL
primary_url("https://www.example.com");
389 GURL
secondary_url("https://www.sample.com");
391 PrefProvider
provider(prefs
, false);
393 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
398 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
402 provider
.SetWebsiteSetting(ContentSettingsPattern::FromURL(primary_url
),
403 ContentSettingsPattern::Wildcard(),
404 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
406 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
407 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
412 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
415 provider
.ShutdownOnUIThread();
418 // http://crosbug.com/17760
419 TEST_F(PrefProviderTest
, Deadlock
) {
420 TestingPrefServiceSyncable prefs
;
421 PrefProvider::RegisterProfilePrefs(prefs
.registry());
423 // Chain of events: a preference changes, |PrefProvider| notices it, and reads
424 // and writes the preference. When the preference is written, a notification
425 // is sent, and this used to happen when |PrefProvider| was still holding its
428 const WebsiteSettingsInfo
* info
=
429 WebsiteSettingsRegistry::GetInstance()->Get(CONTENT_SETTINGS_TYPE_IMAGES
);
430 PrefProvider
provider(&prefs
, false);
431 DeadlockCheckerObserver
observer(&prefs
, &provider
);
433 DictionaryPrefUpdate
update(&prefs
, info
->pref_name());
434 base::DictionaryValue
* mutable_settings
= update
.Get();
435 mutable_settings
->SetWithoutPathExpansion("www.example.com,*",
436 new base::DictionaryValue());
438 EXPECT_TRUE(observer
.notification_received());
440 provider
.ShutdownOnUIThread();
443 TEST_F(PrefProviderTest
, LastUsage
) {
444 TestingProfile testing_profile
;
445 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
447 base::SimpleTestClock
* test_clock
= new base::SimpleTestClock
;
448 test_clock
->SetNow(base::Time::Now());
450 pref_content_settings_provider
.SetClockForTesting(
451 scoped_ptr
<base::Clock
>(test_clock
));
452 GURL
host("http://example.com/");
453 ContentSettingsPattern pattern
=
454 ContentSettingsPattern::FromString("[*.]example.com");
456 base::Time no_usage
= pref_content_settings_provider
.GetLastUsage(
457 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
458 EXPECT_EQ(no_usage
.ToDoubleT(), 0);
460 pref_content_settings_provider
.UpdateLastUsage(
461 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
462 base::Time first
= pref_content_settings_provider
.GetLastUsage(
463 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
465 test_clock
->Advance(base::TimeDelta::FromSeconds(10));
467 pref_content_settings_provider
.UpdateLastUsage(
468 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
469 base::Time second
= pref_content_settings_provider
.GetLastUsage(
470 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
472 base::TimeDelta delta
= second
- first
;
473 EXPECT_EQ(delta
.InSeconds(), 10);
475 pref_content_settings_provider
.ShutdownOnUIThread();
478 TEST_F(PrefProviderTest
, IncognitoInheritsValueMap
) {
479 TestingPrefServiceSyncable prefs
;
480 PrefProvider::RegisterProfilePrefs(prefs
.registry());
482 ContentSettingsPattern pattern_1
=
483 ContentSettingsPattern::FromString("google.com");
484 ContentSettingsPattern pattern_2
=
485 ContentSettingsPattern::FromString("www.google.com");
486 ContentSettingsPattern wildcard
=
487 ContentSettingsPattern::FromString("*");
488 scoped_ptr
<base::Value
> value(
489 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
491 // Create a normal provider and set a setting.
492 PrefProvider
normal_provider(&prefs
, false);
493 normal_provider
.SetWebsiteSetting(pattern_1
,
495 CONTENT_SETTINGS_TYPE_IMAGES
,
499 // Non-OTR provider, Non-OTR iterator has one setting (pattern 1).
501 scoped_ptr
<RuleIterator
> it(normal_provider
.GetRuleIterator(
502 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), false));
503 EXPECT_TRUE(it
->HasNext());
504 EXPECT_EQ(pattern_1
, it
->Next().primary_pattern
);
505 EXPECT_FALSE(it
->HasNext());
508 // Non-OTR provider, OTR iterator has no settings.
510 scoped_ptr
<RuleIterator
> it(normal_provider
.GetRuleIterator(
511 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), true));
512 EXPECT_FALSE(it
->HasNext());
515 // Create an incognito provider and set a setting.
516 PrefProvider
incognito_provider(&prefs
, true);
517 incognito_provider
.SetWebsiteSetting(pattern_2
,
519 CONTENT_SETTINGS_TYPE_IMAGES
,
523 // OTR provider, non-OTR iterator has one setting (pattern 1).
525 scoped_ptr
<RuleIterator
> it(incognito_provider
.GetRuleIterator(
526 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), false));
527 EXPECT_TRUE(it
->HasNext());
528 EXPECT_EQ(pattern_1
, it
->Next().primary_pattern
);
529 EXPECT_FALSE(it
->HasNext());
532 // OTR provider, OTR iterator has one setting (pattern 2).
534 scoped_ptr
<RuleIterator
> it(incognito_provider
.GetRuleIterator(
535 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), true));
536 EXPECT_TRUE(it
->HasNext());
537 EXPECT_EQ(pattern_2
, it
->Next().primary_pattern
);
538 EXPECT_FALSE(it
->HasNext());
541 incognito_provider
.ShutdownOnUIThread();
542 normal_provider
.ShutdownOnUIThread();
545 TEST_F(PrefProviderTest
, ClearAllContentSettingsRules
) {
546 TestingPrefServiceSyncable prefs
;
547 PrefProvider::RegisterProfilePrefs(prefs
.registry());
549 ContentSettingsPattern pattern
=
550 ContentSettingsPattern::FromString("google.com");
551 ContentSettingsPattern wildcard
=
552 ContentSettingsPattern::FromString("*");
553 scoped_ptr
<base::Value
> value(
554 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
555 ResourceIdentifier
res_id("abcde");
557 PrefProvider
provider(&prefs
, false);
559 // Non-empty pattern, syncable, empty resource identifier.
560 provider
.SetWebsiteSetting(pattern
, wildcard
, CONTENT_SETTINGS_TYPE_IMAGES
,
561 ResourceIdentifier(), value
->DeepCopy());
563 // Non-empty pattern, non-syncable, empty resource identifier.
564 provider
.SetWebsiteSetting(pattern
, wildcard
,
565 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
566 ResourceIdentifier(), value
->DeepCopy());
568 // Non-empty pattern, plugins, non-empty resource identifier.
569 provider
.SetWebsiteSetting(pattern
, wildcard
, CONTENT_SETTINGS_TYPE_PLUGINS
,
570 res_id
, value
->DeepCopy());
572 // Empty pattern, plugins, non-empty resource identifier.
573 provider
.SetWebsiteSetting(wildcard
, wildcard
, CONTENT_SETTINGS_TYPE_PLUGINS
,
574 res_id
, value
->DeepCopy());
576 // Non-empty pattern, syncable, empty resource identifier.
577 provider
.SetWebsiteSetting(pattern
, wildcard
, CONTENT_SETTINGS_TYPE_COOKIES
,
578 ResourceIdentifier(), value
->DeepCopy());
580 // Non-empty pattern, non-syncable, empty resource identifier.
581 provider
.SetWebsiteSetting(pattern
, wildcard
,
582 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
583 ResourceIdentifier(), value
->DeepCopy());
585 provider
.ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_IMAGES
);
586 provider
.ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_GEOLOCATION
);
587 provider
.ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_PLUGINS
);
589 WebsiteSettingsRegistry
* registry
= WebsiteSettingsRegistry::GetInstance();
590 // Test that the preferences for images, geolocation and plugins are empty.
591 const char* empty_prefs
[] = {
592 registry
->Get(CONTENT_SETTINGS_TYPE_IMAGES
)->pref_name().c_str(),
593 registry
->Get(CONTENT_SETTINGS_TYPE_GEOLOCATION
)->pref_name().c_str(),
594 registry
->Get(CONTENT_SETTINGS_TYPE_PLUGINS
)->pref_name().c_str(),
597 for (const char* pref
: empty_prefs
) {
598 DictionaryPrefUpdate
update(&prefs
, pref
);
599 const base::DictionaryValue
* dictionary
= update
.Get();
600 EXPECT_TRUE(dictionary
->empty());
603 // Test that the preferences for cookies and notifications are not empty.
604 const char* nonempty_prefs
[] = {
605 registry
->Get(CONTENT_SETTINGS_TYPE_COOKIES
)->pref_name().c_str(),
606 registry
->Get(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
)->pref_name().c_str(),
609 for (const char* pref
: nonempty_prefs
) {
610 DictionaryPrefUpdate
update(&prefs
, pref
);
611 const base::DictionaryValue
* dictionary
= update
.Get();
612 EXPECT_EQ(1u, dictionary
->size());
615 provider
.ShutdownOnUIThread();
618 } // namespace content_settings