15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be 35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file. 45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/cocoa/apps/quit_with_apps_controller_mac.h" 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/command_line.h" 8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/run_loop.h" 95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/apps/app_browsertest_util.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/apps/app_window_registry_util.h" 115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/browser_process.h" 12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "chrome/browser/chrome_browser_application_mac.h" 135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/extensions/extension_service.h" 145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/lifetime/application_lifetime.h" 155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/notifications/message_center_notification_manager.h" 165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/notifications/notification_ui_manager.h" 175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/profiles/profile.h" 185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/browser_iterator.h" 195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/browser/ui/browser_window.h" 205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/common/chrome_switches.h" 215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/browser/notification_service.h" 225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "content/public/test/test_utils.h" 235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "extensions/common/extension.h" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "extensions/test/extension_test_message_listener.h" 255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "ui/message_center/message_center.h" 265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace { 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass QuitWithAppsControllerInteractiveTest 305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu : public extensions::PlatformAppBrowserTest { 315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu protected: 325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu QuitWithAppsControllerInteractiveTest() : app_(NULL) {} 335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual ~QuitWithAppsControllerInteractiveTest() {} 355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu PlatformAppBrowserTest::SetUpCommandLine(command_line); 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch command_line->AppendSwitch(switches::kAppsKeepChromeAliveInTests); 395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const extensions::Extension* app_; 425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu private: 445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DISALLOW_COPY_AND_ASSIGN(QuitWithAppsControllerInteractiveTest); 455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}; 465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} // namespace 485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Test that quitting while apps are open shows a notification instead. 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuIN_PROC_BROWSER_TEST_F(QuitWithAppsControllerInteractiveTest, QuitBehavior) { 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu scoped_refptr<QuitWithAppsController> controller = 525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu new QuitWithAppsController(); 535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const Notification* notification; 545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_center::MessageCenter* message_center = 555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_center::MessageCenter::Get(); 56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // With no app windows open, ShouldQuit returns true. 58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_TRUE(controller->ShouldQuit()); 59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) notification = g_browser_process->notification_ui_manager()->FindById( 60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuitWithAppsController::kQuitWithAppsNotificationID); 61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) EXPECT_EQ(NULL, notification); 62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Open an app window. 64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ExtensionTestMessageListener listener("Launched", false); 65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) app_ = InstallAndLaunchPlatformApp("minimal_id"); 66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ASSERT_TRUE(listener.WaitUntilSatisfied()); 67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // One browser and one app window at this point. 695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(chrome::BrowserIterator().done()); 701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // On the first quit, show notification. 735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(controller->ShouldQuit()); 741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification = g_browser_process->notification_ui_manager()->FindById( 765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu QuitWithAppsController::kQuitWithAppsNotificationID); 775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(notification); 785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If notification was dismissed by click, show again on next quit. 805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification->delegate()->Click(); 815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_center->RemoveAllNotifications(false); 825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(controller->ShouldQuit()); 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification = g_browser_process->notification_ui_manager()->FindById( 855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu QuitWithAppsController::kQuitWithAppsNotificationID); 865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(notification); 875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(chrome::BrowserIterator().done()); 891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // If notification is closed by user, don't show it next time. 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification->delegate()->Close(true); 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_center->RemoveAllNotifications(false); 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(controller->ShouldQuit()); 951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification = g_browser_process->notification_ui_manager()->FindById( 975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu QuitWithAppsController::kQuitWithAppsNotificationID); 985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_EQ(NULL, notification); 995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(chrome::BrowserIterator().done()); 1011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Quitting should not quit but close all browsers 1045c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::WindowedNotificationObserver observer( 1055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu chrome::NOTIFICATION_BROWSER_CLOSED, 1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu content::NotificationService::AllSources()); 107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome_browser_application_mac::Terminate(); 1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu observer.Wait(); 1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_TRUE(chrome::BrowserIterator().done()); 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_TRUE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu // Trying to quit while there are no browsers always shows notification. 1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EXPECT_FALSE(controller->ShouldQuit()); 1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification = g_browser_process->notification_ui_manager()->FindById( 1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu QuitWithAppsController::kQuitWithAppsNotificationID); 1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu ASSERT_TRUE(notification); 1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Clicking "Quit All Apps." button closes all app windows. With no browsers 120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // open, this should also quit Chrome. 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::WindowedNotificationObserver quit_observer( 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) chrome::NOTIFICATION_APP_TERMINATING, 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) content::NotificationService::AllSources()); 1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu notification->delegate()->ButtonClick(0); 1255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu message_center->RemoveAllNotifications(false); 1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci EXPECT_FALSE(AppWindowRegistryUtil::IsAppWindowRegisteredInAnyProfile(0)); 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) quit_observer.Wait(); 1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 129