Home | History | Annotate | Download | only in notifications
      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 "base/strings/string_number_conversions.h"
      6 #include "base/strings/stringprintf.h"
      7 #include "base/strings/utf_string_conversions.h"
      8 #include "chrome/browser/browser_process.h"
      9 #include "chrome/browser/extensions/api/notifications/notifications_api.h"
     10 #include "chrome/browser/extensions/extension_apitest.h"
     11 #include "chrome/browser/extensions/extension_function_test_utils.h"
     12 #include "chrome/browser/notifications/notification.h"
     13 #include "chrome/browser/notifications/notification_ui_manager.h"
     14 #include "content/public/browser/notification_service.h"
     15 #include "content/public/test/test_utils.h"
     16 #include "extensions/browser/api/test/test_api.h"
     17 #include "extensions/browser/notification_types.h"
     18 #include "extensions/common/features/feature.h"
     19 #include "extensions/common/test_util.h"
     20 #include "extensions/test/result_catcher.h"
     21 #include "ui/message_center/message_center.h"
     22 #include "ui/message_center/notification_list.h"
     23 #include "ui/message_center/notifier_settings.h"
     24 
     25 using extensions::Extension;
     26 using extensions::ResultCatcher;
     27 
     28 namespace utils = extension_function_test_utils;
     29 
     30 namespace {
     31 
     32 // A class that waits for a |chrome.test.sendMessage| call, ignores the message,
     33 // and writes down the user gesture status of the message.
     34 class UserGestureCatcher : public content::NotificationObserver {
     35  public:
     36   UserGestureCatcher() : waiting_(false) {
     37     registrar_.Add(this,
     38                    extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE,
     39                    content::NotificationService::AllSources());
     40   }
     41 
     42   virtual ~UserGestureCatcher() {}
     43 
     44   bool GetNextResult() {
     45     if (results_.empty()) {
     46       waiting_ = true;
     47       content::RunMessageLoop();
     48       waiting_ = false;
     49     }
     50 
     51     if (!results_.empty()) {
     52       bool ret = results_.front();
     53       results_.pop_front();
     54       return ret;
     55     }
     56     NOTREACHED();
     57     return false;
     58   }
     59 
     60  private:
     61   virtual void Observe(int type,
     62                        const content::NotificationSource& source,
     63                        const content::NotificationDetails& details) OVERRIDE {
     64     results_.push_back(
     65         static_cast<content::Source<extensions::TestSendMessageFunction> >(
     66             source)
     67             .ptr()
     68             ->user_gesture());
     69     if (waiting_)
     70       base::MessageLoopForUI::current()->Quit();
     71   }
     72 
     73   content::NotificationRegistrar registrar_;
     74 
     75   // A sequential list of user gesture notifications from the test extension(s).
     76   std::deque<bool> results_;
     77 
     78   // True if we're in a nested message loop waiting for results from
     79   // the extension.
     80   bool waiting_;
     81 };
     82 
     83 class NotificationsApiTest : public ExtensionApiTest {
     84  public:
     85   const extensions::Extension* LoadExtensionAndWait(
     86       const std::string& test_name) {
     87     base::FilePath extdir = test_data_dir_.AppendASCII(test_name);
     88     content::WindowedNotificationObserver page_created(
     89         extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
     90         content::NotificationService::AllSources());
     91     const extensions::Extension* extension = LoadExtension(extdir);
     92     if (extension) {
     93       page_created.Wait();
     94     }
     95     return extension;
     96   }
     97 };
     98 
     99 }  // namespace
    100 
    101 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestBasicUsage) {
    102   ASSERT_TRUE(RunExtensionTest("notifications/api/basic_usage")) << message_;
    103 }
    104 
    105 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestEvents) {
    106   ASSERT_TRUE(RunExtensionTest("notifications/api/events")) << message_;
    107 }
    108 
    109 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestCSP) {
    110   ASSERT_TRUE(RunExtensionTest("notifications/api/csp")) << message_;
    111 }
    112 
    113 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) {
    114   const extensions::Extension* extension =
    115       LoadExtensionAndWait("notifications/api/by_user");
    116   ASSERT_TRUE(extension) << message_;
    117 
    118   {
    119     ResultCatcher catcher;
    120     g_browser_process->message_center()->RemoveNotification(
    121         extension->id() + "-FOO",
    122         false);
    123     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    124   }
    125 
    126   {
    127     ResultCatcher catcher;
    128     g_browser_process->message_center()->RemoveNotification(
    129         extension->id() + "-BAR",
    130         true);
    131     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    132   }
    133 
    134   {
    135     ResultCatcher catcher;
    136     g_browser_process->message_center()->RemoveAllNotifications(false);
    137     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    138   }
    139   {
    140     ResultCatcher catcher;
    141     g_browser_process->message_center()->RemoveAllNotifications(true);
    142     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    143   }
    144 }
    145 
    146 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestPartialUpdate) {
    147   ASSERT_TRUE(RunExtensionTest("notifications/api/partial_update")) << message_;
    148   const extensions::Extension* extension = GetSingleLoadedExtension();
    149   ASSERT_TRUE(extension) << message_;
    150 
    151   const char kNewTitle[] = "Changed!";
    152   const char kNewMessage[] = "Too late! The show ended yesterday";
    153   int kNewPriority = 2;
    154 
    155   const message_center::NotificationList::Notifications& notifications =
    156       g_browser_process->message_center()->GetVisibleNotifications();
    157   ASSERT_EQ(1u, notifications.size());
    158   message_center::Notification* notification = *(notifications.begin());
    159   LOG(INFO) << "Notification ID: " << notification->id();
    160 
    161   EXPECT_EQ(base::ASCIIToUTF16(kNewTitle), notification->title());
    162   EXPECT_EQ(base::ASCIIToUTF16(kNewMessage), notification->message());
    163   EXPECT_EQ(kNewPriority, notification->priority());
    164   EXPECT_EQ(0u, notification->buttons().size());
    165 }
    166 
    167 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestGetPermissionLevel) {
    168   scoped_refptr<Extension> empty_extension(
    169       extensions::test_util::CreateEmptyExtension());
    170 
    171   // Get permission level for the extension whose notifications are enabled.
    172   {
    173     scoped_refptr<extensions::NotificationsGetPermissionLevelFunction>
    174         notification_function(
    175             new extensions::NotificationsGetPermissionLevelFunction());
    176 
    177     notification_function->set_extension(empty_extension.get());
    178     notification_function->set_has_callback(true);
    179 
    180     scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
    181         notification_function.get(),
    182         "[]",
    183         browser(),
    184         utils::NONE));
    185 
    186     EXPECT_EQ(base::Value::TYPE_STRING, result->GetType());
    187     std::string permission_level;
    188     EXPECT_TRUE(result->GetAsString(&permission_level));
    189     EXPECT_EQ("granted", permission_level);
    190   }
    191 
    192   // Get permission level for the extension whose notifications are disabled.
    193   {
    194     scoped_refptr<extensions::NotificationsGetPermissionLevelFunction>
    195         notification_function(
    196             new extensions::NotificationsGetPermissionLevelFunction());
    197 
    198     notification_function->set_extension(empty_extension.get());
    199     notification_function->set_has_callback(true);
    200 
    201     message_center::NotifierId notifier_id(
    202         message_center::NotifierId::APPLICATION,
    203         empty_extension->id());
    204     message_center::Notifier notifier(notifier_id, base::string16(), true);
    205     g_browser_process->message_center()->GetNotifierSettingsProvider()->
    206         SetNotifierEnabled(notifier, false);
    207 
    208     scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
    209         notification_function.get(),
    210         "[]",
    211         browser(),
    212         utils::NONE));
    213 
    214     EXPECT_EQ(base::Value::TYPE_STRING, result->GetType());
    215     std::string permission_level;
    216     EXPECT_TRUE(result->GetAsString(&permission_level));
    217     EXPECT_EQ("denied", permission_level);
    218   }
    219 }
    220 
    221 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestOnPermissionLevelChanged) {
    222   const extensions::Extension* extension =
    223       LoadExtensionAndWait("notifications/api/permission");
    224   ASSERT_TRUE(extension) << message_;
    225 
    226   // Test permission level changing from granted to denied.
    227   {
    228     ResultCatcher catcher;
    229 
    230     message_center::NotifierId notifier_id(
    231         message_center::NotifierId::APPLICATION,
    232         extension->id());
    233     message_center::Notifier notifier(notifier_id, base::string16(), true);
    234     g_browser_process->message_center()->GetNotifierSettingsProvider()->
    235         SetNotifierEnabled(notifier, false);
    236 
    237     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    238   }
    239 
    240   // Test permission level changing from denied to granted.
    241   {
    242     ResultCatcher catcher;
    243 
    244     message_center::NotifierId notifier_id(
    245         message_center::NotifierId::APPLICATION,
    246         extension->id());
    247     message_center::Notifier notifier(notifier_id, base::string16(), false);
    248     g_browser_process->message_center()->GetNotifierSettingsProvider()->
    249         SetNotifierEnabled(notifier, true);
    250 
    251     EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
    252   }
    253 }
    254 
    255 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestUserGesture) {
    256   const extensions::Extension* extension =
    257       LoadExtensionAndWait("notifications/api/user_gesture");
    258   ASSERT_TRUE(extension) << message_;
    259 
    260   const message_center::NotificationList::Notifications& notifications =
    261       g_browser_process->message_center()->GetVisibleNotifications();
    262   ASSERT_EQ(1u, notifications.size());
    263   message_center::Notification* notification = *(notifications.begin());
    264 
    265   {
    266     UserGestureCatcher catcher;
    267     notification->ButtonClick(0);
    268     EXPECT_TRUE(catcher.GetNextResult());
    269     notification->Click();
    270     EXPECT_TRUE(catcher.GetNextResult());
    271     notification->Close(true);
    272     EXPECT_TRUE(catcher.GetNextResult());
    273     notification->Close(false);
    274     EXPECT_FALSE(catcher.GetNextResult());
    275   }
    276 }
    277