OLD | NEW |
| (Empty) |
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 "chrome/browser/chromeos/notifications/desktop_notifications_unittest.h
" | |
6 | |
7 #include "base/stringprintf.h" | |
8 #include "base/utf_string_conversions.h" | |
9 #include "chrome/browser/prefs/browser_prefs.h" | |
10 #include "chrome/browser/prefs/pref_service.h" | |
11 #include "content/public/common/show_desktop_notification_params.h" | |
12 | |
13 #if defined(USE_AURA) | |
14 #include "ash/shell.h" | |
15 #include "chrome/browser/chromeos/notifications/balloon_collection_impl_aura.h" | |
16 #include "ui/aura/root_window.h" | |
17 #else | |
18 #include "chrome/browser/chromeos/notifications/balloon_collection_impl.h" | |
19 #endif | |
20 | |
21 #if defined(USE_AURA) | |
22 typedef class chromeos::BalloonCollectionImplAura BalloonCollectionImplType; | |
23 #else | |
24 typedef class chromeos::BalloonCollectionImpl BalloonCollectionImplType; | |
25 #endif | |
26 | |
27 using content::BrowserThread; | |
28 | |
29 namespace chromeos { | |
30 | |
31 // static | |
32 std::string DesktopNotificationsTest::log_output_; | |
33 | |
34 class BalloonViewImpl; | |
35 | |
36 #if !defined(USE_AURA) | |
37 class MockNotificationUI : public BalloonCollectionImplType::NotificationUI { | |
38 public: | |
39 virtual void Add(Balloon* balloon) {} | |
40 virtual bool Update(Balloon* balloon) { return false; } | |
41 virtual void Remove(Balloon* balloon) {} | |
42 virtual void Show(Balloon* balloon) {} | |
43 virtual void ResizeNotification(Balloon* balloon, | |
44 const gfx::Size& size) {} | |
45 virtual void SetActiveView(BalloonViewImpl* view) {} | |
46 }; | |
47 #endif | |
48 | |
49 // Test version of the balloon collection which counts the number | |
50 // of notifications that are added to it. | |
51 class MockBalloonCollection : public BalloonCollectionImplType { | |
52 public: | |
53 MockBalloonCollection() { | |
54 #if !defined(USE_AURA) | |
55 set_notification_ui(new MockNotificationUI()); | |
56 #endif | |
57 } | |
58 virtual ~MockBalloonCollection() {}; | |
59 | |
60 // BalloonCollectionImplType overrides | |
61 virtual void Add(const Notification& notification, Profile* profile) OVERRIDE; | |
62 virtual Balloon* MakeBalloon(const Notification& notification, | |
63 Profile* profile) OVERRIDE; | |
64 virtual void OnBalloonClosed(Balloon* source) OVERRIDE; | |
65 | |
66 // Number of balloons being shown. | |
67 std::set<Balloon*>& balloons() { return balloons_; } | |
68 int count() const { return balloons_.size(); } | |
69 | |
70 private: | |
71 std::set<Balloon*> balloons_; | |
72 }; | |
73 | |
74 void MockBalloonCollection::Add(const Notification& notification, | |
75 Profile* profile) { | |
76 // Swap in a logging proxy for the purpose of logging calls that | |
77 // would be made into javascript, then pass this down to the | |
78 // balloon collection. | |
79 typedef LoggingNotificationDelegate<DesktopNotificationsTest> | |
80 LoggingNotificationProxy; | |
81 Notification test_notification( | |
82 notification.origin_url(), | |
83 notification.content_url(), | |
84 notification.display_source(), | |
85 notification.replace_id(), | |
86 new LoggingNotificationProxy(notification.notification_id())); | |
87 BalloonCollectionImplType::Add(test_notification, profile); | |
88 } | |
89 | |
90 Balloon* MockBalloonCollection::MakeBalloon(const Notification& notification, | |
91 Profile* profile) { | |
92 // Start with a normal balloon but mock out the view. | |
93 Balloon* balloon = | |
94 BalloonCollectionImplType::MakeBalloon(notification, profile); | |
95 balloon->set_view(new MockBalloonView(balloon)); | |
96 balloons_.insert(balloon); | |
97 return balloon; | |
98 } | |
99 | |
100 void MockBalloonCollection::OnBalloonClosed(Balloon* source) { | |
101 balloons_.erase(source); | |
102 BalloonCollectionImplType::OnBalloonClosed(source); | |
103 } | |
104 | |
105 // DesktopNotificationsTest | |
106 | |
107 DesktopNotificationsTest::DesktopNotificationsTest() | |
108 : ui_thread_(BrowserThread::UI, &message_loop_) { | |
109 } | |
110 | |
111 DesktopNotificationsTest::~DesktopNotificationsTest() { | |
112 } | |
113 | |
114 void DesktopNotificationsTest::SetUp() { | |
115 #if defined(USE_ASH) | |
116 // Make sure a root window has been instantiated. | |
117 ash::Shell::CreateInstance(NULL); | |
118 #endif | |
119 browser::RegisterLocalState(&local_state_); | |
120 profile_.reset(new TestingProfile()); | |
121 balloon_collection_ = new MockBalloonCollection(); | |
122 ui_manager_.reset(NotificationUIManager::Create(&local_state_, | |
123 balloon_collection_)); | |
124 service_.reset(new DesktopNotificationService(profile(), ui_manager_.get())); | |
125 log_output_.clear(); | |
126 } | |
127 | |
128 void DesktopNotificationsTest::TearDown() { | |
129 service_.reset(NULL); | |
130 ui_manager_.reset(NULL); | |
131 profile_.reset(NULL); | |
132 #if defined(USE_ASH) | |
133 ash::Shell::DeleteInstance(); | |
134 #endif | |
135 } | |
136 | |
137 content::ShowDesktopNotificationHostMsgParams | |
138 DesktopNotificationsTest::StandardTestNotification() { | |
139 content::ShowDesktopNotificationHostMsgParams params; | |
140 params.notification_id = 0; | |
141 params.origin = GURL("http://www.google.com"); | |
142 params.is_html = false; | |
143 params.icon_url = GURL("/icon.png"); | |
144 params.title = ASCIIToUTF16("Title"); | |
145 params.body = ASCIIToUTF16("Text"); | |
146 params.direction = WebKit::WebTextDirectionDefault; | |
147 return params; | |
148 } | |
149 | |
150 TEST_F(DesktopNotificationsTest, TestShow) { | |
151 content::ShowDesktopNotificationHostMsgParams params = | |
152 StandardTestNotification(); | |
153 params.notification_id = 1; | |
154 EXPECT_TRUE(service_->ShowDesktopNotification( | |
155 params, 0, 0, DesktopNotificationService::PageNotification)); | |
156 | |
157 MessageLoopForUI::current()->RunAllPending(); | |
158 EXPECT_EQ(1, balloon_collection_->count()); | |
159 | |
160 content::ShowDesktopNotificationHostMsgParams params2; | |
161 params2.origin = GURL("http://www.google.com"); | |
162 params2.is_html = true; | |
163 params2.contents_url = GURL("http://www.google.com/notification.html"); | |
164 params2.notification_id = 2; | |
165 | |
166 EXPECT_TRUE(service_->ShowDesktopNotification( | |
167 params2, 0, 0, DesktopNotificationService::PageNotification)); | |
168 MessageLoopForUI::current()->RunAllPending(); | |
169 EXPECT_EQ(2, balloon_collection_->count()); | |
170 | |
171 EXPECT_EQ("notification displayed\n" | |
172 "notification displayed\n", | |
173 log_output_); | |
174 } | |
175 | |
176 TEST_F(DesktopNotificationsTest, TestClose) { | |
177 content::ShowDesktopNotificationHostMsgParams params = | |
178 StandardTestNotification(); | |
179 params.notification_id = 1; | |
180 | |
181 // Request a notification; should open a balloon. | |
182 EXPECT_TRUE(service_->ShowDesktopNotification( | |
183 params, 0, 0, DesktopNotificationService::PageNotification)); | |
184 MessageLoopForUI::current()->RunAllPending(); | |
185 EXPECT_EQ(1, balloon_collection_->count()); | |
186 | |
187 // Close all the open balloons. | |
188 std::set<Balloon*> balloons = balloon_collection_->balloons(); | |
189 std::set<Balloon*>::iterator iter; | |
190 for (iter = balloons.begin(); iter != balloons.end(); ++iter) { | |
191 (*iter)->OnClose(true); | |
192 } | |
193 | |
194 // Verify that the balloon collection is now empty. | |
195 EXPECT_EQ(0, balloon_collection_->count()); | |
196 | |
197 EXPECT_EQ("notification displayed\n" | |
198 "notification closed by user\n", | |
199 log_output_); | |
200 } | |
201 | |
202 TEST_F(DesktopNotificationsTest, TestCancel) { | |
203 int process_id = 0; | |
204 int route_id = 0; | |
205 int notification_id = 1; | |
206 | |
207 content::ShowDesktopNotificationHostMsgParams params = | |
208 StandardTestNotification(); | |
209 params.notification_id = notification_id; | |
210 | |
211 // Request a notification; should open a balloon. | |
212 EXPECT_TRUE(service_->ShowDesktopNotification( | |
213 params, process_id, route_id, | |
214 DesktopNotificationService::PageNotification)); | |
215 MessageLoopForUI::current()->RunAllPending(); | |
216 EXPECT_EQ(1, balloon_collection_->count()); | |
217 | |
218 // Cancel the same notification | |
219 service_->CancelDesktopNotification(process_id, | |
220 route_id, | |
221 notification_id); | |
222 MessageLoopForUI::current()->RunAllPending(); | |
223 // Verify that the balloon collection is now empty. | |
224 EXPECT_EQ(0, balloon_collection_->count()); | |
225 | |
226 EXPECT_EQ("notification displayed\n" | |
227 "notification closed by script\n", | |
228 log_output_); | |
229 } | |
230 | |
231 TEST_F(DesktopNotificationsTest, TestManyNotifications) { | |
232 int process_id = 0; | |
233 int route_id = 0; | |
234 | |
235 // Request lots of identical notifications. | |
236 #if defined(USE_AURA) | |
237 // Aura is using the non-chromeos notification system which has a limit | |
238 // of 4 visible toasts. | |
239 const int kLotsOfToasts = 4; | |
240 #else | |
241 const int kLotsOfToasts = 20; | |
242 #endif | |
243 for (int id = 1; id <= kLotsOfToasts; ++id) { | |
244 SCOPED_TRACE(base::StringPrintf("Creation loop: id=%d", id)); | |
245 content::ShowDesktopNotificationHostMsgParams params = | |
246 StandardTestNotification(); | |
247 params.notification_id = id; | |
248 EXPECT_TRUE(service_->ShowDesktopNotification( | |
249 params, process_id, route_id, | |
250 DesktopNotificationService::PageNotification)); | |
251 } | |
252 MessageLoopForUI::current()->RunAllPending(); | |
253 | |
254 // Build up an expected log of what should be happening. | |
255 std::string expected_log; | |
256 for (int i = 0; i < kLotsOfToasts; ++i) { | |
257 expected_log.append("notification displayed\n"); | |
258 } | |
259 | |
260 EXPECT_EQ(kLotsOfToasts, balloon_collection_->count()); | |
261 EXPECT_EQ(expected_log, log_output_); | |
262 | |
263 // Cancel half of the notifications from the start | |
264 int id; | |
265 int cancelled = kLotsOfToasts / 2; | |
266 for (id = 1; | |
267 id <= cancelled; | |
268 ++id) { | |
269 SCOPED_TRACE(base::StringPrintf("Cancel half of notifications: id=%d", id)); | |
270 service_->CancelDesktopNotification(process_id, route_id, id); | |
271 MessageLoopForUI::current()->RunAllPending(); | |
272 expected_log.append("notification closed by script\n"); | |
273 EXPECT_EQ(kLotsOfToasts - id, | |
274 balloon_collection_->count()); | |
275 EXPECT_EQ(expected_log, log_output_); | |
276 } | |
277 | |
278 // Now cancel the rest. It should empty the balloon space. | |
279 for (; id <= kLotsOfToasts; ++id) { | |
280 SCOPED_TRACE(base::StringPrintf("Cancel loop: id=%d", id)); | |
281 service_->CancelDesktopNotification(process_id, route_id, id); | |
282 expected_log.append("notification closed by script\n"); | |
283 MessageLoopForUI::current()->RunAllPending(); | |
284 EXPECT_EQ(expected_log, log_output_); | |
285 } | |
286 | |
287 // Verify that the balloon collection is now empty. | |
288 EXPECT_EQ(0, balloon_collection_->count()); | |
289 } | |
290 | |
291 TEST_F(DesktopNotificationsTest, TestEarlyDestruction) { | |
292 // Create some toasts and then prematurely delete the notification service, | |
293 // just to make sure nothing crashes/leaks. | |
294 for (int id = 0; id <= 3; ++id) { | |
295 SCOPED_TRACE(base::StringPrintf("Show Text loop: id=%d", id)); | |
296 | |
297 EXPECT_TRUE(service_->ShowDesktopNotification( | |
298 StandardTestNotification(), 0, 0, | |
299 DesktopNotificationService::PageNotification)); | |
300 } | |
301 service_.reset(NULL); | |
302 } | |
303 | |
304 TEST_F(DesktopNotificationsTest, TestUserInputEscaping) { | |
305 // Create a test script with some HTML; assert that it doesn't get into the | |
306 // data:// URL that's produced for the balloon. | |
307 content::ShowDesktopNotificationHostMsgParams params = | |
308 StandardTestNotification(); | |
309 params.title = ASCIIToUTF16("<script>window.alert('uh oh');</script>"); | |
310 params.body = ASCIIToUTF16("<i>this text is in italics</i>"); | |
311 params.notification_id = 1; | |
312 EXPECT_TRUE(service_->ShowDesktopNotification( | |
313 params, 0, 0, DesktopNotificationService::PageNotification)); | |
314 | |
315 MessageLoopForUI::current()->RunAllPending(); | |
316 EXPECT_EQ(1, balloon_collection_->count()); | |
317 Balloon* balloon = (*balloon_collection_->balloons().begin()); | |
318 GURL data_url = balloon->notification().content_url(); | |
319 EXPECT_EQ(std::string::npos, data_url.spec().find("<script>")); | |
320 EXPECT_EQ(std::string::npos, data_url.spec().find("<i>")); | |
321 } | |
322 | |
323 } // namespace chromeos | |
OLD | NEW |