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/threading/platform_thread.h"
18 #include "base/values.h"
19 #include "chrome/browser/content_settings/content_settings_mock_observer.h"
20 #include "chrome/browser/content_settings/content_settings_utils.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/user_prefs/pref_registry_syncable.h"
30 #include "content/public/test/test_browser_thread.h"
31 #include "testing/gtest/include/gtest/gtest.h"
35 using content::BrowserThread
;
37 namespace content_settings
{
39 class DeadlockCheckerThread
: public base::PlatformThread::Delegate
{
41 explicit DeadlockCheckerThread(PrefProvider
* provider
)
42 : provider_(provider
) {}
44 virtual 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 class PrefProviderTest
: public testing::Test
{
96 PrefProviderTest() : ui_thread_(
97 BrowserThread::UI
, &message_loop_
) {
101 base::MessageLoop message_loop_
;
102 content::TestBrowserThread ui_thread_
;
105 TEST_F(PrefProviderTest
, Observer
) {
106 TestingProfile profile
;
107 PrefProvider
pref_content_settings_provider(profile
.GetPrefs(), false);
109 ContentSettingsPattern pattern
=
110 ContentSettingsPattern::FromString("[*.]example.com");
111 content_settings::MockObserver mock_observer
;
112 EXPECT_CALL(mock_observer
,
113 OnContentSettingChanged(pattern
,
114 ContentSettingsPattern::Wildcard(),
115 CONTENT_SETTINGS_TYPE_IMAGES
,
118 pref_content_settings_provider
.AddObserver(&mock_observer
);
120 pref_content_settings_provider
.SetWebsiteSetting(
122 ContentSettingsPattern::Wildcard(),
123 CONTENT_SETTINGS_TYPE_IMAGES
,
125 base::Value::CreateIntegerValue(CONTENT_SETTING_ALLOW
));
127 pref_content_settings_provider
.ShutdownOnUIThread();
130 // Test for regression in which the PrefProvider modified the user pref store
131 // of the OTR unintentionally: http://crbug.com/74466.
132 TEST_F(PrefProviderTest
, Incognito
) {
133 PersistentPrefStore
* user_prefs
= new TestingPrefStore();
134 OverlayUserPrefStore
* otr_user_prefs
=
135 new OverlayUserPrefStore(user_prefs
);
137 PrefServiceMockFactory factory
;
138 factory
.set_user_prefs(make_scoped_refptr(user_prefs
));
139 scoped_refptr
<user_prefs::PrefRegistrySyncable
> registry(
140 new user_prefs::PrefRegistrySyncable
);
141 PrefServiceSyncable
* regular_prefs
=
142 factory
.CreateSyncable(registry
.get()).release();
144 chrome::RegisterUserProfilePrefs(registry
.get());
146 PrefServiceMockFactory otr_factory
;
147 otr_factory
.set_user_prefs(make_scoped_refptr(otr_user_prefs
));
148 scoped_refptr
<user_prefs::PrefRegistrySyncable
> otr_registry(
149 new user_prefs::PrefRegistrySyncable
);
150 PrefServiceSyncable
* otr_prefs
=
151 otr_factory
.CreateSyncable(otr_registry
.get()).release();
153 chrome::RegisterUserProfilePrefs(otr_registry
.get());
155 TestingProfile::Builder profile_builder
;
156 profile_builder
.SetPrefService(make_scoped_ptr(regular_prefs
));
157 scoped_ptr
<TestingProfile
> profile
= profile_builder
.Build();
159 TestingProfile::Builder otr_profile_builder
;
160 otr_profile_builder
.SetIncognito();
161 otr_profile_builder
.SetPrefService(make_scoped_ptr(otr_prefs
));
162 scoped_ptr
<TestingProfile
> otr_profile(otr_profile_builder
.Build());
163 profile
->SetOffTheRecordProfile(otr_profile
.PassAs
<Profile
>());
165 PrefProvider
pref_content_settings_provider(regular_prefs
, false);
166 PrefProvider
pref_content_settings_provider_incognito(otr_prefs
, true);
167 ContentSettingsPattern pattern
=
168 ContentSettingsPattern::FromString("[*.]example.com");
169 pref_content_settings_provider
.SetWebsiteSetting(
172 CONTENT_SETTINGS_TYPE_IMAGES
,
174 base::Value::CreateIntegerValue(CONTENT_SETTING_ALLOW
));
176 GURL
host("http://example.com/");
177 // The value should of course be visible in the regular PrefProvider.
178 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
179 GetContentSetting(&pref_content_settings_provider
,
182 CONTENT_SETTINGS_TYPE_IMAGES
,
185 // And also in the OTR version.
186 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
187 GetContentSetting(&pref_content_settings_provider_incognito
,
190 CONTENT_SETTINGS_TYPE_IMAGES
,
193 // But the value should not be overridden in the OTR user prefs accidentally.
194 EXPECT_FALSE(otr_user_prefs
->IsSetInOverlay(
195 prefs::kContentSettingsPatternPairs
));
197 pref_content_settings_provider
.ShutdownOnUIThread();
198 pref_content_settings_provider_incognito
.ShutdownOnUIThread();
201 TEST_F(PrefProviderTest
, GetContentSettingsValue
) {
202 TestingProfile testing_profile
;
203 PrefProvider
provider(testing_profile
.GetPrefs(), false);
205 GURL
primary_url("http://example.com/");
206 ContentSettingsPattern primary_pattern
=
207 ContentSettingsPattern::FromString("[*.]example.com");
209 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
210 GetContentSetting(&provider
,
213 CONTENT_SETTINGS_TYPE_IMAGES
,
218 GetContentSettingValue(&provider
,
221 CONTENT_SETTINGS_TYPE_IMAGES
,
225 provider
.SetWebsiteSetting(primary_pattern
,
227 CONTENT_SETTINGS_TYPE_IMAGES
,
229 base::Value::CreateIntegerValue(
230 CONTENT_SETTING_BLOCK
));
231 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
232 GetContentSetting(&provider
,
235 CONTENT_SETTINGS_TYPE_IMAGES
,
238 scoped_ptr
<base::Value
> value_ptr(
239 GetContentSettingValue(&provider
,
242 CONTENT_SETTINGS_TYPE_IMAGES
,
246 value_ptr
->GetAsInteger(&int_value
);
247 EXPECT_EQ(CONTENT_SETTING_BLOCK
, IntToContentSetting(int_value
));
249 provider
.SetWebsiteSetting(primary_pattern
,
251 CONTENT_SETTINGS_TYPE_IMAGES
,
255 GetContentSettingValue(&provider
,
258 CONTENT_SETTINGS_TYPE_IMAGES
,
261 provider
.ShutdownOnUIThread();
264 TEST_F(PrefProviderTest
, Patterns
) {
265 TestingProfile testing_profile
;
266 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
269 GURL
host1("http://example.com/");
270 GURL
host2("http://www.example.com/");
271 GURL
host3("http://example.org/");
272 GURL
host4("file:///tmp/test.html");
273 ContentSettingsPattern pattern1
=
274 ContentSettingsPattern::FromString("[*.]example.com");
275 ContentSettingsPattern pattern2
=
276 ContentSettingsPattern::FromString("example.org");
277 ContentSettingsPattern pattern3
=
278 ContentSettingsPattern::FromString("file:///tmp/test.html");
280 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
281 GetContentSetting(&pref_content_settings_provider
,
284 CONTENT_SETTINGS_TYPE_IMAGES
,
287 pref_content_settings_provider
.SetWebsiteSetting(
290 CONTENT_SETTINGS_TYPE_IMAGES
,
292 base::Value::CreateIntegerValue(CONTENT_SETTING_BLOCK
));
293 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
294 GetContentSetting(&pref_content_settings_provider
,
297 CONTENT_SETTINGS_TYPE_IMAGES
,
300 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
301 GetContentSetting(&pref_content_settings_provider
,
304 CONTENT_SETTINGS_TYPE_IMAGES
,
308 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
309 GetContentSetting(&pref_content_settings_provider
,
312 CONTENT_SETTINGS_TYPE_IMAGES
,
315 pref_content_settings_provider
.SetWebsiteSetting(
318 CONTENT_SETTINGS_TYPE_IMAGES
,
320 base::Value::CreateIntegerValue(CONTENT_SETTING_BLOCK
));
321 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
322 GetContentSetting(&pref_content_settings_provider
,
325 CONTENT_SETTINGS_TYPE_IMAGES
,
329 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
330 GetContentSetting(&pref_content_settings_provider
,
333 CONTENT_SETTINGS_TYPE_IMAGES
,
336 pref_content_settings_provider
.SetWebsiteSetting(
339 CONTENT_SETTINGS_TYPE_IMAGES
,
341 base::Value::CreateIntegerValue(CONTENT_SETTING_BLOCK
));
342 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
343 GetContentSetting(&pref_content_settings_provider
,
346 CONTENT_SETTINGS_TYPE_IMAGES
,
350 pref_content_settings_provider
.ShutdownOnUIThread();
353 TEST_F(PrefProviderTest
, ResourceIdentifier
) {
354 TestingProfile testing_profile
;
355 PrefProvider
pref_content_settings_provider(testing_profile
.GetPrefs(),
358 GURL
host("http://example.com/");
359 ContentSettingsPattern pattern
=
360 ContentSettingsPattern::FromString("[*.]example.com");
361 std::string
resource1("someplugin");
362 std::string
resource2("otherplugin");
364 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
366 &pref_content_settings_provider
,
367 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
369 pref_content_settings_provider
.SetWebsiteSetting(
372 CONTENT_SETTINGS_TYPE_PLUGINS
,
374 base::Value::CreateIntegerValue(CONTENT_SETTING_BLOCK
));
375 EXPECT_EQ(CONTENT_SETTING_BLOCK
,
377 &pref_content_settings_provider
,
378 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
380 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
382 &pref_content_settings_provider
,
383 host
, host
, CONTENT_SETTINGS_TYPE_PLUGINS
,
386 pref_content_settings_provider
.ShutdownOnUIThread();
389 TEST_F(PrefProviderTest
, AutoSubmitCertificateContentSetting
) {
390 TestingProfile profile
;
391 TestingPrefServiceSyncable
* prefs
= profile
.GetTestingPrefService();
392 GURL
primary_url("https://www.example.com");
393 GURL
secondary_url("https://www.sample.com");
395 PrefProvider
provider(prefs
, false);
397 EXPECT_EQ(CONTENT_SETTING_DEFAULT
,
402 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
406 provider
.SetWebsiteSetting(
407 ContentSettingsPattern::FromURL(primary_url
),
408 ContentSettingsPattern::Wildcard(),
409 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
411 base::Value::CreateIntegerValue(CONTENT_SETTING_ALLOW
));
412 EXPECT_EQ(CONTENT_SETTING_ALLOW
,
417 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE
,
420 provider
.ShutdownOnUIThread();
423 // http://crosbug.com/17760
424 TEST_F(PrefProviderTest
, Deadlock
) {
425 TestingPrefServiceSyncable prefs
;
426 PrefProvider::RegisterProfilePrefs(prefs
.registry());
428 // Chain of events: a preference changes, |PrefProvider| notices it, and reads
429 // and writes the preference. When the preference is written, a notification
430 // is sent, and this used to happen when |PrefProvider| was still holding its
433 PrefProvider
provider(&prefs
, false);
434 DeadlockCheckerObserver
observer(&prefs
, &provider
);
436 DictionaryPrefUpdate
update(&prefs
,
437 prefs::kContentSettingsPatternPairs
);
438 base::DictionaryValue
* mutable_settings
= update
.Get();
439 mutable_settings
->SetWithoutPathExpansion("www.example.com,*",
440 new base::DictionaryValue());
442 EXPECT_TRUE(observer
.notification_received());
444 provider
.ShutdownOnUIThread();
447 } // namespace content_settings