summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorharaken@chromium.org <haraken@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-07 07:45:54 +0000
committerharaken@chromium.org <haraken@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-10-07 07:45:54 +0000
commitfd908e678588a998d8c9c666090ed9b50ff8bda8 (patch)
tree9f21ffeafab380c6f5bb497ebe1052e0a72dde78 /content
parenta217b8af416f1368b8e094da66ae017c83c78eee (diff)
downloadchromium_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.cc48
-rw-r--r--content/browser/tracing/trace_message_filter.h8
-rw-r--r--content/browser/tracing/tracing_controller_browsertest.cc93
-rw-r--r--content/browser/tracing/tracing_controller_impl.cc194
-rw-r--r--content/browser/tracing/tracing_controller_impl.h39
-rw-r--r--content/public/browser/trace_subscriber.h2
-rw-r--r--content/public/browser/tracing_controller.h12
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: