diff options
author | haraken@chromium.org <haraken@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-07 07:45:54 +0000 |
---|---|---|
committer | haraken@chromium.org <haraken@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-10-07 07:45:54 +0000 |
commit | fd908e678588a998d8c9c666090ed9b50ff8bda8 (patch) | |
tree | 9f21ffeafab380c6f5bb497ebe1052e0a72dde78 /content | |
parent | a217b8af416f1368b8e094da66ae017c83c78eee (diff) | |
download | chromium_src-fd908e678588a998d8c9c666090ed9b50ff8bda8.zip chromium_src-fd908e678588a998d8c9c666090ed9b50ff8bda8.tar.gz chromium_src-fd908e678588a998d8c9c666090ed9b50ff8bda8.tar.bz2 |
Implement TracingController::{Enable,Disable,Capture}Monitoring
This CL implements TracingController::EnableMonitoring,
TracingController::DisableMonitoring and
TracingController::CaptureMonitoringSnapshot.
BUG=241743
TEST=base_unittests::TraceEventTestFixture.TraceContinuousSampling,
content_browsertests::TracingControllerTest.EnableCaptureAndDisableMonitoring
Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=226701
R=dsinclair@chromium.org, joi@chromium.org, nduca@chromium.org, tsepez@chromium.org
Review URL: https://codereview.chromium.org/23531042
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@227262 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/tracing/trace_message_filter.cc | 48 | ||||
-rw-r--r-- | content/browser/tracing/trace_message_filter.h | 8 | ||||
-rw-r--r-- | content/browser/tracing/tracing_controller_browsertest.cc | 93 | ||||
-rw-r--r-- | content/browser/tracing/tracing_controller_impl.cc | 194 | ||||
-rw-r--r-- | content/browser/tracing/tracing_controller_impl.h | 39 | ||||
-rw-r--r-- | content/public/browser/trace_subscriber.h | 2 | ||||
-rw-r--r-- | content/public/browser/tracing_controller.h | 12 |
7 files changed, 336 insertions, 60 deletions
diff --git a/content/browser/tracing/trace_message_filter.cc b/content/browser/tracing/trace_message_filter.cc index b77c908..628a92f 100644 --- a/content/browser/tracing/trace_message_filter.cc +++ b/content/browser/tracing/trace_message_filter.cc @@ -6,12 +6,14 @@ #include "components/tracing/tracing_messages.h" #include "content/browser/tracing/trace_controller_impl.h" +#include "content/browser/tracing/tracing_controller_impl.h" namespace content { TraceMessageFilter::TraceMessageFilter() : has_child_(false), is_awaiting_end_ack_(false), + is_awaiting_capture_monitoring_snapshot_ack_(false), is_awaiting_buffer_percent_full_ack_(false) { } @@ -20,6 +22,9 @@ void TraceMessageFilter::OnChannelClosing() { if (is_awaiting_end_ack_) OnEndTracingAck(std::vector<std::string>()); + if (is_awaiting_capture_monitoring_snapshot_ack_) + OnCaptureMonitoringSnapshotAcked(); + if (is_awaiting_buffer_percent_full_ack_) OnTraceBufferPercentFullReply(0.0f); @@ -35,8 +40,12 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message, IPC_MESSAGE_HANDLER(TracingHostMsg_ChildSupportsTracing, OnChildSupportsTracing) IPC_MESSAGE_HANDLER(TracingHostMsg_EndTracingAck, OnEndTracingAck) + IPC_MESSAGE_HANDLER(TracingHostMsg_CaptureMonitoringSnapshotAck, + OnCaptureMonitoringSnapshotAcked) IPC_MESSAGE_HANDLER(TracingHostMsg_TraceDataCollected, OnTraceDataCollected) + IPC_MESSAGE_HANDLER(TracingHostMsg_MonitoringTraceDataCollected, + OnMonitoringTraceDataCollected) IPC_MESSAGE_HANDLER(TracingHostMsg_TraceNotification, OnTraceNotification) IPC_MESSAGE_HANDLER(TracingHostMsg_TraceBufferPercentFullReply, @@ -62,6 +71,27 @@ void TraceMessageFilter::SendEndTracing() { Send(new TracingMsg_EndTracing); } +void TraceMessageFilter::SendEnableMonitoring( + const std::string& category_filter_str, + base::debug::TraceLog::Options options) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + Send(new TracingMsg_EnableMonitoring(category_filter_str, + base::TimeTicks::NowFromSystemTraceTime(), + options)); +} + +void TraceMessageFilter::SendDisableMonitoring() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + Send(new TracingMsg_DisableMonitoring); +} + +void TraceMessageFilter::SendCaptureMonitoringSnapshot() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DCHECK(!is_awaiting_capture_monitoring_snapshot_ack_); + is_awaiting_capture_monitoring_snapshot_ack_ = true; + Send(new TracingMsg_CaptureMonitoringSnapshot); +} + void TraceMessageFilter::SendGetTraceBufferPercentFull() { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!is_awaiting_buffer_percent_full_ack_); @@ -97,12 +127,30 @@ void TraceMessageFilter::OnEndTracingAck( } } +void TraceMessageFilter::OnCaptureMonitoringSnapshotAcked() { + // is_awaiting_capture_monitoring_snapshot_ack_ should always be true here, + // but check in case the child process is compromised. + if (is_awaiting_capture_monitoring_snapshot_ack_) { + is_awaiting_capture_monitoring_snapshot_ack_ = false; + TracingControllerImpl::GetInstance()->OnCaptureMonitoringSnapshotAcked(); + } else { + NOTREACHED(); + } +} + void TraceMessageFilter::OnTraceDataCollected(const std::string& data) { scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString()); data_ptr->data() = data; TraceControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr); } +void TraceMessageFilter::OnMonitoringTraceDataCollected( + const std::string& data) { + scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString()); + data_ptr->data() = data; + TracingControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr); +} + void TraceMessageFilter::OnTraceNotification(int notification) { TraceControllerImpl::GetInstance()->OnTraceNotification(notification); } diff --git a/content/browser/tracing/trace_message_filter.h b/content/browser/tracing/trace_message_filter.h index 9f97184..c8290d9 100644 --- a/content/browser/tracing/trace_message_filter.h +++ b/content/browser/tracing/trace_message_filter.h @@ -28,6 +28,10 @@ class TraceMessageFilter : public BrowserMessageFilter { void SendBeginTracing(const std::string& category_filter_str, base::debug::TraceLog::Options options); void SendEndTracing(); + void SendEnableMonitoring(const std::string& category_filter_str, + base::debug::TraceLog::Options options); + void SendDisableMonitoring(); + void SendCaptureMonitoringSnapshot(); void SendGetTraceBufferPercentFull(); void SendSetWatchEvent(const std::string& category_name, const std::string& event_name); @@ -40,15 +44,19 @@ class TraceMessageFilter : public BrowserMessageFilter { // Message handlers. void OnChildSupportsTracing(); void OnEndTracingAck(const std::vector<std::string>& known_categories); + void OnCaptureMonitoringSnapshotAcked(); void OnTraceNotification(int notification); void OnTraceBufferPercentFullReply(float percent_full); void OnTraceDataCollected(const std::string& data); + void OnMonitoringTraceDataCollected(const std::string& data); // ChildTraceMessageFilter exists: bool has_child_; // Awaiting ack for previously sent SendEndTracing bool is_awaiting_end_ack_; + // Awaiting ack for previously sent SendCaptureMonitoringSnapshot + bool is_awaiting_capture_monitoring_snapshot_ack_; // Awaiting ack for previously sent SendGetTraceBufferPercentFull bool is_awaiting_buffer_percent_full_ack_; diff --git a/content/browser/tracing/tracing_controller_browsertest.cc b/content/browser/tracing/tracing_controller_browsertest.cc index c88932e..a3a589f 100644 --- a/content/browser/tracing/tracing_controller_browsertest.cc +++ b/content/browser/tracing/tracing_controller_browsertest.cc @@ -20,6 +20,9 @@ class TracingControllerTest : public ContentBrowserTest { get_categories_done_callback_count_ = 0; enable_recording_done_callback_count_ = 0; disable_recording_done_callback_count_ = 0; + enable_monitoring_done_callback_count_ = 0; + disable_monitoring_done_callback_count_ = 0; + capture_monitoring_snapshot_done_callback_count_ = 0; ContentBrowserTest::SetUp(); } @@ -47,6 +50,29 @@ class TracingControllerTest : public ContentBrowserTest { scoped_ptr<base::FilePath> file_path) { disable_recording_done_callback_count_++; EXPECT_TRUE(PathExists(*file_path)); + int64 file_size; + file_util::GetFileSize(*file_path, &file_size); + EXPECT_TRUE(file_size > 0); + quit_callback.Run(); + } + + void EnableMonitoringDoneCallbackTest(base::Closure quit_callback) { + enable_monitoring_done_callback_count_++; + quit_callback.Run(); + } + + void DisableMonitoringDoneCallbackTest(base::Closure quit_callback) { + disable_monitoring_done_callback_count_++; + quit_callback.Run(); + } + + void CaptureMonitoringSnapshotDoneCallbackTest( + base::Closure quit_callback, scoped_ptr<base::FilePath> file_path) { + capture_monitoring_snapshot_done_callback_count_++; + EXPECT_TRUE(PathExists(*file_path)); + int64 file_size; + file_util::GetFileSize(*file_path, &file_size); + EXPECT_TRUE(file_size > 0); quit_callback.Run(); } @@ -62,10 +88,25 @@ class TracingControllerTest : public ContentBrowserTest { return disable_recording_done_callback_count_; } + int enable_monitoring_done_callback_count() const { + return enable_monitoring_done_callback_count_; + } + + int disable_monitoring_done_callback_count() const { + return disable_monitoring_done_callback_count_; + } + + int capture_monitoring_snapshot_done_callback_count() const { + return capture_monitoring_snapshot_done_callback_count_; + } + private: int get_categories_done_callback_count_; int enable_recording_done_callback_count_; int disable_recording_done_callback_count_; + int enable_monitoring_done_callback_count_; + int disable_monitoring_done_callback_count_; + int capture_monitoring_snapshot_done_callback_count_; }; IN_PROC_BROWSER_TEST_F(TracingControllerTest, GetCategories) { @@ -94,8 +135,9 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) { base::Bind(&TracingControllerTest::EnableRecordingDoneCallbackTest, base::Unretained(this), run_loop.QuitClosure()); - controller->EnableRecording(base::debug::CategoryFilter("*"), - TracingController::Options(), callback); + bool result = controller->EnableRecording(base::debug::CategoryFilter("*"), + TracingController::Options(), callback); + EXPECT_TRUE(result); run_loop.Run(); EXPECT_EQ(enable_recording_done_callback_count(), 1); } @@ -106,10 +148,55 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest, EnableAndDisableRecording) { base::Bind(&TracingControllerTest::DisableRecordingDoneCallbackTest, base::Unretained(this), run_loop.QuitClosure()); - controller->DisableRecording(callback); + bool result = controller->DisableRecording(callback); + EXPECT_TRUE(result); run_loop.Run(); EXPECT_EQ(disable_recording_done_callback_count(), 1); } } +IN_PROC_BROWSER_TEST_F(TracingControllerTest, + EnableCaptureAndDisableMonitoring) { + Navigate(shell()); + + TracingController* controller = TracingController::GetInstance(); + + { + base::RunLoop run_loop; + TracingController::EnableMonitoringDoneCallback callback = + base::Bind(&TracingControllerTest::EnableMonitoringDoneCallbackTest, + base::Unretained(this), + run_loop.QuitClosure()); + bool result = controller->EnableMonitoring(base::debug::CategoryFilter("*"), + TracingController::ENABLE_SAMPLING, callback); + EXPECT_TRUE(result); + run_loop.Run(); + EXPECT_EQ(enable_monitoring_done_callback_count(), 1); + } + + { + base::RunLoop run_loop; + TracingController::TracingFileResultCallback callback = + base::Bind(&TracingControllerTest:: + CaptureMonitoringSnapshotDoneCallbackTest, + base::Unretained(this), + run_loop.QuitClosure()); + controller->CaptureMonitoringSnapshot(callback); + run_loop.Run(); + EXPECT_EQ(capture_monitoring_snapshot_done_callback_count(), 1); + } + + { + base::RunLoop run_loop; + TracingController::DisableMonitoringDoneCallback callback = + base::Bind(&TracingControllerTest::DisableMonitoringDoneCallbackTest, + base::Unretained(this), + run_loop.QuitClosure()); + bool result = controller->DisableMonitoring(callback); + EXPECT_TRUE(result); + run_loop.Run(); + EXPECT_EQ(disable_monitoring_done_callback_count(), 1); + } +} + } // namespace content diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index 1c1c43a..845f1c5 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc @@ -29,10 +29,14 @@ TracingController* TracingController::GetInstance() { } TracingControllerImpl::TracingControllerImpl() : - pending_end_ack_count_(0), + pending_disable_recording_ack_count_(0), + pending_capture_monitoring_snapshot_ack_count_(0), is_recording_(false), + is_monitoring_(false), category_filter_( - base::debug::CategoryFilter::kDefaultCategoryFilterString) { + base::debug::CategoryFilter::kDefaultCategoryFilterString), + result_file_(0), + result_file_has_at_least_one_result_(false) { } TracingControllerImpl::~TracingControllerImpl() { @@ -58,14 +62,14 @@ void TracingControllerImpl::GetCategories( DisableRecording(TracingFileResultCallback()); } -void TracingControllerImpl::EnableRecording( +bool TracingControllerImpl::EnableRecording( const base::debug::CategoryFilter& filter, TracingController::Options options, const EnableRecordingDoneCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); if (!can_enable_recording()) - return; + return false; trace_options_ = TraceLog::GetInstance()->trace_options(); TraceLog::GetInstance()->SetEnabled(filter, trace_options_); @@ -80,14 +84,15 @@ void TracingControllerImpl::EnableRecording( if (!callback.is_null()) callback.Run(); + return true; } -void TracingControllerImpl::DisableRecording( +bool TracingControllerImpl::DisableRecording( const TracingFileResultCallback& callback) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); - if (!can_end_recording()) - return; + if (!can_disable_recording()) + return false; pending_disable_recording_done_callback_ = callback; @@ -99,18 +104,23 @@ void TracingControllerImpl::DisableRecording( if (pending_get_categories_done_callback_.is_null()) { base::FilePath temporary_file; file_util::CreateTemporaryFile(&temporary_file); - recording_result_file_.reset(new base::FilePath(temporary_file)); + result_file_path_.reset(new base::FilePath(temporary_file)); + result_file_ = file_util::OpenFile(*result_file_path_, "w"); + result_file_has_at_least_one_result_ = false; + const char* preamble = "{\"traceEvents\": ["; + fwrite(preamble, strlen(preamble), 1, result_file_); } // There could be a case where there are no child processes and filters_ // is empty. In that case we can immediately tell the subscriber that tracing // has ended. To avoid recursive calls back to the subscriber, we will just // use the existing asynchronous OnDisableRecordingAcked code. - // Count myself (local trace) in pending_end_ack_count_, acked below. - pending_end_ack_count_ = filters_.size() + 1; + // Count myself (local trace) in pending_disable_recording_ack_count_, + // acked below. + pending_disable_recording_ack_count_ = filters_.size() + 1; // Handle special case of zero child processes. - if (pending_end_ack_count_ == 1) { + if (pending_disable_recording_ack_count_ == 1) { // Ack asynchronously now, because we don't have any children to wait for. std::vector<std::string> category_groups; TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups); @@ -123,18 +133,50 @@ void TracingControllerImpl::DisableRecording( for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { it->get()->SendEndTracing(); } + return true; } -void TracingControllerImpl::EnableMonitoring( +bool TracingControllerImpl::EnableMonitoring( const base::debug::CategoryFilter& filter, TracingController::Options options, const EnableMonitoringDoneCallback& callback) { - NOTIMPLEMENTED(); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!can_enable_monitoring()) + return false; + is_monitoring_ = true; + + int monitoring_tracing_options = 0; + if (options & ENABLE_SAMPLING) + monitoring_tracing_options |= base::debug::TraceLog::MONITOR_SAMPLING; + + // Notify all child processes. + for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + it->get()->SendEnableMonitoring(filter.ToString(), + base::debug::TraceLog::Options(monitoring_tracing_options)); + } + + if (!callback.is_null()) + callback.Run(); + return true; } -void TracingControllerImpl::DisableMonitoring( +bool TracingControllerImpl::DisableMonitoring( const DisableMonitoringDoneCallback& callback) { - NOTIMPLEMENTED(); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!can_disable_monitoring()) + return false; + is_monitoring_ = false; + + // Notify all child processes. + for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + it->get()->SendDisableMonitoring(); + } + + if (!callback.is_null()) + callback.Run(); + return true; } void TracingControllerImpl::GetMonitoringStatus( @@ -144,9 +186,43 @@ void TracingControllerImpl::GetMonitoringStatus( NOTIMPLEMENTED(); } -void TracingControllerImpl::CaptureCurrentMonitoringSnapshot( +void TracingControllerImpl::CaptureMonitoringSnapshot( const TracingFileResultCallback& callback) { - NOTIMPLEMENTED(); + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + if (!can_disable_monitoring()) + return; + + pending_capture_monitoring_snapshot_done_callback_ = callback; + + base::FilePath temporary_file; + file_util::CreateTemporaryFile(&temporary_file); + result_file_path_.reset(new base::FilePath(temporary_file)); + result_file_ = file_util::OpenFile(*result_file_path_, "w"); + result_file_has_at_least_one_result_ = false; + const char* preamble = "{\"traceEvents\": ["; + fwrite(preamble, strlen(preamble), 1, result_file_); + + // There could be a case where there are no child processes and filters_ + // is empty. In that case we can immediately tell the subscriber that tracing + // has ended. To avoid recursive calls back to the subscriber, we will just + // use the existing asynchronous OnCaptureMonitoringSnapshotAcked code. + // Count myself in pending_capture_monitoring_snapshot_ack_count_, + // acked below. + pending_capture_monitoring_snapshot_ack_count_ = filters_.size() + 1; + + // Handle special case of zero child processes. + if (pending_capture_monitoring_snapshot_ack_count_ == 1) { + // Ack asynchronously now, because we don't have any children to wait for. + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, + base::Unretained(this))); + } + + // Notify all child processes. + for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) { + it->get()->SendCaptureMonitoringSnapshot(); + } } void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) { @@ -158,7 +234,7 @@ void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) { } filters_.insert(filter); - if (is_recording_enabled()) { + if (can_disable_recording()) { std::string cf_str = category_filter_.ToString(); filter->SendBeginTracing(cf_str, trace_options_); } @@ -188,10 +264,10 @@ void TracingControllerImpl::OnDisableRecordingAcked( known_category_groups_.insert(known_category_groups.begin(), known_category_groups.end()); - if (pending_end_ack_count_ == 0) + if (pending_disable_recording_ack_count_ == 0) return; - if (--pending_end_ack_count_ == 1) { + if (--pending_disable_recording_ack_count_ == 1) { // All acks from subprocesses have been received. Now flush the local trace. // During or after this call, our OnLocalTraceDataCollected will be // called with the last of the local trace data. @@ -200,7 +276,7 @@ void TracingControllerImpl::OnDisableRecordingAcked( base::Unretained(this))); } - if (pending_end_ack_count_ != 0) + if (pending_disable_recording_ack_count_ != 0) return; // All acks (including from the subprocesses and the local trace) have been @@ -211,17 +287,48 @@ void TracingControllerImpl::OnDisableRecordingAcked( if (!pending_get_categories_done_callback_.is_null()) { pending_get_categories_done_callback_.Run(known_category_groups_); pending_get_categories_done_callback_.Reset(); - } else { - OnEndTracingComplete(); + } else if (!pending_disable_recording_done_callback_.is_null()) { + const char* trailout = "]}"; + fwrite(trailout, strlen(trailout), 1, result_file_); + file_util::CloseFile(result_file_); + result_file_ = 0; + pending_disable_recording_done_callback_.Run(result_file_path_.Pass()); + pending_disable_recording_done_callback_.Reset(); } } -void TracingControllerImpl::OnEndTracingComplete() { - if (pending_disable_recording_done_callback_.is_null()) +void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked() { + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked, + base::Unretained(this))); + return; + } + + if (pending_capture_monitoring_snapshot_ack_count_ == 0) return; - pending_disable_recording_done_callback_.Run(recording_result_file_.Pass()); - pending_disable_recording_done_callback_.Reset(); + if (--pending_capture_monitoring_snapshot_ack_count_ == 1) { + // All acks from subprocesses have been received. Now flush the local trace. + // During or after this call, our OnLocalMonitoringTraceDataCollected + // will be called with the last of the local trace data. + TraceLog::GetInstance()->FlushButLeaveBufferIntact( + base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected, + base::Unretained(this))); + } + + if (pending_capture_monitoring_snapshot_ack_count_ != 0) + return; + + if (!pending_capture_monitoring_snapshot_done_callback_.is_null()) { + const char* trailout = "]}"; + fwrite(trailout, strlen(trailout), 1, result_file_); + file_util::CloseFile(result_file_); + result_file_ = 0; + pending_capture_monitoring_snapshot_done_callback_.Run( + result_file_path_.Pass()); + pending_capture_monitoring_snapshot_done_callback_.Reset(); + } } void TracingControllerImpl::OnTraceDataCollected( @@ -239,17 +346,15 @@ void TracingControllerImpl::OnTraceDataCollected( if (!pending_get_categories_done_callback_.is_null()) return; - std::string javascript; - javascript.reserve(events_str_ptr->size() * 2); - base::JsonDoubleQuote(events_str_ptr->data(), false, &javascript); - - // Intentionally append a , to the traceData. This technically causes all - // traceData that we pass back to JS to end with a comma, but that is - // actually something the JS side strips away anyway - javascript.append(","); - - file_util::WriteFile(*recording_result_file_, - javascript.c_str(), javascript.length()); + // If there is already a result in the file, then put a commma + // before the next batch of results. + if (result_file_has_at_least_one_result_) { + fwrite(",", 1, 1, result_file_); + } else { + result_file_has_at_least_one_result_ = true; + } + fwrite(events_str_ptr->data().c_str(), events_str_ptr->data().size(), 1, + result_file_); } void TracingControllerImpl::OnLocalTraceDataCollected( @@ -267,4 +372,17 @@ void TracingControllerImpl::OnLocalTraceDataCollected( OnDisableRecordingAcked(category_groups); } +void TracingControllerImpl::OnLocalMonitoringTraceDataCollected( + const scoped_refptr<base::RefCountedString>& events_str_ptr, + bool has_more_events) { + if (events_str_ptr->data().size()) + OnTraceDataCollected(events_str_ptr); + + if (has_more_events) + return; + + // Simulate an CaptureMonitoringSnapshotAcked for the local trace. + OnCaptureMonitoringSnapshotAcked(); +} + } // namespace content diff --git a/content/browser/tracing/tracing_controller_impl.h b/content/browser/tracing/tracing_controller_impl.h index 2219225..175365e 100644 --- a/content/browser/tracing/tracing_controller_impl.h +++ b/content/browser/tracing/tracing_controller_impl.h @@ -25,22 +25,22 @@ class TracingControllerImpl : // TracingController implementation. virtual void GetCategories( const GetCategoriesDoneCallback& callback) OVERRIDE; - virtual void EnableRecording( + virtual bool EnableRecording( const base::debug::CategoryFilter& filter, TracingController::Options options, const EnableRecordingDoneCallback& callback) OVERRIDE; - virtual void DisableRecording( + virtual bool DisableRecording( const TracingFileResultCallback& callback) OVERRIDE; - virtual void EnableMonitoring(const base::debug::CategoryFilter& filter, + virtual bool EnableMonitoring(const base::debug::CategoryFilter& filter, TracingController::Options options, const EnableMonitoringDoneCallback& callback) OVERRIDE; - virtual void DisableMonitoring( + virtual bool DisableMonitoring( const DisableMonitoringDoneCallback& callback) OVERRIDE; virtual void GetMonitoringStatus( bool* out_enabled, base::debug::CategoryFilter* out_filter, TracingController::Options* out_options) OVERRIDE; - virtual void CaptureCurrentMonitoringSnapshot( + virtual void CaptureMonitoringSnapshot( const TracingFileResultCallback& callback) OVERRIDE; private: @@ -53,7 +53,6 @@ class TracingControllerImpl : virtual ~TracingControllerImpl(); // TraceSubscriber implementation. - virtual void OnEndTracingComplete() OVERRIDE; virtual void OnTraceDataCollected( const scoped_refptr<base::RefCountedString>& events_str_ptr) OVERRIDE; @@ -61,12 +60,17 @@ class TracingControllerImpl : return !is_recording_; } - bool can_end_recording() const { - return is_recording_ && pending_end_ack_count_ == 0; + bool can_disable_recording() const { + return is_recording_ && pending_disable_recording_ack_count_ == 0; } - bool is_recording_enabled() const { - return can_end_recording(); + bool can_enable_monitoring() const { + return !is_monitoring_; + } + + bool can_disable_monitoring() const { + return is_monitoring_ && + pending_capture_monitoring_snapshot_ack_count_ == 0; } // Methods for use by TraceMessageFilter. @@ -77,20 +81,31 @@ class TracingControllerImpl : void OnLocalTraceDataCollected( const scoped_refptr<base::RefCountedString>& events_str_ptr, bool has_more_events); + // Callback of TraceLog::FlushMonitoring() for the local trace. + void OnLocalMonitoringTraceDataCollected( + const scoped_refptr<base::RefCountedString>& events_str_ptr, + bool has_more_events); void OnDisableRecordingAcked( const std::vector<std::string>& known_category_groups); + void OnCaptureMonitoringSnapshotAcked(); FilterMap filters_; // Pending acks for DisableRecording. - int pending_end_ack_count_; + int pending_disable_recording_ack_count_; + // Pending acks for CaptureMonitoringSnapshot. + int pending_capture_monitoring_snapshot_ack_count_; bool is_recording_; + bool is_monitoring_; GetCategoriesDoneCallback pending_get_categories_done_callback_; TracingFileResultCallback pending_disable_recording_done_callback_; + TracingFileResultCallback pending_capture_monitoring_snapshot_done_callback_; std::set<std::string> known_category_groups_; base::debug::TraceLog::Options trace_options_; base::debug::CategoryFilter category_filter_; - scoped_ptr<base::FilePath> recording_result_file_; + FILE* result_file_; + scoped_ptr<base::FilePath> result_file_path_; + bool result_file_has_at_least_one_result_; DISALLOW_COPY_AND_ASSIGN(TracingControllerImpl); }; diff --git a/content/public/browser/trace_subscriber.h b/content/public/browser/trace_subscriber.h index 02e9f1c..8b63d35 100644 --- a/content/public/browser/trace_subscriber.h +++ b/content/public/browser/trace_subscriber.h @@ -18,7 +18,7 @@ namespace content { class TraceSubscriber { public: // Called once after TraceController::EndTracingAsync. - virtual void OnEndTracingComplete() = 0; + virtual void OnEndTracingComplete() {} // Called 0 or more times between TraceController::BeginTracing and // OnEndTracingComplete. Use base::debug::TraceResultBuffer to convert one or diff --git a/content/public/browser/tracing_controller.h b/content/public/browser/tracing_controller.h index 18d4355..d3bc7bd 100644 --- a/content/public/browser/tracing_controller.h +++ b/content/public/browser/tracing_controller.h @@ -59,7 +59,7 @@ class TracingController { // // |options| controls what kind of tracing is enabled. typedef base::Callback<void()> EnableRecordingDoneCallback; - virtual void EnableRecording( + virtual bool EnableRecording( const base::debug::CategoryFilter& filter, TracingController::Options options, const EnableRecordingDoneCallback& callback) = 0; @@ -77,7 +77,7 @@ class TracingController { // the traced data. typedef base::Callback<void(scoped_ptr<base::FilePath>)> TracingFileResultCallback; - virtual void DisableRecording(const TracingFileResultCallback& callback) = 0; + virtual bool DisableRecording(const TracingFileResultCallback& callback) = 0; // Start monitoring on all processes. // @@ -91,7 +91,7 @@ class TracingController { // // |options| controls what kind of tracing is enabled. typedef base::Callback<void()> EnableMonitoringDoneCallback; - virtual void EnableMonitoring(const base::debug::CategoryFilter& filter, + virtual bool EnableMonitoring(const base::debug::CategoryFilter& filter, TracingController::Options options, const EnableMonitoringDoneCallback& callback) = 0; @@ -100,7 +100,7 @@ class TracingController { // Once all child processes have acked to the DisableMonitoring request, // DisableMonitoringDoneCallback is called back. typedef base::Callback<void()> DisableMonitoringDoneCallback; - virtual void DisableMonitoring( + virtual bool DisableMonitoring( const DisableMonitoringDoneCallback& callback) = 0; // Get the current monitoring configuration. @@ -116,10 +116,10 @@ class TracingController { // to avoid much runtime overhead of tracing. So, to end tracing, we must // asynchronously ask all child processes to flush any pending trace data. // - // Once all child processes have acked to the CaptureCurrentMonitoringSnapshot + // Once all child processes have acked to the CaptureMonitoringSnapshot // request, TracingFileResultCallback will be called back with a file that // contains the traced data. - virtual void CaptureCurrentMonitoringSnapshot( + virtual void CaptureMonitoringSnapshot( const TracingFileResultCallback& callback) = 0; protected: |