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