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

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: Updated. 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
221 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { 204 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) {
222 OnMemoryPressure(level); 205 OnMemoryPressure(level);
223 } 206 }
224 } 207 }
225 #endif 208 #endif
226 // purge-and-suspend param is used for Purge+Suspend finch experiment 209 // purge-and-suspend param is used for Purge+Suspend finch experiment
227 // in the following way: 210 // in the following way:
228 // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7 PPbk/edit?usp=sharing 211 // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7 PPbk/edit?usp=sharing
229 std::string purge_and_suspend_time = variations::GetVariationParamValue( 212 std::string purge_and_suspend_time = variations::GetVariationParamValue(
230 "PurgeAndSuspend", "purge-and-suspend-time"); 213 "PurgeAndSuspend", "purge-and-suspend-time");
231 unsigned int time_to_first_purge_sec = 0; 214 unsigned int min_time_to_purge_sec = 0;
232 if (purge_and_suspend_time.empty() || 215 if (purge_and_suspend_time.empty() ||
233 !base::StringToUint(purge_and_suspend_time, &time_to_first_purge_sec)) 216 !base::StringToUint(purge_and_suspend_time, &min_time_to_purge_sec))
234 time_to_first_suspension_ = kDefaultTimeToFirstPurge; 217 min_time_to_purge_ = kDefaultMinTimeToPurge;
235 else 218 else
236 time_to_first_suspension_ = 219 min_time_to_purge_ = base::TimeDelta::FromSeconds(min_time_to_purge_sec);
237 base::TimeDelta::FromSeconds(time_to_first_purge_sec);
238 } 220 }
239 221
240 void TabManager::Stop() { 222 void TabManager::Stop() {
241 update_timer_.Stop(); 223 update_timer_.Stop();
242 recent_tab_discard_timer_.Stop(); 224 recent_tab_discard_timer_.Stop();
243 memory_pressure_listener_.reset(); 225 memory_pressure_listener_.reset();
244 } 226 }
245 227
228 int TabManager::FindTabStripModelById(int64_t target_web_contents_id,
229 TabStripModel** model) const {
tasak 2017/03/06 10:30:19 I made FindTabStripModelById TabManager's method,
Wez 2017/03/08 02:03:55 Acknowledged.
230 DCHECK(model);
231 // TODO(tasak): Move this code to a TabStripModel enumeration delegate!
232 if (!test_tab_strip_models_.empty()) {
233 for (size_t i = 0; i < test_tab_strip_models_.size(); ++i) {
234 TabStripModel* local_model =
235 const_cast<TabStripModel*>(test_tab_strip_models_[i].first);
236 int idx = FindWebContentsById(local_model, target_web_contents_id);
237 if (idx != -1) {
238 *model = local_model;
239 return idx;
240 }
241 }
242
243 return -1;
244 }
245
246 for (auto* browser : *BrowserList::GetInstance()) {
247 TabStripModel* local_model = browser->tab_strip_model();
248 int idx = FindWebContentsById(local_model, target_web_contents_id);
249 if (idx != -1) {
250 *model = local_model;
251 return idx;
252 }
253 }
254
255 return -1;
256 }
257
246 TabStatsList TabManager::GetTabStats() const { 258 TabStatsList TabManager::GetTabStats() const {
247 TabStatsList stats_list(GetUnsortedTabStats()); 259 TabStatsList stats_list(GetUnsortedTabStats());
248 260
249 // Sort the collected data so that least desirable to be killed is first, most 261 // Sort the collected data so that least desirable to be killed is first, most
250 // desirable is last. 262 // desirable is last.
251 std::sort(stats_list.begin(), stats_list.end(), CompareTabStats); 263 std::sort(stats_list.begin(), stats_list.end(), CompareTabStats);
252 264
253 return stats_list; 265 return stats_list;
254 } 266 }
255 267
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
446 content::WebContents* TabManager::GetWebContentsById( 458 content::WebContents* TabManager::GetWebContentsById(
447 int64_t tab_contents_id) const { 459 int64_t tab_contents_id) const {
448 TabStripModel* model = nullptr; 460 TabStripModel* model = nullptr;
449 int index = FindTabStripModelById(tab_contents_id, &model); 461 int index = FindTabStripModelById(tab_contents_id, &model);
450 if (index == -1) 462 if (index == -1)
451 return nullptr; 463 return nullptr;
452 return model->GetWebContentsAt(index); 464 return model->GetWebContentsAt(index);
453 } 465 }
454 466
455 bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) const { 467 bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) const {
456 // A renderer can be suspended if it's not playing media. 468 // A renderer can be purged if it's not playing media.
457 auto tab_stats = GetUnsortedTabStats(); 469 auto tab_stats = GetUnsortedTabStats();
458 for (auto& tab : tab_stats) { 470 for (auto& tab : tab_stats) {
459 if (tab.child_process_host_id != render_process_id) 471 if (tab.child_process_host_id != render_process_id)
460 continue; 472 continue;
461 WebContents* web_contents = GetWebContentsById(tab.tab_contents_id); 473 WebContents* web_contents = GetWebContentsById(tab.tab_contents_id);
462 if (!web_contents) 474 if (!web_contents)
463 return false; 475 return false;
464 if (IsMediaTab(web_contents)) 476 if (IsMediaTab(web_contents))
465 return false; 477 return false;
466 } 478 }
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 stats.title = contents->GetTitle(); 691 stats.title = contents->GetTitle();
680 stats.tab_contents_id = IdFromWebContents(contents); 692 stats.tab_contents_id = IdFromWebContents(contents);
681 stats_list->push_back(stats); 693 stats_list->push_back(stats);
682 } 694 }
683 } 695 }
684 } 696 }
685 697
686 // This function is called when |update_timer_| fires. It will adjust the clock 698 // This function is called when |update_timer_| fires. It will adjust the clock
687 // if needed (if it detects that the machine was asleep) and will fire the stats 699 // if needed (if it detects that the machine was asleep) and will fire the stats
688 // updating on ChromeOS via the delegate. This function also tries to purge 700 // updating on ChromeOS via the delegate. This function also tries to purge
689 // cache memory and suspend tabs which becomes and keeps backgrounded for a 701 // cache memory.
690 // while.
691 void TabManager::UpdateTimerCallback() { 702 void TabManager::UpdateTimerCallback() {
692 // If Chrome is shutting down, do not do anything. 703 // If Chrome is shutting down, do not do anything.
693 if (g_browser_process->IsShuttingDown()) 704 if (g_browser_process->IsShuttingDown())
694 return; 705 return;
695 706
696 if (BrowserList::GetInstance()->empty()) 707 if (BrowserList::GetInstance()->empty())
697 return; 708 return;
698 709
699 // Check for a discontinuity in time caused by the machine being suspended.
700 if (!last_adjust_time_.is_null()) {
701 TimeDelta suspend_time = NowTicks() - last_adjust_time_;
702 if (suspend_time.InSeconds() > kSuspendThresholdSeconds) {
703 // System was probably suspended, move the event timers forward in time so
704 // when they get subtracted out later, "uptime" is being counted.
705 start_time_ += suspend_time;
706 if (!last_discard_time_.is_null())
707 last_discard_time_ += suspend_time;
708 }
709 }
710 last_adjust_time_ = NowTicks(); 710 last_adjust_time_ = NowTicks();
711 711
712 #if defined(OS_CHROMEOS) 712 #if defined(OS_CHROMEOS)
713 TabStatsList stats_list = GetTabStats(); 713 TabStatsList stats_list = GetTabStats();
714 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. 714 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj.
715 delegate_->AdjustOomPriorities(stats_list); 715 delegate_->AdjustOomPriorities(stats_list);
716 #endif 716 #endif
717 717
718 PurgeAndSuspendBackgroundedTabs(); 718 PurgeBackgroundedTabsIfNeeded();
719 } 719 }
720 720
721 TabManager::PurgeAndSuspendState TabManager::GetNextPurgeAndSuspendState( 721 base::TimeDelta TabManager::GetTimeToPurge(
722 content::WebContents* content, 722 base::TimeDelta min_time_to_purge) const {
723 base::TimeTicks current_time, 723 return base::TimeDelta::FromSeconds(base::RandInt(
724 const base::TimeDelta& time_to_first_suspension) const { 724 min_time_to_purge.InSeconds(), min_time_to_purge.InSeconds() * 2));
725 DCHECK(content);
726 PurgeAndSuspendState state =
727 GetWebContentsData(content)->GetPurgeAndSuspendState();
728
729 auto time_passed = current_time -
730 GetWebContentsData(content)->LastPurgeAndSuspendModifiedTime();
731 switch (state) {
732 case RUNNING:
733 if (time_passed > time_to_first_suspension)
734 return SUSPENDED;
735 break;
736 case RESUMED:
737 if (time_passed > kDurationOfRendererResumption)
738 return SUSPENDED;
739 break;
740 case SUSPENDED:
741 if (time_passed > kDurationOfRendererSuspension)
742 return RESUMED;
743 break;
744 }
745 return state;
746 } 725 }
747 726
748 void TabManager::PurgeAndSuspendBackgroundedTabs() { 727 bool TabManager::ShouldPurgeNow(content::WebContents* content) const {
749 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() {
750 auto tab_stats = GetUnsortedTabStats(); 737 auto tab_stats = GetUnsortedTabStats();
751 for (auto& tab : tab_stats) { 738 for (auto& tab : tab_stats) {
752 if (!tab.render_process_host->IsProcessBackgrounded()) 739 if (!tab.render_process_host->IsProcessBackgrounded())
753 continue; 740 continue;
754 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id)) 741 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id))
755 continue; 742 continue;
756 743
757 WebContents* content = GetWebContentsById(tab.tab_contents_id); 744 WebContents* content = GetWebContentsById(tab.tab_contents_id);
758 if (!content) 745 if (!content)
759 continue; 746 continue;
760 747
761 PurgeAndSuspendState current_state = 748 bool purge_now = ShouldPurgeNow(content);
762 GetWebContentsData(content)->GetPurgeAndSuspendState(); 749 if (!purge_now)
763 // If the tab's purge-and-suspend state is not RUNNING, the tab should be
764 // backgrounded. Since tab.last_hidden is updated everytime the tab is
765 // hidden, we should see tab.last_hidden < last_modified_time.
766 DCHECK(current_state == RUNNING ||
767 tab.last_hidden <
768 GetWebContentsData(content)->LastPurgeAndSuspendModifiedTime());
769 PurgeAndSuspendState next_state = GetNextPurgeAndSuspendState(
770 content, current_time, time_to_first_suspension_);
771 if (current_state == next_state)
772 continue; 750 continue;
773 751
774 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without 752 // Since |content|'s tab is kept inactive and background for more than
775 // timers for simplicity, so PurgeAndSuspend is called even after the 753 // time-to-purge time, its purged state changes: false => true.
776 // renderer is purged and suspended once. This should be replaced with 754 GetWebContentsData(content)->set_is_purged(true);
777 // timers if we want necessary and sufficient signals. 755 // TODO(tasak): rename PurgeAndSuspend with a better name, e.g.
778 GetWebContentsData(content)->SetPurgeAndSuspendState(next_state); 756 // RequestPurgeCache, because we don't suspend any renderers.
779 switch (next_state) { 757 tab.render_process_host->PurgeAndSuspend();
780 case SUSPENDED:
781 tab.render_process_host->PurgeAndSuspend();
782 break;
783 case RESUMED:
784 tab.render_process_host->Resume();
785 break;
786 case RUNNING:
787 NOTREACHED();
788 }
789 } 758 }
790 } 759 }
791 760
792 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) { 761 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) {
793 // Can't discard active index. 762 // Can't discard active index.
794 if (model->active_index() == index) 763 if (model->active_index() == index)
795 return nullptr; 764 return nullptr;
796 765
797 WebContents* old_contents = model->GetWebContentsAt(index); 766 WebContents* old_contents = model->GetWebContentsAt(index);
798 767
(...skipping 19 matching lines...) Expand all
818 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime()); 787 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime());
819 // Copy over the discard count. 788 // Copy over the discard count.
820 WebContentsData::CopyState(old_contents, null_contents); 789 WebContentsData::CopyState(old_contents, null_contents);
821 790
822 // Replace the discarded tab with the null version. 791 // Replace the discarded tab with the null version.
823 model->ReplaceWebContentsAt(index, null_contents); 792 model->ReplaceWebContentsAt(index, null_contents);
824 // Mark the tab so it will reload when clicked on. 793 // Mark the tab so it will reload when clicked on.
825 GetWebContentsData(null_contents)->SetDiscardState(true); 794 GetWebContentsData(null_contents)->SetDiscardState(true);
826 GetWebContentsData(null_contents)->IncrementDiscardCount(); 795 GetWebContentsData(null_contents)->IncrementDiscardCount();
827 796
797 // Make the tab PURGED to avoid purging null_contents.
798 GetWebContentsData(null_contents)->set_is_purged(true);
799
828 // Discard the old tab's renderer. 800 // Discard the old tab's renderer.
829 // TODO(jamescook): This breaks script connections with other tabs. 801 // TODO(jamescook): This breaks script connections with other tabs.
830 // 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
831 // to swappedout://. 803 // to swappedout://.
832 delete old_contents; 804 delete old_contents;
833 recent_tab_discard_ = true; 805 recent_tab_discard_ = true;
834 806
835 return null_contents; 807 return null_contents;
836 } 808 }
837 809
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
879 data->SetRecentlyAudible(current_state); 851 data->SetRecentlyAudible(current_state);
880 data->SetLastAudioChangeTime(NowTicks()); 852 data->SetLastAudioChangeTime(NowTicks());
881 } 853 }
882 } 854 }
883 855
884 void TabManager::ActiveTabChanged(content::WebContents* old_contents, 856 void TabManager::ActiveTabChanged(content::WebContents* old_contents,
885 content::WebContents* new_contents, 857 content::WebContents* new_contents,
886 int index, 858 int index,
887 int reason) { 859 int reason) {
888 GetWebContentsData(new_contents)->SetDiscardState(false); 860 GetWebContentsData(new_contents)->SetDiscardState(false);
889 GetWebContentsData(new_contents)->SetPurgeAndSuspendState(RUNNING); 861 // When ActiveTabChaged, |new_contents| purged state changes to be false.
862 GetWebContentsData(new_contents)->set_is_purged(false);
890 // 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
891 // inactive, so record the time of that transition. 864 // inactive, so record the time of that transition.
892 if (old_contents) 865 if (old_contents) {
893 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 }
894 } 871 }
895 872
896 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, 873 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model,
897 content::WebContents* contents, 874 content::WebContents* contents,
898 int index, 875 int index,
899 bool foreground) { 876 bool foreground) {
900 // 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
901 // ActiveTabChanged. 878 // ActiveTabChanged.
902 if (foreground) 879 if (foreground)
903 return; 880 return;
904 881
905 // 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
906 // inactive. 883 // inactive.
907 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_));
908 } 888 }
909 889
910 bool TabManager::IsMediaTab(WebContents* contents) const { 890 bool TabManager::IsMediaTab(WebContents* contents) const {
911 if (contents->WasRecentlyAudible()) 891 if (contents->WasRecentlyAudible())
912 return true; 892 return true;
913 893
914 scoped_refptr<MediaStreamCaptureIndicator> media_indicator = 894 scoped_refptr<MediaStreamCaptureIndicator> media_indicator =
915 MediaCaptureDevicesDispatcher::GetInstance() 895 MediaCaptureDevicesDispatcher::GetInstance()
916 ->GetMediaStreamCaptureIndicator(); 896 ->GetMediaStreamCaptureIndicator();
917 if (media_indicator->IsCapturingUserMedia(contents) || 897 if (media_indicator->IsCapturingUserMedia(contents) ||
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
1031 // platform. 1011 // platform.
1032 std::string allow_multiple_discards = variations::GetVariationParamValue( 1012 std::string allow_multiple_discards = variations::GetVariationParamValue(
1033 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); 1013 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards");
1034 return (allow_multiple_discards != "true"); 1014 return (allow_multiple_discards != "true");
1035 #else 1015 #else
1036 return false; 1016 return false;
1037 #endif 1017 #endif
1038 } 1018 }
1039 1019
1040 } // 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