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 #ifndef CHROME_BROWSER_ANDROID_DATA_USAGE_EXTERNAL_DATA_USE_OBSERVER_H_ | 5 #ifndef CHROME_BROWSER_ANDROID_DATA_USAGE_EXTERNAL_DATA_USE_OBSERVER_H_ |
6 #define CHROME_BROWSER_ANDROID_DATA_USAGE_EXTERNAL_DATA_USE_OBSERVER_H_ | 6 #define CHROME_BROWSER_ANDROID_DATA_USAGE_EXTERNAL_DATA_USE_OBSERVER_H_ |
7 | 7 |
8 #include <stddef.h> | |
9 #include <stdint.h> | |
10 | |
11 #include <memory> | |
12 #include <string> | |
13 #include <vector> | |
14 | |
15 #include "base/containers/hash_tables.h" | |
16 #include "base/gtest_prod_util.h" | 8 #include "base/gtest_prod_util.h" |
17 #include "base/macros.h" | 9 #include "base/macros.h" |
18 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
19 #include "base/memory/weak_ptr.h" | 11 #include "base/memory/weak_ptr.h" |
20 #include "base/threading/thread_checker.h" | 12 #include "base/threading/thread_checker.h" |
21 #include "base/time/time.h" | 13 #include "base/time/time.h" |
22 #include "chrome/browser/android/data_usage/data_use_tab_model.h" | |
23 #include "components/data_usage/core/data_use_aggregator.h" | 14 #include "components/data_usage/core/data_use_aggregator.h" |
24 #include "net/base/network_change_notifier.h" | |
25 | |
26 #if defined(OS_ANDROID) | |
27 #include "base/android/application_status_listener.h" | |
28 #endif | |
29 | 15 |
30 namespace base { | 16 namespace base { |
31 class SingleThreadTaskRunner; | 17 class SingleThreadTaskRunner; |
32 } | 18 } |
33 | 19 |
34 namespace data_usage { | 20 namespace data_usage { |
35 struct DataUse; | 21 struct DataUse; |
36 } | 22 } |
37 | 23 |
38 namespace chrome { | 24 namespace chrome { |
39 | 25 |
40 namespace android { | 26 namespace android { |
41 | 27 |
| 28 class DataUseTabModel; |
42 class ExternalDataUseObserverBridge; | 29 class ExternalDataUseObserverBridge; |
| 30 class ExternalDataUseReporter; |
43 | 31 |
44 // This class allows platform APIs that are external to Chromium to observe how | 32 // This class allows platform APIs that are external to Chromium to observe how |
45 // much data is used by Chromium on the current Android device. This class | 33 // much data is used by Chromium on the current Android device. This class |
46 // registers as a data use observer with DataUseAggregator (as long as there is | 34 // registers as a data use observer with DataUseAggregator (as long as there is |
47 // at least one valid matching rule is present), filters the received | 35 // at least one valid matching rule is present), collects a batch of data |
48 // observations by applying the regex matching to the URLs of the requests, and | 36 // use observations and passes them to ExternalDataUseReporter for labeling the |
49 // notifies the filtered data use to the platform. This class is not thread | 37 // data usage and reporting to the platform. This class also fetches the |
50 // safe, and must only be accessed on IO thread. | 38 // matching rules from external platform APIs, on demand and periodically. This |
| 39 // class is not thread safe, and must only be accessed on IO thread. |
51 class ExternalDataUseObserver : public data_usage::DataUseAggregator::Observer { | 40 class ExternalDataUseObserver : public data_usage::DataUseAggregator::Observer { |
52 public: | 41 public: |
53 // Result of data usage report submission. This enum must remain synchronized | |
54 // with the enum of the same name in metrics/histograms/histograms.xml. | |
55 enum DataUsageReportSubmissionResult { | |
56 // Submission of data use report to the external observer was successful. | |
57 DATAUSAGE_REPORT_SUBMISSION_SUCCESSFUL = 0, | |
58 // Submission of data use report to the external observer returned error. | |
59 DATAUSAGE_REPORT_SUBMISSION_FAILED = 1, | |
60 // Submission of data use report to the external observer timed out. | |
61 DATAUSAGE_REPORT_SUBMISSION_TIMED_OUT = 2, | |
62 // Data use report was lost before an attempt was made to submit it. | |
63 DATAUSAGE_REPORT_SUBMISSION_LOST = 3, | |
64 DATAUSAGE_REPORT_SUBMISSION_MAX = 4 | |
65 }; | |
66 | |
67 // External data use observer field trial name. | 42 // External data use observer field trial name. |
68 static const char kExternalDataUseObserverFieldTrial[]; | 43 static const char kExternalDataUseObserverFieldTrial[]; |
69 | 44 |
70 ExternalDataUseObserver( | 45 ExternalDataUseObserver( |
71 data_usage::DataUseAggregator* data_use_aggregator, | 46 data_usage::DataUseAggregator* data_use_aggregator, |
72 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, | 47 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, |
73 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); | 48 const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner); |
74 ~ExternalDataUseObserver() override; | 49 ~ExternalDataUseObserver() override; |
75 | 50 |
76 // Returns the pointer to the DataUseTabModel object owned by |this|. The | 51 // Returns the pointer to the DataUseTabModel object owned by |this|. The |
77 // caller does not owns the returned pointer. | 52 // caller does not owns the returned pointer. |
78 DataUseTabModel* GetDataUseTabModel() const; | 53 DataUseTabModel* GetDataUseTabModel() const; |
79 | 54 |
80 // Called by ExternalDataUseObserverBridge::OnReportDataUseDone when a data | |
81 // use report has been submitted. |success| is true if the request was | |
82 // successfully submitted to the external data use observer by Java. | |
83 void OnReportDataUseDone(bool success); | |
84 | |
85 // Called by ExternalDataUseObserverBridge. |should_register| is true if | 55 // Called by ExternalDataUseObserverBridge. |should_register| is true if |
86 // |this| should register as a data use observer. | 56 // |this| should register as a data use observer. |
87 void ShouldRegisterAsDataUseObserver(bool should_register); | 57 void ShouldRegisterAsDataUseObserver(bool should_register); |
88 | 58 |
89 // Fetches the matching rules asynchronously. | 59 // Fetches the matching rules asynchronously. |
90 void FetchMatchingRules(); | 60 void FetchMatchingRules(); |
91 | 61 |
92 base::WeakPtr<ExternalDataUseObserver> GetWeakPtr(); | 62 base::WeakPtr<ExternalDataUseObserver> GetWeakPtr(); |
93 | 63 |
| 64 // Called by ExternalDataUseObserverBridge::OnReportDataUseDone when a data |
| 65 // use report has been submitted. |success| is true if the request was |
| 66 // successfully submitted to the external data use observer by Java. |
| 67 // TODO(rajendrant): Move this callback to ExternalDataUseReporter. In order |
| 68 // to move this, ExternalDataUseObserverBridge needs to hold a pointer to |
| 69 // ExternalDataUseReporter. This is currently not doable, since this creates |
| 70 // a circular dependency between ExternalDataUseReporter, DataUseTabModel and |
| 71 // ExternalDataUseObserverBridge, which creates issues during desctruction. |
| 72 void OnReportDataUseDone(bool success); |
| 73 |
| 74 ExternalDataUseReporter* GetExternalDataUseReporterForTesting() const { |
| 75 return external_data_use_reporter_; |
| 76 } |
| 77 |
94 private: | 78 private: |
95 friend class DataUseTabModelTest; | 79 friend class DataUseTabModelTest; |
96 friend class DataUseUITabModelTest; | 80 friend class DataUseUITabModelTest; |
97 friend class ExternalDataUseObserverTest; | 81 friend class ExternalDataUseObserverTest; |
98 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, BufferDataUseReports); | |
99 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, BufferSize); | |
100 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, DataUseReportTimedOut); | |
101 #if defined(OS_ANDROID) | |
102 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, | |
103 DataUseReportingOnApplicationStatusChange); | |
104 #endif | |
105 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, HashFunction); | |
106 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, | 82 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, |
107 MatchingRuleFetchOnControlAppInstall); | 83 MatchingRuleFetchOnControlAppInstall); |
108 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, MultipleMatchingRules); | |
109 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, | 84 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, |
110 PeriodicFetchMatchingRules); | 85 PeriodicFetchMatchingRules); |
111 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, | 86 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, |
112 RegisteredAsDataUseObserver); | 87 RegisteredAsDataUseObserver); |
113 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, ReportsMergedCorrectly); | 88 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, Variations); |
114 FRIEND_TEST_ALL_PREFIXES(DataUseUITabModelTest, ReportTabEventsTest); | 89 FRIEND_TEST_ALL_PREFIXES(DataUseUITabModelTest, ReportTabEventsTest); |
115 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, | |
116 TimestampsMergedCorrectly); | |
117 FRIEND_TEST_ALL_PREFIXES(ExternalDataUseObserverTest, Variations); | |
118 | |
119 // DataUseReportKey is a unique identifier for a data use report. | |
120 struct DataUseReportKey { | |
121 DataUseReportKey(const std::string& label, | |
122 const std::string& tag, | |
123 net::NetworkChangeNotifier::ConnectionType connection_type, | |
124 const std::string& mcc_mnc); | |
125 | |
126 DataUseReportKey(const DataUseReportKey& other); | |
127 | |
128 bool operator==(const DataUseReportKey& other) const; | |
129 | |
130 // Label provided by the matching rules. | |
131 const std::string label; | |
132 | |
133 // Tag to report for the data usage. | |
134 const std::string tag; | |
135 | |
136 // Type of network used by the request. | |
137 const net::NetworkChangeNotifier::ConnectionType connection_type; | |
138 | |
139 // mcc_mnc operator of the provider of the SIM as obtained from | |
140 // TelephonyManager#getNetworkOperator() Java API in Android. | |
141 const std::string mcc_mnc; | |
142 }; | |
143 | |
144 // DataUseReport is paired with a DataUseReportKey object. DataUseReport | |
145 // contains the bytes send/received during a specific interval. Only the bytes | |
146 // from the data use reports that have the |label|, |connection_type|, and | |
147 // |mcc_mnc| specified in the corresponding DataUseReportKey object are | |
148 // counted in the DataUseReport. | |
149 struct DataUseReport { | |
150 // |start_time| and |end_time| are the start and end timestamps (in UTC | |
151 // since the standard Java epoch of 1970-01-01 00:00:00) of the interval | |
152 // that this data report covers. |bytes_downloaded| and |bytes_uploaded| are | |
153 // the total bytes received and send during this interval. | |
154 DataUseReport(const base::Time& start_time, | |
155 const base::Time& end_time, | |
156 int64_t bytes_downloaded, | |
157 int64_t bytes_uploaded); | |
158 | |
159 // Start time of |this| data report (in UTC since the standard Java epoch of | |
160 // 1970-01-01 00:00:00). | |
161 const base::Time start_time; | |
162 | |
163 // End time of |this| data report (in UTC since the standard Java epoch of | |
164 // 1970-01-01 00:00:00) | |
165 const base::Time end_time; | |
166 | |
167 // Number of bytes downloaded and uploaded by Chromium from |start_time| to | |
168 // |end_time|. | |
169 const int64_t bytes_downloaded; | |
170 const int64_t bytes_uploaded; | |
171 }; | |
172 | |
173 // Class that implements hash operator on DataUseReportKey. | |
174 class DataUseReportKeyHash { | |
175 public: | |
176 // A simple heuristical hash function that satisifes the property that two | |
177 // equal data structures have the same hash value. | |
178 size_t operator()(const DataUseReportKey& k) const; | |
179 }; | |
180 | |
181 typedef base::hash_map<DataUseReportKey, DataUseReport, DataUseReportKeyHash> | |
182 DataUseReports; | |
183 | |
184 // Maximum buffer size. If an entry needs to be added to the buffer that has | |
185 // size |kMaxBufferSize|, then the oldest entry will be removed. | |
186 static const size_t kMaxBufferSize; | |
187 | 90 |
188 // data_usage::DataUseAggregator::Observer implementation: | 91 // data_usage::DataUseAggregator::Observer implementation: |
189 void OnDataUse(const data_usage::DataUse& data_use) override; | 92 void OnDataUse(const data_usage::DataUse& data_use) override; |
190 | 93 |
191 // Called by DataUseTabModel when tracking info has been retrieved for the | |
192 // |data_use| object. |tracking_info_valid| is true if |tracking_info| is | |
193 // populated that applies to the |data_use| object. |tracking_info| is owned | |
194 // by the caller. | |
195 void DataUseTrackingInfoRetrieved( | |
196 const data_usage::DataUse& data_use, | |
197 const base::Time& start_time, | |
198 const base::Time& end_time, | |
199 const DataUseTabModel::TrackingInfo* tracking_info, | |
200 bool tracking_info_valid); | |
201 | |
202 // Adds |data_use| to buffered reports. |data_use| is the data use report | |
203 // received from DataUseAggregator. |label| is a non-empty label that applies | |
204 // to |data_use|. |tag| is the tag to be applied for this data use. | |
205 // |start_time| and |end_time| are the start, and end times of the interval | |
206 // during which bytes reported in |data_use| went over the network. | |
207 void BufferDataUseReport(const data_usage::DataUse& data_use, | |
208 const std::string& label, | |
209 const std::string& tag, | |
210 const base::Time& start_time, | |
211 const base::Time& end_time); | |
212 | |
213 // Submits the first data report among the buffered data reports in | |
214 // |buffered_data_reports_|. Since an unordered map is used to buffer the | |
215 // reports, the order of reports may change. The reports are buffered in an | |
216 // arbitrary order and there are no guarantees that the next report to be | |
217 // submitted is the oldest one buffered. |immediate| indicates whether to | |
218 // submit the report immediately or to wait until |data_use_report_min_bytes_| | |
219 // unreported bytes are buffered. | |
220 void SubmitBufferedDataUseReport(bool immediate); | |
221 | |
222 #if defined(OS_ANDROID) | |
223 // Called whenever the application transitions from foreground to background | |
224 // or vice versa. | |
225 void OnApplicationStateChange(base::android::ApplicationState new_state); | |
226 #endif | |
227 | |
228 // Aggregator that sends data use observations to |this|. | 94 // Aggregator that sends data use observations to |this|. |
229 data_usage::DataUseAggregator* data_use_aggregator_; | 95 data_usage::DataUseAggregator* data_use_aggregator_; |
230 | 96 |
231 // |external_data_use_observer_bridge_| is owned by |this|, and interacts with | 97 // |external_data_use_observer_bridge_| is owned by |this|, and interacts with |
232 // the Java code. It is created on IO thread but afterwards, should only be | 98 // the Java code. It is created on IO thread but afterwards, should only be |
233 // accessed on UI thread. | 99 // accessed on UI thread. |
234 ExternalDataUseObserverBridge* external_data_use_observer_bridge_; | 100 ExternalDataUseObserverBridge* external_data_use_observer_bridge_; |
235 | 101 |
236 // Maintains tab sessions and is owned by |this|. It is created on IO thread | 102 // Maintains tab sessions and is owned by |this|. It is created on IO thread |
237 // but afterwards, should only be accessed on UI thread. | 103 // but afterwards, should only be accessed on UI thread. |
238 DataUseTabModel* data_use_tab_model_; | 104 DataUseTabModel* data_use_tab_model_; |
239 | 105 |
240 // Time when the currently pending data use report was submitted. | 106 // Labels, buffers and reports the data usage. It is owned by |this|. It is |
241 // |last_data_report_submitted_ticks_| is null if no data use report is | 107 // created on IO thread but afterwards, should only be accessed on UI thread. |
242 // currently pending. | 108 ExternalDataUseReporter* external_data_use_reporter_; |
243 base::TimeTicks last_data_report_submitted_ticks_; | |
244 | |
245 // |pending_report_bytes_| is the total byte count in the data use report that | |
246 // is currently pending. | |
247 int64_t pending_report_bytes_; | |
248 | |
249 // Buffered data reports that need to be submitted to the | |
250 // |external_data_use_observer_bridge_|. | |
251 DataUseReports buffered_data_reports_; | |
252 | 109 |
253 // |ui_task_runner_| is used to call methods on UI thread. | 110 // |ui_task_runner_| is used to call methods on UI thread. |
254 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; | 111 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_; |
255 | 112 |
256 // Time when the data use reports were last received from DataUseAggregator. | |
257 base::Time previous_report_time_; | |
258 | |
259 // Time when the matching rules were last fetched. | 113 // Time when the matching rules were last fetched. |
260 base::TimeTicks last_matching_rules_fetch_time_; | 114 base::TimeTicks last_matching_rules_fetch_time_; |
261 | 115 |
262 // Total number of bytes transmitted or received across all the buffered | |
263 // reports. | |
264 int64_t total_bytes_buffered_; | |
265 | |
266 // Duration after which matching rules are periodically fetched. | 116 // Duration after which matching rules are periodically fetched. |
267 const base::TimeDelta fetch_matching_rules_duration_; | 117 const base::TimeDelta fetch_matching_rules_duration_; |
268 | 118 |
269 // Minimum number of bytes that should be buffered before a data use report is | |
270 // submitted. | |
271 const int64_t data_use_report_min_bytes_; | |
272 | |
273 // If a data use report is pending for more than |data_report_submit_timeout_| | |
274 // duration, it is considered as timed out. | |
275 const base::TimeDelta data_report_submit_timeout_; | |
276 | |
277 #if defined(OS_ANDROID) | |
278 // Listens to when Chromium gets backgrounded and submits buffered data use | |
279 // reports. | |
280 std::unique_ptr<base::android::ApplicationStatusListener> app_state_listener_; | |
281 #endif | |
282 | |
283 // True if |this| is currently registered as a data use observer. | 119 // True if |this| is currently registered as a data use observer. |
284 bool registered_as_data_use_observer_; | 120 bool registered_as_data_use_observer_; |
285 | 121 |
286 base::ThreadChecker thread_checker_; | 122 base::ThreadChecker thread_checker_; |
287 | 123 |
288 base::WeakPtrFactory<ExternalDataUseObserver> weak_factory_; | 124 base::WeakPtrFactory<ExternalDataUseObserver> weak_factory_; |
289 | 125 |
290 DISALLOW_COPY_AND_ASSIGN(ExternalDataUseObserver); | 126 DISALLOW_COPY_AND_ASSIGN(ExternalDataUseObserver); |
291 }; | 127 }; |
292 | 128 |
293 } // namespace android | 129 } // namespace android |
294 | 130 |
295 } // namespace chrome | 131 } // namespace chrome |
296 | 132 |
297 #endif // CHROME_BROWSER_ANDROID_DATA_USAGE_EXTERNAL_DATA_USE_OBSERVER_H_ | 133 #endif // CHROME_BROWSER_ANDROID_DATA_USAGE_EXTERNAL_DATA_USE_OBSERVER_H_ |
OLD | NEW |