using testing::_;
using testing::AtLeast;

class BrowserShutdownBrowserTest : public InProcessBrowserTest {
 public:
  BrowserShutdownBrowserTest() {}
  ~BrowserShutdownBrowserTest() override {}

 protected:
  base::HistogramTester histogram_tester_;

 private:
  DISALLOW_COPY_AND_ASSIGN(BrowserShutdownBrowserTest);
};

class BrowserClosingObserver : public BrowserListObserver {
 public:
  BrowserClosingObserver() {}
  MOCK_METHOD1(OnBrowserClosing, void(Browser* browser));

 private:
  DISALLOW_COPY_AND_ASSIGN(BrowserClosingObserver);
};

// ChromeOS has the different shutdown flow on user initiated exit process.
// See the comment for chrome::AttemptUserExit() function declaration.
#if !defined(OS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(BrowserShutdownBrowserTest,
                       PRE_TwoBrowsersClosingShutdownHistograms) {
  ui_test_utils::NavigateToURL(browser(), GURL("browser://version"));
  Browser* browser2 = CreateBrowser(browser()->profile());
  ui_test_utils::NavigateToURL(browser2, GURL("browser://help"));

  BrowserClosingObserver closing_observer;
  BrowserList::AddObserver(&closing_observer);
  EXPECT_CALL(closing_observer, OnBrowserClosing(_)).Times(AtLeast(1));

  content::WindowedNotificationObserver terminate_observer(
      chrome::NOTIFICATION_APP_TERMINATING,
      content::NotificationService::AllSources());
  chrome::ExecuteCommand(browser(), IDC_EXIT);
  terminate_observer.Wait();

  EXPECT_TRUE(browser_shutdown::IsTryingToQuit());
  EXPECT_TRUE(BrowserList::GetInstance()->empty());
  EXPECT_EQ(browser_shutdown::GetShutdownType(),
            browser_shutdown::ShutdownType::kWindowClose);
  BrowserList::RemoveObserver(&closing_observer);
}

IN_PROC_BROWSER_TEST_F(BrowserShutdownBrowserTest,
                       TwoBrowsersClosingShutdownHistograms) {
  histogram_tester_.ExpectUniqueSample(
      "Shutdown.ShutdownType",
      static_cast<int>(browser_shutdown::ShutdownType::kWindowClose), 1);
  histogram_tester_.ExpectTotalCount("Shutdown.renderers.total", 1);
  histogram_tester_.ExpectTotalCount("Shutdown.window_close.time2", 1);
  histogram_tester_.ExpectTotalCount("Shutdown.window_close.time_per_process",
                                     1);
}
#else
// On Chrome OS, the shutdown accelerator is handled by Ash and requires
// confirmation, so Chrome shouldn't try to shut down after it's been hit one
// time. Regression test for crbug.com/834092
IN_PROC_BROWSER_TEST_F(BrowserShutdownBrowserTest, ShutdownConfirmation) {
  const int modifiers = ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN;

  ui::test::EventGenerator generator(
      browser()->window()->GetNativeWindow()->GetRootWindow());

  // Press the accelerator for quitting.
  generator.PressKey(ui::VKEY_Q, modifiers);
  generator.ReleaseKey(ui::VKEY_Q, modifiers);
  base::RunLoop().RunUntilIdle();

  EXPECT_FALSE(browser_shutdown::IsTryingToQuit());
}
#endif  // !defined(OS_CHROMEOS)
