| Index: content/browser/tracing/tracing_controller_impl.cc
|
| diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc
|
| index af6bf14189f0f17409482f12eed0cdee143f5f3b..da406016f6ec127e061d4e802535e61fbfb0fc4c 100644
|
| --- a/content/browser/tracing/tracing_controller_impl.cc
|
| +++ b/content/browser/tracing/tracing_controller_impl.cc
|
| @@ -5,9 +5,11 @@
|
| #include "content/browser/tracing/tracing_controller_impl.h"
|
|
|
| #include "base/bind.h"
|
| +#include "base/debug/trace_event.h"
|
| #include "base/file_util.h"
|
| #include "base/json/string_escape.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/values.h"
|
| #include "content/browser/tracing/trace_message_filter.h"
|
| #include "content/common/child_process_messages.h"
|
| #include "content/public/browser/browser_message_filter.h"
|
| @@ -22,6 +24,13 @@ namespace {
|
| base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
|
| LAZY_INSTANCE_INITIALIZER;
|
|
|
| +// The keys of tracing parameters in JSON. Must keep consistent with
|
| +// third_party/trace-viewer/src/about_tracing/begin_recording.js.
|
| +const char kCategoryFilter[] = "categoryFilter";
|
| +const char kUseSystemTracing[] = "useSystemTracing";
|
| +const char kUseContinuousTracing[] = "useContinuousTracing";
|
| +const char kUseSampling[] = "useSampling";
|
| +
|
| } // namespace
|
|
|
| TracingController* TracingController::GetInstance() {
|
| @@ -116,9 +125,7 @@ TracingControllerImpl::TracingControllerImpl() :
|
| // Tracing may have been enabled by ContentMainRunner if kTraceStartup
|
| // is specified in command line.
|
| is_recording_(TraceLog::GetInstance()->IsEnabled()),
|
| - is_monitoring_(false),
|
| - category_filter_(
|
| - base::debug::CategoryFilter::kDefaultCategoryFilterString) {
|
| + is_monitoring_(false) {
|
| }
|
|
|
| TracingControllerImpl::~TracingControllerImpl() {
|
| @@ -138,14 +145,13 @@ void TracingControllerImpl::GetCategories(
|
| // message. So to get known categories, just begin and end tracing immediately
|
| // afterwards. This will ping all the child processes for categories.
|
| pending_get_categories_done_callback_ = callback;
|
| - EnableRecording(base::debug::CategoryFilter("*"),
|
| - TracingController::Options(),
|
| + EnableRecording("*", TracingController::Options(),
|
| EnableRecordingDoneCallback());
|
| DisableRecording(base::FilePath(), TracingFileResultCallback());
|
| }
|
|
|
| bool TracingControllerImpl::EnableRecording(
|
| - const base::debug::CategoryFilter& filter,
|
| + const std::string& category_filter,
|
| TracingController::Options options,
|
| const EnableRecordingDoneCallback& callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| @@ -166,13 +172,14 @@ bool TracingControllerImpl::EnableRecording(
|
| }
|
| // TODO(haraken): How to handle ENABLE_SYSTRACE?
|
|
|
| - TraceLog::GetInstance()->SetEnabled(filter, trace_options);
|
| + TraceLog::GetInstance()->SetEnabled(
|
| + base::debug::CategoryFilter(category_filter), trace_options);
|
| is_recording_ = true;
|
| - category_filter_ = TraceLog::GetInstance()->GetCurrentCategoryFilter();
|
|
|
| // Notify all child processes.
|
| - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
|
| - it->get()->SendBeginTracing(category_filter_.ToString(), trace_options);
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| + it->get()->SendBeginTracing(category_filter, trace_options);
|
| }
|
|
|
| if (!callback.is_null())
|
| @@ -202,15 +209,13 @@ bool TracingControllerImpl::DisableRecording(
|
| if (!callback.is_null() || !result_file_path.empty())
|
| result_file_.reset(new ResultFile(result_file_path));
|
|
|
| - // 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_disable_recording_ack_count_,
|
| // acked below.
|
| - pending_disable_recording_ack_count_ = filters_.size() + 1;
|
| + pending_disable_recording_ack_count_ = trace_message_filters_.size() + 1;
|
|
|
| - // Handle special case of zero child processes.
|
| + // Handle special case of zero child processes by immediately telling the
|
| + // caller that tracing has ended. Use asynchronous OnDisableRecordingAcked
|
| + // to avoid recursive call back to the caller.
|
| 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;
|
| @@ -221,14 +226,15 @@ bool TracingControllerImpl::DisableRecording(
|
| }
|
|
|
| // Notify all child processes.
|
| - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| it->get()->SendEndTracing();
|
| }
|
| return true;
|
| }
|
|
|
| bool TracingControllerImpl::EnableMonitoring(
|
| - const base::debug::CategoryFilter& filter,
|
| + const std::string& category_filter,
|
| TracingController::Options options,
|
| const EnableMonitoringDoneCallback& callback) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| @@ -246,8 +252,9 @@ bool TracingControllerImpl::EnableMonitoring(
|
| 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(),
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| + it->get()->SendEnableMonitoring(category_filter,
|
| base::debug::TraceLog::Options(monitoring_tracing_options));
|
| }
|
|
|
| @@ -265,7 +272,8 @@ bool TracingControllerImpl::DisableMonitoring(
|
| is_monitoring_ = false;
|
|
|
| // Notify all child processes.
|
| - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| it->get()->SendDisableMonitoring();
|
| }
|
|
|
| @@ -276,7 +284,7 @@ bool TracingControllerImpl::DisableMonitoring(
|
|
|
| void TracingControllerImpl::GetMonitoringStatus(
|
| bool* out_enabled,
|
| - base::debug::CategoryFilter* out_filter,
|
| + std::string* out_category_filter,
|
| TracingController::Options* out_options) {
|
| NOTIMPLEMENTED();
|
| }
|
| @@ -294,15 +302,15 @@ void TracingControllerImpl::CaptureMonitoringSnapshot(
|
| if (!callback.is_null() || !result_file_path.empty())
|
| monitoring_snapshot_file_.reset(new ResultFile(result_file_path));
|
|
|
| - // 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;
|
| + pending_capture_monitoring_snapshot_ack_count_ =
|
| + trace_message_filters_.size() + 1;
|
|
|
| - // Handle special case of zero child processes.
|
| + // Handle special case of zero child processes by immediately telling the
|
| + // caller that capturing snapshot has ended. Use asynchronous
|
| + // OnCaptureMonitoringSnapshotAcked to avoid recursive call back to the
|
| + // caller.
|
| 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,
|
| @@ -311,7 +319,8 @@ void TracingControllerImpl::CaptureMonitoringSnapshot(
|
| }
|
|
|
| // Notify all child processes.
|
| - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| it->get()->SendCaptureMonitoringSnapshot();
|
| }
|
|
|
| @@ -330,7 +339,8 @@ bool TracingControllerImpl::GetTraceBufferPercentFull(
|
| pending_trace_buffer_percent_full_callback_ = callback;
|
|
|
| // Count myself in pending_trace_buffer_percent_full_ack_count_, acked below.
|
| - pending_trace_buffer_percent_full_ack_count_ = filters_.size() + 1;
|
| + pending_trace_buffer_percent_full_ack_count_ =
|
| + trace_message_filters_.size() + 1;
|
| maximum_trace_buffer_percent_full_ = 0;
|
|
|
| // Handle special case of zero child processes.
|
| @@ -342,36 +352,75 @@ bool TracingControllerImpl::GetTraceBufferPercentFull(
|
| }
|
|
|
| // Notify all child processes.
|
| - for (FilterMap::iterator it = filters_.begin(); it != filters_.end(); ++it) {
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| it->get()->SendGetTraceBufferPercentFull();
|
| }
|
| return true;
|
| }
|
|
|
| -void TracingControllerImpl::AddFilter(TraceMessageFilter* filter) {
|
| +bool TracingControllerImpl::SetWatchEvent(
|
| + const std::string& category_name,
|
| + const std::string& event_name,
|
| + const WatchEventCallback& callback) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + if (!can_set_watch_event() || callback.is_null())
|
| + return false;
|
| +
|
| + watch_event_callback_ = callback;
|
| +
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| + it->get()->SendSetWatchEvent(category_name, event_name);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool TracingControllerImpl::CancelWatchEvent() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + if (!can_cancel_watch_event())
|
| + return false;
|
| +
|
| + for (TraceMessageFilterMap::iterator it = trace_message_filters_.begin();
|
| + it != trace_message_filters_.end(); ++it) {
|
| + it->get()->SendCancelWatchEvent();
|
| + }
|
| +
|
| + watch_event_callback_.Reset();
|
| + return true;
|
| +}
|
| +
|
| +void TracingControllerImpl::AddTraceMessageFilter(
|
| + TraceMessageFilter* trace_message_filter) {
|
| if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::AddFilter, base::Unretained(this),
|
| - make_scoped_refptr(filter)));
|
| + base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
|
| + base::Unretained(this),
|
| + make_scoped_refptr(trace_message_filter)));
|
| return;
|
| }
|
|
|
| - filters_.insert(filter);
|
| + trace_message_filters_.insert(trace_message_filter);
|
| if (can_disable_recording()) {
|
| - std::string cf_str = category_filter_.ToString();
|
| - filter->SendBeginTracing(cf_str, TraceLog::GetInstance()->trace_options());
|
| + trace_message_filter->SendBeginTracing(
|
| + TraceLog::GetInstance()->GetCurrentCategoryFilter().ToString(),
|
| + TraceLog::GetInstance()->trace_options());
|
| }
|
| }
|
|
|
| -void TracingControllerImpl::RemoveFilter(TraceMessageFilter* filter) {
|
| +void TracingControllerImpl::RemoveTraceMessageFilter(
|
| + TraceMessageFilter* trace_message_filter) {
|
| if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::RemoveFilter, base::Unretained(this),
|
| - make_scoped_refptr(filter)));
|
| + base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
|
| + base::Unretained(this),
|
| + make_scoped_refptr(trace_message_filter)));
|
| return;
|
| }
|
|
|
| - filters_.erase(filter);
|
| + trace_message_filters_.erase(trace_message_filter);
|
| }
|
|
|
| void TracingControllerImpl::OnDisableRecordingAcked(
|
| @@ -561,4 +610,55 @@ void TracingControllerImpl::OnTraceBufferPercentFullReply(float percent_full) {
|
| }
|
| }
|
|
|
| +void TracingControllerImpl::OnWatchEventMatched() {
|
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + base::Bind(&TracingControllerImpl::OnWatchEventMatched,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + if (!watch_event_callback_.is_null())
|
| + watch_event_callback_.Run();
|
| +}
|
| +
|
| +// static
|
| +bool TracingControllerImpl::ParseTracingParams(
|
| + const base::DictionaryValue* params,
|
| + std::string* category_filter,
|
| + Options* options) {
|
| + bool use_system_tracing;
|
| + bool use_continuous_tracing;
|
| + bool use_sampling;
|
| +
|
| + if (!params->GetString(kCategoryFilter, category_filter) ||
|
| + !params->GetBoolean(kUseSystemTracing, &use_system_tracing) ||
|
| + !params->GetBoolean(kUseContinuousTracing, &use_continuous_tracing) ||
|
| + !params->GetBoolean(kUseSampling, &use_sampling)) {
|
| + LOG(ERROR) << "Malformed params";
|
| + return false;
|
| + }
|
| +
|
| + int tracing_options = 0;
|
| + if (use_system_tracing)
|
| + tracing_options |= ENABLE_SYSTRACE;
|
| + if (use_continuous_tracing)
|
| + tracing_options |= RECORD_CONTINUOUSLY;
|
| + if (use_sampling)
|
| + tracing_options |= ENABLE_SAMPLING;
|
| +
|
| + *options = static_cast<Options>(tracing_options);
|
| + return true;
|
| +}
|
| +
|
| +// static
|
| +void TracingControllerImpl::EncodeTracingParams(
|
| + const std::string& category_filter,
|
| + Options options,
|
| + base::DictionaryValue* result) {
|
| + result->SetString(kCategoryFilter, category_filter);
|
| + result->SetBoolean(kUseSystemTracing, options & ENABLE_SYSTRACE);
|
| + result->SetBoolean(kUseContinuousTracing, options & RECORD_CONTINUOUSLY);
|
| + result->SetBoolean(kUseSampling, options & ENABLE_SAMPLING);
|
| +}
|
| +
|
| } // namespace content
|
|
|