| 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) |
| 19 #include "chromeos/dbus/dbus_thread_manager.h" |
| 20 #include "chromeos/dbus/debug_daemon_client.h" |
| 21 #endif |
| 22 |
| 18 using base::debug::TraceLog; | 23 using base::debug::TraceLog; |
| 19 | 24 |
| 20 namespace content { | 25 namespace content { |
| 21 | 26 |
| 22 namespace { | 27 namespace { |
| 23 | 28 |
| 24 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = | 29 base::LazyInstance<TracingControllerImpl>::Leaky g_controller = |
| 25 LAZY_INSTANCE_INITIALIZER; | 30 LAZY_INSTANCE_INITIALIZER; |
| 26 | 31 |
| 27 } // namespace | 32 } // namespace |
| 28 | 33 |
| 29 TracingController* TracingController::GetInstance() { | 34 TracingController* TracingController::GetInstance() { |
| 30 return TracingControllerImpl::GetInstance(); | 35 return TracingControllerImpl::GetInstance(); |
| 31 } | 36 } |
| 32 | 37 |
| 33 class TracingControllerImpl::ResultFile { | 38 class TracingControllerImpl::ResultFile { |
| 34 public: | 39 public: |
| 35 explicit ResultFile(const base::FilePath& path); | 40 explicit ResultFile(const base::FilePath& path); |
| 36 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { | 41 void Write(const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 37 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 42 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 38 base::Bind(&TracingControllerImpl::ResultFile::WriteTask, | 43 base::Bind(&TracingControllerImpl::ResultFile::WriteTask, |
| 39 base::Unretained(this), events_str_ptr)); | 44 base::Unretained(this), events_str_ptr)); |
| 40 } | 45 } |
| 41 void Close(const base::Closure& callback) { | 46 void Close(const base::Closure& callback) { |
| 42 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 47 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 43 base::Bind(&TracingControllerImpl::ResultFile::CloseTask, | 48 base::Bind(&TracingControllerImpl::ResultFile::CloseTask, |
| 44 base::Unretained(this), callback)); | 49 base::Unretained(this), callback)); |
| 45 } | 50 } |
| 51 void WriteSystemTrace( |
| 52 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 53 BrowserThread::PostTask( |
| 54 BrowserThread::FILE, |
| 55 FROM_HERE, |
| 56 base::Bind(&TracingControllerImpl::ResultFile::WriteSystemTraceTask, |
| 57 base::Unretained(this), events_str_ptr)); |
| 58 } |
| 59 |
| 46 const base::FilePath& path() const { return path_; } | 60 const base::FilePath& path() const { return path_; } |
| 47 | 61 |
| 48 private: | 62 private: |
| 49 void OpenTask(); | 63 void OpenTask(); |
| 50 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr); | 64 void WriteTask(const scoped_refptr<base::RefCountedString>& events_str_ptr); |
| 65 void WriteSystemTraceTask( |
| 66 const scoped_refptr<base::RefCountedString>& events_str_ptr); |
| 51 void CloseTask(const base::Closure& callback); | 67 void CloseTask(const base::Closure& callback); |
| 52 | 68 |
| 53 FILE* file_; | 69 FILE* file_; |
| 54 base::FilePath path_; | 70 base::FilePath path_; |
| 55 bool has_at_least_one_result_; | 71 bool has_at_least_one_result_; |
| 72 scoped_refptr<base::RefCountedString> system_trace_; |
| 56 | 73 |
| 57 DISALLOW_COPY_AND_ASSIGN(ResultFile); | 74 DISALLOW_COPY_AND_ASSIGN(ResultFile); |
| 58 }; | 75 }; |
| 59 | 76 |
| 60 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path) | 77 TracingControllerImpl::ResultFile::ResultFile(const base::FilePath& path) |
| 61 : file_(NULL), | 78 : file_(NULL), |
| 62 path_(path), | 79 path_(path), |
| 63 has_at_least_one_result_(false) { | 80 has_at_least_one_result_(false) { |
| 64 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 81 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 65 base::Bind(&TracingControllerImpl::ResultFile::OpenTask, | 82 base::Bind(&TracingControllerImpl::ResultFile::OpenTask, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 90 size_t written = fwrite(",", 1, 1, file_); | 107 size_t written = fwrite(",", 1, 1, file_); |
| 91 DCHECK(written == 1); | 108 DCHECK(written == 1); |
| 92 } | 109 } |
| 93 has_at_least_one_result_ = true; | 110 has_at_least_one_result_ = true; |
| 94 size_t written = fwrite(events_str_ptr->data().c_str(), | 111 size_t written = fwrite(events_str_ptr->data().c_str(), |
| 95 events_str_ptr->data().size(), 1, | 112 events_str_ptr->data().size(), 1, |
| 96 file_); | 113 file_); |
| 97 DCHECK(written == 1); | 114 DCHECK(written == 1); |
| 98 } | 115 } |
| 99 | 116 |
| 117 void TracingControllerImpl::ResultFile::WriteSystemTraceTask( |
| 118 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 119 system_trace_ = events_str_ptr; |
| 120 } |
| 121 |
| 100 void TracingControllerImpl::ResultFile::CloseTask( | 122 void TracingControllerImpl::ResultFile::CloseTask( |
| 101 const base::Closure& callback) { | 123 const base::Closure& callback) { |
| 102 if (!file_) | 124 if (!file_) |
| 103 return; | 125 return; |
| 104 | 126 |
| 105 const char* trailout = "]}"; | 127 const char* trailevents = "]"; |
| 106 size_t written = fwrite(trailout, strlen(trailout), 1, file_); | 128 size_t written = fwrite(trailevents, strlen(trailevents), 1, file_); |
| 129 DCHECK(written == 1); |
| 130 |
| 131 if (system_trace_) { |
| 132 std::string json_string = base::GetQuotedJSONString(system_trace_->data()); |
| 133 |
| 134 const char* systemTraceHead = ", \"systemTraceEvents\": "; |
| 135 written = fwrite(systemTraceHead, strlen(systemTraceHead), 1, file_); |
| 136 DCHECK(written == 1); |
| 137 |
| 138 written = fwrite(json_string.data(), json_string.size(), 1, file_); |
| 139 DCHECK(written == 1); |
| 140 |
| 141 system_trace_ = NULL; |
| 142 } |
| 143 |
| 144 const char* trailout = "}"; |
| 145 written = fwrite(trailout, strlen(trailout), 1, file_); |
| 107 DCHECK(written == 1); | 146 DCHECK(written == 1); |
| 108 base::CloseFile(file_); | 147 base::CloseFile(file_); |
| 109 file_ = NULL; | 148 file_ = NULL; |
| 110 | 149 |
| 111 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); | 150 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback); |
| 112 } | 151 } |
| 113 | 152 |
| 114 | 153 |
| 115 TracingControllerImpl::TracingControllerImpl() : | 154 TracingControllerImpl::TracingControllerImpl() : |
| 116 pending_disable_recording_ack_count_(0), | 155 pending_disable_recording_ack_count_(0), |
| 117 pending_capture_monitoring_snapshot_ack_count_(0), | 156 pending_capture_monitoring_snapshot_ack_count_(0), |
| 118 pending_trace_buffer_percent_full_ack_count_(0), | 157 pending_trace_buffer_percent_full_ack_count_(0), |
| 119 maximum_trace_buffer_percent_full_(0), | 158 maximum_trace_buffer_percent_full_(0), |
| 120 // Tracing may have been enabled by ContentMainRunner if kTraceStartup | 159 // Tracing may have been enabled by ContentMainRunner if kTraceStartup |
| 121 // is specified in command line. | 160 // is specified in command line. |
| 161 #if defined(OS_CHROMEOS) |
| 162 is_system_tracing_(false), |
| 163 #endif |
| 122 is_recording_(TraceLog::GetInstance()->IsEnabled()), | 164 is_recording_(TraceLog::GetInstance()->IsEnabled()), |
| 123 is_monitoring_(false) { | 165 is_monitoring_(false) { |
| 124 } | 166 } |
| 125 | 167 |
| 126 TracingControllerImpl::~TracingControllerImpl() { | 168 TracingControllerImpl::~TracingControllerImpl() { |
| 127 // This is a Leaky instance. | 169 // This is a Leaky instance. |
| 128 NOTREACHED(); | 170 NOTREACHED(); |
| 129 } | 171 } |
| 130 | 172 |
| 131 TracingControllerImpl* TracingControllerImpl::GetInstance() { | 173 TracingControllerImpl* TracingControllerImpl::GetInstance() { |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 if (pending_get_categories_done_callback_.is_null()) | 229 if (pending_get_categories_done_callback_.is_null()) |
| 188 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); | 230 TraceLog::GetInstance()->AddClockSyncMetadataEvent(); |
| 189 #endif | 231 #endif |
| 190 | 232 |
| 191 options_ = options; | 233 options_ = options; |
| 192 int trace_options = (options & RECORD_CONTINUOUSLY) ? | 234 int trace_options = (options & RECORD_CONTINUOUSLY) ? |
| 193 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; | 235 TraceLog::RECORD_CONTINUOUSLY : TraceLog::RECORD_UNTIL_FULL; |
| 194 if (options & ENABLE_SAMPLING) { | 236 if (options & ENABLE_SAMPLING) { |
| 195 trace_options |= TraceLog::ENABLE_SAMPLING; | 237 trace_options |= TraceLog::ENABLE_SAMPLING; |
| 196 } | 238 } |
| 197 // TODO(haraken): How to handle ENABLE_SYSTRACE? | 239 #if defined(OS_CHROMEOS) |
| 240 if (options & ENABLE_SYSTRACE) { |
| 241 DCHECK(!is_system_tracing_); |
| 242 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
| 243 StartSystemTracing(); |
| 244 is_system_tracing_ = true; |
| 245 } |
| 246 #endif |
| 198 | 247 |
| 199 base::Closure on_enable_recording_done_callback = | 248 base::Closure on_enable_recording_done_callback = |
| 200 base::Bind(&TracingControllerImpl::OnEnableRecordingDone, | 249 base::Bind(&TracingControllerImpl::OnEnableRecordingDone, |
| 201 base::Unretained(this), | 250 base::Unretained(this), |
| 202 category_filter,trace_options, callback); | 251 category_filter,trace_options, callback); |
| 203 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, | 252 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, |
| 204 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, | 253 base::Bind(&TracingControllerImpl::SetEnabledOnFileThread, |
| 205 base::Unretained(this), | 254 base::Unretained(this), |
| 206 category_filter, | 255 category_filter, |
| 207 base::debug::TraceLog::RECORDING_MODE, | 256 base::debug::TraceLog::RECORDING_MODE, |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 602 // called with the last of the local trace data. | 651 // called with the last of the local trace data. |
| 603 TraceLog::GetInstance()->Flush( | 652 TraceLog::GetInstance()->Flush( |
| 604 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, | 653 base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected, |
| 605 base::Unretained(this))); | 654 base::Unretained(this))); |
| 606 return; | 655 return; |
| 607 } | 656 } |
| 608 | 657 |
| 609 if (pending_disable_recording_ack_count_ != 0) | 658 if (pending_disable_recording_ack_count_ != 0) |
| 610 return; | 659 return; |
| 611 | 660 |
| 661 OnDisableRecordingComplete(); |
| 662 } |
| 663 |
| 664 void TracingControllerImpl::OnDisableRecordingComplete() { |
| 612 // All acks (including from the subprocesses and the local trace) have been | 665 // All acks (including from the subprocesses and the local trace) have been |
| 613 // received. | 666 // received. |
| 614 is_recording_ = false; | 667 is_recording_ = false; |
| 615 | 668 |
| 669 #if defined(OS_CHROMEOS) |
| 670 if (is_system_tracing_) { |
| 671 // Disable system tracing now that the local trace has shutdown. |
| 672 // This must be done last because we potentially need to push event |
| 673 // records into the system event log for synchronizing system event |
| 674 // 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 |
| 676 // way we're confident we'll have them in the final result. |
| 677 is_system_tracing_ = false; |
| 678 chromeos::DBusThreadManager::Get()->GetDebugDaemonClient()-> |
| 679 RequestStopSystemTracing( |
| 680 base::Bind(&TracingControllerImpl::OnEndSystemTracingAcked, |
| 681 base::Unretained(this))); |
| 682 return; |
| 683 } |
| 684 #endif |
| 685 |
| 616 // Trigger callback if one is set. | 686 // Trigger callback if one is set. |
| 617 if (!pending_get_categories_done_callback_.is_null()) { | 687 if (!pending_get_categories_done_callback_.is_null()) { |
| 618 pending_get_categories_done_callback_.Run(known_category_groups_); | 688 pending_get_categories_done_callback_.Run(known_category_groups_); |
| 619 pending_get_categories_done_callback_.Reset(); | 689 pending_get_categories_done_callback_.Reset(); |
| 620 } else if (result_file_) { | 690 } else if (result_file_) { |
| 621 result_file_->Close( | 691 result_file_->Close( |
| 622 base::Bind(&TracingControllerImpl::OnResultFileClosed, | 692 base::Bind(&TracingControllerImpl::OnResultFileClosed, |
| 623 base::Unretained(this))); | 693 base::Unretained(this))); |
| 624 } | 694 } |
| 625 } | 695 } |
| 626 | 696 |
| 627 void TracingControllerImpl::OnResultFileClosed() { | 697 void TracingControllerImpl::OnResultFileClosed() { |
| 628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 698 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 629 | 699 |
| 630 if (!result_file_) | 700 if (!result_file_) |
| 631 return; | 701 return; |
| 632 | 702 |
| 633 if (!pending_disable_recording_done_callback_.is_null()) { | 703 if (!pending_disable_recording_done_callback_.is_null()) { |
| 634 pending_disable_recording_done_callback_.Run(result_file_->path()); | 704 pending_disable_recording_done_callback_.Run(result_file_->path()); |
| 635 pending_disable_recording_done_callback_.Reset(); | 705 pending_disable_recording_done_callback_.Reset(); |
| 636 } | 706 } |
| 637 result_file_.reset(); | 707 result_file_.reset(); |
| 638 } | 708 } |
| 639 | 709 |
| 710 #if defined(OS_CHROMEOS) |
| 711 void TracingControllerImpl::OnEndSystemTracingAcked( |
| 712 const scoped_refptr<base::RefCountedString>& events_str_ptr) { |
| 713 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 714 |
| 715 if (result_file_) |
| 716 result_file_->WriteSystemTrace(events_str_ptr); |
| 717 |
| 718 DCHECK(!is_system_tracing_); |
| 719 OnDisableRecordingComplete(); |
| 720 } |
| 721 #endif |
| 722 |
| 640 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( | 723 void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked( |
| 641 TraceMessageFilter* trace_message_filter) { | 724 TraceMessageFilter* trace_message_filter) { |
| 642 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { | 725 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 643 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 726 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 644 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, | 727 base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, |
| 645 base::Unretained(this), | 728 base::Unretained(this), |
| 646 make_scoped_refptr(trace_message_filter))); | 729 make_scoped_refptr(trace_message_filter))); |
| 647 return; | 730 return; |
| 648 } | 731 } |
| 649 | 732 |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 811 is_monitoring_ = is_monitoring; | 894 is_monitoring_ = is_monitoring; |
| 812 #if !defined(OS_ANDROID) | 895 #if !defined(OS_ANDROID) |
| 813 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); | 896 for (std::set<TracingUI*>::iterator it = tracing_uis_.begin(); |
| 814 it != tracing_uis_.end(); it++) { | 897 it != tracing_uis_.end(); it++) { |
| 815 (*it)->OnMonitoringStateChanged(is_monitoring); | 898 (*it)->OnMonitoringStateChanged(is_monitoring); |
| 816 } | 899 } |
| 817 #endif | 900 #endif |
| 818 } | 901 } |
| 819 | 902 |
| 820 } // namespace content | 903 } // namespace content |
| OLD | NEW |