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_utils.h"
30 #include "components/content_settings/core/test/content_settings_test_utils.h"
31 #include "components/pref_registry/pref_registry_syncable.h"
32 #include "testing/gtest/include/gtest/gtest.h"
37 namespace content_settings
{
39 class DeadlockCheckerThread
: public base::PlatformThread::Delegate
{
41 explicit DeadlockCheckerThread(PrefProvider
* provider
)
42 : provider_(provider
) {}
44 void ThreadMain() override
{
45 bool got_lock
= provider_
->lock_
.Try();
46 EXPECT_TRUE(got_lock
);
48 provider_
->lock_
.Release();
51 PrefProvider
* provider_
;
52 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerThread
);
55 // A helper for observing an preference changes and testing whether
56 // |PrefProvider| holds a lock when the preferences change.
57 class DeadlockCheckerObserver
{
59 // |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
61 DeadlockCheckerObserver(PrefService
* prefs
, PrefProvider
* provider
)
62 : provider_(provider
),
63 notification_received_(false) {
64 pref_change_registrar_
.Init(prefs
);
65 pref_change_registrar_
.Add(
66 prefs::kContentSettingsPatternPairs
,
68 &DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged
,
69 base::Unretained(this)));
71 virtual ~DeadlockCheckerObserver() {}
73 bool notification_received() const {
74 return notification_received_
;
78 void OnContentSettingsPatternPairsChanged() {
79 // Check whether |provider_| holds its lock. For this, we need a
81 DeadlockCheckerThread
thread(provider_
);
82 base::PlatformThreadHandle handle
;
83 ASSERT_TRUE(base::PlatformThread::Create(0, &thread
, &handle
));
84 base::PlatformThread::Join(handle
);
85 notification_received_
= true;
88 PrefProvider
* provider_
;
89 PrefChangeRegistrar pref_change_registrar_
;
90 bool notification_received_
;
91 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerObserver
);
94 TEST(PrefProviderTest
, Observer
) {
95 TestingProfile profile
;
96 PrefProvider
pref_content_settings_provider(profile
.GetPrefs(), false);
98 ContentSettingsPattern pattern
=
99 ContentSettingsPattern::FromString("[*.]example.com");
100 content_settings::MockObserver mock_observer
;
101 EXPECT_CALL(mock_observer
,
102 OnContentSettingChanged(pattern
,
103 ContentSettingsPattern::Wildcard(),
104 CONTENT_SETTINGS_TYPE_IMAGES
,
107 pref_content_settings_provider
.AddObserver(&mock_observer
);
109 pref_content_settings_provider
.SetWebsiteSetting(
111 ContentSettingsPattern::Wildcard(),
112 CONTENT_SETTINGS_TYPE_IMAGES
,
114 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
116 pref_content_settings_provider
.ShutdownOnUIThread();
119 // Test for regression in which the PrefProvider modified the user pref store
120 // of the OTR unintentionally: http://crbug.com/74466.
121 TEST(PrefProviderTest
, Incognito
) {
122 PersistentPrefStore
* user_prefs
= new TestingPrefStore();
123 OverlayUserPrefStore
* otr_user_prefs
=
124 new OverlayUserPrefStore(user_prefs
);
126 PrefServiceMockFactory factory
;
127 factory
.set_user_prefs(make_scoped_refptr(user_prefs
));
128 scoped_refptr
<user_prefs::PrefRegistrySyncable
> registry(
129 new user_prefs::PrefRegistrySyncable
);
130 PrefServiceSyncable
* regular_prefs
=
131 factory
.CreateSyncable(registry
.get()).release();
133 chrome::RegisterUserProfilePrefs(registry
.get());
135 PrefServiceMockFactory otr_factory
;
136 otr_factory
.set_user_prefs(make_scoped_refptr(otr_user_prefs
));
137 scoped_refptr
<user_prefs::PrefRegistrySyncable
> otr_registry(
138 new user_prefs::PrefRegistrySyncable
);
139 PrefServiceSyncable
* otr_prefs
=
140 otr_factory
.CreateSyncable(otr_registry
.get()).release();
142 chrome::RegisterUserProfilePrefs(otr_registry
.get());
144 TestingProfile::Builder profile_builder
;
145 profile_builder
.SetPrefService(make_scoped_ptr(regular_prefs
));
146 scoped_ptr
<TestingProfile
> profile
= profile_builder
.Build();
148 TestingProfile::Builder otr_profile_builder
;
149 otr_profile_builder
.SetPrefService(make_scoped_ptr(otr_prefs
));
150 otr_profile_builder
.BuildIncognito(profile
.get());
152 PrefProvider
pref_content_settings_provider(regular_prefs
, false);
153 PrefProvider
pref_content_settings_provider_incognito(otr_prefs
, true);
154 ContentSettingsPattern pattern
=
155 ContentSettingsPattern::FromString("[*.]example.com");
156 pref_content_settings_provider
.SetWebsiteSetting(
159 CONTENT_SETTINGS_TYPE_IMAGES
,
161 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
163 GURL
host("http://example.com/");
164 // The value should of course be visible in the regular PrefProvider.
165 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
166 GetContentSetting(&pref_content_settings_provider
,
169 CONTENT_SETTINGS_TYPE_IMAGES
,
172 // And also in the OTR version.
173 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
174 GetContentSetting(&pref_content_settings_provider_incognito
,
177 CONTENT_SETTINGS_TYPE_IMAGES
,
180 // But the value should not be overridden in the OTR user prefs accidentally.
181 EXPECT_FALSE(otr_user_prefs
->IsSetInOverlay(
182 prefs::kContentSettingsPatternPairs
));
184 pref_content_settings_provider
.ShutdownOnUIThread();
185 pref_content_settings_provider_incognito
.ShutdownOnUIThread();
188 TEST(PrefProviderTest
, GetContentSettingsValue
) {
189 TestingProfile testing_profile
;
190 PrefProvider
provider(testing_profile
.GetPrefs(), false);
192 GURL
primary_url("http://example.com/");
193 ContentSettingsPattern primary_pattern
=
194 ContentSettingsPattern::FromString("[*.]example.com");
196 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
197 GetContentSetting(&provider
,
200 CONTENT_SETTINGS_TYPE_IMAGES
,
205 GetContentSettingValue(&provider
,
208 CONTENT_SETTINGS_TYPE_IMAGES
,
212 provider
.SetWebsiteSetting(primary_pattern
,
214 CONTENT_SETTINGS_TYPE_IMAGES
,
216 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
217 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
218 GetContentSetting(&provider
,
221 CONTENT_SETTINGS_TYPE_IMAGES
,
224 scoped_ptr
<base::Value
> value_ptr(
225 GetContentSettingValue(&provider
,
228 CONTENT_SETTINGS_TYPE_IMAGES
,
232 value_ptr
->GetAsInteger(&int_value
);
233 EXPECT_EQ(CONTENT_SETTING_BLOCK
, IntToContentSetting(int_value
));
235 provider
.SetWebsiteSetting(primary_pattern
,
237 CONTENT_SETTINGS_TYPE_IMAGES
,
241 GetContentSettingValue(&provider
,
244 CONTENT_SETTINGS_TYPE_IMAGES
,
247 provider
.ShutdownOnUIThread();
250 TEST(PrefProviderTest
, Patterns
) {
251 TestingProfile testing_profile
;
252 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
255 GURL
host1("http://example.com/");
256 GURL
host2("http://www.example.com/");
257 GURL
host3("http://example.org/");
258 GURL
host4("file:///tmp/test.html");
259 ContentSettingsPattern pattern1
=
260 ContentSettingsPattern::FromString("[*.]example.com");
261 ContentSettingsPattern pattern2
=
262 ContentSettingsPattern::FromString("example.org");
263 ContentSettingsPattern pattern3
=
264 ContentSettingsPattern::FromString("file:///tmp/test.html");
266 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
267 GetContentSetting(&pref_content_settings_provider
,
270 CONTENT_SETTINGS_TYPE_IMAGES
,
273 pref_content_settings_provider
.SetWebsiteSetting(
276 CONTENT_SETTINGS_TYPE_IMAGES
,
278 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
279 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
280 GetContentSetting(&pref_content_settings_provider
,
283 CONTENT_SETTINGS_TYPE_IMAGES
,
286 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
287 GetContentSetting(&pref_content_settings_provider
,
290 CONTENT_SETTINGS_TYPE_IMAGES
,
294 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
295 GetContentSetting(&pref_content_settings_provider
,
298 CONTENT_SETTINGS_TYPE_IMAGES
,
301 pref_content_settings_provider
.SetWebsiteSetting(
304 CONTENT_SETTINGS_TYPE_IMAGES
,
306 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
307 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
308 GetContentSetting(&pref_content_settings_provider
,
311 CONTENT_SETTINGS_TYPE_IMAGES
,
315 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
316 GetContentSetting(&pref_content_settings_provider
,
319 CONTENT_SETTINGS_TYPE_IMAGES
,
322 pref_content_settings_provider
.SetWebsiteSetting(
325 CONTENT_SETTINGS_TYPE_IMAGES
,
327 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
328 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
329 GetContentSetting(&pref_content_settings_provider
,
332 CONTENT_SETTINGS_TYPE_IMAGES
,
336 pref_content_settings_provider
.ShutdownOnUIThread();
339 TEST(PrefProviderTest
, ResourceIdentifier
) {
340 TestingProfile testing_profile
;
341 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
344 GURL
host("http://example.com/");
345 ContentSettingsPattern pattern
=
346 ContentSettingsPattern::FromString("[*.]example.com");
347 std::string
resource1("someplugin");
348 std::string
resource2("otherplugin");
350 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
352 &pref_content_settings_provider
,
353 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
355 pref_content_settings_provider
.SetWebsiteSetting(
358 CONTENT_SETTINGS_TYPE_PLUGINS
,
360 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
361 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
363 &pref_content_settings_provider
,
364 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
366 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
368 &pref_content_settings_provider
,
369 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
372 pref_content_settings_provider
.ShutdownOnUIThread();
375 TEST(PrefProviderTest
, AutoSubmitCertificateContentSetting
) {
376 TestingProfile profile
;
377 TestingPrefServiceSyncable
* prefs
= profile
.GetTestingPrefService();
378 GURL
primary_url("https://www.example.com");
379 GURL
secondary_url("https://www.sample.com");
381 PrefProvider
provider(prefs
, false);
383 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
388 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
392 provider
.SetWebsiteSetting(ContentSettingsPattern::FromURL(primary_url
),
393 ContentSettingsPattern::Wildcard(),
394 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
396 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
397 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
402 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
405 provider
.ShutdownOnUIThread();
408 // http://crosbug.com/17760
409 TEST(PrefProviderTest
, Deadlock
) {
410 TestingPrefServiceSyncable prefs
;
411 PrefProvider::RegisterProfilePrefs(prefs
.registry());
413 // Chain of events: a preference changes, |PrefProvider| notices it, and reads
414 // and writes the preference. When the preference is written, a notification
415 // is sent, and this used to happen when |PrefProvider| was still holding its
418 PrefProvider
provider(&prefs
, false);
419 DeadlockCheckerObserver
observer(&prefs
, &provider
);
421 DictionaryPrefUpdate
update(&prefs
,
422 prefs::kContentSettingsPatternPairs
);
423 base::DictionaryValue
* mutable_settings
= update
.Get();
424 mutable_settings
->SetWithoutPathExpansion("www.example.com,*",
425 new base::DictionaryValue());
427 EXPECT_TRUE(observer
.notification_received());
429 provider
.ShutdownOnUIThread();
432 TEST(PrefProviderTest
, LastUsage
) {
433 TestingProfile testing_profile
;
434 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
436 base::SimpleTestClock
* test_clock
= new base::SimpleTestClock
;
437 test_clock
->SetNow(base::Time::Now());
439 pref_content_settings_provider
.SetClockForTesting(
440 scoped_ptr
<base::Clock
>(test_clock
));
441 GURL
host("http://example.com/");
442 ContentSettingsPattern pattern
=
443 ContentSettingsPattern::FromString("[*.]example.com");
445 base::Time no_usage
= pref_content_settings_provider
.GetLastUsage(
446 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
447 EXPECT_EQ(no_usage
.ToDoubleT(), 0);
449 pref_content_settings_provider
.UpdateLastUsage(
450 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
451 base::Time first
= pref_content_settings_provider
.GetLastUsage(
452 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
454 test_clock
->Advance(base::TimeDelta::FromSeconds(10));
456 pref_content_settings_provider
.UpdateLastUsage(
457 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
458 base::Time second
= pref_content_settings_provider
.GetLastUsage(
459 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
461 base::TimeDelta delta
= second
- first
;
462 EXPECT_EQ(delta
.InSeconds(), 10);
464 pref_content_settings_provider
.ShutdownOnUIThread();
467 } // namespace content_settings