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/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"
     33 #include "url/gurl.h"
     34 
     35 using ::testing::_;
     36 using content::BrowserThread;
     37 
     38 namespace content_settings {
     39 
     40 class DeadlockCheckerThread : public base::PlatformThread::Delegate {
     41  public:
     42   explicit DeadlockCheckerThread(PrefProvider* provider)
     43       : provider_(provider) {}
     44 
     45   virtual void ThreadMain() OVERRIDE {
     46     bool got_lock = provider_->lock_.Try();
     47     EXPECT_TRUE(got_lock);
     48     if (got_lock)
     49       provider_->lock_.Release();
     50   }
     51  private:
     52   PrefProvider* provider_;
     53   DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerThread);
     54 };
     55 
     56 // A helper for observing an preference changes and testing whether
     57 // |PrefProvider| holds a lock when the preferences change.
     58 class DeadlockCheckerObserver {
     59  public:
     60   // |DeadlockCheckerObserver| doesn't take the ownership of |prefs| or
     61   // ||provider|.
     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,
     68         base::Bind(
     69             &DeadlockCheckerObserver::OnContentSettingsPatternPairsChanged,
     70             base::Unretained(this)));
     71   }
     72   virtual ~DeadlockCheckerObserver() {}
     73 
     74   bool notification_received() const {
     75     return notification_received_;
     76   }
     77 
     78  private:
     79   void OnContentSettingsPatternPairsChanged() {
     80     // Check whether |provider_| holds its lock. For this, we need a
     81     // separate thread.
     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;
     87   }
     88 
     89   PrefProvider* provider_;
     90   PrefChangeRegistrar pref_change_registrar_;
     91   bool notification_received_;
     92   DISALLOW_COPY_AND_ASSIGN(DeadlockCheckerObserver);
     93 };
     94 
     95 class PrefProviderTest : public testing::Test {
     96  public:
     97   PrefProviderTest() : ui_thread_(
     98       BrowserThread::UI, &message_loop_) {
     99   }
    100 
    101  protected:
    102   base::MessageLoop message_loop_;
    103   content::TestBrowserThread ui_thread_;
    104 };
    105 
    106 TEST_F(PrefProviderTest, Observer) {
    107   TestingProfile profile;
    108   PrefProvider pref_content_settings_provider(profile.GetPrefs(), false);
    109 
    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,
    117                                       ""));
    118 
    119   pref_content_settings_provider.AddObserver(&mock_observer);
    120 
    121   pref_content_settings_provider.SetWebsiteSetting(
    122       pattern,
    123       ContentSettingsPattern::Wildcard(),
    124       CONTENT_SETTINGS_TYPE_IMAGES,
    125       std::string(),
    126       new base::FundamentalValue(CONTENT_SETTING_ALLOW));
    127 
    128   pref_content_settings_provider.ShutdownOnUIThread();
    129 }
    130 
    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);
    137 
    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();
    144 
    145   chrome::RegisterUserProfilePrefs(registry.get());
    146 
    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();
    153 
    154   chrome::RegisterUserProfilePrefs(otr_registry.get());
    155 
    156   TestingProfile::Builder profile_builder;
    157   profile_builder.SetPrefService(make_scoped_ptr(regular_prefs));
    158   scoped_ptr<TestingProfile> profile = profile_builder.Build();
    159 
    160   TestingProfile::Builder otr_profile_builder;
    161   otr_profile_builder.SetPrefService(make_scoped_ptr(otr_prefs));
    162   otr_profile_builder.BuildIncognito(profile.get());
    163 
    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(
    169       pattern,
    170       pattern,
    171       CONTENT_SETTINGS_TYPE_IMAGES,
    172       std::string(),
    173       new base::FundamentalValue(CONTENT_SETTING_ALLOW));
    174 
    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,
    179                               host,
    180                               host,
    181                               CONTENT_SETTINGS_TYPE_IMAGES,
    182                               std::string(),
    183                               false));
    184   // And also in the OTR version.
    185   EXPECT_EQ(CONTENT_SETTING_ALLOW,
    186             GetContentSetting(&pref_content_settings_provider_incognito,
    187                               host,
    188                               host,
    189                               CONTENT_SETTINGS_TYPE_IMAGES,
    190                               std::string(),
    191                               false));
    192   // But the value should not be overridden in the OTR user prefs accidentally.
    193   EXPECT_FALSE(otr_user_prefs->IsSetInOverlay(
    194       prefs::kContentSettingsPatternPairs));
    195 
    196   pref_content_settings_provider.ShutdownOnUIThread();
    197   pref_content_settings_provider_incognito.ShutdownOnUIThread();
    198 }
    199 
    200 TEST_F(PrefProviderTest, GetContentSettingsValue) {
    201   TestingProfile testing_profile;
    202   PrefProvider provider(testing_profile.GetPrefs(), false);
    203 
    204   GURL primary_url("http://example.com/");
    205   ContentSettingsPattern primary_pattern =
    206       ContentSettingsPattern::FromString("[*.]example.com");
    207 
    208   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    209             GetContentSetting(&provider,
    210                               primary_url,
    211                               primary_url,
    212                               CONTENT_SETTINGS_TYPE_IMAGES,
    213                               std::string(),
    214                               false));
    215 
    216   EXPECT_EQ(NULL,
    217             GetContentSettingValue(&provider,
    218                                    primary_url,
    219                                    primary_url,
    220                                    CONTENT_SETTINGS_TYPE_IMAGES,
    221                                    std::string(),
    222                                    false));
    223 
    224   provider.SetWebsiteSetting(primary_pattern,
    225                              primary_pattern,
    226                              CONTENT_SETTINGS_TYPE_IMAGES,
    227                              std::string(),
    228                              new base::FundamentalValue(CONTENT_SETTING_BLOCK));
    229   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    230             GetContentSetting(&provider,
    231                               primary_url,
    232                               primary_url,
    233                               CONTENT_SETTINGS_TYPE_IMAGES,
    234                               std::string(),
    235                               false));
    236   scoped_ptr<base::Value> value_ptr(
    237       GetContentSettingValue(&provider,
    238                              primary_url,
    239                              primary_url,
    240                              CONTENT_SETTINGS_TYPE_IMAGES,
    241                              std::string(),
    242                              false));
    243   int int_value = -1;
    244   value_ptr->GetAsInteger(&int_value);
    245   EXPECT_EQ(CONTENT_SETTING_BLOCK, IntToContentSetting(int_value));
    246 
    247   provider.SetWebsiteSetting(primary_pattern,
    248                              primary_pattern,
    249                              CONTENT_SETTINGS_TYPE_IMAGES,
    250                              std::string(),
    251                              NULL);
    252   EXPECT_EQ(NULL,
    253             GetContentSettingValue(&provider,
    254                                    primary_url,
    255                                    primary_url,
    256                                    CONTENT_SETTINGS_TYPE_IMAGES,
    257                                    std::string(),
    258                                    false));
    259   provider.ShutdownOnUIThread();
    260 }
    261 
    262 TEST_F(PrefProviderTest, Patterns) {
    263   TestingProfile testing_profile;
    264   PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(),
    265                                               false);
    266 
    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");
    277 
    278   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    279             GetContentSetting(&pref_content_settings_provider,
    280                               host1,
    281                               host1,
    282                               CONTENT_SETTINGS_TYPE_IMAGES,
    283                               std::string(),
    284                               false));
    285   pref_content_settings_provider.SetWebsiteSetting(
    286       pattern1,
    287       pattern1,
    288       CONTENT_SETTINGS_TYPE_IMAGES,
    289       std::string(),
    290       new base::FundamentalValue(CONTENT_SETTING_BLOCK));
    291   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    292             GetContentSetting(&pref_content_settings_provider,
    293                               host1,
    294                               host1,
    295                               CONTENT_SETTINGS_TYPE_IMAGES,
    296                               std::string(),
    297                               false));
    298   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    299             GetContentSetting(&pref_content_settings_provider,
    300                               host2,
    301                               host2,
    302                               CONTENT_SETTINGS_TYPE_IMAGES,
    303                               std::string(),
    304                               false));
    305 
    306   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    307             GetContentSetting(&pref_content_settings_provider,
    308                               host3,
    309                               host3,
    310                               CONTENT_SETTINGS_TYPE_IMAGES,
    311                               std::string(),
    312                               false));
    313   pref_content_settings_provider.SetWebsiteSetting(
    314       pattern2,
    315       pattern2,
    316       CONTENT_SETTINGS_TYPE_IMAGES,
    317       std::string(),
    318       new base::FundamentalValue(CONTENT_SETTING_BLOCK));
    319   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    320             GetContentSetting(&pref_content_settings_provider,
    321                               host3,
    322                               host3,
    323                               CONTENT_SETTINGS_TYPE_IMAGES,
    324                               std::string(),
    325                               false));
    326 
    327   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    328             GetContentSetting(&pref_content_settings_provider,
    329                               host4,
    330                               host4,
    331                               CONTENT_SETTINGS_TYPE_IMAGES,
    332                               std::string(),
    333                               false));
    334   pref_content_settings_provider.SetWebsiteSetting(
    335       pattern3,
    336       pattern3,
    337       CONTENT_SETTINGS_TYPE_IMAGES,
    338       std::string(),
    339       new base::FundamentalValue(CONTENT_SETTING_BLOCK));
    340   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    341             GetContentSetting(&pref_content_settings_provider,
    342                               host4,
    343                               host4,
    344                               CONTENT_SETTINGS_TYPE_IMAGES,
    345                               std::string(),
    346                               false));
    347 
    348   pref_content_settings_provider.ShutdownOnUIThread();
    349 }
    350 
    351 TEST_F(PrefProviderTest, ResourceIdentifier) {
    352   TestingProfile testing_profile;
    353   PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(),
    354                                               false);
    355 
    356   GURL host("http://example.com/");
    357   ContentSettingsPattern pattern =
    358       ContentSettingsPattern::FromString("[*.]example.com");
    359   std::string resource1("someplugin");
    360   std::string resource2("otherplugin");
    361 
    362   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    363             GetContentSetting(
    364                 &pref_content_settings_provider,
    365                 host, host, CONTENT_SETTINGS_TYPE_PLUGINS,
    366                 resource1, false));
    367   pref_content_settings_provider.SetWebsiteSetting(
    368       pattern,
    369       pattern,
    370       CONTENT_SETTINGS_TYPE_PLUGINS,
    371       resource1,
    372       new base::FundamentalValue(CONTENT_SETTING_BLOCK));
    373   EXPECT_EQ(CONTENT_SETTING_BLOCK,
    374             GetContentSetting(
    375                 &pref_content_settings_provider,
    376                 host, host, CONTENT_SETTINGS_TYPE_PLUGINS,
    377                 resource1, false));
    378   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    379             GetContentSetting(
    380                 &pref_content_settings_provider,
    381                 host, host, CONTENT_SETTINGS_TYPE_PLUGINS,
    382                 resource2, false));
    383 
    384   pref_content_settings_provider.ShutdownOnUIThread();
    385 }
    386 
    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");
    392 
    393   PrefProvider provider(prefs, false);
    394 
    395   EXPECT_EQ(CONTENT_SETTING_DEFAULT,
    396             GetContentSetting(
    397                 &provider,
    398                 primary_url,
    399                 primary_url,
    400                 CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
    401                 std::string(),
    402                 false));
    403 
    404   provider.SetWebsiteSetting(ContentSettingsPattern::FromURL(primary_url),
    405                              ContentSettingsPattern::Wildcard(),
    406                              CONTENT_SETTINGS_TYPE_AUTO_SELECT_CERTIFICATE,
    407                              std::string(),
    408                              new base::FundamentalValue(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     base::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 TEST_F(PrefProviderTest, LastUsage) {
    445   TestingProfile testing_profile;
    446   PrefProvider pref_content_settings_provider(testing_profile.GetPrefs(),
    447                                               false);
    448   base::SimpleTestClock* test_clock = new base::SimpleTestClock;
    449   test_clock->SetNow(base::Time::Now());
    450 
    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");
    456 
    457   base::Time no_usage = pref_content_settings_provider.GetLastUsage(
    458       pattern, pattern, CONTENT_SETTINGS_TYPE_GEOLOCATION);
    459   EXPECT_EQ(no_usage.ToDoubleT(), 0);
    460 
    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);
    465 
    466   test_clock->Advance(base::TimeDelta::FromSeconds(10));
    467 
    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);
    472 
    473   base::TimeDelta delta = second - first;
    474   EXPECT_EQ(delta.InSeconds(), 10);
    475 
    476   pref_content_settings_provider.ShutdownOnUIThread();
    477 }
    478 
    479 }  // namespace content_settings
    480