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

Side by Side Diff: chrome/browser/ui/browser_list.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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/ui/browser_list.h ('k') | chrome/browser/ui/browser_list_aura.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/browser_list.h" 5 #include "chrome/browser/ui/browser_list.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop.h"
10 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
11 #include "build/build_config.h" 10 #include "build/build_config.h"
12 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/browser_shutdown.h" 12 #include "chrome/browser/browser_shutdown.h"
14 #include "chrome/browser/download/download_service.h" 13 #include "chrome/browser/lifetime/application_lifetime.h"
15 #include "chrome/browser/metrics/thread_watcher.h"
16 #include "chrome/browser/prefs/pref_service.h" 14 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/browser/printing/background_printing_manager.h" 15 #include "chrome/browser/printing/background_printing_manager.h"
18 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/browser/ui/browser.h" 17 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_window.h" 18 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 19 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
23 #include "chrome/common/chrome_notification_types.h" 20 #include "chrome/common/chrome_notification_types.h"
24 #include "chrome/common/chrome_switches.h" 21 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
26 #include "content/public/browser/browser_shutdown.h" 23 #include "content/public/browser/browser_shutdown.h"
27 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
28 #include "content/public/browser/navigation_details.h" 25 #include "content/public/browser/navigation_details.h"
29 #include "content/public/browser/notification_registrar.h" 26 #include "content/public/browser/notification_registrar.h"
30 #include "content/public/browser/notification_service.h" 27 #include "content/public/browser/notification_service.h"
31 #include "content/public/browser/render_process_host.h" 28 #include "content/public/browser/render_process_host.h"
32 #include "content/public/common/result_codes.h" 29 #include "content/public/common/result_codes.h"
33 30
34 #if defined(OS_MACOSX)
35 #include "chrome/browser/chrome_browser_application_mac.h"
36 #endif
37
38 #if defined(OS_CHROMEOS) 31 #if defined(OS_CHROMEOS)
39 #include "base/chromeos/chromeos_version.h"
40 #include "chrome/browser/chromeos/boot_times_loader.h"
41 #include "chrome/browser/chromeos/login/user_manager.h" 32 #include "chrome/browser/chromeos/login/user_manager.h"
42 #include "chromeos/dbus/dbus_thread_manager.h"
43 #include "chromeos/dbus/session_manager_client.h"
44 #include "chromeos/dbus/update_engine_client.h"
45 #endif 33 #endif
46 34
47 using content::WebContents; 35 using content::WebContents;
48 36
49 namespace { 37 namespace {
50 38
51 // This object is instantiated when the first Browser object is added to the 39 // This object is instantiated when the first Browser object is added to the
52 // list and delete when the last one is removed. It watches for loads and 40 // list and delete when the last one is removed. It watches for loads and
53 // creates histograms of some global object counts. 41 // creates histograms of some global object counts.
54 class BrowserActivityObserver : public content::NotificationObserver { 42 class BrowserActivityObserver : public content::NotificationObserver {
55 public: 43 public:
56 BrowserActivityObserver() { 44 BrowserActivityObserver() {
57 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED, 45 registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_COMMITTED,
58 content::NotificationService::AllSources()); 46 content::NotificationService::AllSources());
47 registrar_.Add(this, content::NOTIFICATION_APP_TERMINATING,
48 content::NotificationService::AllSources());
59 } 49 }
60 ~BrowserActivityObserver() {} 50 ~BrowserActivityObserver() {}
61 51
62 private: 52 private:
63 // content::NotificationObserver implementation. 53 // content::NotificationObserver implementation.
64 virtual void Observe(int type, 54 virtual void Observe(int type,
65 const content::NotificationSource& source, 55 const content::NotificationSource& source,
66 const content::NotificationDetails& details) { 56 const content::NotificationDetails& details) {
67 DCHECK(type == content::NOTIFICATION_NAV_ENTRY_COMMITTED); 57 if (type == content::NOTIFICATION_NAV_ENTRY_COMMITTED) {
68 const content::LoadCommittedDetails& load = 58 const content::LoadCommittedDetails& load =
69 *content::Details<content::LoadCommittedDetails>(details).ptr(); 59 *content::Details<content::LoadCommittedDetails>(details).ptr();
70 if (!load.is_navigation_to_different_page()) 60 if (!load.is_navigation_to_different_page())
71 return; // Don't log for subframes or other trivial types. 61 return; // Don't log for subframes or other trivial types.
72 62
73 LogRenderProcessHostCount(); 63 LogRenderProcessHostCount();
74 LogBrowserTabCount(); 64 LogBrowserTabCount();
65 } else if (type == content::NOTIFICATION_APP_TERMINATING) {
66 delete this;
67 }
75 } 68 }
76 69
77 // Counts the number of active RenderProcessHosts and logs them. 70 // Counts the number of active RenderProcessHosts and logs them.
78 void LogRenderProcessHostCount() const { 71 void LogRenderProcessHostCount() const {
79 int hosts_count = 0; 72 int hosts_count = 0;
80 for (content::RenderProcessHost::iterator i( 73 for (content::RenderProcessHost::iterator i(
81 content::RenderProcessHost::AllHostsIterator()); 74 content::RenderProcessHost::AllHostsIterator());
82 !i.IsAtEnd(); i.Advance()) 75 !i.IsAtEnd(); i.Advance())
83 ++hosts_count; 76 ++hosts_count;
84 UMA_HISTOGRAM_CUSTOM_COUNTS("MPArch.RPHCountPerLoad", hosts_count, 77 UMA_HISTOGRAM_CUSTOM_COUNTS("MPArch.RPHCountPerLoad", hosts_count,
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
129 static ObserverList<BrowserList::Observer>& observers() { 122 static ObserverList<BrowserList::Observer>& observers() {
130 CR_DEFINE_STATIC_LOCAL( 123 CR_DEFINE_STATIC_LOCAL(
131 ObserverList<BrowserList::Observer>, observer_vector, ()); 124 ObserverList<BrowserList::Observer>, observer_vector, ());
132 return observer_vector; 125 return observer_vector;
133 } 126 }
134 127
135 printing::BackgroundPrintingManager* GetBackgroundPrintingManager() { 128 printing::BackgroundPrintingManager* GetBackgroundPrintingManager() {
136 return g_browser_process->background_printing_manager(); 129 return g_browser_process->background_printing_manager();
137 } 130 }
138 131
139 // Returns true if all browsers can be closed without user interaction.
140 // This currently checks if there is pending download, or if it needs to
141 // handle unload handler.
142 bool AreAllBrowsersCloseable() {
143 BrowserList::const_iterator browser_it = BrowserList::begin();
144 if (browser_it == BrowserList::end())
145 return true;
146
147 // If there are any downloads active, all browsers are not closeable.
148 if (DownloadService::DownloadCountAllProfiles() > 0)
149 return false;
150
151 // Check TabsNeedBeforeUnloadFired().
152 for (; browser_it != BrowserList::end(); ++browser_it) {
153 if ((*browser_it)->TabsNeedBeforeUnloadFired())
154 return false;
155 }
156 return true;
157 }
158
159 // Emits APP_TERMINATING notification. It is guaranteed that the
160 // notification is sent only once.
161 void NotifyAppTerminating() {
162 static bool notified = false;
163 if (notified)
164 return;
165 notified = true;
166 content::NotificationService::current()->Notify(
167 content::NOTIFICATION_APP_TERMINATING,
168 content::NotificationService::AllSources(),
169 content::NotificationService::NoDetails());
170 }
171
172 #if defined(OS_CHROMEOS)
173 // Whether a session manager requested to shutdown.
174 bool g_session_manager_requested_shutdown = true;
175 #endif
176
177 } // namespace 132 } // namespace
178 133
179 // static 134 // static
180 void BrowserList::AddBrowser(Browser* browser) { 135 void BrowserList::AddBrowser(Browser* browser) {
181 DCHECK(browser); 136 DCHECK(browser);
182 browsers().push_back(browser); 137 browsers().push_back(browser);
183 138
184 g_browser_process->AddRefModule(); 139 g_browser_process->AddRefModule();
185 140
186 if (!activity_observer) 141 if (!activity_observer)
187 activity_observer = new BrowserActivityObserver; 142 activity_observer = new BrowserActivityObserver;
188 143
189 content::NotificationService::current()->Notify( 144 content::NotificationService::current()->Notify(
190 chrome::NOTIFICATION_BROWSER_OPENED, 145 chrome::NOTIFICATION_BROWSER_OPENED,
191 content::Source<Browser>(browser), 146 content::Source<Browser>(browser),
192 content::NotificationService::NoDetails()); 147 content::NotificationService::NoDetails());
193 148
194 // Send out notifications after add has occurred. Do some basic checking to 149 // Send out notifications after add has occurred. Do some basic checking to
195 // try to catch evil observers that change the list from under us. 150 // try to catch evil observers that change the list from under us.
196 size_t original_count = observers().size(); 151 size_t original_count = observers().size();
197 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserAdded(browser)); 152 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserAdded(browser));
198 DCHECK_EQ(original_count, observers().size()) 153 DCHECK_EQ(original_count, observers().size())
199 << "observer list modified during notification"; 154 << "observer list modified during notification";
200 } 155 }
201 156
202 // static 157 // static
203 void BrowserList::MarkAsCleanShutdown() {
204 for (const_iterator i = begin(); i != end(); ++i) {
205 (*i)->profile()->MarkAsCleanShutdown();
206 }
207 }
208
209 void BrowserList::AttemptExitInternal() {
210 content::NotificationService::current()->Notify(
211 content::NOTIFICATION_APP_EXITING,
212 content::NotificationService::AllSources(),
213 content::NotificationService::NoDetails());
214
215 #if !defined(OS_MACOSX)
216 // On most platforms, closing all windows causes the application to exit.
217 CloseAllBrowsers();
218 #else
219 // On the Mac, the application continues to run once all windows are closed.
220 // Terminate will result in a CloseAllBrowsers() call, and once (and if)
221 // that is done, will cause the application to exit cleanly.
222 chrome_browser_application_mac::Terminate();
223 #endif
224 }
225
226 // static
227 void BrowserList::NotifyAndTerminate(bool fast_path) {
228 #if defined(OS_CHROMEOS)
229 static bool notified = false;
230 // Don't ask SessionManager to shutdown if
231 // a) a shutdown request has already been sent.
232 // b) shutdown request comes from session manager.
233 if (notified || g_session_manager_requested_shutdown)
234 return;
235 notified = true;
236 #endif
237
238 if (fast_path)
239 NotifyAppTerminating();
240
241 #if defined(OS_CHROMEOS)
242 if (base::chromeos::IsRunningOnChromeOS()) {
243 // If we're on a ChromeOS device, reboot if an update has been applied,
244 // or else signal the session manager to log out.
245 chromeos::UpdateEngineClient* update_engine_client
246 = chromeos::DBusThreadManager::Get()->GetUpdateEngineClient();
247 if (update_engine_client->GetLastStatus().status ==
248 chromeos::UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT) {
249 update_engine_client->RebootAfterUpdate();
250 } else {
251 chromeos::DBusThreadManager::Get()->GetSessionManagerClient()
252 ->StopSession();
253 }
254 } else {
255 // If running the Chrome OS build, but we're not on the device, act
256 // as if we received signal from SessionManager.
257 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
258 base::Bind(&BrowserList::ExitCleanly));
259 }
260 #endif
261 }
262
263 void BrowserList::OnAppExiting() {
264 static bool notified = false;
265 if (notified)
266 return;
267 notified = true;
268
269 delete activity_observer;
270 activity_observer = NULL;
271 HandleAppExitingForPlatform();
272 }
273
274 // static
275 void BrowserList::RemoveBrowser(Browser* browser) { 158 void BrowserList::RemoveBrowser(Browser* browser) {
276 RemoveBrowserFrom(browser, &last_active_browsers()); 159 RemoveBrowserFrom(browser, &last_active_browsers());
277 160
278 // Many UI tests rely on closing the last browser window quitting the 161 // Many UI tests rely on closing the last browser window quitting the
279 // application. 162 // application.
280 // Mac: Closing all windows does not indicate quitting the application. Lie 163 // Mac: Closing all windows does not indicate quitting the application. Lie
281 // for now and ignore behavior outside of unit tests. 164 // for now and ignore behavior outside of unit tests.
282 // ChromeOS: Force closing last window to close app with flag. 165 // ChromeOS: Force closing last window to close app with flag.
283 // TODO(andybons | pkotwicz): Fix the UI tests to Do The Right Thing. 166 // TODO(andybons | pkotwicz): Fix the UI tests to Do The Right Thing.
284 #if defined(OS_CHROMEOS) 167 #if defined(OS_CHROMEOS)
(...skipping 27 matching lines...) Expand all
312 // If we're exiting, send out the APP_TERMINATING notification to allow other 195 // If we're exiting, send out the APP_TERMINATING notification to allow other
313 // modules to shut themselves down. 196 // modules to shut themselves down.
314 if (browsers().empty() && 197 if (browsers().empty() &&
315 (browser_shutdown::IsTryingToQuit() || 198 (browser_shutdown::IsTryingToQuit() ||
316 g_browser_process->IsShuttingDown())) { 199 g_browser_process->IsShuttingDown())) {
317 // Last browser has just closed, and this is a user-initiated quit or there 200 // Last browser has just closed, and this is a user-initiated quit or there
318 // is no module keeping the app alive, so send out our notification. No need 201 // is no module keeping the app alive, so send out our notification. No need
319 // to call ProfileManager::ShutdownSessionServices() as part of the 202 // to call ProfileManager::ShutdownSessionServices() as part of the
320 // shutdown, because Browser::WindowClosing() already makes sure that the 203 // shutdown, because Browser::WindowClosing() already makes sure that the
321 // SessionService is created and notified. 204 // SessionService is created and notified.
322 NotifyAppTerminating(); 205 browser::NotifyAppTerminating();
323 OnAppExiting(); 206 browser::OnAppExiting();
324 } 207 }
325 } 208 }
326 209
327 // static 210 // static
328 void BrowserList::AddObserver(BrowserList::Observer* observer) { 211 void BrowserList::AddObserver(BrowserList::Observer* observer) {
329 observers().AddObserver(observer); 212 observers().AddObserver(observer);
330 } 213 }
331 214
332 // static 215 // static
333 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { 216 void BrowserList::RemoveObserver(BrowserList::Observer* observer) {
334 observers().RemoveObserver(observer); 217 observers().RemoveObserver(observer);
335 } 218 }
336 219
337 // static
338 void BrowserList::CloseAllBrowsers() {
339 bool session_ending =
340 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION;
341 // Tell everyone that we are shutting down.
342 browser_shutdown::SetTryingToQuit(true);
343
344 // Before we close the browsers shutdown all session services. That way an
345 // exit can restore all browsers open before exiting.
346 ProfileManager::ShutdownSessionServices();
347
348 // If there are no browsers, send the APP_TERMINATING action here. Otherwise,
349 // it will be sent by RemoveBrowser() when the last browser has closed.
350 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() ||
351 browsers().empty()) {
352 NotifyAndTerminate(true);
353 OnAppExiting();
354 return;
355 }
356
357 #if defined(OS_CHROMEOS)
358 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker(
359 "StartedClosingWindows", false);
360 #endif
361 for (BrowserList::const_iterator i = BrowserList::begin();
362 i != BrowserList::end();) {
363 Browser* browser = *i;
364 browser->window()->Close();
365 if (!session_ending) {
366 ++i;
367 } else {
368 // This path is hit during logoff/power-down. In this case we won't get
369 // a final message and so we force the browser to be deleted.
370 // Close doesn't immediately destroy the browser
371 // (Browser::TabStripEmpty() uses invoke later) but when we're ending the
372 // session we need to make sure the browser is destroyed now. So, invoke
373 // DestroyBrowser to make sure the browser is deleted and cleanup can
374 // happen.
375 while (browser->tab_count())
376 delete browser->GetTabContentsWrapperAt(0);
377 browser->window()->DestroyBrowser();
378 i = BrowserList::begin();
379 if (i != BrowserList::end() && browser == *i) {
380 // Destroying the browser should have removed it from the browser list.
381 // We should never get here.
382 NOTREACHED();
383 return;
384 }
385 }
386 }
387 }
388
389 void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) { 220 void BrowserList::CloseAllBrowsersWithProfile(Profile* profile) {
390 BrowserVector browsers_to_close; 221 BrowserVector browsers_to_close;
391 for (BrowserList::const_iterator i = BrowserList::begin(); 222 for (BrowserList::const_iterator i = BrowserList::begin();
392 i != BrowserList::end(); ++i) { 223 i != BrowserList::end(); ++i) {
393 if ((*i)->profile()->GetOriginalProfile() == profile->GetOriginalProfile()) 224 if ((*i)->profile()->GetOriginalProfile() == profile->GetOriginalProfile())
394 browsers_to_close.push_back(*i); 225 browsers_to_close.push_back(*i);
395 } 226 }
396 227
397 for (BrowserVector::const_iterator i = browsers_to_close.begin(); 228 for (BrowserVector::const_iterator i = browsers_to_close.begin();
398 i != browsers_to_close.end(); ++i) { 229 i != browsers_to_close.end(); ++i) {
399 (*i)->window()->Close(); 230 (*i)->window()->Close();
400 } 231 }
401 } 232 }
402 233
403 // static 234 // static
404 void BrowserList::AttemptUserExit() {
405 #if defined(OS_CHROMEOS)
406 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker("LogoutStarted", false);
407 // Write /tmp/uptime-logout-started as well.
408 const char kLogoutStarted[] = "logout-started";
409 chromeos::BootTimesLoader::Get()->RecordCurrentStats(kLogoutStarted);
410
411 // Login screen should show up in owner's locale.
412 PrefService* state = g_browser_process->local_state();
413 if (state) {
414 std::string owner_locale = state->GetString(prefs::kOwnerLocale);
415 if (!owner_locale.empty() &&
416 state->GetString(prefs::kApplicationLocale) != owner_locale &&
417 !state->IsManagedPreference(prefs::kApplicationLocale)) {
418 state->SetString(prefs::kApplicationLocale, owner_locale);
419 state->CommitPendingWrite();
420 }
421 }
422 g_session_manager_requested_shutdown = false;
423 // On ChromeOS, always terminate the browser, regardless of the result of
424 // AreAllBrowsersCloseable(). See crbug.com/123107.
425 BrowserList::NotifyAndTerminate(true);
426 #else
427 // Reset the restart bit that might have been set in cancelled restart
428 // request.
429 PrefService* pref_service = g_browser_process->local_state();
430 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, false);
431 AttemptExitInternal();
432 #endif
433 }
434
435 // static
436 void BrowserList::AttemptRestart() {
437 if (!CommandLine::ForCurrentProcess()->HasSwitch(
438 switches::kDisableRestoreSessionState)) {
439 BrowserVector::const_iterator it;
440 for (it = begin(); it != end(); ++it)
441 content::BrowserContext::SaveSessionState((*it)->profile());
442 }
443
444 PrefService* pref_service = g_browser_process->local_state();
445 pref_service->SetBoolean(prefs::kWasRestarted, true);
446
447 #if defined(OS_CHROMEOS)
448 // For CrOS instead of browser restart (which is not supported) perform a full
449 // sign out. Session will be only restored if user has that setting set.
450 // Same session restore behavior happens in case of full restart after update.
451 AttemptUserExit();
452 #else
453 // Set the flag to restore state after the restart.
454 pref_service->SetBoolean(prefs::kRestartLastSessionOnShutdown, true);
455 AttemptExit();
456 #endif
457 }
458
459 // static
460 void BrowserList::AttemptExit() {
461 // If we know that all browsers can be closed without blocking,
462 // don't notify users of crashes beyond this point.
463 // Note that MarkAsCleanShutdown does not set UMA's exit cleanly bit
464 // so crashes during shutdown are still reported in UMA.
465 if (AreAllBrowsersCloseable())
466 MarkAsCleanShutdown();
467 AttemptExitInternal();
468 }
469
470 #if defined(OS_CHROMEOS)
471 // A function called when SIGTERM is received.
472 // static
473 void BrowserList::ExitCleanly() {
474 // We always mark exit cleanly because SessionManager may kill
475 // chrome in 3 seconds after SIGTERM.
476 g_browser_process->EndSession();
477
478 // Don't block when SIGTERM is received. AreaAllBrowsersCloseable()
479 // can be false in following cases. a) power-off b) signout from
480 // screen locker.
481 if (!AreAllBrowsersCloseable())
482 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
483 AttemptExitInternal();
484 }
485 #endif
486
487 // static
488 void BrowserList::SessionEnding() {
489 // This is a time-limited shutdown where we need to write as much to
490 // disk as we can as soon as we can, and where we must kill the
491 // process within a hang timeout to avoid user prompts.
492
493 // Start watching for hang during shutdown, and crash it if takes too long.
494 // We disarm when |shutdown_watcher| object is destroyed, which is when we
495 // exit this function.
496 ShutdownWatcherHelper shutdown_watcher;
497 shutdown_watcher.Arm(base::TimeDelta::FromSeconds(90));
498
499 // EndSession is invoked once per frame. Only do something the first time.
500 static bool already_ended = false;
501 // We may get called in the middle of shutdown, e.g. http://crbug.com/70852
502 // In this case, do nothing.
503 if (already_ended || !content::NotificationService::current())
504 return;
505 already_ended = true;
506
507 browser_shutdown::OnShutdownStarting(browser_shutdown::END_SESSION);
508
509 content::NotificationService::current()->Notify(
510 content::NOTIFICATION_APP_EXITING,
511 content::NotificationService::AllSources(),
512 content::NotificationService::NoDetails());
513
514 // Write important data first.
515 g_browser_process->EndSession();
516
517 BrowserList::CloseAllBrowsers();
518
519 // Send out notification. This is used during testing so that the test harness
520 // can properly shutdown before we exit.
521 content::NotificationService::current()->Notify(
522 chrome::NOTIFICATION_SESSION_END,
523 content::NotificationService::AllSources(),
524 content::NotificationService::NoDetails());
525
526 // This will end by terminating the process.
527 content::ImmediateShutdownAndExitProcess();
528 }
529
530 // static
531 int BrowserList::keep_alive_count_ = 0;
532
533 // static
534 void BrowserList::StartKeepAlive() {
535 // Increment the browser process refcount as long as we're keeping the
536 // application alive.
537 if (!WillKeepAlive())
538 g_browser_process->AddRefModule();
539 keep_alive_count_++;
540 }
541
542 // static
543 void BrowserList::EndKeepAlive() {
544 DCHECK_GT(keep_alive_count_, 0);
545 keep_alive_count_--;
546
547 DCHECK(g_browser_process);
548 // Although we should have a browser process, if there is none,
549 // there is nothing to do.
550 if (!g_browser_process) return;
551
552 // Allow the app to shutdown again.
553 if (!WillKeepAlive()) {
554 g_browser_process->ReleaseModule();
555 // If there are no browsers open and we aren't already shutting down,
556 // initiate a shutdown. Also skips shutdown if this is a unit test
557 // (MessageLoop::current() == null).
558 if (browsers().empty() && !browser_shutdown::IsTryingToQuit() &&
559 MessageLoop::current())
560 CloseAllBrowsers();
561 }
562 }
563
564 // static
565 bool BrowserList::WillKeepAlive() {
566 return keep_alive_count_ > 0;
567 }
568
569 // static
570 BrowserList::const_iterator BrowserList::begin() { 235 BrowserList::const_iterator BrowserList::begin() {
571 return browsers().begin(); 236 return browsers().begin();
572 } 237 }
573 238
574 // static 239 // static
575 BrowserList::const_iterator BrowserList::end() { 240 BrowserList::const_iterator BrowserList::end() {
576 return browsers().end(); 241 return browsers().end();
577 } 242 }
578 243
579 // static 244 // static
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 // If no more WebContents from Browsers, check the BackgroundPrintingManager. 352 // If no more WebContents from Browsers, check the BackgroundPrintingManager.
688 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { 353 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) {
689 cur_ = *bg_printing_iterator_; 354 cur_ = *bg_printing_iterator_;
690 CHECK(cur_); 355 CHECK(cur_);
691 ++bg_printing_iterator_; 356 ++bg_printing_iterator_;
692 return; 357 return;
693 } 358 }
694 // Reached the end - no more WebContents. 359 // Reached the end - no more WebContents.
695 cur_ = NULL; 360 cur_ = NULL;
696 } 361 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/browser_list.h ('k') | chrome/browser/ui/browser_list_aura.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698