| 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 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 stats.title = contents->GetTitle(); | 674 stats.title = contents->GetTitle(); |
| 680 stats.tab_contents_id = IdFromWebContents(contents); | 675 stats.tab_contents_id = IdFromWebContents(contents); |
| 681 stats_list->push_back(stats); | 676 stats_list->push_back(stats); |
| 682 } | 677 } |
| 683 } | 678 } |
| 684 } | 679 } |
| 685 | 680 |
| 686 // This function is called when |update_timer_| fires. It will adjust the clock | 681 // 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 | 682 // 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 | 683 // 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 | 684 // cache memory. |
| 690 // while. | |
| 691 void TabManager::UpdateTimerCallback() { | 685 void TabManager::UpdateTimerCallback() { |
| 692 // If Chrome is shutting down, do not do anything. | 686 // If Chrome is shutting down, do not do anything. |
| 693 if (g_browser_process->IsShuttingDown()) | 687 if (g_browser_process->IsShuttingDown()) |
| 694 return; | 688 return; |
| 695 | 689 |
| 696 if (BrowserList::GetInstance()->empty()) | 690 if (BrowserList::GetInstance()->empty()) |
| 697 return; | 691 return; |
| 698 | 692 |
| 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(); | 693 last_adjust_time_ = NowTicks(); |
| 711 | 694 |
| 712 #if defined(OS_CHROMEOS) | 695 #if defined(OS_CHROMEOS) |
| 713 TabStatsList stats_list = GetTabStats(); | 696 TabStatsList stats_list = GetTabStats(); |
| 714 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. | 697 // This starts the CrOS specific OOM adjustments in /proc/<pid>/oom_score_adj. |
| 715 delegate_->AdjustOomPriorities(stats_list); | 698 delegate_->AdjustOomPriorities(stats_list); |
| 716 #endif | 699 #endif |
| 717 | 700 |
| 718 PurgeAndSuspendBackgroundedTabs(); | 701 PurgeBackgroundedTabsIfNeeded(); |
| 719 } | 702 } |
| 720 | 703 |
| 721 TabManager::PurgeAndSuspendState TabManager::GetNextPurgeAndSuspendState( | 704 base::TimeDelta TabManager::GetTimeToPurge( |
| 722 content::WebContents* content, | 705 base::TimeDelta min_time_to_purge) const { |
| 723 base::TimeTicks current_time, | 706 return min_time_to_purge + base::TimeDelta::FromMinutes(base::RandGenerator( |
| 724 const base::TimeDelta& time_to_first_suspension) const { | 707 kRangeBetweenMinAndMaxTimeToPurgeInMinutes)); |
| 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 } | 708 } |
| 747 | 709 |
| 748 void TabManager::PurgeAndSuspendBackgroundedTabs() { | 710 bool TabManager::ShouldPurgeAtTime(content::WebContents* content) const { |
| 749 base::TimeTicks current_time = NowTicks(); | 711 if (GetWebContentsData(content)->is_purged()) |
| 712 return false; |
| 713 |
| 714 base::TimeDelta time_passed = |
| 715 NowTicks() - GetWebContentsData(content)->LastInactiveTime(); |
| 716 return time_passed > GetWebContentsData(content)->time_to_purge(); |
| 717 } |
| 718 |
| 719 void TabManager::PurgeBackgroundedTabsIfNeeded() { |
| 750 auto tab_stats = GetUnsortedTabStats(); | 720 auto tab_stats = GetUnsortedTabStats(); |
| 751 for (auto& tab : tab_stats) { | 721 for (auto& tab : tab_stats) { |
| 752 if (!tab.render_process_host->IsProcessBackgrounded()) | 722 if (!tab.render_process_host->IsProcessBackgrounded()) |
| 753 continue; | 723 continue; |
| 754 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id)) | 724 if (!CanSuspendBackgroundedRenderer(tab.child_process_host_id)) |
| 755 continue; | 725 continue; |
| 756 | 726 |
| 757 WebContents* content = GetWebContentsById(tab.tab_contents_id); | 727 WebContents* content = GetWebContentsById(tab.tab_contents_id); |
| 758 if (!content) | 728 if (!content) |
| 759 continue; | 729 continue; |
| 760 | 730 |
| 761 PurgeAndSuspendState current_state = | 731 bool purge_now = ShouldPurgeAtTime(content); |
| 762 GetWebContentsData(content)->GetPurgeAndSuspendState(); | 732 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; | 733 continue; |
| 773 | 734 |
| 774 // TODO(hajimehoshi): Now calling PurgeAndSuspend is implemented without | 735 GetWebContentsData(content)->set_is_purged(true); |
| 775 // timers for simplicity, so PurgeAndSuspend is called even after the | 736 // TODO(tasak): rename PurgeAndSuspend with a better name, e.g. |
| 776 // renderer is purged and suspended once. This should be replaced with | 737 // RequestPurgeCache, because we don't suspend any renderers. |
| 777 // timers if we want necessary and sufficient signals. | 738 tab.render_process_host->PurgeAndSuspend(); |
| 778 GetWebContentsData(content)->SetPurgeAndSuspendState(next_state); | |
| 779 switch (next_state) { | |
| 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 } | 739 } |
| 790 } | 740 } |
| 791 | 741 |
| 792 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) { | 742 WebContents* TabManager::DiscardWebContentsAt(int index, TabStripModel* model) { |
| 793 // Can't discard active index. | 743 // Can't discard active index. |
| 794 if (model->active_index() == index) | 744 if (model->active_index() == index) |
| 795 return nullptr; | 745 return nullptr; |
| 796 | 746 |
| 797 WebContents* old_contents = model->GetWebContentsAt(index); | 747 WebContents* old_contents = model->GetWebContentsAt(index); |
| 798 | 748 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 818 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime()); | 768 null_contents->SetLastActiveTime(old_contents->GetLastActiveTime()); |
| 819 // Copy over the discard count. | 769 // Copy over the discard count. |
| 820 WebContentsData::CopyState(old_contents, null_contents); | 770 WebContentsData::CopyState(old_contents, null_contents); |
| 821 | 771 |
| 822 // Replace the discarded tab with the null version. | 772 // Replace the discarded tab with the null version. |
| 823 model->ReplaceWebContentsAt(index, null_contents); | 773 model->ReplaceWebContentsAt(index, null_contents); |
| 824 // Mark the tab so it will reload when clicked on. | 774 // Mark the tab so it will reload when clicked on. |
| 825 GetWebContentsData(null_contents)->SetDiscardState(true); | 775 GetWebContentsData(null_contents)->SetDiscardState(true); |
| 826 GetWebContentsData(null_contents)->IncrementDiscardCount(); | 776 GetWebContentsData(null_contents)->IncrementDiscardCount(); |
| 827 | 777 |
| 778 // Make the tab PURGED to avoid purging null_contents. |
| 779 GetWebContentsData(null_contents)->set_is_purged(true); |
| 780 |
| 828 // Discard the old tab's renderer. | 781 // Discard the old tab's renderer. |
| 829 // TODO(jamescook): This breaks script connections with other tabs. | 782 // TODO(jamescook): This breaks script connections with other tabs. |
| 830 // Find a different approach that doesn't do that, perhaps based on navigation | 783 // Find a different approach that doesn't do that, perhaps based on navigation |
| 831 // to swappedout://. | 784 // to swappedout://. |
| 832 delete old_contents; | 785 delete old_contents; |
| 833 recent_tab_discard_ = true; | 786 recent_tab_discard_ = true; |
| 834 | 787 |
| 835 return null_contents; | 788 return null_contents; |
| 836 } | 789 } |
| 837 | 790 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 879 data->SetRecentlyAudible(current_state); | 832 data->SetRecentlyAudible(current_state); |
| 880 data->SetLastAudioChangeTime(NowTicks()); | 833 data->SetLastAudioChangeTime(NowTicks()); |
| 881 } | 834 } |
| 882 } | 835 } |
| 883 | 836 |
| 884 void TabManager::ActiveTabChanged(content::WebContents* old_contents, | 837 void TabManager::ActiveTabChanged(content::WebContents* old_contents, |
| 885 content::WebContents* new_contents, | 838 content::WebContents* new_contents, |
| 886 int index, | 839 int index, |
| 887 int reason) { | 840 int reason) { |
| 888 GetWebContentsData(new_contents)->SetDiscardState(false); | 841 GetWebContentsData(new_contents)->SetDiscardState(false); |
| 889 GetWebContentsData(new_contents)->SetPurgeAndSuspendState(RUNNING); | 842 GetWebContentsData(new_contents)->set_is_purged(false); |
| 890 // If |old_contents| is set, that tab has switched from being active to | 843 // If |old_contents| is set, that tab has switched from being active to |
| 891 // inactive, so record the time of that transition. | 844 // inactive, so record the time of that transition. |
| 892 if (old_contents) | 845 if (old_contents) { |
| 893 GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); | 846 GetWebContentsData(old_contents)->SetLastInactiveTime(NowTicks()); |
| 847 // Re-setting time-to-purge every time a tab becomes inactive. |
| 848 GetWebContentsData(old_contents) |
| 849 ->set_time_to_purge(GetTimeToPurge(min_time_to_purge_)); |
| 850 } |
| 894 } | 851 } |
| 895 | 852 |
| 896 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, | 853 void TabManager::TabInsertedAt(TabStripModel* tab_strip_model, |
| 897 content::WebContents* contents, | 854 content::WebContents* contents, |
| 898 int index, | 855 int index, |
| 899 bool foreground) { | 856 bool foreground) { |
| 900 // Only interested in background tabs, as foreground tabs get taken care of by | 857 // Only interested in background tabs, as foreground tabs get taken care of by |
| 901 // ActiveTabChanged. | 858 // ActiveTabChanged. |
| 902 if (foreground) | 859 if (foreground) |
| 903 return; | 860 return; |
| 904 | 861 |
| 905 // A new background tab is similar to having a tab switch from being active to | 862 // A new background tab is similar to having a tab switch from being active to |
| 906 // inactive. | 863 // inactive. |
| 907 GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); | 864 GetWebContentsData(contents)->SetLastInactiveTime(NowTicks()); |
| 865 // Re-setting time-to-purge every time a tab becomes inactive. |
| 866 GetWebContentsData(contents)->set_time_to_purge( |
| 867 GetTimeToPurge(min_time_to_purge_)); |
| 908 } | 868 } |
| 909 | 869 |
| 910 bool TabManager::IsMediaTab(WebContents* contents) const { | 870 bool TabManager::IsMediaTab(WebContents* contents) const { |
| 911 if (contents->WasRecentlyAudible()) | 871 if (contents->WasRecentlyAudible()) |
| 912 return true; | 872 return true; |
| 913 | 873 |
| 914 scoped_refptr<MediaStreamCaptureIndicator> media_indicator = | 874 scoped_refptr<MediaStreamCaptureIndicator> media_indicator = |
| 915 MediaCaptureDevicesDispatcher::GetInstance() | 875 MediaCaptureDevicesDispatcher::GetInstance() |
| 916 ->GetMediaStreamCaptureIndicator(); | 876 ->GetMediaStreamCaptureIndicator(); |
| 917 if (media_indicator->IsCapturingUserMedia(contents) || | 877 if (media_indicator->IsCapturingUserMedia(contents) || |
| (...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 // platform. | 991 // platform. |
| 1032 std::string allow_multiple_discards = variations::GetVariationParamValue( | 992 std::string allow_multiple_discards = variations::GetVariationParamValue( |
| 1033 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); | 993 features::kAutomaticTabDiscarding.name, "AllowMultipleDiscards"); |
| 1034 return (allow_multiple_discards != "true"); | 994 return (allow_multiple_discards != "true"); |
| 1035 #else | 995 #else |
| 1036 return false; | 996 return false; |
| 1037 #endif | 997 #endif |
| 1038 } | 998 } |
| 1039 | 999 |
| 1040 } // namespace memory | 1000 } // namespace memory |
| OLD | NEW |