| 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> |
| 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 Loading... |
| 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 // The range between minimum and maximum time-to-purge. |
| 84 // machine was suspended and correct the timing statistics. | 85 // The minimum time-to-purge is min_time_to_purge_ and its default value is |
| 85 const int kSuspendThresholdSeconds = kAdjustmentIntervalSeconds * 4; | 86 // kDefaultMinTimeToPurge. |
| 86 | 87 // An inactive background tab's cache will be purged the time-to-purge |
| 87 // A suspended renderer is suspended for this duration. | 88 // after the tab is backgrounded. |
| 88 constexpr base::TimeDelta kDurationOfRendererSuspension = | 89 const unsigned int kRangeBetweenMinAndMaxTimeToPurgeInMinutes = 30; |
| 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 | 90 |
| 95 // The time during which a tab is protected from discarding after it stops being | 91 // The time during which a tab is protected from discarding after it stops being |
| 96 // audible. | 92 // audible. |
| 97 const int kAudioProtectionTimeSeconds = 60; | 93 const int kAudioProtectionTimeSeconds = 60; |
| 98 | 94 |
| 99 int FindTabStripModelById(int64_t target_web_contents_id, | 95 int FindTabStripModelById(int64_t target_web_contents_id, |
| 100 TabStripModel** model) { | 96 TabStripModel** model) { |
| 101 DCHECK(model); | 97 DCHECK(model); |
| 102 for (auto* browser : *BrowserList::GetInstance()) { | 98 for (auto* browser : *BrowserList::GetInstance()) { |
| 103 TabStripModel* local_model = browser->tab_strip_model(); | 99 TabStripModel* local_model = browser->tab_strip_model(); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 132 base::MemoryPressureListener::MemoryPressureLevel level) { | 128 base::MemoryPressureListener::MemoryPressureLevel level) { |
| 133 content::MemoryPressureController::SendPressureNotification( | 129 content::MemoryPressureController::SendPressureNotification( |
| 134 render_process_host, level); | 130 render_process_host, level); |
| 135 } | 131 } |
| 136 | 132 |
| 137 } // namespace | 133 } // namespace |
| 138 | 134 |
| 139 //////////////////////////////////////////////////////////////////////////////// | 135 //////////////////////////////////////////////////////////////////////////////// |
| 140 // TabManager | 136 // TabManager |
| 141 | 137 |
| 142 constexpr base::TimeDelta TabManager::kDefaultTimeToFirstPurge; | 138 constexpr base::TimeDelta TabManager::kDefaultMinTimeToPurge; |
| 143 | 139 |
| 144 TabManager::TabManager() | 140 TabManager::TabManager() |
| 145 : discard_count_(0), | 141 : discard_count_(0), |
| 146 recent_tab_discard_(false), | 142 recent_tab_discard_(false), |
| 147 discard_once_(false), | 143 discard_once_(false), |
| 148 #if !defined(OS_CHROMEOS) | 144 #if !defined(OS_CHROMEOS) |
| 149 minimum_protection_time_(base::TimeDelta::FromMinutes(10)), | 145 minimum_protection_time_(base::TimeDelta::FromMinutes(10)), |
| 150 #endif | 146 #endif |
| 151 browser_tab_strip_tracker_(this, nullptr, nullptr), | 147 browser_tab_strip_tracker_(this, nullptr, nullptr), |
| 152 test_tick_clock_(nullptr), | 148 test_tick_clock_(nullptr), |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 221 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { | 217 if (level == base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL) { |
| 222 OnMemoryPressure(level); | 218 OnMemoryPressure(level); |
| 223 } | 219 } |
| 224 } | 220 } |
| 225 #endif | 221 #endif |
| 226 // purge-and-suspend param is used for Purge+Suspend finch experiment | 222 // purge-and-suspend param is used for Purge+Suspend finch experiment |
| 227 // in the following way: | 223 // in the following way: |
| 228 // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7
PPbk/edit?usp=sharing | 224 // https://docs.google.com/document/d/1hPHkKtXXBTlsZx9s-9U17XC-ofEIzPo9FYbBEc7
PPbk/edit?usp=sharing |
| 229 std::string purge_and_suspend_time = variations::GetVariationParamValue( | 225 std::string purge_and_suspend_time = variations::GetVariationParamValue( |
| 230 "PurgeAndSuspend", "purge-and-suspend-time"); | 226 "PurgeAndSuspend", "purge-and-suspend-time"); |
| 231 unsigned int time_to_first_purge_sec = 0; | 227 unsigned int min_time_to_purge_sec = 0; |
| 232 if (purge_and_suspend_time.empty() || | 228 if (purge_and_suspend_time.empty() || |
| 233 !base::StringToUint(purge_and_suspend_time, &time_to_first_purge_sec)) | 229 !base::StringToUint(purge_and_suspend_time, &min_time_to_purge_sec)) |
| 234 time_to_first_suspension_ = kDefaultTimeToFirstPurge; | 230 min_time_to_purge_ = kDefaultMinTimeToPurge; |
| 235 else | 231 else |
| 236 time_to_first_suspension_ = | 232 min_time_to_purge_ = base::TimeDelta::FromSeconds(min_time_to_purge_sec); |
| 237 base::TimeDelta::FromSeconds(time_to_first_purge_sec); | |
| 238 } | 233 } |
| 239 | 234 |
| 240 void TabManager::Stop() { | 235 void TabManager::Stop() { |
| 241 update_timer_.Stop(); | 236 update_timer_.Stop(); |
| 242 recent_tab_discard_timer_.Stop(); | 237 recent_tab_discard_timer_.Stop(); |
| 243 memory_pressure_listener_.reset(); | 238 memory_pressure_listener_.reset(); |
| 244 } | 239 } |
| 245 | 240 |
| 246 TabStatsList TabManager::GetTabStats() const { | 241 TabStatsList TabManager::GetTabStats() const { |
| 247 TabStatsList stats_list(GetUnsortedTabStats()); | 242 TabStatsList stats_list(GetUnsortedTabStats()); |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 content::WebContents* TabManager::GetWebContentsById( | 441 content::WebContents* TabManager::GetWebContentsById( |
| 447 int64_t tab_contents_id) const { | 442 int64_t tab_contents_id) const { |
| 448 TabStripModel* model = nullptr; | 443 TabStripModel* model = nullptr; |
| 449 int index = FindTabStripModelById(tab_contents_id, &model); | 444 int index = FindTabStripModelById(tab_contents_id, &model); |
| 450 if (index == -1) | 445 if (index == -1) |
| 451 return nullptr; | 446 return nullptr; |
| 452 return model->GetWebContentsAt(index); | 447 return model->GetWebContentsAt(index); |
| 453 } | 448 } |
| 454 | 449 |
| 455 bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) const { | 450 bool TabManager::CanSuspendBackgroundedRenderer(int render_process_id) const { |
| 456 // A renderer can be suspended if it's not playing media. | 451 // A renderer can be purged if it's not playing media. |
| 457 auto tab_stats = GetUnsortedTabStats(); | 452 auto tab_stats = GetUnsortedTabStats(); |
| 458 for (auto& tab : tab_stats) { | 453 for (auto& tab : tab_stats) { |
| 459 if (tab.child_process_host_id != render_process_id) | 454 if (tab.child_process_host_id != render_process_id) |
| 460 continue; | 455 continue; |
| 461 WebContents* web_contents = GetWebContentsById(tab.tab_contents_id); | 456 WebContents* web_contents = GetWebContentsById(tab.tab_contents_id); |
| 462 if (!web_contents) | 457 if (!web_contents) |
| 463 return false; | 458 return false; |
| 464 if (IsMediaTab(web_contents)) | 459 if (IsMediaTab(web_contents)) |
| 465 return false; | 460 return false; |
| 466 } | 461 } |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 stats.title = contents->GetTitle(); | 675 stats.title = contents->GetTitle(); |
| 681 stats.tab_contents_id = IdFromWebContents(contents); | 676 stats.tab_contents_id = IdFromWebContents(contents); |
| 682 stats_list->push_back(stats); | 677 stats_list->push_back(stats); |
| 683 } | 678 } |
| 684 } | 679 } |
| 685 } | 680 } |
| 686 | 681 |
| 687 // This function is called when |update_timer_| fires. It will adjust the clock | 682 // This function is called when |update_timer_| fires. It will adjust the clock |
| 688 // if needed (if it detects that the machine was asleep) and will fire the stats | 683 // if needed (if it detects that the machine was asleep) and will fire the stats |
| 689 // updating on ChromeOS via the delegate. This function also tries to purge | 684 // updating on ChromeOS via the delegate. This function also tries to purge |
| 690 // cache memory and suspend tabs which becomes and keeps backgrounded for a | 685 // cache memory. |
| 691 // while. | |
| 692 void TabManager::UpdateTimerCallback() { | 686 void TabManager::UpdateTimerCallback() { |
| 693 // If Chrome is shutting down, do not do anything. | 687 // If Chrome is shutting down, do not do anything. |
| 694 if (g_browser_process->IsShuttingDown()) | 688 if (g_browser_process->IsShuttingDown()) |
| 695 return; | 689 return; |
| 696 | 690 |
| 697 if (BrowserList::GetInstance()->empty()) | 691 if (BrowserList::GetInstance()->empty()) |
| 698 return; | 692 return; |
| 699 | 693 |
| 700 // Check for a discontinuity in time caused by the machine being suspended. | |
| 701 if (!last_adjust_time_.is_null()) { | |
| 702 TimeDelta suspend_time = NowTicks() - last_adjust_time_; | |
| 703 if (suspend_time.InSeconds() > kSuspendThresholdSeconds) { | |
| 704 // System was probably suspended, move the event timers forward in time so | |
| 705 // when they get subtracted out later, "uptime" is being counted. | |
| 706 start_time_ += suspend_time; | |
| 707 if (!last_discard_time_.is_null()) | |
| 708 last_discard_time_ += suspend_time; | |
| 709 } | |
| 710 } | |
| 711 last_adjust_time_ = NowTicks(); | 694 last_adjust_time_ = NowTicks(); |
| 712 | 695 |
| 713 #if defined(OS_CHROMEOS) | 696 #if defined(OS_CHROMEOS) |
| 714 TabStatsList stats_list = GetTabStats(); | 697 TabStatsList stats_list = GetTabStats(); |
| 715 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. | 698 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. |
| 716 delegate_->AdjustOomPriorities(stats_list); | 699 delegate_->AdjustOomPriorities(stats_list); |
| 717 #endif | 700 #endif |
| 718 | 701 |
| 719 PurgeAndSuspendBackgroundedTabs(); | 702 PurgeBackgroundedTabsIfNeeded(); |
| 720 } | 703 } |
| 721 | 704 |
| 722 TabManager::PurgeAndSuspendState TabManager::GetNextPurgeAndSuspendState( | 705 base::TimeDelta TabManager::GetTimeToPurge( |
| 723 content::WebContents* content, | 706 base::TimeDelta min_time_to_purge) const { |
| 724 base::TimeTicks current_time, | 707 return min_time_to_purge + base::TimeDelta::FromMinutes(base::RandGenerator( |
| 725 const base::TimeDelta& time_to_first_suspension) const { | 708 kRangeBetweenMinAndMaxTimeToPurgeInMinutes)); |
| 726 DCHECK(content); | |
| 727 PurgeAndSuspendState state = | |
| 728 GetWebContentsData(content)->GetPurgeAndSuspendState(); | |
| 729 | |
| 730 auto time_passed = current_time - | |
| 731 GetWebContentsData(content)->LastPurgeAndSuspendModifiedTime(); | |
| 732 switch (state) { | |
| 733 case RUNNING: | |
| 734 if (time_passed > time_to_first_suspension) | |
| 735 return SUSPENDED; | |
| 736 break; | |
| 737 case RESUMED: | |
| 738 if (time_passed > kDurationOfRendererResumption) | |
| 739 return SUSPENDED; | |
| 740 break; | |
| 741 case SUSPENDED: | |
| 742 if (time_passed > kDurationOfRendererSuspension) | |
| 743 return RESUMED; | |
| 744 break; | |
| 745 } | |
| 746 return state; | |
| 747 } | 709 } |
| 748 | 710 |
| 749 void TabManager::PurgeAndSuspendBackgroundedTabs() { | 711 bool TabManager::ShouldPurgeAtTime(content::WebContents* content, |
| 712 base::TimeTicks current_time) const { |
| 713 if (GetWebContentsData(content)->IsPurged()) |
| 714 return false; |
| 715 |
| 716 base::TimeDelta time_passed = |
| 717 current_time - GetWebContentsData(content)->LastInactiveTime(); |
| 718 return time_passed > GetWebContentsData(content)->TimeToPurge(); |
| 719 } |
| 720 |
| 721 void TabManager::PurgeBackgroundedTabsIfNeeded() { |
| 750 base::TimeTicks current_time = NowTicks(); | 722 base::TimeTicks current_time = NowTicks(); |
| 751 auto tab_stats = GetUnsortedTabStats(); | 723 auto tab_stats = GetUnsortedTabStats(); |
| 752 for (auto& tab : tab_stats) { | 724 for (auto& tab : tab_stats) { |
| 753 if (!tab.render_process_host->IsProcessBackgrounded()) | 725 if (!tab.render_process_host->IsProcessBackgrounded()) |
| 754 continue; | 726 continue; |
| 755 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id)) | 727 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id)) |
| 756 continue; | 728 continue; |
| 757 | 729 |
| 758 WebContents* content = GetWebContentsById(tab.tab_contents_id); | 730 WebContents* content = GetWebContentsById(tab.tab_contents_id); |
| 759 if (!content) | 731 if (!content) |
| 760 continue; | 732 continue; |
| 761 | 733 |
| 762 PurgeAndSuspendState current_state = | 734 bool purge_now = ShouldPurgeAtTime(content, current_time); |
| 763 GetWebContentsData(content)->GetPurgeAndSuspendState(); | 735 if (!purge_now) |
| 764 // If the tab's purge-and-suspend state is not RUNNING, the tab should be | |
| 765 // backgrounded. Since tab.last_hidden is updated everytime the tab is | |
| 766 // hidden, we should see tab.last_hidden < last_modified_time. | |
| 767 DCHECK(current_state == RUNNING || | |
| 768 tab.last_hidden < | |
| 769 GetWebContentsData(content)->LastPurgeAndSuspendModifiedTime()); | |
| 770 PurgeAndSuspendState next_state = GetNextPurgeAndSuspendState( | |
| 771 content, current_time, time_to_first_suspension_); | |
| 772 if (current_state == next_state) | |
| 773 continue; | 736 continue; |
| 774 | 737 |
| 775 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without | 738 GetWebContentsData(content)->SetPurgeState(true); |
| 776 // timers for simplicity, so PurgeAndSuspend is called even after the | 739 // TODO(tasak): rename PurgeAndSuspend with a better name, e.g. |
| 777 // renderer is purged and suspended once. This should be replaced with | 740 // RequestPurgeCache, because we don't suspend any renderers. |
| 778 // timers if we want necessary and sufficient signals. | 741 tab.render_process_host->PurgeAndSuspend(); |
| 779 GetWebContentsData(content)->SetPurgeAndSuspendState(next_state); | |
| 780 switch (next_state) { | |
| 781 case SUSPENDED: | |
| 782 tab.render_process_host->PurgeAndSuspend(); | |
| 783 break; | |
| 784 case RESUMED: | |
| 785 tab.render_process_host->Resume(); | |
| 786 break; | |
| 787 case RUNNING: | |
| 788 NOTREACHED(); | |
| 789 } | |
| 790 } | 742 } |
| 791 } | 743 } |
| 792 | 744 |
| 793 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) { | 745 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) { |
| 794 // Can't discard active index. | 746 // Can't discard active index. |
| 795 if (model->active_index() == index) | 747 if (model->active_index() == index) |
| 796 return nullptr; | 748 return nullptr; |
| 797 | 749 |
| 798 WebContents* old_contents = model->GetWebContentsAt(index); | 750 WebContents* old_contents = model->GetWebContentsAt(index); |
| 799 | 751 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 819 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime()); | 771 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime()); |
| 820 // Copy over the discard count. | 772 // Copy over the discard count. |
| 821 WebContentsData::CopyState(old_contents, null_contents); | 773 WebContentsData::CopyState(old_contents, null_contents); |
| 822 | 774 |
| 823 // Replace the discarded tab with the null version. | 775 // Replace the discarded tab with the null version. |
| 824 model->ReplaceWebContentsAt(index, null_contents); | 776 model->ReplaceWebContentsAt(index, null_contents); |
| 825 // Mark the tab so it will reload when clicked on. | 777 // Mark the tab so it will reload when clicked on. |
| 826 GetWebContentsData(null_contents)->SetDiscardState(true); | 778 GetWebContentsData(null_contents)->SetDiscardState(true); |
| 827 GetWebContentsData(null_contents)->IncrementDiscardCount(); | 779 GetWebContentsData(null_contents)->IncrementDiscardCount(); |
| 828 | 780 |
| 781 // Make the tab PURGED to avoid purging null_contents. |
| 782 GetWebContentsData(null_contents)->SetPurgeState(true); |
| 783 |
| 829 // Discard the old tab's renderer. | 784 // Discard the old tab's renderer. |
| 830 // TODO(jamescook): This breaks script connections with other tabs. | 785 // TODO(jamescook): This breaks script connections with other tabs. |
| 831 // Find a different approach that doesn't do that, perhaps based on navigation | 786 // Find a different approach that doesn't do that, perhaps based on navigation |
| 832 // to swappedout://. | 787 // to swappedout://. |
| 833 delete old_contents; | 788 delete old_contents; |
| 834 recent_tab_discard_ = true; | 789 recent_tab_discard_ = true; |
| 835 | 790 |
| 836 return null_contents; | 791 return null_contents; |
| 837 } | 792 } |
| 838 | 793 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 data->SetRecentlyAudible(current_state); | 835 data->SetRecentlyAudible(current_state); |
| 881 data->SetLastAudioChangeTime(NowTicks()); | 836 data->SetLastAudioChangeTime(NowTicks()); |
| 882 } | 837 } |
| 883 } | 838 } |
| 884 | 839 |
| 885 void TabManager::ActiveTabChanged(content::WebContents* old_contents, | 840 void TabManager::ActiveTabChanged(content::WebContents* old_contents, |
| 886 content::WebContents* new_contents, | 841 content::WebContents* new_contents, |
| 887 int index, | 842 int index, |
| 888 int reason) { | 843 int reason) { |
| 889 GetWebContentsData(new_contents)->SetDiscardState(false); | 844 GetWebContentsData(new_contents)->SetDiscardState(false); |
| 890 GetWebContentsData(new_contents)->SetPurgeAndSuspendState(RUNNING); | 845 GetWebContentsData(new_contents)->SetPurgeState(false); |
| 891 // If |old_contents| is set, that tab has switched from being active to | 846 // If |old_contents| is set, that tab has switched from being active to |
| 892 // inactive, so record the time of that transition. | 847 // inactive, so record the time of that transition. |
| 893 if (old_contents) | 848 if (old_contents) { |
| 894 GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); | 849 GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); |
| 850 // Re-setting time-to-purge every time a tab becomes inactive. |
| 851 GetWebContentsData(old_contents) |
| 852 ->SetTimeToPurge(GetTimeToPurge(min_time_to_purge_)); |
| 853 } |
| 895 } | 854 } |
| 896 | 855 |
| 897 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, | 856 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, |
| 898 content::WebContents* contents, | 857 content::WebContents* contents, |
| 899 int index, | 858 int index, |
| 900 bool foreground) { | 859 bool foreground) { |
| 901 // Only interested in background tabs, as foreground tabs get taken care of by | 860 // Only interested in background tabs, as foreground tabs get taken care of by |
| 902 // ActiveTabChanged. | 861 // ActiveTabChanged. |
| 903 if (foreground) | 862 if (foreground) |
| 904 return; | 863 return; |
| 905 | 864 |
| 906 // A new background tab is similar to having a tab switch from being active to | 865 // A new background tab is similar to having a tab switch from being active to |
| 907 // inactive. | 866 // inactive. |
| 908 GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); | 867 GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); |
| 868 // Re-setting time-to-purge every time a tab becomes inactive. |
| 869 GetWebContentsData(contents)->SetTimeToPurge( |
| 870 GetTimeToPurge(min_time_to_purge_)); |
| 909 } | 871 } |
| 910 | 872 |
| 911 bool TabManager::IsMediaTab(WebContents* contents) const { | 873 bool TabManager::IsMediaTab(WebContents* contents) const { |
| 912 if (contents->WasRecentlyAudible()) | 874 if (contents->WasRecentlyAudible()) |
| 913 return true; | 875 return true; |
| 914 | 876 |
| 915 scoped_refptr<MediaStreamCaptureIndicator> media_indicator = | 877 scoped_refptr<MediaStreamCaptureIndicator> media_indicator = |
| 916 MediaCaptureDevicesDispatcher::GetInstance() | 878 MediaCaptureDevicesDispatcher::GetInstance() |
| 917 ->GetMediaStreamCaptureIndicator(); | 879 ->GetMediaStreamCaptureIndicator(); |
| 918 if (media_indicator->IsCapturingUserMedia(contents) || | 880 if (media_indicator->IsCapturingUserMedia(contents) || |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 // platform. | 994 // platform. |
| 1033 std::string allow_multiple_discards = variations::GetVariationParamValue( | 995 std::string allow_multiple_discards = variations::GetVariationParamValue( |
| 1034 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); | 996 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); |
| 1035 return (allow_multiple_discards != "true"); | 997 return (allow_multiple_discards != "true"); |
| 1036 #else | 998 #else |
| 1037 return false; | 999 return false; |
| 1038 #endif | 1000 #endif |
| 1039 } | 1001 } |
| 1040 | 1002 |
| 1041 } // namespace memory | 1003 } // namespace memory |
| OLD | NEW |