| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "chrome/browser/memory/tab_manager_web_contents_data.h" | |
| 6 | |
| 7 #include "base/metrics/histogram_macros.h" | |
| 8 #include "base/time/tick_clock.h" | |
| 9 #include "chrome/browser/browser_process.h" | |
| 10 #include "chrome/browser/engagement/site_engagement_service.h" | |
| 11 #include "chrome/browser/profiles/profile.h" | |
| 12 #include "content/public/browser/browser_thread.h" | |
| 13 #include "content/public/browser/web_contents.h" | |
| 14 | |
| 15 using base::TimeTicks; | |
| 16 using content::WebContents; | |
| 17 | |
| 18 DEFINE_WEB_CONTENTS_USER_DATA_KEY(memory::TabManager::WebContentsData); | |
| 19 | |
| 20 namespace memory { | |
| 21 | |
| 22 TabManager::WebContentsData::WebContentsData(content::WebContents* web_contents) | |
| 23 : WebContentsObserver(web_contents), | |
| 24 test_tick_clock_(nullptr), | |
| 25 time_to_purge_(base::TimeDelta::FromMinutes(30)), | |
| 26 is_purged_(false) {} | |
| 27 | |
| 28 TabManager::WebContentsData::~WebContentsData() {} | |
| 29 | |
| 30 void TabManager::WebContentsData::DidStartLoading() { | |
| 31 // Marks the tab as no longer discarded if it has been reloaded from another | |
| 32 // source (ie: context menu). | |
| 33 SetDiscardState(false); | |
| 34 } | |
| 35 | |
| 36 void TabManager::WebContentsData::WebContentsDestroyed() { | |
| 37 // If Chrome is shutting down, ignore this event. | |
| 38 if (g_browser_process->IsShuttingDown()) | |
| 39 return; | |
| 40 | |
| 41 // If the tab has been previously discarded but is not currently discarded | |
| 42 // (ie. it has been reloaded), we want to record the time it took between the | |
| 43 // reload event and the closing of the tab. | |
| 44 if (tab_data_.discard_count > 0 && !tab_data_.is_discarded) { | |
| 45 auto delta = NowTicks() - tab_data_.last_reload_time; | |
| 46 // Capped to one day for now, will adjust if necessary. | |
| 47 UMA_HISTOGRAM_CUSTOM_TIMES("TabManager.Discarding.ReloadToCloseTime", delta, | |
| 48 base::TimeDelta::FromSeconds(1), | |
| 49 base::TimeDelta::FromDays(1), 100); | |
| 50 } | |
| 51 } | |
| 52 | |
| 53 bool TabManager::WebContentsData::IsDiscarded() { | |
| 54 return tab_data_.is_discarded; | |
| 55 } | |
| 56 | |
| 57 void TabManager::WebContentsData::SetDiscardState(bool state) { | |
| 58 if (tab_data_.is_discarded == state) | |
| 59 return; | |
| 60 | |
| 61 if (!state) { | |
| 62 static int reload_count = 0; | |
| 63 tab_data_.last_reload_time = NowTicks(); | |
| 64 UMA_HISTOGRAM_CUSTOM_COUNTS("TabManager.Discarding.ReloadCount", | |
| 65 ++reload_count, 1, 1000, 50); | |
| 66 auto delta = tab_data_.last_reload_time - tab_data_.last_discard_time; | |
| 67 // Capped to one day for now, will adjust if necessary. | |
| 68 UMA_HISTOGRAM_CUSTOM_TIMES("TabManager.Discarding.DiscardToReloadTime", | |
| 69 delta, base::TimeDelta::FromSeconds(1), | |
| 70 base::TimeDelta::FromDays(1), 100); | |
| 71 | |
| 72 // Record the site engagement score if available. | |
| 73 if (tab_data_.engagement_score >= 0.0) { | |
| 74 UMA_HISTOGRAM_COUNTS_100("TabManager.Discarding.ReloadedEngagementScore", | |
| 75 tab_data_.engagement_score); | |
| 76 } | |
| 77 if (tab_data_.last_inactive_time != base::TimeTicks::UnixEpoch()) { | |
| 78 delta = tab_data_.last_reload_time - tab_data_.last_inactive_time; | |
| 79 UMA_HISTOGRAM_CUSTOM_TIMES("TabManager.Discarding.InactiveToReloadTime", | |
| 80 delta, base::TimeDelta::FromSeconds(1), | |
| 81 base::TimeDelta::FromDays(1), 100); | |
| 82 } | |
| 83 | |
| 84 } else { | |
| 85 static int discard_count = 0; | |
| 86 UMA_HISTOGRAM_CUSTOM_COUNTS("TabManager.Discarding.DiscardCount", | |
| 87 ++discard_count, 1, 1000, 50); | |
| 88 tab_data_.last_discard_time = NowTicks(); | |
| 89 // Record the site engagement score if available. | |
| 90 if (SiteEngagementService::IsEnabled()) { | |
| 91 SiteEngagementService* service = SiteEngagementService::Get( | |
| 92 Profile::FromBrowserContext(web_contents()->GetBrowserContext())); | |
| 93 if (service) { | |
| 94 tab_data_.engagement_score = | |
| 95 service->GetScore(web_contents()->GetLastCommittedURL()); | |
| 96 UMA_HISTOGRAM_COUNTS_100( | |
| 97 "TabManager.Discarding.DiscardedEngagementScore", | |
| 98 tab_data_.engagement_score); | |
| 99 } | |
| 100 } | |
| 101 } | |
| 102 | |
| 103 tab_data_.is_discarded = state; | |
| 104 g_browser_process->GetTabManager()->OnDiscardedStateChange(web_contents(), | |
| 105 state); | |
| 106 } | |
| 107 | |
| 108 int TabManager::WebContentsData::DiscardCount() { | |
| 109 return tab_data_.discard_count; | |
| 110 } | |
| 111 | |
| 112 void TabManager::WebContentsData::IncrementDiscardCount() { | |
| 113 tab_data_.discard_count++; | |
| 114 } | |
| 115 | |
| 116 bool TabManager::WebContentsData::IsRecentlyAudible() { | |
| 117 return tab_data_.is_recently_audible; | |
| 118 } | |
| 119 | |
| 120 void TabManager::WebContentsData::SetRecentlyAudible(bool state) { | |
| 121 tab_data_.is_recently_audible = state; | |
| 122 } | |
| 123 | |
| 124 TimeTicks TabManager::WebContentsData::LastAudioChangeTime() { | |
| 125 return tab_data_.last_audio_change_time; | |
| 126 } | |
| 127 | |
| 128 void TabManager::WebContentsData::SetLastAudioChangeTime(TimeTicks timestamp) { | |
| 129 tab_data_.last_audio_change_time = timestamp; | |
| 130 } | |
| 131 | |
| 132 TimeTicks TabManager::WebContentsData::LastInactiveTime() { | |
| 133 return tab_data_.last_inactive_time; | |
| 134 } | |
| 135 | |
| 136 void TabManager::WebContentsData::SetLastInactiveTime(TimeTicks timestamp) { | |
| 137 tab_data_.last_inactive_time = timestamp; | |
| 138 } | |
| 139 | |
| 140 // static | |
| 141 void TabManager::WebContentsData::CopyState( | |
| 142 content::WebContents* old_contents, | |
| 143 content::WebContents* new_contents) { | |
| 144 // Only copy if an existing state is found. | |
| 145 if (FromWebContents(old_contents)) { | |
| 146 CreateForWebContents(new_contents); | |
| 147 FromWebContents(new_contents)->tab_data_ = | |
| 148 FromWebContents(old_contents)->tab_data_; | |
| 149 FromWebContents(new_contents)->test_tick_clock_ = | |
| 150 FromWebContents(old_contents)->test_tick_clock_; | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 void TabManager::WebContentsData::set_test_tick_clock( | |
| 155 base::TickClock* test_tick_clock) { | |
| 156 test_tick_clock_ = test_tick_clock; | |
| 157 } | |
| 158 | |
| 159 TimeTicks TabManager::WebContentsData::NowTicks() const { | |
| 160 if (!test_tick_clock_) | |
| 161 return TimeTicks::Now(); | |
| 162 | |
| 163 return test_tick_clock_->NowTicks(); | |
| 164 } | |
| 165 | |
| 166 TabManager::WebContentsData::Data::Data() | |
| 167 : is_discarded(false), | |
| 168 discard_count(0), | |
| 169 is_recently_audible(false), | |
| 170 last_audio_change_time(TimeTicks::UnixEpoch()), | |
| 171 last_discard_time(TimeTicks::UnixEpoch()), | |
| 172 last_reload_time(TimeTicks::UnixEpoch()), | |
| 173 last_inactive_time(TimeTicks::UnixEpoch()), | |
| 174 engagement_score(-1.0), | |
| 175 is_auto_discardable(true) {} | |
| 176 | |
| 177 bool TabManager::WebContentsData::Data::operator==(const Data& right) const { | |
| 178 return is_discarded == right.is_discarded && | |
| 179 is_recently_audible == right.is_recently_audible && | |
| 180 last_audio_change_time == right.last_audio_change_time && | |
| 181 last_discard_time == right.last_discard_time && | |
| 182 last_reload_time == right.last_reload_time && | |
| 183 last_inactive_time == right.last_inactive_time && | |
| 184 engagement_score == right.engagement_score; | |
| 185 } | |
| 186 | |
| 187 bool TabManager::WebContentsData::Data::operator!=(const Data& right) const { | |
| 188 return !(*this == right); | |
| 189 } | |
| 190 | |
| 191 void TabManager::WebContentsData::SetAutoDiscardableState(bool state) { | |
| 192 if (tab_data_.is_auto_discardable == state) | |
| 193 return; | |
| 194 | |
| 195 tab_data_.is_auto_discardable = state; | |
| 196 g_browser_process->GetTabManager()->OnAutoDiscardableStateChange( | |
| 197 web_contents(), state); | |
| 198 } | |
| 199 | |
| 200 bool TabManager::WebContentsData::IsAutoDiscardable() { | |
| 201 return tab_data_.is_auto_discardable; | |
| 202 } | |
| 203 | |
| 204 } // namespace memory | |
| OLD | NEW |