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

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

Issue 1406003005: Rename chrome/browser/android/datausage to data_usage (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 1 month 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/android/datausage/external_data_use_observer.h"
6
7 #include <utility>
8
9 #include "base/android/jni_string.h"
10 #include "base/message_loop/message_loop.h"
11 #include "components/data_usage/core/data_use.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "jni/ExternalDataUseObserver_jni.h"
14 #include "third_party/re2/re2/re2.h"
15 #include "url/gurl.h"
16
17 using base::android::ConvertUTF8ToJavaString;
18 using base::android::ToJavaArrayOfStrings;
19
20 namespace chrome {
21
22 namespace android {
23
24 ExternalDataUseObserver::ExternalDataUseObserver(
25 data_usage::DataUseAggregator* data_use_aggregator,
26 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
27 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
28 : data_use_aggregator_(data_use_aggregator),
29 matching_rules_fetch_pending_(false),
30 submit_data_report_pending_(false),
31 registered_as_observer_(false),
32 io_task_runner_(io_task_runner),
33 ui_task_runner_(ui_task_runner),
34 previous_report_time_(base::Time::Now()),
35 io_weak_factory_(this),
36 ui_weak_factory_(this) {
37 DCHECK(data_use_aggregator_);
38 DCHECK(io_task_runner_);
39 DCHECK(ui_task_runner_);
40 ui_task_runner_->PostTask(
41 FROM_HERE,
42 base::Bind(&ExternalDataUseObserver::CreateJavaObjectOnUIThread,
43 GetUIWeakPtr()));
44
45 ui_task_runner_->PostTask(
46 FROM_HERE,
47 base::Bind(&ExternalDataUseObserver::FetchMatchingRulesOnUIThread,
48 GetUIWeakPtr()));
49
50 matching_rules_fetch_pending_ = true;
51 data_use_aggregator_->AddObserver(this);
52 registered_as_observer_ = true;
53 }
54
55 void ExternalDataUseObserver::CreateJavaObjectOnUIThread() {
56 DCHECK(ui_task_runner_->BelongsToCurrentThread());
57 JNIEnv* env = base::android::AttachCurrentThread();
58 j_external_data_use_observer_.Reset(Java_ExternalDataUseObserver_create(
59 env, base::android::GetApplicationContext(),
60 reinterpret_cast<intptr_t>(this)));
61 DCHECK(!j_external_data_use_observer_.is_null());
62 }
63
64 ExternalDataUseObserver::~ExternalDataUseObserver() {
65 DCHECK(thread_checker_.CalledOnValidThread());
66
67 JNIEnv* env = base::android::AttachCurrentThread();
68 if (!j_external_data_use_observer_.is_null()) {
69 Java_ExternalDataUseObserver_onDestroy(env,
70 j_external_data_use_observer_.obj());
71 }
72 if (registered_as_observer_)
73 data_use_aggregator_->RemoveObserver(this);
74 }
75
76 void ExternalDataUseObserver::FetchMatchingRulesOnUIThread() const {
77 DCHECK(ui_task_runner_->BelongsToCurrentThread());
78 DCHECK(!j_external_data_use_observer_.is_null());
79 JNIEnv* env = base::android::AttachCurrentThread();
80 Java_ExternalDataUseObserver_fetchMatchingRules(
81 env, j_external_data_use_observer_.obj());
82 }
83
84 void ExternalDataUseObserver::FetchMatchingRulesCallback(
85 JNIEnv* env,
86 jobject obj,
87 const base::android::JavaParamRef<jobjectArray>& app_package_name,
88 const base::android::JavaParamRef<jobjectArray>& domain_path_regex,
89 const base::android::JavaParamRef<jobjectArray>& label) {
90 DCHECK(ui_task_runner_->BelongsToCurrentThread());
91 // Convert to native objects.
92 std::vector<std::string> app_package_name_native;
93 std::vector<std::string> domain_path_regex_native;
94 std::vector<std::string> label_native;
95
96 if (app_package_name && domain_path_regex && label) {
97 base::android::AppendJavaStringArrayToStringVector(
98 env, app_package_name, &app_package_name_native);
99 base::android::AppendJavaStringArrayToStringVector(
100 env, domain_path_regex, &domain_path_regex_native);
101 base::android::AppendJavaStringArrayToStringVector(env, label,
102 &label_native);
103 }
104
105 io_task_runner_->PostTask(
106 FROM_HERE,
107 base::Bind(&ExternalDataUseObserver::FetchMatchingRulesCallbackOnIOThread,
108 GetIOWeakPtr(), app_package_name_native,
109 domain_path_regex_native, label_native));
110 }
111
112 void ExternalDataUseObserver::FetchMatchingRulesCallbackOnIOThread(
113 const std::vector<std::string>& app_package_name,
114 const std::vector<std::string>& domain_path_regex,
115 const std::vector<std::string>& label) {
116 DCHECK(thread_checker_.CalledOnValidThread());
117
118 RegisterURLRegexes(app_package_name, domain_path_regex, label);
119 matching_rules_fetch_pending_ = false;
120 // Process buffered reports.
121 }
122
123 void ExternalDataUseObserver::OnReportDataUseDone(JNIEnv* env,
124 jobject obj,
125 bool success) {
126 DCHECK(ui_task_runner_->BelongsToCurrentThread());
127 io_task_runner_->PostTask(
128 FROM_HERE,
129 base::Bind(&ExternalDataUseObserver::OnReportDataUseDoneOnIOThread,
130 GetIOWeakPtr(), success));
131 }
132
133 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetIOWeakPtr() {
134 return io_weak_factory_.GetWeakPtr();
135 }
136
137 base::WeakPtr<ExternalDataUseObserver> ExternalDataUseObserver::GetUIWeakPtr() {
138 return ui_weak_factory_.GetWeakPtr();
139 }
140
141 void ExternalDataUseObserver::OnReportDataUseDoneOnIOThread(bool success) {
142 DCHECK(thread_checker_.CalledOnValidThread());
143 DCHECK(!buffered_data_reports_.empty());
144 DCHECK(submit_data_report_pending_);
145
146 // TODO(tbansal): If not successful, record UMA.
147
148 submit_data_report_pending_ = false;
149
150 SubmitBufferedDataUseReport();
151 }
152
153 void ExternalDataUseObserver::OnDataUse(
154 const std::vector<const data_usage::DataUse*>& data_use_sequence) {
155 DCHECK(thread_checker_.CalledOnValidThread());
156
157 if (matching_rules_fetch_pending_) {
158 // TODO(tbansal): Buffer reports.
159 }
160
161 std::string label;
162
163 for (const data_usage::DataUse* data_use : data_use_sequence) {
164 if (!Matches(data_use->url, &label))
165 continue;
166
167 BufferDataUseReport(data_use, label, previous_report_time_,
168 base::Time::Now());
169 }
170 previous_report_time_ = base::Time::Now();
171
172 // TODO(tbansal): Post SubmitBufferedDataUseReport on IO thread once the
173 // task runners are plumbed in.
174 SubmitBufferedDataUseReport();
175 }
176
177 void ExternalDataUseObserver::BufferDataUseReport(
178 const data_usage::DataUse* data_use,
179 const std::string& label,
180 const base::Time& start_time,
181 const base::Time& end_time) {
182 DCHECK(thread_checker_.CalledOnValidThread());
183 DCHECK(!label.empty());
184 DCHECK_LE(0, data_use->rx_bytes);
185 DCHECK_LE(0, data_use->tx_bytes);
186 if (data_use->rx_bytes < 0 || data_use->tx_bytes < 0)
187 return;
188
189 DataUseReportKey data_use_report_key =
190 DataUseReportKey(label, data_use->connection_type, data_use->mcc_mnc);
191
192 DataUseReport report = DataUseReport(start_time, end_time, data_use->rx_bytes,
193 data_use->tx_bytes);
194
195 // Check if the |data_use_report_key| is already in the buffered reports.
196 DataUseReports::iterator it =
197 buffered_data_reports_.find(data_use_report_key);
198 if (it == buffered_data_reports_.end()) {
199 // Limit the buffer size.
200 if (buffered_data_reports_.size() == kMaxBufferSize) {
201 // TODO(tbansal): Add UMA to track impact of lost reports.
202 // Remove the first entry.
203 buffered_data_reports_.erase(buffered_data_reports_.begin());
204 }
205 buffered_data_reports_.insert(std::make_pair(data_use_report_key, report));
206 } else {
207 DataUseReport existing_report = DataUseReport(it->second);
208 DataUseReport merged_report = DataUseReport(
209 std::min(existing_report.start_time, report.start_time),
210 std::max(existing_report.end_time, report.end_time),
211 existing_report.bytes_downloaded + report.bytes_downloaded,
212 existing_report.bytes_uploaded + report.bytes_uploaded);
213 buffered_data_reports_.erase(it);
214 buffered_data_reports_.insert(
215 std::make_pair(data_use_report_key, merged_report));
216 }
217
218 DCHECK_LE(buffered_data_reports_.size(),
219 static_cast<size_t>(kMaxBufferSize));
220 }
221
222 void ExternalDataUseObserver::SubmitBufferedDataUseReport() {
223 DCHECK(thread_checker_.CalledOnValidThread());
224
225 if (submit_data_report_pending_ || buffered_data_reports_.empty())
226 return;
227
228 // TODO(tbansal): Keep buffering until enough data has been received.
229
230 // Send one data use report.
231 DataUseReports::iterator it = buffered_data_reports_.begin();
232 DataUseReportKey key = it->first;
233 DataUseReport report = it->second;
234
235 // Remove the entry from the map.
236 buffered_data_reports_.erase(it);
237
238 submit_data_report_pending_ = true;
239
240 ui_task_runner_->PostTask(
241 FROM_HERE, base::Bind(&ExternalDataUseObserver::ReportDataUseOnUIThread,
242 GetIOWeakPtr(), key, report));
243 }
244
245 void ExternalDataUseObserver::ReportDataUseOnUIThread(
246 const DataUseReportKey& key,
247 const DataUseReport& report) const {
248 DCHECK(ui_task_runner_->BelongsToCurrentThread());
249 JNIEnv* env = base::android::AttachCurrentThread();
250 DCHECK(!j_external_data_use_observer_.is_null());
251
252 // End time should be greater than start time.
253 int64_t start_time_milliseconds = report.start_time.ToJavaTime();
254 int64_t end_time_milliseconds = report.end_time.ToJavaTime();
255 if (start_time_milliseconds >= end_time_milliseconds)
256 start_time_milliseconds = end_time_milliseconds - 1;
257
258 Java_ExternalDataUseObserver_reportDataUse(
259 env, j_external_data_use_observer_.obj(),
260 ConvertUTF8ToJavaString(env, key.label).obj(), key.connection_type,
261 ConvertUTF8ToJavaString(env, key.mcc_mnc).obj(), start_time_milliseconds,
262 end_time_milliseconds, report.bytes_downloaded, report.bytes_uploaded);
263 }
264
265 void ExternalDataUseObserver::RegisterURLRegexes(
266 const std::vector<std::string>& app_package_name,
267 const std::vector<std::string>& domain_path_regex,
268 const std::vector<std::string>& label) {
269 DCHECK(thread_checker_.CalledOnValidThread());
270 DCHECK_EQ(app_package_name.size(), domain_path_regex.size());
271 DCHECK_EQ(app_package_name.size(), label.size());
272
273 matching_rules_.clear();
274 re2::RE2::Options options(re2::RE2::DefaultOptions);
275 options.set_case_sensitive(false);
276
277 for (size_t i = 0; i < domain_path_regex.size(); ++i) {
278 const std::string& url_regex = domain_path_regex[i];
279 if (url_regex.empty())
280 continue;
281 scoped_ptr<re2::RE2> pattern(new re2::RE2(url_regex, options));
282 if (!pattern->ok())
283 continue;
284 DCHECK(!label[i].empty());
285 matching_rules_.push_back(
286 new MatchingRule(app_package_name[i], pattern.Pass(), label[i]));
287 }
288
289 if (matching_rules_.size() == 0 && registered_as_observer_) {
290 // Unregister as an observer if no regular expressions were received.
291 data_use_aggregator_->RemoveObserver(this);
292 registered_as_observer_ = false;
293 } else if (matching_rules_.size() > 0 && !registered_as_observer_) {
294 // Register as an observer if regular expressions were received.
295 data_use_aggregator_->AddObserver(this);
296 registered_as_observer_ = true;
297 }
298 }
299
300 bool ExternalDataUseObserver::Matches(const GURL& gurl,
301 std::string* label) const {
302 DCHECK(thread_checker_.CalledOnValidThread());
303 *label = "";
304
305 if (!gurl.is_valid() || gurl.is_empty())
306 return false;
307
308 for (size_t i = 0; i < matching_rules_.size(); ++i) {
309 const re2::RE2* pattern = matching_rules_[i]->pattern();
310 if (re2::RE2::FullMatch(gurl.spec(), *pattern)) {
311 *label = matching_rules_[i]->label();
312 return true;
313 }
314 }
315
316 return false;
317 }
318
319 ExternalDataUseObserver::MatchingRule::MatchingRule(
320 const std::string& app_package_name,
321 scoped_ptr<re2::RE2> pattern,
322 const std::string& label)
323 : app_package_name_(app_package_name),
324 pattern_(pattern.Pass()),
325 label_(label) {}
326
327 ExternalDataUseObserver::MatchingRule::~MatchingRule() {}
328
329 const re2::RE2* ExternalDataUseObserver::MatchingRule::pattern() const {
330 return pattern_.get();
331 }
332
333 const std::string& ExternalDataUseObserver::MatchingRule::label() const {
334 return label_;
335 }
336
337 bool RegisterExternalDataUseObserver(JNIEnv* env) {
338 return RegisterNativesImpl(env);
339 }
340
341 } // namespace android
342
343 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698