Index: chrome/browser/notifications/desktop_notifications_unittest.cc |
=================================================================== |
--- chrome/browser/notifications/desktop_notifications_unittest.cc (revision 263121) |
+++ chrome/browser/notifications/desktop_notifications_unittest.cc (working copy) |
@@ -1,588 +0,0 @@ |
-// Copyright (c) 2012 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/notifications/desktop_notifications_unittest.h" |
- |
-#include "base/prefs/testing_pref_service.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "chrome/browser/notifications/balloon_notification_ui_manager.h" |
-#include "chrome/browser/notifications/fake_balloon_view.h" |
-#include "chrome/browser/prefs/browser_prefs.h" |
-#include "chrome/common/pref_names.h" |
-#include "chrome/test/base/chrome_unit_test_suite.h" |
-#include "chrome/test/base/testing_browser_process.h" |
-#include "chrome/test/base/testing_profile.h" |
-#include "chrome/test/base/testing_profile_manager.h" |
-#include "content/public/common/show_desktop_notification_params.h" |
-#include "ui/base/ime/input_method_initializer.h" |
-#include "ui/gl/gl_surface.h" |
-#include "ui/message_center/message_center.h" |
- |
-#if defined(USE_ASH) |
-#include "ash/shell.h" |
-#include "ash/test/test_shell_delegate.h" |
-#include "ui/aura/env.h" |
-#include "ui/aura/window_event_dispatcher.h" |
-#include "ui/compositor/scoped_animation_duration_scale_mode.h" |
-#include "ui/compositor/test/context_factories_for_test.h" |
-#endif |
- |
-#if defined(USE_AURA) |
-#include "ui/wm/core/wm_state.h" |
-#endif |
- |
- |
-using content::BrowserThread; |
- |
-// static |
-const int MockBalloonCollection::kMockBalloonSpace = 5; |
- |
-// static |
-std::string DesktopNotificationsTest::log_output_; |
- |
-MockBalloonCollection::MockBalloonCollection() {} |
- |
-MockBalloonCollection::~MockBalloonCollection() {} |
- |
-void MockBalloonCollection::Add(const Notification& notification, |
- Profile* profile) { |
- // Swap in a logging proxy for the purpose of logging calls that |
- // would be made into javascript, then pass this down to the |
- // balloon collection. |
- Notification test_notification( |
- notification.origin_url(), |
- notification.content_url(), |
- notification.display_source(), |
- notification.replace_id(), |
- new LoggingNotificationProxy(notification.notification_id())); |
- BalloonCollectionImpl::Add(test_notification, profile); |
-} |
- |
-bool MockBalloonCollection::HasSpace() const { |
- return count() < kMockBalloonSpace; |
-} |
- |
-Balloon* MockBalloonCollection::MakeBalloon(const Notification& notification, |
- Profile* profile) { |
- // Start with a normal balloon but mock out the view. |
- Balloon* balloon = BalloonCollectionImpl::MakeBalloon(notification, profile); |
- balloon->set_view(new FakeBalloonView(balloon)); |
- balloons_.push_back(balloon); |
- return balloon; |
-} |
- |
-void MockBalloonCollection::OnBalloonClosed(Balloon* source) { |
- std::deque<Balloon*>::iterator it; |
- for (it = balloons_.begin(); it != balloons_.end(); ++it) { |
- if (*it == source) { |
- balloons_.erase(it); |
- BalloonCollectionImpl::OnBalloonClosed(source); |
- break; |
- } |
- } |
-} |
- |
-const BalloonCollection::Balloons& MockBalloonCollection::GetActiveBalloons() { |
- return balloons_; |
-} |
- |
-int MockBalloonCollection::UppermostVerticalPosition() { |
- int min = 0; |
- std::deque<Balloon*>::iterator iter; |
- for (iter = balloons_.begin(); iter != balloons_.end(); ++iter) { |
- int pos = (*iter)->GetPosition().y(); |
- if (iter == balloons_.begin() || pos < min) |
- min = pos; |
- } |
- return min; |
-} |
- |
-DesktopNotificationsTest::DesktopNotificationsTest() |
- : ui_thread_(BrowserThread::UI, &message_loop_), |
- balloon_collection_(NULL) { |
-} |
- |
-DesktopNotificationsTest::~DesktopNotificationsTest() { |
-} |
- |
-void DesktopNotificationsTest::SetUp() { |
- ChromeUnitTestSuite::InitializeProviders(); |
- ChromeUnitTestSuite::InitializeResourceBundle(); |
- ui::InitializeInputMethodForTesting(); |
-#if defined(USE_AURA) |
- wm_state_.reset(new wm::WMState); |
-#endif |
-#if defined(USE_ASH) |
- ui::ScopedAnimationDurationScaleMode normal_duration_mode( |
- ui::ScopedAnimationDurationScaleMode::ZERO_DURATION); |
- // The message center is notmally initialized on |g_browser_process| which |
- // is not created for these tests. |
- message_center::MessageCenter::Initialize(); |
- // The ContextFactory must exist before any Compositors are created. |
- bool enable_pixel_output = false; |
- ui::InitializeContextFactoryForTests(enable_pixel_output); |
- // MockBalloonCollection retrieves information about the screen on creation. |
- // So it is necessary to make sure the desktop gets created first. |
- ash::Shell::CreateInstance(new ash::test::TestShellDelegate); |
-#endif |
- chrome::RegisterLocalState(local_state_.registry()); |
- profile_.reset(new TestingProfile()); |
- ui_manager_.reset(new BalloonNotificationUIManager(&local_state_)); |
- balloon_collection_ = new MockBalloonCollection(); |
- ui_manager_->SetBalloonCollection(balloon_collection_); |
- service_.reset(new DesktopNotificationService(profile(), ui_manager_.get())); |
- log_output_.clear(); |
-} |
- |
-void DesktopNotificationsTest::TearDown() { |
- service_.reset(NULL); |
- ui_manager_.reset(NULL); |
- profile_.reset(NULL); |
-#if defined(USE_ASH) |
- ash::Shell::DeleteInstance(); |
- // The message center is notmally shutdown on |g_browser_process| which |
- // is not created for these tests. |
- message_center::MessageCenter::Shutdown(); |
- aura::Env::DeleteInstance(); |
- ui::TerminateContextFactoryForTests(); |
-#endif |
-#if defined(USE_AURA) |
- wm_state_.reset(); |
-#endif |
- ui::ShutdownInputMethodForTesting(); |
-} |
- |
-content::ShowDesktopNotificationHostMsgParams |
-DesktopNotificationsTest::StandardTestNotification() { |
- content::ShowDesktopNotificationHostMsgParams params; |
- params.notification_id = 0; |
- params.origin = GURL("http://www.google.com"); |
- params.icon_url = GURL("/icon.png"); |
- params.title = base::ASCIIToUTF16("Title"); |
- params.body = base::ASCIIToUTF16("Text"); |
- params.direction = blink::WebTextDirectionDefault; |
- return params; |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestShow) { |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- params.notification_id = 1; |
- |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- EXPECT_EQ(1, balloon_collection_->count()); |
- |
- content::ShowDesktopNotificationHostMsgParams params2 = |
- StandardTestNotification(); |
- params2.notification_id = 2; |
- params2.origin = GURL("http://www.google.com"); |
- params2.body = base::ASCIIToUTF16("Text"); |
- |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params2, 0, 0, DesktopNotificationService::PageNotification)); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- EXPECT_EQ(2, balloon_collection_->count()); |
- |
- EXPECT_EQ("notification displayed\n" |
- "notification displayed\n", |
- log_output_); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestClose) { |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- params.notification_id = 1; |
- |
- // Request a notification; should open a balloon. |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- EXPECT_EQ(1, balloon_collection_->count()); |
- |
- // Close all the open balloons. |
- while (balloon_collection_->count() > 0) { |
- (*(balloon_collection_->GetActiveBalloons().begin()))->OnClose(true); |
- } |
- |
- EXPECT_EQ("notification displayed\n" |
- "notification closed by user\n", |
- log_output_); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestCancel) { |
- int process_id = 0; |
- int route_id = 0; |
- int notification_id = 1; |
- |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- params.notification_id = notification_id; |
- |
- // Request a notification; should open a balloon. |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, process_id, route_id, |
- DesktopNotificationService::PageNotification)); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- EXPECT_EQ(1, balloon_collection_->count()); |
- |
- // Cancel the same notification |
- service_->CancelDesktopNotification(process_id, |
- route_id, |
- notification_id); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- // Verify that the balloon collection is now empty. |
- EXPECT_EQ(0, balloon_collection_->count()); |
- |
- EXPECT_EQ("notification displayed\n" |
- "notification closed by script\n", |
- log_output_); |
-} |
- |
-#if defined(OS_WIN) || defined(TOOLKIT_VIEWS) |
-TEST_F(DesktopNotificationsTest, TestPositioning) { |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- std::string expected_log; |
- // Create some toasts. After each but the first, make sure there |
- // is a minimum separation between the toasts. |
- int last_top = 0; |
- for (int id = 0; id <= 3; ++id) { |
- params.notification_id = id; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- expected_log.append("notification displayed\n"); |
- int top = balloon_collection_->UppermostVerticalPosition(); |
- if (id > 0) |
- EXPECT_LE(top, last_top - balloon_collection_->MinHeight()); |
- last_top = top; |
- } |
- |
- EXPECT_EQ(expected_log, log_output_); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestVariableSize) { |
- content::ShowDesktopNotificationHostMsgParams params; |
- params.origin = GURL("http://long.google.com"); |
- params.icon_url = GURL("/icon.png"); |
- params.title = base::ASCIIToUTF16("Really Really Really Really Really Really " |
- "Really Really Really Really Really Really " |
- "Really Really Really Really Really Really " |
- "Really Long Title"), |
- params.body = base::ASCIIToUTF16("Text"); |
- params.notification_id = 0; |
- |
- std::string expected_log; |
- // Create some toasts. After each but the first, make sure there |
- // is a minimum separation between the toasts. |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- expected_log.append("notification displayed\n"); |
- |
- params.origin = GURL("http://short.google.com"); |
- params.title = base::ASCIIToUTF16("Short title"); |
- params.notification_id = 1; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- expected_log.append("notification displayed\n"); |
- |
- std::deque<Balloon*>& balloons = balloon_collection_->balloons(); |
- std::deque<Balloon*>::iterator iter; |
- for (iter = balloons.begin(); iter != balloons.end(); ++iter) { |
- if ((*iter)->notification().origin_url().host() == "long.google.com") { |
- EXPECT_GE((*iter)->GetViewSize().height(), |
- balloon_collection_->MinHeight()); |
- EXPECT_LE((*iter)->GetViewSize().height(), |
- balloon_collection_->MaxHeight()); |
- } else { |
- EXPECT_EQ((*iter)->GetViewSize().height(), |
- balloon_collection_->MinHeight()); |
- } |
- } |
- EXPECT_EQ(expected_log, log_output_); |
-} |
-#endif |
- |
-TEST_F(DesktopNotificationsTest, TestCancelByProfile) { |
- int process_id = 0; |
- int route_id = 0; |
- |
- TestingBrowserProcess* browser_process = |
- TestingBrowserProcess::GetGlobal(); |
- TestingProfileManager profile_manager(browser_process); |
- ASSERT_TRUE(profile_manager.SetUp()); |
- |
- TestingProfile* second_profile = |
- profile_manager.CreateTestingProfile("SecondTestingProfile"); |
- |
- scoped_ptr<DesktopNotificationService> second_service( |
- new DesktopNotificationService(second_profile, ui_manager_.get())); |
- |
- // Request lots of identical notifications. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- params.notification_id = 1; |
- // Notice that the first one is the only one that doesn't use |
- // the second profile. |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, process_id, route_id, |
- DesktopNotificationService::PageNotification)); |
- |
- // |kLotsOfToasts| must be large enough to trigger a resize of the underlying |
- // std::deque while we're clearing it. |
- const int kLotsOfToasts = 20; |
- for (int id = 2; id <= kLotsOfToasts; ++id) { |
- params.notification_id = id; |
- EXPECT_TRUE(second_service->ShowDesktopNotification( |
- params, process_id, route_id, |
- DesktopNotificationService::PageNotification)); |
- } |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- |
- ui_manager_->CancelAllByProfile(second_profile); |
- |
- // Verify that the balloon collection only contains the single |
- // notification from the first profile. |
- EXPECT_EQ(1, balloon_collection_->count()); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestCancelBySourceOrigin) { |
- int process_id = 0; |
- int route_id = 0; |
- |
- // Request lots of identical notifications. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- |
- // After the first, all the notifications are from attacker.com. |
- content::ShowDesktopNotificationHostMsgParams odd_params = |
- StandardTestNotification(); |
- odd_params.origin = GURL("attacker.com"); |
- |
- // Show the only non-attacker.com notification. |
- params.notification_id = 1; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, process_id, route_id, |
- DesktopNotificationService::PageNotification)); |
- |
- // |kLotsOfToasts| must be large enough to trigger a resize of the underlying |
- // std::deque while we're clearing it. |
- const int kLotsOfToasts = 20; |
- for (int id = 2; id <= kLotsOfToasts; ++id) { |
- odd_params.notification_id = id; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- odd_params, process_id, route_id, |
- DesktopNotificationService::PageNotification)); |
- } |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- |
- ui_manager_->CancelAllBySourceOrigin(odd_params.origin); |
- |
- // Verify that the balloon collection only contains the single |
- // notification which is not from the canceled origin. |
- EXPECT_EQ(1, balloon_collection_->count()); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestQueueing) { |
- int process_id = 0; |
- int route_id = 0; |
- |
- // Request lots of identical notifications. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- const int kLotsOfToasts = 20; |
- for (int id = 1; id <= kLotsOfToasts; ++id) { |
- params.notification_id = id; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, process_id, route_id, |
- DesktopNotificationService::PageNotification)); |
- } |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- |
- // Build up an expected log of what should be happening. |
- std::string expected_log; |
- for (int i = 0; i < balloon_collection_->max_balloon_count(); ++i) { |
- expected_log.append("notification displayed\n"); |
- } |
- |
- // The max number that our balloon collection can hold should be |
- // shown. |
- EXPECT_EQ(balloon_collection_->max_balloon_count(), |
- balloon_collection_->count()); |
- EXPECT_EQ(expected_log, log_output_); |
- |
- // Cancel the notifications from the start; the balloon space should |
- // remain full. |
- { |
- int id; |
- for (id = 1; |
- id <= kLotsOfToasts - balloon_collection_->max_balloon_count(); |
- ++id) { |
- service_->CancelDesktopNotification(process_id, route_id, id); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- expected_log.append("notification closed by script\n"); |
- expected_log.append("notification displayed\n"); |
- EXPECT_EQ(balloon_collection_->max_balloon_count(), |
- balloon_collection_->count()); |
- EXPECT_EQ(expected_log, log_output_); |
- } |
- |
- // Now cancel the rest. It should empty the balloon space. |
- for (; id <= kLotsOfToasts; ++id) { |
- service_->CancelDesktopNotification(process_id, route_id, id); |
- expected_log.append("notification closed by script\n"); |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- EXPECT_EQ(expected_log, log_output_); |
- } |
- } |
- |
- // Verify that the balloon collection is now empty. |
- EXPECT_EQ(0, balloon_collection_->count()); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestEarlyDestruction) { |
- // Create some toasts and then prematurely delete the notification service, |
- // just to make sure nothing crashes/leaks. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- for (int id = 0; id <= 3; ++id) { |
- params.notification_id = id; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- } |
- service_.reset(NULL); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestUserInputEscaping) { |
- // Create a test script with some HTML; assert that it doesn't get into the |
- // data:// URL that's produced for the balloon. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- params.title = base::ASCIIToUTF16("<script>window.alert('uh oh');</script>"); |
- params.body = base::ASCIIToUTF16("<i>this text is in italics</i>"); |
- params.notification_id = 1; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- |
- base::MessageLoopForUI::current()->RunUntilIdle(); |
- EXPECT_EQ(1, balloon_collection_->count()); |
- Balloon* balloon = (*balloon_collection_->balloons().begin()); |
- GURL data_url = balloon->notification().content_url(); |
- EXPECT_EQ(std::string::npos, data_url.spec().find("<script>")); |
- EXPECT_EQ(std::string::npos, data_url.spec().find("<i>")); |
- // URL-encoded versions of tags should also not be found. |
- EXPECT_EQ(std::string::npos, data_url.spec().find("%3cscript%3e")); |
- EXPECT_EQ(std::string::npos, data_url.spec().find("%3ci%3e")); |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestBoundingBox) { |
- // Create some notifications. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- for (int id = 0; id <= 3; ++id) { |
- params.notification_id = id; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- } |
- |
- gfx::Rect box = balloon_collection_->GetBalloonsBoundingBox(); |
- |
- // Try this for all positions. |
- BalloonCollection::PositionPreference pref; |
- for (pref = BalloonCollection::UPPER_RIGHT; |
- pref <= BalloonCollection::LOWER_LEFT; |
- pref = static_cast<BalloonCollection::PositionPreference>(pref + 1)) { |
- // Make sure each balloon's 4 corners are inside the box. |
- std::deque<Balloon*>& balloons = balloon_collection_->balloons(); |
- std::deque<Balloon*>::iterator iter; |
- for (iter = balloons.begin(); iter != balloons.end(); ++iter) { |
- int min_x = (*iter)->GetPosition().x(); |
- int max_x = min_x + (*iter)->GetViewSize().width() - 1; |
- int min_y = (*iter)->GetPosition().y(); |
- int max_y = min_y + (*iter)->GetViewSize().height() - 1; |
- |
- EXPECT_TRUE(box.Contains(gfx::Point(min_x, min_y))); |
- EXPECT_TRUE(box.Contains(gfx::Point(min_x, max_y))); |
- EXPECT_TRUE(box.Contains(gfx::Point(max_x, min_y))); |
- EXPECT_TRUE(box.Contains(gfx::Point(max_x, max_y))); |
- } |
- } |
-} |
- |
-TEST_F(DesktopNotificationsTest, TestPositionPreference) { |
- // Set position preference to lower right. |
- local_state_.SetInteger(prefs::kDesktopNotificationPosition, |
- BalloonCollection::LOWER_RIGHT); |
- |
- // Create some notifications. |
- content::ShowDesktopNotificationHostMsgParams params = |
- StandardTestNotification(); |
- for (int id = 0; id <= 3; ++id) { |
- params.notification_id = id; |
- EXPECT_TRUE(service_->ShowDesktopNotification( |
- params, 0, 0, DesktopNotificationService::PageNotification)); |
- } |
- |
- std::deque<Balloon*>& balloons = balloon_collection_->balloons(); |
- std::deque<Balloon*>::iterator iter; |
- |
- // Check that they decrease in y-position (for MAC, with reversed |
- // coordinates, they should increase). |
- int last_y = -1; |
- int last_x = -1; |
- |
- for (iter = balloons.begin(); iter != balloons.end(); ++iter) { |
- int current_x = (*iter)->GetPosition().x(); |
- int current_y = (*iter)->GetPosition().y(); |
- if (last_x > 0) |
- EXPECT_EQ(last_x, current_x); |
- |
- if (last_y > 0) { |
-#if defined(OS_MACOSX) |
- EXPECT_GT(current_y, last_y); |
-#else |
- EXPECT_LT(current_y, last_y); |
-#endif |
- } |
- |
- last_x = current_x; |
- last_y = current_y; |
- } |
- |
- // Now change the position to upper right. This should cause an immediate |
- // repositioning, and we check for the reverse ordering. |
- local_state_.SetInteger(prefs::kDesktopNotificationPosition, |
- BalloonCollection::UPPER_RIGHT); |
- last_x = -1; |
- last_y = -1; |
- |
- for (iter = balloons.begin(); iter != balloons.end(); ++iter) { |
- int current_x = (*iter)->GetPosition().x(); |
- int current_y = (*iter)->GetPosition().y(); |
- |
- if (last_x > 0) |
- EXPECT_EQ(last_x, current_x); |
- |
- if (last_y > 0) { |
-#if defined(OS_MACOSX) |
- EXPECT_LT(current_y, last_y); |
-#else |
- EXPECT_GT(current_y, last_y); |
-#endif |
- } |
- |
- last_x = current_x; |
- last_y = current_y; |
- } |
- |
- // Now change the position to upper left. Confirm that the X value for the |
- // balloons gets smaller. |
- local_state_.SetInteger(prefs::kDesktopNotificationPosition, |
- BalloonCollection::UPPER_LEFT); |
- |
- int current_x = (*balloons.begin())->GetPosition().x(); |
- EXPECT_LT(current_x, last_x); |
-} |