Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(23)

Side by Side Diff: chrome/browser/android/data_usage/external_data_use_observer.cc

Issue 2145863002: Separate data use reporting logic in ExternalDataUseObserver (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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>
8
9 #include "base/containers/hash_tables.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/metrics/field_trial.h" 7 #include "base/metrics/field_trial.h"
12 #include "base/metrics/histogram_base.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/single_thread_task_runner.h" 8 #include "base/single_thread_task_runner.h"
15 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
16 #include "base/task_runner_util.h"
17 #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h" 10 #include "chrome/browser/android/data_usage/external_data_use_observer_bridge.h"
11 #include "chrome/browser/android/data_usage/external_data_use_reporter.h"
18 #include "components/data_usage/core/data_use.h" 12 #include "components/data_usage/core/data_use.h"
19 #include "components/variations/variations_associated_data.h" 13 #include "components/variations/variations_associated_data.h"
20 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
21 15
22 namespace chrome { 16 namespace chrome {
23 17
24 namespace android { 18 namespace android {
25 19
26 namespace { 20 namespace {
27 21
28 // Record the result of data use report submission. |bytes| is the sum of send
29 // and received bytes in the report.
30 void RecordDataUsageReportSubmission(
31 ExternalDataUseObserver::DataUsageReportSubmissionResult result,
32 int64_t bytes) {
33 DCHECK_LE(0, bytes);
34 UMA_HISTOGRAM_ENUMERATION(
35 "DataUsage.ReportSubmissionResult", result,
36 ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_MAX);
37 // Cap to the maximum sample value.
38 const int32_t bytes_capped = bytes <= base::HistogramBase::kSampleType_MAX - 1
39 ? bytes
40 : base::HistogramBase::kSampleType_MAX - 1;
41 switch (result) {
42 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL:
43 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Successful",
44 bytes_capped);
45 break;
46 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_FAILED:
47 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Failed",
48 bytes_capped);
49 break;
50 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT:
51 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.TimedOut",
52 bytes_capped);
53 break;
54 case ExternalDataUseObserver::DATAUSAGE_REPORT_SUBMISSION_LOST:
55 UMA_HISTOGRAM_COUNTS("DataUsage.ReportSubmission.Bytes.Lost",
56 bytes_capped);
57 break;
58 default:
59 NOTIMPLEMENTED();
60 break;
61 }
62 }
63
64 // Default duration after which matching rules are periodically fetched. May be 22 // Default duration after which matching rules are periodically fetched. May be
65 // overridden by the field trial. 23 // overridden by the field trial.
66 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes. 24 const int kDefaultFetchMatchingRulesDurationSeconds = 60 * 15; // 15 minutes.
67 25
68 // Default duration after which a pending data use report is considered timed
69 // out. May be overridden by the field trial.
70 const int kDefaultDataUseReportSubmitTimeoutMsec = 60 * 2 * 1000; // 2 minutes.
71
72 // Default value of the minimum number of bytes that should be buffered before
73 // a data use report is submitted. May be overridden by the field trial.
74 const int64_t kDefaultDataUseReportMinBytes = 100 * 1024; // 100 KB.
75
76 // Populates various parameters from the values specified in the field trial. 26 // Populates various parameters from the values specified in the field trial.
77 int32_t GetFetchMatchingRulesDurationSeconds() { 27 int32_t GetFetchMatchingRulesDurationSeconds() {
78 int32_t duration_seconds = -1; 28 int32_t duration_seconds = -1;
79 const std::string variation_value = variations::GetVariationParamValue( 29 const std::string variation_value = variations::GetVariationParamValue(
80 chrome::android::ExternalDataUseObserver:: 30 chrome::android::ExternalDataUseObserver::
81 kExternalDataUseObserverFieldTrial, 31 kExternalDataUseObserverFieldTrial,
82 "fetch_matching_rules_duration_seconds"); 32 "fetch_matching_rules_duration_seconds");
83 if (!variation_value.empty() && 33 if (!variation_value.empty() &&
84 base::StringToInt(variation_value, &duration_seconds)) { 34 base::StringToInt(variation_value, &duration_seconds)) {
85 DCHECK_LE(0, duration_seconds); 35 DCHECK_LE(0, duration_seconds);
86 return duration_seconds; 36 return duration_seconds;
87 } 37 }
88 return kDefaultFetchMatchingRulesDurationSeconds; 38 return kDefaultFetchMatchingRulesDurationSeconds;
89 } 39 }
90 40
91 // Populates various parameters from the values specified in the field trial.
92 int32_t GetDataReportSubmitTimeoutMsec() {
93 int32_t duration_seconds = -1;
94 const std::string variation_value = variations::GetVariationParamValue(
95 chrome::android::ExternalDataUseObserver::
96 kExternalDataUseObserverFieldTrial,
97 "data_report_submit_timeout_msec");
98 if (!variation_value.empty() &&
99 base::StringToInt(variation_value, &duration_seconds)) {
100 DCHECK_LE(0, duration_seconds);
101 return duration_seconds;
102 }
103 return kDefaultDataUseReportSubmitTimeoutMsec;
104 }
105
106 // Populates various parameters from the values specified in the field trial.
107 int64_t GetMinBytes() {
108 int64_t min_bytes = -1;
109 const std::string variation_value = variations::GetVariationParamValue(
110 chrome::android::ExternalDataUseObserver::
111 kExternalDataUseObserverFieldTrial,
112 "data_use_report_min_bytes");
113 if (!variation_value.empty() &&
114 base::StringToInt64(variation_value, &min_bytes)) {
115 DCHECK_LE(0, min_bytes);
116 return min_bytes;
117 }
118 return kDefaultDataUseReportMinBytes;
119 }
120
121 } // namespace 41 } // namespace
122 42
123 // static 43 // static
124 const char ExternalDataUseObserver::kExternalDataUseObserverFieldTrial[] = 44 const char ExternalDataUseObserver::kExternalDataUseObserverFieldTrial[] =
125 "ExternalDataUseObserver"; 45 "ExternalDataUseObserver";
126 46
127 // static
128 const size_t ExternalDataUseObserver::kMaxBufferSize = 100;
129
130 ExternalDataUseObserver::ExternalDataUseObserver( 47 ExternalDataUseObserver::ExternalDataUseObserver(
131 data_usage::DataUseAggregator* data_use_aggregator, 48 data_usage::DataUseAggregator* data_use_aggregator,
132 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 49 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
133 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner) 50 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner)
134 : data_use_aggregator_(data_use_aggregator), 51 : data_use_aggregator_(data_use_aggregator),
135 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()), 52 external_data_use_observer_bridge_(new ExternalDataUseObserverBridge()),
136 data_use_tab_model_(new DataUseTabModel()), 53 data_use_tab_model_(new DataUseTabModel()),
137 last_data_report_submitted_ticks_(base::TimeTicks()), 54 external_data_use_reporter_(
138 pending_report_bytes_(0), 55 new ExternalDataUseReporter(data_use_tab_model_,
56 external_data_use_observer_bridge_)),
139 ui_task_runner_(ui_task_runner), 57 ui_task_runner_(ui_task_runner),
140 previous_report_time_(base::Time::Now()),
141 last_matching_rules_fetch_time_(base::TimeTicks::Now()), 58 last_matching_rules_fetch_time_(base::TimeTicks::Now()),
142 total_bytes_buffered_(0),
143 fetch_matching_rules_duration_( 59 fetch_matching_rules_duration_(
144 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())), 60 base::TimeDelta::FromSeconds(GetFetchMatchingRulesDurationSeconds())),
145 data_use_report_min_bytes_(GetMinBytes()),
146 data_report_submit_timeout_(
147 base::TimeDelta::FromMilliseconds(GetDataReportSubmitTimeoutMsec())),
148 #if defined(OS_ANDROID)
149 app_state_listener_(new base::android::ApplicationStatusListener(
150 base::Bind(&ExternalDataUseObserver::OnApplicationStateChange,
151 base::Unretained(this)))),
152 #endif
153 registered_as_data_use_observer_(false), 61 registered_as_data_use_observer_(false),
154 weak_factory_(this) { 62 weak_factory_(this) {
155 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); 63 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
156 DCHECK(data_use_aggregator_); 64 DCHECK(data_use_aggregator_);
157 DCHECK(io_task_runner); 65 DCHECK(io_task_runner);
158 DCHECK(ui_task_runner_); 66 DCHECK(ui_task_runner_);
159 DCHECK(last_data_report_submitted_ticks_.is_null());
160 67
161 ui_task_runner_->PostTask(FROM_HERE, 68 ui_task_runner_->PostTask(FROM_HERE,
162 base::Bind(&DataUseTabModel::InitOnUIThread, 69 base::Bind(&DataUseTabModel::InitOnUIThread,
163 base::Unretained(data_use_tab_model_), 70 base::Unretained(data_use_tab_model_),
164 external_data_use_observer_bridge_)); 71 external_data_use_observer_bridge_));
165 72
166 // Initialize the ExternalDataUseObserverBridge object. It is okay to use 73 // Initialize the ExternalDataUseObserverBridge object. It is okay to use
167 // base::Unretained here since |external_data_use_observer_bridge_| is owned 74 // base::Unretained here since |external_data_use_observer_bridge_| is owned
168 // by |this|, and is destroyed on UI thread when |this| is destroyed. 75 // by |this|, and is destroyed on UI thread when |this| is destroyed.
169 ui_task_runner_->PostTask( 76 ui_task_runner_->PostTask(
170 FROM_HERE, 77 FROM_HERE,
171 base::Bind(&ExternalDataUseObserverBridge::Init, 78 base::Bind(&ExternalDataUseObserverBridge::Init,
172 base::Unretained(external_data_use_observer_bridge_), 79 base::Unretained(external_data_use_observer_bridge_),
173 io_task_runner, GetWeakPtr(), data_use_tab_model_)); 80 io_task_runner, GetWeakPtr(), data_use_tab_model_));
174 } 81 }
175 82
176 ExternalDataUseObserver::~ExternalDataUseObserver() { 83 ExternalDataUseObserver::~ExternalDataUseObserver() {
177 DCHECK(thread_checker_.CalledOnValidThread()); 84 DCHECK(thread_checker_.CalledOnValidThread());
178 85
179 if (registered_as_data_use_observer_) 86 if (registered_as_data_use_observer_)
180 data_use_aggregator_->RemoveObserver(this); 87 data_use_aggregator_->RemoveObserver(this);
181 88
89 // Delete |external_data_use_reporter_| on the UI thread.
90 // |external_data_use_reporter_| should be deleted before
91 // |data_use_tab_model_| and |external_data_use_observer_bridge_|.
92 if (!ui_task_runner_->DeleteSoon(FROM_HERE, external_data_use_reporter_)) {
93 NOTIMPLEMENTED() << " ExternalDataUseReporter was not deleted successfully";
94 }
95
182 // Delete |data_use_tab_model_| on the UI thread. |data_use_tab_model_| should 96 // Delete |data_use_tab_model_| on the UI thread. |data_use_tab_model_| should
183 // be deleted before |external_data_use_observer_bridge_|. 97 // be deleted before |external_data_use_observer_bridge_|.
184 if (!ui_task_runner_->DeleteSoon(FROM_HERE, data_use_tab_model_)) { 98 if (!ui_task_runner_->DeleteSoon(FROM_HERE, data_use_tab_model_)) {
185 NOTIMPLEMENTED() << " DataUseTabModel was not deleted successfully"; 99 NOTIMPLEMENTED() << " DataUseTabModel was not deleted successfully";
186 } 100 }
187 101
188 // Delete |external_data_use_observer_bridge_| on the UI thread. 102 // Delete |external_data_use_observer_bridge_| on the UI thread.
189 if (!ui_task_runner_->DeleteSoon(FROM_HERE, 103 if (!ui_task_runner_->DeleteSoon(FROM_HERE,
190 external_data_use_observer_bridge_)) { 104 external_data_use_observer_bridge_)) {
191 NOTIMPLEMENTED() 105 NOTIMPLEMENTED()
192 << " ExternalDataUseObserverBridge was not deleted successfully"; 106 << " ExternalDataUseObserverBridge was not deleted successfully";
193 } 107 }
194 } 108 }
195 109
196 void ExternalDataUseObserver::OnReportDataUseDone(bool success) {
197 DCHECK(thread_checker_.CalledOnValidThread());
198 DCHECK(!last_data_report_submitted_ticks_.is_null());
199
200 if (success) {
201 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL,
202 pending_report_bytes_);
203 } else {
204 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_FAILED,
205 pending_report_bytes_);
206 }
207 UMA_HISTOGRAM_TIMES(
208 "DataUsage.Perf.ReportSubmissionDuration",
209 base::TimeTicks::Now() - last_data_report_submitted_ticks_);
210
211 last_data_report_submitted_ticks_ = base::TimeTicks();
212 pending_report_bytes_ = 0;
213
214 SubmitBufferedDataUseReport(false);
215 }
216
217 #if defined(OS_ANDROID)
218 void ExternalDataUseObserver::OnApplicationStateChange(
219 base::android::ApplicationState new_state) {
220 DCHECK(thread_checker_.CalledOnValidThread());
221 if (new_state == base::android::APPLICATION_STATE_HAS_PAUSED_ACTIVITIES)
222 SubmitBufferedDataUseReport(true);
223 }
224 #endif
225
226 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) { 110 void ExternalDataUseObserver::OnDataUse(const data_usage::DataUse& data_use) {
227 DCHECK(thread_checker_.CalledOnValidThread()); 111 DCHECK(thread_checker_.CalledOnValidThread());
228 DCHECK(registered_as_data_use_observer_); 112 DCHECK(registered_as_data_use_observer_);
229 113
230 const base::TimeTicks now_ticks = base::TimeTicks::Now(); 114 const base::TimeTicks now_ticks = base::TimeTicks::Now();
231 const base::Time now_time = base::Time::Now();
232 115
233 // If the time when the matching rules were last fetched is more than 116 // If the time when the matching rules were last fetched is more than
234 // |fetch_matching_rules_duration_|, fetch them again. 117 // |fetch_matching_rules_duration_|, fetch them again.
235 if (now_ticks - last_matching_rules_fetch_time_ >= 118 if (now_ticks - last_matching_rules_fetch_time_ >=
236 fetch_matching_rules_duration_) { 119 fetch_matching_rules_duration_) {
237 FetchMatchingRules(); 120 FetchMatchingRules();
238 } 121 }
239 122
240 std::unique_ptr<DataUseTabModel::TrackingInfo> tracking_info( 123 // It is okay to use base::Unretained here since |external_data_use_reporter_|
241 new DataUseTabModel::TrackingInfo()); 124 // is owned by |this|, and is destroyed on UI thread when |this| is destroyed.
125 ui_task_runner_->PostTask(
126 FROM_HERE,
127 base::Bind(&ExternalDataUseReporter::OnDataUse,
128 base::Unretained(external_data_use_reporter_), data_use));
129 }
242 130
243 content::BrowserThread::PostTaskAndReplyWithResult( 131 void ExternalDataUseObserver::OnReportDataUseDone(bool success) {
tbansal1 2016/07/13 16:10:58 Can this be moved to reporter? That will save two
Raj 2016/07/13 17:06:52 Yes. I have a TODO in the header file.
244 content::BrowserThread::UI, FROM_HERE, 132 DCHECK(thread_checker_.CalledOnValidThread());
245 base::Bind(&DataUseTabModel::GetTrackingInfoForTabAtTime,
246 base::Unretained(data_use_tab_model_), data_use.tab_id,
247 data_use.request_start, tracking_info.get()),
248 base::Bind(&ExternalDataUseObserver::DataUseTrackingInfoRetrieved,
249 GetWeakPtr(), data_use, previous_report_time_, now_time,
250 base::Owned(tracking_info.release())));
251 133
252 previous_report_time_ = now_time; 134 // It is okay to use base::Unretained here since |external_data_use_reporter_|
135 // is owned by |this|, and is destroyed on UI thread when |this| is destroyed.
136 ui_task_runner_->PostTask(
137 FROM_HERE,
138 base::Bind(&ExternalDataUseReporter::OnReportDataUseDone,
139 base::Unretained(external_data_use_reporter_), success));
253 } 140 }
254 141
255 void ExternalDataUseObserver::ShouldRegisterAsDataUseObserver( 142 void ExternalDataUseObserver::ShouldRegisterAsDataUseObserver(
256 bool should_register) { 143 bool should_register) {
257 DCHECK(thread_checker_.CalledOnValidThread()); 144 DCHECK(thread_checker_.CalledOnValidThread());
258 if (registered_as_data_use_observer_ == should_register) 145 if (registered_as_data_use_observer_ == should_register)
259 return; 146 return;
260 147
261 if (!registered_as_data_use_observer_ && should_register) 148 if (!registered_as_data_use_observer_ && should_register)
262 data_use_aggregator_->AddObserver(this); 149 data_use_aggregator_->AddObserver(this);
(...skipping 11 matching lines...) Expand all
274 161
275 // It is okay to use base::Unretained here since 162 // It is okay to use base::Unretained here since
276 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed 163 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
277 // on UI thread when |this| is destroyed. 164 // on UI thread when |this| is destroyed.
278 ui_task_runner_->PostTask( 165 ui_task_runner_->PostTask(
279 FROM_HERE, 166 FROM_HERE,
280 base::Bind(&ExternalDataUseObserverBridge::FetchMatchingRules, 167 base::Bind(&ExternalDataUseObserverBridge::FetchMatchingRules,
281 base::Unretained(external_data_use_observer_bridge_))); 168 base::Unretained(external_data_use_observer_bridge_)));
282 } 169 }
283 170
284 void ExternalDataUseObserver::DataUseTrackingInfoRetrieved(
285 const data_usage::DataUse& data_use,
286 const base::Time& start_time,
287 const base::Time& end_time,
288 const DataUseTabModel::TrackingInfo* tracking_info,
289 bool tracking_info_valid) {
290 DCHECK(thread_checker_.CalledOnValidThread());
291
292 if (!tracking_info_valid)
293 return;
294
295 BufferDataUseReport(data_use, tracking_info->label, tracking_info->tag,
296 start_time, end_time);
297 SubmitBufferedDataUseReport(false);
298 }
299
300 void ExternalDataUseObserver::BufferDataUseReport(
301 const data_usage::DataUse& data_use,
302 const std::string& label,
303 const std::string& tag,
304 const base::Time& start_time,
305 const base::Time& end_time) {
306 DCHECK(thread_checker_.CalledOnValidThread());
307 DCHECK(!label.empty());
308 DCHECK_LE(0, data_use.rx_bytes);
309 DCHECK_LE(0, data_use.tx_bytes);
310 // Skip if the |data_use| does not report any network traffic.
311 if (data_use.rx_bytes == 0 && data_use.tx_bytes == 0)
312 return;
313
314 DataUseReportKey data_use_report_key =
315 DataUseReportKey(label, tag, data_use.connection_type, data_use.mcc_mnc);
316
317 DataUseReport report =
318 DataUseReport(start_time, end_time, data_use.rx_bytes, data_use.tx_bytes);
319
320 // Check if the |data_use_report_key| is already in the buffered reports.
321 DataUseReports::iterator it =
322 buffered_data_reports_.find(data_use_report_key);
323 if (it == buffered_data_reports_.end()) {
324 // Limit the buffer size.
325 if (buffered_data_reports_.size() == kMaxBufferSize) {
326 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_LOST,
327 data_use.rx_bytes + data_use.tx_bytes);
328 return;
329 }
330 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report));
331 } else {
332 DataUseReport existing_report = DataUseReport(it->second);
333 DataUseReport merged_report = DataUseReport(
334 std::min(existing_report.start_time, report.start_time),
335 std::max(existing_report.end_time, report.end_time),
336 existing_report.bytes_downloaded + report.bytes_downloaded,
337 existing_report.bytes_uploaded + report.bytes_uploaded);
338 buffered_data_reports_.erase(it);
339 buffered_data_reports_.insert(
340 std::make_pair(data_use_report_key, merged_report));
341 }
342 total_bytes_buffered_ += (data_use.rx_bytes + data_use.tx_bytes);
343
344 DCHECK_LT(0U, buffered_data_reports_.size());
345 DCHECK_LE(buffered_data_reports_.size(), kMaxBufferSize);
346 }
347
348 void ExternalDataUseObserver::SubmitBufferedDataUseReport(bool immediate) {
349 DCHECK(thread_checker_.CalledOnValidThread());
350
351 const base::TimeTicks ticks_now = base::TimeTicks::Now();
352
353 // Return if a data use report has been pending for less than
354 // |data_report_submit_timeout_| duration.
355 if (!last_data_report_submitted_ticks_.is_null() &&
356 ticks_now - last_data_report_submitted_ticks_ <
357 data_report_submit_timeout_) {
358 return;
359 }
360
361 if (buffered_data_reports_.empty())
362 return;
363
364 if (!immediate && total_bytes_buffered_ < data_use_report_min_bytes_)
365 return;
366
367 if (!last_data_report_submitted_ticks_.is_null()) {
368 // Mark the pending DataUsage report as timed out.
369 RecordDataUsageReportSubmission(DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT,
370 pending_report_bytes_);
371 pending_report_bytes_ = 0;
372 last_data_report_submitted_ticks_ = base::TimeTicks();
373 }
374
375 // Send one data use report.
376 DataUseReports::iterator it = buffered_data_reports_.begin();
377 DataUseReportKey key = it->first;
378 DataUseReport report = it->second;
379
380 DCHECK_EQ(0, pending_report_bytes_);
381 DCHECK(last_data_report_submitted_ticks_.is_null());
382 pending_report_bytes_ = report.bytes_downloaded + report.bytes_uploaded;
383 last_data_report_submitted_ticks_ = ticks_now;
384
385 // Remove the entry from the map.
386 buffered_data_reports_.erase(it);
387 total_bytes_buffered_ -= (report.bytes_downloaded + report.bytes_uploaded);
388
389 // It is okay to use base::Unretained here since
390 // |external_data_use_observer_bridge_| is owned by |this|, and is destroyed
391 // on UI thread when |this| is destroyed.
392 ui_task_runner_->PostTask(
393 FROM_HERE,
394 base::Bind(&ExternalDataUseObserverBridge::ReportDataUse,
395 base::Unretained(external_data_use_observer_bridge_),
396 key.label, key.tag, key.connection_type, key.mcc_mnc,
397 report.start_time, report.end_time, report.bytes_downloaded,
398 report.bytes_uploaded));
399 }
400
401 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetWeakPtr() { 171 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetWeakPtr() {
402 DCHECK(thread_checker_.CalledOnValidThread()); 172 DCHECK(thread_checker_.CalledOnValidThread());
403 return weak_factory_.GetWeakPtr(); 173 return weak_factory_.GetWeakPtr();
404 } 174 }
405 175
406 DataUseTabModel* ExternalDataUseObserver::GetDataUseTabModel() const { 176 DataUseTabModel* ExternalDataUseObserver::GetDataUseTabModel() const {
407 DCHECK(thread_checker_.CalledOnValidThread()); 177 DCHECK(thread_checker_.CalledOnValidThread());
408 return data_use_tab_model_; 178 return data_use_tab_model_;
409 } 179 }
410 180
411 ExternalDataUseObserver::DataUseReportKey::DataUseReportKey(
412 const std::string& label,
413 const std::string& tag,
414 net::NetworkChangeNotifier::ConnectionType connection_type,
415 const std::string& mcc_mnc)
416 : label(label),
417 tag(tag),
418 connection_type(connection_type),
419 mcc_mnc(mcc_mnc) {}
420
421 ExternalDataUseObserver::DataUseReportKey::DataUseReportKey(
422 const ExternalDataUseObserver::DataUseReportKey& other) =
423 default;
424
425 bool ExternalDataUseObserver::DataUseReportKey::operator==(
426 const DataUseReportKey& other) const {
427 return label == other.label && tag == other.tag &&
428 connection_type == other.connection_type && mcc_mnc == other.mcc_mnc;
429 }
430
431 ExternalDataUseObserver::DataUseReport::DataUseReport(
432 const base::Time& start_time,
433 const base::Time& end_time,
434 int64_t bytes_downloaded,
435 int64_t bytes_uploaded)
436 : start_time(start_time),
437 end_time(end_time),
438 bytes_downloaded(bytes_downloaded),
439 bytes_uploaded(bytes_uploaded) {}
440
441 size_t ExternalDataUseObserver::DataUseReportKeyHash::operator()(
442 const DataUseReportKey& k) const {
443 // The hash is computed by hashing individual variables and combining them
444 // using prime numbers. Prime numbers are used for multiplication because the
445 // number of buckets used by map is always an even number. Using a prime
446 // number ensures that for two different DataUseReportKey objects (say |j|
447 // and |k|), if the hash value of |k.label| is equal to hash value of
448 // |j.mcc_mnc|, then |j| and |k| map to different buckets. Large prime
449 // numbers are used so that hash value is spread over a larger range.
450 std::hash<std::string> hash_function;
451 size_t hash = 1;
452 hash = hash * 23 + hash_function(k.label);
453 hash = hash * 31 + hash_function(k.tag);
454 hash = hash * 43 + k.connection_type;
455 hash = hash * 83 + hash_function(k.mcc_mnc);
456 return hash;
457 }
458
459 } // namespace android 181 } // namespace android
460 182
461 } // namespace chrome 183 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698