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_registry.h"
31 #include "components/content_settings/core/browser/content_settings_rule.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/common/content_settings_pattern.h"
35 #include "components/content_settings/core/test/content_settings_test_utils.h"
36 #include "components/pref_registry/pref_registry_syncable.h"
37 #include "content/public/test/test_browser_thread_bundle.h"
38 #include "testing/gtest/include/gtest/gtest.h"
43 namespace content_settings
{
45 class DeadlockCheckerThread
: public base::PlatformThread::Delegate
{
47 explicit DeadlockCheckerThread(const ContentSettingsPref
* pref
)
50 void ThreadMain() override
{
51 EXPECT_TRUE(pref_
->TryLockForTesting());
54 const ContentSettingsPref
* pref_
;
55 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerThread
);
58 // A helper for observing an preference changes and testing whether
59 // |PrefProvider| holds a lock when the preferences change.
60 class DeadlockCheckerObserver
{
62 // |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
64 DeadlockCheckerObserver(PrefService
* prefs
, PrefProvider
* provider
)
65 : provider_(provider
),
66 notification_received_(false) {
67 pref_change_registrar_
.Init(prefs
);
68 for (ContentSettingsPref
* pref
: provider_
->content_settings_prefs_
) {
69 pref_change_registrar_
.Add(
72 &DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged
,
73 base::Unretained(this), base::Unretained(pref
)));
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
{
102 // Ensure all content settings are initialized.
103 ContentSettingsRegistry::GetInstance();
107 content::TestBrowserThreadBundle thread_bundle_
;
110 TEST_F(PrefProviderTest
, Observer
) {
111 TestingProfile profile
;
112 PrefProvider
pref_content_settings_provider(profile
.GetPrefs(), false);
114 ContentSettingsPattern pattern
=
115 ContentSettingsPattern::FromString("[*.]example.com");
116 MockObserver mock_observer
;
117 EXPECT_CALL(mock_observer
,
118 OnContentSettingChanged(pattern
,
119 ContentSettingsPattern::Wildcard(),
120 CONTENT_SETTINGS_TYPE_IMAGES
,
123 pref_content_settings_provider
.AddObserver(&mock_observer
);
125 pref_content_settings_provider
.SetWebsiteSetting(
127 ContentSettingsPattern::Wildcard(),
128 CONTENT_SETTINGS_TYPE_IMAGES
,
130 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
132 pref_content_settings_provider
.ShutdownOnUIThread();
135 // Test for regression in which the PrefProvider modified the user pref store
136 // of the OTR unintentionally: http://crbug.com/74466.
137 TEST_F(PrefProviderTest
, Incognito
) {
138 PersistentPrefStore
* user_prefs
= new TestingPrefStore();
139 OverlayUserPrefStore
* otr_user_prefs
=
140 new OverlayUserPrefStore(user_prefs
);
142 PrefServiceMockFactory factory
;
143 factory
.set_user_prefs(make_scoped_refptr(user_prefs
));
144 scoped_refptr
<user_prefs::PrefRegistrySyncable
> registry(
145 new user_prefs::PrefRegistrySyncable
);
146 PrefServiceSyncable
* regular_prefs
=
147 factory
.CreateSyncable(registry
.get()).release();
149 chrome::RegisterUserProfilePrefs(registry
.get());
151 PrefServiceMockFactory otr_factory
;
152 otr_factory
.set_user_prefs(make_scoped_refptr(otr_user_prefs
));
153 scoped_refptr
<user_prefs::PrefRegistrySyncable
> otr_registry(
154 new user_prefs::PrefRegistrySyncable
);
155 PrefServiceSyncable
* otr_prefs
=
156 otr_factory
.CreateSyncable(otr_registry
.get()).release();
158 chrome::RegisterUserProfilePrefs(otr_registry
.get());
160 TestingProfile::Builder profile_builder
;
161 profile_builder
.SetPrefService(make_scoped_ptr(regular_prefs
));
162 scoped_ptr
<TestingProfile
> profile
= profile_builder
.Build();
164 TestingProfile::Builder otr_profile_builder
;
165 otr_profile_builder
.SetPrefService(make_scoped_ptr(otr_prefs
));
166 otr_profile_builder
.BuildIncognito(profile
.get());
168 PrefProvider
pref_content_settings_provider(regular_prefs
, false);
169 PrefProvider
pref_content_settings_provider_incognito(otr_prefs
, true);
170 ContentSettingsPattern pattern
=
171 ContentSettingsPattern::FromString("[*.]example.com");
172 pref_content_settings_provider
.SetWebsiteSetting(
175 CONTENT_SETTINGS_TYPE_IMAGES
,
177 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
179 GURL
host("http://example.com/");
180 // The value should of course be visible in the regular PrefProvider.
181 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
182 GetContentSetting(&pref_content_settings_provider
,
185 CONTENT_SETTINGS_TYPE_IMAGES
,
188 // And also in the OTR version.
189 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
190 GetContentSetting(&pref_content_settings_provider_incognito
,
193 CONTENT_SETTINGS_TYPE_IMAGES
,
196 const WebsiteSettingsInfo
* info
=
197 WebsiteSettingsRegistry::GetInstance()->Get(CONTENT_SETTINGS_TYPE_IMAGES
);
198 // But the value should not be overridden in the OTR user prefs accidentally.
199 EXPECT_FALSE(otr_user_prefs
->IsSetInOverlay(info
->pref_name()));
201 pref_content_settings_provider
.ShutdownOnUIThread();
202 pref_content_settings_provider_incognito
.ShutdownOnUIThread();
205 TEST_F(PrefProviderTest
, GetContentSettingsValue
) {
206 TestingProfile testing_profile
;
207 PrefProvider
provider(testing_profile
.GetPrefs(), false);
209 GURL
primary_url("http://example.com/");
210 ContentSettingsPattern primary_pattern
=
211 ContentSettingsPattern::FromString("[*.]example.com");
213 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
214 GetContentSetting(&provider
,
217 CONTENT_SETTINGS_TYPE_IMAGES
,
222 GetContentSettingValue(&provider
,
225 CONTENT_SETTINGS_TYPE_IMAGES
,
229 provider
.SetWebsiteSetting(primary_pattern
,
231 CONTENT_SETTINGS_TYPE_IMAGES
,
233 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
234 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
235 GetContentSetting(&provider
,
238 CONTENT_SETTINGS_TYPE_IMAGES
,
241 scoped_ptr
<base::Value
> value_ptr(
242 GetContentSettingValue(&provider
,
245 CONTENT_SETTINGS_TYPE_IMAGES
,
249 value_ptr
->GetAsInteger(&int_value
);
250 EXPECT_EQ(CONTENT_SETTING_BLOCK
, IntToContentSetting(int_value
));
252 provider
.SetWebsiteSetting(primary_pattern
,
254 CONTENT_SETTINGS_TYPE_IMAGES
,
258 GetContentSettingValue(&provider
,
261 CONTENT_SETTINGS_TYPE_IMAGES
,
264 provider
.ShutdownOnUIThread();
267 TEST_F(PrefProviderTest
, Patterns
) {
268 TestingProfile testing_profile
;
269 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
272 GURL
host1("http://example.com/");
273 GURL
host2("http://www.example.com/");
274 GURL
host3("http://example.org/");
275 GURL
host4("file:///tmp/test.html");
276 ContentSettingsPattern pattern1
=
277 ContentSettingsPattern::FromString("[*.]example.com");
278 ContentSettingsPattern pattern2
=
279 ContentSettingsPattern::FromString("example.org");
280 ContentSettingsPattern pattern3
=
281 ContentSettingsPattern::FromString("file:///tmp/test.html");
283 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
284 GetContentSetting(&pref_content_settings_provider
,
287 CONTENT_SETTINGS_TYPE_IMAGES
,
290 pref_content_settings_provider
.SetWebsiteSetting(
293 CONTENT_SETTINGS_TYPE_IMAGES
,
295 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
296 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
297 GetContentSetting(&pref_content_settings_provider
,
300 CONTENT_SETTINGS_TYPE_IMAGES
,
303 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
304 GetContentSetting(&pref_content_settings_provider
,
307 CONTENT_SETTINGS_TYPE_IMAGES
,
311 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
312 GetContentSetting(&pref_content_settings_provider
,
315 CONTENT_SETTINGS_TYPE_IMAGES
,
318 pref_content_settings_provider
.SetWebsiteSetting(
321 CONTENT_SETTINGS_TYPE_IMAGES
,
323 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
324 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
325 GetContentSetting(&pref_content_settings_provider
,
328 CONTENT_SETTINGS_TYPE_IMAGES
,
332 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
333 GetContentSetting(&pref_content_settings_provider
,
336 CONTENT_SETTINGS_TYPE_IMAGES
,
339 pref_content_settings_provider
.SetWebsiteSetting(
342 CONTENT_SETTINGS_TYPE_IMAGES
,
344 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
345 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
346 GetContentSetting(&pref_content_settings_provider
,
349 CONTENT_SETTINGS_TYPE_IMAGES
,
353 pref_content_settings_provider
.ShutdownOnUIThread();
356 TEST_F(PrefProviderTest
, ResourceIdentifier
) {
357 TestingProfile testing_profile
;
358 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
361 GURL
host("http://example.com/");
362 ContentSettingsPattern pattern
=
363 ContentSettingsPattern::FromString("[*.]example.com");
364 std::string
resource1("someplugin");
365 std::string
resource2("otherplugin");
367 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
369 &pref_content_settings_provider
,
370 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
372 pref_content_settings_provider
.SetWebsiteSetting(
375 CONTENT_SETTINGS_TYPE_PLUGINS
,
377 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
378 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
380 &pref_content_settings_provider
,
381 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
383 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
385 &pref_content_settings_provider
,
386 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
389 pref_content_settings_provider
.ShutdownOnUIThread();
392 TEST_F(PrefProviderTest
, AutoSubmitCertificateContentSetting
) {
393 TestingProfile profile
;
394 TestingPrefServiceSyncable
* prefs
= profile
.GetTestingPrefService();
395 GURL
primary_url("https://www.example.com");
396 GURL
secondary_url("https://www.sample.com");
398 PrefProvider
provider(prefs
, false);
400 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
405 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
409 provider
.SetWebsiteSetting(ContentSettingsPattern::FromURL(primary_url
),
410 ContentSettingsPattern::Wildcard(),
411 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
413 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
414 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
419 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
422 provider
.ShutdownOnUIThread();
425 // http://crosbug.com/17760
426 TEST_F(PrefProviderTest
, Deadlock
) {
427 TestingPrefServiceSyncable prefs
;
428 PrefProvider::RegisterProfilePrefs(prefs
.registry());
430 // Chain of events: a preference changes, |PrefProvider| notices it, and reads
431 // and writes the preference. When the preference is written, a notification
432 // is sent, and this used to happen when |PrefProvider| was still holding its
435 const WebsiteSettingsInfo
* info
=
436 WebsiteSettingsRegistry::GetInstance()->Get(CONTENT_SETTINGS_TYPE_IMAGES
);
437 PrefProvider
provider(&prefs
, false);
438 DeadlockCheckerObserver
observer(&prefs
, &provider
);
440 DictionaryPrefUpdate
update(&prefs
, info
->pref_name());
441 base::DictionaryValue
* mutable_settings
= update
.Get();
442 mutable_settings
->SetWithoutPathExpansion("www.example.com,*",
443 new base::DictionaryValue());
445 EXPECT_TRUE(observer
.notification_received());
447 provider
.ShutdownOnUIThread();
450 TEST_F(PrefProviderTest
, LastUsage
) {
451 TestingProfile testing_profile
;
452 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
454 base::SimpleTestClock
* test_clock
= new base::SimpleTestClock
;
455 test_clock
->SetNow(base::Time::Now());
457 pref_content_settings_provider
.SetClockForTesting(
458 scoped_ptr
<base::Clock
>(test_clock
));
459 GURL
host("http://example.com/");
460 ContentSettingsPattern pattern
=
461 ContentSettingsPattern::FromString("[*.]example.com");
463 base::Time no_usage
= pref_content_settings_provider
.GetLastUsage(
464 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
465 EXPECT_EQ(no_usage
.ToDoubleT(), 0);
467 pref_content_settings_provider
.UpdateLastUsage(
468 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
469 base::Time first
= pref_content_settings_provider
.GetLastUsage(
470 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
472 test_clock
->Advance(base::TimeDelta::FromSeconds(10));
474 pref_content_settings_provider
.UpdateLastUsage(
475 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
476 base::Time second
= pref_content_settings_provider
.GetLastUsage(
477 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
479 base::TimeDelta delta
= second
- first
;
480 EXPECT_EQ(delta
.InSeconds(), 10);
482 pref_content_settings_provider
.ShutdownOnUIThread();
485 TEST_F(PrefProviderTest
, IncognitoInheritsValueMap
) {
486 TestingPrefServiceSyncable prefs
;
487 PrefProvider::RegisterProfilePrefs(prefs
.registry());
489 ContentSettingsPattern pattern_1
=
490 ContentSettingsPattern::FromString("google.com");
491 ContentSettingsPattern pattern_2
=
492 ContentSettingsPattern::FromString("www.google.com");
493 ContentSettingsPattern wildcard
=
494 ContentSettingsPattern::FromString("*");
495 scoped_ptr
<base::Value
> value(
496 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
498 // Create a normal provider and set a setting.
499 PrefProvider
normal_provider(&prefs
, false);
500 normal_provider
.SetWebsiteSetting(pattern_1
,
502 CONTENT_SETTINGS_TYPE_IMAGES
,
506 // Non-OTR provider, Non-OTR iterator has one setting (pattern 1).
508 scoped_ptr
<RuleIterator
> it(normal_provider
.GetRuleIterator(
509 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), false));
510 EXPECT_TRUE(it
->HasNext());
511 EXPECT_EQ(pattern_1
, it
->Next().primary_pattern
);
512 EXPECT_FALSE(it
->HasNext());
515 // Non-OTR provider, OTR iterator has no settings.
517 scoped_ptr
<RuleIterator
> it(normal_provider
.GetRuleIterator(
518 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), true));
519 EXPECT_FALSE(it
->HasNext());
522 // Create an incognito provider and set a setting.
523 PrefProvider
incognito_provider(&prefs
, true);
524 incognito_provider
.SetWebsiteSetting(pattern_2
,
526 CONTENT_SETTINGS_TYPE_IMAGES
,
530 // OTR provider, non-OTR iterator has one setting (pattern 1).
532 scoped_ptr
<RuleIterator
> it(incognito_provider
.GetRuleIterator(
533 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), false));
534 EXPECT_TRUE(it
->HasNext());
535 EXPECT_EQ(pattern_1
, it
->Next().primary_pattern
);
536 EXPECT_FALSE(it
->HasNext());
539 // OTR provider, OTR iterator has one setting (pattern 2).
541 scoped_ptr
<RuleIterator
> it(incognito_provider
.GetRuleIterator(
542 CONTENT_SETTINGS_TYPE_IMAGES
, std::string(), true));
543 EXPECT_TRUE(it
->HasNext());
544 EXPECT_EQ(pattern_2
, it
->Next().primary_pattern
);
545 EXPECT_FALSE(it
->HasNext());
548 incognito_provider
.ShutdownOnUIThread();
549 normal_provider
.ShutdownOnUIThread();
552 TEST_F(PrefProviderTest
, ClearAllContentSettingsRules
) {
553 TestingPrefServiceSyncable prefs
;
554 PrefProvider::RegisterProfilePrefs(prefs
.registry());
556 ContentSettingsPattern pattern
=
557 ContentSettingsPattern::FromString("google.com");
558 ContentSettingsPattern wildcard
=
559 ContentSettingsPattern::FromString("*");
560 scoped_ptr
<base::Value
> value(
561 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
562 ResourceIdentifier
res_id("abcde");
564 PrefProvider
provider(&prefs
, false);
566 // Non-empty pattern, syncable, empty resource identifier.
567 provider
.SetWebsiteSetting(pattern
, wildcard
, CONTENT_SETTINGS_TYPE_IMAGES
,
568 ResourceIdentifier(), value
->DeepCopy());
570 // Non-empty pattern, non-syncable, empty resource identifier.
571 provider
.SetWebsiteSetting(pattern
, wildcard
,
572 CONTENT_SETTINGS_TYPE_GEOLOCATION
,
573 ResourceIdentifier(), value
->DeepCopy());
575 // Non-empty pattern, plugins, non-empty resource identifier.
576 provider
.SetWebsiteSetting(pattern
, wildcard
, CONTENT_SETTINGS_TYPE_PLUGINS
,
577 res_id
, value
->DeepCopy());
579 // Empty pattern, plugins, non-empty resource identifier.
580 provider
.SetWebsiteSetting(wildcard
, wildcard
, CONTENT_SETTINGS_TYPE_PLUGINS
,
581 res_id
, value
->DeepCopy());
583 // Non-empty pattern, syncable, empty resource identifier.
584 provider
.SetWebsiteSetting(pattern
, wildcard
, CONTENT_SETTINGS_TYPE_COOKIES
,
585 ResourceIdentifier(), value
->DeepCopy());
587 // Non-empty pattern, non-syncable, empty resource identifier.
588 provider
.SetWebsiteSetting(pattern
, wildcard
,
589 CONTENT_SETTINGS_TYPE_NOTIFICATIONS
,
590 ResourceIdentifier(), value
->DeepCopy());
592 provider
.ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_IMAGES
);
593 provider
.ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_GEOLOCATION
);
594 provider
.ClearAllContentSettingsRules(CONTENT_SETTINGS_TYPE_PLUGINS
);
596 WebsiteSettingsRegistry
* registry
= WebsiteSettingsRegistry::GetInstance();
597 // Test that the preferences for images, geolocation and plugins are empty.
598 const char* empty_prefs
[] = {
599 registry
->Get(CONTENT_SETTINGS_TYPE_IMAGES
)->pref_name().c_str(),
600 registry
->Get(CONTENT_SETTINGS_TYPE_GEOLOCATION
)->pref_name().c_str(),
601 registry
->Get(CONTENT_SETTINGS_TYPE_PLUGINS
)->pref_name().c_str(),
604 for (const char* pref
: empty_prefs
) {
605 DictionaryPrefUpdate
update(&prefs
, pref
);
606 const base::DictionaryValue
* dictionary
= update
.Get();
607 EXPECT_TRUE(dictionary
->empty());
610 // Test that the preferences for cookies and notifications are not empty.
611 const char* nonempty_prefs
[] = {
612 registry
->Get(CONTENT_SETTINGS_TYPE_COOKIES
)->pref_name().c_str(),
613 registry
->Get(CONTENT_SETTINGS_TYPE_NOTIFICATIONS
)->pref_name().c_str(),
616 for (const char* pref
: nonempty_prefs
) {
617 DictionaryPrefUpdate
update(&prefs
, pref
);
618 const base::DictionaryValue
* dictionary
= update
.Get();
619 EXPECT_EQ(1u, dictionary
->size());
622 provider
.ShutdownOnUIThread();
625 } // namespace content_settings