Chromium Code Reviews| 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/debug/trace_event.h" | 7 #include "base/debug/trace_event.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" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 using base::debug::TraceOptions; | 27 using base::debug::TraceOptions; |
| 28 using base::debug::CategoryFilter; | 28 using base::debug::CategoryFilter; |
| 29 | 29 |
| 30 namespace content { | 30 namespace content { |
| 31 | 31 |
| 32 namespace { | 32 namespace { |
| 33 | 33 |
| 34 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = | 34 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = |
| 35 LAZY_INSTANCE_INITIALIZER; | 35 LAZY_INSTANCE_INITIALIZER; |
| 36 | 36 |
| 37 class FileTraceDataSink : public TracingController::TraceDataSink { | |
| 38 public: | |
| 39 explicit FileTraceDataSink( | |
| 40 const base::FilePath& trace_file_path, const base::Closure& callback) | |
| 41 : file_path_(trace_file_path), | |
| 42 completion_callback_(callback), | |
| 43 file_(NULL) { | |
| 44 } | |
| 45 | |
| 46 virtual void AddTraceChunk(const std::string& chunk) OVERRIDE { | |
| 47 std::string tmp = chunk; | |
| 48 scoped_refptr<base::RefCountedString> chunk_ptr = | |
| 49 base::RefCountedString::TakeString(&tmp); | |
| 50 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 51 base::Bind(&FileTraceDataSink::AddTraceChunkOnFileThread, | |
| 52 base::Unretained(this), chunk_ptr)); | |
| 53 } | |
| 54 virtual void SetSystemTrace(const std::string& data) OVERRIDE { | |
| 55 system_trace_ = data; | |
| 56 } | |
| 57 virtual void Close() OVERRIDE { | |
| 58 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 59 base::Bind(&FileTraceDataSink::CloseOnFileThread, | |
| 60 base::Unretained(this))); | |
| 61 } | |
| 62 | |
| 63 private: | |
| 64 virtual ~FileTraceDataSink() {} | |
| 65 | |
| 66 void AddTraceChunkOnFileThread( | |
| 67 const scoped_refptr<base::RefCountedString> chunk) { | |
| 68 if (!OpenFileIfNeededOnFileThread()) | |
| 69 return; | |
| 70 fwrite(chunk->data().c_str(), strlen(chunk->data().c_str()), 1, file_); | |
| 71 } | |
| 72 | |
| 73 bool OpenFileIfNeededOnFileThread() { | |
| 74 if (file_) | |
| 75 return true; | |
| 76 file_ = base::OpenFile(file_path_, "w"); | |
| 77 if (!file_) { | |
| 78 LOG(ERROR) << "Failed to open " << file_path_.value(); | |
| 79 return false; | |
| 80 } | |
| 81 const char preamble[] = "{\"traceEvents\": ["; | |
| 82 fwrite(preamble, strlen(preamble), 1, file_); | |
| 83 return true; | |
| 84 } | |
| 85 | |
| 86 void CloseOnFileThread() { | |
| 87 if (OpenFileIfNeededOnFileThread()) { | |
| 88 fputc(']', file_); | |
| 89 if (!system_trace_.empty()) { | |
| 90 const char systemTraceEvents[] = ",\"systemTraceEvents\":["; | |
| 91 fwrite(systemTraceEvents, strlen(systemTraceEvents), 1, file_); | |
| 92 fwrite(system_trace_.c_str(), strlen(system_trace_.c_str()), 1, file_); | |
| 93 fputc(']', file_); | |
| 94 } | |
| 95 fputc('}', file_); | |
| 96 base::CloseFile(file_); | |
| 97 } | |
| 98 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | |
| 99 base::Bind(&FileTraceDataSink::FinalizeOnUIThread, | |
| 100 base::Unretained(this))); | |
| 101 } | |
| 102 | |
| 103 void FinalizeOnUIThread() { | |
| 104 completion_callback_.Run(); | |
| 105 delete this; | |
| 106 } | |
| 107 | |
| 108 base::FilePath file_path_; | |
| 109 base::Closure completion_callback_; | |
| 110 FILE* file_; | |
| 111 std::string system_trace_; | |
| 112 }; | |
| 113 | |
| 114 class StringTraceDataSink : public TracingController::TraceDataSink { | |
| 115 public: | |
| 116 typedef base::Callback<void(base::RefCountedMemory*)> | |
| 117 CompletionCallback; | |
| 118 | |
| 119 explicit StringTraceDataSink(CompletionCallback callback) | |
| 120 : completion_callback_(callback) { | |
| 121 } | |
| 122 | |
| 123 // TracingController::TraceDataSink implementation | |
| 124 virtual void AddTraceChunk(const std::string& chunk) OVERRIDE { | |
| 125 if (!trace_.empty()) | |
| 126 trace_ += ","; | |
| 127 trace_ += chunk; | |
| 128 } | |
| 129 virtual void SetSystemTrace(const std::string& data) OVERRIDE { | |
| 130 system_trace_ = data; | |
| 131 } | |
| 132 virtual void Close() OVERRIDE { | |
| 133 std::string result = "{\"traceEvents\":[" + trace_ + "]"; | |
| 134 if (!system_trace_.empty()) | |
| 135 result += ",\"systemTraceEvents\":[" + system_trace_ + "]"; | |
| 136 result += "}"; | |
| 137 | |
| 138 completion_callback_.Run(base::RefCountedString::TakeString(&result)); | |
| 139 delete this; | |
|
dsinclair
2014/09/04 18:03:12
I'm not a fan of the delete this on the Close() me
| |
| 140 } | |
| 141 | |
| 142 private: | |
| 143 virtual ~StringTraceDataSink() {} | |
| 144 | |
| 145 std::string trace_; | |
| 146 std::string system_trace_; | |
| 147 CompletionCallback completion_callback_; | |
| 148 }; | |
| 149 | |
| 37 } // namespace | 150 } // namespace |
| 38 | 151 |
| 39 TracingController* TracingController::GetInstance() { | 152 TracingController* TracingController::GetInstance() { |
| 40 return TracingControllerImpl::GetInstance(); | 153 return TracingControllerImpl::GetInstance(); |
| 41 } | 154 } |
| 42 | 155 |
| 43 class TracingControllerImpl::ResultFile { | 156 TracingController::TraceDataSink* TracingControllerImpl::CreateStringSink( |
| 44 public: | 157 const base::Callback<void(base::RefCountedMemory*)>& callback) { |
| 45 explicit ResultFile(const base::FilePath& path); | 158 return new StringTraceDataSink(callback); |
| 46 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
| 47 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 48 base::Bind(&TracingControllerImpl::ResultFile::WriteTask, | |
| 49 base::Unretained(this), events_str_ptr)); | |
| 50 } | |
| 51 void Close(const base::Closure& callback) { | |
| 52 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 53 base::Bind(&TracingControllerImpl::ResultFile::CloseTask, | |
| 54 base::Unretained(this), callback)); | |
| 55 } | |
| 56 void WriteSystemTrace( | |
| 57 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
| 58 BrowserThread::PostTask( | |
| 59 BrowserThread::FILE, | |
| 60 FROM_HERE, | |
| 61 base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask, | |
| 62 base::Unretained(this), events_str_ptr)); | |
| 63 } | |
| 64 | |
| 65 const base::FilePath& path() const { return path_; } | |
| 66 | |
| 67 private: | |
| 68 void OpenTask(); | |
| 69 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr); | |
| 70 void WriteSystemTraceTask( | |
| 71 const scoped_refptr<base::RefCountedString>& events_str_ptr); | |
| 72 void CloseTask(const base::Closure& callback); | |
| 73 | |
| 74 FILE* file_; | |
| 75 base::FilePath path_; | |
| 76 bool has_at_least_one_result_; | |
| 77 scoped_refptr<base::RefCountedString> system_trace_; | |
| 78 | |
| 79 DISALLOW_COPY_AND_ASSIGN(ResultFile); | |
| 80 }; | |
| 81 | |
| 82 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path) | |
| 83 : file_(NULL), | |
| 84 path_(path), | |
| 85 has_at_least_one_result_(false) { | |
| 86 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | |
| 87 base::Bind(&TracingControllerImpl::ResultFile::OpenTask, | |
| 88 base::Unretained(this))); | |
| 89 } | 159 } |
| 90 | 160 |
| 91 void TracingControllerImpl::ResultFile::OpenTask() { | 161 TracingController::TraceDataSink* TracingControllerImpl::CreateFileSink( |
| 92 if (path_.empty()) | 162 const base::FilePath& file_path, const base::Closure& callback) { |
| 93 base::CreateTemporaryFile(&path_); | 163 return new FileTraceDataSink(file_path, callback); |
| 94 file_ = base::OpenFile(path_, "w"); | |
| 95 if (!file_) { | |
| 96 LOG(ERROR) << "Failed to open " << path_.value(); | |
| 97 return; | |
| 98 } | |
| 99 const char* preamble = "{\"traceEvents\": ["; | |
| 100 size_t written = fwrite(preamble, strlen(preamble), 1, file_); | |
| 101 DCHECK(written == 1); | |
| 102 } | 164 } |
| 103 | 165 |
| 104 void TracingControllerImpl::ResultFile::WriteTask( | |
| 105 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
| 106 if (!file_ || !events_str_ptr->data().size()) | |
| 107 return; | |
| 108 | |
| 109 // If there is already a result in the file, then put a comma | |
| 110 // before the next batch of results. | |
| 111 if (has_at_least_one_result_) { | |
| 112 size_t written = fwrite(",", 1, 1, file_); | |
| 113 DCHECK(written == 1); | |
| 114 } | |
| 115 has_at_least_one_result_ = true; | |
| 116 size_t written = fwrite(events_str_ptr->data().c_str(), | |
| 117 events_str_ptr->data().size(), 1, | |
| 118 file_); | |
| 119 DCHECK(written == 1); | |
| 120 } | |
| 121 | |
| 122 void TracingControllerImpl::ResultFile::WriteSystemTraceTask( | |
| 123 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | |
| 124 system_trace_ = events_str_ptr; | |
| 125 } | |
| 126 | |
| 127 void TracingControllerImpl::ResultFile::CloseTask( | |
| 128 const base::Closure& callback) { | |
| 129 if (!file_) | |
| 130 return; | |
| 131 | |
| 132 const char* trailevents = "]"; | |
| 133 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_); | |
| 134 DCHECK(written == 1); | |
| 135 | |
| 136 if (system_trace_.get()) { | |
| 137 #if defined(OS_WIN) | |
| 138 // The Windows kernel events are kept into a JSon format stored as string | |
| 139 // and must not be escaped. | |
| 140 std::string json_string = system_trace_->data(); | |
| 141 #else | |
| 142 std::string json_string = base::GetQuotedJSONString(system_trace_->data()); | |
| 143 #endif | |
| 144 | |
| 145 const char* systemTraceHead = ",\n\"systemTraceEvents\": "; | |
| 146 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_); | |
| 147 DCHECK(written == 1); | |
| 148 | |
| 149 written = fwrite(json_string.data(), json_string.size(), 1, file_); | |
| 150 DCHECK(written == 1); | |
| 151 | |
| 152 system_trace_ = NULL; | |
| 153 } | |
| 154 | |
| 155 const char* trailout = "}"; | |
| 156 written = fwrite(trailout, strlen(trailout), 1, file_); | |
| 157 DCHECK(written == 1); | |
| 158 base::CloseFile(file_); | |
| 159 file_ = NULL; | |
| 160 | |
| 161 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | |
| 162 } | |
| 163 | |
| 164 | |
| 165 TracingControllerImpl::TracingControllerImpl() : | 166 TracingControllerImpl::TracingControllerImpl() : |
| 166 pending_disable_recording_ack_count_(0), | 167 pending_disable_recording_ack_count_(0), |
| 167 pending_capture_monitoring_snapshot_ack_count_(0), | 168 pending_capture_monitoring_snapshot_ack_count_(0), |
| 168 pending_trace_buffer_percent_full_ack_count_(0), | 169 pending_trace_buffer_percent_full_ack_count_(0), |
| 169 maximum_trace_buffer_percent_full_(0), | 170 maximum_trace_buffer_percent_full_(0), |
| 170 // Tracing may have been enabled by ContentMainRunner if kTraceStartup | 171 // Tracing may have been enabled by ContentMainRunner if kTraceStartup |
| 171 // is specified in command line. | 172 // is specified in command line. |
| 172 #if defined(OS_CHROMEOS) || defined(OS_WIN) | 173 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
| 173 is_system_tracing_(false), | 174 is_system_tracing_(false), |
| 174 #endif | 175 #endif |
| 175 is_recording_(TraceLog::GetInstance()->IsEnabled()), | 176 is_recording_(TraceLog::GetInstance()->IsEnabled()), |
| 176 is_monitoring_(false) { | 177 is_monitoring_(false), |
| 178 trace_data_sink_(NULL), | |
| 179 monitoring_data_sink_(NULL) { | |
| 177 } | 180 } |
| 178 | 181 |
| 179 TracingControllerImpl::~TracingControllerImpl() { | 182 TracingControllerImpl::~TracingControllerImpl() { |
| 180 // This is a Leaky instance. | 183 // This is a Leaky instance. |
| 181 NOTREACHED(); | 184 NOTREACHED(); |
| 182 } | 185 } |
| 183 | 186 |
| 184 TracingControllerImpl* TracingControllerImpl::GetInstance() { | 187 TracingControllerImpl* TracingControllerImpl::GetInstance() { |
| 185 return g_controller.Pointer(); | 188 return g_controller.Pointer(); |
| 186 } | 189 } |
| 187 | 190 |
| 188 bool TracingControllerImpl::GetCategories( | 191 bool TracingControllerImpl::GetCategories( |
| 189 const GetCategoriesDoneCallback& callback) { | 192 const GetCategoriesDoneCallback& callback) { |
| 190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 191 | 194 |
| 192 // Known categories come back from child processes with the EndTracingAck | 195 // Known categories come back from child processes with the EndTracingAck |
| 193 // message. So to get known categories, just begin and end tracing immediately | 196 // message. So to get known categories, just begin and end tracing immediately |
| 194 // afterwards. This will ping all the child processes for categories. | 197 // afterwards. This will ping all the child processes for categories. |
| 195 pending_get_categories_done_callback_ = callback; | 198 pending_get_categories_done_callback_ = callback; |
| 196 if (!EnableRecording( | 199 if (!EnableRecording( |
| 197 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) { | 200 CategoryFilter("*"), TraceOptions(), EnableRecordingDoneCallback())) { |
| 198 pending_get_categories_done_callback_.Reset(); | 201 pending_get_categories_done_callback_.Reset(); |
| 199 return false; | 202 return false; |
| 200 } | 203 } |
| 201 | 204 |
| 202 bool ok = DisableRecording(base::FilePath(), TracingFileResultCallback()); | 205 bool ok = DisableRecording(NULL); |
| 203 DCHECK(ok); | 206 DCHECK(ok); |
| 204 return true; | 207 return true; |
| 205 } | 208 } |
| 206 | 209 |
| 207 void TracingControllerImpl::SetEnabledOnFileThread( | 210 void TracingControllerImpl::SetEnabledOnFileThread( |
| 208 const CategoryFilter& category_filter, | 211 const CategoryFilter& category_filter, |
| 209 int mode, | 212 int mode, |
| 210 const TraceOptions& trace_options, | 213 const TraceOptions& trace_options, |
| 211 const base::Closure& callback) { | 214 const base::Closure& callback) { |
| 212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 215 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 278 // Notify all child processes. | 281 // Notify all child processes. |
| 279 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | 282 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); |
| 280 it != trace_message_filters_.end(); ++it) { | 283 it != trace_message_filters_.end(); ++it) { |
| 281 it->get()->SendBeginTracing(category_filter, trace_options); | 284 it->get()->SendBeginTracing(category_filter, trace_options); |
| 282 } | 285 } |
| 283 | 286 |
| 284 if (!callback.is_null()) | 287 if (!callback.is_null()) |
| 285 callback.Run(); | 288 callback.Run(); |
| 286 } | 289 } |
| 287 | 290 |
| 288 bool TracingControllerImpl::DisableRecording( | 291 bool TracingControllerImpl::DisableRecording(TraceDataSink* trace_data_sink) { |
| 289 const base::FilePath& result_file_path, | |
| 290 const TracingFileResultCallback& callback) { | |
| 291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 292 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 292 | 293 |
| 293 if (!can_disable_recording()) | 294 if (!can_disable_recording()) |
| 294 return false; | 295 return false; |
| 295 | 296 |
| 296 trace_options_ = TraceOptions(); | 297 trace_options_ = TraceOptions(); |
| 297 // Disable local trace early to avoid traces during end-tracing process from | 298 // Disable local trace early to avoid traces during end-tracing process from |
| 298 // interfering with the process. | 299 // interfering with the process. |
| 299 base::Closure on_disable_recording_done_callback = | 300 base::Closure on_disable_recording_done_callback = |
| 300 base::Bind(&TracingControllerImpl::OnDisableRecordingDone, | 301 base::Bind(&TracingControllerImpl::OnDisableRecordingDone, |
| 301 base::Unretained(this), | 302 base::Unretained(this), trace_data_sink); |
| 302 result_file_path, callback); | |
| 303 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 303 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 304 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, | 304 base::Bind(&TracingControllerImpl::SetDisabledOnFileThread, |
| 305 base::Unretained(this), | 305 base::Unretained(this), |
| 306 on_disable_recording_done_callback)); | 306 on_disable_recording_done_callback)); |
| 307 return true; | 307 return true; |
| 308 } | 308 } |
| 309 | 309 |
| 310 void TracingControllerImpl::OnDisableRecordingDone( | 310 void TracingControllerImpl::OnDisableRecordingDone( |
| 311 const base::FilePath& result_file_path, | 311 TraceDataSink* trace_data_sink) { |
| 312 const TracingFileResultCallback& callback) { | |
| 313 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 314 | 313 |
| 315 pending_disable_recording_done_callback_ = callback; | |
| 316 | |
| 317 #if defined(OS_ANDROID) | 314 #if defined(OS_ANDROID) |
| 318 if (pending_get_categories_done_callback_.is_null()) | 315 if (pending_get_categories_done_callback_.is_null()) |
| 319 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 316 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 320 #endif | 317 #endif |
| 321 | 318 |
| 322 if (!callback.is_null() || !result_file_path.empty()) | 319 trace_data_sink_ = trace_data_sink; |
| 323 result_file_.reset(new ResultFile(result_file_path)); | |
| 324 | 320 |
| 325 // Count myself (local trace) in pending_disable_recording_ack_count_, | 321 // Count myself (local trace) in pending_disable_recording_ack_count_, |
| 326 // acked below. | 322 // acked below. |
| 327 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; | 323 pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1; |
| 328 pending_disable_recording_filters_ = trace_message_filters_; | 324 pending_disable_recording_filters_ = trace_message_filters_; |
| 329 | 325 |
| 330 #if defined(OS_CHROMEOS) || defined(OS_WIN) | 326 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
| 331 if (is_system_tracing_) { | 327 if (is_system_tracing_) { |
| 332 // Disable system tracing. | 328 // Disable system tracing. |
| 333 is_system_tracing_ = false; | 329 is_system_tracing_ = false; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 435 const DisableMonitoringDoneCallback& callback) { | 431 const DisableMonitoringDoneCallback& callback) { |
| 436 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 437 | 433 |
| 438 OnMonitoringStateChanged(false); | 434 OnMonitoringStateChanged(false); |
| 439 | 435 |
| 440 // Notify all child processes. | 436 // Notify all child processes. |
| 441 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); | 437 for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin(); |
| 442 it != trace_message_filters_.end(); ++it) { | 438 it != trace_message_filters_.end(); ++it) { |
| 443 it->get()->SendDisableMonitoring(); | 439 it->get()->SendDisableMonitoring(); |
| 444 } | 440 } |
| 445 | |
| 446 if (!callback.is_null()) | 441 if (!callback.is_null()) |
| 447 callback.Run(); | 442 callback.Run(); |
| 448 } | 443 } |
| 449 | 444 |
| 450 void TracingControllerImpl::GetMonitoringStatus( | 445 void TracingControllerImpl::GetMonitoringStatus( |
| 451 bool* out_enabled, | 446 bool* out_enabled, |
| 452 CategoryFilter* out_category_filter, | 447 CategoryFilter* out_category_filter, |
| 453 TraceOptions* out_trace_options) { | 448 TraceOptions* out_trace_options) { |
| 454 *out_enabled = is_monitoring_; | 449 *out_enabled = is_monitoring_; |
| 455 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter(); | 450 *out_category_filter = TraceLog::GetInstance()->GetCurrentCategoryFilter(); |
| 456 *out_trace_options = trace_options_; | 451 *out_trace_options = trace_options_; |
| 457 } | 452 } |
| 458 | 453 |
| 459 bool TracingControllerImpl::CaptureMonitoringSnapshot( | 454 bool TracingControllerImpl::CaptureMonitoringSnapshot( |
| 460 const base::FilePath& result_file_path, | 455 TraceDataSink* monitoring_data_sink) { |
| 461 const TracingFileResultCallback& callback) { | |
| 462 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 456 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 463 | 457 |
| 464 if (!can_disable_monitoring()) | 458 if (!can_disable_monitoring()) |
| 465 return false; | 459 return false; |
| 466 | 460 |
| 467 if (callback.is_null() && result_file_path.empty()) | 461 if (!monitoring_data_sink) |
| 468 return false; | 462 return false; |
| 469 | 463 |
| 470 pending_capture_monitoring_snapshot_done_callback_ = callback; | 464 monitoring_data_sink_ = monitoring_data_sink; |
| 471 monitoring_snapshot_file_.reset(new ResultFile(result_file_path)); | |
| 472 | 465 |
| 473 // Count myself in pending_capture_monitoring_snapshot_ack_count_, | 466 // Count myself in pending_capture_monitoring_snapshot_ack_count_, |
| 474 // acked below. | 467 // acked below. |
| 475 pending_capture_monitoring_snapshot_ack_count_ = | 468 pending_capture_monitoring_snapshot_ack_count_ = |
| 476 trace_message_filters_.size() + 1; | 469 trace_message_filters_.size() + 1; |
| 477 pending_capture_monitoring_filters_ = trace_message_filters_; | 470 pending_capture_monitoring_filters_ = trace_message_filters_; |
| 478 | 471 |
| 479 // Handle special case of zero child processes by immediately flushing the | 472 // Handle special case of zero child processes by immediately flushing the |
| 480 // trace log. Once the flush has completed the caller will be notified that | 473 // trace log. Once the flush has completed the caller will be notified that |
| 481 // the capture snapshot has ended. | 474 // the capture snapshot has ended. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 678 // called with the last of the local trace data. | 671 // called with the last of the local trace data. |
| 679 TraceLog::GetInstance()->Flush( | 672 TraceLog::GetInstance()->Flush( |
| 680 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | 673 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, |
| 681 base::Unretained(this))); | 674 base::Unretained(this))); |
| 682 return; | 675 return; |
| 683 } | 676 } |
| 684 | 677 |
| 685 if (pending_disable_recording_ack_count_ != 0) | 678 if (pending_disable_recording_ack_count_ != 0) |
| 686 return; | 679 return; |
| 687 | 680 |
| 688 OnDisableRecordingComplete(); | |
| 689 } | |
| 690 | |
| 691 void TracingControllerImpl::OnDisableRecordingComplete() { | |
| 692 // All acks (including from the subprocesses and the local trace) have been | 681 // All acks (including from the subprocesses and the local trace) have been |
| 693 // received. | 682 // received. |
| 694 is_recording_ = false; | 683 is_recording_ = false; |
| 695 | 684 |
| 696 // Trigger callback if one is set. | 685 // Trigger callback if one is set. |
| 697 if (!pending_get_categories_done_callback_.is_null()) { | 686 if (!pending_get_categories_done_callback_.is_null()) { |
| 698 pending_get_categories_done_callback_.Run(known_category_groups_); | 687 pending_get_categories_done_callback_.Run(known_category_groups_); |
| 699 pending_get_categories_done_callback_.Reset(); | 688 pending_get_categories_done_callback_.Reset(); |
| 700 } else if (result_file_) { | 689 } else if (trace_data_sink_) { |
| 701 result_file_->Close( | 690 trace_data_sink_->Close(); |
| 702 base::Bind(&TracingControllerImpl::OnResultFileClosed, | 691 trace_data_sink_ = 0; |
| 703 base::Unretained(this))); | |
| 704 } | 692 } |
| 705 } | 693 } |
| 706 | 694 |
| 707 void TracingControllerImpl::OnResultFileClosed() { | |
| 708 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 709 | |
| 710 if (!result_file_) | |
| 711 return; | |
| 712 | |
| 713 if (!pending_disable_recording_done_callback_.is_null()) { | |
| 714 pending_disable_recording_done_callback_.Run(result_file_->path()); | |
| 715 pending_disable_recording_done_callback_.Reset(); | |
| 716 } | |
| 717 result_file_.reset(); | |
| 718 } | |
| 719 | |
| 720 #if defined(OS_CHROMEOS) || defined(OS_WIN) | 695 #if defined(OS_CHROMEOS) || defined(OS_WIN) |
| 721 void TracingControllerImpl::OnEndSystemTracingAcked( | 696 void TracingControllerImpl::OnEndSystemTracingAcked( |
| 722 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 697 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 723 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 724 | 699 |
| 725 if (result_file_) | 700 if (trace_data_sink_) { |
| 726 result_file_->WriteSystemTrace(events_str_ptr); | 701 #if defined(OS_WIN) |
| 727 | 702 // The Windows kernel events are kept into a JSon format stored as string |
| 703 // and must not be escaped. | |
| 704 std::string json_string = events_str_ptr_->data(); | |
| 705 #else | |
| 706 std::string json_string = | |
| 707 base::GetQuotedJSONString(events_str_ptr_->data()); | |
| 708 #endif | |
| 709 trace_data_sink_->SetSystemTrace(json_string); | |
| 710 } | |
| 728 DCHECK(!is_system_tracing_); | 711 DCHECK(!is_system_tracing_); |
| 729 std::vector<std::string> category_groups; | 712 std::vector<std::string> category_groups; |
| 730 OnDisableRecordingAcked(NULL, category_groups); | 713 OnDisableRecordingAcked(NULL, category_groups); |
| 731 } | 714 } |
| 732 #endif | 715 #endif |
| 733 | 716 |
| 734 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( | 717 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( |
| 735 TraceMessageFilter* trace_message_filter) { | 718 TraceMessageFilter* trace_message_filter) { |
| 736 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 719 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 737 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 720 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 756 // will be called with the last of the local trace data. | 739 // will be called with the last of the local trace data. |
| 757 TraceLog::GetInstance()->FlushButLeaveBufferIntact( | 740 TraceLog::GetInstance()->FlushButLeaveBufferIntact( |
| 758 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, | 741 base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, |
| 759 base::Unretained(this))); | 742 base::Unretained(this))); |
| 760 return; | 743 return; |
| 761 } | 744 } |
| 762 | 745 |
| 763 if (pending_capture_monitoring_snapshot_ack_count_ != 0) | 746 if (pending_capture_monitoring_snapshot_ack_count_ != 0) |
| 764 return; | 747 return; |
| 765 | 748 |
| 766 if (monitoring_snapshot_file_) { | 749 if (monitoring_data_sink_) { |
| 767 monitoring_snapshot_file_->Close( | 750 monitoring_data_sink_->Close(); |
| 768 base::Bind(&TracingControllerImpl::OnMonitoringSnapshotFileClosed, | 751 monitoring_data_sink_ = NULL; |
| 769 base::Unretained(this))); | |
| 770 } | 752 } |
| 771 } | 753 } |
| 772 | 754 |
| 773 void TracingControllerImpl::OnMonitoringSnapshotFileClosed() { | |
| 774 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 775 | |
| 776 if (!monitoring_snapshot_file_) | |
| 777 return; | |
| 778 | |
| 779 if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) { | |
| 780 pending_capture_monitoring_snapshot_done_callback_.Run( | |
| 781 monitoring_snapshot_file_->path()); | |
| 782 pending_capture_monitoring_snapshot_done_callback_.Reset(); | |
| 783 } | |
| 784 monitoring_snapshot_file_.reset(); | |
| 785 } | |
| 786 | |
| 787 void TracingControllerImpl::OnTraceDataCollected( | 755 void TracingControllerImpl::OnTraceDataCollected( |
| 788 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 756 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 789 // OnTraceDataCollected may be called from any browser thread, either by the | 757 // OnTraceDataCollected may be called from any browser thread, either by the |
| 790 // local event trace system or from child processes via TraceMessageFilter. | 758 // local event trace system or from child processes via TraceMessageFilter. |
| 791 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 759 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 792 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 760 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 793 base::Bind(&TracingControllerImpl::OnTraceDataCollected, | 761 base::Bind(&TracingControllerImpl::OnTraceDataCollected, |
| 794 base::Unretained(this), events_str_ptr)); | 762 base::Unretained(this), events_str_ptr)); |
| 795 return; | 763 return; |
| 796 } | 764 } |
| 797 | 765 |
| 798 if (result_file_) | 766 if (trace_data_sink_) |
| 799 result_file_->Write(events_str_ptr); | 767 trace_data_sink_->AddTraceChunk(events_str_ptr->data()); |
| 800 } | 768 } |
| 801 | 769 |
| 802 void TracingControllerImpl::OnMonitoringTraceDataCollected( | 770 void TracingControllerImpl::OnMonitoringTraceDataCollected( |
| 803 const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 771 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 804 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 772 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 805 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 773 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 806 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected, | 774 base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected, |
| 807 base::Unretained(this), events_str_ptr)); | 775 base::Unretained(this), events_str_ptr)); |
| 808 return; | 776 return; |
| 809 } | 777 } |
| 810 | 778 |
| 811 if (monitoring_snapshot_file_) | 779 if (monitoring_data_sink_) |
| 812 monitoring_snapshot_file_->Write(events_str_ptr); | 780 monitoring_data_sink_->AddTraceChunk(events_str_ptr->data()); |
| 813 } | 781 } |
| 814 | 782 |
| 815 void TracingControllerImpl::OnLocalTraceDataCollected( | 783 void TracingControllerImpl::OnLocalTraceDataCollected( |
| 816 const scoped_refptr<base::RefCountedString>& events_str_ptr, | 784 const scoped_refptr<base::RefCountedString>& events_str_ptr, |
| 817 bool has_more_events) { | 785 bool has_more_events) { |
| 818 if (events_str_ptr->data().size()) | 786 if (events_str_ptr->data().size()) |
| 819 OnTraceDataCollected(events_str_ptr); | 787 OnTraceDataCollected(events_str_ptr); |
| 820 | 788 |
| 821 if (has_more_events) | 789 if (has_more_events) |
| 822 return; | 790 return; |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 902 is_monitoring_ = is_monitoring; | 870 is_monitoring_ = is_monitoring; |
| 903 #if !defined(OS_ANDROID) | 871 #if !defined(OS_ANDROID) |
| 904 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); | 872 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); |
| 905 it != tracing_uis_.end(); it++) { | 873 it != tracing_uis_.end(); it++) { |
| 906 (*it)->OnMonitoringStateChanged(is_monitoring); | 874 (*it)->OnMonitoringStateChanged(is_monitoring); |
| 907 } | 875 } |
| 908 #endif | 876 #endif |
| 909 } | 877 } |
| 910 | 878 |
| 911 } // namespace content | 879 } // namespace content |
| OLD | NEW |