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 "chrome/browser/profiles/profile_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/browser/notification_types.h"
19 #include "extensions/common/features/feature.h"
20 #include "extensions/common/test_util.h"
21 #include "extensions/test/result_catcher.h"
22 #include "ui/message_center/message_center.h"
23 #include "ui/message_center/notification_list.h"
24 #include "ui/message_center/notifier_settings.h"
26 using extensions::Extension
;
27 using extensions::ResultCatcher
;
29 namespace utils
= extension_function_test_utils
;
33 // A class that waits for a |chrome.test.sendMessage| call, ignores the message,
34 // and writes down the user gesture status of the message.
35 class UserGestureCatcher
: public content::NotificationObserver
{
37 UserGestureCatcher() : waiting_(false) {
39 extensions::NOTIFICATION_EXTENSION_TEST_MESSAGE
,
40 content::NotificationService::AllSources());
43 ~UserGestureCatcher() override
{}
45 bool GetNextResult() {
46 if (results_
.empty()) {
48 content::RunMessageLoop();
52 if (!results_
.empty()) {
53 bool ret
= results_
.front();
62 void Observe(int type
,
63 const content::NotificationSource
& source
,
64 const content::NotificationDetails
& details
) override
{
66 static_cast<content::Source
<extensions::TestSendMessageFunction
> >(
71 base::MessageLoopForUI::current()->Quit();
74 content::NotificationRegistrar registrar_
;
76 // A sequential list of user gesture notifications from the test extension(s).
77 std::deque
<bool> results_
;
79 // True if we're in a nested message loop waiting for results from
84 class NotificationsApiTest
: public ExtensionApiTest
{
86 const extensions::Extension
* LoadExtensionAndWait(
87 const std::string
& test_name
) {
88 base::FilePath extdir
= test_data_dir_
.AppendASCII(test_name
);
89 content::WindowedNotificationObserver
page_created(
90 extensions::NOTIFICATION_EXTENSION_BACKGROUND_PAGE_READY
,
91 content::NotificationService::AllSources());
92 const extensions::Extension
* extension
= LoadExtension(extdir
);
100 std::string
GetNotificationIdFromDelegateId(std::string delegate_id
) {
101 return g_browser_process
->notification_ui_manager()
104 NotificationUIManager::GetProfileID(
105 g_browser_process
->profile_manager()->GetLastUsedProfile()))
112 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestBasicUsage
) {
113 ASSERT_TRUE(RunExtensionTest("notifications/api/basic_usage")) << message_
;
116 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestEvents
) {
117 ASSERT_TRUE(RunExtensionTest("notifications/api/events")) << message_
;
120 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestCSP
) {
121 ASSERT_TRUE(RunExtensionTest("notifications/api/csp")) << message_
;
124 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestByUser
) {
125 const extensions::Extension
* extension
=
126 LoadExtensionAndWait("notifications/api/by_user");
127 ASSERT_TRUE(extension
) << message_
;
130 ResultCatcher catcher
;
131 const std::string notification_id
=
132 GetNotificationIdFromDelegateId(extension
->id() + "-FOO");
133 g_browser_process
->message_center()->RemoveNotification(notification_id
,
135 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
139 ResultCatcher catcher
;
140 const std::string notification_id
=
141 GetNotificationIdFromDelegateId(extension
->id() + "-BAR");
142 g_browser_process
->message_center()->RemoveNotification(notification_id
,
144 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
148 ResultCatcher catcher
;
149 g_browser_process
->message_center()->RemoveAllNotifications(false);
150 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
153 ResultCatcher catcher
;
154 g_browser_process
->message_center()->RemoveAllNotifications(true);
155 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
159 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestPartialUpdate
) {
160 ASSERT_TRUE(RunExtensionTest("notifications/api/partial_update")) << message_
;
161 const extensions::Extension
* extension
= GetSingleLoadedExtension();
162 ASSERT_TRUE(extension
) << message_
;
164 const char kNewTitle
[] = "Changed!";
165 const char kNewMessage
[] = "Too late! The show ended yesterday";
166 int kNewPriority
= 2;
167 const char kButtonTitle
[] = "NewButton";
169 const message_center::NotificationList::Notifications
& notifications
=
170 g_browser_process
->message_center()->GetVisibleNotifications();
171 ASSERT_EQ(1u, notifications
.size());
172 message_center::Notification
* notification
= *(notifications
.begin());
173 LOG(INFO
) << "Notification ID: " << notification
->id();
175 EXPECT_EQ(base::ASCIIToUTF16(kNewTitle
), notification
->title());
176 EXPECT_EQ(base::ASCIIToUTF16(kNewMessage
), notification
->message());
177 EXPECT_EQ(kNewPriority
, notification
->priority());
178 EXPECT_EQ(1u, notification
->buttons().size());
179 EXPECT_EQ(base::ASCIIToUTF16(kButtonTitle
), notification
->buttons()[0].title
);
182 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestGetPermissionLevel
) {
183 scoped_refptr
<Extension
> empty_extension(
184 extensions::test_util::CreateEmptyExtension());
186 // Get permission level for the extension whose notifications are enabled.
188 scoped_refptr
<extensions::NotificationsGetPermissionLevelFunction
>
189 notification_function(
190 new extensions::NotificationsGetPermissionLevelFunction());
192 notification_function
->set_extension(empty_extension
.get());
193 notification_function
->set_has_callback(true);
195 scoped_ptr
<base::Value
> result(utils::RunFunctionAndReturnSingleResult(
196 notification_function
.get(),
201 EXPECT_EQ(base::Value::TYPE_STRING
, result
->GetType());
202 std::string permission_level
;
203 EXPECT_TRUE(result
->GetAsString(&permission_level
));
204 EXPECT_EQ("granted", permission_level
);
207 // Get permission level for the extension whose notifications are disabled.
209 scoped_refptr
<extensions::NotificationsGetPermissionLevelFunction
>
210 notification_function(
211 new extensions::NotificationsGetPermissionLevelFunction());
213 notification_function
->set_extension(empty_extension
.get());
214 notification_function
->set_has_callback(true);
216 message_center::NotifierId
notifier_id(
217 message_center::NotifierId::APPLICATION
,
218 empty_extension
->id());
219 message_center::Notifier
notifier(notifier_id
, base::string16(), true);
220 g_browser_process
->message_center()->GetNotifierSettingsProvider()->
221 SetNotifierEnabled(notifier
, false);
223 scoped_ptr
<base::Value
> result(utils::RunFunctionAndReturnSingleResult(
224 notification_function
.get(),
229 EXPECT_EQ(base::Value::TYPE_STRING
, result
->GetType());
230 std::string permission_level
;
231 EXPECT_TRUE(result
->GetAsString(&permission_level
));
232 EXPECT_EQ("denied", permission_level
);
236 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestOnPermissionLevelChanged
) {
237 const extensions::Extension
* extension
=
238 LoadExtensionAndWait("notifications/api/permission");
239 ASSERT_TRUE(extension
) << message_
;
241 // Test permission level changing from granted to denied.
243 ResultCatcher catcher
;
245 message_center::NotifierId
notifier_id(
246 message_center::NotifierId::APPLICATION
,
248 message_center::Notifier
notifier(notifier_id
, base::string16(), true);
249 g_browser_process
->message_center()->GetNotifierSettingsProvider()->
250 SetNotifierEnabled(notifier
, false);
252 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
255 // Test permission level changing from denied to granted.
257 ResultCatcher catcher
;
259 message_center::NotifierId
notifier_id(
260 message_center::NotifierId::APPLICATION
,
262 message_center::Notifier
notifier(notifier_id
, base::string16(), false);
263 g_browser_process
->message_center()->GetNotifierSettingsProvider()->
264 SetNotifierEnabled(notifier
, true);
266 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
270 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestUserGesture
) {
271 const extensions::Extension
* extension
=
272 LoadExtensionAndWait("notifications/api/user_gesture");
273 ASSERT_TRUE(extension
) << message_
;
275 const message_center::NotificationList::Notifications
& notifications
=
276 g_browser_process
->message_center()->GetVisibleNotifications();
277 ASSERT_EQ(1u, notifications
.size());
278 message_center::Notification
* notification
= *(notifications
.begin());
281 UserGestureCatcher catcher
;
282 notification
->ButtonClick(0);
283 EXPECT_TRUE(catcher
.GetNextResult());
284 notification
->Click();
285 EXPECT_TRUE(catcher
.GetNextResult());
286 notification
->Close(true);
287 EXPECT_TRUE(catcher
.GetNextResult());
288 notification
->Close(false);
289 EXPECT_FALSE(catcher
.GetNextResult());