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

Side by Side Diff: content/browser/tracing/tracing_controller_impl.cc

Issue 66893003: Allow TracingController to output trace data to specified file (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "content/browser/tracing/tracing_controller_impl.h" 5 #include "content/browser/tracing/tracing_controller_impl.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/file_util.h" 8 #include "base/file_util.h"
9 #include "base/json/string_escape.h" 9 #include "base/json/string_escape.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/threading/thread_restrictions.h"
11 #include "content/browser/tracing/trace_message_filter.h" 12 #include "content/browser/tracing/trace_message_filter.h"
12 #include "content/common/child_process_messages.h" 13 #include "content/common/child_process_messages.h"
13 #include "content/public/browser/browser_message_filter.h" 14 #include "content/public/browser/browser_message_filter.h"
14 #include "content/public/common/content_switches.h" 15 #include "content/public/common/content_switches.h"
15 16
16 using base::debug::TraceLog; 17 using base::debug::TraceLog;
17 18
18 namespace content { 19 namespace content {
19 20
20 namespace { 21 namespace {
21 22
22 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = 23 base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
23 LAZY_INSTANCE_INITIALIZER; 24 LAZY_INSTANCE_INITIALIZER;
24 25
25 } // namespace 26 } // namespace
26 27
27 TracingController* TracingController::GetInstance() { 28 TracingController* TracingController::GetInstance() {
28 return TracingControllerImpl::GetInstance(); 29 return TracingControllerImpl::GetInstance();
29 } 30 }
30 31
32 class TracingControllerImpl::ResultFile {
33 public:
34 explicit ResultFile(const base::FilePath& path);
35 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) {
36 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
37 base::Bind(&TracingControllerImpl::ResultFile::WriteTask,
38 base::Unretained(this), events_str_ptr));
39 }
40 void Close(const base::Closure& callback) {
41 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
42 base::Bind(&TracingControllerImpl::ResultFile::CloseTask,
43 base::Unretained(this), callback));
44 }
45 const base::FilePath& path() const { return path_; }
46
47 private:
48 void OpenTask();
49 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr);
50 void CloseTask(const base::Closure& callback);
51
52 FILE* file_;
53 base::FilePath path_;
54 bool has_at_least_one_result_;
55
56 DISALLOW_COPY_AND_ASSIGN(ResultFile);
57 };
58
59 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path)
60 : file_(NULL),
61 path_(path),
62 has_at_least_one_result_(false) {
63 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
64 base::Bind(&TracingControllerImpl::ResultFile::OpenTask,
65 base::Unretained(this)));
66 }
67
68 void TracingControllerImpl::ResultFile::OpenTask() {
69 if (path_.empty())
70 file_util::CreateTemporaryFile(&path_);
71 file_ = file_util::OpenFile(path_, "w");
72 if (!file_) {
73 LOG(ERROR) << "Failed to open " << path_.value();
74 return;
75 }
76 const char* preamble = "{\"traceEvents\": [";
77 size_t written = fwrite(preamble, strlen(preamble), 1, file_);
78 DCHECK(written == 1);
79 }
80
81 void TracingControllerImpl::ResultFile::WriteTask(
82 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
83 if (!file_)
84 return;
85
86 // If there is already a result in the file, then put a commma
87 // before the next batch of results.
88 if (has_at_least_one_result_)
89 fwrite(",", 1, 1, file_);
90 has_at_least_one_result_ = true;
91 size_t written = fwrite(events_str_ptr->data().c_str(),
92 events_str_ptr->data().size(), 1,
93 file_);
94 DCHECK(written == 1);
95 }
96
97 void TracingControllerImpl::ResultFile::CloseTask(
98 const base::Closure& callback) {
99 if (!file_)
100 return;
101
102 const char* trailout = "]}";
103 size_t written = fwrite(trailout, strlen(trailout), 1, file_);
104 DCHECK(written == 1);
105 file_util::CloseFile(file_);
106 file_ = NULL;
107
108 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
109 }
110
111
31 TracingControllerImpl::TracingControllerImpl() : 112 TracingControllerImpl::TracingControllerImpl() :
32 pending_disable_recording_ack_count_(0), 113 pending_disable_recording_ack_count_(0),
33 pending_capture_monitoring_snapshot_ack_count_(0), 114 pending_capture_monitoring_snapshot_ack_count_(0),
34 is_recording_(false), 115 is_recording_(false),
35 is_monitoring_(false), 116 is_monitoring_(false),
117 trace_options_(TraceLog::RECORD_UNTIL_FULL),
36 category_filter_( 118 category_filter_(
37 base::debug::CategoryFilter::kDefaultCategoryFilterString), 119 base::debug::CategoryFilter::kDefaultCategoryFilterString) {
38 result_file_(0),
39 result_file_has_at_least_one_result_(false) {
40 } 120 }
41 121
42 TracingControllerImpl::~TracingControllerImpl() { 122 TracingControllerImpl::~TracingControllerImpl() {
43 // This is a Leaky instance. 123 // This is a Leaky instance.
44 NOTREACHED(); 124 NOTREACHED();
45 } 125 }
46 126
47 TracingControllerImpl* TracingControllerImpl::GetInstance() { 127 TracingControllerImpl* TracingControllerImpl::GetInstance() {
48 return g_controller.Pointer(); 128 return g_controller.Pointer();
49 } 129 }
50 130
51 void TracingControllerImpl::GetCategories( 131 void TracingControllerImpl::GetCategories(
52 const GetCategoriesDoneCallback& callback) { 132 const GetCategoriesDoneCallback& callback) {
53 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 133 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
54 134
55 // Known categories come back from child processes with the EndTracingAck 135 // Known categories come back from child processes with the EndTracingAck
56 // message. So to get known categories, just begin and end tracing immediately 136 // message. So to get known categories, just begin and end tracing immediately
57 // afterwards. This will ping all the child processes for categories. 137 // afterwards. This will ping all the child processes for categories.
58 pending_get_categories_done_callback_ = callback; 138 pending_get_categories_done_callback_ = callback;
59 EnableRecording(base::debug::CategoryFilter("*"), 139 EnableRecording(base::debug::CategoryFilter("*"),
60 TracingController::Options(), 140 TracingController::Options(),
61 EnableRecordingDoneCallback()); 141 EnableRecordingDoneCallback());
62 DisableRecording(TracingFileResultCallback()); 142 DisableRecording(base::FilePath(), TracingFileResultCallback());
63 } 143 }
64 144
65 bool TracingControllerImpl::EnableRecording( 145 bool TracingControllerImpl::EnableRecording(
66 const base::debug::CategoryFilter& filter, 146 const base::debug::CategoryFilter& filter,
67 TracingController::Options options, 147 TracingController::Options options,
68 const EnableRecordingDoneCallback& callback) { 148 const EnableRecordingDoneCallback& callback) {
69 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
70 150
71 if (!can_enable_recording()) 151 if (!can_enable_recording())
72 return false; 152 return false;
(...skipping 14 matching lines...) Expand all
87 it->get()->SendBeginTracing( 167 it->get()->SendBeginTracing(
88 category_filter_.ToString(), trace_options_, false); 168 category_filter_.ToString(), trace_options_, false);
89 } 169 }
90 170
91 if (!callback.is_null()) 171 if (!callback.is_null())
92 callback.Run(); 172 callback.Run();
93 return true; 173 return true;
94 } 174 }
95 175
96 bool TracingControllerImpl::DisableRecording( 176 bool TracingControllerImpl::DisableRecording(
177 const base::FilePath& result_file_path,
97 const TracingFileResultCallback& callback) { 178 const TracingFileResultCallback& callback) {
98 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
99 180
100 if (!can_disable_recording()) 181 if (!can_disable_recording())
101 return false; 182 return false;
102 183
103 pending_disable_recording_done_callback_ = callback; 184 pending_disable_recording_done_callback_ = callback;
104 185
105 // Disable local trace early to avoid traces during end-tracing process from 186 // Disable local trace early to avoid traces during end-tracing process from
106 // interfering with the process. 187 // interfering with the process.
107 TraceLog::GetInstance()->SetDisabled(); 188 TraceLog::GetInstance()->SetDisabled();
108 189
109 #if defined(OS_ANDROID) 190 #if defined(OS_ANDROID)
110 if (pending_get_categories_done_callback_.is_null()) 191 if (pending_get_categories_done_callback_.is_null())
111 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); 192 TraceLog::GetInstance()->AddClockSyncMetadataEvent();
112 #endif 193 #endif
113 194
114 // We don't need to create a temporary file when getting categories. 195 if (!callback.is_null() || !result_file_path.empty())
115 if (pending_get_categories_done_callback_.is_null()) { 196 result_file_.reset(new ResultFile(result_file_path));
Jói 2013/11/19 12:42:22 Do you not need to close the previous result_file_
Xianzhu 2013/11/19 16:48:34 The !can_disable_recording() condition above ensur
116 base::FilePath temporary_file;
117 file_util::CreateTemporaryFile(&temporary_file);
118 result_file_path_.reset(new base::FilePath(temporary_file));
119 result_file_ = file_util::OpenFile(*result_file_path_, "w");
120 result_file_has_at_least_one_result_ = false;
121 const char* preamble = "{\"traceEvents\": [";
122 size_t written = fwrite(preamble, strlen(preamble), 1, result_file_);
123 DCHECK(written == 1);
124 }
125 197
126 // There could be a case where there are no child processes and filters_ 198 // There could be a case where there are no child processes and filters_
127 // is empty. In that case we can immediately tell the subscriber that tracing 199 // is empty. In that case we can immediately tell the subscriber that tracing
128 // has ended. To avoid recursive calls back to the subscriber, we will just 200 // has ended. To avoid recursive calls back to the subscriber, we will just
129 // use the existing asynchronous OnDisableRecordingAcked code. 201 // use the existing asynchronous OnDisableRecordingAcked code.
130 // Count myself (local trace) in pending_disable_recording_ack_count_, 202 // Count myself (local trace) in pending_disable_recording_ack_count_,
131 // acked below. 203 // acked below.
132 pending_disable_recording_ack_count_ = filters_.size() + 1; 204 pending_disable_recording_ack_count_ = filters_.size() + 1;
133 205
134 // Handle special case of zero child processes. 206 // Handle special case of zero child processes.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 } 268 }
197 269
198 void TracingControllerImpl::GetMonitoringStatus( 270 void TracingControllerImpl::GetMonitoringStatus(
199 bool* out_enabled, 271 bool* out_enabled,
200 base::debug::CategoryFilter* out_filter, 272 base::debug::CategoryFilter* out_filter,
201 TracingController::Options* out_options) { 273 TracingController::Options* out_options) {
202 NOTIMPLEMENTED(); 274 NOTIMPLEMENTED();
203 } 275 }
204 276
205 void TracingControllerImpl::CaptureMonitoringSnapshot( 277 void TracingControllerImpl::CaptureMonitoringSnapshot(
278 const base::FilePath& result_file_path,
206 const TracingFileResultCallback& callback) { 279 const TracingFileResultCallback& callback) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
208 281
209 if (!can_disable_monitoring()) 282 if (!can_disable_monitoring())
210 return; 283 return;
211 284
212 pending_capture_monitoring_snapshot_done_callback_ = callback; 285 pending_capture_monitoring_snapshot_done_callback_ = callback;
213 286
214 base::FilePath temporary_file; 287 if (!callback.is_null() || !result_file_path.empty())
215 file_util::CreateTemporaryFile(&temporary_file); 288 monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
216 result_file_path_.reset(new base::FilePath(temporary_file));
217 result_file_ = file_util::OpenFile(*result_file_path_, "w");
218 result_file_has_at_least_one_result_ = false;
219 const char* preamble = "{\"traceEvents\": [";
220 size_t written = fwrite(preamble, strlen(preamble), 1, result_file_);
221 DCHECK(written == 1);
222 289
223 // There could be a case where there are no child processes and filters_ 290 // There could be a case where there are no child processes and filters_
224 // is empty. In that case we can immediately tell the subscriber that tracing 291 // is empty. In that case we can immediately tell the subscriber that tracing
225 // has ended. To avoid recursive calls back to the subscriber, we will just 292 // has ended. To avoid recursive calls back to the subscriber, we will just
226 // use the existing asynchronous OnCaptureMonitoringSnapshotAcked code. 293 // use the existing asynchronous OnCaptureMonitoringSnapshotAcked code.
227 // Count myself in pending_capture_monitoring_snapshot_ack_count_, 294 // Count myself in pending_capture_monitoring_snapshot_ack_count_,
228 // acked below. 295 // acked below.
229 pending_capture_monitoring_snapshot_ack_count_ = filters_.size() + 1; 296 pending_capture_monitoring_snapshot_ack_count_ = filters_.size() + 1;
230 297
231 // Handle special case of zero child processes. 298 // Handle special case of zero child processes.
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
301 return; 368 return;
302 369
303 // All acks (including from the subprocesses and the local trace) have been 370 // All acks (including from the subprocesses and the local trace) have been
304 // received. 371 // received.
305 is_recording_ = false; 372 is_recording_ = false;
306 373
307 // Trigger callback if one is set. 374 // Trigger callback if one is set.
308 if (!pending_get_categories_done_callback_.is_null()) { 375 if (!pending_get_categories_done_callback_.is_null()) {
309 pending_get_categories_done_callback_.Run(known_category_groups_); 376 pending_get_categories_done_callback_.Run(known_category_groups_);
310 pending_get_categories_done_callback_.Reset(); 377 pending_get_categories_done_callback_.Reset();
311 } else if (!pending_disable_recording_done_callback_.is_null()) { 378 } else if (result_file_) {
312 const char* trailout = "]}"; 379 result_file_->Close(
313 size_t written = fwrite(trailout, strlen(trailout), 1, result_file_); 380 base::Bind(&TracingControllerImpl::OnResultFileClosed,
314 DCHECK(written == 1); 381 base::Unretained(this)));
315 file_util::CloseFile(result_file_);
316 result_file_ = 0;
317 pending_disable_recording_done_callback_.Run(result_file_path_.Pass());
318 pending_disable_recording_done_callback_.Reset();
319 } 382 }
320 } 383 }
321 384
385 void TracingControllerImpl::OnResultFileClosed() {
386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
387
388 if (!result_file_)
389 return;
390
391 if (!pending_disable_recording_done_callback_.is_null()) {
392 pending_disable_recording_done_callback_.Run(result_file_->path());
393 pending_disable_recording_done_callback_.Reset();
394 }
395 result_file_.reset();
396 }
397
322 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() { 398 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() {
323 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 399 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
324 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 400 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
325 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, 401 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
326 base::Unretained(this))); 402 base::Unretained(this)));
327 return; 403 return;
328 } 404 }
329 405
330 if (pending_capture_monitoring_snapshot_ack_count_ == 0) 406 if (pending_capture_monitoring_snapshot_ack_count_ == 0)
331 return; 407 return;
332 408
333 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) { 409 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
334 // All acks from subprocesses have been received. Now flush the local trace. 410 // All acks from subprocesses have been received. Now flush the local trace.
335 // During or after this call, our OnLocalMonitoringTraceDataCollected 411 // During or after this call, our OnLocalMonitoringTraceDataCollected
336 // will be called with the last of the local trace data. 412 // will be called with the last of the local trace data.
337 TraceLog::GetInstance()->FlushButLeaveBufferIntact( 413 TraceLog::GetInstance()->FlushButLeaveBufferIntact(
338 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, 414 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
339 base::Unretained(this))); 415 base::Unretained(this)));
340 } 416 }
341 417
342 if (pending_capture_monitoring_snapshot_ack_count_ != 0) 418 if (pending_capture_monitoring_snapshot_ack_count_ != 0)
343 return; 419 return;
344 420
345 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) { 421 if (monitoring_snapshot_file_) {
346 const char* trailout = "]}"; 422 monitoring_snapshot_file_->Close(
347 size_t written = fwrite(trailout, strlen(trailout), 1, result_file_); 423 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed,
348 DCHECK(written == 1); 424 base::Unretained(this)));
349 file_util::CloseFile(result_file_);
350 result_file_ = 0;
351 pending_capture_monitoring_snapshot_done_callback_.Run(
352 result_file_path_.Pass());
353 pending_capture_monitoring_snapshot_done_callback_.Reset();
354 } 425 }
355 } 426 }
356 427
428 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() {
429 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
430
431 if (!monitoring_snapshot_file_)
432 return;
433
434 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) {
435 pending_capture_monitoring_snapshot_done_callback_.Run(
436 monitoring_snapshot_file_->path());
437 pending_capture_monitoring_snapshot_done_callback_.Reset();
438 }
439 monitoring_snapshot_file_.reset();
440 }
441
357 void TracingControllerImpl::OnTraceDataCollected( 442 void TracingControllerImpl::OnTraceDataCollected(
358 const scoped_refptr<base::RefCountedString>& events_str_ptr) { 443 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
359 // OnTraceDataCollected may be called from any browser thread, either by the 444 // OnTraceDataCollected may be called from any browser thread, either by the
360 // local event trace system or from child processes via TraceMessageFilter. 445 // local event trace system or from child processes via TraceMessageFilter.
361 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { 446 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
362 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 447 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
363 base::Bind(&TracingControllerImpl::OnTraceDataCollected, 448 base::Bind(&TracingControllerImpl::OnTraceDataCollected,
364 base::Unretained(this), events_str_ptr)); 449 base::Unretained(this), events_str_ptr));
365 return; 450 return;
366 } 451 }
367 452
368 // Drop trace events if we are just getting categories. 453 if (result_file_)
369 if (!pending_get_categories_done_callback_.is_null()) 454 result_file_->Write(events_str_ptr);
455 }
456
457 void TracingControllerImpl::OnMonitoringTraceDataCollected(
458 const scoped_refptr<base::RefCountedString>& events_str_ptr) {
459 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
460 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
461 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
462 base::Unretained(this), events_str_ptr));
370 return; 463 return;
464 }
371 465
372 // If there is already a result in the file, then put a commma 466 if (!monitoring_snapshot_file_)
373 // before the next batch of results. 467 monitoring_snapshot_file_->Write(events_str_ptr);
374 if (result_file_has_at_least_one_result_) {
375 size_t written = fwrite(",", 1, 1, result_file_);
376 DCHECK(written == 1);
377 } else {
378 result_file_has_at_least_one_result_ = true;
379 }
380 size_t written = fwrite(events_str_ptr->data().c_str(),
381 events_str_ptr->data().size(), 1,
382 result_file_);
383 DCHECK(written == 1);
384 } 468 }
385 469
386 void TracingControllerImpl::OnLocalTraceDataCollected( 470 void TracingControllerImpl::OnLocalTraceDataCollected(
387 const scoped_refptr<base::RefCountedString>& events_str_ptr, 471 const scoped_refptr<base::RefCountedString>& events_str_ptr,
388 bool has_more_events) { 472 bool has_more_events) {
389 if (events_str_ptr->data().size()) 473 if (events_str_ptr->data().size())
390 OnTraceDataCollected(events_str_ptr); 474 OnTraceDataCollected(events_str_ptr);
391 475
392 if (has_more_events) 476 if (has_more_events)
393 return; 477 return;
394 478
395 // Simulate an DisableRecordingAcked for the local trace. 479 // Simulate an DisableRecordingAcked for the local trace.
396 std::vector<std::string> category_groups; 480 std::vector<std::string> category_groups;
397 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); 481 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
398 OnDisableRecordingAcked(category_groups); 482 OnDisableRecordingAcked(category_groups);
399 } 483 }
400 484
401 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected( 485 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
402 const scoped_refptr<base::RefCountedString>& events_str_ptr, 486 const scoped_refptr<base::RefCountedString>& events_str_ptr,
403 bool has_more_events) { 487 bool has_more_events) {
404 if (events_str_ptr->data().size()) 488 if (events_str_ptr->data().size())
405 OnTraceDataCollected(events_str_ptr); 489 OnMonitoringTraceDataCollected(events_str_ptr);
406 490
407 if (has_more_events) 491 if (has_more_events)
408 return; 492 return;
409 493
410 // Simulate an CaptureMonitoringSnapshotAcked for the local trace. 494 // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
411 OnCaptureMonitoringSnapshotAcked(); 495 OnCaptureMonitoringSnapshotAcked();
412 } 496 }
413 497
414 } // namespace content 498 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698