OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/android/data_usage/external_data_use_observer.h" | 5 #include "chrome/browser/android/data_usage/external_data_use_observer.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/containers/hash_tables.h" | 9 #include "base/containers/hash_tables.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/metrics/field_trial.h" | 11 #include "base/metrics/field_trial.h" |
12 #include "base/single_thread_task_runner.h" | 12 #include "base/metrics/histogram_base.h" |
13 #include "base/metrics/histogram_macros.h" | |
13 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
14 #include "chrome/browser/android/data_usage/data_use_tab_model.h" | 15 #include "chrome/browser/android/data_usage/data_use_tab_model.h" |
15 #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h" | 16 #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h" |
16 #include "components/data_usage/core/data_use.h" | 17 #include "components/data_usage/core/data_use.h" |
17 #include "components/variations/variations_associated_data.h" | 18 #include "components/variations/variations_associated_data.h" |
18 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
19 #include "third_party/re2/re2/re2.h" | 20 #include "third_party/re2/re2/re2.h" |
20 #include "url/gurl.h" | 21 #include "url/gurl.h" |
21 | 22 |
22 namespace { | 23 namespace { |
Alexei Svitkine (slow)
2015/12/09 18:15:47
Nit: Move this anon namespace to be inside of chro
tbansal1
2015/12/10 00:41:39
Done.
| |
23 | 24 |
25 // Record the result of data use report submission. |bytes| is the sum of send | |
26 // and received bytes in the report. | |
27 void RecordDataUsageReportSubmission( | |
28 chrome::android::ExternalDataUseObserver::DataUsageReportSubmissionResult | |
29 result, | |
30 int64_t bytes) { | |
31 DCHECK_LE(0, bytes); | |
32 UMA_HISTOGRAM_ENUMERATION("DataUsage.ReportSubmissionResult", result, | |
33 chrome::android::ExternalDataUseObserver:: | |
34 DATAUSAGE_REPORT_SUBMISSION_MAX); | |
35 // Cap to the maximum sample value. | |
36 const int32_t bytes_capped = bytes <= base::HistogramBase::kSampleType_MAX - 1 | |
37 ? bytes | |
38 : base::HistogramBase::kSampleType_MAX - 1; | |
39 switch (result) { | |
40 case chrome::android::ExternalDataUseObserver:: | |
41 DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL: | |
42 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Successful.Bytes", | |
43 bytes_capped); | |
44 break; | |
45 case chrome::android::ExternalDataUseObserver:: | |
46 DATAUSAGE_REPORT_SUBMISSION_FAILED: | |
47 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Failed.Bytes", | |
48 bytes_capped); | |
49 break; | |
50 case chrome::android::ExternalDataUseObserver:: | |
51 DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT: | |
52 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.TimedOut.Bytes", | |
53 bytes_capped); | |
54 break; | |
55 case chrome::android::ExternalDataUseObserver:: | |
56 DATAUSAGE_REPORT_SUBMISSION_LOST: | |
57 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Lost.Bytes", | |
58 bytes_capped); | |
59 break; | |
60 default: | |
61 NOTIMPLEMENTED(); | |
62 break; | |
63 } | |
64 } | |
65 | |
24 // Default duration after which matching rules are periodically fetched. May be | 66 // Default duration after which matching rules are periodically fetched. May be |
25 // overridden by the field trial. | 67 // overridden by the field trial. |
26 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes. | 68 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes. |
27 | 69 |
70 // Default duration after which a pending data use report is considered timed | |
71 // out. May be overridden by the field trial. | |
72 const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes. | |
73 | |
28 // Default value of the minimum number of bytes that should be buffered before | 74 // Default value of the minimum number of bytes that should be buffered before |
29 // a data use report is submitted. May be overridden by the field trial. | 75 // a data use report is submitted. May be overridden by the field trial. |
30 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB. | 76 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB. |
31 | 77 |
32 // Populates various parameters from the values specified in the field trial. | 78 // Populates various parameters from the values specified in the field trial. |
33 int32_t GetFetchMatchingRulesDurationSeconds() { | 79 int32_t GetFetchMatchingRulesDurationSeconds() { |
34 int32_t duration_seconds = -1; | 80 int32_t duration_seconds = -1; |
35 std::string variation_value = variations::GetVariationParamValue( | 81 const std::string variation_value = variations::GetVariationParamValue( |
36 chrome::android::ExternalDataUseObserver:: | 82 chrome::android::ExternalDataUseObserver:: |
37 kExternalDataUseObserverFieldTrial, | 83 kExternalDataUseObserverFieldTrial, |
38 "fetch_matching_rules_duration_seconds"); | 84 "fetch_matching_rules_duration_seconds"); |
39 if (!variation_value.empty() && | 85 if (!variation_value.empty() && |
40 base::StringToInt(variation_value, &duration_seconds)) { | 86 base::StringToInt(variation_value, &duration_seconds)) { |
41 DCHECK_LE(0, duration_seconds); | 87 DCHECK_LE(0, duration_seconds); |
42 return duration_seconds; | 88 return duration_seconds; |
43 } | 89 } |
44 return kDefaultFetchMatchingRulesDurationSeconds; | 90 return kDefaultFetchMatchingRulesDurationSeconds; |
45 } | 91 } |
46 | 92 |
47 // Populates various parameters from the values specified in the field trial. | 93 // Populates various parameters from the values specified in the field trial. |
94 int32_t GetDataReportSubmitTimeoutMsec() { | |
95 int32_t duration_seconds = -1; | |
96 const std::string variation_value = variations::GetVariationParamValue( | |
97 chrome::android::ExternalDataUseObserver:: | |
98 kExternalDataUseObserverFieldTrial, | |
99 "data_report_submit_timeout_msec"); | |
100 if (!variation_value.empty() && | |
101 base::StringToInt(variation_value, &duration_seconds)) { | |
102 DCHECK_LE(0, duration_seconds); | |
103 return duration_seconds; | |
104 } | |
105 return kDefaultDataUseReportSubmitTimeoutMsec; | |
106 } | |
107 | |
108 // Populates various parameters from the values specified in the field trial. | |
48 int64_t GetMinBytes() { | 109 int64_t GetMinBytes() { |
49 int64_t min_bytes = -1; | 110 int64_t min_bytes = -1; |
50 std::string variation_value = variations::GetVariationParamValue( | 111 const std::string variation_value = variations::GetVariationParamValue( |
51 chrome::android::ExternalDataUseObserver:: | 112 chrome::android::ExternalDataUseObserver:: |
52 kExternalDataUseObserverFieldTrial, | 113 kExternalDataUseObserverFieldTrial, |
53 "data_use_report_min_bytes"); | 114 "data_use_report_min_bytes"); |
54 if (!variation_value.empty() && | 115 if (!variation_value.empty() && |
55 base::StringToInt64(variation_value, &min_bytes)) { | 116 base::StringToInt64(variation_value, &min_bytes)) { |
56 DCHECK_LE(0, min_bytes); | 117 DCHECK_LE(0, min_bytes); |
57 return min_bytes; | 118 return min_bytes; |
58 } | 119 } |
59 return kDefaultDataUseReportMinBytes; | 120 return kDefaultDataUseReportMinBytes; |
60 } | 121 } |
(...skipping 10 matching lines...) Expand all Loading... | |
71 | 132 |
72 // static | 133 // static |
73 const size_t ExternalDataUseObserver::kMaxBufferSize = 100; | 134 const size_t ExternalDataUseObserver::kMaxBufferSize = 100; |
74 | 135 |
75 ExternalDataUseObserver::ExternalDataUseObserver( | 136 ExternalDataUseObserver::ExternalDataUseObserver( |
76 data_usage::DataUseAggregator* data_use_aggregator, | 137 data_usage::DataUseAggregator* data_use_aggregator, |
77 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, | 138 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, |
78 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) | 139 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) |
79 : data_use_aggregator_(data_use_aggregator), | 140 : data_use_aggregator_(data_use_aggregator), |
80 matching_rules_fetch_pending_(false), | 141 matching_rules_fetch_pending_(false), |
81 submit_data_report_pending_(false), | 142 last_data_report_submitted_ticks_(base::TimeTicks()), |
143 pending_report_bytes_(0), | |
82 registered_as_observer_(false), | 144 registered_as_observer_(false), |
83 ui_task_runner_(ui_task_runner), | 145 ui_task_runner_(ui_task_runner), |
84 previous_report_time_(base::Time::Now()), | 146 previous_report_time_(base::Time::Now()), |
85 last_matching_rules_fetch_time_(base::TimeTicks::Now()), | 147 last_matching_rules_fetch_time_(base::TimeTicks::Now()), |
86 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()), | 148 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()), |
87 total_bytes_buffered_(0), | 149 total_bytes_buffered_(0), |
88 fetch_matching_rules_duration_( | 150 fetch_matching_rules_duration_( |
89 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())), | 151 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())), |
90 data_use_report_min_bytes_(GetMinBytes()), | 152 data_use_report_min_bytes_(GetMinBytes()), |
153 data_report_submit_timeout_( | |
154 base::TimeDelta::FromMilliseconds(GetDataReportSubmitTimeoutMsec())), | |
91 weak_factory_(this) { | 155 weak_factory_(this) { |
92 DCHECK(data_use_aggregator_); | 156 DCHECK(data_use_aggregator_); |
93 DCHECK(io_task_runner); | 157 DCHECK(io_task_runner); |
94 DCHECK(ui_task_runner_); | 158 DCHECK(ui_task_runner_); |
159 DCHECK(last_data_report_submitted_ticks_.is_null()); | |
95 | 160 |
96 // Initialize the ExternalDataUseObserverBridge object. Initialization will | 161 // Initialize the ExternalDataUseObserverBridge object. Initialization will |
97 // also trigger the fetching of matching rules. It is okay to use | 162 // also trigger the fetching of matching rules. It is okay to use |
98 // base::Unretained here since |external_data_use_observer_bridge_| is | 163 // base::Unretained here since |external_data_use_observer_bridge_| is |
99 // owned by |this|, and is destroyed on UI thread when |this| is destroyed. | 164 // owned by |this|, and is destroyed on UI thread when |this| is destroyed. |
100 ui_task_runner_->PostTask( | 165 ui_task_runner_->PostTask( |
101 FROM_HERE, | 166 FROM_HERE, |
102 base::Bind(&ExternalDataUseObserverBridge::Init, | 167 base::Bind(&ExternalDataUseObserverBridge::Init, |
103 base::Unretained(external_data_use_observer_bridge_), | 168 base::Unretained(external_data_use_observer_bridge_), |
104 io_task_runner, GetWeakPtr())); | 169 io_task_runner, GetWeakPtr())); |
(...skipping 26 matching lines...) Expand all Loading... | |
131 const std::vector<std::string>* label) { | 196 const std::vector<std::string>* label) { |
132 DCHECK(thread_checker_.CalledOnValidThread()); | 197 DCHECK(thread_checker_.CalledOnValidThread()); |
133 | 198 |
134 RegisterURLRegexes(app_package_name, domain_path_regex, label); | 199 RegisterURLRegexes(app_package_name, domain_path_regex, label); |
135 matching_rules_fetch_pending_ = false; | 200 matching_rules_fetch_pending_ = false; |
136 // Process buffered reports. | 201 // Process buffered reports. |
137 } | 202 } |
138 | 203 |
139 void ExternalDataUseObserver::OnReportDataUseDone(bool success) { | 204 void ExternalDataUseObserver::OnReportDataUseDone(bool success) { |
140 DCHECK(thread_checker_.CalledOnValidThread()); | 205 DCHECK(thread_checker_.CalledOnValidThread()); |
141 DCHECK(submit_data_report_pending_); | 206 DCHECK(!last_data_report_submitted_ticks_.is_null()); |
142 | 207 |
143 // TODO(tbansal): If not successful, record UMA. | 208 if (success) { |
209 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL, | |
210 pending_report_bytes_); | |
211 } else { | |
212 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_FAILED, | |
213 pending_report_bytes_); | |
214 } | |
144 | 215 |
145 submit_data_report_pending_ = false; | 216 last_data_report_submitted_ticks_ = base::TimeTicks(); |
217 pending_report_bytes_ = 0; | |
146 | 218 |
147 SubmitBufferedDataUseReport(); | 219 SubmitBufferedDataUseReport(); |
148 } | 220 } |
149 | 221 |
150 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) { | 222 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) { |
151 DCHECK(thread_checker_.CalledOnValidThread()); | 223 DCHECK(thread_checker_.CalledOnValidThread()); |
152 const base::TimeTicks now_ticks = base::TimeTicks::Now(); | 224 const base::TimeTicks now_ticks = base::TimeTicks::Now(); |
153 const base::Time now_time = base::Time::Now(); | 225 const base::Time now_time = base::Time::Now(); |
154 | 226 |
155 // If the time when the matching rules were last fetched is more than | 227 // If the time when the matching rules were last fetched is more than |
(...skipping 26 matching lines...) Expand all Loading... | |
182 | 254 |
183 void ExternalDataUseObserver::BufferDataUseReport( | 255 void ExternalDataUseObserver::BufferDataUseReport( |
184 const data_usage::DataUse& data_use, | 256 const data_usage::DataUse& data_use, |
185 const std::string& label, | 257 const std::string& label, |
186 const base::Time& start_time, | 258 const base::Time& start_time, |
187 const base::Time& end_time) { | 259 const base::Time& end_time) { |
188 DCHECK(thread_checker_.CalledOnValidThread()); | 260 DCHECK(thread_checker_.CalledOnValidThread()); |
189 DCHECK(!label.empty()); | 261 DCHECK(!label.empty()); |
190 DCHECK_LE(0, data_use.rx_bytes); | 262 DCHECK_LE(0, data_use.rx_bytes); |
191 DCHECK_LE(0, data_use.tx_bytes); | 263 DCHECK_LE(0, data_use.tx_bytes); |
192 if (data_use.rx_bytes < 0 || data_use.tx_bytes < 0) | 264 // Skip if the |data_use| does not report any network traffic. |
265 if (data_use.rx_bytes == 0 && data_use.tx_bytes == 0) | |
193 return; | 266 return; |
194 | 267 |
195 DataUseReportKey data_use_report_key = | 268 DataUseReportKey data_use_report_key = |
196 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc); | 269 DataUseReportKey(label, data_use.connection_type, data_use.mcc_mnc); |
197 | 270 |
198 DataUseReport report = | 271 DataUseReport report = |
199 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes); | 272 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes); |
200 | 273 |
201 // Check if the |data_use_report_key| is already in the buffered reports. | 274 // Check if the |data_use_report_key| is already in the buffered reports. |
202 DataUseReports::iterator it = | 275 DataUseReports::iterator it = |
203 buffered_data_reports_.find(data_use_report_key); | 276 buffered_data_reports_.find(data_use_report_key); |
204 if (it == buffered_data_reports_.end()) { | 277 if (it == buffered_data_reports_.end()) { |
205 // Limit the buffer size. | 278 // Limit the buffer size. |
206 if (buffered_data_reports_.size() == kMaxBufferSize) { | 279 if (buffered_data_reports_.size() == kMaxBufferSize) { |
207 // TODO(tbansal): Add UMA to track impact of lost reports. | 280 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_LOST, |
281 data_use.rx_bytes + data_use.tx_bytes); | |
208 return; | 282 return; |
209 } | 283 } |
210 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report)); | 284 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report)); |
211 } else { | 285 } else { |
212 DataUseReport existing_report = DataUseReport(it->second); | 286 DataUseReport existing_report = DataUseReport(it->second); |
213 DataUseReport merged_report = DataUseReport( | 287 DataUseReport merged_report = DataUseReport( |
214 std::min(existing_report.start_time, report.start_time), | 288 std::min(existing_report.start_time, report.start_time), |
215 std::max(existing_report.end_time, report.end_time), | 289 std::max(existing_report.end_time, report.end_time), |
216 existing_report.bytes_downloaded + report.bytes_downloaded, | 290 existing_report.bytes_downloaded + report.bytes_downloaded, |
217 existing_report.bytes_uploaded + report.bytes_uploaded); | 291 existing_report.bytes_uploaded + report.bytes_uploaded); |
218 buffered_data_reports_.erase(it); | 292 buffered_data_reports_.erase(it); |
219 buffered_data_reports_.insert( | 293 buffered_data_reports_.insert( |
220 std::make_pair(data_use_report_key, merged_report)); | 294 std::make_pair(data_use_report_key, merged_report)); |
221 } | 295 } |
222 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes); | 296 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes); |
223 | 297 |
298 DCHECK_LT(0U, buffered_data_reports_.size()); | |
224 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize); | 299 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize); |
225 } | 300 } |
226 | 301 |
227 void ExternalDataUseObserver::SubmitBufferedDataUseReport() { | 302 void ExternalDataUseObserver::SubmitBufferedDataUseReport() { |
228 DCHECK(thread_checker_.CalledOnValidThread()); | 303 DCHECK(thread_checker_.CalledOnValidThread()); |
229 | 304 |
230 if (submit_data_report_pending_ || buffered_data_reports_.empty()) | 305 const base::TimeTicks ticks_now = base::TimeTicks::Now(); |
306 | |
307 // Return if a data use report has been pending for less than | |
308 // |data_report_submit_timeout_| duration. | |
309 if (!last_data_report_submitted_ticks_.is_null() && | |
310 ticks_now - last_data_report_submitted_ticks_ < | |
311 data_report_submit_timeout_) { | |
312 return; | |
313 } | |
314 | |
315 if (buffered_data_reports_.empty()) | |
231 return; | 316 return; |
232 | 317 |
233 if (total_bytes_buffered_ < data_use_report_min_bytes_) | 318 if (total_bytes_buffered_ < data_use_report_min_bytes_) |
234 return; | 319 return; |
235 | 320 |
321 if (!last_data_report_submitted_ticks_.is_null()) { | |
322 // Mark the pending DataUsage report as timed out. | |
323 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT, | |
324 pending_report_bytes_); | |
325 pending_report_bytes_ = 0; | |
326 last_data_report_submitted_ticks_ = base::TimeTicks(); | |
327 } | |
328 | |
236 // Send one data use report. | 329 // Send one data use report. |
237 DataUseReports::iterator it = buffered_data_reports_.begin(); | 330 DataUseReports::iterator it = buffered_data_reports_.begin(); |
238 DataUseReportKey key = it->first; | 331 DataUseReportKey key = it->first; |
239 DataUseReport report = it->second; | 332 DataUseReport report = it->second; |
240 | 333 |
334 DCHECK_EQ(0, pending_report_bytes_); | |
335 DCHECK(last_data_report_submitted_ticks_.is_null()); | |
336 pending_report_bytes_ = report.bytes_downloaded + report.bytes_uploaded; | |
337 last_data_report_submitted_ticks_ = ticks_now; | |
338 | |
241 // Remove the entry from the map. | 339 // Remove the entry from the map. |
242 buffered_data_reports_.erase(it); | 340 buffered_data_reports_.erase(it); |
243 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded); | 341 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded); |
244 | 342 |
245 submit_data_report_pending_ = true; | |
246 | |
247 // It is okay to use base::Unretained here since | 343 // It is okay to use base::Unretained here since |
248 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed | 344 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed |
249 // on UI thread when |this| is destroyed. | 345 // on UI thread when |this| is destroyed. |
250 ui_task_runner_->PostTask( | 346 ui_task_runner_->PostTask( |
251 FROM_HERE, | 347 FROM_HERE, |
252 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse, | 348 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse, |
253 base::Unretained(external_data_use_observer_bridge_), | 349 base::Unretained(external_data_use_observer_bridge_), |
254 key.label, key.connection_type, key.mcc_mnc, report.start_time, | 350 key.label, key.connection_type, key.mcc_mnc, report.start_time, |
255 report.end_time, report.bytes_downloaded, | 351 report.end_time, report.bytes_downloaded, |
256 report.bytes_uploaded)); | 352 report.bytes_uploaded)); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
407 return app_package_name_; | 503 return app_package_name_; |
408 } | 504 } |
409 | 505 |
410 const std::string& ExternalDataUseObserver::MatchingRule::label() const { | 506 const std::string& ExternalDataUseObserver::MatchingRule::label() const { |
411 return label_; | 507 return label_; |
412 } | 508 } |
413 | 509 |
414 } // namespace android | 510 } // namespace android |
415 | 511 |
416 } // namespace chrome | 512 } // namespace chrome |
OLD | NEW |