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