Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(193)

Side by Side Diff: chrome/browser/notifications/desktop_notifications_unittest.cc

Issue 231723006: Remove balloon notification code. The last user was the Linux GTK port but that's deleted now. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: sync after elliot's r263101 Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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/notifications/desktop_notifications_unittest.h"
6
7 #include "base/prefs/testing_pref_service.h"
8 #include "base/strings/string_util.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/notifications/balloon_notification_ui_manager.h"
11 #include "chrome/browser/notifications/fake_balloon_view.h"
12 #include "chrome/browser/prefs/browser_prefs.h"
13 #include "chrome/common/pref_names.h"
14 #include "chrome/test/base/chrome_unit_test_suite.h"
15 #include "chrome/test/base/testing_browser_process.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "chrome/test/base/testing_profile_manager.h"
18 #include "content/public/common/show_desktop_notification_params.h"
19 #include "ui/base/ime/input_method_initializer.h"
20 #include "ui/gl/gl_surface.h"
21 #include "ui/message_center/message_center.h"
22
23 #if defined(USE_ASH)
24 #include "ash/shell.h"
25 #include "ash/test/test_shell_delegate.h"
26 #include "ui/aura/env.h"
27 #include "ui/aura/window_event_dispatcher.h"
28 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
29 #include "ui/compositor/test/context_factories_for_test.h"
30 #endif
31
32 #if defined(USE_AURA)
33 #include "ui/wm/core/wm_state.h"
34 #endif
35
36
37 using content::BrowserThread;
38
39 // static
40 const int MockBalloonCollection::kMockBalloonSpace = 5;
41
42 // static
43 std::string DesktopNotificationsTest::log_output_;
44
45 MockBalloonCollection::MockBalloonCollection() {}
46
47 MockBalloonCollection::~MockBalloonCollection() {}
48
49 void MockBalloonCollection::Add(const Notification& notification,
50 Profile* profile) {
51 // Swap in a logging proxy for the purpose of logging calls that
52 // would be made into javascript, then pass this down to the
53 // balloon collection.
54 Notification test_notification(
55 notification.origin_url(),
56 notification.content_url(),
57 notification.display_source(),
58 notification.replace_id(),
59 new LoggingNotificationProxy(notification.notification_id()));
60 BalloonCollectionImpl::Add(test_notification, profile);
61 }
62
63 bool MockBalloonCollection::HasSpace() const {
64 return count() < kMockBalloonSpace;
65 }
66
67 Balloon* MockBalloonCollection::MakeBalloon(const Notification& notification,
68 Profile* profile) {
69 // Start with a normal balloon but mock out the view.
70 Balloon* balloon = BalloonCollectionImpl::MakeBalloon(notification, profile);
71 balloon->set_view(new FakeBalloonView(balloon));
72 balloons_.push_back(balloon);
73 return balloon;
74 }
75
76 void MockBalloonCollection::OnBalloonClosed(Balloon* source) {
77 std::deque<Balloon*>::iterator it;
78 for (it = balloons_.begin(); it != balloons_.end(); ++it) {
79 if (*it == source) {
80 balloons_.erase(it);
81 BalloonCollectionImpl::OnBalloonClosed(source);
82 break;
83 }
84 }
85 }
86
87 const BalloonCollection::Balloons& MockBalloonCollection::GetActiveBalloons() {
88 return balloons_;
89 }
90
91 int MockBalloonCollection::UppermostVerticalPosition() {
92 int min = 0;
93 std::deque<Balloon*>::iterator iter;
94 for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) {
95 int pos = (*iter)->GetPosition().y();
96 if (iter == balloons_.begin() || pos < min)
97 min = pos;
98 }
99 return min;
100 }
101
102 DesktopNotificationsTest::DesktopNotificationsTest()
103 : ui_thread_(BrowserThread::UI, &message_loop_),
104 balloon_collection_(NULL) {
105 }
106
107 DesktopNotificationsTest::~DesktopNotificationsTest() {
108 }
109
110 void DesktopNotificationsTest::SetUp() {
111 ChromeUnitTestSuite::InitializeProviders();
112 ChromeUnitTestSuite::InitializeResourceBundle();
113 ui::InitializeInputMethodForTesting();
114 #if defined(USE_AURA)
115 wm_state_.reset(new wm::WMState);
116 #endif
117 #if defined(USE_ASH)
118 ui::ScopedAnimationDurationScaleMode normal_duration_mode(
119 ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
120 // The message center is notmally initialized on |g_browser_process| which
121 // is not created for these tests.
122 message_center::MessageCenter::Initialize();
123 // The ContextFactory must exist before any Compositors are created.
124 bool enable_pixel_output = false;
125 ui::InitializeContextFactoryForTests(enable_pixel_output);
126 // MockBalloonCollection retrieves information about the screen on creation.
127 // So it is necessary to make sure the desktop gets created first.
128 ash::Shell::CreateInstance(new ash::test::TestShellDelegate);
129 #endif
130 chrome::RegisterLocalState(local_state_.registry());
131 profile_.reset(new TestingProfile());
132 ui_manager_.reset(new BalloonNotificationUIManager(&local_state_));
133 balloon_collection_ = new MockBalloonCollection();
134 ui_manager_->SetBalloonCollection(balloon_collection_);
135 service_.reset(new DesktopNotificationService(profile(), ui_manager_.get()));
136 log_output_.clear();
137 }
138
139 void DesktopNotificationsTest::TearDown() {
140 service_.reset(NULL);
141 ui_manager_.reset(NULL);
142 profile_.reset(NULL);
143 #if defined(USE_ASH)
144 ash::Shell::DeleteInstance();
145 // The message center is notmally shutdown on |g_browser_process| which
146 // is not created for these tests.
147 message_center::MessageCenter::Shutdown();
148 aura::Env::DeleteInstance();
149 ui::TerminateContextFactoryForTests();
150 #endif
151 #if defined(USE_AURA)
152 wm_state_.reset();
153 #endif
154 ui::ShutdownInputMethodForTesting();
155 }
156
157 content::ShowDesktopNotificationHostMsgParams
158 DesktopNotificationsTest::StandardTestNotification() {
159 content::ShowDesktopNotificationHostMsgParams params;
160 params.notification_id = 0;
161 params.origin = GURL("http://www.google.com");
162 params.icon_url = GURL("/icon.png");
163 params.title = base::ASCIIToUTF16("Title");
164 params.body = base::ASCIIToUTF16("Text");
165 params.direction = blink::WebTextDirectionDefault;
166 return params;
167 }
168
169 TEST_F(DesktopNotificationsTest, TestShow) {
170 content::ShowDesktopNotificationHostMsgParams params =
171 StandardTestNotification();
172 params.notification_id = 1;
173
174 EXPECT_TRUE(service_->ShowDesktopNotification(
175 params, 0, 0, DesktopNotificationService::PageNotification));
176 base::MessageLoopForUI::current()->RunUntilIdle();
177 EXPECT_EQ(1, balloon_collection_->count());
178
179 content::ShowDesktopNotificationHostMsgParams params2 =
180 StandardTestNotification();
181 params2.notification_id = 2;
182 params2.origin = GURL("http://www.google.com");
183 params2.body = base::ASCIIToUTF16("Text");
184
185 EXPECT_TRUE(service_->ShowDesktopNotification(
186 params2, 0, 0, DesktopNotificationService::PageNotification));
187 base::MessageLoopForUI::current()->RunUntilIdle();
188 EXPECT_EQ(2, balloon_collection_->count());
189
190 EXPECT_EQ("notification displayed\n"
191 "notification displayed\n",
192 log_output_);
193 }
194
195 TEST_F(DesktopNotificationsTest, TestClose) {
196 content::ShowDesktopNotificationHostMsgParams params =
197 StandardTestNotification();
198 params.notification_id = 1;
199
200 // Request a notification; should open a balloon.
201 EXPECT_TRUE(service_->ShowDesktopNotification(
202 params, 0, 0, DesktopNotificationService::PageNotification));
203 base::MessageLoopForUI::current()->RunUntilIdle();
204 EXPECT_EQ(1, balloon_collection_->count());
205
206 // Close all the open balloons.
207 while (balloon_collection_->count() > 0) {
208 (*(balloon_collection_->GetActiveBalloons().begin()))->OnClose(true);
209 }
210
211 EXPECT_EQ("notification displayed\n"
212 "notification closed by user\n",
213 log_output_);
214 }
215
216 TEST_F(DesktopNotificationsTest, TestCancel) {
217 int process_id = 0;
218 int route_id = 0;
219 int notification_id = 1;
220
221 content::ShowDesktopNotificationHostMsgParams params =
222 StandardTestNotification();
223 params.notification_id = notification_id;
224
225 // Request a notification; should open a balloon.
226 EXPECT_TRUE(service_->ShowDesktopNotification(
227 params, process_id, route_id,
228 DesktopNotificationService::PageNotification));
229 base::MessageLoopForUI::current()->RunUntilIdle();
230 EXPECT_EQ(1, balloon_collection_->count());
231
232 // Cancel the same notification
233 service_->CancelDesktopNotification(process_id,
234 route_id,
235 notification_id);
236 base::MessageLoopForUI::current()->RunUntilIdle();
237 // Verify that the balloon collection is now empty.
238 EXPECT_EQ(0, balloon_collection_->count());
239
240 EXPECT_EQ("notification displayed\n"
241 "notification closed by script\n",
242 log_output_);
243 }
244
245 #if defined(OS_WIN) || defined(TOOLKIT_VIEWS)
246 TEST_F(DesktopNotificationsTest, TestPositioning) {
247 content::ShowDesktopNotificationHostMsgParams params =
248 StandardTestNotification();
249 std::string expected_log;
250 // Create some toasts. After each but the first, make sure there
251 // is a minimum separation between the toasts.
252 int last_top = 0;
253 for (int id = 0; id <= 3; ++id) {
254 params.notification_id = id;
255 EXPECT_TRUE(service_->ShowDesktopNotification(
256 params, 0, 0, DesktopNotificationService::PageNotification));
257 expected_log.append("notification displayed\n");
258 int top = balloon_collection_->UppermostVerticalPosition();
259 if (id > 0)
260 EXPECT_LE(top, last_top - balloon_collection_->MinHeight());
261 last_top = top;
262 }
263
264 EXPECT_EQ(expected_log, log_output_);
265 }
266
267 TEST_F(DesktopNotificationsTest, TestVariableSize) {
268 content::ShowDesktopNotificationHostMsgParams params;
269 params.origin = GURL("http://long.google.com");
270 params.icon_url = GURL("/icon.png");
271 params.title = base::ASCIIToUTF16("Really Really Really Really Really Really "
272 "Really Really Really Really Really Really "
273 "Really Really Really Really Really Really "
274 "Really Long Title"),
275 params.body = base::ASCIIToUTF16("Text");
276 params.notification_id = 0;
277
278 std::string expected_log;
279 // Create some toasts. After each but the first, make sure there
280 // is a minimum separation between the toasts.
281 EXPECT_TRUE(service_->ShowDesktopNotification(
282 params, 0, 0, DesktopNotificationService::PageNotification));
283 expected_log.append("notification displayed\n");
284
285 params.origin = GURL("http://short.google.com");
286 params.title = base::ASCIIToUTF16("Short title");
287 params.notification_id = 1;
288 EXPECT_TRUE(service_->ShowDesktopNotification(
289 params, 0, 0, DesktopNotificationService::PageNotification));
290 expected_log.append("notification displayed\n");
291
292 std::deque<Balloon*>& balloons = balloon_collection_->balloons();
293 std::deque<Balloon*>::iterator iter;
294 for (iter = balloons.begin(); iter != balloons.end(); ++iter) {
295 if ((*iter)->notification().origin_url().host() == "long.google.com") {
296 EXPECT_GE((*iter)->GetViewSize().height(),
297 balloon_collection_->MinHeight());
298 EXPECT_LE((*iter)->GetViewSize().height(),
299 balloon_collection_->MaxHeight());
300 } else {
301 EXPECT_EQ((*iter)->GetViewSize().height(),
302 balloon_collection_->MinHeight());
303 }
304 }
305 EXPECT_EQ(expected_log, log_output_);
306 }
307 #endif
308
309 TEST_F(DesktopNotificationsTest, TestCancelByProfile) {
310 int process_id = 0;
311 int route_id = 0;
312
313 TestingBrowserProcess* browser_process =
314 TestingBrowserProcess::GetGlobal();
315 TestingProfileManager profile_manager(browser_process);
316 ASSERT_TRUE(profile_manager.SetUp());
317
318 TestingProfile* second_profile =
319 profile_manager.CreateTestingProfile("SecondTestingProfile");
320
321 scoped_ptr<DesktopNotificationService> second_service(
322 new DesktopNotificationService(second_profile, ui_manager_.get()));
323
324 // Request lots of identical notifications.
325 content::ShowDesktopNotificationHostMsgParams params =
326 StandardTestNotification();
327 params.notification_id = 1;
328 // Notice that the first one is the only one that doesn't use
329 // the second profile.
330 EXPECT_TRUE(service_->ShowDesktopNotification(
331 params, process_id, route_id,
332 DesktopNotificationService::PageNotification));
333
334 // |kLotsOfToasts| must be large enough to trigger a resize of the underlying
335 // std::deque while we're clearing it.
336 const int kLotsOfToasts = 20;
337 for (int id = 2; id <= kLotsOfToasts; ++id) {
338 params.notification_id = id;
339 EXPECT_TRUE(second_service->ShowDesktopNotification(
340 params, process_id, route_id,
341 DesktopNotificationService::PageNotification));
342 }
343 base::MessageLoopForUI::current()->RunUntilIdle();
344
345 ui_manager_->CancelAllByProfile(second_profile);
346
347 // Verify that the balloon collection only contains the single
348 // notification from the first profile.
349 EXPECT_EQ(1, balloon_collection_->count());
350 }
351
352 TEST_F(DesktopNotificationsTest, TestCancelBySourceOrigin) {
353 int process_id = 0;
354 int route_id = 0;
355
356 // Request lots of identical notifications.
357 content::ShowDesktopNotificationHostMsgParams params =
358 StandardTestNotification();
359
360 // After the first, all the notifications are from attacker.com.
361 content::ShowDesktopNotificationHostMsgParams odd_params =
362 StandardTestNotification();
363 odd_params.origin = GURL("attacker.com");
364
365 // Show the only non-attacker.com notification.
366 params.notification_id = 1;
367 EXPECT_TRUE(service_->ShowDesktopNotification(
368 params, process_id, route_id,
369 DesktopNotificationService::PageNotification));
370
371 // |kLotsOfToasts| must be large enough to trigger a resize of the underlying
372 // std::deque while we're clearing it.
373 const int kLotsOfToasts = 20;
374 for (int id = 2; id <= kLotsOfToasts; ++id) {
375 odd_params.notification_id = id;
376 EXPECT_TRUE(service_->ShowDesktopNotification(
377 odd_params, process_id, route_id,
378 DesktopNotificationService::PageNotification));
379 }
380 base::MessageLoopForUI::current()->RunUntilIdle();
381
382 ui_manager_->CancelAllBySourceOrigin(odd_params.origin);
383
384 // Verify that the balloon collection only contains the single
385 // notification which is not from the canceled origin.
386 EXPECT_EQ(1, balloon_collection_->count());
387 }
388
389 TEST_F(DesktopNotificationsTest, TestQueueing) {
390 int process_id = 0;
391 int route_id = 0;
392
393 // Request lots of identical notifications.
394 content::ShowDesktopNotificationHostMsgParams params =
395 StandardTestNotification();
396 const int kLotsOfToasts = 20;
397 for (int id = 1; id <= kLotsOfToasts; ++id) {
398 params.notification_id = id;
399 EXPECT_TRUE(service_->ShowDesktopNotification(
400 params, process_id, route_id,
401 DesktopNotificationService::PageNotification));
402 }
403 base::MessageLoopForUI::current()->RunUntilIdle();
404
405 // Build up an expected log of what should be happening.
406 std::string expected_log;
407 for (int i = 0; i < balloon_collection_->max_balloon_count(); ++i) {
408 expected_log.append("notification displayed\n");
409 }
410
411 // The max number that our balloon collection can hold should be
412 // shown.
413 EXPECT_EQ(balloon_collection_->max_balloon_count(),
414 balloon_collection_->count());
415 EXPECT_EQ(expected_log, log_output_);
416
417 // Cancel the notifications from the start; the balloon space should
418 // remain full.
419 {
420 int id;
421 for (id = 1;
422 id <= kLotsOfToasts - balloon_collection_->max_balloon_count();
423 ++id) {
424 service_->CancelDesktopNotification(process_id, route_id, id);
425 base::MessageLoopForUI::current()->RunUntilIdle();
426 expected_log.append("notification closed by script\n");
427 expected_log.append("notification displayed\n");
428 EXPECT_EQ(balloon_collection_->max_balloon_count(),
429 balloon_collection_->count());
430 EXPECT_EQ(expected_log, log_output_);
431 }
432
433 // Now cancel the rest. It should empty the balloon space.
434 for (; id <= kLotsOfToasts; ++id) {
435 service_->CancelDesktopNotification(process_id, route_id, id);
436 expected_log.append("notification closed by script\n");
437 base::MessageLoopForUI::current()->RunUntilIdle();
438 EXPECT_EQ(expected_log, log_output_);
439 }
440 }
441
442 // Verify that the balloon collection is now empty.
443 EXPECT_EQ(0, balloon_collection_->count());
444 }
445
446 TEST_F(DesktopNotificationsTest, TestEarlyDestruction) {
447 // Create some toasts and then prematurely delete the notification service,
448 // just to make sure nothing crashes/leaks.
449 content::ShowDesktopNotificationHostMsgParams params =
450 StandardTestNotification();
451 for (int id = 0; id <= 3; ++id) {
452 params.notification_id = id;
453 EXPECT_TRUE(service_->ShowDesktopNotification(
454 params, 0, 0, DesktopNotificationService::PageNotification));
455 }
456 service_.reset(NULL);
457 }
458
459 TEST_F(DesktopNotificationsTest, TestUserInputEscaping) {
460 // Create a test script with some HTML; assert that it doesn't get into the
461 // data:// URL that's produced for the balloon.
462 content::ShowDesktopNotificationHostMsgParams params =
463 StandardTestNotification();
464 params.title = base::ASCIIToUTF16("<script>window.alert('uh oh');</script>");
465 params.body = base::ASCIIToUTF16("<i>this text is in italics</i>");
466 params.notification_id = 1;
467 EXPECT_TRUE(service_->ShowDesktopNotification(
468 params, 0, 0, DesktopNotificationService::PageNotification));
469
470 base::MessageLoopForUI::current()->RunUntilIdle();
471 EXPECT_EQ(1, balloon_collection_->count());
472 Balloon* balloon = (*balloon_collection_->balloons().begin());
473 GURL data_url = balloon->notification().content_url();
474 EXPECT_EQ(std::string::npos, data_url.spec().find("<script>"));
475 EXPECT_EQ(std::string::npos, data_url.spec().find("<i>"));
476 // URL-encoded versions of tags should also not be found.
477 EXPECT_EQ(std::string::npos, data_url.spec().find("%3cscript%3e"));
478 EXPECT_EQ(std::string::npos, data_url.spec().find("%3ci%3e"));
479 }
480
481 TEST_F(DesktopNotificationsTest, TestBoundingBox) {
482 // Create some notifications.
483 content::ShowDesktopNotificationHostMsgParams params =
484 StandardTestNotification();
485 for (int id = 0; id <= 3; ++id) {
486 params.notification_id = id;
487 EXPECT_TRUE(service_->ShowDesktopNotification(
488 params, 0, 0, DesktopNotificationService::PageNotification));
489 }
490
491 gfx::Rect box = balloon_collection_->GetBalloonsBoundingBox();
492
493 // Try this for all positions.
494 BalloonCollection::PositionPreference pref;
495 for (pref = BalloonCollection::UPPER_RIGHT;
496 pref <= BalloonCollection::LOWER_LEFT;
497 pref = static_cast<BalloonCollection::PositionPreference>(pref + 1)) {
498 // Make sure each balloon's 4 corners are inside the box.
499 std::deque<Balloon*>& balloons = balloon_collection_->balloons();
500 std::deque<Balloon*>::iterator iter;
501 for (iter = balloons.begin(); iter != balloons.end(); ++iter) {
502 int min_x = (*iter)->GetPosition().x();
503 int max_x = min_x + (*iter)->GetViewSize().width() - 1;
504 int min_y = (*iter)->GetPosition().y();
505 int max_y = min_y + (*iter)->GetViewSize().height() - 1;
506
507 EXPECT_TRUE(box.Contains(gfx::Point(min_x, min_y)));
508 EXPECT_TRUE(box.Contains(gfx::Point(min_x, max_y)));
509 EXPECT_TRUE(box.Contains(gfx::Point(max_x, min_y)));
510 EXPECT_TRUE(box.Contains(gfx::Point(max_x, max_y)));
511 }
512 }
513 }
514
515 TEST_F(DesktopNotificationsTest, TestPositionPreference) {
516 // Set position preference to lower right.
517 local_state_.SetInteger(prefs::kDesktopNotificationPosition,
518 BalloonCollection::LOWER_RIGHT);
519
520 // Create some notifications.
521 content::ShowDesktopNotificationHostMsgParams params =
522 StandardTestNotification();
523 for (int id = 0; id <= 3; ++id) {
524 params.notification_id = id;
525 EXPECT_TRUE(service_->ShowDesktopNotification(
526 params, 0, 0, DesktopNotificationService::PageNotification));
527 }
528
529 std::deque<Balloon*>& balloons = balloon_collection_->balloons();
530 std::deque<Balloon*>::iterator iter;
531
532 // Check that they decrease in y-position (for MAC, with reversed
533 // coordinates, they should increase).
534 int last_y = -1;
535 int last_x = -1;
536
537 for (iter = balloons.begin(); iter != balloons.end(); ++iter) {
538 int current_x = (*iter)->GetPosition().x();
539 int current_y = (*iter)->GetPosition().y();
540 if (last_x > 0)
541 EXPECT_EQ(last_x, current_x);
542
543 if (last_y > 0) {
544 #if defined(OS_MACOSX)
545 EXPECT_GT(current_y, last_y);
546 #else
547 EXPECT_LT(current_y, last_y);
548 #endif
549 }
550
551 last_x = current_x;
552 last_y = current_y;
553 }
554
555 // Now change the position to upper right. This should cause an immediate
556 // repositioning, and we check for the reverse ordering.
557 local_state_.SetInteger(prefs::kDesktopNotificationPosition,
558 BalloonCollection::UPPER_RIGHT);
559 last_x = -1;
560 last_y = -1;
561
562 for (iter = balloons.begin(); iter != balloons.end(); ++iter) {
563 int current_x = (*iter)->GetPosition().x();
564 int current_y = (*iter)->GetPosition().y();
565
566 if (last_x > 0)
567 EXPECT_EQ(last_x, current_x);
568
569 if (last_y > 0) {
570 #if defined(OS_MACOSX)
571 EXPECT_LT(current_y, last_y);
572 #else
573 EXPECT_GT(current_y, last_y);
574 #endif
575 }
576
577 last_x = current_x;
578 last_y = current_y;
579 }
580
581 // Now change the position to upper left. Confirm that the X value for the
582 // balloons gets smaller.
583 local_state_.SetInteger(prefs::kDesktopNotificationPosition,
584 BalloonCollection::UPPER_LEFT);
585
586 int current_x = (*balloons.begin())->GetPosition().x();
587 EXPECT_LT(current_x, last_x);
588 }
OLDNEW
« no previous file with comments | « chrome/browser/notifications/desktop_notifications_unittest.h ('k') | chrome/browser/notifications/fake_balloon_view.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698