Chromium Code Reviews| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <set> | 10 #include <set> |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 TabManager::~TabManager() { | 158 TabManager::~TabManager() { |
| 159 Stop(); | 159 Stop(); |
| 160 } | 160 } |
| 161 | 161 |
| 162 void TabManager::Start() { | 162 void TabManager::Start() { |
| 163 #if defined(OS_WIN) || defined(OS_MACOSX) | 163 #if defined(OS_WIN) || defined(OS_MACOSX) |
| 164 // If the feature is not enabled, do nothing. | 164 // If the feature is not enabled, do nothing. |
| 165 if (!base::FeatureList::IsEnabled(features::kAutomaticTabDiscarding)) | 165 if (!base::FeatureList::IsEnabled(features::kAutomaticTabDiscarding)) |
| 166 return; | 166 return; |
| 167 | 167 |
| 168 // Check the variation parameter to see if a tab be discarded more than once. | |
| 169 // Default is to only discard once per tab. | |
| 170 std::string allow_multiple_discards = variations::GetVariationParamValue( | |
| 171 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); | |
| 172 if (allow_multiple_discards == "true") | |
| 173 discard_once_ = true; | |
| 174 else | |
| 175 discard_once_ = false; | |
| 176 | |
| 177 // Check the variation parameter to see if a tab is to be protected for an | 168 // Check the variation parameter to see if a tab is to be protected for an |
| 178 // amount of time after being backgrounded. The value is in seconds. | 169 // amount of time after being backgrounded. The value is in seconds. |
| 179 std::string minimum_protection_time_string = | 170 std::string minimum_protection_time_string = |
| 180 variations::GetVariationParamValue(features::kAutomaticTabDiscarding.name, | 171 variations::GetVariationParamValue(features::kAutomaticTabDiscarding.name, |
| 181 "MinimumProtectionTime"); | 172 "MinimumProtectionTime"); |
| 182 if (!minimum_protection_time_string.empty()) { | 173 if (!minimum_protection_time_string.empty()) { |
| 183 unsigned int minimum_protection_time_seconds = 0; | 174 unsigned int minimum_protection_time_seconds = 0; |
| 184 if (base::StringToUint(minimum_protection_time_string, | 175 if (base::StringToUint(minimum_protection_time_string, |
| 185 &minimum_protection_time_seconds)) { | 176 &minimum_protection_time_seconds)) { |
| 186 if (minimum_protection_time_seconds > 0) | 177 if (minimum_protection_time_seconds > 0) |
| 187 minimum_protection_time_ = | 178 minimum_protection_time_ = |
| 188 base::TimeDelta::FromSeconds(minimum_protection_time_seconds); | 179 base::TimeDelta::FromSeconds(minimum_protection_time_seconds); |
| 189 } | 180 } |
| 190 } | 181 } |
| 182 #endif | |
| 191 | 183 |
| 192 #elif defined(OS_CHROMEOS) | 184 // Check if multiple discards are allowed. |
| 193 // On Chrome OS, tab manager is always started and tabs can be discarded more | 185 discard_once_ = !AllowMultipleDiscards(); |
| 194 // than once. | |
| 195 discard_once_ = false; | |
| 196 #endif | |
| 197 | 186 |
| 198 if (!update_timer_.IsRunning()) { | 187 if (!update_timer_.IsRunning()) { |
| 199 update_timer_.Start(FROM_HERE, | 188 update_timer_.Start(FROM_HERE, |
| 200 TimeDelta::FromSeconds(kAdjustmentIntervalSeconds), | 189 TimeDelta::FromSeconds(kAdjustmentIntervalSeconds), |
| 201 this, &TabManager::UpdateTimerCallback); | 190 this, &TabManager::UpdateTimerCallback); |
| 202 } | 191 } |
| 203 | 192 |
| 204 // MemoryPressureMonitor is not implemented on Linux so far and tabs are never | 193 // MemoryPressureMonitor is not implemented on Linux so far and tabs are never |
| 205 // discarded. | 194 // discarded. |
| 206 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) | 195 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS) |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 554 if (!command_line.HasSwitch(switches::kPurgeAndSuspendTime)) | 543 if (!command_line.HasSwitch(switches::kPurgeAndSuspendTime)) |
| 555 return; | 544 return; |
| 556 int purge_and_suspend_time = 0; | 545 int purge_and_suspend_time = 0; |
| 557 if (!base::StringToInt( | 546 if (!base::StringToInt( |
| 558 command_line.GetSwitchValueASCII(switches::kPurgeAndSuspendTime), | 547 command_line.GetSwitchValueASCII(switches::kPurgeAndSuspendTime), |
| 559 &purge_and_suspend_time)) { | 548 &purge_and_suspend_time)) { |
| 560 return; | 549 return; |
| 561 } | 550 } |
| 562 if (purge_and_suspend_time <= 0) | 551 if (purge_and_suspend_time <= 0) |
| 563 return; | 552 return; |
| 564 auto purge_and_suspend_time_threshold = NowTicks() - | 553 auto purge_and_suspend_time_threshold = |
| 565 base::TimeDelta::FromSeconds(purge_and_suspend_time); | 554 NowTicks() - base::TimeDelta::FromSeconds(purge_and_suspend_time); |
| 566 auto tab_stats = GetUnsortedTabStats(); | 555 auto tab_stats = GetUnsortedTabStats(); |
| 567 for (auto& tab : tab_stats) { | 556 for (auto& tab : tab_stats) { |
| 568 if (!tab.render_process_host->IsProcessBackgrounded()) | 557 if (!tab.render_process_host->IsProcessBackgrounded()) |
| 569 continue; | 558 continue; |
| 570 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without | 559 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without |
| 571 // timers for simplicity, so PurgeAndSuspend is called even after the | 560 // timers for simplicity, so PurgeAndSuspend is called even after the |
| 572 // renderer is purged and suspended once. This should be replaced with | 561 // renderer is purged and suspended once. This should be replaced with |
| 573 // timers if we want necessary and sufficient signals. | 562 // timers if we want necessary and sufficient signals. |
| 574 if (tab.last_active > purge_and_suspend_time_threshold) | 563 if (tab.last_active > purge_and_suspend_time_threshold) |
| 575 continue; | 564 continue; |
| (...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 851 for (TabStatsList::const_reverse_iterator stats_rit = stats.rbegin(); | 840 for (TabStatsList::const_reverse_iterator stats_rit = stats.rbegin(); |
| 852 stats_rit != stats.rend(); ++stats_rit) { | 841 stats_rit != stats.rend(); ++stats_rit) { |
| 853 int64_t least_important_tab_id = stats_rit->tab_contents_id; | 842 int64_t least_important_tab_id = stats_rit->tab_contents_id; |
| 854 if (CanDiscardTab(least_important_tab_id) && | 843 if (CanDiscardTab(least_important_tab_id) && |
| 855 DiscardTabById(least_important_tab_id)) | 844 DiscardTabById(least_important_tab_id)) |
| 856 return true; | 845 return true; |
| 857 } | 846 } |
| 858 return false; | 847 return false; |
| 859 } | 848 } |
| 860 | 849 |
| 850 // Check the variation parameter to see if a tab be discarded more than once. | |
| 851 // Default is to only discard once per tab. | |
| 852 bool TabManager::AllowMultipleDiscards() { | |
|
Georges Khalil
2016/05/17 13:49:07
Rename this to ShouldOnlyDiscardOnce and flip logi
Anderson Silva
2016/05/17 15:12:02
Acknowledged.
| |
| 853 #if defined(OS_CHROMEOS) | |
| 854 // On Chrome OS, tab manager is always started and tabs can be discarded more | |
| 855 // than once. | |
| 856 return true; | |
| 857 #endif | |
| 858 | |
| 859 std::string allow_multiple_discards = variations::GetVariationParamValue( | |
| 860 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); | |
| 861 return (allow_multiple_discards == "true"); | |
| 862 } | |
| 863 | |
| 861 // Things to collect on the browser thread (because TabStripModel isn't thread | 864 // Things to collect on the browser thread (because TabStripModel isn't thread |
| 862 // safe): | 865 // safe): |
| 863 // 1) whether or not a tab is pinned | 866 // 1) whether or not a tab is pinned |
| 864 // 2) last time a tab was selected | 867 // 2) last time a tab was selected |
| 865 // 3) is the tab currently selected | 868 // 3) is the tab currently selected |
| 866 TabStatsList TabManager::GetUnsortedTabStats() { | 869 TabStatsList TabManager::GetUnsortedTabStats() { |
| 867 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 870 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 868 TabStatsList stats_list; | 871 TabStatsList stats_list; |
| 869 stats_list.reserve(32); // 99% of users have < 30 tabs open. | 872 stats_list.reserve(32); // 99% of users have < 30 tabs open. |
| 870 | 873 |
| 871 // TODO(chrisha): Move this code to a TabStripModel enumeration delegate! | 874 // TODO(chrisha): Move this code to a TabStripModel enumeration delegate! |
| 872 if (!test_tab_strip_models_.empty()) { | 875 if (!test_tab_strip_models_.empty()) { |
| 873 for (size_t i = 0; i < test_tab_strip_models_.size(); ++i) { | 876 for (size_t i = 0; i < test_tab_strip_models_.size(); ++i) { |
| 874 AddTabStats(test_tab_strip_models_[i].first, // tab_strip_model | 877 AddTabStats(test_tab_strip_models_[i].first, // tab_strip_model |
| 875 test_tab_strip_models_[i].second, // is_app | 878 test_tab_strip_models_[i].second, // is_app |
| 876 i == 0, // is_active | 879 i == 0, // is_active |
| 877 &stats_list); | 880 &stats_list); |
| 878 } | 881 } |
| 879 } else { | 882 } else { |
| 880 // The code here can only be tested under a full browser test. | 883 // The code here can only be tested under a full browser test. |
| 881 AddTabStats(&stats_list); | 884 AddTabStats(&stats_list); |
| 882 } | 885 } |
| 883 | 886 |
| 884 return stats_list; | 887 return stats_list; |
| 885 } | 888 } |
| 886 | 889 |
| 887 } // namespace memory | 890 } // namespace memory |
| OLD | NEW |