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

Side by Side Diff: chrome/browser/android/datausage/external_data_use_observer_unittest.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 <string>
8 #include <vector>
9
10 #include "base/memory/scoped_ptr.h"
11 #include "base/memory/scoped_vector.h"
12 #include "base/run_loop.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/thread_task_runner_handle.h"
15 #include "components/data_usage/core/data_use.h"
16 #include "components/data_usage/core/data_use_aggregator.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/test/test_browser_thread_bundle.h"
19 #include "net/base/network_change_notifier.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "url/gurl.h"
22
23 namespace chrome {
24
25 namespace android {
26
27 class ExternalDataUseObserverTest : public testing::Test {
28 public:
29 void SetUp() override {
30 thread_bundle_.reset(new content::TestBrowserThreadBundle(
31 content::TestBrowserThreadBundle::REAL_IO_THREAD));
32 io_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
33 content::BrowserThread::IO);
34 ui_task_runner_ = content::BrowserThread::GetMessageLoopProxyForThread(
35 content::BrowserThread::UI);
36 data_use_aggregator_.reset(new data_usage::DataUseAggregator());
37 external_data_use_observer_.reset(new ExternalDataUseObserver(
38 data_use_aggregator_.get(), io_task_runner_.get(),
39 ui_task_runner_.get()));
40 }
41
42 ExternalDataUseObserver* external_data_use_observer() const {
43 return external_data_use_observer_.get();
44 }
45
46 private:
47 // Required for creating multiple threads for unit testing.
48 scoped_ptr<content::TestBrowserThreadBundle> thread_bundle_;
49 scoped_ptr<data_usage::DataUseAggregator> data_use_aggregator_;
50 scoped_ptr<ExternalDataUseObserver> external_data_use_observer_;
51 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
52 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
53 };
54
55 TEST_F(ExternalDataUseObserverTest, SingleRegex) {
56 const struct {
57 std::string url;
58 std::string regex;
59 bool expect_match;
60 } tests[] = {
61 {"http://www.google.com", "http://www.google.com/", true},
62 {"http://www.Google.com", "http://www.google.com/", true},
63 {"http://www.googleacom", "http://www.google.com/", true},
64 {"http://www.googleaacom", "http://www.google.com/", false},
65 {"http://www.google.com", "https://www.google.com/", false},
66 {"http://www.google.com", "{http|https}://www[.]google[.]com/search.*",
67 false},
68 {"https://www.google.com/search=test",
69 "https://www[.]google[.]com/search.*", true},
70 {"https://www.googleacom/search=test",
71 "https://www[.]google[.]com/search.*", false},
72 {"https://www.google.com/Search=test",
73 "https://www[.]google[.]com/search.*", true},
74 {"www.google.com", "http://www.google.com", false},
75 {"www.google.com:80", "http://www.google.com", false},
76 {"http://www.google.com:80", "http://www.google.com", false},
77 {"http://www.google.com:80/", "http://www.google.com/", true},
78 {"", "http://www.google.com", false},
79 {"", "", false},
80 {"https://www.google.com", "http://www.google.com", false},
81 };
82
83 std::string label("test");
84 for (size_t i = 0; i < arraysize(tests); ++i) {
85 external_data_use_observer()->RegisterURLRegexes(
86 std::vector<std::string>(1, std::string()),
87 std::vector<std::string>(1, tests[i].regex),
88 std::vector<std::string>(1, "label"));
89 EXPECT_EQ(tests[i].expect_match,
90 external_data_use_observer()->Matches(GURL(tests[i].url), &label))
91 << i;
92
93 // Verify label matches the expected label.
94 std::string expected_label = "";
95 if (tests[i].expect_match)
96 expected_label = "label";
97
98 EXPECT_EQ(expected_label, label);
99 }
100 }
101
102 TEST_F(ExternalDataUseObserverTest, TwoRegex) {
103 const struct {
104 std::string url;
105 std::string regex1;
106 std::string regex2;
107 bool expect_match;
108 } tests[] = {
109 {"http://www.google.com", "http://www.google.com/",
110 "https://www.google.com/", true},
111 {"http://www.googleacom", "http://www.google.com/",
112 "http://www.google.com/", true},
113 {"https://www.google.com", "http://www.google.com/",
114 "https://www.google.com/", true},
115 {"https://www.googleacom", "http://www.google.com/",
116 "https://www.google.com/", true},
117 {"http://www.google.com", "{http|https}://www[.]google[.]com/search.*",
118 "", false},
119 {"http://www.google.com/search=test",
120 "http://www[.]google[.]com/search.*",
121 "https://www[.]google[.]com/search.*", true},
122 {"https://www.google.com/search=test",
123 "http://www[.]google[.]com/search.*",
124 "https://www[.]google[.]com/search.*", true},
125 {"http://google.com/search=test", "http://www[.]google[.]com/search.*",
126 "https://www[.]google[.]com/search.*", false},
127 {"https://www.googleacom/search=test", "",
128 "https://www[.]google[.]com/search.*", false},
129 {"https://www.google.com/Search=test", "",
130 "https://www[.]google[.]com/search.*", true},
131 {"www.google.com", "http://www.google.com", "", false},
132 {"www.google.com:80", "http://www.google.com", "", false},
133 {"http://www.google.com:80", "http://www.google.com", "", false},
134 {"", "http://www.google.com", "", false},
135 {"https://www.google.com", "http://www.google.com", "", false},
136 };
137
138 std::string label;
139 for (size_t i = 0; i < arraysize(tests); ++i) {
140 std::vector<std::string> url_regexes;
141 url_regexes.push_back(tests[i].regex1 + "|" + tests[i].regex2);
142 external_data_use_observer()->RegisterURLRegexes(
143 std::vector<std::string>(url_regexes.size(), std::string()),
144 url_regexes, std::vector<std::string>(url_regexes.size(), "label"));
145 EXPECT_EQ(tests[i].expect_match,
146 external_data_use_observer()->Matches(GURL(tests[i].url), &label))
147 << i;
148 }
149 }
150
151 TEST_F(ExternalDataUseObserverTest, MultipleRegex) {
152 std::vector<std::string> url_regexes;
153 url_regexes.push_back(
154 "https?://www[.]google[.]com/#q=.*|https?://www[.]google[.]com[.]ph/"
155 "#q=.*|https?://www[.]google[.]com[.]ph/[?]gws_rd=ssl#q=.*");
156 external_data_use_observer()->RegisterURLRegexes(
157 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
158 std::vector<std::string>(url_regexes.size(), "label"));
159
160 const struct {
161 std::string url;
162 bool expect_match;
163 } tests[] = {
164 {"", false},
165 {"http://www.google.com", false},
166 {"http://www.googleacom", false},
167 {"https://www.google.com", false},
168 {"https://www.googleacom", false},
169 {"https://www.google.com", false},
170 {"quic://www.google.com/q=test", false},
171 {"http://www.google.com/q=test", false},
172 {"http://www.google.com/.q=test", false},
173 {"http://www.google.com/#q=test", true},
174 {"https://www.google.com/#q=test", true},
175 {"https://www.google.com.ph/#q=test+abc", true},
176 {"https://www.google.com.ph/?gws_rd=ssl#q=test+abc", true},
177 {"http://www.google.com.ph/#q=test", true},
178 {"https://www.google.com.ph/#q=test", true},
179 {"http://www.google.co.in/#q=test", false},
180 {"http://google.com/#q=test", false},
181 {"https://www.googleacom/#q=test", false},
182 {"https://www.google.com/#Q=test", true}, // case in-sensitive
183 {"www.google.com/#q=test", false},
184 {"www.google.com:80/#q=test", false},
185 {"http://www.google.com:80/#q=test", true},
186 {"http://www.google.com:80/search?=test", false},
187 };
188
189 std::string label;
190 for (size_t i = 0; i < arraysize(tests); ++i) {
191 EXPECT_EQ(tests[i].expect_match,
192 external_data_use_observer()->Matches(GURL(tests[i].url), &label))
193 << i << " " << tests[i].url;
194 }
195 }
196
197 TEST_F(ExternalDataUseObserverTest, ChangeRegex) {
198 std::string label;
199 // When no regex is specified, the URL match should fail.
200 EXPECT_FALSE(external_data_use_observer()->Matches(GURL(""), &label));
201 EXPECT_FALSE(external_data_use_observer()->Matches(
202 GURL("http://www.google.com"), &label));
203
204 std::vector<std::string> url_regexes;
205 url_regexes.push_back("http://www[.]google[.]com/#q=.*");
206 url_regexes.push_back("https://www[.]google[.]com/#q=.*");
207 external_data_use_observer()->RegisterURLRegexes(
208 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
209 std::vector<std::string>(url_regexes.size(), "label"));
210
211 EXPECT_FALSE(external_data_use_observer()->Matches(GURL(""), &label));
212 EXPECT_TRUE(external_data_use_observer()->Matches(
213 GURL("http://www.google.com#q=abc"), &label));
214 EXPECT_FALSE(external_data_use_observer()->Matches(
215 GURL("http://www.google.co.in#q=abc"), &label));
216
217 // Change the regular expressions to verify that the new regexes replace
218 // the ones specified before.
219 url_regexes.clear();
220 url_regexes.push_back("http://www[.]google[.]co[.]in/#q=.*");
221 url_regexes.push_back("https://www[.]google[.]co[.]in/#q=.*");
222 external_data_use_observer()->RegisterURLRegexes(
223 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
224 std::vector<std::string>(url_regexes.size(), "label"));
225 EXPECT_FALSE(external_data_use_observer()->Matches(GURL(""), &label));
226 EXPECT_FALSE(external_data_use_observer()->Matches(
227 GURL("http://www.google.com#q=abc"), &label));
228 EXPECT_TRUE(external_data_use_observer()->Matches(
229 GURL("http://www.google.co.in#q=abc"), &label));
230 }
231
232 // Tests that at most one data use request is submitted.
233 TEST_F(ExternalDataUseObserverTest, AtMostOneDataUseSubmitRequest) {
234 const std::string label("label");
235
236 std::vector<std::string> url_regexes;
237 url_regexes.push_back(
238 "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*");
239
240 external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread(
241 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
242 std::vector<std::string>(url_regexes.size(), label));
243 EXPECT_EQ(0U, external_data_use_observer()->buffered_data_reports_.size());
244 EXPECT_FALSE(external_data_use_observer()->submit_data_report_pending_);
245 EXPECT_FALSE(external_data_use_observer()->matching_rules_fetch_pending_);
246
247 std::vector<const data_usage::DataUse*> data_use_sequence;
248 data_usage::DataUse data_use_foo(
249 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
250 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1, 2);
251 data_use_sequence.push_back(&data_use_foo);
252 data_usage::DataUse data_use_bar(
253 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
254 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_bar", 1, 2);
255 data_use_sequence.push_back(&data_use_bar);
256 external_data_use_observer()->OnDataUse(data_use_sequence);
257
258 EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size());
259 EXPECT_TRUE(external_data_use_observer()->submit_data_report_pending_);
260 }
261
262 // Verifies that buffer size does not exceed the specified limit.
263 TEST_F(ExternalDataUseObserverTest, BufferSize) {
264 const std::string label("label");
265
266 std::vector<std::string> url_regexes;
267 url_regexes.push_back(
268 "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*");
269
270 external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread(
271 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
272 std::vector<std::string>(url_regexes.size(), label));
273
274 const size_t max_buffer_size = ExternalDataUseObserver::kMaxBufferSize;
275
276 ScopedVector<data_usage::DataUse> data_use_vector;
277 // Push more entries than the buffer size. Buffer size should not be exceeded.
278 for (size_t i = 0; i < max_buffer_size * 5; ++i) {
279 scoped_ptr<data_usage::DataUse> data_use(new data_usage::DataUse(
280 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
281 net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
282 "mccmnc" + base::Int64ToString(i), 0, 0));
283 data_use_vector.push_back(data_use.Pass());
284 }
285
286 std::vector<const data_usage::DataUse*> const_sequence(
287 data_use_vector.begin(), data_use_vector.end());
288
289 external_data_use_observer()->OnDataUse(const_sequence);
290 // One report will be consumed.
291 EXPECT_EQ(max_buffer_size - 1,
292 external_data_use_observer()->buffered_data_reports_.size());
293
294 // Verify the label of the data use report.
295 for (const auto& it : external_data_use_observer()->buffered_data_reports_)
296 EXPECT_EQ(label, it.first.label);
297 }
298
299 // Tests that buffered data use reports are merged correctly.
300 TEST_F(ExternalDataUseObserverTest, ReportsMergedCorrectly) {
301 const std::string label("label");
302
303 std::vector<std::string> url_regexes;
304 url_regexes.push_back(
305 "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*");
306
307 external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread(
308 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
309 std::vector<std::string>(url_regexes.size(), label));
310
311 const size_t num_iterations = ExternalDataUseObserver::kMaxBufferSize * 5;
312
313 ScopedVector<data_usage::DataUse> data_use_vector;
314 for (size_t i = 0; i < num_iterations; ++i) {
315 scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse(
316 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
317 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1, 2));
318 data_use_vector.push_back(data_use_foo.Pass());
319
320 scoped_ptr<data_usage::DataUse> data_use_bar(new data_usage::DataUse(
321 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
322 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_bar", 1, 2));
323 data_use_vector.push_back(data_use_bar.Pass());
324
325 scoped_ptr<data_usage::DataUse> data_use_baz(new data_usage::DataUse(
326 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
327 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_baz", 1, 2));
328 data_use_vector.push_back(data_use_baz.Pass());
329 }
330
331 std::vector<const data_usage::DataUse*> const_sequence(
332 data_use_vector.begin(), data_use_vector.end());
333
334 external_data_use_observer()->OnDataUse(const_sequence);
335
336 EXPECT_EQ(2U, external_data_use_observer()->buffered_data_reports_.size());
337 EXPECT_EQ(static_cast<int64_t>(num_iterations * 2),
338 external_data_use_observer()
339 ->buffered_data_reports_.begin()
340 ->second.bytes_downloaded);
341 EXPECT_EQ(static_cast<int64_t>(num_iterations * 1),
342 external_data_use_observer()
343 ->buffered_data_reports_.begin()
344 ->second.bytes_uploaded);
345
346 // Delete the first entry and verify the next entry.
347 external_data_use_observer()->buffered_data_reports_.erase(
348 external_data_use_observer()->buffered_data_reports_.begin());
349 EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size());
350 EXPECT_EQ(static_cast<int64_t>(num_iterations * 2),
351 external_data_use_observer()
352 ->buffered_data_reports_.begin()
353 ->second.bytes_downloaded);
354 EXPECT_EQ(static_cast<int64_t>(num_iterations * 1),
355 external_data_use_observer()
356 ->buffered_data_reports_.begin()
357 ->second.bytes_uploaded);
358 }
359
360 // Tests that timestamps of merged reports is correct.
361 TEST_F(ExternalDataUseObserverTest, TimestampsMergedCorrectly) {
362 const std::string label("label");
363
364 std::vector<std::string> url_regexes;
365 url_regexes.push_back(
366 "http://www[.]google[.]com/#q=.*|https://www[.]google[.]com/#q=.*");
367
368 external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread(
369 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
370 std::vector<std::string>(url_regexes.size(), label));
371
372 const size_t num_iterations = ExternalDataUseObserver::kMaxBufferSize * 5;
373
374 ScopedVector<data_usage::DataUse> data_use_vector;
375 for (size_t i = 0; i < num_iterations; ++i) {
376 scoped_ptr<data_usage::DataUse> data_use_foo(new data_usage::DataUse(
377 GURL("http://www.google.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
378 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_foo", 1, 2));
379 data_use_vector.push_back(data_use_foo.Pass());
380 }
381
382 std::vector<const data_usage::DataUse*> const_sequence(
383 data_use_vector.begin(), data_use_vector.end());
384
385 int64_t start_timestamp = 0;
386 int64_t end_timestamp = 1;
387 for (auto it : const_sequence) {
388 const data_usage::DataUse* data_usage(it);
389 external_data_use_observer()->BufferDataUseReport(
390 data_usage, "foo_label", base::Time::FromDoubleT(start_timestamp++),
391 base::Time::FromDoubleT(end_timestamp++));
392 }
393 EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size());
394 EXPECT_EQ(0, external_data_use_observer()
395 ->buffered_data_reports_.begin()
396 ->second.start_time.ToJavaTime());
397 // Convert from seconds to milliseconds.
398 EXPECT_EQ(static_cast<int64_t>(num_iterations * 1000),
399 external_data_use_observer()
400 ->buffered_data_reports_.begin()
401 ->second.end_time.ToJavaTime());
402 }
403
404 // Tests the behavior when multiple matching rules are available.
405 TEST_F(ExternalDataUseObserverTest, MultipleMatchingRules) {
406 std::vector<std::string> url_regexes;
407 url_regexes.push_back(
408 "http://www[.]foo[.]com/#q=.*|https://www[.]foo[.]com/#q=.*");
409 url_regexes.push_back(
410 "http://www[.]bar[.]com/#q=.*|https://www[.]bar[.]com/#q=.*");
411
412 std::vector<std::string> labels;
413 const std::string label_foo("label_foo");
414 const std::string label_bar("label_bar");
415 labels.push_back(label_foo);
416 labels.push_back(label_bar);
417
418 external_data_use_observer()->FetchMatchingRulesCallbackOnIOThread(
419 std::vector<std::string>(url_regexes.size(), std::string()), url_regexes,
420 labels);
421 EXPECT_EQ(0U, external_data_use_observer()->buffered_data_reports_.size());
422 EXPECT_FALSE(external_data_use_observer()->submit_data_report_pending_);
423 EXPECT_FALSE(external_data_use_observer()->matching_rules_fetch_pending_);
424
425 // Check |label_foo| matching rule.
426 std::vector<const data_usage::DataUse*> data_use_sequence;
427 data_usage::DataUse data_foo_1(
428 GURL("http://www.foo.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
429 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_1", 0, 0);
430 data_usage::DataUse data_foo_2(
431 GURL("http://www.foo.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
432 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc_2", 0, 0);
433 data_use_sequence.push_back(&data_foo_1);
434 data_use_sequence.push_back(&data_foo_2);
435 external_data_use_observer()->OnDataUse(data_use_sequence);
436
437 EXPECT_EQ(1U, external_data_use_observer()->buffered_data_reports_.size());
438 EXPECT_TRUE(external_data_use_observer()->submit_data_report_pending_);
439
440 // Verify the label of the data use report.
441 EXPECT_EQ(label_foo, external_data_use_observer()
442 ->buffered_data_reports_.begin()
443 ->first.label);
444 EXPECT_EQ("mccmnc_1", external_data_use_observer()
445 ->buffered_data_reports_.begin()
446 ->first.mcc_mnc);
447
448 // Clear the state.
449 external_data_use_observer()->buffered_data_reports_.clear();
450 data_use_sequence.clear();
451
452 // Check |label_bar| matching rule.
453 data_usage::DataUse data_bar(
454 GURL("http://www.bar.com/#q=abc"), base::TimeTicks::Now(), GURL(), 0,
455 net::NetworkChangeNotifier::CONNECTION_UNKNOWN, "mccmnc", 0, 0);
456 data_use_sequence.push_back(&data_bar);
457 external_data_use_observer()->OnDataUse(data_use_sequence);
458 for (const auto& it : external_data_use_observer()->buffered_data_reports_) {
459 EXPECT_EQ(label_bar, it.first.label);
460 EXPECT_EQ("mccmnc", it.first.mcc_mnc);
461 }
462 }
463
464 // Tests that hash function reports distinct values. This test may fail if there
465 // is a hash collision, however the chances of that happening are very low.
466 TEST_F(ExternalDataUseObserverTest, HashFunction) {
467 ExternalDataUseObserver::DataUseReportKeyHash hash;
468
469 ExternalDataUseObserver::DataUseReportKey foo(
470 "foo_label", net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
471 "foo_mcc_mnc");
472 ExternalDataUseObserver::DataUseReportKey bar_label(
473 "bar_label", net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
474 "foo_mcc_mnc");
475 ExternalDataUseObserver::DataUseReportKey bar_network_type(
476 "foo_label", net::NetworkChangeNotifier::CONNECTION_WIFI, "foo_mcc_mnc");
477 ExternalDataUseObserver::DataUseReportKey bar_mcc_mnc(
478 "foo_label", net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
479 "bar_mcc_mnc");
480
481 EXPECT_NE(hash(foo), hash(bar_label));
482 EXPECT_NE(hash(foo), hash(bar_label));
483 EXPECT_NE(hash(foo), hash(bar_network_type));
484 EXPECT_NE(hash(foo), hash(bar_mcc_mnc));
485 }
486
487 } // namespace android
488
489 } // namespace chrome
OLDNEW
« no previous file with comments | « chrome/browser/android/datausage/external_data_use_observer.cc ('k') | chrome/browser/io_thread.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698