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