blob: 4e45bee124d13598551d56f7d884d733ba9719cf [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/tracing/child/child_trace_message_filter.h"
#include <memory>
#include "base/metrics/statistics_recorder.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "components/tracing/common/tracing_messages.h"
#include "ipc/ipc_channel.h"
using base::trace_event::MemoryDumpManager;
using base::trace_event::TraceLog;
namespace tracing {
namespace {
const int kMinTimeBetweenHistogramChangesInSeconds = 10;
} // namespace
ChildTraceMessageFilter::ChildTraceMessageFilter(
base::SingleThreadTaskRunner* ipc_task_runner)
: enabled_tracing_modes_(0),
sender_(nullptr),
ipc_task_runner_(ipc_task_runner) {}
void ChildTraceMessageFilter::OnFilterAdded(IPC::Channel* channel) {
sender_ = channel;
sender_->Send(new TracingHostMsg_ChildSupportsTracing());
}
void ChildTraceMessageFilter::SetSenderForTesting(IPC::Sender* sender) {
sender_ = sender;
}
void ChildTraceMessageFilter::OnFilterRemoved() {
sender_ = nullptr;
}
bool ChildTraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ChildTraceMessageFilter, message)
IPC_MESSAGE_HANDLER(TracingMsg_SetTracingProcessId, OnSetTracingProcessId)
IPC_MESSAGE_HANDLER(TracingMsg_SetUMACallback, OnSetUMACallback)
IPC_MESSAGE_HANDLER(TracingMsg_ClearUMACallback, OnClearUMACallback)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
ChildTraceMessageFilter::~ChildTraceMessageFilter() {}
void ChildTraceMessageFilter::OnSetTracingProcessId(
uint64_t tracing_process_id) {
MemoryDumpManager::GetInstance()->set_tracing_process_id(tracing_process_id);
}
void ChildTraceMessageFilter::OnHistogramChanged(
const std::string& histogram_name,
base::Histogram::Sample reference_lower_value,
base::Histogram::Sample reference_upper_value,
bool repeat,
base::Histogram::Sample actual_value) {
if (actual_value < reference_lower_value ||
actual_value > reference_upper_value) {
if (!repeat) {
ipc_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&ChildTraceMessageFilter::SendAbortBackgroundTracingMessage,
this));
}
return;
}
ipc_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&ChildTraceMessageFilter::SendTriggerMessage,
this, histogram_name));
}
void ChildTraceMessageFilter::SendTriggerMessage(
const std::string& histogram_name) {
if (!histogram_last_changed_.is_null()) {
base::Time computed_next_allowed_time =
histogram_last_changed_ +
base::TimeDelta::FromSeconds(kMinTimeBetweenHistogramChangesInSeconds);
if (computed_next_allowed_time > TRACE_TIME_NOW())
return;
}
histogram_last_changed_ = TRACE_TIME_NOW();
if (sender_)
sender_->Send(new TracingHostMsg_TriggerBackgroundTrace(histogram_name));
}
void ChildTraceMessageFilter::SendAbortBackgroundTracingMessage() {
if (sender_)
sender_->Send(new TracingHostMsg_AbortBackgroundTrace());
}
void ChildTraceMessageFilter::OnSetUMACallback(
const std::string& histogram_name,
int histogram_lower_value,
int histogram_upper_value,
bool repeat) {
histogram_last_changed_ = base::Time();
base::StatisticsRecorder::SetCallback(
histogram_name, base::Bind(&ChildTraceMessageFilter::OnHistogramChanged,
this, histogram_name, histogram_lower_value,
histogram_upper_value, repeat));
base::HistogramBase* existing_histogram =
base::StatisticsRecorder::FindHistogram(histogram_name);
if (!existing_histogram)
return;
std::unique_ptr<base::HistogramSamples> samples =
existing_histogram->SnapshotSamples();
if (!samples)
return;
std::unique_ptr<base::SampleCountIterator> sample_iterator =
samples->Iterator();
if (!sample_iterator)
return;
while (!sample_iterator->Done()) {
base::HistogramBase::Sample min;
int64_t max;
base::HistogramBase::Count count;
sample_iterator->Get(&min, &max, &count);
if (min >= histogram_lower_value && max <= histogram_upper_value) {
ipc_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&ChildTraceMessageFilter::SendTriggerMessage, this,
histogram_name));
break;
} else if (!repeat) {
ipc_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&ChildTraceMessageFilter::SendAbortBackgroundTracingMessage,
this));
break;
}
sample_iterator->Next();
}
}
void ChildTraceMessageFilter::OnClearUMACallback(
const std::string& histogram_name) {
histogram_last_changed_ = base::Time();
base::StatisticsRecorder::ClearCallback(histogram_name);
}
} // namespace tracing