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