OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/logging.h" | 7 #include "base/logging.h" |
8 #include "base/message_loop.h" | 8 #include "base/message_loop.h" |
9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
110 BrowserActivityObserver* activity_observer = NULL; | 110 BrowserActivityObserver* activity_observer = NULL; |
111 | 111 |
112 // Type used to indicate to match anything. | 112 // Type used to indicate to match anything. |
113 const int kMatchAny = 0; | 113 const int kMatchAny = 0; |
114 | 114 |
115 // See BrowserMatches for details. | 115 // See BrowserMatches for details. |
116 const int kMatchOriginalProfile = 1 << 0; | 116 const int kMatchOriginalProfile = 1 << 0; |
117 const int kMatchCanSupportWindowFeature = 1 << 1; | 117 const int kMatchCanSupportWindowFeature = 1 << 1; |
118 const int kMatchTabbed = 1 << 2; | 118 const int kMatchTabbed = 1 << 2; |
119 | 119 |
120 static BrowserList::BrowserVector& browsers() { | |
121 CR_DEFINE_STATIC_LOCAL(BrowserList::BrowserVector, browser_vector, ()); | |
122 return browser_vector; | |
123 } | |
124 | |
125 static BrowserList::BrowserVector& last_active_browsers() { | |
126 CR_DEFINE_STATIC_LOCAL(BrowserList::BrowserVector, last_active_vector, ()); | |
127 return last_active_vector; | |
128 } | |
129 | |
130 static ObserverList<BrowserList::Observer>& observers() { | |
joth
2011/11/18 01:18:14
again non-const refs
| |
131 CR_DEFINE_STATIC_LOCAL( | |
132 ObserverList<BrowserList::Observer>, observer_vector, ()); | |
133 return observer_vector; | |
134 } | |
135 | |
120 // Returns true if the specified |browser| matches the specified arguments. | 136 // Returns true if the specified |browser| matches the specified arguments. |
121 // |match_types| is a bitmask dictating what parameters to match: | 137 // |match_types| is a bitmask dictating what parameters to match: |
122 // . If it contains kMatchOriginalProfile then the original profile of the | 138 // . If it contains kMatchOriginalProfile then the original profile of the |
123 // browser must match |profile->GetOriginalProfile()|. This is used to match | 139 // browser must match |profile->GetOriginalProfile()|. This is used to match |
124 // incognito windows. | 140 // incognito windows. |
125 // . If it contains kMatchCanSupportWindowFeature | 141 // . If it contains kMatchCanSupportWindowFeature |
126 // |CanSupportWindowFeature(window_feature)| must return true. | 142 // |CanSupportWindowFeature(window_feature)| must return true. |
127 // . If it contains kMatchTabbed, the browser must be a tabbed browser. | 143 // . If it contains kMatchTabbed, the browser must be a tabbed browser. |
128 bool BrowserMatches(Browser* browser, | 144 bool BrowserMatches(Browser* browser, |
129 Profile* profile, | 145 Profile* profile, |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
244 chromeos::WmIpc::instance()->NotifyAboutSignout(); | 260 chromeos::WmIpc::instance()->NotifyAboutSignout(); |
245 notified = true; | 261 notified = true; |
246 } | 262 } |
247 #endif | 263 #endif |
248 } | 264 } |
249 | 265 |
250 #endif | 266 #endif |
251 | 267 |
252 } // namespace | 268 } // namespace |
253 | 269 |
254 BrowserList::BrowserVector BrowserList::browsers_; | |
255 ObserverList<BrowserList::Observer> BrowserList::observers_; | |
256 | |
257 // static | 270 // static |
258 void BrowserList::AddBrowser(Browser* browser) { | 271 void BrowserList::AddBrowser(Browser* browser) { |
259 DCHECK(browser); | 272 DCHECK(browser); |
260 browsers_.push_back(browser); | 273 browsers().push_back(browser); |
261 | 274 |
262 g_browser_process->AddRefModule(); | 275 g_browser_process->AddRefModule(); |
263 | 276 |
264 if (!activity_observer) | 277 if (!activity_observer) |
265 activity_observer = new BrowserActivityObserver; | 278 activity_observer = new BrowserActivityObserver; |
266 | 279 |
267 content::NotificationService::current()->Notify( | 280 content::NotificationService::current()->Notify( |
268 chrome::NOTIFICATION_BROWSER_OPENED, | 281 chrome::NOTIFICATION_BROWSER_OPENED, |
269 content::Source<Browser>(browser), | 282 content::Source<Browser>(browser), |
270 content::NotificationService::NoDetails()); | 283 content::NotificationService::NoDetails()); |
271 | 284 |
272 // Send out notifications after add has occurred. Do some basic checking to | 285 // Send out notifications after add has occurred. Do some basic checking to |
273 // try to catch evil observers that change the list from under us. | 286 // try to catch evil observers that change the list from under us. |
274 size_t original_count = observers_.size(); | 287 size_t original_count = observers().size(); |
275 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserAdded(browser)); | 288 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserAdded(browser)); |
276 DCHECK_EQ(original_count, observers_.size()) | 289 DCHECK_EQ(original_count, observers().size()) |
277 << "observer list modified during notification"; | 290 << "observer list modified during notification"; |
278 } | 291 } |
279 | 292 |
280 // static | 293 // static |
281 void BrowserList::MarkAsCleanShutdown() { | 294 void BrowserList::MarkAsCleanShutdown() { |
282 for (const_iterator i = begin(); i != end(); ++i) { | 295 for (const_iterator i = begin(); i != end(); ++i) { |
283 (*i)->profile()->MarkAsCleanShutdown(); | 296 (*i)->profile()->MarkAsCleanShutdown(); |
284 } | 297 } |
285 } | 298 } |
286 | 299 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
330 } | 343 } |
331 return; | 344 return; |
332 } | 345 } |
333 // If running the Chrome OS build, but we're not on the device, fall through | 346 // If running the Chrome OS build, but we're not on the device, fall through |
334 #endif | 347 #endif |
335 AllBrowsersClosedAndAppExiting(); | 348 AllBrowsersClosedAndAppExiting(); |
336 } | 349 } |
337 | 350 |
338 // static | 351 // static |
339 void BrowserList::RemoveBrowser(Browser* browser) { | 352 void BrowserList::RemoveBrowser(Browser* browser) { |
340 RemoveBrowserFrom(browser, &last_active_browsers_); | 353 RemoveBrowserFrom(browser, &last_active_browsers()); |
341 | 354 |
342 // Closing all windows does not indicate quitting the application on the Mac, | 355 // Closing all windows does not indicate quitting the application on the Mac, |
343 // however, many UI tests rely on this behavior so leave it be for now and | 356 // however, many UI tests rely on this behavior so leave it be for now and |
344 // simply ignore the behavior on the Mac outside of unit tests. | 357 // simply ignore the behavior on the Mac outside of unit tests. |
345 // TODO(andybons): Fix the UI tests to Do The Right Thing. | 358 // TODO(andybons): Fix the UI tests to Do The Right Thing. |
346 bool closing_last_browser = (browsers_.size() == 1); | 359 bool closing_last_browser = (browsers().size() == 1); |
347 content::NotificationService::current()->Notify( | 360 content::NotificationService::current()->Notify( |
348 chrome::NOTIFICATION_BROWSER_CLOSED, | 361 chrome::NOTIFICATION_BROWSER_CLOSED, |
349 content::Source<Browser>(browser), | 362 content::Source<Browser>(browser), |
350 content::Details<bool>(&closing_last_browser)); | 363 content::Details<bool>(&closing_last_browser)); |
351 | 364 |
352 RemoveBrowserFrom(browser, &browsers_); | 365 RemoveBrowserFrom(browser, &browsers()); |
353 | 366 |
354 // Do some basic checking to try to catch evil observers | 367 // Do some basic checking to try to catch evil observers |
355 // that change the list from under us. | 368 // that change the list from under us. |
356 size_t original_count = observers_.size(); | 369 size_t original_count = observers().size(); |
357 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserRemoved(browser)); | 370 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserRemoved(browser)); |
358 DCHECK_EQ(original_count, observers_.size()) | 371 DCHECK_EQ(original_count, observers().size()) |
359 << "observer list modified during notification"; | 372 << "observer list modified during notification"; |
360 | 373 |
361 // If the last Browser object was destroyed, make sure we try to close any | 374 // If the last Browser object was destroyed, make sure we try to close any |
362 // remaining dependent windows too. | 375 // remaining dependent windows too. |
363 if (browsers_.empty()) { | 376 if (browsers().empty()) { |
364 delete activity_observer; | 377 delete activity_observer; |
365 activity_observer = NULL; | 378 activity_observer = NULL; |
366 } | 379 } |
367 | 380 |
368 g_browser_process->ReleaseModule(); | 381 g_browser_process->ReleaseModule(); |
369 | 382 |
370 // If we're exiting, send out the APP_TERMINATING notification to allow other | 383 // If we're exiting, send out the APP_TERMINATING notification to allow other |
371 // modules to shut themselves down. | 384 // modules to shut themselves down. |
372 if (browsers_.empty() && | 385 if (browsers().empty() && |
373 (browser_shutdown::IsTryingToQuit() || | 386 (browser_shutdown::IsTryingToQuit() || |
374 g_browser_process->IsShuttingDown())) { | 387 g_browser_process->IsShuttingDown())) { |
375 // Last browser has just closed, and this is a user-initiated quit or there | 388 // Last browser has just closed, and this is a user-initiated quit or there |
376 // is no module keeping the app alive, so send out our notification. No need | 389 // is no module keeping the app alive, so send out our notification. No need |
377 // to call ProfileManager::ShutdownSessionServices() as part of the | 390 // to call ProfileManager::ShutdownSessionServices() as part of the |
378 // shutdown, because Browser::WindowClosing() already makes sure that the | 391 // shutdown, because Browser::WindowClosing() already makes sure that the |
379 // SessionService is created and notified. | 392 // SessionService is created and notified. |
380 NotifyAppTerminating(); | 393 NotifyAppTerminating(); |
381 AllBrowsersClosedAndAppExiting(); | 394 AllBrowsersClosedAndAppExiting(); |
382 } | 395 } |
383 } | 396 } |
384 | 397 |
385 // static | 398 // static |
386 void BrowserList::AddObserver(BrowserList::Observer* observer) { | 399 void BrowserList::AddObserver(BrowserList::Observer* observer) { |
387 observers_.AddObserver(observer); | 400 observers().AddObserver(observer); |
388 } | 401 } |
389 | 402 |
390 // static | 403 // static |
391 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { | 404 void BrowserList::RemoveObserver(BrowserList::Observer* observer) { |
392 observers_.RemoveObserver(observer); | 405 observers().RemoveObserver(observer); |
393 } | 406 } |
394 | 407 |
395 // static | 408 // static |
396 void BrowserList::CloseAllBrowsers() { | 409 void BrowserList::CloseAllBrowsers() { |
397 bool session_ending = | 410 bool session_ending = |
398 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; | 411 browser_shutdown::GetShutdownType() == browser_shutdown::END_SESSION; |
399 // Tell everyone that we are shutting down. | 412 // Tell everyone that we are shutting down. |
400 browser_shutdown::SetTryingToQuit(true); | 413 browser_shutdown::SetTryingToQuit(true); |
401 | 414 |
402 // Before we close the browsers shutdown all session services. That way an | 415 // Before we close the browsers shutdown all session services. That way an |
403 // exit can restore all browsers open before exiting. | 416 // exit can restore all browsers open before exiting. |
404 ProfileManager::ShutdownSessionServices(); | 417 ProfileManager::ShutdownSessionServices(); |
405 | 418 |
406 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, | 419 // If there are no browsers, send the APP_TERMINATING action here. Otherwise, |
407 // it will be sent by RemoveBrowser() when the last browser has closed. | 420 // it will be sent by RemoveBrowser() when the last browser has closed. |
408 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || | 421 if (browser_shutdown::ShuttingDownWithoutClosingBrowsers() || |
409 browsers_.empty()) { | 422 browsers().empty()) { |
410 NotifyAndTerminate(true); | 423 NotifyAndTerminate(true); |
411 return; | 424 return; |
412 } | 425 } |
413 | 426 |
414 #if defined(OS_CHROMEOS) | 427 #if defined(OS_CHROMEOS) |
415 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( | 428 chromeos::BootTimesLoader::Get()->AddLogoutTimeMarker( |
416 "StartedClosingWindows", false); | 429 "StartedClosingWindows", false); |
417 #endif | 430 #endif |
418 for (BrowserList::const_iterator i = BrowserList::begin(); | 431 for (BrowserList::const_iterator i = BrowserList::begin(); |
419 i != BrowserList::end();) { | 432 i != BrowserList::end();) { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
616 // Although we should have a browser process, if there is none, | 629 // Although we should have a browser process, if there is none, |
617 // there is nothing to do. | 630 // there is nothing to do. |
618 if (!g_browser_process) return; | 631 if (!g_browser_process) return; |
619 | 632 |
620 // Allow the app to shutdown again. | 633 // Allow the app to shutdown again. |
621 if (!WillKeepAlive()) { | 634 if (!WillKeepAlive()) { |
622 g_browser_process->ReleaseModule(); | 635 g_browser_process->ReleaseModule(); |
623 // If there are no browsers open and we aren't already shutting down, | 636 // If there are no browsers open and we aren't already shutting down, |
624 // initiate a shutdown. Also skips shutdown if this is a unit test | 637 // initiate a shutdown. Also skips shutdown if this is a unit test |
625 // (MessageLoop::current() == null). | 638 // (MessageLoop::current() == null). |
626 if (browsers_.empty() && !browser_shutdown::IsTryingToQuit() && | 639 if (browsers().empty() && !browser_shutdown::IsTryingToQuit() && |
627 MessageLoop::current()) | 640 MessageLoop::current()) |
628 CloseAllBrowsers(); | 641 CloseAllBrowsers(); |
629 } | 642 } |
630 } | 643 } |
631 | 644 |
632 // static | 645 // static |
633 bool BrowserList::WillKeepAlive() { | 646 bool BrowserList::WillKeepAlive() { |
634 return keep_alive_count_ > 0; | 647 return keep_alive_count_ > 0; |
635 } | 648 } |
636 | 649 |
637 // static | 650 // static |
638 BrowserList::BrowserVector BrowserList::last_active_browsers_; | 651 BrowserList::const_iterator BrowserList::begin() { |
652 return browsers().begin(); | |
653 } | |
654 | |
655 // static | |
656 BrowserList::const_iterator BrowserList::end() { | |
657 return browsers().end(); | |
658 } | |
659 | |
660 // static | |
661 bool BrowserList::empty() { | |
662 return browsers().empty(); | |
663 } | |
664 | |
665 // static | |
666 size_t BrowserList::size() { | |
667 return browsers().size(); | |
668 } | |
639 | 669 |
640 // static | 670 // static |
641 void BrowserList::SetLastActive(Browser* browser) { | 671 void BrowserList::SetLastActive(Browser* browser) { |
642 // If the browser is currently trying to quit, we don't want to set the last | 672 // If the browser is currently trying to quit, we don't want to set the last |
643 // active browser because that can alter the last active browser that the user | 673 // active browser because that can alter the last active browser that the user |
644 // intended depending on the order in which the windows close. | 674 // intended depending on the order in which the windows close. |
645 if (browser_shutdown::IsTryingToQuit()) | 675 if (browser_shutdown::IsTryingToQuit()) |
646 return; | 676 return; |
647 RemoveBrowserFrom(browser, &last_active_browsers_); | 677 RemoveBrowserFrom(browser, &last_active_browsers()); |
648 last_active_browsers_.push_back(browser); | 678 last_active_browsers().push_back(browser); |
649 | 679 |
650 FOR_EACH_OBSERVER(Observer, observers_, OnBrowserSetLastActive(browser)); | 680 FOR_EACH_OBSERVER(Observer, observers(), OnBrowserSetLastActive(browser)); |
651 } | 681 } |
652 | 682 |
653 // static | 683 // static |
654 Browser* BrowserList::GetLastActive() { | 684 Browser* BrowserList::GetLastActive() { |
655 if (!last_active_browsers_.empty()) | 685 if (!last_active_browsers().empty()) |
656 return *(last_active_browsers_.rbegin()); | 686 return *(last_active_browsers().rbegin()); |
657 | 687 |
658 return NULL; | 688 return NULL; |
659 } | 689 } |
660 | 690 |
661 // static | 691 // static |
662 Browser* BrowserList::GetLastActiveWithProfile(Profile* profile) { | 692 Browser* BrowserList::GetLastActiveWithProfile(Profile* profile) { |
663 // We are only interested in last active browsers, so we don't fall back to | 693 // We are only interested in last active browsers, so we don't fall back to |
664 // all browsers like FindBrowserWith* do. | 694 // all browsers like FindBrowserWith* do. |
665 return FindBrowserMatching( | 695 return FindBrowserMatching( |
666 BrowserList::begin_last_active(), BrowserList::end_last_active(), profile, | 696 BrowserList::begin_last_active(), BrowserList::end_last_active(), profile, |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
721 Browser* BrowserList::FindBrowserWithTabContents(TabContents* tab_contents) { | 751 Browser* BrowserList::FindBrowserWithTabContents(TabContents* tab_contents) { |
722 DCHECK(tab_contents); | 752 DCHECK(tab_contents); |
723 for (TabContentsIterator it; !it.done(); ++it) { | 753 for (TabContentsIterator it; !it.done(); ++it) { |
724 if (it->tab_contents() == tab_contents) | 754 if (it->tab_contents() == tab_contents) |
725 return it.browser(); | 755 return it.browser(); |
726 } | 756 } |
727 return NULL; | 757 return NULL; |
728 } | 758 } |
729 | 759 |
730 // static | 760 // static |
761 BrowserList::const_reverse_iterator BrowserList::begin_last_active() { | |
762 return last_active_browsers().rbegin(); | |
763 } | |
764 | |
765 // static | |
766 BrowserList::const_reverse_iterator BrowserList::end_last_active() { | |
767 return last_active_browsers().rend(); | |
768 } | |
769 | |
770 // static | |
771 size_t BrowserList::GetBrowserCount(Profile* profile) { | |
772 size_t result = 0; | |
773 for (BrowserList::const_iterator i = BrowserList::begin(); | |
774 i != BrowserList::end(); ++i) { | |
775 if (BrowserMatches(*i, profile, Browser::FEATURE_NONE, kMatchAny)) { | |
776 ++result; | |
777 } | |
778 } | |
779 return result; | |
780 } | |
781 | |
782 // static | |
731 size_t BrowserList::GetBrowserCountForType(Profile* profile, | 783 size_t BrowserList::GetBrowserCountForType(Profile* profile, |
732 bool match_tabbed) { | 784 bool match_tabbed) { |
733 size_t result = 0; | 785 size_t result = 0; |
734 for (BrowserList::const_iterator i = BrowserList::begin(); | 786 for (BrowserList::const_iterator i = BrowserList::begin(); |
735 i != BrowserList::end(); ++i) { | 787 i != BrowserList::end(); ++i) { |
736 if (BrowserMatches(*i, profile, Browser::FEATURE_NONE, | 788 if (BrowserMatches(*i, profile, Browser::FEATURE_NONE, |
737 match_tabbed ? kMatchTabbed : kMatchAny)) | 789 match_tabbed ? kMatchTabbed : kMatchAny)) |
738 ++result; | 790 ++result; |
739 } | 791 } |
740 return result; | 792 return result; |
741 } | 793 } |
742 | |
743 // static | |
744 size_t BrowserList::GetBrowserCount(Profile* profile) { | |
745 size_t result = 0; | |
746 for (BrowserList::const_iterator i = BrowserList::begin(); | |
747 i != BrowserList::end(); ++i) { | |
748 if (BrowserMatches(*i, profile, Browser::FEATURE_NONE, kMatchAny)) { | |
749 result++; | |
750 } | |
751 } | |
752 return result; | |
753 } | |
754 | 794 |
755 // static | 795 // static |
756 bool BrowserList::IsOffTheRecordSessionActive() { | 796 bool BrowserList::IsOffTheRecordSessionActive() { |
757 for (BrowserList::const_iterator i = BrowserList::begin(); | 797 for (BrowserList::const_iterator i = BrowserList::begin(); |
758 i != BrowserList::end(); ++i) { | 798 i != BrowserList::end(); ++i) { |
759 if ((*i)->profile()->IsOffTheRecord()) | 799 if ((*i)->profile()->IsOffTheRecord()) |
760 return true; | 800 return true; |
761 } | 801 } |
762 return false; | 802 return false; |
763 } | 803 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
815 // If no more TabContents from Browsers, check the BackgroundPrintingManager. | 855 // If no more TabContents from Browsers, check the BackgroundPrintingManager. |
816 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { | 856 while (bg_printing_iterator_ != GetBackgroundPrintingManager()->end()) { |
817 cur_ = *bg_printing_iterator_; | 857 cur_ = *bg_printing_iterator_; |
818 CHECK(cur_); | 858 CHECK(cur_); |
819 ++bg_printing_iterator_; | 859 ++bg_printing_iterator_; |
820 return; | 860 return; |
821 } | 861 } |
822 // Reached the end - no more TabContents. | 862 // Reached the end - no more TabContents. |
823 cur_ = NULL; | 863 cur_ = NULL; |
824 } | 864 } |
OLD | NEW |