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 "components/data_usage/core/data_use_aggregator.h" | 5 #include "components/data_usage/core/data_use_aggregator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/memory/scoped_ptr.h" | |
10 #include "base/message_loop/message_loop.h" | |
11 #include "base/single_thread_task_runner.h" | |
12 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
13 #include "components/data_usage/core/data_use.h" | 10 #include "components/data_usage/core/data_use.h" |
| 11 #include "components/data_usage/core/data_use_amortizer.h" |
14 #include "components/data_usage/core/data_use_annotator.h" | 12 #include "components/data_usage/core/data_use_annotator.h" |
15 #include "net/base/load_timing_info.h" | 13 #include "net/base/load_timing_info.h" |
16 #include "net/base/network_change_notifier.h" | 14 #include "net/base/network_change_notifier.h" |
17 #include "net/url_request/url_request.h" | 15 #include "net/url_request/url_request.h" |
18 | 16 |
19 #if defined(OS_ANDROID) | 17 #if defined(OS_ANDROID) |
20 #include "net/android/network_library.h" | 18 #include "net/android/network_library.h" |
21 #endif // OS_ANDROID | 19 #endif // OS_ANDROID |
22 | 20 |
23 namespace data_usage { | 21 namespace data_usage { |
24 | 22 |
25 DataUseAggregator::DataUseAggregator(scoped_ptr<DataUseAnnotator> annotator) | 23 DataUseAggregator::DataUseAggregator(scoped_ptr<DataUseAnnotator> annotator, |
| 24 scoped_ptr<DataUseAmortizer> amortizer) |
26 : annotator_(annotator.Pass()), | 25 : annotator_(annotator.Pass()), |
| 26 amortizer_(amortizer.Pass()), |
27 connection_type_(net::NetworkChangeNotifier::GetConnectionType()), | 27 connection_type_(net::NetworkChangeNotifier::GetConnectionType()), |
28 off_the_record_tx_bytes_since_last_flush_(0), | |
29 off_the_record_rx_bytes_since_last_flush_(0), | |
30 is_flush_pending_(false), | |
31 weak_ptr_factory_(this) { | 28 weak_ptr_factory_(this) { |
32 #if defined(OS_ANDROID) | 29 #if defined(OS_ANDROID) |
33 mcc_mnc_ = net::android::GetTelephonySimOperator(); | 30 mcc_mnc_ = net::android::GetTelephonySimOperator(); |
34 #endif // OS_ANDROID | 31 #endif // OS_ANDROID |
35 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 32 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); |
36 } | 33 } |
37 | 34 |
38 DataUseAggregator::~DataUseAggregator() { | 35 DataUseAggregator::~DataUseAggregator() { |
39 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 36 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
40 } | 37 } |
(...skipping 15 matching lines...) Expand all Loading... |
56 | 53 |
57 net::LoadTimingInfo load_timing_info; | 54 net::LoadTimingInfo load_timing_info; |
58 request->GetLoadTimingInfo(&load_timing_info); | 55 request->GetLoadTimingInfo(&load_timing_info); |
59 | 56 |
60 scoped_ptr<DataUse> data_use( | 57 scoped_ptr<DataUse> data_use( |
61 new DataUse(request->url(), load_timing_info.request_start, | 58 new DataUse(request->url(), load_timing_info.request_start, |
62 request->first_party_for_cookies(), -1 /* tab_id */, | 59 request->first_party_for_cookies(), -1 /* tab_id */, |
63 connection_type_, mcc_mnc_, tx_bytes, rx_bytes)); | 60 connection_type_, mcc_mnc_, tx_bytes, rx_bytes)); |
64 | 61 |
65 if (!annotator_) { | 62 if (!annotator_) { |
66 AppendDataUse(data_use.Pass()); | 63 PassDataUseToAmortizer(data_use.Pass()); |
67 return; | 64 return; |
68 } | 65 } |
69 | 66 |
| 67 // TODO(sclittle): Instead of binding a new callback every time, re-use the |
| 68 // same callback every time. |
70 annotator_->Annotate( | 69 annotator_->Annotate( |
71 request, data_use.Pass(), | 70 request, data_use.Pass(), |
72 base::Bind(&DataUseAggregator::AppendDataUse, GetWeakPtr())); | 71 base::Bind(&DataUseAggregator::PassDataUseToAmortizer, GetWeakPtr())); |
73 } | 72 } |
74 | 73 |
75 void DataUseAggregator::ReportOffTheRecordDataUse(int64_t tx_bytes, | 74 void DataUseAggregator::ReportOffTheRecordDataUse(int64_t tx_bytes, |
76 int64_t rx_bytes) { | 75 int64_t rx_bytes) { |
77 DCHECK(thread_checker_.CalledOnValidThread()); | 76 DCHECK(thread_checker_.CalledOnValidThread()); |
78 off_the_record_tx_bytes_since_last_flush_ += tx_bytes; | 77 if (!amortizer_) |
79 off_the_record_rx_bytes_since_last_flush_ += rx_bytes; | 78 return; |
| 79 |
| 80 amortizer_->OnExtraBytes(tx_bytes, rx_bytes); |
80 } | 81 } |
81 | 82 |
82 base::WeakPtr<DataUseAggregator> DataUseAggregator::GetWeakPtr() { | 83 base::WeakPtr<DataUseAggregator> DataUseAggregator::GetWeakPtr() { |
83 DCHECK(thread_checker_.CalledOnValidThread()); | 84 DCHECK(thread_checker_.CalledOnValidThread()); |
84 return weak_ptr_factory_.GetWeakPtr(); | 85 return weak_ptr_factory_.GetWeakPtr(); |
85 } | 86 } |
86 | 87 |
87 void DataUseAggregator::OnConnectionTypeChanged( | 88 void DataUseAggregator::OnConnectionTypeChanged( |
88 net::NetworkChangeNotifier::ConnectionType type) { | 89 net::NetworkChangeNotifier::ConnectionType type) { |
89 DCHECK(thread_checker_.CalledOnValidThread()); | 90 DCHECK(thread_checker_.CalledOnValidThread()); |
90 | 91 |
91 connection_type_ = type; | 92 connection_type_ = type; |
92 #if defined(OS_ANDROID) | 93 #if defined(OS_ANDROID) |
93 mcc_mnc_ = net::android::GetTelephonySimOperator(); | 94 mcc_mnc_ = net::android::GetTelephonySimOperator(); |
94 #endif // OS_ANDROID | 95 #endif // OS_ANDROID |
95 } | 96 } |
96 | 97 |
97 void DataUseAggregator::SetMccMncForTests(const std::string& mcc_mnc) { | 98 void DataUseAggregator::SetMccMncForTests(const std::string& mcc_mnc) { |
98 DCHECK(thread_checker_.CalledOnValidThread()); | 99 DCHECK(thread_checker_.CalledOnValidThread()); |
99 mcc_mnc_ = mcc_mnc; | 100 mcc_mnc_ = mcc_mnc; |
100 } | 101 } |
101 | 102 |
102 void DataUseAggregator::AppendDataUse(scoped_ptr<DataUse> data_use) { | 103 void DataUseAggregator::PassDataUseToAmortizer(scoped_ptr<DataUse> data_use) { |
103 DCHECK(thread_checker_.CalledOnValidThread()); | 104 DCHECK(thread_checker_.CalledOnValidThread()); |
104 DCHECK(data_use); | 105 DCHECK(data_use); |
105 | 106 |
106 // As an optimization, attempt to combine the newly reported data use with the | 107 if (!amortizer_) { |
107 // most recent buffered data use, if the annotations on the data use are the | 108 OnAmortizationComplete(data_use.Pass()); |
108 // same. | 109 return; |
109 if (!buffered_data_use_.empty() && | |
110 buffered_data_use_.back()->CanCombineWith(*data_use)) { | |
111 buffered_data_use_.back()->tx_bytes += data_use->tx_bytes; | |
112 buffered_data_use_.back()->rx_bytes += data_use->rx_bytes; | |
113 } else { | |
114 buffered_data_use_.push_back(data_use.Pass()); | |
115 } | 110 } |
116 | 111 |
117 if (!is_flush_pending_) { | 112 // TODO(sclittle): Instead of binding a new callback every time, re-use the |
118 // Post a flush operation to happen in the future, so that the | 113 // same callback every time. |
119 // DataUseAggregator has a chance to batch together some data use before | 114 amortizer_->AmortizeDataUse( |
120 // notifying observers. | 115 data_use.Pass(), |
121 base::MessageLoop::current()->task_runner()->PostTask( | 116 base::Bind(&DataUseAggregator::OnAmortizationComplete, GetWeakPtr())); |
122 FROM_HERE, | |
123 base::Bind(&DataUseAggregator::FlushBufferedDataUse, GetWeakPtr())); | |
124 is_flush_pending_ = true; | |
125 } | |
126 } | 117 } |
127 | 118 |
128 void DataUseAggregator::FlushBufferedDataUse() { | 119 void DataUseAggregator::OnAmortizationComplete( |
| 120 scoped_ptr<DataUse> amortized_data_use) { |
129 DCHECK(thread_checker_.CalledOnValidThread()); | 121 DCHECK(thread_checker_.CalledOnValidThread()); |
130 | 122 |
131 // TODO(sclittle): Amortize data use on supported platforms before notifying | |
132 // observers. | |
133 | |
134 // Pass Observers a sequence of const DataUse pointers instead of using the | 123 // Pass Observers a sequence of const DataUse pointers instead of using the |
135 // buffer directly in order to prevent Observers from modifying the DataUse | 124 // buffer directly in order to prevent Observers from modifying the DataUse |
136 // objects. | 125 // objects. |
137 std::vector<const DataUse*> const_sequence(buffered_data_use_.begin(), | 126 // TODO(sclittle): Change the observer interface to take in a const DataUse&. |
138 buffered_data_use_.end()); | 127 std::vector<const DataUse*> const_sequence(1, amortized_data_use.get()); |
139 DCHECK(!ContainsValue(const_sequence, nullptr)); | 128 DCHECK(!ContainsValue(const_sequence, nullptr)); |
140 FOR_EACH_OBSERVER(Observer, observer_list_, OnDataUse(const_sequence)); | 129 FOR_EACH_OBSERVER(Observer, observer_list_, OnDataUse(const_sequence)); |
141 | |
142 buffered_data_use_.clear(); | |
143 off_the_record_tx_bytes_since_last_flush_ = 0; | |
144 off_the_record_rx_bytes_since_last_flush_ = 0; | |
145 is_flush_pending_ = false; | |
146 } | 130 } |
147 | 131 |
148 } // namespace data_usage | 132 } // namespace data_usage |
OLD | NEW |