- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / lifetime / browser_close_manager.cc
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.
4
5 #include "chrome/browser/lifetime/browser_close_manager.h"
6
7 #include "base/command_line.h"
8 #include "chrome/browser/background/background_mode_manager.h"
9 #include "chrome/browser/browser_process.h"
10 #include "chrome/browser/browser_shutdown.h"
11 #include "chrome/browser/download/download_service.h"
12 #include "chrome/browser/download/download_service_factory.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/browser_iterator.h"
16 #include "chrome/browser/ui/browser_list.h"
17 #include "chrome/browser/ui/browser_window.h"
18 #include "chrome/browser/ui/chrome_pages.h"
19 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "content/public/browser/web_contents.h"
23
24 BrowserCloseManager::BrowserCloseManager() : current_browser_(NULL) {}
25
26 BrowserCloseManager::~BrowserCloseManager() {}
27
28 void BrowserCloseManager::StartClosingBrowsers() {
29   // If the session is ending or batch browser shutdown is disabled, skip
30   // straight to closing the browsers. In the former case, there's no time to
31   // wait for beforeunload dialogs; in the latter, the windows will manage
32   // showing their own dialogs.
33   if (browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION ||
34       CommandLine::ForCurrentProcess()->HasSwitch(
35           switches::kDisableBatchedShutdown)) {
36     // Tell everyone that we are shutting down.
37     browser_shutdown::SetTryingToQuit(true);
38     CloseBrowsers();
39     return;
40   }
41   TryToCloseBrowsers();
42 }
43
44 void BrowserCloseManager::CancelBrowserClose() {
45   browser_shutdown::SetTryingToQuit(false);
46   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
47     it->ResetBeforeUnloadHandlers();
48   }
49 }
50
51 void BrowserCloseManager::TryToCloseBrowsers() {
52   // If all browser windows can immediately be closed, fall out of this loop and
53   // close the browsers. If any browser window cannot be closed, temporarily
54   // stop closing. CallBeforeUnloadHandlers prompts the user and calls
55   // OnBrowserReportCloseable with the result. If the user confirms the close,
56   // this will trigger TryToCloseBrowsers to try again.
57   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
58     if (it->CallBeforeUnloadHandlers(
59             base::Bind(&BrowserCloseManager::OnBrowserReportCloseable, this))) {
60       current_browser_ = *it;
61       return;
62     }
63   }
64   CheckForDownloadsInProgress();
65 }
66
67 void BrowserCloseManager::OnBrowserReportCloseable(bool proceed) {
68   if (!current_browser_)
69     return;
70
71   current_browser_ = NULL;
72
73   if (proceed)
74     TryToCloseBrowsers();
75   else
76     CancelBrowserClose();
77 }
78
79 void BrowserCloseManager::CheckForDownloadsInProgress() {
80   int download_count = DownloadService::NonMaliciousDownloadCountAllProfiles();
81   if (download_count == 0) {
82     CloseBrowsers();
83     return;
84   }
85   ConfirmCloseWithPendingDownloads(
86       download_count,
87       base::Bind(&BrowserCloseManager::OnReportDownloadsCancellable, this));
88 }
89
90 void BrowserCloseManager::ConfirmCloseWithPendingDownloads(
91     int download_count,
92     const base::Callback<void(bool)>& callback) {
93   Browser* browser =
94       BrowserList::GetInstance(chrome::GetActiveDesktop())->GetLastActive();
95   DCHECK(browser);
96   browser->window()->ConfirmBrowserCloseWithPendingDownloads(
97       download_count,
98       Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN,
99       true,
100       callback);
101 }
102
103 void BrowserCloseManager::OnReportDownloadsCancellable(bool proceed) {
104   if (proceed) {
105     CloseBrowsers();
106     return;
107   }
108
109   CancelBrowserClose();
110
111   // Open the downloads page for each profile with downloads in progress.
112   std::vector<Profile*> profiles(
113       g_browser_process->profile_manager()->GetLoadedProfiles());
114   for (std::vector<Profile*>::iterator it = profiles.begin();
115        it != profiles.end();
116        ++it) {
117     DownloadService* download_service =
118         DownloadServiceFactory::GetForBrowserContext(*it);
119     if (download_service->NonMaliciousDownloadCount() > 0) {
120       chrome::ScopedTabbedBrowserDisplayer displayer(
121           *it, chrome::GetActiveDesktop());
122       chrome::ShowDownloads(displayer.browser());
123     }
124   }
125 }
126
127 void BrowserCloseManager::CloseBrowsers() {
128 #if defined(ENABLE_SESSION_SERVICE)
129   // Before we close the browsers shutdown all session services. That way an
130   // exit can restore all browsers open before exiting.
131   ProfileManager::ShutdownSessionServices();
132 #endif
133   if (!browser_shutdown::IsTryingToQuit()) {
134     BackgroundModeManager* background_mode_manager =
135         g_browser_process->background_mode_manager();
136     if (background_mode_manager)
137       background_mode_manager->SuspendBackgroundMode();
138   }
139
140   bool session_ending =
141       browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
142   for (scoped_ptr<chrome::BrowserIterator> it_ptr(
143            new chrome::BrowserIterator());
144        !it_ptr->done();) {
145     Browser* browser = **it_ptr;
146     browser->window()->Close();
147     if (!session_ending) {
148       it_ptr->Next();
149     } else {
150       // This path is hit during logoff/power-down. In this case we won't get
151       // a final message and so we force the browser to be deleted.
152       // Close doesn't immediately destroy the browser
153       // (Browser::TabStripEmpty() uses invoke later) but when we're ending the
154       // session we need to make sure the browser is destroyed now. So, invoke
155       // DestroyBrowser to make sure the browser is deleted and cleanup can
156       // happen.
157       while (browser->tab_strip_model()->count())
158         delete browser->tab_strip_model()->GetWebContentsAt(0);
159       browser->window()->DestroyBrowser();
160       it_ptr.reset(new chrome::BrowserIterator());
161       if (!it_ptr->done() && browser == **it_ptr) {
162         // Destroying the browser should have removed it from the browser list.
163         // We should never get here.
164         NOTREACHED();
165         return;
166       }
167     }
168   }
169 }