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 "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"
25 using extensions::Extension;
26 using extensions::ResultCatcher;
28 namespace utils = extension_function_test_utils;
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 {
36 UserGestureCatcher() : waiting_(false) {
38 extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE,
39 content::NotificationService::AllSources());
42 virtual ~UserGestureCatcher() {}
44 bool GetNextResult() {
45 if (results_.empty()) {
47 content::RunMessageLoop();
51 if (!results_.empty()) {
52 bool ret = results_.front();
61 virtual void Observe(int type,
62 const content::NotificationSource& source,
63 const content::NotificationDetails& details) OVERRIDE {
65 static_cast<content::Source<extensions::TestSendMessageFunction> >(
70 base::MessageLoopForUI::current()->Quit();
73 content::NotificationRegistrar registrar_;
75 // A sequential list of user gesture notifications from the test extension(s).
76 std::deque<bool> results_;
78 // True if we're in a nested message loop waiting for results from
83 class NotificationsApiTest : public ExtensionApiTest {
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);
101 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestBasicUsage) {
102 ASSERT_TRUE(RunExtensionTest("notifications/api/basic_usage")) << message_;
105 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestEvents) {
106 ASSERT_TRUE(RunExtensionTest("notifications/api/events")) << message_;
109 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestCSP) {
110 ASSERT_TRUE(RunExtensionTest("notifications/api/csp")) << message_;
113 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestByUser) {
114 const extensions::Extension* extension =
115 LoadExtensionAndWait("notifications/api/by_user");
116 ASSERT_TRUE(extension) << message_;
119 ResultCatcher catcher;
120 g_browser_process->message_center()->RemoveNotification(
121 extension->id() + "-FOO",
123 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
127 ResultCatcher catcher;
128 g_browser_process->message_center()->RemoveNotification(
129 extension->id() + "-BAR",
131 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
135 ResultCatcher catcher;
136 g_browser_process->message_center()->RemoveAllNotifications(false);
137 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
140 ResultCatcher catcher;
141 g_browser_process->message_center()->RemoveAllNotifications(true);
142 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
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_;
151 const char kNewTitle[] = "Changed!";
152 const char kNewMessage[] = "Too late! The show ended yesterday";
153 int kNewPriority = 2;
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();
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());
167 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestGetPermissionLevel) {
168 scoped_refptr<Extension> empty_extension(
169 extensions::test_util::CreateEmptyExtension());
171 // Get permission level for the extension whose notifications are enabled.
173 scoped_refptr<extensions::NotificationsGetPermissionLevelFunction>
174 notification_function(
175 new extensions::NotificationsGetPermissionLevelFunction());
177 notification_function->set_extension(empty_extension.get());
178 notification_function->set_has_callback(true);
180 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
181 notification_function.get(),
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);
192 // Get permission level for the extension whose notifications are disabled.
194 scoped_refptr<extensions::NotificationsGetPermissionLevelFunction>
195 notification_function(
196 new extensions::NotificationsGetPermissionLevelFunction());
198 notification_function->set_extension(empty_extension.get());
199 notification_function->set_has_callback(true);
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);
208 scoped_ptr<base::Value> result(utils::RunFunctionAndReturnSingleResult(
209 notification_function.get(),
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);
221 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestOnPermissionLevelChanged) {
222 const extensions::Extension* extension =
223 LoadExtensionAndWait("notifications/api/permission");
224 ASSERT_TRUE(extension) << message_;
226 // Test permission level changing from granted to denied.
228 ResultCatcher catcher;
230 message_center::NotifierId notifier_id(
231 message_center::NotifierId::APPLICATION,
233 message_center::Notifier notifier(notifier_id, base::string16(), true);
234 g_browser_process->message_center()->GetNotifierSettingsProvider()->
235 SetNotifierEnabled(notifier, false);
237 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
240 // Test permission level changing from denied to granted.
242 ResultCatcher catcher;
244 message_center::NotifierId notifier_id(
245 message_center::NotifierId::APPLICATION,
247 message_center::Notifier notifier(notifier_id, base::string16(), false);
248 g_browser_process->message_center()->GetNotifierSettingsProvider()->
249 SetNotifierEnabled(notifier, true);
251 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
255 IN_PROC_BROWSER_TEST_F(NotificationsApiTest, TestUserGesture) {
256 const extensions::Extension* extension =
257 LoadExtensionAndWait("notifications/api/user_gesture");
258 ASSERT_TRUE(extension) << message_;
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());
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());