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

Side by Side Diff: chrome/browser/memory/tab_manager.cc

Issue 2711093002: Purge once random minutes(between 30min and 60min) after backgrounded. (Closed)
Patch Set: Fixed Created 3 years, 9 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
« no previous file with comments | « chrome/browser/memory/tab_manager.h ('k') | chrome/browser/memory/tab_manager_browsertest.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/memory/tab_manager.h" 5 #include "chrome/browser/memory/tab_manager.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <set> 10 #include <set>
11 #include <vector> 11 #include <vector>
12 12
13 #include "base/bind.h" 13 #include "base/bind.h"
14 #include "base/bind_helpers.h" 14 #include "base/bind_helpers.h"
15 #include "base/command_line.h" 15 #include "base/command_line.h"
16 #include "base/feature_list.h" 16 #include "base/feature_list.h"
17 #include "base/macros.h" 17 #include "base/macros.h"
18 #include "base/memory/memory_pressure_monitor.h" 18 #include "base/memory/memory_pressure_monitor.h"
19 #include "base/metrics/field_trial.h" 19 #include "base/metrics/field_trial.h"
20 #include "base/metrics/histogram_macros.h" 20 #include "base/metrics/histogram_macros.h"
21 #include "base/observer_list.h" 21 #include "base/observer_list.h"
22 #include "base/process/process.h" 22 #include "base/process/process.h"
23 #include "base/rand_util.h"
23 #include "base/strings/string16.h" 24 #include "base/strings/string16.h"
24 #include "base/strings/string_number_conversions.h" 25 #include "base/strings/string_number_conversions.h"
25 #include "base/strings/string_util.h" 26 #include "base/strings/string_util.h"
26 #include "base/strings/utf_string_conversions.h" 27 #include "base/strings/utf_string_conversions.h"
27 #include "base/threading/thread.h" 28 #include "base/threading/thread.h"
28 #include "base/threading/thread_task_runner_handle.h" 29 #include "base/threading/thread_task_runner_handle.h"
29 #include "base/time/tick_clock.h" 30 #include "base/time/tick_clock.h"
30 #include "build/build_config.h" 31 #include "build/build_config.h"
31 #include "chrome/browser/browser_process.h" 32 #include "chrome/browser/browser_process.h"
32 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" 33 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 // value. 74 // value.
74 const int kAdjustmentIntervalSeconds = 10; 75 const int kAdjustmentIntervalSeconds = 10;
75 76
76 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) 77 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
77 // For each period of this length record a statistic to indicate whether or not 78 // For each period of this length record a statistic to indicate whether or not
78 // the user experienced a low memory event. If this interval is changed, 79 // the user experienced a low memory event. If this interval is changed,
79 // Tabs.Discard.DiscardInLastMinute must be replaced with a new statistic. 80 // Tabs.Discard.DiscardInLastMinute must be replaced with a new statistic.
80 const int kRecentTabDiscardIntervalSeconds = 60; 81 const int kRecentTabDiscardIntervalSeconds = 60;
81 #endif 82 #endif
82 83
83 // If there has been no priority adjustment in this interval, assume the
84 // machine was suspended and correct the timing statistics.
85 const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4;
86
87 // A suspended renderer is suspended for this duration.
88 constexpr base::TimeDelta kDurationOfRendererSuspension =
89 base::TimeDelta::FromSeconds(1200);
90
91 // A resumed renderer is resumed for this duration.
92 constexpr base::TimeDelta kDurationOfRendererResumption =
93 base::TimeDelta::FromSeconds(10);
94
95 // The time during which a tab is protected from discarding after it stops being 84 // The time during which a tab is protected from discarding after it stops being
96 // audible. 85 // audible.
97 const int kAudioProtectionTimeSeconds = 60; 86 const int kAudioProtectionTimeSeconds = 60;
98 87
99 int FindTabStripModelById(int64_t target_web_contents_id, 88 int FindWebContentsById(const TabStripModel* model,
100 TabStripModel** model) { 89 int64_t target_web_contents_id) {
101 DCHECK(model); 90 for (int idx = 0; idx < model->count(); idx++) {
102 for (auto* browser : *BrowserList::GetInstance()) { 91 WebContents* web_contents = model->GetWebContentsAt(idx);
103 TabStripModel* local_model = browser->tab_strip_model(); 92 int64_t web_contents_id = TabManager::IdFromWebContents(web_contents);
104 for (int idx = 0; idx < local_model->count(); idx++) { 93 if (web_contents_id == target_web_contents_id)
105 WebContents* web_contents = local_model->GetWebContentsAt(idx); 94 return idx;
106 int64_t web_contents_id = TabManager::IdFromWebContents(web_contents);
107 if (web_contents_id == target_web_contents_id) {
108 *model = local_model;
109 return idx;
110 }
111 }
112 } 95 }
113 96
114 return -1; 97 return -1;
115 } 98 }
116 99
117 // A wrapper around base::MemoryPressureMonitor::GetCurrentPressureLevel. 100 // A wrapper around base::MemoryPressureMonitor::GetCurrentPressureLevel.
118 // TODO(chrisha): Move this do the default implementation of a delegate. 101 // TODO(chrisha): Move this do the default implementation of a delegate.
119 base::MemoryPressureListener::MemoryPressureLevel 102 base::MemoryPressureListener::MemoryPressureLevel
120 GetCurrentPressureLevel() { 103 GetCurrentPressureLevel() {
121 auto* monitor = base::MemoryPressureMonitor::Get(); 104 auto* monitor = base::MemoryPressureMonitor::Get();
(...skipping 10 matching lines...) Expand all
132 base::MemoryPressureListener::MemoryPressureLevel level) { 115 base::MemoryPressureListener::MemoryPressureLevel level) {
133 content::MemoryPressureController::SendPressureNotification( 116 content::MemoryPressureController::SendPressureNotification(
134 render_process_host, level); 117 render_process_host, level);
135 } 118 }
136 119
137 } // namespace 120 } // namespace
138 121
139 //////////////////////////////////////////////////////////////////////////////// 122 ////////////////////////////////////////////////////////////////////////////////
140 // TabManager 123 // TabManager
141 124
142 constexpr base::TimeDelta TabManager::kDefaultTimeToFirstPurge; 125 constexpr base::TimeDelta TabManager::kDefaultMinTimeToPurge;
143 126
144 TabManager::TabManager() 127 TabManager::TabManager()
145 : discard_count_(0), 128 : discard_count_(0),
146 recent_tab_discard_(false), 129 recent_tab_discard_(false),
147 discard_once_(false), 130 discard_once_(false),
148 #if !defined(OS_CHROMEOS) 131 #if !defined(OS_CHROMEOS)
149 minimum_protection_time_(base::TimeDelta::FromMinutes(10)), 132 minimum_protection_time_(base::TimeDelta::FromMinutes(10)),
150 #endif 133 #endif
151 browser_tab_strip_tracker_(this, nullptr, nullptr), 134 browser_tab_strip_tracker_(this, nullptr, nullptr),
152 test_tick_clock_(nullptr), 135 test_tick_clock_(nullptr),
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { 203 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
221 OnMemoryPressure(level); 204 OnMemoryPressure(level);
222 } 205 }
223 } 206 }
224 #endif 207 #endif
225 // purge-and-suspend param is used for Purge+Suspend finch experiment 208 // purge-and-suspend param is used for Purge+Suspend finch experiment
226 // in the following way: 209 // in the following way:
227 // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7 PPbk/edit?usp=sharing 210 // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7 PPbk/edit?usp=sharing
228 std::string purge_and_suspend_time = variations::GetVariationParamValue( 211 std::string purge_and_suspend_time = variations::GetVariationParamValue(
229 "PurgeAndSuspend", "purge-and-suspend-time"); 212 "PurgeAndSuspend", "purge-and-suspend-time");
230 unsigned int time_to_first_purge_sec = 0; 213 unsigned int min_time_to_purge_sec = 0;
231 if (purge_and_suspend_time.empty() || 214 if (purge_and_suspend_time.empty() ||
232 !base::StringToUint(purge_and_suspend_time, &time_to_first_purge_sec)) 215 !base::StringToUint(purge_and_suspend_time, &min_time_to_purge_sec))
233 time_to_first_suspension_ = kDefaultTimeToFirstPurge; 216 min_time_to_purge_ = kDefaultMinTimeToPurge;
234 else 217 else
235 time_to_first_suspension_ = 218 min_time_to_purge_ = base::TimeDelta::FromSeconds(min_time_to_purge_sec);
236 base::TimeDelta::FromSeconds(time_to_first_purge_sec);
237 } 219 }
238 220
239 void TabManager::Stop() { 221 void TabManager::Stop() {
240 update_timer_.Stop(); 222 update_timer_.Stop();
241 recent_tab_discard_timer_.Stop(); 223 recent_tab_discard_timer_.Stop();
242 memory_pressure_listener_.reset(); 224 memory_pressure_listener_.reset();
243 } 225 }
244 226
227 int TabManager::FindTabStripModelById(int64_t target_web_contents_id,
228 TabStripModel** model) const {
229 DCHECK(model);
230 // TODO(tasak): Move this code to a TabStripModel enumeration delegate!
231 if (!test_tab_strip_models_.empty()) {
232 for (size_t i = 0; i < test_tab_strip_models_.size(); ++i) {
233 TabStripModel* local_model =
234 const_cast<TabStripModel*>(test_tab_strip_models_[i].first);
235 int idx = FindWebContentsById(local_model, target_web_contents_id);
236 if (idx != -1) {
237 *model = local_model;
238 return idx;
239 }
240 }
241
242 return -1;
243 }
244
245 for (auto* browser : *BrowserList::GetInstance()) {
246 TabStripModel* local_model = browser->tab_strip_model();
247 int idx = FindWebContentsById(local_model, target_web_contents_id);
248 if (idx != -1) {
249 *model = local_model;
250 return idx;
251 }
252 }
253
254 return -1;
255 }
256
245 TabStatsList TabManager::GetTabStats() const { 257 TabStatsList TabManager::GetTabStats() const {
246 TabStatsList stats_list(GetUnsortedTabStats()); 258 TabStatsList stats_list(GetUnsortedTabStats());
247 259
248 // Sort the collected data so that least desirable to be killed is first, most 260 // Sort the collected data so that least desirable to be killed is first, most
249 // desirable is last. 261 // desirable is last.
250 std::sort(stats_list.begin(), stats_list.end(), CompareTabStats); 262 std::sort(stats_list.begin(), stats_list.end(), CompareTabStats);
251 263
252 return stats_list; 264 return stats_list;
253 } 265 }
254 266
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
445 content::WebContents* TabManager::GetWebContentsById( 457 content::WebContents* TabManager::GetWebContentsById(
446 int64_t tab_contents_id) const { 458 int64_t tab_contents_id) const {
447 TabStripModel* model = nullptr; 459 TabStripModel* model = nullptr;
448 int index = FindTabStripModelById(tab_contents_id, &model); 460 int index = FindTabStripModelById(tab_contents_id, &model);
449 if (index == -1) 461 if (index == -1)
450 return nullptr; 462 return nullptr;
451 return model->GetWebContentsAt(index); 463 return model->GetWebContentsAt(index);
452 } 464 }
453 465
454 bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) const { 466 bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) const {
455 // A renderer can be suspended if it's not playing media. 467 // A renderer can be purged if it's not playing media.
456 auto tab_stats = GetUnsortedTabStats(); 468 auto tab_stats = GetUnsortedTabStats();
457 for (auto& tab : tab_stats) { 469 for (auto& tab : tab_stats) {
458 if (tab.child_process_host_id != render_process_id) 470 if (tab.child_process_host_id != render_process_id)
459 continue; 471 continue;
460 WebContents* web_contents = GetWebContentsById(tab.tab_contents_id); 472 WebContents* web_contents = GetWebContentsById(tab.tab_contents_id);
461 if (!web_contents) 473 if (!web_contents)
462 return false; 474 return false;
463 if (IsMediaTab(web_contents)) 475 if (IsMediaTab(web_contents))
464 return false; 476 return false;
465 } 477 }
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
678 stats.title = contents->GetTitle(); 690 stats.title = contents->GetTitle();
679 stats.tab_contents_id = IdFromWebContents(contents); 691 stats.tab_contents_id = IdFromWebContents(contents);
680 stats_list->push_back(stats); 692 stats_list->push_back(stats);
681 } 693 }
682 } 694 }
683 } 695 }
684 696
685 // This function is called when |update_timer_| fires. It will adjust the clock 697 // This function is called when |update_timer_| fires. It will adjust the clock
686 // if needed (if it detects that the machine was asleep) and will fire the stats 698 // if needed (if it detects that the machine was asleep) and will fire the stats
687 // updating on ChromeOS via the delegate. This function also tries to purge 699 // updating on ChromeOS via the delegate. This function also tries to purge
688 // cache memory and suspend tabs which becomes and keeps backgrounded for a 700 // cache memory.
689 // while.
690 void TabManager::UpdateTimerCallback() { 701 void TabManager::UpdateTimerCallback() {
691 // If Chrome is shutting down, do not do anything. 702 // If Chrome is shutting down, do not do anything.
692 if (g_browser_process->IsShuttingDown()) 703 if (g_browser_process->IsShuttingDown())
693 return; 704 return;
694 705
695 if (BrowserList::GetInstance()->empty()) 706 if (BrowserList::GetInstance()->empty())
696 return; 707 return;
697 708
698 // Check for a discontinuity in time caused by the machine being suspended.
699 if (!last_adjust_time_.is_null()) {
700 TimeDelta suspend_time = NowTicks() - last_adjust_time_;
701 if (suspend_time.InSeconds() > kSuspendThresholdSeconds) {
702 // System was probably suspended, move the event timers forward in time so
703 // when they get subtracted out later, "uptime" is being counted.
704 start_time_ += suspend_time;
705 if (!last_discard_time_.is_null())
706 last_discard_time_ += suspend_time;
707 }
708 }
709 last_adjust_time_ = NowTicks(); 709 last_adjust_time_ = NowTicks();
710 710
711 #if defined(OS_CHROMEOS) 711 #if defined(OS_CHROMEOS)
712 TabStatsList stats_list = GetTabStats(); 712 TabStatsList stats_list = GetTabStats();
713 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. 713 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj.
714 delegate_->AdjustOomPriorities(stats_list); 714 delegate_->AdjustOomPriorities(stats_list);
715 #endif 715 #endif
716 716
717 PurgeAndSuspendBackgroundedTabs(); 717 PurgeBackgroundedTabsIfNeeded();
718 } 718 }
719 719
720 TabManager::PurgeAndSuspendState TabManager::GetNextPurgeAndSuspendState( 720 base::TimeDelta TabManager::GetTimeToPurge(
721 content::WebContents* content, 721 base::TimeDelta min_time_to_purge) const {
722 base::TimeTicks current_time, 722 return base::TimeDelta::FromSeconds(
723 const base::TimeDelta& time_to_first_suspension) const { 723 base::RandInt(min_time_to_purge.InSeconds(),
724 DCHECK(content); 724 min_time_to_purge.InSeconds() * kMinMaxTimeToPurgeRatio));
725 PurgeAndSuspendState state =
726 GetWebContentsData(content)->GetPurgeAndSuspendState();
727
728 auto time_passed = current_time -
729 GetWebContentsData(content)->LastPurgeAndSuspendModifiedTime();
730 switch (state) {
731 case RUNNING:
732 if (time_passed > time_to_first_suspension)
733 return SUSPENDED;
734 break;
735 case RESUMED:
736 if (time_passed > kDurationOfRendererResumption)
737 return SUSPENDED;
738 break;
739 case SUSPENDED:
740 if (time_passed > kDurationOfRendererSuspension)
741 return RESUMED;
742 break;
743 }
744 return state;
745 } 725 }
746 726
747 void TabManager::PurgeAndSuspendBackgroundedTabs() { 727 bool TabManager::ShouldPurgeNow(content::WebContents* content) const {
748 base::TimeTicks current_time = NowTicks(); 728 if (GetWebContentsData(content)->is_purged())
729 return false;
730
731 base::TimeDelta time_passed =
732 NowTicks() - GetWebContentsData(content)->LastInactiveTime();
733 return time_passed > GetWebContentsData(content)->time_to_purge();
734 }
735
736 void TabManager::PurgeBackgroundedTabsIfNeeded() {
749 auto tab_stats = GetUnsortedTabStats(); 737 auto tab_stats = GetUnsortedTabStats();
750 for (auto& tab : tab_stats) { 738 for (auto& tab : tab_stats) {
751 if (!tab.render_process_host->IsProcessBackgrounded()) 739 if (!tab.render_process_host->IsProcessBackgrounded())
752 continue; 740 continue;
753 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id)) 741 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id))
754 continue; 742 continue;
755 743
756 WebContents* content = GetWebContentsById(tab.tab_contents_id); 744 WebContents* content = GetWebContentsById(tab.tab_contents_id);
757 if (!content) 745 if (!content)
758 continue; 746 continue;
759 747
760 PurgeAndSuspendState current_state = 748 bool purge_now = ShouldPurgeNow(content);
761 GetWebContentsData(content)->GetPurgeAndSuspendState(); 749 if (!purge_now)
762 // If the tab's purge-and-suspend state is not RUNNING, the tab should be
763 // backgrounded. Since tab.last_hidden is updated everytime the tab is
764 // hidden, we should see tab.last_hidden < last_modified_time.
765 DCHECK(current_state == RUNNING ||
766 tab.last_hidden <
767 GetWebContentsData(content)->LastPurgeAndSuspendModifiedTime());
768 PurgeAndSuspendState next_state = GetNextPurgeAndSuspendState(
769 content, current_time, time_to_first_suspension_);
770 if (current_state == next_state)
771 continue; 750 continue;
772 751
773 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without 752 // Since |content|'s tab is kept inactive and background for more than
774 // timers for simplicity, so PurgeAndSuspend is called even after the 753 // time-to-purge time, its purged state changes: false => true.
775 // renderer is purged and suspended once. This should be replaced with 754 GetWebContentsData(content)->set_is_purged(true);
776 // timers if we want necessary and sufficient signals. 755 // TODO(tasak): rename PurgeAndSuspend with a better name, e.g.
777 GetWebContentsData(content)->SetPurgeAndSuspendState(next_state); 756 // RequestPurgeCache, because we don't suspend any renderers.
778 switch (next_state) { 757 tab.render_process_host->PurgeAndSuspend();
779 case SUSPENDED:
780 tab.render_process_host->PurgeAndSuspend();
781 break;
782 case RESUMED:
783 tab.render_process_host->Resume();
784 break;
785 case RUNNING:
786 NOTREACHED();
787 }
788 } 758 }
789 } 759 }
790 760
791 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) { 761 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) {
792 // Can't discard active index. 762 // Can't discard active index.
793 if (model->active_index() == index) 763 if (model->active_index() == index)
794 return nullptr; 764 return nullptr;
795 765
796 WebContents* old_contents = model->GetWebContentsAt(index); 766 WebContents* old_contents = model->GetWebContentsAt(index);
797 767
(...skipping 19 matching lines...) Expand all
817 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime()); 787 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime());
818 // Copy over the discard count. 788 // Copy over the discard count.
819 WebContentsData::CopyState(old_contents, null_contents); 789 WebContentsData::CopyState(old_contents, null_contents);
820 790
821 // Replace the discarded tab with the null version. 791 // Replace the discarded tab with the null version.
822 model->ReplaceWebContentsAt(index, null_contents); 792 model->ReplaceWebContentsAt(index, null_contents);
823 // Mark the tab so it will reload when clicked on. 793 // Mark the tab so it will reload when clicked on.
824 GetWebContentsData(null_contents)->SetDiscardState(true); 794 GetWebContentsData(null_contents)->SetDiscardState(true);
825 GetWebContentsData(null_contents)->IncrementDiscardCount(); 795 GetWebContentsData(null_contents)->IncrementDiscardCount();
826 796
797 // Make the tab PURGED to avoid purging null_contents.
798 GetWebContentsData(null_contents)->set_is_purged(true);
799
827 // Discard the old tab's renderer. 800 // Discard the old tab's renderer.
828 // TODO(jamescook): This breaks script connections with other tabs. 801 // TODO(jamescook): This breaks script connections with other tabs.
829 // Find a different approach that doesn't do that, perhaps based on navigation 802 // Find a different approach that doesn't do that, perhaps based on navigation
830 // to swappedout://. 803 // to swappedout://.
831 delete old_contents; 804 delete old_contents;
832 recent_tab_discard_ = true; 805 recent_tab_discard_ = true;
833 806
834 return null_contents; 807 return null_contents;
835 } 808 }
836 809
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
878 data->SetRecentlyAudible(current_state); 851 data->SetRecentlyAudible(current_state);
879 data->SetLastAudioChangeTime(NowTicks()); 852 data->SetLastAudioChangeTime(NowTicks());
880 } 853 }
881 } 854 }
882 855
883 void TabManager::ActiveTabChanged(content::WebContents* old_contents, 856 void TabManager::ActiveTabChanged(content::WebContents* old_contents,
884 content::WebContents* new_contents, 857 content::WebContents* new_contents,
885 int index, 858 int index,
886 int reason) { 859 int reason) {
887 GetWebContentsData(new_contents)->SetDiscardState(false); 860 GetWebContentsData(new_contents)->SetDiscardState(false);
888 GetWebContentsData(new_contents)->SetPurgeAndSuspendState(RUNNING); 861 // When ActiveTabChanged, |new_contents| purged state changes to be false.
862 GetWebContentsData(new_contents)->set_is_purged(false);
889 // If |old_contents| is set, that tab has switched from being active to 863 // If |old_contents| is set, that tab has switched from being active to
890 // inactive, so record the time of that transition. 864 // inactive, so record the time of that transition.
891 if (old_contents) 865 if (old_contents) {
892 GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); 866 GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks());
867 // Re-setting time-to-purge every time a tab becomes inactive.
868 GetWebContentsData(old_contents)
869 ->set_time_to_purge(GetTimeToPurge(min_time_to_purge_));
870 }
893 } 871 }
894 872
895 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, 873 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model,
896 content::WebContents* contents, 874 content::WebContents* contents,
897 int index, 875 int index,
898 bool foreground) { 876 bool foreground) {
899 // Only interested in background tabs, as foreground tabs get taken care of by 877 // Only interested in background tabs, as foreground tabs get taken care of by
900 // ActiveTabChanged. 878 // ActiveTabChanged.
901 if (foreground) 879 if (foreground)
902 return; 880 return;
903 881
904 // A new background tab is similar to having a tab switch from being active to 882 // A new background tab is similar to having a tab switch from being active to
905 // inactive. 883 // inactive.
906 GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); 884 GetWebContentsData(contents)->SetLastInactiveTime(NowTicks());
885 // Re-setting time-to-purge every time a tab becomes inactive.
886 GetWebContentsData(contents)->set_time_to_purge(
887 GetTimeToPurge(min_time_to_purge_));
907 } 888 }
908 889
909 bool TabManager::IsMediaTab(WebContents* contents) const { 890 bool TabManager::IsMediaTab(WebContents* contents) const {
910 if (contents->WasRecentlyAudible()) 891 if (contents->WasRecentlyAudible())
911 return true; 892 return true;
912 893
913 scoped_refptr<MediaStreamCaptureIndicator> media_indicator = 894 scoped_refptr<MediaStreamCaptureIndicator> media_indicator =
914 MediaCaptureDevicesDispatcher::GetInstance() 895 MediaCaptureDevicesDispatcher::GetInstance()
915 ->GetMediaStreamCaptureIndicator(); 896 ->GetMediaStreamCaptureIndicator();
916 if (media_indicator->IsCapturingUserMedia(contents) || 897 if (media_indicator->IsCapturingUserMedia(contents) ||
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1030 // platform. 1011 // platform.
1031 std::string allow_multiple_discards = variations::GetVariationParamValue( 1012 std::string allow_multiple_discards = variations::GetVariationParamValue(
1032 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); 1013 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards");
1033 return (allow_multiple_discards != "true"); 1014 return (allow_multiple_discards != "true");
1034 #else 1015 #else
1035 return false; 1016 return false;
1036 #endif 1017 #endif
1037 } 1018 }
1038 1019
1039 } // namespace memory 1020 } // namespace memory
OLDNEW
« no previous file with comments | « chrome/browser/memory/tab_manager.h ('k') | chrome/browser/memory/tab_manager_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698