Home | History | Annotate | Download | only in notifications
      1 // Copyright (c) 2011 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/notifications/desktop_notification_service.h"
      6 
      7 #include "base/memory/ref_counted.h"
      8 #include "base/message_loop.h"
      9 #include "base/synchronization/waitable_event.h"
     10 #include "chrome/browser/notifications/desktop_notification_service_factory.h"
     11 #include "chrome/browser/notifications/notifications_prefs_cache.h"
     12 #include "chrome/browser/prefs/pref_service.h"
     13 #include "chrome/browser/prefs/scoped_user_pref_update.h"
     14 #include "chrome/common/pref_names.h"
     15 #include "chrome/test/testing_profile.h"
     16 #include "content/browser/browser_thread.h"
     17 #include "content/browser/renderer_host/test_render_view_host.h"
     18 #include "grit/generated_resources.h"
     19 #include "testing/gtest/include/gtest/gtest.h"
     20 #include "third_party/WebKit/Source/WebKit/chromium/public/WebNotificationPresenter.h"
     21 
     22 namespace {
     23 
     24 // NotificationsPrefsCache wants to be called on the IO thread. This class
     25 // routes calls to the cache on the IO thread.
     26 class ThreadProxy : public base::RefCountedThreadSafe<ThreadProxy> {
     27  public:
     28   ThreadProxy()
     29       : io_event_(false, false),
     30         ui_event_(false, false),
     31         permission_(0) {
     32     // The current message loop was already initalized by the test superclass.
     33     ui_thread_.reset(
     34         new BrowserThread(BrowserThread::UI, MessageLoop::current()));
     35 
     36     // Create IO thread, start its message loop.
     37     io_thread_.reset(new BrowserThread(BrowserThread::IO));
     38     io_thread_->Start();
     39 
     40     // Calling PauseIOThread() here isn't safe, because the runnable method
     41     // could complete before the constructor is done, deleting |this|.
     42   }
     43 
     44   int CacheHasPermission(NotificationsPrefsCache* cache, const GURL& url) {
     45     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     46     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
     47         NewRunnableMethod(this, &ThreadProxy::CacheHasPermissionIO,
     48                           make_scoped_refptr(cache), url));
     49     io_event_.Signal();
     50     ui_event_.Wait();  // Wait for IO thread to be done.
     51     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
     52         NewRunnableMethod(this, &ThreadProxy::PauseIOThreadIO));
     53 
     54     return permission_;
     55   }
     56 
     57   void PauseIOThread() {
     58     BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
     59         NewRunnableMethod(this, &ThreadProxy::PauseIOThreadIO));
     60   }
     61 
     62   void DrainIOThread() {
     63     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
     64     io_event_.Signal();
     65     io_thread_->Stop();
     66   }
     67 
     68  private:
     69   friend class base::RefCountedThreadSafe<ThreadProxy>;
     70   ~ThreadProxy() {
     71      DrainIOThread();
     72   }
     73 
     74   void PauseIOThreadIO() {
     75     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     76     io_event_.Wait();
     77   }
     78 
     79   void CacheHasPermissionIO(NotificationsPrefsCache* cache, const GURL& url) {
     80     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
     81     permission_ = cache->HasPermission(url);
     82     ui_event_.Signal();
     83   }
     84 
     85   base::WaitableEvent io_event_;
     86   base::WaitableEvent ui_event_;
     87   scoped_ptr<BrowserThread> ui_thread_;
     88   scoped_ptr<BrowserThread> io_thread_;
     89 
     90   int permission_;
     91 };
     92 
     93 
     94 class DesktopNotificationServiceTest : public RenderViewHostTestHarness {
     95  public:
     96   DesktopNotificationServiceTest() {
     97   }
     98 
     99   virtual void SetUp() {
    100     RenderViewHostTestHarness::SetUp();
    101     proxy_ = new ThreadProxy;
    102     proxy_->PauseIOThread();
    103 
    104     // Creates the service, calls InitPrefs() on it which loads data from the
    105     // profile into the cache and then puts the cache in io thread mode.
    106     service_ = DesktopNotificationServiceFactory::GetForProfile(profile());
    107     cache_ = service_->prefs_cache();
    108   }
    109 
    110   virtual void TearDown() {
    111     // The io thread's waiting on the io_event_ might hold a ref to |proxy_|,
    112     // preventing its destruction. Clear that ref.
    113     proxy_->DrainIOThread();
    114     RenderViewHostTestHarness::TearDown();
    115   }
    116 
    117   DesktopNotificationService* service_;
    118   NotificationsPrefsCache* cache_;
    119   scoped_refptr<ThreadProxy> proxy_;
    120 };
    121 
    122 TEST_F(DesktopNotificationServiceTest, DefaultContentSettingSentToCache) {
    123   // The default pref registered in DesktopNotificationService is "ask",
    124   // and that's what sent to the cache.
    125   EXPECT_EQ(CONTENT_SETTING_ASK, cache_->CachedDefaultContentSetting());
    126 
    127   // Change the default content setting. This will post a task on the IO thread
    128   // to update the cache.
    129   service_->SetDefaultContentSetting(CONTENT_SETTING_BLOCK);
    130 
    131   // The updated pref shouldn't be sent to the cache immediately.
    132   EXPECT_EQ(CONTENT_SETTING_ASK, cache_->CachedDefaultContentSetting());
    133 
    134   // Run IO thread tasks.
    135   proxy_->DrainIOThread();
    136 
    137   // Now that IO thread events have been processed, it should be there.
    138   EXPECT_EQ(CONTENT_SETTING_BLOCK, cache_->CachedDefaultContentSetting());
    139 }
    140 
    141 TEST_F(DesktopNotificationServiceTest, SettingsForSchemes) {
    142   GURL url("file:///html/test.html");
    143 
    144   EXPECT_EQ(CONTENT_SETTING_ASK, cache_->CachedDefaultContentSetting());
    145   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    146             proxy_->CacheHasPermission(cache_, url));
    147 
    148   service_->GrantPermission(url);
    149   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    150             proxy_->CacheHasPermission(cache_, url));
    151 
    152   service_->DenyPermission(url);
    153   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
    154             proxy_->CacheHasPermission(cache_, url));
    155 
    156   GURL https_url("https://testurl");
    157   GURL http_url("http://testurl");
    158   EXPECT_EQ(CONTENT_SETTING_ASK, cache_->CachedDefaultContentSetting());
    159   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    160             proxy_->CacheHasPermission(cache_, http_url));
    161   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    162             proxy_->CacheHasPermission(cache_, https_url));
    163 
    164   service_->GrantPermission(https_url);
    165   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    166             proxy_->CacheHasPermission(cache_, https_url));
    167   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    168             proxy_->CacheHasPermission(cache_, http_url));
    169 
    170   service_->DenyPermission(http_url);
    171   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
    172             proxy_->CacheHasPermission(cache_, http_url));
    173   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    174             proxy_->CacheHasPermission(cache_, https_url));
    175 }
    176 
    177 TEST_F(DesktopNotificationServiceTest, GrantPermissionSentToCache) {
    178   GURL url("http://allowed.com");
    179   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    180             proxy_->CacheHasPermission(cache_, url));
    181 
    182   service_->GrantPermission(url);
    183 
    184   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    185             proxy_->CacheHasPermission(cache_, url));
    186 }
    187 
    188 TEST_F(DesktopNotificationServiceTest, DenyPermissionSentToCache) {
    189   GURL url("http://denied.com");
    190   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    191             proxy_->CacheHasPermission(cache_, url));
    192 
    193   service_->DenyPermission(url);
    194 
    195   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
    196             proxy_->CacheHasPermission(cache_, url));
    197 }
    198 
    199 TEST_F(DesktopNotificationServiceTest, PrefChangesSentToCache) {
    200   PrefService* prefs = profile()->GetPrefs();
    201 
    202   {
    203     ListPrefUpdate update_allowed_origins(
    204         prefs, prefs::kDesktopNotificationAllowedOrigins);
    205     ListValue* allowed_origins = update_allowed_origins.Get();
    206     allowed_origins->Append(new StringValue(GURL("http://allowed.com").spec()));
    207   }
    208 
    209   {
    210     ListPrefUpdate update_denied_origins(
    211         prefs, prefs::kDesktopNotificationDeniedOrigins);
    212     ListValue* denied_origins = update_denied_origins.Get();
    213     denied_origins->Append(new StringValue(GURL("http://denied.com").spec()));
    214   }
    215 
    216   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    217             proxy_->CacheHasPermission(cache_, GURL("http://allowed.com")));
    218   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
    219             proxy_->CacheHasPermission(cache_, GURL("http://denied.com")));
    220 }
    221 
    222 TEST_F(DesktopNotificationServiceTest, GetAllowedOrigins) {
    223   service_->GrantPermission(GURL("http://allowed2.com"));
    224   service_->GrantPermission(GURL("http://allowed.com"));
    225 
    226   std::vector<GURL> allowed_origins(service_->GetAllowedOrigins());
    227   ASSERT_EQ(2u, allowed_origins.size());
    228   EXPECT_EQ(GURL("http://allowed2.com"), allowed_origins[0]);
    229   EXPECT_EQ(GURL("http://allowed.com"), allowed_origins[1]);
    230 }
    231 
    232 TEST_F(DesktopNotificationServiceTest, GetBlockedOrigins) {
    233   service_->DenyPermission(GURL("http://denied2.com"));
    234   service_->DenyPermission(GURL("http://denied.com"));
    235 
    236   std::vector<GURL> denied_origins(service_->GetBlockedOrigins());
    237   ASSERT_EQ(2u, denied_origins.size());
    238   EXPECT_EQ(GURL("http://denied2.com"), denied_origins[0]);
    239   EXPECT_EQ(GURL("http://denied.com"), denied_origins[1]);
    240 }
    241 
    242 TEST_F(DesktopNotificationServiceTest, ResetAllSentToCache) {
    243   GURL allowed_url("http://allowed.com");
    244   service_->GrantPermission(allowed_url);
    245   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    246             proxy_->CacheHasPermission(cache_, allowed_url));
    247   GURL denied_url("http://denied.com");
    248   service_->DenyPermission(denied_url);
    249   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
    250             proxy_->CacheHasPermission(cache_, denied_url));
    251 
    252   service_->ResetAllOrigins();
    253 
    254   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    255             proxy_->CacheHasPermission(cache_, allowed_url));
    256   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    257             proxy_->CacheHasPermission(cache_, denied_url));
    258 }
    259 
    260 TEST_F(DesktopNotificationServiceTest, ResetAllowedSentToCache) {
    261   GURL allowed_url("http://allowed.com");
    262   service_->GrantPermission(allowed_url);
    263   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionAllowed,
    264             proxy_->CacheHasPermission(cache_, allowed_url));
    265 
    266   service_->ResetAllowedOrigin(allowed_url);
    267 
    268   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    269             proxy_->CacheHasPermission(cache_, allowed_url));
    270 }
    271 
    272 TEST_F(DesktopNotificationServiceTest, ResetBlockedSentToCache) {
    273   GURL denied_url("http://denied.com");
    274   service_->DenyPermission(denied_url);
    275   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionDenied,
    276             proxy_->CacheHasPermission(cache_, denied_url));
    277 
    278   service_->ResetBlockedOrigin(denied_url);
    279 
    280   EXPECT_EQ(WebKit::WebNotificationPresenter::PermissionNotAllowed,
    281             proxy_->CacheHasPermission(cache_, denied_url));
    282 }
    283 
    284 }  // namespace
    285