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 |