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.
5 #include "chrome/browser/ui/browser_list.h"
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"
24 #if defined(OS_CHROMEOS)
25 #include "chrome/browser/chromeos/login/user_manager.h"
28 using base::UserMetricsAction
;
29 using content::WebContents
;
32 base::LazyInstance
<ObserverList
<chrome::BrowserListObserver
> >::Leaky
33 BrowserList::observers_
= LAZY_INSTANCE_INITIALIZER
;
36 BrowserList
* BrowserList::native_instance_
= NULL
;
37 BrowserList
* BrowserList::ash_instance_
= NULL
;
39 ////////////////////////////////////////////////////////////////////////////////
40 // BrowserList, public:
42 Browser
* BrowserList::GetLastActive() const {
43 if (!last_active_browsers_
.empty())
44 return *(last_active_browsers_
.rbegin());
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_
;
58 *list
= new BrowserList
;
63 void BrowserList::AddBrowser(Browser
* 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
);
69 g_browser_process
->AddRefModule();
71 content::NotificationService::current()->Notify(
72 chrome::NOTIFICATION_BROWSER_OPENED
,
73 content::Source
<Browser
>(browser
),
74 content::NotificationService::NoDetails());
76 FOR_EACH_OBSERVER(chrome::BrowserListObserver
, observers_
.Get(),
77 OnBrowserAdded(browser
));
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_
);
86 content::NotificationService::current()->Notify(
87 chrome::NOTIFICATION_BROWSER_CLOSED
,
88 content::Source
<Browser
>(browser
),
89 content::NotificationService::NoDetails());
91 RemoveBrowserFrom(browser
, &browser_list
->browsers_
);
93 FOR_EACH_OBSERVER(chrome::BrowserListObserver
, observers_
.Get(),
94 OnBrowserRemoved(browser
));
96 g_browser_process
->ReleaseModule();
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();
114 void BrowserList::AddObserver(chrome::BrowserListObserver
* observer
) {
115 observers_
.Get().AddObserver(observer
);
119 void BrowserList::RemoveObserver(chrome::BrowserListObserver
* observer
) {
120 observers_
.Get().RemoveObserver(observer
);
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
);
130 for (BrowserVector::const_iterator it
= browsers_to_close
.begin();
131 it
!= browsers_to_close
.end(); ++it
) {
132 (*it
)->window()->Close();
137 void BrowserList::SetLastActive(Browser
* browser
) {
138 content::RecordAction(UserMetricsAction("ActiveBrowserChanged"));
139 BrowserList
* browser_list
= GetInstance(browser
->host_desktop_type());
141 RemoveBrowserFrom(browser
, &browser_list
->last_active_browsers_
);
142 browser_list
->last_active_browsers_
.push_back(browser
);
144 FOR_EACH_OBSERVER(chrome::BrowserListObserver
, observers_
.Get(),
145 OnBrowserSetLastActive(browser
));
149 bool BrowserList::IsOffTheRecordSessionActive() {
150 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
151 if (it
->profile()->IsOffTheRecord())
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())
165 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
166 if (it
->profile()->IsSameProfile(profile
) &&
167 it
->profile()->IsOffTheRecord()) {
174 ////////////////////////////////////////////////////////////////////////////////
175 // BrowserList, private:
177 BrowserList::BrowserList() {
180 BrowserList::~BrowserList() {
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
);