Home | History | Annotate | Download | only in content_settings
      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.
      4 
      5 #include "chrome/browser/content_settings/content_settings_pref_provider.h"
      6 
      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/testing_pref_store.h"
     16 #include "base/threading/platform_thread.h"
     17 #include "base/values.h"
     18 #include "chrome/browser/content_settings/content_settings_mock_observer.h"
     19 #include "chrome/browser/content_settings/content_settings_utils.h"
     20 #include "chrome/browser/prefs/browser_prefs.h"
     21 #include "chrome/browser/prefs/pref_service_mock_builder.h"
     22 #include "chrome/browser/prefs/pref_service_syncable.h"
     23 #include "chrome/browser/prefs/scoped_user_pref_update.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"
     32 #include "url/gurl.h"
     33 
     34 using ::testing::_;
     35 using content::BrowserThread;
     36 
     37 namespace content_settings {
     38 
     39 class DeadlockCheckerThread : public base::PlatformThread::Delegate {
     40  public:
     41   explicit DeadlockCheckerThread(PrefProvider* provider)
     42       : provider_(provider) {}
     43 
     44   virtual void ThreadMain() OVERRIDE {
     45     bool got_lock = provider_->lock_.Try();
     46     EXPECT_TRUE(got_lock);
     47     if (got_lock)
     48       provider_->lock_.Release();
     49   }
     50  private:
     51   PrefProvider* provider_;
     52   DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerThread);
     53 };
     54 
     55 // A helper for observing an preference changes and testing whether
     56 // |PrefProvider| holds a lock when the preferences change.
     57 class DeadlockCheckerObserver {
     58  public:
     59   // |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
     60   // ||provider|.
     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,
     67         base::Bind(
     68             &DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged,
     69             base::Unretained(this)));
     70   }
     71   virtual ~DeadlockCheckerObserver() {}
     72 
     73   bool notification_received() const {
     74     return notification_received_;
     75   }
     76 
     77  private:
     78   void OnContentSettingsPatternPairsChanged() {
     79     // Check whether |provider_| holds its lock. For this, we need a
     80     // separate thread.
     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;
     86   }
     87 
     88   PrefProvider* provider_;
     89   PrefChangeRegistrar pref_change_registrar_;
     90   bool notification_received_;
     91   DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerObserver);
     92 };
     93 
     94 class PrefProviderTest : public testing::Test {
     95  public:
     96   PrefProviderTest() : ui_thread_(
     97       BrowserThread::UI, &message_loop_) {
     98   }
     99 
    100  protected:
    101   base::MessageLoop message_loop_;
    102   content::TestBrowserThread ui_thread_;
    103 };
    104 
    105 TEST_F(PrefProviderTest, Observer) {
    106   TestingProfile profile;
    107   PrefProvider pref_content_settings_provider(profile.GetPrefs(), false);
    108 
    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,
    116                                       ""));
    117 
    118   pref_content_settings_provider.AddObserver(&mock_observer);
    119 
    120   pref_content_settings_provider.SetWebsiteSetting(
    121       pattern,
    122       ContentSettingsPattern::Wildcard(),
    123       CONTENT_SETTINGS_TYPE_IMAGES,
    124       std::string(),
    125       Value::CreateIntegerValue(CONTENT_SETTING_ALLOW));
    126 
    127   pref_content_settings_provider.ShutdownOnUIThread();
    128 }
    129 
    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);
    136 
    137   PrefServiceMockBuilder builder;
    138   builder.WithUserPrefs(user_prefs);
    139   scoped_refptr<user_prefs::PrefRegistrySyncable> registry(
    140       new user_prefs::PrefRegistrySyncable);
    141   PrefServiceSyncable* regular_prefs = builder.CreateSyncable(registry.get());
    142 
    143   chrome::RegisterUserProfilePrefs(registry.get());
    144 
    145   builder.WithUserPrefs(otr_user_prefs);
    146   scoped_refptr<user_prefs::PrefRegistrySyncable> otr_registry(
    147       new user_prefs::PrefRegistrySyncable);
    148   PrefServiceSyncable* otr_prefs = builder.CreateSyncable(otr_registry.get());
    149 
    150   chrome::RegisterUserProfilePrefs(otr_registry.get());
    151 
    152   TestingProfile::Builder profile_builder;
    153   profile_builder.SetPrefService(make_scoped_ptr(regular_prefs));
    154   scoped_ptr<TestingProfile> profile = profile_builder.Build();
    155 
    156   TestingProfile::Builder otr_profile_builder;
    157   otr_profile_builder.SetPrefService(make_scoped_ptr(otr_prefs));
    158   TestingProfile* otr_profile = otr_profile_builder.Build().release();
    159 
    160   otr_profile->set_incognito(true);
    161   profile->SetOffTheRecordProfile(otr_profile);
    162 
    163   PrefProvider pref_content_settings_provider(regular_prefs, false);
    164   PrefProvider pref_content_settings_provider_incognito(otr_prefs, true);
    165   ContentSettingsPattern pattern =
    166       ContentSettingsPattern::FromString("[*.]example.com");
    167   pref_content_settings_provider.SetWebsiteSetting(
    168       pattern,
    169       pattern,
    170       CONTENT_SETTINGS_TYPE_IMAGES,
    171       std::string(),
    172       Value::CreateIntegerValue(CONTENT_SETTING_ALLOW));
    173 
    174   GURL host("http://example.com/");
    175   // The value should of course be visible in the regular PrefProvider.
    176   EXPECT_EQ(CONTENT_SETTING_ALLOW,
    177             GetContentSetting(&pref_content_settings_provider,
    178                               host,
    179                               host,
    180                               CONTENT_SETTINGS_TYPE_IMAGES,
    181                               std::string(),
    182                               false));
    183   // And also in the OTR version.
    184   EXPECT_EQ(CONTENT_SETTING_ALLOW,
    185             GetContentSetting(&pref_content_settings_provider_incognito,
    186                               host,
    187                               host,
    188                               CONTENT_SETTINGS_TYPE_IMAGES,
    189                               std::string(),
    190                               false));
    191   // But the value should not be overridden in the OTR user prefs accidentally.
    192   EXPECT_FALSE(otr_user_prefs->IsSetInOverlay(
    193       prefs::kContentSettingsPatternPairs));
    194 
    195   pref_content_settings_provider.ShutdownOnUIThread();
    196   pref_content_settings_provider_incognito.ShutdownOnUIThread();
    197 }
    198 
    199 TEST_F(PrefProviderTest, GetContentSettingsValue) {
    200   TestingProfile testing_profile;
    201   PrefProvider provider(testing_profile.GetPrefs(), false);
    202 
    203   GURL primary_url("http://example.com/");
    204   ContentSettingsPattern primary_pattern =
    205       ContentSettingsPattern::FromString("[*.]example.com");
    206 
    207   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    208             GetContentSetting(&provider,
    209                               primary_url,
    210                               primary_url,
    211                               CONTENT_SETTINGS_TYPE_IMAGES,
    212                               std::string(),
    213                               false));
    214 
    215   EXPECT_EQ(NULL,
    216             GetContentSettingValue(&provider,
    217                                    primary_url,
    218                                    primary_url,
    219                                    CONTENT_SETTINGS_TYPE_IMAGES,
    220                                    std::string(),
    221                                    false));
    222 
    223   provider.SetWebsiteSetting(primary_pattern,
    224                              primary_pattern,
    225                              CONTENT_SETTINGS_TYPE_IMAGES,
    226                              std::string(),
    227                              Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
    228   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    229             GetContentSetting(&provider,
    230                               primary_url,
    231                               primary_url,
    232                               CONTENT_SETTINGS_TYPE_IMAGES,
    233                               std::string(),
    234                               false));
    235   scoped_ptr<Value> value_ptr(
    236       GetContentSettingValue(&provider,
    237                              primary_url,
    238                              primary_url,
    239                              CONTENT_SETTINGS_TYPE_IMAGES,
    240                              std::string(),
    241                              false));
    242   int int_value = -1;
    243   value_ptr->GetAsInteger(&int_value);
    244   EXPECT_EQ(CONTENT_SETTING_BLOCK, IntToContentSetting(int_value));
    245 
    246   provider.SetWebsiteSetting(primary_pattern,
    247                              primary_pattern,
    248                              CONTENT_SETTINGS_TYPE_IMAGES,
    249                              std::string(),
    250                              NULL);
    251   EXPECT_EQ(NULL,
    252             GetContentSettingValue(&provider,
    253                                    primary_url,
    254                                    primary_url,
    255                                    CONTENT_SETTINGS_TYPE_IMAGES,
    256                                    std::string(),
    257                                    false));
    258   provider.ShutdownOnUIThread();
    259 }
    260 
    261 TEST_F(PrefProviderTest, Patterns) {
    262   TestingProfile testing_profile;
    263   PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(),
    264                                               false);
    265 
    266   GURL host1("http://example.com/");
    267   GURL host2("http://www.example.com/");
    268   GURL host3("http://example.org/");
    269   GURL host4("file:///tmp/test.html");
    270   ContentSettingsPattern pattern1 =
    271       ContentSettingsPattern::FromString("[*.]example.com");
    272   ContentSettingsPattern pattern2 =
    273       ContentSettingsPattern::FromString("example.org");
    274   ContentSettingsPattern pattern3 =
    275       ContentSettingsPattern::FromString("file:///tmp/test.html");
    276 
    277   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    278             GetContentSetting(&pref_content_settings_provider,
    279                               host1,
    280                               host1,
    281                               CONTENT_SETTINGS_TYPE_IMAGES,
    282                               std::string(),
    283                               false));
    284   pref_content_settings_provider.SetWebsiteSetting(
    285       pattern1,
    286       pattern1,
    287       CONTENT_SETTINGS_TYPE_IMAGES,
    288       std::string(),
    289       Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
    290   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    291             GetContentSetting(&pref_content_settings_provider,
    292                               host1,
    293                               host1,
    294                               CONTENT_SETTINGS_TYPE_IMAGES,
    295                               std::string(),
    296                               false));
    297   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    298             GetContentSetting(&pref_content_settings_provider,
    299                               host2,
    300                               host2,
    301                               CONTENT_SETTINGS_TYPE_IMAGES,
    302                               std::string(),
    303                               false));
    304 
    305   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    306             GetContentSetting(&pref_content_settings_provider,
    307                               host3,
    308                               host3,
    309                               CONTENT_SETTINGS_TYPE_IMAGES,
    310                               std::string(),
    311                               false));
    312   pref_content_settings_provider.SetWebsiteSetting(
    313       pattern2,
    314       pattern2,
    315       CONTENT_SETTINGS_TYPE_IMAGES,
    316       std::string(),
    317       Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
    318   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    319             GetContentSetting(&pref_content_settings_provider,
    320                               host3,
    321                               host3,
    322                               CONTENT_SETTINGS_TYPE_IMAGES,
    323                               std::string(),
    324                               false));
    325 
    326   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    327             GetContentSetting(&pref_content_settings_provider,
    328                               host4,
    329                               host4,
    330                               CONTENT_SETTINGS_TYPE_IMAGES,
    331                               std::string(),
    332                               false));
    333   pref_content_settings_provider.SetWebsiteSetting(
    334       pattern3,
    335       pattern3,
    336       CONTENT_SETTINGS_TYPE_IMAGES,
    337       std::string(),
    338       Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
    339   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    340             GetContentSetting(&pref_content_settings_provider,
    341                               host4,
    342                               host4,
    343                               CONTENT_SETTINGS_TYPE_IMAGES,
    344                               std::string(),
    345                               false));
    346 
    347   pref_content_settings_provider.ShutdownOnUIThread();
    348 }
    349 
    350 TEST_F(PrefProviderTest, ResourceIdentifier) {
    351   TestingProfile testing_profile;
    352   PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(),
    353                                               false);
    354 
    355   GURL host("http://example.com/");
    356   ContentSettingsPattern pattern =
    357       ContentSettingsPattern::FromString("[*.]example.com");
    358   std::string resource1("someplugin");
    359   std::string resource2("otherplugin");
    360 
    361   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    362             GetContentSetting(
    363                 &pref_content_settings_provider,
    364                 host, host, CONTENT_SETTINGS_TYPE_PLUGINS,
    365                 resource1, false));
    366   pref_content_settings_provider.SetWebsiteSetting(
    367       pattern,
    368       pattern,
    369       CONTENT_SETTINGS_TYPE_PLUGINS,
    370       resource1,
    371       Value::CreateIntegerValue(CONTENT_SETTING_BLOCK));
    372   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    373             GetContentSetting(
    374                 &pref_content_settings_provider,
    375                 host, host, CONTENT_SETTINGS_TYPE_PLUGINS,
    376                 resource1, false));
    377   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    378             GetContentSetting(
    379                 &pref_content_settings_provider,
    380                 host, host, CONTENT_SETTINGS_TYPE_PLUGINS,
    381                 resource2, false));
    382 
    383   pref_content_settings_provider.ShutdownOnUIThread();
    384 }
    385 
    386 TEST_F(PrefProviderTest, AutoSubmitCertificateContentSetting) {
    387   TestingProfile profile;
    388   TestingPrefServiceSyncable* prefs = profile.GetTestingPrefService();
    389   GURL primary_url("https://www.example.com");
    390   GURL secondary_url("https://www.sample.com");
    391 
    392   PrefProvider provider(prefs, false);
    393 
    394   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    395             GetContentSetting(
    396                 &provider,
    397                 primary_url,
    398                 primary_url,
    399                 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
    400                 std::string(),
    401                 false));
    402 
    403   provider.SetWebsiteSetting(
    404       ContentSettingsPattern::FromURL(primary_url),
    405       ContentSettingsPattern::Wildcard(),
    406       CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
    407       std::string(),
    408       Value::CreateIntegerValue(CONTENT_SETTING_ALLOW));
    409   EXPECT_EQ(CONTENT_SETTING_ALLOW,
    410             GetContentSetting(
    411                 &provider,
    412                 primary_url,
    413                 secondary_url,
    414                 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
    415                 std::string(),
    416                 false));
    417   provider.ShutdownOnUIThread();
    418 }
    419 
    420 // http://crosbug.com/17760
    421 TEST_F(PrefProviderTest, Deadlock) {
    422   TestingPrefServiceSyncable prefs;
    423   PrefProvider::RegisterProfilePrefs(prefs.registry());
    424 
    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
    428   // lock.
    429 
    430   PrefProvider provider(&prefs, false);
    431   DeadlockCheckerObserver observer(&prefs, &provider);
    432   {
    433     DictionaryPrefUpdate update(&prefs,
    434                                 prefs::kContentSettingsPatternPairs);
    435     DictionaryValue* mutable_settings = update.Get();
    436     mutable_settings->SetWithoutPathExpansion("www.example.com,*",
    437                                               new base::DictionaryValue());
    438   }
    439   EXPECT_TRUE(observer.notification_received());
    440 
    441   provider.ShutdownOnUIThread();
    442 }
    443 
    444 }  // namespace content_settings
    445