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 "chrome/browser/content_settings/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/content_settings/content_settings_utils.h"
22 #include "chrome/browser/prefs/browser_prefs.h"
23 #include "chrome/browser/prefs/pref_service_mock_factory.h"
24 #include "chrome/browser/prefs/pref_service_syncable.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/pref_names.h"
27 #include "chrome/common/url_constants.h"
28 #include "chrome/test/base/testing_pref_service_syncable.h"
29 #include "chrome/test/base/testing_profile.h"
30 #include "components/pref_registry/pref_registry_syncable.h"
31 #include "content/public/test/test_browser_thread.h"
32 #include "testing/gtest/include/gtest/gtest.h"
36 using content::BrowserThread
;
38 namespace content_settings
{
40 class DeadlockCheckerThread
: public base::PlatformThread::Delegate
{
42 explicit DeadlockCheckerThread(PrefProvider
* provider
)
43 : provider_(provider
) {}
45 virtual void ThreadMain() override
{
46 bool got_lock
= provider_
->lock_
.Try();
47 EXPECT_TRUE(got_lock
);
49 provider_
->lock_
.Release();
52 PrefProvider
* provider_
;
53 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerThread
);
56 // A helper for observing an preference changes and testing whether
57 // |PrefProvider| holds a lock when the preferences change.
58 class DeadlockCheckerObserver
{
60 // |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
62 DeadlockCheckerObserver(PrefService
* prefs
, PrefProvider
* provider
)
63 : provider_(provider
),
64 notification_received_(false) {
65 pref_change_registrar_
.Init(prefs
);
66 pref_change_registrar_
.Add(
67 prefs::kContentSettingsPatternPairs
,
69 &DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged
,
70 base::Unretained(this)));
72 virtual ~DeadlockCheckerObserver() {}
74 bool notification_received() const {
75 return notification_received_
;
79 void OnContentSettingsPatternPairsChanged() {
80 // Check whether |provider_| holds its lock. For this, we need a
82 DeadlockCheckerThread
thread(provider_
);
83 base::PlatformThreadHandle handle
;
84 ASSERT_TRUE(base::PlatformThread::Create(0, &thread
, &handle
));
85 base::PlatformThread::Join(handle
);
86 notification_received_
= true;
89 PrefProvider
* provider_
;
90 PrefChangeRegistrar pref_change_registrar_
;
91 bool notification_received_
;
92 DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerObserver
);
95 class PrefProviderTest
: public testing::Test
{
97 PrefProviderTest() : ui_thread_(
98 BrowserThread::UI
, &message_loop_
) {
102 base::MessageLoop message_loop_
;
103 content::TestBrowserThread ui_thread_
;
106 TEST_F(PrefProviderTest
, Observer
) {
107 TestingProfile profile
;
108 PrefProvider
pref_content_settings_provider(profile
.GetPrefs(), false);
110 ContentSettingsPattern pattern
=
111 ContentSettingsPattern::FromString("[*.]example.com");
112 content_settings::MockObserver mock_observer
;
113 EXPECT_CALL(mock_observer
,
114 OnContentSettingChanged(pattern
,
115 ContentSettingsPattern::Wildcard(),
116 CONTENT_SETTINGS_TYPE_IMAGES
,
119 pref_content_settings_provider
.AddObserver(&mock_observer
);
121 pref_content_settings_provider
.SetWebsiteSetting(
123 ContentSettingsPattern::Wildcard(),
124 CONTENT_SETTINGS_TYPE_IMAGES
,
126 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
128 pref_content_settings_provider
.ShutdownOnUIThread();
131 // Test for regression in which the PrefProvider modified the user pref store
132 // of the OTR unintentionally: http://crbug.com/74466.
133 TEST_F(PrefProviderTest
, Incognito
) {
134 PersistentPrefStore
* user_prefs
= new TestingPrefStore();
135 OverlayUserPrefStore
* otr_user_prefs
=
136 new OverlayUserPrefStore(user_prefs
);
138 PrefServiceMockFactory factory
;
139 factory
.set_user_prefs(make_scoped_refptr(user_prefs
));
140 scoped_refptr
<user_prefs::PrefRegistrySyncable
> registry(
141 new user_prefs::PrefRegistrySyncable
);
142 PrefServiceSyncable
* regular_prefs
=
143 factory
.CreateSyncable(registry
.get()).release();
145 chrome::RegisterUserProfilePrefs(registry
.get());
147 PrefServiceMockFactory otr_factory
;
148 otr_factory
.set_user_prefs(make_scoped_refptr(otr_user_prefs
));
149 scoped_refptr
<user_prefs::PrefRegistrySyncable
> otr_registry(
150 new user_prefs::PrefRegistrySyncable
);
151 PrefServiceSyncable
* otr_prefs
=
152 otr_factory
.CreateSyncable(otr_registry
.get()).release();
154 chrome::RegisterUserProfilePrefs(otr_registry
.get());
156 TestingProfile::Builder profile_builder
;
157 profile_builder
.SetPrefService(make_scoped_ptr(regular_prefs
));
158 scoped_ptr
<TestingProfile
> profile
= profile_builder
.Build();
160 TestingProfile::Builder otr_profile_builder
;
161 otr_profile_builder
.SetPrefService(make_scoped_ptr(otr_prefs
));
162 otr_profile_builder
.BuildIncognito(profile
.get());
164 PrefProvider
pref_content_settings_provider(regular_prefs
, false);
165 PrefProvider
pref_content_settings_provider_incognito(otr_prefs
, true);
166 ContentSettingsPattern pattern
=
167 ContentSettingsPattern::FromString("[*.]example.com");
168 pref_content_settings_provider
.SetWebsiteSetting(
171 CONTENT_SETTINGS_TYPE_IMAGES
,
173 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
175 GURL
host("http://example.com/");
176 // The value should of course be visible in the regular PrefProvider.
177 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
178 GetContentSetting(&pref_content_settings_provider
,
181 CONTENT_SETTINGS_TYPE_IMAGES
,
184 // And also in the OTR version.
185 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
186 GetContentSetting(&pref_content_settings_provider_incognito
,
189 CONTENT_SETTINGS_TYPE_IMAGES
,
192 // But the value should not be overridden in the OTR user prefs accidentally.
193 EXPECT_FALSE(otr_user_prefs
->IsSetInOverlay(
194 prefs::kContentSettingsPatternPairs
));
196 pref_content_settings_provider
.ShutdownOnUIThread();
197 pref_content_settings_provider_incognito
.ShutdownOnUIThread();
200 TEST_F(PrefProviderTest
, GetContentSettingsValue
) {
201 TestingProfile testing_profile
;
202 PrefProvider
provider(testing_profile
.GetPrefs(), false);
204 GURL
primary_url("http://example.com/");
205 ContentSettingsPattern primary_pattern
=
206 ContentSettingsPattern::FromString("[*.]example.com");
208 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
209 GetContentSetting(&provider
,
212 CONTENT_SETTINGS_TYPE_IMAGES
,
217 GetContentSettingValue(&provider
,
220 CONTENT_SETTINGS_TYPE_IMAGES
,
224 provider
.SetWebsiteSetting(primary_pattern
,
226 CONTENT_SETTINGS_TYPE_IMAGES
,
228 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
229 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
230 GetContentSetting(&provider
,
233 CONTENT_SETTINGS_TYPE_IMAGES
,
236 scoped_ptr
<base::Value
> value_ptr(
237 GetContentSettingValue(&provider
,
240 CONTENT_SETTINGS_TYPE_IMAGES
,
244 value_ptr
->GetAsInteger(&int_value
);
245 EXPECT_EQ(CONTENT_SETTING_BLOCK
, IntToContentSetting(int_value
));
247 provider
.SetWebsiteSetting(primary_pattern
,
249 CONTENT_SETTINGS_TYPE_IMAGES
,
253 GetContentSettingValue(&provider
,
256 CONTENT_SETTINGS_TYPE_IMAGES
,
259 provider
.ShutdownOnUIThread();
262 TEST_F(PrefProviderTest
, Patterns
) {
263 TestingProfile testing_profile
;
264 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
267 GURL
host1("http://example.com/");
268 GURL
host2("http://www.example.com/");
269 GURL
host3("http://example.org/");
270 GURL
host4("file:///tmp/test.html");
271 ContentSettingsPattern pattern1
=
272 ContentSettingsPattern::FromString("[*.]example.com");
273 ContentSettingsPattern pattern2
=
274 ContentSettingsPattern::FromString("example.org");
275 ContentSettingsPattern pattern3
=
276 ContentSettingsPattern::FromString("file:///tmp/test.html");
278 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
279 GetContentSetting(&pref_content_settings_provider
,
282 CONTENT_SETTINGS_TYPE_IMAGES
,
285 pref_content_settings_provider
.SetWebsiteSetting(
288 CONTENT_SETTINGS_TYPE_IMAGES
,
290 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
291 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
292 GetContentSetting(&pref_content_settings_provider
,
295 CONTENT_SETTINGS_TYPE_IMAGES
,
298 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
299 GetContentSetting(&pref_content_settings_provider
,
302 CONTENT_SETTINGS_TYPE_IMAGES
,
306 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
307 GetContentSetting(&pref_content_settings_provider
,
310 CONTENT_SETTINGS_TYPE_IMAGES
,
313 pref_content_settings_provider
.SetWebsiteSetting(
316 CONTENT_SETTINGS_TYPE_IMAGES
,
318 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
319 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
320 GetContentSetting(&pref_content_settings_provider
,
323 CONTENT_SETTINGS_TYPE_IMAGES
,
327 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
328 GetContentSetting(&pref_content_settings_provider
,
331 CONTENT_SETTINGS_TYPE_IMAGES
,
334 pref_content_settings_provider
.SetWebsiteSetting(
337 CONTENT_SETTINGS_TYPE_IMAGES
,
339 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
340 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
341 GetContentSetting(&pref_content_settings_provider
,
344 CONTENT_SETTINGS_TYPE_IMAGES
,
348 pref_content_settings_provider
.ShutdownOnUIThread();
351 TEST_F(PrefProviderTest
, ResourceIdentifier
) {
352 TestingProfile testing_profile
;
353 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
356 GURL
host("http://example.com/");
357 ContentSettingsPattern pattern
=
358 ContentSettingsPattern::FromString("[*.]example.com");
359 std::string
resource1("someplugin");
360 std::string
resource2("otherplugin");
362 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
364 &pref_content_settings_provider
,
365 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
367 pref_content_settings_provider
.SetWebsiteSetting(
370 CONTENT_SETTINGS_TYPE_PLUGINS
,
372 new base::FundamentalValue(CONTENT_SETTING_BLOCK
));
373 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
375 &pref_content_settings_provider
,
376 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
378 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
380 &pref_content_settings_provider
,
381 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
384 pref_content_settings_provider
.ShutdownOnUIThread();
387 TEST_F(PrefProviderTest
, AutoSubmitCertificateContentSetting
) {
388 TestingProfile profile
;
389 TestingPrefServiceSyncable
* prefs
= profile
.GetTestingPrefService();
390 GURL
primary_url("https://www.example.com");
391 GURL
secondary_url("https://www.sample.com");
393 PrefProvider
provider(prefs
, false);
395 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
400 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
404 provider
.SetWebsiteSetting(ContentSettingsPattern::FromURL(primary_url
),
405 ContentSettingsPattern::Wildcard(),
406 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
408 new base::FundamentalValue(CONTENT_SETTING_ALLOW
));
409 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
414 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
417 provider
.ShutdownOnUIThread();
420 // http://crosbug.com/17760
421 TEST_F(PrefProviderTest
, Deadlock
) {
422 TestingPrefServiceSyncable prefs
;
423 PrefProvider::RegisterProfilePrefs(prefs
.registry());
425 // Chain of events: a preference changes, |PrefProvider| notices it, and reads
426 // and writes the preference. When the preference is written, a notification
427 // is sent, and this used to happen when |PrefProvider| was still holding its
430 PrefProvider
provider(&prefs
, false);
431 DeadlockCheckerObserver
observer(&prefs
, &provider
);
433 DictionaryPrefUpdate
update(&prefs
,
434 prefs::kContentSettingsPatternPairs
);
435 base::DictionaryValue
* mutable_settings
= update
.Get();
436 mutable_settings
->SetWithoutPathExpansion("www.example.com,*",
437 new base::DictionaryValue());
439 EXPECT_TRUE(observer
.notification_received());
441 provider
.ShutdownOnUIThread();
444 TEST_F(PrefProviderTest
, LastUsage
) {
445 TestingProfile testing_profile
;
446 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
448 base::SimpleTestClock
* test_clock
= new base::SimpleTestClock
;
449 test_clock
->SetNow(base::Time::Now());
451 pref_content_settings_provider
.SetClockForTesting(
452 scoped_ptr
<base::Clock
>(test_clock
));
453 GURL
host("http://example.com/");
454 ContentSettingsPattern pattern
=
455 ContentSettingsPattern::FromString("[*.]example.com");
457 base::Time no_usage
= pref_content_settings_provider
.GetLastUsage(
458 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
459 EXPECT_EQ(no_usage
.ToDoubleT(), 0);
461 pref_content_settings_provider
.UpdateLastUsage(
462 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
463 base::Time first
= pref_content_settings_provider
.GetLastUsage(
464 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
466 test_clock
->Advance(base::TimeDelta::FromSeconds(10));
468 pref_content_settings_provider
.UpdateLastUsage(
469 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
470 base::Time second
= pref_content_settings_provider
.GetLastUsage(
471 pattern
, pattern
, CONTENT_SETTINGS_TYPE_GEOLOCATION
);
473 base::TimeDelta delta
= second
- first
;
474 EXPECT_EQ(delta
.InSeconds(), 10);
476 pref_content_settings_provider
.ShutdownOnUIThread();
479 } // namespace content_settings