blob: 178f40849f703f0f8574b942739130192d9aeb1a [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_impl.h"
#include "base/command_line.h"
#include "base/logging.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.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_list_observer.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/notification_service.h"
// #include "build/build_config.h"
// #include "chrome/browser/prefs/pref_service.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/login/user_manager.h"
#endif
namespace chrome {
// static
BrowserListImpl* BrowserListImpl::native_instance_ = NULL;
BrowserListImpl* BrowserListImpl::ash_instance_ = NULL;
////////////////////////////////////////////////////////////////////////////////
// BrowserListImpl, public:
// static
BrowserListImpl* BrowserListImpl::GetInstance(HostDesktopType type) {
BrowserListImpl** list = NULL;
if (type == HOST_DESKTOP_TYPE_NATIVE)
list = &native_instance_;
else if (type == HOST_DESKTOP_TYPE_ASH)
list = &ash_instance_;
else
NOTREACHED();
if (!*list)
*list = new BrowserListImpl;
return *list;
}
void BrowserListImpl::AddBrowser(Browser* browser) {
DCHECK(browser);
browsers_.push_back(browser);
g_browser_process->AddRefModule();
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_BROWSER_OPENED,
content::Source<Browser>(browser),
content::NotificationService::NoDetails());
// Send out notifications after add has occurred. Do some basic checking to
// try to catch evil observers that change the list from under us.
size_t original_count = observers_.size();
FOR_EACH_OBSERVER(BrowserListObserver, observers_, OnBrowserAdded(browser));
DCHECK_EQ(original_count, observers_.size())
<< "observer list modified during notification";
}
void BrowserListImpl::RemoveBrowser(Browser* browser) {
RemoveBrowserFrom(browser, &last_active_browsers_);
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_BROWSER_CLOSED,
content::Source<Browser>(browser),
content::NotificationService::NoDetails());
RemoveBrowserFrom(browser, &browsers_);
FOR_EACH_OBSERVER(BrowserListObserver, observers_, 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 (browsers_.empty() &&
(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.
browser::NotifyAppTerminating();
browser::OnAppExiting();
}
}
void BrowserListImpl::AddObserver(BrowserListObserver* observer) {
observers_.AddObserver(observer);
}
void BrowserListImpl::RemoveObserver(BrowserListObserver* observer) {
observers_.RemoveObserver(observer);
}
void BrowserListImpl::SetLastActive(Browser* browser) {
RemoveBrowserFrom(browser, &last_active_browsers_);
last_active_browsers_.push_back(browser);
FOR_EACH_OBSERVER(BrowserListObserver, observers_,
OnBrowserSetLastActive(browser));
}
Browser* BrowserListImpl::GetLastActive() {
if (!last_active_browsers_.empty())
return *(last_active_browsers_.rbegin());
return NULL;
}
void BrowserListImpl::CloseAllBrowsersWithProfile(Profile* profile) {
BrowserVector browsers_to_close;
for (BrowserListImpl::const_iterator i = BrowserListImpl::begin();
i != BrowserListImpl::end(); ++i) {
if ((*i)->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
browsers_to_close.push_back(*i);
}
for (BrowserVector::const_iterator i = browsers_to_close.begin();
i != browsers_to_close.end(); ++i) {
(*i)->window()->Close();
}
}
bool BrowserListImpl::IsIncognitoWindowOpen() {
for (BrowserListImpl::const_iterator i = BrowserListImpl::begin();
i != BrowserListImpl::end(); ++i) {
if ((*i)->profile()->IsOffTheRecord())
return true;
}
return false;
}
bool BrowserListImpl::IsIncognitoWindowOpenForProfile(Profile* profile) {
#if defined(OS_CHROMEOS)
// In ChromeOS, we assume that the default profile is always valid, so if
// we are in guest mode, keep the OTR profile active so it won't be deleted.
if (chromeos::UserManager::Get()->IsLoggedInAsGuest())
return true;
#endif
for (BrowserListImpl::const_iterator i = BrowserListImpl::begin();
i != BrowserListImpl::end(); ++i) {
if ((*i)->profile()->IsSameProfile(profile) &&
(*i)->profile()->IsOffTheRecord()) {
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////////////
// BrowserListImpl, private:
BrowserListImpl::BrowserListImpl() {
}
BrowserListImpl::~BrowserListImpl() {
}
void BrowserListImpl::RemoveBrowserFrom(Browser* browser,
BrowserVector* browser_list) {
const iterator remove_browser =
std::find(browser_list->begin(), browser_list->end(), browser);
if (remove_browser != browser_list->end())
browser_list->erase(remove_browser);
}
} // namespace chrome