• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetLastActive() const42 Browser* BrowserList::GetLastActive() const {
43   if (!last_active_browsers_.empty())
44     return *(last_active_browsers_.rbegin());
45   return NULL;
46 }
47 
48 // static
GetInstance(chrome::HostDesktopType type)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
AddBrowser(Browser * browser)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
RemoveBrowser(Browser * 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_);
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
AddObserver(chrome::BrowserListObserver * observer)114 void BrowserList::AddObserver(chrome::BrowserListObserver* observer) {
115   observers_.Get().AddObserver(observer);
116 }
117 
118 // static
RemoveObserver(chrome::BrowserListObserver * observer)119 void BrowserList::RemoveObserver(chrome::BrowserListObserver* observer) {
120   observers_.Get().RemoveObserver(observer);
121 }
122 
CloseAllBrowsersWithProfile(Profile * profile)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
SetLastActive(Browser * browser)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
IsOffTheRecordSessionActive()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
IsOffTheRecordSessionActiveForProfile(Profile * profile)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 
BrowserList()177 BrowserList::BrowserList() {
178 }
179 
~BrowserList()180 BrowserList::~BrowserList() {
181 }
182 
183 // static
RemoveBrowserFrom(Browser * browser,BrowserVector * browser_list)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