blob: 000c4c6210db311e0600ad9cac30d7a454e833c8 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/browser_list.h"
#include <algorithm>
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_iterator.h"
#include "chrome/browser/ui/browser_list_observer.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/host_desktop.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/user_metrics.h"
using base::UserMetricsAction;
using content::WebContents;
// static
base::LazyInstance<ObserverList<chrome::BrowserListObserver> >::Leaky
BrowserList::observers_ = LAZY_INSTANCE_INITIALIZER;
// static
BrowserList* BrowserList::native_instance_ = NULL;
BrowserList* BrowserList::ash_instance_ = NULL;
////////////////////////////////////////////////////////////////////////////////
// BrowserList, public:
Browser* BrowserList::GetLastActive() const {
if (!last_active_browsers_.empty())
return *(last_active_browsers_.rbegin());
return NULL;
}
// static
BrowserList* BrowserList::GetInstance(chrome::HostDesktopType type) {
BrowserList** list = NULL;
if (type == chrome::HOST_DESKTOP_TYPE_NATIVE)
list = &native_instance_;
else if (type == chrome::HOST_DESKTOP_TYPE_ASH)
list = &ash_instance_;
else
NOTREACHED();
if (!*list)
*list = new BrowserList;
return *list;
}
// static
void BrowserList::AddBrowser(Browser* browser) {
DCHECK(browser);
// Push |browser| on the appropriate list instance.
BrowserList* browser_list = GetInstance(browser->host_desktop_type());
browser_list->browsers_.push_back(browser);
g_browser_process->AddRefModule();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_BROWSER_OPENED,
content::Source<Browser>(browser),
content::NotificationService::NoDetails());
FOR_EACH_OBSERVER(chrome::BrowserListObserver, observers_.Get(),
OnBrowserAdded(browser));
}
// static
void BrowserList::RemoveBrowser(Browser* browser) {
// Remove |browser| from the appropriate list instance.
BrowserList* browser_list = GetInstance(browser->host_desktop_type());
RemoveBrowserFrom(browser, &browser_list->last_active_browsers_);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::Source<Browser>(browser),
content::NotificationService::NoDetails());
RemoveBrowserFrom(browser, &browser_list->browsers_);
FOR_EACH_OBSERVER(chrome::BrowserListObserver, observers_.Get(),
OnBrowserRemoved(browser));
g_browser_process->ReleaseModule();
// If we're exiting, send out the APP_TERMINATING notification to allow other
// modules to shut themselves down.
if (chrome::GetTotalBrowserCount() == 0 &&
(browser_shutdown::IsTryingToQuit() ||
g_browser_process->IsShuttingDown())) {
// Last browser has just closed, and this is a user-initiated quit or there
// is no module keeping the app alive, so send out our notification. No need
// to call ProfileManager::ShutdownSessionServices() as part of the
// shutdown, because Browser::WindowClosing() already makes sure that the
// SessionService is created and notified.
chrome::NotifyAppTerminating();
chrome::OnAppExiting();
}
}
// static
void BrowserList::AddObserver(chrome::BrowserListObserver* observer) {
observers_.Get().AddObserver(observer);
}
// static
void BrowserList::RemoveObserver(chrome::BrowserListObserver* observer) {
observers_.Get().RemoveObserver(observer);
}
void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
BrowserVector browsers_to_close;
for (chrome::BrowserIterator it; !it.done(); it.Next()) {
if (it->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
browsers_to_close.push_back(*it);
}
for (BrowserVector::const_iterator it = browsers_to_close.begin();
it != browsers_to_close.end(); ++it) {
(*it)->window()->Close();
}
}
// static
void BrowserList::SetLastActive(Browser* browser) {
content::RecordAction(UserMetricsAction("ActiveBrowserChanged"));
BrowserList* browser_list = GetInstance(browser->host_desktop_type());
RemoveBrowserFrom(browser, &browser_list->last_active_browsers_);
browser_list->last_active_browsers_.push_back(browser);
FOR_EACH_OBSERVER(chrome::BrowserListObserver, observers_.Get(),
OnBrowserSetLastActive(browser));
}
// static
bool BrowserList::IsOffTheRecordSessionActive() {
for (chrome::BrowserIterator it; !it.done(); it.Next()) {
if (it->profile()->IsOffTheRecord())
return true;
}
return false;
}
// static
bool BrowserList::IsOffTheRecordSessionActiveForProfile(Profile* profile) {
if (profile->IsGuestSession())
return true;
for (chrome::BrowserIterator it; !it.done(); it.Next()) {
if (it->profile()->IsSameProfile(profile) &&
it->profile()->IsOffTheRecord()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
// BrowserList, private:
BrowserList::BrowserList() {
}
BrowserList::~BrowserList() {
}
// static
void BrowserList::RemoveBrowserFrom(Browser* browser,
BrowserVector* browser_list) {
BrowserVector::iterator remove_browser =
std::find(browser_list->begin(), browser_list->end(), browser);
if (remove_browser != browser_list->end())
browser_list->erase(remove_browser);
}