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/users/user_manager.h" 26 #endif 27 28 using base::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 (profile->IsGuestSession()) 160 return true; 161 for (chrome::BrowserIterator it; !it.done(); it.Next()) { 162 if (it->profile()->IsSameProfile(profile) && 163 it->profile()->IsOffTheRecord()) { 164 return true; 165 } 166 } 167 return false; 168 } 169 170 //////////////////////////////////////////////////////////////////////////////// 171 // BrowserList, private: 172 173 BrowserList::BrowserList() { 174 } 175 176 BrowserList::~BrowserList() { 177 } 178 179 // static 180 void BrowserList::RemoveBrowserFrom(Browser* browser, 181 BrowserVector* browser_list) { 182 BrowserVector::iterator remove_browser = 183 std::find(browser_list->begin(), browser_list->end(), browser); 184 if (remove_browser != browser_list->end()) 185 browser_list->erase(remove_browser); 186 } 187