Home | History | Annotate | Download | only in ui
      1 // Copyright (c) 2012 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/ui/browser_list.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/logging.h"
     10 #include "chrome/browser/browser_process.h"
     11 #include "chrome/browser/browser_shutdown.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/lifetime/application_lifetime.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/ui/browser.h"
     16 #include "chrome/browser/ui/browser_finder.h"
     17 #include "chrome/browser/ui/browser_iterator.h"
     18 #include "chrome/browser/ui/browser_list_observer.h"
     19 #include "chrome/browser/ui/browser_window.h"
     20 #include "chrome/browser/ui/host_desktop.h"
     21 #include "content/public/browser/notification_service.h"
     22 #include "content/public/browser/user_metrics.h"
     23 
     24 #if defined(OS_CHROMEOS)
     25 #include "chrome/browser/chromeos/login/user_manager.h"
     26 #endif
     27 
     28 using content::UserMetricsAction;
     29 using content::WebContents;
     30 
     31 // static
     32 base::LazyInstance<ObserverList<chrome::BrowserListObserver> >::Leaky
     33     BrowserList::observers_ = LAZY_INSTANCE_INITIALIZER;
     34 
     35 // static
     36 BrowserList* BrowserList::native_instance_ = NULL;
     37 BrowserList* BrowserList::ash_instance_ = NULL;
     38 
     39 ////////////////////////////////////////////////////////////////////////////////
     40 // BrowserList, public:
     41 
     42 Browser* BrowserList::GetLastActive() const {
     43   if (!last_active_browsers_.empty())
     44     return *(last_active_browsers_.rbegin());
     45   return NULL;
     46 }
     47 
     48 // static
     49 BrowserList* BrowserList::GetInstance(chrome::HostDesktopType type) {
     50   BrowserList** list = NULL;
     51   if (type == chrome::HOST_DESKTOP_TYPE_NATIVE)
     52     list = &native_instance_;
     53   else if (type == chrome::HOST_DESKTOP_TYPE_ASH)
     54     list = &ash_instance_;
     55   else
     56     NOTREACHED();
     57   if (!*list)
     58     *list = new BrowserList;
     59   return *list;
     60 }
     61 
     62 // static
     63 void BrowserList::AddBrowser(Browser* browser) {
     64   DCHECK(browser);
     65   // Push |browser| on the appropriate list instance.
     66   BrowserList* browser_list = GetInstance(browser->host_desktop_type());
     67   browser_list->browsers_.push_back(browser);
     68 
     69   g_browser_process->AddRefModule();
     70 
     71   content::NotificationService::current()->Notify(
     72       chrome::NOTIFICATION_BROWSER_OPENED,
     73       content::Source<Browser>(browser),
     74       content::NotificationService::NoDetails());
     75 
     76   FOR_EACH_OBSERVER(chrome::BrowserListObserver, observers_.Get(),
     77                     OnBrowserAdded(browser));
     78 }
     79 
     80 // static
     81 void BrowserList::RemoveBrowser(Browser* browser) {
     82   // Remove |browser| from the appropriate list instance.
     83   BrowserList* browser_list = GetInstance(browser->host_desktop_type());
     84   RemoveBrowserFrom(browser, &browser_list->last_active_browsers_);
     85 
     86   content::NotificationService::current()->Notify(
     87       chrome::NOTIFICATION_BROWSER_CLOSED,
     88       content::Source<Browser>(browser),
     89       content::NotificationService::NoDetails());
     90 
     91   RemoveBrowserFrom(browser, &browser_list->browsers_);
     92 
     93   FOR_EACH_OBSERVER(chrome::BrowserListObserver, observers_.Get(),
     94                     OnBrowserRemoved(browser));
     95 
     96   g_browser_process->ReleaseModule();
     97 
     98   // If we're exiting, send out the APP_TERMINATING notification to allow other
     99   // modules to shut themselves down.
    100   if (chrome::GetTotalBrowserCount() == 0 &&
    101       (browser_shutdown::IsTryingToQuit() ||
    102        g_browser_process->IsShuttingDown())) {
    103     // Last browser has just closed, and this is a user-initiated quit or there
    104     // is no module keeping the app alive, so send out our notification. No need
    105     // to call ProfileManager::ShutdownSessionServices() as part of the
    106     // shutdown, because Browser::WindowClosing() already makes sure that the
    107     // SessionService is created and notified.
    108     chrome::NotifyAppTerminating();
    109     chrome::OnAppExiting();
    110   }
    111 }
    112 
    113 // static
    114 void BrowserList::AddObserver(chrome::BrowserListObserver* observer) {
    115   observers_.Get().AddObserver(observer);
    116 }
    117 
    118 // static
    119 void BrowserList::RemoveObserver(chrome::BrowserListObserver* observer) {
    120   observers_.Get().RemoveObserver(observer);
    121 }
    122 
    123 void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
    124   BrowserVector browsers_to_close;
    125   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
    126     if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
    127       browsers_to_close.push_back(*it);
    128   }
    129 
    130   for (BrowserVector::const_iterator it = browsers_to_close.begin();
    131        it != browsers_to_close.end(); ++it) {
    132     (*it)->window()->Close();
    133   }
    134 }
    135 
    136 // static
    137 void BrowserList::SetLastActive(Browser* browser) {
    138   content::RecordAction(UserMetricsAction("ActiveBrowserChanged"));
    139   BrowserList* browser_list = GetInstance(browser->host_desktop_type());
    140 
    141   RemoveBrowserFrom(browser, &browser_list->last_active_browsers_);
    142   browser_list->last_active_browsers_.push_back(browser);
    143 
    144   FOR_EACH_OBSERVER(chrome::BrowserListObserver, observers_.Get(),
    145                     OnBrowserSetLastActive(browser));
    146 }
    147 
    148 // static
    149 bool BrowserList::IsOffTheRecordSessionActive() {
    150   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
    151     if (it->profile()->IsOffTheRecord())
    152       return true;
    153   }
    154   return false;
    155 }
    156 
    157 // static
    158 bool BrowserList::IsOffTheRecordSessionActiveForProfile(Profile* profile) {
    159   #if defined(OS_CHROMEOS)
    160   // In ChromeOS, we assume that the default profile is always valid, so if
    161   // we are in guest mode, keep the OTR profile active so it won't be deleted.
    162   if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
    163     return true;
    164 #endif
    165   for (chrome::BrowserIterator it; !it.done(); it.Next()) {
    166     if (it->profile()->IsSameProfile(profile) &&
    167         it->profile()->IsOffTheRecord()) {
    168       return true;
    169     }
    170   }
    171   return false;
    172 }
    173 
    174 ////////////////////////////////////////////////////////////////////////////////
    175 // BrowserList, private:
    176 
    177 BrowserList::BrowserList() {
    178 }
    179 
    180 BrowserList::~BrowserList() {
    181 }
    182 
    183 // static
    184 void BrowserList::RemoveBrowserFrom(Browser* browser,
    185                                     BrowserVector* browser_list) {
    186   BrowserVector::iterator remove_browser =
    187       std::find(browser_list->begin(), browser_list->end(), browser);
    188   if (remove_browser != browser_list->end())
    189     browser_list->erase(remove_browser);
    190 }
    191