| OLD | NEW |
| 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/memory/tab_manager.h" | 5 #include "chrome/browser/memory/tab_manager.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/macros.h" | 12 #include "base/macros.h" |
| 13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
| 14 #include "base/metrics/field_trial.h" | 14 #include "base/metrics/field_trial.h" |
| 15 #include "base/strings/string16.h" | 15 #include "base/strings/string16.h" |
| 16 #include "base/test/mock_entropy_provider.h" | 16 #include "base/test/mock_entropy_provider.h" |
| 17 #include "base/test/simple_test_tick_clock.h" | 17 #include "base/test/simple_test_tick_clock.h" |
| 18 #include "base/time/time.h" | 18 #include "base/time/time.h" |
| 19 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 20 #include "chrome/browser/memory/tab_manager_web_contents_data.h" | 20 #include "chrome/browser/memory/tab_manager_web_contents_data.h" |
| 21 #include "chrome/browser/memory/tab_stats.h" | 21 #include "chrome/browser/memory/tab_stats.h" |
| 22 #include "chrome/browser/profiles/profile.h" | 22 #include "chrome/browser/profiles/profile.h" |
| 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 23 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 24 #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h" | 24 #include "chrome/browser/ui/tabs/test_tab_strip_model_delegate.h" |
| 25 #include "chrome/common/chrome_features.h" | 25 #include "chrome/common/chrome_features.h" |
| 26 #include "chrome/common/url_constants.h" | 26 #include "chrome/common/url_constants.h" |
| 27 #include "chrome/test/base/chrome_render_view_host_test_harness.h" | 27 #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| 28 #include "chrome/test/base/testing_profile.h" | 28 #include "chrome/test/base/testing_profile.h" |
| 29 #include "components/variations/variations_associated_data.h" | 29 #include "components/variations/variations_associated_data.h" |
| 30 #include "content/public/browser/render_process_host.h" |
| 30 #include "content/public/browser/web_contents.h" | 31 #include "content/public/browser/web_contents.h" |
| 32 #include "content/public/test/mock_render_process_host.h" |
| 31 #include "content/public/test/web_contents_tester.h" | 33 #include "content/public/test/web_contents_tester.h" |
| 32 #include "testing/gmock/include/gmock/gmock.h" | 34 #include "testing/gmock/include/gmock/gmock.h" |
| 33 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
| 34 #include "url/gurl.h" | 36 #include "url/gurl.h" |
| 35 | 37 |
| 36 using content::WebContents; | 38 using content::WebContents; |
| 37 using content::WebContentsTester; | 39 using content::WebContentsTester; |
| 38 | 40 |
| 39 namespace memory { | 41 namespace memory { |
| 40 namespace { | 42 namespace { |
| (...skipping 624 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 EXPECT_FALSE(tm.under_memory_pressure_); | 667 EXPECT_FALSE(tm.under_memory_pressure_); |
| 666 EXPECT_EQ(0u, task_runner->size()); | 668 EXPECT_EQ(0u, task_runner->size()); |
| 667 EXPECT_EQ(0u, tm.notified_renderers_.size()); | 669 EXPECT_EQ(0u, tm.notified_renderers_.size()); |
| 668 | 670 |
| 669 | 671 |
| 670 // Clean up the tabstrip. | 672 // Clean up the tabstrip. |
| 671 tabstrip.CloseAllTabs(); | 673 tabstrip.CloseAllTabs(); |
| 672 ASSERT_TRUE(tabstrip.empty()); | 674 ASSERT_TRUE(tabstrip.empty()); |
| 673 } | 675 } |
| 674 | 676 |
| 675 TEST_F(TabManagerTest, NextPurgeAndSuspendState) { | 677 TEST_F(TabManagerTest, DefaultTimeToPurgeInCorrectRange) { |
| 678 TabManager tab_manager; |
| 679 base::TimeDelta time_to_purge = |
| 680 tab_manager.GetTimeToPurge(TabManager::kDefaultMinTimeToPurge); |
| 681 EXPECT_GE(time_to_purge, base::TimeDelta::FromMinutes(30)); |
| 682 EXPECT_LT(time_to_purge, base::TimeDelta::FromMinutes(60)); |
| 683 } |
| 684 |
| 685 TEST_F(TabManagerTest, ShouldPurgeAtDefaultTime) { |
| 676 TabManager tab_manager; | 686 TabManager tab_manager; |
| 677 TabStripDummyDelegate delegate; | 687 TabStripDummyDelegate delegate; |
| 678 TabStripModel tabstrip(&delegate, profile()); | 688 TabStripModel tabstrip(&delegate, profile()); |
| 679 tabstrip.AddObserver(&tab_manager); | 689 tabstrip.AddObserver(&tab_manager); |
| 680 | 690 |
| 681 WebContents* test_contents = CreateWebContents(); | 691 WebContents* test_contents = CreateWebContents(); |
| 682 tabstrip.AppendWebContents(test_contents, false); | 692 tabstrip.AppendWebContents(test_contents, false); |
| 683 | 693 |
| 684 // Use default time-to-first-purge defined in TabManager. | |
| 685 base::TimeDelta threshold = TabManager::kDefaultTimeToFirstPurge; | |
| 686 base::SimpleTestTickClock test_clock; | 694 base::SimpleTestTickClock test_clock; |
| 695 tab_manager.set_test_tick_clock(&test_clock); |
| 687 | 696 |
| 697 tab_manager.GetWebContentsData(test_contents)->set_is_purged(false); |
| 688 tab_manager.GetWebContentsData(test_contents) | 698 tab_manager.GetWebContentsData(test_contents) |
| 689 ->SetPurgeAndSuspendState(TabManager::RUNNING); | 699 ->SetLastInactiveTime(test_clock.NowTicks()); |
| 690 tab_manager.GetWebContentsData(test_contents) | 700 tab_manager.GetWebContentsData(test_contents) |
| 691 ->SetLastPurgeAndSuspendModifiedTimeForTesting(test_clock.NowTicks()); | 701 ->set_time_to_purge(base::TimeDelta::FromMinutes(1)); |
| 692 | 702 |
| 693 // Wait 30 minutes and verify that the tab is still RUNNING. | 703 // Wait 1 minute and verify that the tab is still not to be purged. |
| 694 test_clock.Advance(base::TimeDelta::FromMinutes(30)); | 704 test_clock.Advance(base::TimeDelta::FromMinutes(1)); |
| 695 EXPECT_EQ(TabManager::RUNNING, | 705 EXPECT_FALSE(tab_manager.ShouldPurgeNow(test_contents)); |
| 696 tab_manager.GetNextPurgeAndSuspendState( | |
| 697 test_contents, test_clock.NowTicks(), threshold)); | |
| 698 | 706 |
| 699 // Wait another second and verify that it is now SUSPENDED. | 707 // Wait another 1 second and verify that it should be purged now . |
| 700 test_clock.Advance(base::TimeDelta::FromSeconds(1)); | 708 test_clock.Advance(base::TimeDelta::FromSeconds(1)); |
| 701 EXPECT_EQ(TabManager::SUSPENDED, | 709 EXPECT_TRUE(tab_manager.ShouldPurgeNow(test_contents)); |
| 702 tab_manager.GetNextPurgeAndSuspendState( | |
| 703 test_contents, test_clock.NowTicks(), threshold)); | |
| 704 | 710 |
| 711 tab_manager.GetWebContentsData(test_contents)->set_is_purged(true); |
| 705 tab_manager.GetWebContentsData(test_contents) | 712 tab_manager.GetWebContentsData(test_contents) |
| 706 ->SetPurgeAndSuspendState(TabManager::SUSPENDED); | 713 ->SetLastInactiveTime(test_clock.NowTicks()); |
| 707 tab_manager.GetWebContentsData(test_contents) | |
| 708 ->SetLastPurgeAndSuspendModifiedTimeForTesting(test_clock.NowTicks()); | |
| 709 | 714 |
| 710 test_clock.Advance(base::TimeDelta::FromSeconds(1200)); | 715 // Wait 1 day and verify that the tab is still be purged. |
| 711 EXPECT_EQ(TabManager::SUSPENDED, | 716 test_clock.Advance(base::TimeDelta::FromHours(24)); |
| 712 tab_manager.GetNextPurgeAndSuspendState( | 717 EXPECT_FALSE(tab_manager.ShouldPurgeNow(test_contents)); |
| 713 test_contents, test_clock.NowTicks(), threshold)); | |
| 714 | |
| 715 test_clock.Advance(base::TimeDelta::FromSeconds(1)); | |
| 716 EXPECT_EQ(TabManager::RESUMED, | |
| 717 tab_manager.GetNextPurgeAndSuspendState( | |
| 718 test_contents, test_clock.NowTicks(), threshold)); | |
| 719 | |
| 720 tab_manager.GetWebContentsData(test_contents) | |
| 721 ->SetPurgeAndSuspendState(TabManager::RESUMED); | |
| 722 tab_manager.GetWebContentsData(test_contents) | |
| 723 ->SetLastPurgeAndSuspendModifiedTimeForTesting(test_clock.NowTicks()); | |
| 724 | |
| 725 test_clock.Advance(base::TimeDelta::FromSeconds(10)); | |
| 726 EXPECT_EQ(TabManager::RESUMED, | |
| 727 tab_manager.GetNextPurgeAndSuspendState( | |
| 728 test_contents, test_clock.NowTicks(), threshold)); | |
| 729 | |
| 730 test_clock.Advance(base::TimeDelta::FromSeconds(1)); | |
| 731 EXPECT_EQ(TabManager::SUSPENDED, | |
| 732 tab_manager.GetNextPurgeAndSuspendState( | |
| 733 test_contents, test_clock.NowTicks(), threshold)); | |
| 734 | |
| 735 // Clean up the tabstrip. | |
| 736 tabstrip.CloseAllTabs(); | |
| 737 EXPECT_TRUE(tabstrip.empty()); | |
| 738 } | 718 } |
| 739 | 719 |
| 740 TEST_F(TabManagerTest, ActivateTabResetPurgeAndSuspendState) { | 720 TEST_F(TabManagerTest, ActivateTabResetPurgeState) { |
| 741 TabManager tab_manager; | 721 TabManager tab_manager; |
| 742 TabStripDummyDelegate delegate; | 722 TabStripDummyDelegate delegate; |
| 743 TabStripModel tabstrip(&delegate, profile()); | 723 TabStripModel tabstrip(&delegate, profile()); |
| 744 tabstrip.AddObserver(&tab_manager); | 724 tabstrip.AddObserver(&tab_manager); |
| 725 tab_manager.test_tab_strip_models_.push_back( |
| 726 TabManager::TestTabStripModel(&tabstrip, false /* !is_app */)); |
| 727 |
| 728 base::SimpleTestTickClock test_clock; |
| 729 tab_manager.set_test_tick_clock(&test_clock); |
| 745 | 730 |
| 746 WebContents* tab1 = CreateWebContents(); | 731 WebContents* tab1 = CreateWebContents(); |
| 747 WebContents* tab2 = CreateWebContents(); | 732 WebContents* tab2 = CreateWebContents(); |
| 748 tabstrip.AppendWebContents(tab1, true); | 733 tabstrip.AppendWebContents(tab1, true); |
| 749 tabstrip.AppendWebContents(tab2, false); | 734 tabstrip.AppendWebContents(tab2, false); |
| 750 | 735 |
| 751 base::SimpleTestTickClock test_clock; | 736 tab_manager.GetWebContentsData(tab2)->SetLastInactiveTime( |
| 737 test_clock.NowTicks()); |
| 738 static_cast<content::MockRenderProcessHost*>(tab2->GetRenderProcessHost()) |
| 739 ->set_is_process_backgrounded(true); |
| 740 EXPECT_TRUE(tab2->GetRenderProcessHost()->IsProcessBackgrounded()); |
| 752 | 741 |
| 753 // Initially PurgeAndSuspend state should be RUNNING. | 742 // Initially PurgeAndSuspend state should be NOT_PURGED. |
| 754 EXPECT_EQ(TabManager::RUNNING, | 743 EXPECT_FALSE(tab_manager.GetWebContentsData(tab2)->is_purged()); |
| 755 tab_manager.GetWebContentsData(tab2)->GetPurgeAndSuspendState()); | 744 tab_manager.GetWebContentsData(tab2)->set_time_to_purge( |
| 745 base::TimeDelta::FromMinutes(1)); |
| 746 test_clock.Advance(base::TimeDelta::FromMinutes(2)); |
| 747 tab_manager.PurgeBackgroundedTabsIfNeeded(); |
| 748 // Since tab2 is kept inactive and background for more than time-to-purge, |
| 749 // tab2 should be purged. |
| 750 EXPECT_TRUE(tab_manager.GetWebContentsData(tab2)->is_purged()); |
| 756 | 751 |
| 757 tab_manager.GetWebContentsData(tab2)->SetPurgeAndSuspendState( | 752 // Activate tab2. Tab2's PurgeAndSuspend state should be NOT_PURGED. |
| 758 TabManager::SUSPENDED); | |
| 759 tab_manager.GetWebContentsData(tab2) | |
| 760 ->SetLastPurgeAndSuspendModifiedTimeForTesting(test_clock.NowTicks()); | |
| 761 | |
| 762 // Activate tab2. Tab2's PurgeAndSuspend state should be RUNNING. | |
| 763 tabstrip.ActivateTabAt(1, true /* user_gesture */); | 753 tabstrip.ActivateTabAt(1, true /* user_gesture */); |
| 764 EXPECT_EQ(TabManager::RUNNING, | 754 EXPECT_FALSE(tab_manager.GetWebContentsData(tab2)->is_purged()); |
| 765 tab_manager.GetWebContentsData(tab2)->GetPurgeAndSuspendState()); | |
| 766 | |
| 767 tab_manager.GetWebContentsData(tab1)->SetPurgeAndSuspendState( | |
| 768 TabManager::RESUMED); | |
| 769 tab_manager.GetWebContentsData(tab1) | |
| 770 ->SetLastPurgeAndSuspendModifiedTimeForTesting(test_clock.NowTicks()); | |
| 771 | |
| 772 // Activate tab1. Tab1's PurgeAndSuspend state should be RUNNING. | |
| 773 tabstrip.ActivateTabAt(0, true /* user_gesture */); | |
| 774 EXPECT_EQ(TabManager::RUNNING, | |
| 775 tab_manager.GetWebContentsData(tab1)->GetPurgeAndSuspendState()); | |
| 776 | |
| 777 // Clean up the tabstrip. | |
| 778 tabstrip.CloseAllTabs(); | |
| 779 EXPECT_TRUE(tabstrip.empty()); | |
| 780 } | 755 } |
| 781 | 756 |
| 782 } // namespace memory | 757 } // namespace memory |
| OLD | NEW |