| 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 4af29736a8684de53267b9d40276ea9c84767749..620630f86dc1202b026e995074a8449b48de7226 100644
|
| --- a/content/browser/tracing/tracing_controller_impl.cc
|
| +++ b/content/browser/tracing/tracing_controller_impl.cc
|
| @@ -16,6 +16,7 @@
|
| #include "base/macros.h"
|
| #include "base/memory/ref_counted_memory.h"
|
| #include "base/strings/string_number_conversions.h"
|
| +#include "base/strings/string_split.h"
|
| #include "base/sys_info.h"
|
| #include "base/threading/sequenced_worker_pool.h"
|
| #include "base/threading/thread_task_runner_handle.h"
|
| @@ -36,6 +37,8 @@
|
| #include "content/public/common/content_switches.h"
|
| #include "gpu/config/gpu_info.h"
|
| #include "net/base/network_change_notifier.h"
|
| +#include "services/resource_coordinator/tracing/coordinator_impl.h"
|
| +#include "services/service_manager/public/cpp/connector.h"
|
| #include "v8/include/v8-version-string.h"
|
|
|
| #if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \
|
| @@ -67,74 +70,29 @@ namespace {
|
| base::LazyInstance<TracingControllerImpl>::Leaky g_controller =
|
| LAZY_INSTANCE_INITIALIZER;
|
|
|
| -const char kChromeTracingAgentName[] = "chrome";
|
| -const char kETWTracingAgentName[] = "etw";
|
| -const char kArcTracingAgentName[] = "arc";
|
| -const char kChromeTraceLabel[] = "traceEvents";
|
| -
|
| -const int kStartTracingTimeoutSeconds = 30;
|
| -const int kIssueClockSyncTimeoutSeconds = 30;
|
| -const int kStopTracingRetryTimeMilliseconds = 100;
|
| -
|
| -std::string GetNetworkTypeString() {
|
| - switch (net::NetworkChangeNotifier::GetConnectionType()) {
|
| - case net::NetworkChangeNotifier::CONNECTION_ETHERNET:
|
| - return "Ethernet";
|
| - case net::NetworkChangeNotifier::CONNECTION_WIFI:
|
| - return "WiFi";
|
| - case net::NetworkChangeNotifier::CONNECTION_2G:
|
| - return "2G";
|
| - case net::NetworkChangeNotifier::CONNECTION_3G:
|
| - return "3G";
|
| - case net::NetworkChangeNotifier::CONNECTION_4G:
|
| - return "4G";
|
| - case net::NetworkChangeNotifier::CONNECTION_NONE:
|
| - return "None";
|
| - case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH:
|
| - return "Bluetooth";
|
| - case net::NetworkChangeNotifier::CONNECTION_UNKNOWN:
|
| - default:
|
| - break;
|
| - }
|
| - return "Unknown";
|
| -}
|
| -
|
| -std::string GetClockString() {
|
| - switch (base::TimeTicks::GetClock()) {
|
| - case base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC:
|
| - return "LINUX_CLOCK_MONOTONIC";
|
| - case base::TimeTicks::Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME:
|
| - return "IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME";
|
| - case base::TimeTicks::Clock::MAC_MACH_ABSOLUTE_TIME:
|
| - return "MAC_MACH_ABSOLUTE_TIME";
|
| - case base::TimeTicks::Clock::WIN_QPC:
|
| - return "WIN_QPC";
|
| - case base::TimeTicks::Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME:
|
| - return "WIN_ROLLOVER_PROTECTED_TIME_GET_TIME";
|
| - }
|
| -
|
| - NOTREACHED();
|
| - return std::string();
|
| -}
|
| -
|
| } // namespace
|
|
|
| TracingController* TracingController::GetInstance() {
|
| return TracingControllerImpl::GetInstance();
|
| }
|
|
|
| -TracingControllerImpl::TracingControllerImpl()
|
| - : pending_start_tracing_ack_count_(0),
|
| - pending_stop_tracing_ack_count_(0),
|
| - pending_trace_log_status_ack_count_(0),
|
| - maximum_trace_buffer_usage_(0),
|
| - approximate_event_count_(0),
|
| - pending_clock_sync_ack_count_(0),
|
| - enabled_tracing_modes_(0) {
|
| +TracingControllerImpl::TracingControllerImpl() {
|
| // Deliberately leaked, like this class.
|
| base::FileTracing::SetProvider(new FileTracingProviderImpl);
|
| }
|
|
|
| +void TracingControllerImpl::Initialize(service_manager::Connector* connector) {
|
| + if (connector) {
|
| + connector->BindInterface("tracing", &coordinator_);
|
| + return;
|
| + }
|
| + // If connector is null, the coordinator must be running in this process.
|
| + resource_coordinator::tracing::CoordinatorImpl* coordinator =
|
| + resource_coordinator::tracing::CoordinatorImpl::GetInstance();
|
| + DCHECK(coordinator);
|
| + coordinator->BindCoordinatorRequest(mojo::MakeRequest(&coordinator_));
|
| +}
|
| +
|
| TracingControllerImpl::~TracingControllerImpl() {
|
| // This is a Leaky instance.
|
| NOTREACHED();
|
| @@ -148,257 +106,74 @@ bool TracingControllerImpl::GetCategories(
|
| const GetCategoriesDoneCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| - // Known categories come back from child processes with the EndTracingAck
|
| - // 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;
|
| - if (!StartTracing(TraceConfig("*", ""), StartTracingDoneCallback())) {
|
| - pending_get_categories_done_callback_.Reset();
|
| - return false;
|
| - }
|
| -
|
| - bool ok = StopTracing(NULL);
|
| - DCHECK(ok);
|
| + coordinator_->GetCategories(
|
| + base::BindRepeating(&TracingControllerImpl::GetCategoriesDone,
|
| + base::Unretained(this), callback));
|
| return true;
|
| }
|
|
|
| -void TracingControllerImpl::SetEnabledOnFileThread(
|
| - const TraceConfig& trace_config,
|
| - const base::Closure& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
| -
|
| - TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_);
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
| -}
|
| -
|
| -void TracingControllerImpl::SetDisabledOnFileThread(
|
| - const base::Closure& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::FILE);
|
| -
|
| - DCHECK(enabled_tracing_modes_);
|
| - TraceLog::GetInstance()->SetDisabled(enabled_tracing_modes_);
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
|
| +void TracingControllerImpl::GetCategoriesDone(
|
| + const GetCategoriesDoneCallback& callback,
|
| + const std::string& categories) {
|
| + const std::vector<std::string> split = base::SplitString(
|
| + categories, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
|
| + std::set<std::string> category_set;
|
| + for (const auto& category : split) {
|
| + category_set.insert(category);
|
| + }
|
| + callback.Run(category_set);
|
| }
|
|
|
| bool TracingControllerImpl::StartTracing(
|
| const TraceConfig& trace_config,
|
| const StartTracingDoneCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| - DCHECK(additional_tracing_agents_.empty());
|
| -
|
| - // TODO(ssid): Introduce a priority for tracing agents to handle multiple
|
| - // start and stop requests, crbug.com/705087.
|
| - if (!can_start_tracing())
|
| - return false;
|
| - start_tracing_done_callback_ = callback;
|
| - trace_config_.reset(new base::trace_event::TraceConfig(trace_config));
|
| - enabled_tracing_modes_ = TraceLog::RECORDING_MODE;
|
| - if (!trace_config_->event_filters().empty())
|
| - enabled_tracing_modes_ |= TraceLog::FILTERING_MODE;
|
| - metadata_.reset(new base::DictionaryValue());
|
| - pending_start_tracing_ack_count_ = 0;
|
| -
|
| -#if defined(OS_ANDROID)
|
| - if (pending_get_categories_done_callback_.is_null())
|
| - TraceLog::GetInstance()->AddClockSyncMetadataEvent();
|
| -#endif
|
| -
|
| - if (trace_config.IsSystraceEnabled()) {
|
| -#if defined(ENABLE_POWER_TRACING)
|
| - PowerTracingAgent::GetInstance()->StartAgentTracing(
|
| - trace_config,
|
| - base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| - base::Unretained(this)));
|
| - ++pending_start_tracing_ack_count_;
|
| -#endif
|
| -
|
| -#if defined(OS_CHROMEOS)
|
| - chromeos::DebugDaemonClient* debug_daemon =
|
| - chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
|
| - if (debug_daemon) {
|
| - debug_daemon->StartAgentTracing(
|
| - trace_config,
|
| - base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| - base::Unretained(this)));
|
| - ++pending_start_tracing_ack_count_;
|
| - }
|
| -
|
| - ArcTracingAgent::GetInstance()->StartAgentTracing(
|
| - trace_config,
|
| - base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| - base::Unretained(this)));
|
| - ++pending_start_tracing_ack_count_;
|
| -#elif defined(OS_WIN)
|
| - EtwTracingAgent::GetInstance()->StartAgentTracing(
|
| - trace_config,
|
| - base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| - base::Unretained(this)));
|
| - ++pending_start_tracing_ack_count_;
|
| -#endif
|
| - }
|
| -
|
| - // TraceLog may have been enabled in startup tracing before threads are ready.
|
| - if (TraceLog::GetInstance()->IsEnabled())
|
| - return true;
|
| -
|
| - StartAgentTracing(trace_config,
|
| - base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
|
| - base::Unretained(this)));
|
| - ++pending_start_tracing_ack_count_;
|
| -
|
| - // Set a deadline to ensure all agents ack within a reasonable time frame.
|
| - start_tracing_timer_.Start(
|
| - FROM_HERE, base::TimeDelta::FromSeconds(kStartTracingTimeoutSeconds),
|
| - base::Bind(&TracingControllerImpl::OnAllTracingAgentsStarted,
|
| - base::Unretained(this)));
|
|
|
| + is_tracing_ = true;
|
| + mojo::DataPipe data_pipe;
|
| + coordinator_->StartTracing(std::move(data_pipe.producer_handle),
|
| + trace_config.ToString());
|
| + drainer_.reset(new mojo::common::DataPipeDrainer(
|
| + this, std::move(data_pipe.consumer_handle)));
|
| + if (!callback.is_null())
|
| + callback.Run();
|
| return true;
|
| }
|
|
|
| -void TracingControllerImpl::OnAllTracingAgentsStarted() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| - TRACE_EVENT_API_ADD_METADATA_EVENT(
|
| - TraceLog::GetCategoryGroupEnabled("__metadata"),
|
| - "IsTimeTicksHighResolution", "value",
|
| - base::TimeTicks::IsHighResolution());
|
| -
|
| - // Notify all child processes.
|
| - for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
|
| - it != trace_message_filters_.end(); ++it) {
|
| - it->get()->SendBeginTracing(*trace_config_);
|
| - }
|
| -
|
| - if (!start_tracing_done_callback_.is_null())
|
| - start_tracing_done_callback_.Run();
|
| -
|
| - start_tracing_done_callback_.Reset();
|
| -}
|
| -
|
| -void TracingControllerImpl::AddMetadata(const base::DictionaryValue& data) {
|
| - if (metadata_)
|
| - metadata_->MergeDictionary(&data);
|
| -}
|
| -
|
| bool TracingControllerImpl::StopTracing(
|
| const scoped_refptr<TraceDataSink>& trace_data_sink) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| - if (!can_stop_tracing())
|
| - return false;
|
| -
|
| - // If we're still waiting to start tracing, try again after a delay.
|
| - if (start_tracing_timer_.IsRunning()) {
|
| - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing),
|
| - base::Unretained(this), trace_data_sink),
|
| - base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds));
|
| - return true;
|
| - }
|
| -
|
| - if (trace_data_sink) {
|
| - MetadataFilterPredicate metadata_filter;
|
| - if (TraceLog::GetInstance()->GetCurrentTraceConfig()
|
| - .IsArgumentFilterEnabled()) {
|
| - std::unique_ptr<TracingDelegate> delegate(
|
| - GetContentClient()->browser()->GetTracingDelegate());
|
| - if (delegate)
|
| - metadata_filter = delegate->GetMetadataFilterPredicate();
|
| - }
|
| - AddFilteredMetadata(trace_data_sink.get(), GenerateTracingMetadataDict(),
|
| - metadata_filter);
|
| - AddFilteredMetadata(trace_data_sink.get(), std::move(metadata_),
|
| - metadata_filter);
|
| - } else {
|
| - metadata_.reset();
|
| - }
|
| -
|
| trace_data_sink_ = trace_data_sink;
|
| - trace_config_.reset();
|
| -
|
| - // Issue clock sync marker before actually stopping tracing.
|
| - // StopTracingAfterClockSync() will be called after clock sync is done.
|
| - IssueClockSyncMarker();
|
| -
|
| + coordinator_->StopAndFlush();
|
| return true;
|
| }
|
|
|
| -void TracingControllerImpl::StopTracingAfterClockSync() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| - // |pending_clock_sync_ack_count_| could be non-zero if clock sync times out.
|
| - pending_clock_sync_ack_count_ = 0;
|
| -
|
| - // Disable local trace early to avoid traces during end-tracing process from
|
| - // interfering with the process.
|
| - base::Closure on_stop_tracing_done_callback = base::Bind(
|
| - &TracingControllerImpl::OnStopTracingDone, base::Unretained(this));
|
| - BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
|
| - base::Unretained(this),
|
| - on_stop_tracing_done_callback));
|
| -}
|
| -
|
| -void TracingControllerImpl::OnStopTracingDone() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| -#if defined(OS_ANDROID)
|
| - if (pending_get_categories_done_callback_.is_null())
|
| - TraceLog::GetInstance()->AddClockSyncMetadataEvent();
|
| -#endif
|
| -
|
| - // Count myself (local trace) in pending_stop_tracing_ack_count_,
|
| - // acked below.
|
| - pending_stop_tracing_ack_count_ = trace_message_filters_.size() + 1;
|
| - pending_stop_tracing_filters_ = trace_message_filters_;
|
| -
|
| - pending_stop_tracing_ack_count_ += additional_tracing_agents_.size();
|
| - for (auto* it : additional_tracing_agents_) {
|
| - it->StopAgentTracing(
|
| - base::Bind(&TracingControllerImpl::OnEndAgentTracingAcked,
|
| - base::Unretained(this)));
|
| - }
|
| - additional_tracing_agents_.clear();
|
| -
|
| - StopAgentTracing(StopAgentTracingCallback());
|
| -}
|
| -
|
| bool TracingControllerImpl::GetTraceBufferUsage(
|
| const GetTraceBufferUsageCallback& callback) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
|
|
| - if (!can_get_trace_buffer_usage() || callback.is_null())
|
| - return false;
|
| -
|
| - pending_trace_buffer_usage_callback_ = callback;
|
| -
|
| - // Count myself in pending_trace_log_status_ack_count_, acked below.
|
| - pending_trace_log_status_ack_count_ = trace_message_filters_.size() + 1;
|
| - pending_trace_log_status_filters_ = trace_message_filters_;
|
| - maximum_trace_buffer_usage_ = 0;
|
| - approximate_event_count_ = 0;
|
| -
|
| - base::trace_event::TraceLogStatus status =
|
| - TraceLog::GetInstance()->GetStatus();
|
| - // Call OnTraceLogStatusReply unconditionally for the browser process.
|
| - // This will result in immediate execution of the callback if there are no
|
| - // child processes.
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
|
| - base::Unretained(this), nullptr, status));
|
| -
|
| - // Notify all child processes.
|
| - for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
|
| - it != trace_message_filters_.end(); ++it) {
|
| - it->get()->SendGetTraceLogStatus();
|
| - }
|
| + coordinator_->RequestBufferUsage(
|
| + base::BindRepeating(&TracingControllerImpl::GetTraceBufferUsageDone,
|
| + base::Unretained(this), callback));
|
| return true;
|
| }
|
|
|
| +void TracingControllerImpl::AddMetadata(const base::DictionaryValue& metadata) {
|
| + if (metadata_)
|
| + metadata_->MergeDictionary(&metadata);
|
| +}
|
| +
|
| bool TracingControllerImpl::IsTracing() const {
|
| - return !!enabled_tracing_modes_;
|
| + return is_tracing_;
|
| +}
|
| +
|
| +void TracingControllerImpl::GetTraceBufferUsageDone(
|
| + const GetTraceBufferUsageCallback& callback,
|
| + bool success,
|
| + float percent_full,
|
| + uint32_t approximate_count) {
|
| + callback.Run(percent_full, approximate_count);
|
| }
|
|
|
| void TracingControllerImpl::AddTraceMessageFilter(
|
| @@ -420,11 +195,6 @@ void TracingControllerImpl::AddTraceMessageFilter(
|
| #endif
|
|
|
| trace_message_filters_.insert(trace_message_filter);
|
| - if (can_stop_tracing()) {
|
| - trace_message_filter->SendBeginTracing(
|
| - TraceLog::GetInstance()->GetCurrentTraceConfig());
|
| - }
|
| -
|
| for (auto& observer : trace_message_filter_observers_)
|
| observer.OnTraceMessageFilterAdded(trace_message_filter);
|
| }
|
| @@ -445,237 +215,9 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
|
| trace_message_filter->peer_pid());
|
| #endif
|
|
|
| - // If a filter is removed while a response from that filter is pending then
|
| - // simulate the response. Otherwise the response count will be wrong and the
|
| - // completion callback will never be executed.
|
| - if (pending_stop_tracing_ack_count_ > 0) {
|
| - TraceMessageFilterSet::const_iterator it =
|
| - pending_stop_tracing_filters_.find(trace_message_filter);
|
| - if (it != pending_stop_tracing_filters_.end()) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::OnStopTracingAcked,
|
| - base::Unretained(this),
|
| - base::RetainedRef(trace_message_filter),
|
| - std::vector<std::string>()));
|
| - }
|
| - }
|
| - if (pending_trace_log_status_ack_count_ > 0) {
|
| - TraceMessageFilterSet::const_iterator it =
|
| - pending_trace_log_status_filters_.find(trace_message_filter);
|
| - if (it != pending_trace_log_status_filters_.end()) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
|
| - base::Unretained(this),
|
| - base::RetainedRef(trace_message_filter),
|
| - base::trace_event::TraceLogStatus()));
|
| - }
|
| - }
|
| trace_message_filters_.erase(trace_message_filter);
|
| }
|
|
|
| -void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) {
|
| -#if defined(OS_CHROMEOS)
|
| - auto* debug_daemon =
|
| - chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
|
| - if (agent_name == debug_daemon->GetTracingAgentName()) {
|
| - additional_tracing_agents_.push_back(debug_daemon);
|
| - debug_daemon->SetStopAgentTracingTaskRunner(
|
| - BrowserThread::GetBlockingPool());
|
| - return;
|
| - }
|
| -
|
| - if (agent_name == kArcTracingAgentName) {
|
| - additional_tracing_agents_.push_back(ArcTracingAgent::GetInstance());
|
| - return;
|
| - }
|
| -#elif defined(OS_WIN)
|
| - auto* etw_agent = EtwTracingAgent::GetInstance();
|
| - if (agent_name == etw_agent->GetTracingAgentName()) {
|
| - additional_tracing_agents_.push_back(etw_agent);
|
| - return;
|
| - }
|
| -#endif
|
| -
|
| -#if defined(ENABLE_POWER_TRACING)
|
| - auto* power_agent = PowerTracingAgent::GetInstance();
|
| - if (agent_name == power_agent->GetTracingAgentName()) {
|
| - additional_tracing_agents_.push_back(power_agent);
|
| - return;
|
| - }
|
| -#endif
|
| -
|
| - DCHECK(agent_name == kChromeTracingAgentName);
|
| -}
|
| -
|
| -void TracingControllerImpl::OnStartAgentTracingAcked(
|
| - const std::string& agent_name,
|
| - bool success) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| - // Don't taken any further action if the ack came after the deadline.
|
| - if (!start_tracing_timer_.IsRunning())
|
| - return;
|
| -
|
| - if (success)
|
| - AddTracingAgent(agent_name);
|
| -
|
| - if (--pending_start_tracing_ack_count_ == 0) {
|
| - start_tracing_timer_.Stop();
|
| - OnAllTracingAgentsStarted();
|
| - }
|
| -}
|
| -
|
| -void TracingControllerImpl::OnStopTracingAcked(
|
| - TraceMessageFilter* trace_message_filter,
|
| - const std::vector<std::string>& known_category_groups) {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(
|
| - &TracingControllerImpl::OnStopTracingAcked, base::Unretained(this),
|
| - base::RetainedRef(trace_message_filter), known_category_groups));
|
| - return;
|
| - }
|
| -
|
| - // Merge known_category_groups with known_category_groups_
|
| - known_category_groups_.insert(known_category_groups.begin(),
|
| - known_category_groups.end());
|
| -
|
| - if (pending_stop_tracing_ack_count_ == 0)
|
| - return;
|
| -
|
| - if (trace_message_filter &&
|
| - !pending_stop_tracing_filters_.erase(trace_message_filter)) {
|
| - // The response from the specified message filter has already been received.
|
| - return;
|
| - }
|
| -
|
| - if (--pending_stop_tracing_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.
|
| - if (trace_data_sink_) {
|
| - TraceLog::GetInstance()->Flush(
|
| - base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
|
| - base::Unretained(this)),
|
| - true);
|
| - } else {
|
| - TraceLog::GetInstance()->CancelTracing(
|
| - base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
|
| - base::Unretained(this)));
|
| - }
|
| - return;
|
| - }
|
| -
|
| - if (pending_stop_tracing_ack_count_ != 0)
|
| - return;
|
| -
|
| - // All acks (including from the subprocesses and the local trace) have been
|
| - // received.
|
| - enabled_tracing_modes_ = 0;
|
| -
|
| - // Trigger callback if one is set.
|
| - if (!pending_get_categories_done_callback_.is_null()) {
|
| - pending_get_categories_done_callback_.Run(known_category_groups_);
|
| - pending_get_categories_done_callback_.Reset();
|
| - } else if (trace_data_sink_.get()) {
|
| - trace_data_sink_->Close();
|
| - trace_data_sink_ = NULL;
|
| - }
|
| -}
|
| -
|
| -void TracingControllerImpl::OnEndAgentTracingAcked(
|
| - const std::string& agent_name,
|
| - const std::string& events_label,
|
| - const scoped_refptr<base::RefCountedString>& events_str_ptr) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| - if (trace_data_sink_.get() && events_str_ptr &&
|
| - !events_str_ptr->data().empty()) {
|
| - if (agent_name == kETWTracingAgentName) {
|
| - // The Windows kernel events are kept into a JSON format stored as string
|
| - // and must not be escaped.
|
| - trace_data_sink_->AddAgentTrace(events_label, events_str_ptr->data());
|
| - } else if (agent_name == kArcTracingAgentName) {
|
| - // The ARC events are kept into a JSON format stored as string
|
| - // and must not be escaped.
|
| - trace_data_sink_->AddTraceChunk(events_str_ptr->data());
|
| - } else {
|
| - trace_data_sink_->AddAgentTrace(
|
| - events_label, base::GetQuotedJSONString(events_str_ptr->data()));
|
| - }
|
| - }
|
| - std::vector<std::string> category_groups;
|
| - OnStopTracingAcked(NULL, category_groups);
|
| -}
|
| -
|
| -void TracingControllerImpl::OnTraceDataCollected(
|
| - const scoped_refptr<base::RefCountedString>& events_str_ptr) {
|
| - // OnTraceDataCollected may be called from any browser thread, either by the
|
| - // local event trace system or from child processes via TraceMessageFilter.
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::OnTraceDataCollected,
|
| - base::Unretained(this), events_str_ptr));
|
| - return;
|
| - }
|
| -
|
| - if (trace_data_sink_.get())
|
| - trace_data_sink_->AddTraceChunk(events_str_ptr->data());
|
| -}
|
| -
|
| -void TracingControllerImpl::OnLocalTraceDataCollected(
|
| - 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 StopTracingAcked for the local trace.
|
| - std::vector<std::string> category_groups;
|
| - TraceLog::GetInstance()->GetKnownCategoryGroups(&category_groups);
|
| - OnStopTracingAcked(NULL, category_groups);
|
| -}
|
| -
|
| -void TracingControllerImpl::OnTraceLogStatusReply(
|
| - TraceMessageFilter* trace_message_filter,
|
| - const base::trace_event::TraceLogStatus& status) {
|
| - if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| - BrowserThread::PostTask(
|
| - BrowserThread::UI, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
|
| - base::Unretained(this),
|
| - base::RetainedRef(trace_message_filter), status));
|
| - return;
|
| - }
|
| -
|
| - if (pending_trace_log_status_ack_count_ == 0)
|
| - return;
|
| -
|
| - if (trace_message_filter &&
|
| - !pending_trace_log_status_filters_.erase(trace_message_filter)) {
|
| - // The response from the specified message filter has already been received.
|
| - return;
|
| - }
|
| -
|
| - float percent_full = static_cast<float>(
|
| - static_cast<double>(status.event_count) / status.event_capacity);
|
| - maximum_trace_buffer_usage_ =
|
| - std::max(maximum_trace_buffer_usage_, percent_full);
|
| - approximate_event_count_ += status.event_count;
|
| -
|
| - if (--pending_trace_log_status_ack_count_ == 0) {
|
| - // Trigger callback if one is set.
|
| - pending_trace_buffer_usage_callback_.Run(maximum_trace_buffer_usage_,
|
| - approximate_event_count_);
|
| - pending_trace_buffer_usage_callback_.Reset();
|
| - }
|
| -}
|
| -
|
| void TracingControllerImpl::RegisterTracingUI(TracingUI* tracing_ui) {
|
| DCHECK(tracing_uis_.find(tracing_ui) == tracing_uis_.end());
|
| tracing_uis_.insert(tracing_ui);
|
| @@ -687,238 +229,6 @@ void TracingControllerImpl::UnregisterTracingUI(TracingUI* tracing_ui) {
|
| tracing_uis_.erase(it);
|
| }
|
|
|
| -std::string TracingControllerImpl::GetTracingAgentName() {
|
| - return kChromeTracingAgentName;
|
| -}
|
| -
|
| -std::string TracingControllerImpl::GetTraceEventLabel() {
|
| - return kChromeTraceLabel;
|
| -}
|
| -
|
| -void TracingControllerImpl::StartAgentTracing(
|
| - const base::trace_event::TraceConfig& trace_config,
|
| - const StartAgentTracingCallback& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| - base::Closure on_agent_started =
|
| - base::Bind(callback, kChromeTracingAgentName, true);
|
| - if (!BrowserThread::PostTask(
|
| - BrowserThread::FILE, FROM_HERE,
|
| - base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
|
| - base::Unretained(this), trace_config,
|
| - on_agent_started))) {
|
| - // BrowserThread::PostTask fails if the threads haven't been created yet,
|
| - // so it should be safe to just use TraceLog::SetEnabled directly.
|
| - TraceLog::GetInstance()->SetEnabled(trace_config, enabled_tracing_modes_);
|
| - BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_agent_started);
|
| - }
|
| -}
|
| -
|
| -void TracingControllerImpl::StopAgentTracing(
|
| - const StopAgentTracingCallback& callback) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| - // Handle special case of zero child processes by immediately flushing the
|
| - // trace log. Once the flush has completed the caller will be notified that
|
| - // tracing has ended.
|
| - if (pending_stop_tracing_ack_count_ == 1) {
|
| - // Flush/cancel asynchronously now, because we don't have any children to
|
| - // wait for.
|
| - if (trace_data_sink_) {
|
| - TraceLog::GetInstance()->Flush(
|
| - base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
|
| - base::Unretained(this)),
|
| - true);
|
| - } else {
|
| - TraceLog::GetInstance()->CancelTracing(
|
| - base::Bind(&TracingControllerImpl::OnLocalTraceDataCollected,
|
| - base::Unretained(this)));
|
| - }
|
| - }
|
| -
|
| - // Notify all child processes.
|
| - for (auto it : trace_message_filters_) {
|
| - if (trace_data_sink_)
|
| - it->SendEndTracing();
|
| - else
|
| - it->SendCancelTracing();
|
| - }
|
| -}
|
| -
|
| -bool TracingControllerImpl::SupportsExplicitClockSync() {
|
| - return true;
|
| -}
|
| -
|
| -void TracingControllerImpl::RecordClockSyncMarker(
|
| - const std::string& sync_id,
|
| - const RecordClockSyncMarkerCallback& callback) {
|
| - DCHECK(SupportsExplicitClockSync());
|
| -
|
| - TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id);
|
| -}
|
| -
|
| -void TracingControllerImpl::IssueClockSyncMarker() {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| - DCHECK_EQ(0, pending_clock_sync_ack_count_);
|
| -
|
| - for (auto* it : additional_tracing_agents_) {
|
| - if (it->SupportsExplicitClockSync()) {
|
| - it->RecordClockSyncMarker(
|
| - base::GenerateGUID(),
|
| - base::Bind(&TracingControllerImpl::OnClockSyncMarkerRecordedByAgent,
|
| - base::Unretained(this)));
|
| - pending_clock_sync_ack_count_++;
|
| - }
|
| - }
|
| -
|
| - // If no clock sync is needed, stop tracing right away. Otherwise, schedule
|
| - // to stop tracing after timeout.
|
| - if (pending_clock_sync_ack_count_ == 0) {
|
| - StopTracingAfterClockSync();
|
| - } else {
|
| - clock_sync_timer_.Start(
|
| - FROM_HERE, base::TimeDelta::FromSeconds(kIssueClockSyncTimeoutSeconds),
|
| - this, &TracingControllerImpl::StopTracingAfterClockSync);
|
| - }
|
| -}
|
| -
|
| -void TracingControllerImpl::OnClockSyncMarkerRecordedByAgent(
|
| - const std::string& sync_id,
|
| - const base::TimeTicks& issue_ts,
|
| - const base::TimeTicks& issue_end_ts) {
|
| - DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| -
|
| - // TODO(charliea): Change this function so that it can accept a boolean
|
| - // success indicator instead of having to rely on sentinel issue_ts and
|
| - // issue_end_ts values to signal failure.
|
| - if (!(issue_ts == base::TimeTicks() || issue_end_ts == base::TimeTicks()))
|
| - TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts);
|
| -
|
| - // Timer is not running means that clock sync already timed out.
|
| - if (!clock_sync_timer_.IsRunning())
|
| - return;
|
| -
|
| - // Stop tracing only if all agents report back.
|
| - if (--pending_clock_sync_ack_count_ == 0) {
|
| - clock_sync_timer_.Stop();
|
| - StopTracingAfterClockSync();
|
| - }
|
| -}
|
| -
|
| -void TracingControllerImpl::AddFilteredMetadata(
|
| - TracingController::TraceDataSink* sink,
|
| - std::unique_ptr<base::DictionaryValue> metadata,
|
| - const MetadataFilterPredicate& filter) {
|
| - if (filter.is_null()) {
|
| - sink->AddMetadata(std::move(metadata));
|
| - return;
|
| - }
|
| - std::unique_ptr<base::DictionaryValue> filtered_metadata(
|
| - new base::DictionaryValue);
|
| - for (base::DictionaryValue::Iterator it(*metadata); !it.IsAtEnd();
|
| - it.Advance()) {
|
| - if (filter.Run(it.key()))
|
| - filtered_metadata->Set(it.key(), it.value().DeepCopy());
|
| - else
|
| - filtered_metadata->SetString(it.key(), "__stripped__");
|
| - }
|
| - sink->AddMetadata(std::move(filtered_metadata));
|
| -}
|
| -
|
| -std::unique_ptr<base::DictionaryValue>
|
| -TracingControllerImpl::GenerateTracingMetadataDict() const {
|
| - // It's important that this function creates a new metadata dict and returns
|
| - // it rather than directly populating the metadata_ member, as the data may
|
| - // need filtering in some cases.
|
| - std::unique_ptr<base::DictionaryValue> metadata_dict(
|
| - new base::DictionaryValue());
|
| -
|
| - metadata_dict->SetString("network-type", GetNetworkTypeString());
|
| - metadata_dict->SetString("product-version", GetContentClient()->GetProduct());
|
| - metadata_dict->SetString("v8-version", V8_VERSION_STRING);
|
| - metadata_dict->SetString("user-agent", GetContentClient()->GetUserAgent());
|
| -
|
| - // OS
|
| -#if defined(OS_CHROMEOS)
|
| - metadata_dict->SetString("os-name", "CrOS");
|
| - int32_t major_version;
|
| - int32_t minor_version;
|
| - int32_t bugfix_version;
|
| - // OperatingSystemVersion only has a POSIX implementation which returns the
|
| - // wrong versions for CrOS.
|
| - base::SysInfo::OperatingSystemVersionNumbers(&major_version, &minor_version,
|
| - &bugfix_version);
|
| - metadata_dict->SetString(
|
| - "os-version", base::StringPrintf("%d.%d.%d", major_version, minor_version,
|
| - bugfix_version));
|
| -#else
|
| - metadata_dict->SetString("os-name", base::SysInfo::OperatingSystemName());
|
| - metadata_dict->SetString("os-version",
|
| - base::SysInfo::OperatingSystemVersion());
|
| -#endif
|
| - metadata_dict->SetString("os-arch",
|
| - base::SysInfo::OperatingSystemArchitecture());
|
| -
|
| - // CPU
|
| - base::CPU cpu;
|
| - metadata_dict->SetInteger("cpu-family", cpu.family());
|
| - metadata_dict->SetInteger("cpu-model", cpu.model());
|
| - metadata_dict->SetInteger("cpu-stepping", cpu.stepping());
|
| - metadata_dict->SetInteger("num-cpus", base::SysInfo::NumberOfProcessors());
|
| - metadata_dict->SetInteger("physical-memory",
|
| - base::SysInfo::AmountOfPhysicalMemoryMB());
|
| -
|
| - std::string cpu_brand = cpu.cpu_brand();
|
| - // Workaround for crbug.com/249713.
|
| - // TODO(oysteine): Remove workaround when bug is fixed.
|
| - size_t null_pos = cpu_brand.find('\0');
|
| - if (null_pos != std::string::npos)
|
| - cpu_brand.erase(null_pos);
|
| - metadata_dict->SetString("cpu-brand", cpu_brand);
|
| -
|
| - // GPU
|
| - gpu::GPUInfo gpu_info = content::GpuDataManager::GetInstance()->GetGPUInfo();
|
| -
|
| -#if !defined(OS_ANDROID)
|
| - metadata_dict->SetInteger("gpu-venid", gpu_info.gpu.vendor_id);
|
| - metadata_dict->SetInteger("gpu-devid", gpu_info.gpu.device_id);
|
| -#endif
|
| -
|
| - metadata_dict->SetString("gpu-driver", gpu_info.driver_version);
|
| - metadata_dict->SetString("gpu-psver", gpu_info.pixel_shader_version);
|
| - metadata_dict->SetString("gpu-vsver", gpu_info.vertex_shader_version);
|
| -
|
| -#if defined(OS_MACOSX)
|
| - metadata_dict->SetString("gpu-glver", gpu_info.gl_version);
|
| -#elif defined(OS_POSIX)
|
| - metadata_dict->SetString("gpu-gl-vendor", gpu_info.gl_vendor);
|
| - metadata_dict->SetString("gpu-gl-renderer", gpu_info.gl_renderer);
|
| -#endif
|
| -
|
| - std::unique_ptr<TracingDelegate> delegate(
|
| - GetContentClient()->browser()->GetTracingDelegate());
|
| - if (delegate)
|
| - delegate->GenerateMetadataDict(metadata_dict.get());
|
| -
|
| - metadata_dict->SetString("clock-domain", GetClockString());
|
| - metadata_dict->SetBoolean("highres-ticks",
|
| - base::TimeTicks::IsHighResolution());
|
| -
|
| - metadata_dict->SetString("trace-config", trace_config_->ToString());
|
| -
|
| - metadata_dict->SetString(
|
| - "command_line",
|
| - base::CommandLine::ForCurrentProcess()->GetCommandLineString());
|
| -
|
| - base::Time::Exploded ctime;
|
| - base::Time::Now().UTCExplode(&ctime);
|
| - std::string time_string = base::StringPrintf(
|
| - "%u-%u-%u %d:%d:%d", ctime.year, ctime.month, ctime.day_of_month,
|
| - ctime.hour, ctime.minute, ctime.second);
|
| - metadata_dict->SetString("trace-capture-datetime", time_string);
|
| -
|
| - return metadata_dict;
|
| -}
|
| -
|
| void TracingControllerImpl::AddTraceMessageFilterObserver(
|
| TraceMessageFilterObserver* observer) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| @@ -937,4 +247,20 @@ void TracingControllerImpl::RemoveTraceMessageFilterObserver(
|
| observer->OnTraceMessageFilterRemoved(filter.get());
|
| }
|
|
|
| +void TracingControllerImpl::OnDataAvailable(const void* data,
|
| + size_t num_bytes) {
|
| + if (trace_data_sink_.get()) {
|
| + const std::string chunk(static_cast<const char*>(data), num_bytes);
|
| + trace_data_sink_->AddTraceChunk(chunk);
|
| + }
|
| +}
|
| +
|
| +void TracingControllerImpl::OnDataComplete() {
|
| + is_tracing_ = false;
|
| + if (trace_data_sink_.get()) {
|
| + trace_data_sink_->Close();
|
| + trace_data_sink_ = NULL;
|
| + }
|
| +}
|
| +
|
| } // namespace content
|
|
|