Home | History | Annotate | Download | only in lifetime
      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 
     22 BrowserCloseManager::BrowserCloseManager() : current_browser_(NULL) {}
     23 
     24 BrowserCloseManager::~BrowserCloseManager() {}
     25 
     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 
     38 void BrowserCloseManager::CancelBrowserClose() {
     39   browser_shutdown::SetTryingToQuit(false);
     40   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
     41     it->ResetBeforeUnloadHandlers();
     42   }
     43 }
     44 
     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 
     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 
     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 
     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 
     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 
    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