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;
168 const message_center::NotificationList::Notifications
& notifications
=
169 g_browser_process
->message_center()->GetVisibleNotifications();
170 ASSERT_EQ(1u, notifications
.size());
171 message_center::Notification
* notification
= *(notifications
.begin());
172 LOG(INFO
) << "Notification ID: " << notification
->id();
174 EXPECT_EQ(base::ASCIIToUTF16(kNewTitle
), notification
->title());
175 EXPECT_EQ(base::ASCIIToUTF16(kNewMessage
), notification
->message());
176 EXPECT_EQ(kNewPriority
, notification
->priority());
177 EXPECT_EQ(0u, notification
->buttons().size());
180 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestGetPermissionLevel
) {
181 scoped_refptr
<Extension
> empty_extension(
182 extensions::test_util::CreateEmptyExtension());
184 // Get permission level for the extension whose notifications are enabled.
186 scoped_refptr
<extensions::NotificationsGetPermissionLevelFunction
>
187 notification_function(
188 new extensions::NotificationsGetPermissionLevelFunction());
190 notification_function
->set_extension(empty_extension
.get());
191 notification_function
->set_has_callback(true);
193 scoped_ptr
<base::Value
> result(utils::RunFunctionAndReturnSingleResult(
194 notification_function
.get(),
199 EXPECT_EQ(base::Value::TYPE_STRING
, result
->GetType());
200 std::string permission_level
;
201 EXPECT_TRUE(result
->GetAsString(&permission_level
));
202 EXPECT_EQ("granted", permission_level
);
205 // Get permission level for the extension whose notifications are disabled.
207 scoped_refptr
<extensions::NotificationsGetPermissionLevelFunction
>
208 notification_function(
209 new extensions::NotificationsGetPermissionLevelFunction());
211 notification_function
->set_extension(empty_extension
.get());
212 notification_function
->set_has_callback(true);
214 message_center::NotifierId
notifier_id(
215 message_center::NotifierId::APPLICATION
,
216 empty_extension
->id());
217 message_center::Notifier
notifier(notifier_id
, base::string16(), true);
218 g_browser_process
->message_center()->GetNotifierSettingsProvider()->
219 SetNotifierEnabled(notifier
, false);
221 scoped_ptr
<base::Value
> result(utils::RunFunctionAndReturnSingleResult(
222 notification_function
.get(),
227 EXPECT_EQ(base::Value::TYPE_STRING
, result
->GetType());
228 std::string permission_level
;
229 EXPECT_TRUE(result
->GetAsString(&permission_level
));
230 EXPECT_EQ("denied", permission_level
);
234 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestOnPermissionLevelChanged
) {
235 const extensions::Extension
* extension
=
236 LoadExtensionAndWait("notifications/api/permission");
237 ASSERT_TRUE(extension
) << message_
;
239 // Test permission level changing from granted to denied.
241 ResultCatcher catcher
;
243 message_center::NotifierId
notifier_id(
244 message_center::NotifierId::APPLICATION
,
246 message_center::Notifier
notifier(notifier_id
, base::string16(), true);
247 g_browser_process
->message_center()->GetNotifierSettingsProvider()->
248 SetNotifierEnabled(notifier
, false);
250 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
253 // Test permission level changing from denied to granted.
255 ResultCatcher catcher
;
257 message_center::NotifierId
notifier_id(
258 message_center::NotifierId::APPLICATION
,
260 message_center::Notifier
notifier(notifier_id
, base::string16(), false);
261 g_browser_process
->message_center()->GetNotifierSettingsProvider()->
262 SetNotifierEnabled(notifier
, true);
264 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
268 IN_PROC_BROWSER_TEST_F(NotificationsApiTest
, TestUserGesture
) {
269 const extensions::Extension
* extension
=
270 LoadExtensionAndWait("notifications/api/user_gesture");
271 ASSERT_TRUE(extension
) << message_
;
273 const message_center::NotificationList::Notifications
& notifications
=
274 g_browser_process
->message_center()->GetVisibleNotifications();
275 ASSERT_EQ(1u, notifications
.size());
276 message_center::Notification
* notification
= *(notifications
.begin());
279 UserGestureCatcher catcher
;
280 notification
->ButtonClick(0);
281 EXPECT_TRUE(catcher
.GetNextResult());
282 notification
->Click();
283 EXPECT_TRUE(catcher
.GetNextResult());
284 notification
->Close(true);
285 EXPECT_TRUE(catcher
.GetNextResult());
286 notification
->Close(false);
287 EXPECT_FALSE(catcher
.GetNextResult());