| OLD | NEW |
| 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/debug/trace_event.h" | 8 #include "base/debug/trace_event.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/json/string_escape.h" | 10 #include "base/json/string_escape.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "content/browser/tracing/trace_message_filter.h" | 12 #include "content/browser/tracing/trace_message_filter.h" |
| 13 #include "content/browser/tracing/tracing_ui.h" | 13 #include "content/browser/tracing/tracing_ui.h" |
| 14 #include "content/common/child_process_messages.h" | 14 #include "content/common/child_process_messages.h" |
| 15 #include "content/public/browser/browser_message_filter.h" | 15 #include "content/public/browser/browser_message_filter.h" |
| 16 #include "content/public/common/content_switches.h" | 16 #include "content/public/common/content_switches.h" |
| 17 | 17 |
| 18 #if defined(OS_CHROMEOS) | 18 #if defined(OS_CHROMEOS) |
| 19 #include "chromeos/dbus/dbus_thread_manager.h" | 19 #include "chromeos/dbus/dbus_thread_manager.h" |
| 20 #include "chromeos/dbus/debug_daemon_client.h" | 20 #include "chromeos/dbus/debug_daemon_client.h" |
| 21 #endif | 21 #endif |
| 22 | 22 |
| 23 #if defined(OS_WIN) |
| 24 #include "content/browser/tracing/tracing_consumer_win.h" |
| 25 #endif |
| 26 |
| 23 using base::debug::TraceLog; | 27 using base::debug::TraceLog; |
| 24 | 28 |
| 25 namespace content { | 29 namespace content { |
| 26 | 30 |
| 27 namespace { | 31 namespace { |
| 28 | 32 |
| 29 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = | 33 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = |
| 30 LAZY_INSTANCE_INITIALIZER; | 34 LAZY_INSTANCE_INITIALIZER; |
| 31 | 35 |
| 32 } // namespace | 36 } // namespace |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 const char* preamble = "{\"traceEvents\": ["; | 98 const char* preamble = "{\"traceEvents\": ["; |
| 95 size_t written = fwrite(preamble, strlen(preamble), 1, file_); | 99 size_t written = fwrite(preamble, strlen(preamble), 1, file_); |
| 96 DCHECK(written == 1); | 100 DCHECK(written == 1); |
| 97 } | 101 } |
| 98 | 102 |
| 99 void TracingControllerImpl::ResultFile::WriteTask( | 103 void TracingControllerImpl::ResultFile::WriteTask( |
| 100 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 104 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 101 if (!file_ || !events_str_ptr->data().size()) | 105 if (!file_ || !events_str_ptr->data().size()) |
| 102 return; | 106 return; |
| 103 | 107 |
| 104 // If there is already a result in the file, then put a commma | 108 // If there is already a result in the file, then put a comma |
| 105 // before the next batch of results. | 109 // before the next batch of results. |
| 106 if (has_at_least_one_result_) { | 110 if (has_at_least_one_result_) { |
| 107 size_t written = fwrite(",", 1, 1, file_); | 111 size_t written = fwrite(",", 1, 1, file_); |
| 108 DCHECK(written == 1); | 112 DCHECK(written == 1); |
| 109 } | 113 } |
| 110 has_at_least_one_result_ = true; | 114 has_at_least_one_result_ = true; |
| 111 size_t written = fwrite(events_str_ptr->data().c_str(), | 115 size_t written = fwrite(events_str_ptr->data().c_str(), |
| 112 events_str_ptr->data().size(), 1, | 116 events_str_ptr->data().size(), 1, |
| 113 file_); | 117 file_); |
| 114 DCHECK(written == 1); | 118 DCHECK(written == 1); |
| 115 } | 119 } |
| 116 | 120 |
| 117 void TracingControllerImpl::ResultFile::WriteSystemTraceTask( | 121 void TracingControllerImpl::ResultFile::WriteSystemTraceTask( |
| 118 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 122 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 119 system_trace_ = events_str_ptr; | 123 system_trace_ = events_str_ptr; |
| 120 } | 124 } |
| 121 | 125 |
| 122 void TracingControllerImpl::ResultFile::CloseTask( | 126 void TracingControllerImpl::ResultFile::CloseTask( |
| 123 const base::Closure& callback) { | 127 const base::Closure& callback) { |
| 124 if (!file_) | 128 if (!file_) |
| 125 return; | 129 return; |
| 126 | 130 |
| 127 const char* trailevents = "]"; | 131 const char* trailevents = "]"; |
| 128 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_); | 132 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_); |
| 129 DCHECK(written == 1); | 133 DCHECK(written == 1); |
| 130 | 134 |
| 131 if (system_trace_) { | 135 if (system_trace_) { |
| 136 #if defined(OS_WIN) |
| 137 // TODO(etienneb): This is ugly patch on windows. We should keep Value for |
| 138 // all OS instead of a string to represent system traces. A good idea |
| 139 // could be to wrap other. |
| 140 std::string json_string = system_trace_->data(); |
| 141 #else |
| 132 std::string json_string = base::GetQuotedJSONString(system_trace_->data()); | 142 std::string json_string = base::GetQuotedJSONString(system_trace_->data()); |
| 143 #endif |
| 133 | 144 |
| 134 const char* systemTraceHead = ", \"systemTraceEvents\": "; | 145 const char* systemTraceHead = ",\n\"systemTraceEvents\": "; |
| 135 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_); | 146 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_); |
| 136 DCHECK(written == 1); | 147 DCHECK(written == 1); |
| 137 | 148 |
| 138 written = fwrite(json_string.data(), json_string.size(), 1, file_); | 149 written = fwrite(json_string.data(), json_string.size(), 1, file_); |
| 139 DCHECK(written == 1); | 150 DCHECK(written == 1); |
| 140 | 151 |
| 141 system_trace_ = NULL; | 152 system_trace_ = NULL; |
| 142 } | 153 } |
| 143 | 154 |
| 144 const char* trailout = "}"; | 155 const char* trailout = "}"; |
| 145 written = fwrite(trailout, strlen(trailout), 1, file_); | 156 written = fwrite(trailout, strlen(trailout), 1, file_); |
| 146 DCHECK(written == 1); | 157 DCHECK(written == 1); |
| 147 base::CloseFile(file_); | 158 base::CloseFile(file_); |
| 148 file_ = NULL; | 159 file_ = NULL; |
| 149 | 160 |
| 150 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 161 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
| 151 } | 162 } |
| 152 | 163 |
| 153 | 164 |
| 154 TracingControllerImpl::TracingControllerImpl() : | 165 TracingControllerImpl::TracingControllerImpl() : |
| 155 pending_disable_recording_ack_count_(0), | 166 pending_disable_recording_ack_count_(0), |
| 156 pending_capture_monitoring_snapshot_ack_count_(0), | 167 pending_capture_monitoring_snapshot_ack_count_(0), |
| 157 pending_trace_buffer_percent_full_ack_count_(0), | 168 pending_trace_buffer_percent_full_ack_count_(0), |
| 158 maximum_trace_buffer_percent_full_(0), | 169 maximum_trace_buffer_percent_full_(0), |
| 159 // Tracing may have been enabled by ContentMainRunner if kTraceStartup | 170 // Tracing may have been enabled by ContentMainRunner if kTraceStartup |
| 160 // is specified in command line. | 171 // is specified in command line. |
| 161 #if defined(OS_CHROMEOS) | 172 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
| 162 is_system_tracing_(false), | 173 is_system_tracing_(false), |
| 163 #endif | 174 #endif |
| 164 is_recording_(TraceLog::GetInstance()->IsEnabled()), | 175 is_recording_(TraceLog::GetInstance()->IsEnabled()), |
| 165 is_monitoring_(false) { | 176 is_monitoring_(false) { |
| 166 } | 177 } |
| 167 | 178 |
| 168 TracingControllerImpl::~TracingControllerImpl() { | 179 TracingControllerImpl::~TracingControllerImpl() { |
| 169 // This is a Leaky instance. | 180 // This is a Leaky instance. |
| 170 NOTREACHED(); | 181 NOTREACHED(); |
| 171 } | 182 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 | 238 |
| 228 #if defined(OS_ANDROID) | 239 #if defined(OS_ANDROID) |
| 229 if (pending_get_categories_done_callback_.is_null()) | 240 if (pending_get_categories_done_callback_.is_null()) |
| 230 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 241 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 231 #endif | 242 #endif |
| 232 | 243 |
| 233 options_ = options; | 244 options_ = options; |
| 234 int trace_options = (options & RECORD_CONTINUOUSLY) ? | 245 int trace_options = (options & RECORD_CONTINUOUSLY) ? |
| 235 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; | 246 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; |
| 236 if (options & ENABLE_SAMPLING) { | 247 if (options & ENABLE_SAMPLING) { |
| 237 trace_options |= TraceLog::ENABLE_SAMPLING; | 248 trace_options |= TraceLog::ENABLE_SAMPLING; |
| 238 } | 249 } |
| 239 #if defined(OS_CHROMEOS) | 250 |
| 240 if (options & ENABLE_SYSTRACE) { | 251 if (options & ENABLE_SYSTRACE) { |
| 241 DCHECK(!is_system_tracing_); | 252 DCHECK(!is_system_tracing_); |
| 253 #if defined(OS_CHROMEOS) |
| 242 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> | 254 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
| 243 StartSystemTracing(); | 255 StartSystemTracing(); |
| 244 is_system_tracing_ = true; | 256 is_system_tracing_ = true; |
| 257 #elif defined(OS_WIN) |
| 258 is_system_tracing_ = |
| 259 EtwSystemEventConsumer::Get()->StartKernelSessionTracing(); |
| 260 EtwSystemEventConsumer::Get()->RequestStartTraceConsuming(); |
| 261 #endif |
| 245 } | 262 } |
| 246 #endif | 263 |
| 247 | 264 |
| 248 base::Closure on_enable_recording_done_callback = | 265 base::Closure on_enable_recording_done_callback = |
| 249 base::Bind(&TracingControllerImpl::OnEnableRecordingDone, | 266 base::Bind(&TracingControllerImpl::OnEnableRecordingDone, |
| 250 base::Unretained(this), | 267 base::Unretained(this), |
| 251 category_filter,trace_options, callback); | 268 category_filter, trace_options, callback); |
| 252 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 269 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 253 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, | 270 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, |
| 254 base::Unretained(this), | 271 base::Unretained(this), |
| 255 category_filter, | 272 category_filter, |
| 256 base::debug::TraceLog::RECORDING_MODE, | 273 base::debug::TraceLog::RECORDING_MODE, |
| 257 trace_options, | 274 trace_options, |
| 258 on_enable_recording_done_callback)); | 275 on_enable_recording_done_callback)); |
| 259 return true; | 276 return true; |
| 260 } | 277 } |
| 261 | 278 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 418 if (!callback.is_null()) | 435 if (!callback.is_null()) |
| 419 callback.Run(); | 436 callback.Run(); |
| 420 } | 437 } |
| 421 | 438 |
| 422 void TracingControllerImpl::GetMonitoringStatus( | 439 void TracingControllerImpl::GetMonitoringStatus( |
| 423 bool* out_enabled, | 440 bool* out_enabled, |
| 424 std::string* out_category_filter, | 441 std::string* out_category_filter, |
| 425 TracingController::Options* out_options) { | 442 TracingController::Options* out_options) { |
| 426 *out_enabled = is_monitoring_; | 443 *out_enabled = is_monitoring_; |
| 427 *out_category_filter = | 444 *out_category_filter = |
| 428 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(); | 445 TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(); |
| 429 *out_options = options_; | 446 *out_options = options_; |
| 430 } | 447 } |
| 431 | 448 |
| 432 bool TracingControllerImpl::CaptureMonitoringSnapshot( | 449 bool TracingControllerImpl::CaptureMonitoringSnapshot( |
| 433 const base::FilePath& result_file_path, | 450 const base::FilePath& result_file_path, |
| 434 const TracingFileResultCallback& callback) { | 451 const TracingFileResultCallback& callback) { |
| 435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 436 | 453 |
| 437 if (!can_disable_monitoring()) | 454 if (!can_disable_monitoring()) |
| 438 return false; | 455 return false; |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 return; | 676 return; |
| 660 | 677 |
| 661 OnDisableRecordingComplete(); | 678 OnDisableRecordingComplete(); |
| 662 } | 679 } |
| 663 | 680 |
| 664 void TracingControllerImpl::OnDisableRecordingComplete() { | 681 void TracingControllerImpl::OnDisableRecordingComplete() { |
| 665 // All acks (including from the subprocesses and the local trace) have been | 682 // All acks (including from the subprocesses and the local trace) have been |
| 666 // received. | 683 // received. |
| 667 is_recording_ = false; | 684 is_recording_ = false; |
| 668 | 685 |
| 686 if (is_system_tracing_) { |
| 669 #if defined(OS_CHROMEOS) | 687 #if defined(OS_CHROMEOS) |
| 670 if (is_system_tracing_) { | |
| 671 // Disable system tracing now that the local trace has shutdown. | 688 // Disable system tracing now that the local trace has shutdown. |
| 672 // This must be done last because we potentially need to push event | 689 // This must be done last because we potentially need to push event |
| 673 // records into the system event log for synchronizing system event | 690 // records into the system event log for synchronizing system event |
| 674 // timestamps with chrome event timestamps--and since the system event | 691 // timestamps with chrome event timestamps--and since the system event |
| 675 // log is a ring-buffer (on linux) adding them at the end is the only | 692 // log is a ring-buffer (on linux) adding them at the end is the only |
| 676 // way we're confident we'll have them in the final result. | 693 // way we're confident we'll have them in the final result. |
| 677 is_system_tracing_ = false; | 694 is_system_tracing_ = false; |
| 678 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> | 695 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
| 679 RequestStopSystemTracing( | 696 RequestStopSystemTracing( |
| 680 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked, | 697 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked, |
| 681 base::Unretained(this))); | 698 base::Unretained(this))); |
| 699 #elif defined(OS_WIN) |
| 700 // Disable system tracing. |
| 701 EtwSystemEventConsumer::Get()->StopKernelSessionTracing(); |
| 702 is_system_tracing_ = false; |
| 703 |
| 704 // Request events to be flushed. |
| 705 EtwSystemEventConsumer::Get()->RequestStopTraceConsuming( |
| 706 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked, |
| 707 base::Unretained(this))); |
| 708 #endif |
| 682 return; | 709 return; |
| 683 } | 710 } |
| 684 #endif | |
| 685 | 711 |
| 686 // Trigger callback if one is set. | 712 // Trigger callback if one is set. |
| 687 if (!pending_get_categories_done_callback_.is_null()) { | 713 if (!pending_get_categories_done_callback_.is_null()) { |
| 688 pending_get_categories_done_callback_.Run(known_category_groups_); | 714 pending_get_categories_done_callback_.Run(known_category_groups_); |
| 689 pending_get_categories_done_callback_.Reset(); | 715 pending_get_categories_done_callback_.Reset(); |
| 690 } else if (result_file_) { | 716 } else if (result_file_) { |
| 691 result_file_->Close( | 717 result_file_->Close( |
| 692 base::Bind(&TracingControllerImpl::OnResultFileClosed, | 718 base::Bind(&TracingControllerImpl::OnResultFileClosed, |
| 693 base::Unretained(this))); | 719 base::Unretained(this))); |
| 694 } | 720 } |
| 695 } | 721 } |
| 696 | 722 |
| 697 void TracingControllerImpl::OnResultFileClosed() { | 723 void TracingControllerImpl::OnResultFileClosed() { |
| 698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 724 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 699 | 725 |
| 700 if (!result_file_) | 726 if (!result_file_) |
| 701 return; | 727 return; |
| 702 | 728 |
| 703 if (!pending_disable_recording_done_callback_.is_null()) { | 729 if (!pending_disable_recording_done_callback_.is_null()) { |
| 704 pending_disable_recording_done_callback_.Run(result_file_->path()); | 730 pending_disable_recording_done_callback_.Run(result_file_->path()); |
| 705 pending_disable_recording_done_callback_.Reset(); | 731 pending_disable_recording_done_callback_.Reset(); |
| 706 } | 732 } |
| 707 result_file_.reset(); | 733 result_file_.reset(); |
| 708 } | 734 } |
| 709 | 735 |
| 710 #if defined(OS_CHROMEOS) | 736 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
| 711 void TracingControllerImpl::OnEndSystemTracingAcked( | 737 void TracingControllerImpl::OnEndSystemTracingAcked( |
| 712 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 738 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 713 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 739 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 714 | 740 |
| 715 if (result_file_) | 741 if (result_file_) |
| 716 result_file_->WriteSystemTrace(events_str_ptr); | 742 result_file_->WriteSystemTrace(events_str_ptr); |
| 717 | 743 |
| 718 DCHECK(!is_system_tracing_); | 744 DCHECK(!is_system_tracing_); |
| 719 OnDisableRecordingComplete(); | 745 OnDisableRecordingComplete(); |
| 720 } | 746 } |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 866 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 892 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 867 base::Bind(&TracingControllerImpl::OnWatchEventMatched, | 893 base::Bind(&TracingControllerImpl::OnWatchEventMatched, |
| 868 base::Unretained(this))); | 894 base::Unretained(this))); |
| 869 return; | 895 return; |
| 870 } | 896 } |
| 871 | 897 |
| 872 if (!watch_event_callback_.is_null()) | 898 if (!watch_event_callback_.is_null()) |
| 873 watch_event_callback_.Run(); | 899 watch_event_callback_.Run(); |
| 874 } | 900 } |
| 875 | 901 |
| 876 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) | 902 void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) { |
| 877 { | |
| 878 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end()); | 903 DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end()); |
| 879 tracing_uis_.insert(tracing_ui); | 904 tracing_uis_.insert(tracing_ui); |
| 880 } | 905 } |
| 881 | 906 |
| 882 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) | 907 void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) { |
| 883 { | |
| 884 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui); | 908 std::set<TracingUI*>::iterator it = tracing_uis_.find(tracing_ui); |
| 885 DCHECK(it != tracing_uis_.end()); | 909 DCHECK(it != tracing_uis_.end()); |
| 886 tracing_uis_.erase(it); | 910 tracing_uis_.erase(it); |
| 887 } | 911 } |
| 888 | 912 |
| 889 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) | 913 void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) { |
| 890 { | |
| 891 if (is_monitoring_ == is_monitoring) | 914 if (is_monitoring_ == is_monitoring) |
| 892 return; | 915 return; |
| 893 | 916 |
| 894 is_monitoring_ = is_monitoring; | 917 is_monitoring_ = is_monitoring; |
| 895 #if !defined(OS_ANDROID) | 918 #if !defined(OS_ANDROID) |
| 896 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); | 919 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); |
| 897 it != tracing_uis_.end(); it++) { | 920 it != tracing_uis_.end(); it++) { |
| 898 (*it)->OnMonitoringStateChanged(is_monitoring); | 921 (*it)->OnMonitoringStateChanged(is_monitoring); |
| 899 } | 922 } |
| 900 #endif | 923 #endif |
| 901 } | 924 } |
| 902 | 925 |
| 903 } // namespace content | 926 } // namespace content |
| OLD | NEW |