OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 #include "content/browser/tracing/tracing_controller_impl.h" | 4 #include "content/browser/tracing/tracing_controller_impl.h" |
5 | 5 |
6 #include "base/bind.h" | 6 #include "base/bind.h" |
7 #include "base/cpu.h" | 7 #include "base/cpu.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/guid.h" | 9 #include "base/guid.h" |
10 #include "base/json/string_escape.h" | 10 #include "base/json/string_escape.h" |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 | 153 |
154 } // namespace | 154 } // namespace |
155 | 155 |
156 TracingController* TracingController::GetInstance() { | 156 TracingController* TracingController::GetInstance() { |
157 return TracingControllerImpl::GetInstance(); | 157 return TracingControllerImpl::GetInstance(); |
158 } | 158 } |
159 | 159 |
160 TracingControllerImpl::TracingControllerImpl() | 160 TracingControllerImpl::TracingControllerImpl() |
161 : pending_start_tracing_ack_count_(0), | 161 : pending_start_tracing_ack_count_(0), |
162 pending_stop_tracing_ack_count_(0), | 162 pending_stop_tracing_ack_count_(0), |
163 pending_capture_monitoring_snapshot_ack_count_(0), | |
164 pending_trace_log_status_ack_count_(0), | 163 pending_trace_log_status_ack_count_(0), |
165 maximum_trace_buffer_usage_(0), | 164 maximum_trace_buffer_usage_(0), |
166 approximate_event_count_(0), | 165 approximate_event_count_(0), |
167 pending_memory_dump_ack_count_(0), | 166 pending_memory_dump_ack_count_(0), |
168 failed_memory_dump_count_(0), | 167 failed_memory_dump_count_(0), |
169 pending_clock_sync_ack_count_(0), | 168 pending_clock_sync_ack_count_(0), |
170 is_tracing_(false), | 169 is_tracing_(false) { |
171 is_monitoring_(false) { | |
172 base::trace_event::MemoryDumpManager::GetInstance()->Initialize( | 170 base::trace_event::MemoryDumpManager::GetInstance()->Initialize( |
173 this /* delegate */, true /* is_coordinator */); | 171 this /* delegate */, true /* is_coordinator */); |
174 | 172 |
175 // Deliberately leaked, like this class. | 173 // Deliberately leaked, like this class. |
176 base::FileTracing::SetProvider(new FileTracingProviderImpl); | 174 base::FileTracing::SetProvider(new FileTracingProviderImpl); |
177 } | 175 } |
178 | 176 |
179 TracingControllerImpl::~TracingControllerImpl() { | 177 TracingControllerImpl::~TracingControllerImpl() { |
180 // This is a Leaky instance. | 178 // This is a Leaky instance. |
181 NOTREACHED(); | 179 NOTREACHED(); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 for (auto it : additional_tracing_agents_) { | 379 for (auto it : additional_tracing_agents_) { |
382 it->StopAgentTracing( | 380 it->StopAgentTracing( |
383 base::Bind(&TracingControllerImpl::OnEndAgentTracingAcked, | 381 base::Bind(&TracingControllerImpl::OnEndAgentTracingAcked, |
384 base::Unretained(this))); | 382 base::Unretained(this))); |
385 } | 383 } |
386 additional_tracing_agents_.clear(); | 384 additional_tracing_agents_.clear(); |
387 | 385 |
388 StopAgentTracing(StopAgentTracingCallback()); | 386 StopAgentTracing(StopAgentTracingCallback()); |
389 } | 387 } |
390 | 388 |
391 bool TracingControllerImpl::StartMonitoring( | |
392 const TraceConfig& trace_config, | |
393 const StartMonitoringDoneCallback& callback) { | |
394 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
395 | |
396 if (!can_start_monitoring()) | |
397 return false; | |
398 OnMonitoringStateChanged(true); | |
399 | |
400 #if defined(OS_ANDROID) | |
401 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | |
402 #endif | |
403 | |
404 base::Closure on_start_monitoring_done_callback = | |
405 base::Bind(&TracingControllerImpl::OnStartMonitoringDone, | |
406 base::Unretained(this), | |
407 trace_config, callback); | |
408 if (!BrowserThread::PostTask( | |
409 BrowserThread::FILE, FROM_HERE, | |
410 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, | |
411 base::Unretained(this), trace_config, | |
412 base::trace_event::TraceLog::MONITORING_MODE, | |
413 on_start_monitoring_done_callback))) { | |
414 // BrowserThread::PostTask fails if the threads haven't been created yet, | |
415 // so it should be safe to just use TraceLog::SetEnabled directly. | |
416 base::trace_event::TraceLog::GetInstance()->SetEnabled( | |
417 trace_config, base::trace_event::TraceLog::MONITORING_MODE); | |
418 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
419 on_start_monitoring_done_callback); | |
420 } | |
421 return true; | |
422 } | |
423 | |
424 void TracingControllerImpl::OnStartMonitoringDone( | |
425 const TraceConfig& trace_config, | |
426 const StartMonitoringDoneCallback& callback) { | |
427 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
428 | |
429 // Notify all child processes. | |
430 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | |
431 it != trace_message_filters_.end(); ++it) { | |
432 it->get()->SendStartMonitoring(trace_config); | |
433 } | |
434 | |
435 if (!callback.is_null()) | |
436 callback.Run(); | |
437 } | |
438 | |
439 bool TracingControllerImpl::StopMonitoring( | |
440 const StopMonitoringDoneCallback& callback) { | |
441 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
442 | |
443 if (!can_stop_monitoring()) | |
444 return false; | |
445 | |
446 base::Closure on_stop_monitoring_done_callback = | |
447 base::Bind(&TracingControllerImpl::OnStopMonitoringDone, | |
448 base::Unretained(this), callback); | |
449 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
450 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, | |
451 base::Unretained(this), | |
452 on_stop_monitoring_done_callback)); | |
453 return true; | |
454 } | |
455 | |
456 void TracingControllerImpl::OnStopMonitoringDone( | |
457 const StopMonitoringDoneCallback& callback) { | |
458 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
459 | |
460 OnMonitoringStateChanged(false); | |
461 | |
462 // Notify all child processes. | |
463 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | |
464 it != trace_message_filters_.end(); ++it) { | |
465 it->get()->SendStopMonitoring(); | |
466 } | |
467 if (!callback.is_null()) | |
468 callback.Run(); | |
469 } | |
470 | |
471 void TracingControllerImpl::GetMonitoringStatus( | |
472 bool* out_enabled, | |
473 TraceConfig* out_trace_config) { | |
474 *out_enabled = is_monitoring_; | |
475 *out_trace_config = TraceLog::GetInstance()->GetCurrentTraceConfig(); | |
476 } | |
477 | |
478 bool TracingControllerImpl::CaptureMonitoringSnapshot( | |
479 const scoped_refptr<TraceDataSink>& monitoring_data_sink) { | |
480 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
481 | |
482 if (!can_stop_monitoring()) | |
483 return false; | |
484 | |
485 if (!monitoring_data_sink.get()) | |
486 return false; | |
487 | |
488 monitoring_data_sink_ = monitoring_data_sink; | |
489 | |
490 // Count myself in pending_capture_monitoring_snapshot_ack_count_, | |
491 // acked below. | |
492 pending_capture_monitoring_snapshot_ack_count_ = | |
493 trace_message_filters_.size() + 1; | |
494 pending_capture_monitoring_filters_ = trace_message_filters_; | |
495 | |
496 // Handle special case of zero child processes by immediately flushing the | |
497 // trace log. Once the flush has completed the caller will be notified that | |
498 // the capture snapshot has ended. | |
499 if (pending_capture_monitoring_snapshot_ack_count_ == 1) { | |
500 // Flush asynchronously now, because we don't have any children to wait for. | |
501 TraceLog::GetInstance()->FlushButLeaveBufferIntact( | |
502 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, | |
503 base::Unretained(this))); | |
504 } | |
505 | |
506 // Notify all child processes. | |
507 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | |
508 it != trace_message_filters_.end(); ++it) { | |
509 it->get()->SendCaptureMonitoringSnapshot(); | |
510 } | |
511 | |
512 #if defined(OS_ANDROID) | |
513 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | |
514 #endif | |
515 | |
516 return true; | |
517 } | |
518 | |
519 bool TracingControllerImpl::GetTraceBufferUsage( | 389 bool TracingControllerImpl::GetTraceBufferUsage( |
520 const GetTraceBufferUsageCallback& callback) { | 390 const GetTraceBufferUsageCallback& callback) { |
521 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 391 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
522 | 392 |
523 if (!can_get_trace_buffer_usage() || callback.is_null()) | 393 if (!can_get_trace_buffer_usage() || callback.is_null()) |
524 return false; | 394 return false; |
525 | 395 |
526 pending_trace_buffer_usage_callback_ = callback; | 396 pending_trace_buffer_usage_callback_ = callback; |
527 | 397 |
528 // Count myself in pending_trace_log_status_ack_count_, acked below. | 398 // Count myself in pending_trace_log_status_ack_count_, acked below. |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
613 | 483 |
614 trace_message_filters_.insert(trace_message_filter); | 484 trace_message_filters_.insert(trace_message_filter); |
615 if (can_cancel_watch_event()) { | 485 if (can_cancel_watch_event()) { |
616 trace_message_filter->SendSetWatchEvent(watch_category_name_, | 486 trace_message_filter->SendSetWatchEvent(watch_category_name_, |
617 watch_event_name_); | 487 watch_event_name_); |
618 } | 488 } |
619 if (can_stop_tracing()) { | 489 if (can_stop_tracing()) { |
620 trace_message_filter->SendBeginTracing( | 490 trace_message_filter->SendBeginTracing( |
621 TraceLog::GetInstance()->GetCurrentTraceConfig()); | 491 TraceLog::GetInstance()->GetCurrentTraceConfig()); |
622 } | 492 } |
623 if (can_stop_monitoring()) { | |
624 trace_message_filter->SendStartMonitoring( | |
625 TraceLog::GetInstance()->GetCurrentTraceConfig()); | |
626 } | |
627 | 493 |
628 FOR_EACH_OBSERVER(TraceMessageFilterObserver, trace_message_filter_observers_, | 494 FOR_EACH_OBSERVER(TraceMessageFilterObserver, trace_message_filter_observers_, |
629 OnTraceMessageFilterAdded(trace_message_filter)); | 495 OnTraceMessageFilterAdded(trace_message_filter)); |
630 } | 496 } |
631 | 497 |
632 void TracingControllerImpl::RemoveTraceMessageFilter( | 498 void TracingControllerImpl::RemoveTraceMessageFilter( |
633 TraceMessageFilter* trace_message_filter) { | 499 TraceMessageFilter* trace_message_filter) { |
634 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 500 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
635 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 501 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
636 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, | 502 base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter, |
(...skipping 14 matching lines...) Expand all Loading... |
651 TraceMessageFilterSet::const_iterator it = | 517 TraceMessageFilterSet::const_iterator it = |
652 pending_stop_tracing_filters_.find(trace_message_filter); | 518 pending_stop_tracing_filters_.find(trace_message_filter); |
653 if (it != pending_stop_tracing_filters_.end()) { | 519 if (it != pending_stop_tracing_filters_.end()) { |
654 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 520 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
655 base::Bind(&TracingControllerImpl::OnStopTracingAcked, | 521 base::Bind(&TracingControllerImpl::OnStopTracingAcked, |
656 base::Unretained(this), | 522 base::Unretained(this), |
657 make_scoped_refptr(trace_message_filter), | 523 make_scoped_refptr(trace_message_filter), |
658 std::vector<std::string>())); | 524 std::vector<std::string>())); |
659 } | 525 } |
660 } | 526 } |
661 if (pending_capture_monitoring_snapshot_ack_count_ > 0) { | |
662 TraceMessageFilterSet::const_iterator it = | |
663 pending_capture_monitoring_filters_.find(trace_message_filter); | |
664 if (it != pending_capture_monitoring_filters_.end()) { | |
665 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
666 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, | |
667 base::Unretained(this), | |
668 make_scoped_refptr(trace_message_filter))); | |
669 } | |
670 } | |
671 if (pending_trace_log_status_ack_count_ > 0) { | 527 if (pending_trace_log_status_ack_count_ > 0) { |
672 TraceMessageFilterSet::const_iterator it = | 528 TraceMessageFilterSet::const_iterator it = |
673 pending_trace_log_status_filters_.find(trace_message_filter); | 529 pending_trace_log_status_filters_.find(trace_message_filter); |
674 if (it != pending_trace_log_status_filters_.end()) { | 530 if (it != pending_trace_log_status_filters_.end()) { |
675 BrowserThread::PostTask( | 531 BrowserThread::PostTask( |
676 BrowserThread::UI, FROM_HERE, | 532 BrowserThread::UI, FROM_HERE, |
677 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | 533 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, |
678 base::Unretained(this), | 534 base::Unretained(this), |
679 make_scoped_refptr(trace_message_filter), | 535 make_scoped_refptr(trace_message_filter), |
680 base::trace_event::TraceLogStatus())); | 536 base::trace_event::TraceLogStatus())); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 json_string = events_str_ptr->data(); | 672 json_string = events_str_ptr->data(); |
817 } else { | 673 } else { |
818 json_string = base::GetQuotedJSONString(events_str_ptr->data()); | 674 json_string = base::GetQuotedJSONString(events_str_ptr->data()); |
819 } | 675 } |
820 trace_data_sink_->AddAgentTrace(events_label, json_string); | 676 trace_data_sink_->AddAgentTrace(events_label, json_string); |
821 } | 677 } |
822 std::vector<std::string> category_groups; | 678 std::vector<std::string> category_groups; |
823 OnStopTracingAcked(NULL, category_groups); | 679 OnStopTracingAcked(NULL, category_groups); |
824 } | 680 } |
825 | 681 |
826 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( | |
827 TraceMessageFilter* trace_message_filter) { | |
828 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
829 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
830 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, | |
831 base::Unretained(this), | |
832 make_scoped_refptr(trace_message_filter))); | |
833 return; | |
834 } | |
835 | |
836 if (pending_capture_monitoring_snapshot_ack_count_ == 0) | |
837 return; | |
838 | |
839 if (trace_message_filter && | |
840 !pending_capture_monitoring_filters_.erase(trace_message_filter)) { | |
841 // The response from the specified message filter has already been received. | |
842 return; | |
843 } | |
844 | |
845 if (--pending_capture_monitoring_snapshot_ack_count_ == 1) { | |
846 // All acks from subprocesses have been received. Now flush the local trace. | |
847 // During or after this call, our OnLocalMonitoringTraceDataCollected | |
848 // will be called with the last of the local trace data. | |
849 TraceLog::GetInstance()->FlushButLeaveBufferIntact( | |
850 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, | |
851 base::Unretained(this))); | |
852 return; | |
853 } | |
854 | |
855 if (pending_capture_monitoring_snapshot_ack_count_ != 0) | |
856 return; | |
857 | |
858 if (monitoring_data_sink_.get()) { | |
859 monitoring_data_sink_->Close(); | |
860 monitoring_data_sink_ = NULL; | |
861 } | |
862 } | |
863 | |
864 void TracingControllerImpl::OnTraceDataCollected( | 682 void TracingControllerImpl::OnTraceDataCollected( |
865 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 683 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
866 // OnTraceDataCollected may be called from any browser thread, either by the | 684 // OnTraceDataCollected may be called from any browser thread, either by the |
867 // local event trace system or from child processes via TraceMessageFilter. | 685 // local event trace system or from child processes via TraceMessageFilter. |
868 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 686 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
869 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 687 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
870 base::Bind(&TracingControllerImpl::OnTraceDataCollected, | 688 base::Bind(&TracingControllerImpl::OnTraceDataCollected, |
871 base::Unretained(this), events_str_ptr)); | 689 base::Unretained(this), events_str_ptr)); |
872 return; | 690 return; |
873 } | 691 } |
874 | 692 |
875 if (trace_data_sink_.get()) | 693 if (trace_data_sink_.get()) |
876 trace_data_sink_->AddTraceChunk(events_str_ptr->data()); | 694 trace_data_sink_->AddTraceChunk(events_str_ptr->data()); |
877 } | 695 } |
878 | 696 |
879 void TracingControllerImpl::OnMonitoringTraceDataCollected( | |
880 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
881 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | |
882 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
883 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected, | |
884 base::Unretained(this), events_str_ptr)); | |
885 return; | |
886 } | |
887 | |
888 if (monitoring_data_sink_.get()) | |
889 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data()); | |
890 } | |
891 | |
892 void TracingControllerImpl::OnLocalTraceDataCollected( | 697 void TracingControllerImpl::OnLocalTraceDataCollected( |
893 const scoped_refptr<base::RefCountedString>& events_str_ptr, | 698 const scoped_refptr<base::RefCountedString>& events_str_ptr, |
894 bool has_more_events) { | 699 bool has_more_events) { |
895 if (events_str_ptr->data().size()) | 700 if (events_str_ptr->data().size()) |
896 OnTraceDataCollected(events_str_ptr); | 701 OnTraceDataCollected(events_str_ptr); |
897 | 702 |
898 if (has_more_events) | 703 if (has_more_events) |
899 return; | 704 return; |
900 | 705 |
901 // Simulate an StopTracingAcked for the local trace. | 706 // Simulate an StopTracingAcked for the local trace. |
902 std::vector<std::string> category_groups; | 707 std::vector<std::string> category_groups; |
903 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); | 708 TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); |
904 OnStopTracingAcked(NULL, category_groups); | 709 OnStopTracingAcked(NULL, category_groups); |
905 } | 710 } |
906 | 711 |
907 void TracingControllerImpl::OnLocalMonitoringTraceDataCollected( | |
908 const scoped_refptr<base::RefCountedString>& events_str_ptr, | |
909 bool has_more_events) { | |
910 if (events_str_ptr->data().size()) | |
911 OnMonitoringTraceDataCollected(events_str_ptr); | |
912 | |
913 if (has_more_events) | |
914 return; | |
915 | |
916 // Simulate an CaptureMonitoringSnapshotAcked for the local trace. | |
917 OnCaptureMonitoringSnapshotAcked(NULL); | |
918 } | |
919 | |
920 void TracingControllerImpl::OnTraceLogStatusReply( | 712 void TracingControllerImpl::OnTraceLogStatusReply( |
921 TraceMessageFilter* trace_message_filter, | 713 TraceMessageFilter* trace_message_filter, |
922 const base::trace_event::TraceLogStatus& status) { | 714 const base::trace_event::TraceLogStatus& status) { |
923 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 715 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
924 BrowserThread::PostTask( | 716 BrowserThread::PostTask( |
925 BrowserThread::UI, FROM_HERE, | 717 BrowserThread::UI, FROM_HERE, |
926 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, | 718 base::Bind(&TracingControllerImpl::OnTraceLogStatusReply, |
927 base::Unretained(this), | 719 base::Unretained(this), |
928 make_scoped_refptr(trace_message_filter), status)); | 720 make_scoped_refptr(trace_message_filter), status)); |
929 return; | 721 return; |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1205 DCHECK_NE(0u, pending_memory_dump_guid_); | 997 DCHECK_NE(0u, pending_memory_dump_guid_); |
1206 const bool global_success = failed_memory_dump_count_ == 0; | 998 const bool global_success = failed_memory_dump_count_ == 0; |
1207 if (!pending_memory_dump_callback_.is_null()) { | 999 if (!pending_memory_dump_callback_.is_null()) { |
1208 pending_memory_dump_callback_.Run(pending_memory_dump_guid_, | 1000 pending_memory_dump_callback_.Run(pending_memory_dump_guid_, |
1209 global_success); | 1001 global_success); |
1210 pending_memory_dump_callback_.Reset(); | 1002 pending_memory_dump_callback_.Reset(); |
1211 } | 1003 } |
1212 pending_memory_dump_guid_ = 0; | 1004 pending_memory_dump_guid_ = 0; |
1213 } | 1005 } |
1214 | 1006 |
1215 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) { | |
1216 if (is_monitoring_ == is_monitoring) | |
1217 return; | |
1218 | |
1219 is_monitoring_ = is_monitoring; | |
1220 #if !defined(OS_ANDROID) | |
1221 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); | |
1222 it != tracing_uis_.end(); it++) { | |
1223 (*it)->OnMonitoringStateChanged(is_monitoring); | |
1224 } | |
1225 #endif | |
1226 } | |
1227 | |
1228 } // namespace content | 1007 } // namespace content |
OLD | NEW |