// 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), 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), 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