browser_list.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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
28using base::UserMetricsAction;
29using content::WebContents;
30
31// static
32base::LazyInstance<ObserverList<chrome::BrowserListObserver> >::Leaky
33    BrowserList::observers_ = LAZY_INSTANCE_INITIALIZER;
34
35// static
36BrowserList* BrowserList::native_instance_ = NULL;
37BrowserList* BrowserList::ash_instance_ = NULL;
38
39////////////////////////////////////////////////////////////////////////////////
40// BrowserList, public:
41
42Browser* BrowserList::GetLastActive() const {
43  if (!last_active_browsers_.empty())
44    return *(last_active_browsers_.rbegin());
45  return NULL;
46}
47
48// static
49BrowserList* 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
63void 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
81void 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
114void BrowserList::AddObserver(chrome::BrowserListObserver* observer) {
115  observers_.Get().AddObserver(observer);
116}
117
118// static
119void BrowserList::RemoveObserver(chrome::BrowserListObserver* observer) {
120  observers_.Get().RemoveObserver(observer);
121}
122
123void 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
137void 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
149bool 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
158bool 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
173BrowserList::BrowserList() {
174}
175
176BrowserList::~BrowserList() {
177}
178
179// static
180void 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