Componentize HistoryURLProvider/ScoredHistoryMatch.
[chromium-blink-merge.git] / chrome / browser / lifetime / browser_close_manager.cc
blob8df00c6744d84c8d7069ce6f1cd963a7c9c0a5fe
1 // Copyright 2013 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.
5 #include "chrome/browser/lifetime/browser_close_manager.h"
7 #include "chrome/browser/background/background_mode_manager.h"
8 #include "chrome/browser/browser_process.h"
9 #include "chrome/browser/browser_shutdown.h"
10 #include "chrome/browser/download/download_service.h"
11 #include "chrome/browser/download/download_service_factory.h"
12 #include "chrome/browser/profiles/profile_manager.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/browser_iterator.h"
15 #include "chrome/browser/ui/browser_list.h"
16 #include "chrome/browser/ui/browser_window.h"
17 #include "chrome/browser/ui/chrome_pages.h"
18 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
19 #include "chrome/browser/ui/tabs/tab_strip_model.h"
20 #include "content/public/browser/web_contents.h"
22 namespace {
24 // Navigates a browser window for |profile|, creating one if necessary, to the
25 // downloads page if there are downloads in progress for |profile|.
26 void ShowInProgressDownloads(Profile* profile) {
27 DownloadService* download_service =
28 DownloadServiceFactory::GetForBrowserContext(profile);
29 if (download_service->NonMaliciousDownloadCount() > 0) {
30 chrome::ScopedTabbedBrowserDisplayer displayer(profile,
31 chrome::GetActiveDesktop());
32 chrome::ShowDownloads(displayer.browser());
36 } // namespace
38 BrowserCloseManager::BrowserCloseManager() : current_browser_(NULL) {}
40 BrowserCloseManager::~BrowserCloseManager() {}
42 void BrowserCloseManager::StartClosingBrowsers() {
43 // If the session is ending, skip straight to closing the browsers. There's no
44 // time to wait for beforeunload dialogs.
45 if (browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION) {
46 // Tell everyone that we are shutting down.
47 browser_shutdown::SetTryingToQuit(true);
48 CloseBrowsers();
49 return;
51 TryToCloseBrowsers();
54 void BrowserCloseManager::CancelBrowserClose() {
55 browser_shutdown::SetTryingToQuit(false);
56 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
57 it->ResetBeforeUnloadHandlers();
61 void BrowserCloseManager::TryToCloseBrowsers() {
62 // If all browser windows can immediately be closed, fall out of this loop and
63 // close the browsers. If any browser window cannot be closed, temporarily
64 // stop closing. CallBeforeUnloadHandlers prompts the user and calls
65 // OnBrowserReportCloseable with the result. If the user confirms the close,
66 // this will trigger TryToCloseBrowsers to try again.
67 for (chrome::BrowserIterator it; !it.done(); it.Next()) {
68 if (it->CallBeforeUnloadHandlers(
69 base::Bind(&BrowserCloseManager::OnBrowserReportCloseable, this))) {
70 current_browser_ = *it;
71 return;
74 CheckForDownloadsInProgress();
77 void BrowserCloseManager::OnBrowserReportCloseable(bool proceed) {
78 if (!current_browser_)
79 return;
81 current_browser_ = NULL;
83 if (proceed)
84 TryToCloseBrowsers();
85 else
86 CancelBrowserClose();
89 void BrowserCloseManager::CheckForDownloadsInProgress() {
90 #if defined(OS_MACOSX)
91 // Mac has its own in-progress downloads prompt in app_controller_mac.mm.
92 CloseBrowsers();
93 return;
94 #endif
96 int download_count = DownloadService::NonMaliciousDownloadCountAllProfiles();
97 if (download_count == 0) {
98 CloseBrowsers();
99 return;
102 ConfirmCloseWithPendingDownloads(
103 download_count,
104 base::Bind(&BrowserCloseManager::OnReportDownloadsCancellable, this));
107 void BrowserCloseManager::ConfirmCloseWithPendingDownloads(
108 int download_count,
109 const base::Callback<void(bool)>& callback) {
110 Browser* browser =
111 BrowserList::GetInstance(chrome::GetActiveDesktop())->GetLastActive();
112 DCHECK(browser);
113 browser->window()->ConfirmBrowserCloseWithPendingDownloads(
114 download_count,
115 Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN,
116 true,
117 callback);
120 void BrowserCloseManager::OnReportDownloadsCancellable(bool proceed) {
121 if (proceed) {
122 CloseBrowsers();
123 return;
126 CancelBrowserClose();
128 // Open the downloads page for each profile with downloads in progress.
129 std::vector<Profile*> profiles(
130 g_browser_process->profile_manager()->GetLoadedProfiles());
131 for (Profile* profile : profiles) {
132 ShowInProgressDownloads(profile);
133 if (profile->HasOffTheRecordProfile())
134 ShowInProgressDownloads(profile->GetOffTheRecordProfile());
138 void BrowserCloseManager::CloseBrowsers() {
139 #if defined(ENABLE_SESSION_SERVICE)
140 // Before we close the browsers shutdown all session services. That way an
141 // exit can restore all browsers open before exiting.
142 ProfileManager::ShutdownSessionServices();
143 #endif
144 if (!browser_shutdown::IsTryingToQuit()) {
145 BackgroundModeManager* background_mode_manager =
146 g_browser_process->background_mode_manager();
147 if (background_mode_manager)
148 background_mode_manager->SuspendBackgroundMode();
151 bool session_ending =
152 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
153 for (scoped_ptr<chrome::BrowserIterator> it_ptr(
154 new chrome::BrowserIterator());
155 !it_ptr->done();) {
156 Browser* browser = **it_ptr;
157 browser->window()->Close();
158 if (!session_ending) {
159 it_ptr->Next();
160 } else {
161 // This path is hit during logoff/power-down. In this case we won't get
162 // a final message and so we force the browser to be deleted.
163 // Close doesn't immediately destroy the browser
164 // (Browser::TabStripEmpty() uses invoke later) but when we're ending the
165 // session we need to make sure the browser is destroyed now. So, invoke
166 // DestroyBrowser to make sure the browser is deleted and cleanup can
167 // happen.
168 while (browser->tab_strip_model()->count())
169 delete browser->tab_strip_model()->GetWebContentsAt(0);
170 browser->window()->DestroyBrowser();
171 it_ptr.reset(new chrome::BrowserIterator());
172 if (!it_ptr->done() && browser == **it_ptr) {
173 // Destroying the browser should have removed it from the browser list.
174 // We should never get here.
175 NOTREACHED();
176 return;