Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(257)

Unified Diff: chrome/browser/lifetime/application_lifetime.cc

Issue 10409022: Move application lifetime functionality off BrowserList. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/lifetime/application_lifetime.cc
===================================================================
--- chrome/browser/lifetime/application_lifetime.cc (revision 0)
+++ chrome/browser/lifetime/application_lifetime.cc (working copy)
@@ -7,14 +7,12 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop.h"
-#include "base/metrics/histogram.h"
#include "build/build_config.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/download/download_service.h"
#include "chrome/browser/metrics/thread_watcher.h"
#include "chrome/browser/prefs/pref_service.h"
-#include "chrome/browser/printing/background_printing_manager.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/browser.h"
@@ -26,10 +24,7 @@
#include "content/public/browser/browser_shutdown.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/navigation_details.h"
-#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/common/result_codes.h"
#if defined(OS_MACOSX)
#include "chrome/browser/chrome_browser_application_mac.h"
@@ -44,98 +39,9 @@
#include "chromeos/dbus/update_engine_client.h"
#endif
-using content::WebContents;
-
+namespace browser {
namespace {
-// This object is instantiated when the first Browser object is added to the
-// list and delete when the last one is removed. It watches for loads and
-// creates histograms of some global object counts.
-class BrowserActivityObserver : public content::NotificationObserver {
- public:
- BrowserActivityObserver() {
- registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
- content::NotificationService::AllSources());
- }
- ~BrowserActivityObserver() {}
-
- private:
- // content::NotificationObserver implementation.
- virtual void Observe(int type,
- const content::NotificationSource& source,
- const content::NotificationDetails& details) {
- DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED);
- const content::LoadCommittedDetails& load =
- *content::Details<content::LoadCommittedDetails>(details).ptr();
- if (!load.is_navigation_to_different_page())
- return; // Don't log for subframes or other trivial types.
-
- LogRenderProcessHostCount();
- LogBrowserTabCount();
- }
-
- // Counts the number of active RenderProcessHosts and logs them.
- void LogRenderProcessHostCount() const {
- int hosts_count = 0;
- for (content::RenderProcessHost::iterator i(
- content::RenderProcessHost::AllHostsIterator());
- !i.IsAtEnd(); i.Advance())
- ++hosts_count;
- UMA_HISTOGRAM_CUSTOM_COUNTS("MPArch.RPHCountPerLoad", hosts_count,
- 1, 50, 50);
- }
-
- // Counts the number of tabs in each browser window and logs them. This is
- // different than the number of WebContents objects since WebContents objects
- // can be used for popups and in dialog boxes. We're just counting toplevel
- // tabs here.
- void LogBrowserTabCount() const {
- int tab_count = 0;
- for (BrowserList::const_iterator browser_iterator = BrowserList::begin();
- browser_iterator != BrowserList::end(); browser_iterator++) {
- // Record how many tabs each window has open.
- UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerWindow",
- (*browser_iterator)->tab_count(), 1, 200, 50);
- tab_count += (*browser_iterator)->tab_count();
- }
- // Record how many tabs total are open (across all windows).
- UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountPerLoad", tab_count, 1, 200, 50);
-
- Browser* browser = BrowserList::GetLastActive();
- if (browser) {
- // Record how many tabs the active window has open.
- UMA_HISTOGRAM_CUSTOM_COUNTS("Tabs.TabCountActiveWindow",
- browser->tab_count(), 1, 200, 50);
- }
- }
-
- content::NotificationRegistrar registrar_;
-
- DISALLOW_COPY_AND_ASSIGN(BrowserActivityObserver);
-};
-
-BrowserActivityObserver* activity_observer = NULL;
-
-static BrowserList::BrowserVector& browsers() {
- CR_DEFINE_STATIC_LOCAL(BrowserList::BrowserVector, browser_vector, ());
- return browser_vector;
-}
-
-static BrowserList::BrowserVector& last_active_browsers() {
- CR_DEFINE_STATIC_LOCAL(BrowserList::BrowserVector, last_active_vector, ());
- return last_active_vector;
-}
-
-static ObserverList<BrowserList::Observer>& observers() {
- CR_DEFINE_STATIC_LOCAL(
- ObserverList<BrowserList::Observer>, observer_vector, ());
- return observer_vector;
-}
-
-printing::BackgroundPrintingManager* GetBackgroundPrintingManager() {
- return g_browser_process->background_printing_manager();
-}
-
// Returns true if all browsers can be closed without user interaction.
// This currently checks if there is pending download, or if it needs to
// handle unload handler.
@@ -156,18 +62,7 @@
return true;
}
-// Emits APP_TERMINATING notification. It is guaranteed that the
-// notification is sent only once.
-void NotifyAppTerminating() {
- static bool notified = false;
- if (notified)
- return;
- notified = true;
- content::NotificationService::current()->Notify(
- content::NOTIFICATION_APP_TERMINATING,
- content::NotificationService::AllSources(),
- content::NotificationService::NoDetails());
-}
+int g_keep_alive_count = 0;
#if defined(OS_CHROMEOS)
// Whether a session manager requested to shutdown.
@@ -176,37 +71,15 @@
} // namespace
-// static
-void BrowserList::AddBrowser(Browser* browser) {
- DCHECK(browser);
- browsers().push_back(browser);
-
- g_browser_process->AddRefModule();
-
- if (!activity_observer)
- activity_observer = new BrowserActivityObserver;
-
- 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(Observer, observers(), OnBrowserAdded(browser));
- DCHECK_EQ(original_count, observers().size())
- << "observer list modified during notification";
-}
-
-// static
-void BrowserList::MarkAsCleanShutdown() {
- for (const_iterator i = begin(); i != end(); ++i) {
+void MarkAsCleanShutdown() {
+ // TODO(beng): Can this use ProfileManager::GetLoadedProfiles() instead?
+ for (BrowserList::const_iterator i = BrowserList::begin();
+ i != BrowserList::end(); ++i) {
(*i)->profile()->MarkAsCleanShutdown();
}
}
-void BrowserList::AttemptExitInternal() {
+void AttemptExitInternal() {
content::NotificationService::current()->Notify(
content::NOTIFICATION_APP_EXITING,
content::NotificationService::AllSources(),
@@ -223,8 +96,18 @@
#endif
}
-// static
-void BrowserList::NotifyAndTerminate(bool fast_path) {
+void NotifyAppTerminating() {
+ static bool notified = false;
+ if (notified)
+ return;
+ notified = true;
+ content::NotificationService::current()->Notify(
+ content::NOTIFICATION_APP_TERMINATING,
+ content::NotificationService::AllSources(),
+ content::NotificationService::NoDetails());
+}
+
+void NotifyAndTerminate(bool fast_path) {
#if defined(OS_CHROMEOS)
static bool notified = false;
// Don't ask SessionManager to shutdown if
@@ -255,87 +138,20 @@
// If running the Chrome OS build, but we're not on the device, act
// as if we received signal from SessionManager.
content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&BrowserList::ExitCleanly));
+ base::Bind(&browser::ExitCleanly));
}
#endif
}
-void BrowserList::OnAppExiting() {
+void OnAppExiting() {
static bool notified = false;
if (notified)
return;
notified = true;
-
- delete activity_observer;
- activity_observer = NULL;
HandleAppExitingForPlatform();
}
-// static
-void BrowserList::RemoveBrowser(Browser* browser) {
- RemoveBrowserFrom(browser, &last_active_browsers());
-
- // Many UI tests rely on closing the last browser window quitting the
- // application.
- // Mac: Closing all windows does not indicate quitting the application. Lie
- // for now and ignore behavior outside of unit tests.
- // ChromeOS: Force closing last window to close app with flag.
- // TODO(andybons | pkotwicz): Fix the UI tests to Do The Right Thing.
-#if defined(OS_CHROMEOS)
- bool closing_app;
- if (CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableZeroBrowsersOpenForTests))
- closing_app = (browsers().size() == 1);
- else
- closing_app = (browsers().size() == 1 &&
- browser_shutdown::IsTryingToQuit());
-#else
- bool closing_app = (browsers().size() == 1);
-#endif // OS_CHROMEOS
-
- content::NotificationService::current()->Notify(
- chrome::NOTIFICATION_BROWSER_CLOSED,
- content::Source<Browser>(browser),
- content::Details<bool>(&closing_app));
-
- RemoveBrowserFrom(browser, &browsers());
-
- // 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(Observer, observers(), OnBrowserRemoved(browser));
- DCHECK_EQ(original_count, observers().size())
- << "observer list modified during notification";
-
- 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.
- NotifyAppTerminating();
- OnAppExiting();
- }
-}
-
-// static
-void BrowserList::AddObserver(BrowserList::Observer* observer) {
- observers().AddObserver(observer);
-}
-
-// static
-void BrowserList::RemoveObserver(BrowserList::Observer* observer) {
- observers().RemoveObserver(observer);
-}
-
-// static
-void BrowserList::CloseAllBrowsers() {
+void CloseAllBrowsers() {
bool session_ending =
browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
// Tell everyone that we are shutting down.
@@ -348,7 +164,7 @@
// If there are no browsers, send the APP_TERMINATING action here. Otherwise,
// it will be sent by RemoveBrowser() when the last browser has closed.
if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() ||
- browsers().empty()) {
+ BrowserList::empty()) {
NotifyAndTerminate(true);
OnAppExiting();
return;
@@ -386,22 +202,7 @@
}
}
-void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
- BrowserVector browsers_to_close;
- for (BrowserList::const_iterator i = BrowserList::begin();
- i != BrowserList::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();
- }
-}
-
-// static
-void BrowserList::AttemptUserExit() {
+void AttemptUserExit() {
#if defined(OS_CHROMEOS)
chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false);
// Write /tmp/uptime-logout-started as well.
@@ -422,7 +223,7 @@
g_session_manager_requested_shutdown = false;
// On ChromeOS, always terminate the browser, regardless of the result of
// AreAllBrowsersCloseable(). See crbug.com/123107.
- BrowserList::NotifyAndTerminate(true);
+ NotifyAndTerminate(true);
#else
// Reset the restart bit that might have been set in cancelled restart
// request.
@@ -432,12 +233,12 @@
#endif
}
-// static
-void BrowserList::AttemptRestart() {
+void AttemptRestart() {
if (!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRestoreSessionState)) {
- BrowserVector::const_iterator it;
- for (it = begin(); it != end(); ++it)
+ // TODO(beng): Can this use ProfileManager::GetLoadedProfiles instead?
+ BrowserList::const_iterator it;
+ for (it = BrowserList::begin(); it != BrowserList::end(); ++it)
content::BrowserContext::SaveSessionState((*it)->profile());
}
@@ -456,8 +257,7 @@
#endif
}
-// static
-void BrowserList::AttemptExit() {
+void AttemptExit() {
// If we know that all browsers can be closed without blocking,
// don't notify users of crashes beyond this point.
// Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit
@@ -469,8 +269,7 @@
#if defined(OS_CHROMEOS)
// A function called when SIGTERM is received.
-// static
-void BrowserList::ExitCleanly() {
+void ExitCleanly() {
// We always mark exit cleanly because SessionManager may kill
// chrome in 3 seconds after SIGTERM.
g_browser_process->EndSession();
@@ -484,8 +283,7 @@
}
#endif
-// static
-void BrowserList::SessionEnding() {
+void SessionEnding() {
// This is a time-limited shutdown where we need to write as much to
// disk as we can as soon as we can, and where we must kill the
// process within a hang timeout to avoid user prompts.
@@ -514,7 +312,7 @@
// Write important data first.
g_browser_process->EndSession();
- BrowserList::CloseAllBrowsers();
+ CloseAllBrowsers();
// Send out notification. This is used during testing so that the test harness
// can properly shutdown before we exit.
@@ -527,22 +325,17 @@
content::ImmediateShutdownAndExitProcess();
}
-// static
-int BrowserList::keep_alive_count_ = 0;
-
-// static
-void BrowserList::StartKeepAlive() {
+void StartKeepAlive() {
// Increment the browser process refcount as long as we're keeping the
// application alive.
if (!WillKeepAlive())
g_browser_process->AddRefModule();
- keep_alive_count_++;
+ ++g_keep_alive_count;
}
-// static
-void BrowserList::EndKeepAlive() {
- DCHECK_GT(keep_alive_count_, 0);
- keep_alive_count_--;
+void EndKeepAlive() {
+ DCHECK_GT(g_keep_alive_count, 0);
+ --g_keep_alive_count;
DCHECK(g_browser_process);
// Although we should have a browser process, if there is none,
@@ -555,142 +348,14 @@
// If there are no browsers open and we aren't already shutting down,
// initiate a shutdown. Also skips shutdown if this is a unit test
// (MessageLoop::current() == null).
- if (browsers().empty() && !browser_shutdown::IsTryingToQuit() &&
+ if (BrowserList::empty() && !browser_shutdown::IsTryingToQuit() &&
MessageLoop::current())
CloseAllBrowsers();
}
}
-// static
-bool BrowserList::WillKeepAlive() {
- return keep_alive_count_ > 0;
+bool WillKeepAlive() {
+ return g_keep_alive_count > 0;
}
-// static
-BrowserList::const_iterator BrowserList::begin() {
- return browsers().begin();
-}
-
-// static
-BrowserList::const_iterator BrowserList::end() {
- return browsers().end();
-}
-
-// static
-bool BrowserList::empty() {
- return browsers().empty();
-}
-
-// static
-size_t BrowserList::size() {
- return browsers().size();
-}
-
-// static
-void BrowserList::SetLastActive(Browser* browser) {
- // If the browser is currently trying to quit, we don't want to set the last
- // active browser because that can alter the last active browser that the user
- // intended depending on the order in which the windows close.
- if (browser_shutdown::IsTryingToQuit())
- return;
- RemoveBrowserFrom(browser, &last_active_browsers());
- last_active_browsers().push_back(browser);
-
- FOR_EACH_OBSERVER(Observer, observers(), OnBrowserSetLastActive(browser));
-}
-
-// static
-Browser* BrowserList::GetLastActive() {
- if (!last_active_browsers().empty())
- return *(last_active_browsers().rbegin());
-
- return NULL;
-}
-
-// static
-BrowserList::const_reverse_iterator BrowserList::begin_last_active() {
- return last_active_browsers().rbegin();
-}
-
-// static
-BrowserList::const_reverse_iterator BrowserList::end_last_active() {
- return last_active_browsers().rend();
-}
-
-// static
-bool BrowserList::IsOffTheRecordSessionActive() {
- for (BrowserList::const_iterator i = BrowserList::begin();
- i != BrowserList::end(); ++i) {
- if ((*i)->profile()->IsOffTheRecord())
- return true;
- }
- return false;
-}
-
-// static
-bool BrowserList::IsOffTheRecordSessionActiveForProfile(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 (BrowserList::const_iterator i = BrowserList::begin();
- i != BrowserList::end(); ++i) {
- if ((*i)->profile()->IsSameProfile(profile) &&
- (*i)->profile()->IsOffTheRecord()) {
- return true;
- }
- }
- return false;
-}
-
-// static
-void BrowserList::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);
-}
-
-TabContentsIterator::TabContentsIterator()
- : browser_iterator_(BrowserList::begin()),
- web_view_index_(-1),
- bg_printing_iterator_(GetBackgroundPrintingManager()->begin()),
- cur_(NULL) {
- Advance();
-}
-
-void TabContentsIterator::Advance() {
- // The current WebContents should be valid unless we are at the beginning.
- DCHECK(cur_ || (web_view_index_ == -1 &&
- browser_iterator_ == BrowserList::begin()))
- << "Trying to advance past the end";
-
- // Update cur_ to the next WebContents in the list.
- while (browser_iterator_ != BrowserList::end()) {
- if (++web_view_index_ >= (*browser_iterator_)->tab_count()) {
- // Advance to the next Browser in the list.
- ++browser_iterator_;
- web_view_index_ = -1;
- continue;
- }
-
- TabContentsWrapper* next_tab =
- (*browser_iterator_)->GetTabContentsWrapperAt(web_view_index_);
- if (next_tab) {
- cur_ = next_tab;
- return;
- }
- }
- // If no more WebContents from Browsers, check the BackgroundPrintingManager.
- while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) {
- cur_ = *bg_printing_iterator_;
- CHECK(cur_);
- ++bg_printing_iterator_;
- return;
- }
- // Reached the end - no more WebContents.
- cur_ = NULL;
-}
+} // namespace browser
« no previous file with comments | « chrome/browser/lifetime/application_lifetime.h ('k') | chrome/browser/lifetime/application_lifetime_aura.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698