blob: ff7681f2ea3da9f577f24b76d3151f7516d21a67 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/data_usage/tab_data_use_entry.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/android/data_usage/data_use_tab_model.h"
#include "chrome/browser/android/data_usage/external_data_use_observer.h"
#include "components/variations/variations_associated_data.h"
namespace {
const char kUMATrackingSessionLifetimeHistogram[] =
"DataUsage.TabModel.TrackingSessionLifetime";
const char kUMAOldInactiveSessionRemovalDurationHistogram[] =
"DataUsage.TabModel.OldInactiveSessionRemovalDuration";
} // namespace
namespace chrome {
namespace android {
TabDataUseEntry::TabDataUseEntry(DataUseTabModel* tab_model)
: is_custom_tab_package_match_(false), tab_model_(tab_model) {
DCHECK(tab_model_);
}
TabDataUseEntry::TabDataUseEntry(const TabDataUseEntry& other) = default;
TabDataUseEntry::~TabDataUseEntry() {}
bool TabDataUseEntry::StartTracking(const std::string& label) {
DCHECK(!label.empty());
DCHECK(tab_close_time_.is_null());
if (IsTrackingDataUse())
return false; // Duplicate start events.
// TODO(rajendrant): Explore ability to handle changes in label for current
// session.
sessions_.push_back(TabDataUseTrackingSession(label, tab_model_->NowTicks()));
CompactSessionHistory();
return true;
}
bool TabDataUseEntry::EndTracking() {
DCHECK(tab_close_time_.is_null());
if (!IsTrackingDataUse())
return false; // Duplicate end events.
TabSessions::reverse_iterator back_iterator = sessions_.rbegin();
if (back_iterator == sessions_.rend())
return false;
back_iterator->end_time = tab_model_->NowTicks();
UMA_HISTOGRAM_CUSTOM_TIMES(
kUMATrackingSessionLifetimeHistogram,
back_iterator->end_time - back_iterator->start_time,
base::TimeDelta::FromSeconds(1), base::TimeDelta::FromHours(1), 50);
return true;
}
bool TabDataUseEntry::EndTrackingWithLabel(const std::string& label) {
if (!sessions_.empty() && sessions_.back().label == label)
return EndTracking();
return false;
}
void TabDataUseEntry::OnTabCloseEvent() {
DCHECK(!IsTrackingDataUse());
tab_close_time_ = tab_model_->NowTicks();
}
bool TabDataUseEntry::IsExpired() const {
const base::TimeTicks now = tab_model_->NowTicks();
if (!tab_close_time_.is_null()) {
// Closed tab entry.
return ((now - tab_close_time_) >
tab_model_->closed_tab_expiration_duration());
}
const base::TimeTicks latest_session_time = GetLatestStartOrEndTime();
if (latest_session_time.is_null() ||
((now - latest_session_time) >
tab_model_->open_tab_expiration_duration())) {
return true;
}
return false;
}
bool TabDataUseEntry::GetLabel(const base::TimeTicks& data_use_time,
std::string* output_label) const {
*output_label = "";
// Find a tracking session in history that was active at |data_use_time|.
for (TabSessions::const_reverse_iterator session_iterator =
sessions_.rbegin();
session_iterator != sessions_.rend(); ++session_iterator) {
if (session_iterator->start_time <= data_use_time &&
(session_iterator->end_time.is_null() ||
session_iterator->end_time >= data_use_time)) {
*output_label = session_iterator->label;
return true;
}
if (!session_iterator->end_time.is_null() &&
session_iterator->end_time < data_use_time) {
// Older sessions in history will end before |data_use_time| and will not
// match.
break;
}
}
return false;
}
bool TabDataUseEntry::IsTrackingDataUse() const {
TabSessions::const_reverse_iterator back_iterator = sessions_.rbegin();
if (back_iterator == sessions_.rend())
return false;
return back_iterator->end_time.is_null();
}
const base::TimeTicks TabDataUseEntry::GetLatestStartOrEndTime() const {
TabSessions::const_reverse_iterator back_iterator = sessions_.rbegin();
if (back_iterator == sessions_.rend())
return base::TimeTicks(); // No tab session found.
if (!back_iterator->end_time.is_null())
return back_iterator->end_time;
DCHECK(!back_iterator->start_time.is_null());
return back_iterator->start_time;
}
const std::string TabDataUseEntry::GetActiveTrackingSessionLabel() const {
TabSessions::const_reverse_iterator back_iterator = sessions_.rbegin();
if (back_iterator == sessions_.rend() || !IsTrackingDataUse())
return std::string();
return back_iterator->label;
}
void TabDataUseEntry::set_custom_tab_package_match(
bool is_custom_tab_package_match) {
DCHECK(IsTrackingDataUse());
DCHECK(!GetActiveTrackingSessionLabel().empty());
is_custom_tab_package_match_ = is_custom_tab_package_match;
}
void TabDataUseEntry::CompactSessionHistory() {
while (sessions_.size() > tab_model_->max_sessions_per_tab()) {
const auto& front = sessions_.front();
DCHECK(!front.end_time.is_null());
// Track how often old sessions are lost.
UMA_HISTOGRAM_CUSTOM_TIMES(kUMAOldInactiveSessionRemovalDurationHistogram,
tab_model_->NowTicks() - front.end_time,
base::TimeDelta::FromSeconds(1),
base::TimeDelta::FromHours(1), 50);
sessions_.pop_front();
}
}
} // namespace android
} // namespace chrome
|