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.
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 "ui/message_center/message_center.h"
20 #include "ui/message_center/notification_list.h"
21 #include "ui/message_center/notifier_settings.h"
23 using extensions::Extension;
25 namespace utils = extension_function_test_utils;
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 {
33 UserGestureCatcher() : waiting_(false) {
35 extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE,
36 content::NotificationService::AllSources());
39 virtual ~UserGestureCatcher() {}
41 bool GetNextResult() {
42 if (results_.empty()) {
44 content::RunMessageLoop();
48 if (!results_.empty()) {
49 bool ret = results_.front();
58 virtual void Observe(int type,
59 const content::NotificationSource& source,
60 const content::NotificationDetails& details) OVERRIDE {
62 static_cast<content::Source<extensions::TestSendMessageFunction> >(
67 base::MessageLoopForUI::current()->Quit();
70 content::NotificationRegistrar registrar_;
72 // A sequential list of user gesture notifications from the test extension(s).
73 std::deque<bool> results_;
75 // True if we're in a nested message loop waiting for results from
80 class NotificationsApiTest : public ExtensionApiTest {
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 extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY,
87 content::NotificationService::AllSources());
88 const extensions::Extension* extension = LoadExtension(extdir);
98 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestBasicUsage) {
99 ASSERT_TRUE(RunExtensionTest("notifications/api/basic_usage")) << message_;
102 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestEvents) {
103 ASSERT_TRUE(RunExtensionTest("notifications/api/events")) << message_;
106 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestCSP) {
107 ASSERT_TRUE(RunExtensionTest("notifications/api/csp")) << message_;
110 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) {
111 const extensions::Extension* extension =
112 LoadExtensionAndWait("notifications/api/by_user");
113 ASSERT_TRUE(extension) << message_;
116 ResultCatcher catcher;
117 g_browser_process->message_center()->RemoveNotification(
118 extension->id() + "-FOO",
120 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
124 ResultCatcher catcher;
125 g_browser_process->message_center()->RemoveNotification(
126 extension->id() + "-BAR",
128 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
132 ResultCatcher catcher;
133 g_browser_process->message_center()->RemoveAllNotifications(false);
134 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
137 ResultCatcher catcher;
138 g_browser_process->message_center()->RemoveAllNotifications(true);
139 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
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_;
148 const char kNewTitle[] = "Changed!";
149 const char kNewMessage[] = "Too late! The show ended yesterday";
150 int kNewPriority = 2;
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();
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());
164 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestGetPermissionLevel) {
165 scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension());
167 // Get permission level for the extension whose notifications are enabled.
169 scoped_refptr<extensions::NotificationsGetPermissionLevelFunction>
170 notification_function(
171 new extensions::NotificationsGetPermissionLevelFunction());
173 notification_function->set_extension(empty_extension.get());
174 notification_function->set_has_callback(true);
176 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
177 notification_function.get(),
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);
188 // Get permission level for the extension whose notifications are disabled.
190 scoped_refptr<extensions::NotificationsGetPermissionLevelFunction>
191 notification_function(
192 new extensions::NotificationsGetPermissionLevelFunction());
194 notification_function->set_extension(empty_extension.get());
195 notification_function->set_has_callback(true);
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);
204 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
205 notification_function.get(),
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);
217 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestOnPermissionLevelChanged) {
218 const extensions::Extension* extension =
219 LoadExtensionAndWait("notifications/api/permission");
220 ASSERT_TRUE(extension) << message_;
222 // Test permission level changing from granted to denied.
224 ResultCatcher catcher;
226 message_center::NotifierId notifier_id(
227 message_center::NotifierId::APPLICATION,
229 message_center::Notifier notifier(notifier_id, base::string16(), true);
230 g_browser_process->message_center()->GetNotifierSettingsProvider()->
231 SetNotifierEnabled(notifier, false);
233 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
236 // Test permission level changing from denied to granted.
238 ResultCatcher catcher;
240 message_center::NotifierId notifier_id(
241 message_center::NotifierId::APPLICATION,
243 message_center::Notifier notifier(notifier_id, base::string16(), false);
244 g_browser_process->message_center()->GetNotifierSettingsProvider()->
245 SetNotifierEnabled(notifier, true);
247 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
251 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestUserGesture) {
252 const extensions::Extension* extension =
253 LoadExtensionAndWait("notifications/api/user_gesture");
254 ASSERT_TRUE(extension) << message_;
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());
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());