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 using base::UserMetricsAction
;
25 using content::WebContents
;
28 base::LazyInstance
<ObserverList
<chrome::BrowserListObserver
> >::Leaky
29 BrowserList::observers_
= LAZY_INSTANCE_INITIALIZER
;
32 BrowserList
* BrowserList::native_instance_
= NULL
;
33 BrowserList
* BrowserList::ash_instance_
= NULL
;
35 ////////////////////////////////////////////////////////////////////////////////
36 // BrowserList, public:
38 Browser
* BrowserList::GetLastActive() const {
39 if (!last_active_browsers_
.empty())
40 return *(last_active_browsers_
.rbegin());
45 BrowserList
* BrowserList::GetInstance(chrome::HostDesktopType type
) {
46 BrowserList
** list
= NULL
;
47 if (type
== chrome::HOST_DESKTOP_TYPE_NATIVE
)
48 list
= &native_instance_
;
49 else if (type
== chrome::HOST_DESKTOP_TYPE_ASH
)
50 list
= &ash_instance_
;
54 *list
= new BrowserList
;
59 void BrowserList::AddBrowser(Browser
* browser
) {
61 // Push |browser| on the appropriate list instance.
62 BrowserList
* browser_list
= GetInstance(browser
->host_desktop_type());
63 browser_list
->browsers_
.push_back(browser
);
65 g_browser_process
->AddRefModule();
67 content::NotificationService::current()->Notify(
68 chrome::NOTIFICATION_BROWSER_OPENED
,
69 content::Source
<Browser
>(browser
),
70 content::NotificationService::NoDetails());
72 FOR_EACH_OBSERVER(chrome::BrowserListObserver
, observers_
.Get(),
73 OnBrowserAdded(browser
));
77 void BrowserList::RemoveBrowser(Browser
* browser
) {
78 // Remove |browser| from the appropriate list instance.
79 BrowserList
* browser_list
= GetInstance(browser
->host_desktop_type());
80 RemoveBrowserFrom(browser
, &browser_list
->last_active_browsers_
);
82 content::NotificationService::current()->Notify(
83 chrome::NOTIFICATION_BROWSER_CLOSED
,
84 content::Source
<Browser
>(browser
),
85 content::NotificationService::NoDetails());
87 RemoveBrowserFrom(browser
, &browser_list
->browsers_
);
89 FOR_EACH_OBSERVER(chrome::BrowserListObserver
, observers_
.Get(),
90 OnBrowserRemoved(browser
));
92 g_browser_process
->ReleaseModule();
94 // If we're exiting, send out the APP_TERMINATING notification to allow other
95 // modules to shut themselves down.
96 if (chrome::GetTotalBrowserCount() == 0 &&
97 (browser_shutdown::IsTryingToQuit() ||
98 g_browser_process
->IsShuttingDown())) {
99 // Last browser has just closed, and this is a user-initiated quit or there
100 // is no module keeping the app alive, so send out our notification. No need
101 // to call ProfileManager::ShutdownSessionServices() as part of the
102 // shutdown, because Browser::WindowClosing() already makes sure that the
103 // SessionService is created and notified.
104 chrome::NotifyAppTerminating();
105 chrome::OnAppExiting();
110 void BrowserList::AddObserver(chrome::BrowserListObserver
* observer
) {
111 observers_
.Get().AddObserver(observer
);
115 void BrowserList::RemoveObserver(chrome::BrowserListObserver
* observer
) {
116 observers_
.Get().RemoveObserver(observer
);
119 void BrowserList::CloseAllBrowsersWithProfile(Profile
* profile
) {
120 BrowserVector browsers_to_close
;
121 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
122 if (it
->profile()->GetOriginalProfile() == profile
->GetOriginalProfile())
123 browsers_to_close
.push_back(*it
);
126 for (BrowserVector::const_iterator it
= browsers_to_close
.begin();
127 it
!= browsers_to_close
.end(); ++it
) {
128 (*it
)->window()->Close();
133 void BrowserList::SetLastActive(Browser
* browser
) {
134 content::RecordAction(UserMetricsAction("ActiveBrowserChanged"));
135 BrowserList
* browser_list
= GetInstance(browser
->host_desktop_type());
137 RemoveBrowserFrom(browser
, &browser_list
->last_active_browsers_
);
138 browser_list
->last_active_browsers_
.push_back(browser
);
140 FOR_EACH_OBSERVER(chrome::BrowserListObserver
, observers_
.Get(),
141 OnBrowserSetLastActive(browser
));
145 bool BrowserList::IsOffTheRecordSessionActive() {
146 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
147 if (it
->profile()->IsOffTheRecord())
154 bool BrowserList::IsOffTheRecordSessionActiveForProfile(Profile
* profile
) {
155 if (profile
->IsGuestSession())
157 for (chrome::BrowserIterator it
; !it
.done(); it
.Next()) {
158 if (it
->profile()->IsSameProfile(profile
) &&
159 it
->profile()->IsOffTheRecord()) {
166 ////////////////////////////////////////////////////////////////////////////////
167 // BrowserList, private:
169 BrowserList::BrowserList() {
172 BrowserList::~BrowserList() {
176 void BrowserList::RemoveBrowserFrom(Browser
* browser
,
177 BrowserVector
* browser_list
) {
178 BrowserVector::iterator remove_browser
=
179 std::find(browser_list
->begin(), browser_list
->end(), browser
);
180 if (remove_browser
!= browser_list
->end())
181 browser_list
->erase(remove_browser
);