| 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/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 } | |
| OLD | NEW |