13551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 23551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 33551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// found in the LICENSE file. 43551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 53551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/lifetime/browser_close_manager.h" 63551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 71e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/browser/background/background_mode_manager.h" 83551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/browser_process.h" 93551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/browser_shutdown.h" 103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/download/download_service.h" 113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/download/download_service_factory.h" 123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/profiles/profile_manager.h" 133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/browser_iterator.h" 153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/browser_list.h" 163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/chrome_pages.h" 180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h" 193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "content/public/browser/web_contents.h" 213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BrowserCloseManager::BrowserCloseManager() : current_browser_(NULL) {} 233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)BrowserCloseManager::~BrowserCloseManager() {} 253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::StartClosingBrowsers() { 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If the session is ending, skip straight to closing the browsers. There's no 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // time to wait for beforeunload dialogs. 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION) { 301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Tell everyone that we are shutting down. 311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) browser_shutdown::SetTryingToQuit(true); 323551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CloseBrowsers(); 333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) TryToCloseBrowsers(); 363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::CancelBrowserClose() { 393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) browser_shutdown::SetTryingToQuit(false); 403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) it->ResetBeforeUnloadHandlers(); 423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::TryToCloseBrowsers() { 463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // If all browser windows can immediately be closed, fall out of this loop and 473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // close the browsers. If any browser window cannot be closed, temporarily 483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // stop closing. CallBeforeUnloadHandlers prompts the user and calls 493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // OnBrowserReportCloseable with the result. If the user confirms the close, 503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // this will trigger TryToCloseBrowsers to try again. 513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (chrome::BrowserIterator it; !it.done(); it.Next()) { 523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (it->CallBeforeUnloadHandlers( 533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Bind(&BrowserCloseManager::OnBrowserReportCloseable, this))) { 543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) current_browser_ = *it; 553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CheckForDownloadsInProgress(); 593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::OnBrowserReportCloseable(bool proceed) { 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!current_browser_) 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) current_browser_ = NULL; 663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (proceed) 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) TryToCloseBrowsers(); 693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) else 703551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CancelBrowserClose(); 713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::CheckForDownloadsInProgress() { 748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) int download_count = DownloadService::NonMaliciousDownloadCountAllProfiles(); 753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (download_count == 0) { 763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CloseBrowsers(); 773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ConfirmCloseWithPendingDownloads( 803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) download_count, 813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) base::Bind(&BrowserCloseManager::OnReportDownloadsCancellable, this)); 823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::ConfirmCloseWithPendingDownloads( 853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) int download_count, 863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::Callback<void(bool)>& callback) { 873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Browser* browser = 883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) BrowserList::GetInstance(chrome::GetActiveDesktop())->GetLastActive(); 893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK(browser); 903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) browser->window()->ConfirmBrowserCloseWithPendingDownloads( 913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) download_count, 923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Browser::DOWNLOAD_CLOSE_BROWSER_SHUTDOWN, 933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) true, 943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) callback); 953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::OnReportDownloadsCancellable(bool proceed) { 983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (proceed) { 993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CloseBrowsers(); 1003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) CancelBrowserClose(); 1043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Open the downloads page for each profile with downloads in progress. 1063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) std::vector<Profile*> profiles( 1073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) g_browser_process->profile_manager()->GetLoadedProfiles()); 1083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (std::vector<Profile*>::iterator it = profiles.begin(); 1093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) it != profiles.end(); 1103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ++it) { 1113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DownloadService* download_service = 1123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DownloadServiceFactory::GetForBrowserContext(*it); 1138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) if (download_service->NonMaliciousDownloadCount() > 0) { 1140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::ScopedTabbedBrowserDisplayer displayer( 1150f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) *it, chrome::GetActiveDesktop()); 1160f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) chrome::ShowDownloads(displayer.browser()); 1173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 1203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void BrowserCloseManager::CloseBrowsers() { 1223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#if defined(ENABLE_SESSION_SERVICE) 1233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Before we close the browsers shutdown all session services. That way an 1243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // exit can restore all browsers open before exiting. 1253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ProfileManager::ShutdownSessionServices(); 1263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#endif 1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!browser_shutdown::IsTryingToQuit()) { 1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) BackgroundModeManager* background_mode_manager = 1291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) g_browser_process->background_mode_manager(); 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (background_mode_manager) 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) background_mode_manager->SuspendBackgroundMode(); 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 1333551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 1343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) bool session_ending = 1353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; 1363551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) for (scoped_ptr<chrome::BrowserIterator> it_ptr( 1373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) new chrome::BrowserIterator()); 1383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) !it_ptr->done();) { 1393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) Browser* browser = **it_ptr; 1403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) browser->window()->Close(); 1413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!session_ending) { 1423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) it_ptr->Next(); 1433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } else { 1443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // This path is hit during logoff/power-down. In this case we won't get 1453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // a final message and so we force the browser to be deleted. 1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Close doesn't immediately destroy the browser 1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // (Browser::TabStripEmpty() uses invoke later) but when we're ending the 1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // session we need to make sure the browser is destroyed now. So, invoke 1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // DestroyBrowser to make sure the browser is deleted and cleanup can 1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // happen. 1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) while (browser->tab_strip_model()->count()) 1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) delete browser->tab_strip_model()->GetWebContentsAt(0); 1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) browser->window()->DestroyBrowser(); 1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) it_ptr.reset(new chrome::BrowserIterator()); 1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (!it_ptr->done() && browser == **it_ptr) { 1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Destroying the browser should have removed it from the browser list. 1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // We should never get here. 1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) NOTREACHED(); 1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return; 1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 164