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