blob: 6a3af7cf363cf628cd1d5bbb9226218338d2591b [file] [log] [blame]
// Copyright 2016 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.
// Defines StructTraits specializations for translating between mojo types and
// base::StackSamplingProfiler types, with data validity checks.
#ifndef COMPONENTS_METRICS_PUBLIC_CPP_CALL_STACK_PROFILE_STRUCT_TRAITS_H_
#define COMPONENTS_METRICS_PUBLIC_CPP_CALL_STACK_PROFILE_STRUCT_TRAITS_H_
#include <string>
#include <utility>
#include <vector>
#include "base/files/file_path.h"
#include "base/profiler/stack_sampling_profiler.h"
#include "components/metrics/public/interfaces/call_stack_profile_collector.mojom.h"
namespace mojo {
template <>
struct StructTraits<metrics::mojom::CallStackModuleDataView,
base::StackSamplingProfiler::Module> {
static uint64_t base_address(
const base::StackSamplingProfiler::Module& module) {
return module.base_address;
}
static const std::string& id(
const base::StackSamplingProfiler::Module& module) {
return module.id;
}
static const base::FilePath& filename(
const base::StackSamplingProfiler::Module& module) {
return module.filename;
}
static bool Read(metrics::mojom::CallStackModuleDataView data,
base::StackSamplingProfiler::Module* out) {
std::string id;
base::FilePath filename;
if (!data.ReadId(&id) || !data.ReadFilename(&filename))
return false;
*out =
base::StackSamplingProfiler::Module(data.base_address(), id, filename);
return true;
}
};
template <>
struct StructTraits<metrics::mojom::CallStackFrameDataView,
base::StackSamplingProfiler::Frame> {
static uint64_t instruction_pointer(
const base::StackSamplingProfiler::Frame& frame) {
return frame.instruction_pointer;
}
static uint64_t module_index(
const base::StackSamplingProfiler::Frame& frame) {
return frame.module_index ==
base::StackSamplingProfiler::Frame::kUnknownModuleIndex ?
static_cast<uint64_t>(-1) :
frame.module_index;
}
static bool Read(metrics::mojom::CallStackFrameDataView data,
base::StackSamplingProfiler::Frame* out) {
size_t module_index = data.module_index() == static_cast<uint64_t>(-1) ?
base::StackSamplingProfiler::Frame::kUnknownModuleIndex :
data.module_index();
// We can't know whether the module_index field is valid at this point since
// we don't have access to the number of modules here. This will be checked
// in CallStackProfile's Read function below.
*out = base::StackSamplingProfiler::Frame(data.instruction_pointer(),
module_index);
return true;
}
};
template <>
struct StructTraits<metrics::mojom::CallStackSampleDataView,
base::StackSamplingProfiler::Sample> {
static const std::vector<base::StackSamplingProfiler::Frame>& frames(
const base::StackSamplingProfiler::Sample& sample) {
return sample.frames;
}
static int32_t process_milestones(
const base::StackSamplingProfiler::Sample& sample) {
return sample.process_milestones;
}
static bool Read(metrics::mojom::CallStackSampleDataView data,
base::StackSamplingProfiler::Sample* out) {
std::vector<base::StackSamplingProfiler::Frame> frames;
if (!data.ReadFrames(&frames))
return false;
*out = base::StackSamplingProfiler::Sample();
out->frames = std::move(frames);
out->process_milestones = data.process_milestones();
return true;
}
};
template <>
struct StructTraits<metrics::mojom::CallStackProfileDataView,
base::StackSamplingProfiler::CallStackProfile> {
static const std::vector<base::StackSamplingProfiler::Module>& modules(
const base::StackSamplingProfiler::CallStackProfile& profile) {
return profile.modules;
}
static const std::vector<base::StackSamplingProfiler::Sample>& samples(
const base::StackSamplingProfiler::CallStackProfile& profile) {
return profile.samples;
}
static const base::TimeDelta profile_duration(
const base::StackSamplingProfiler::CallStackProfile& profile) {
return profile.profile_duration;
}
static const base::TimeDelta sampling_period(
const base::StackSamplingProfiler::CallStackProfile& profile) {
return profile.sampling_period;
}
static bool ValidateSamples(
std::vector<base::StackSamplingProfiler::Sample> samples,
size_t module_count) {
for (const base::StackSamplingProfiler::Sample& sample : samples) {
for (const base::StackSamplingProfiler::Frame& frame : sample.frames) {
if (frame.module_index >= module_count &&
frame.module_index !=
base::StackSamplingProfiler::Frame::kUnknownModuleIndex)
return false;
}
}
return true;
}
static bool Read(metrics::mojom::CallStackProfileDataView data,
base::StackSamplingProfiler::CallStackProfile* out) {
std::vector<base::StackSamplingProfiler::Module> modules;
std::vector<base::StackSamplingProfiler::Sample> samples;
base::TimeDelta profile_duration, sampling_period;
if (!data.ReadModules(&modules) || !data.ReadSamples(&samples) ||
!data.ReadProfileDuration(&profile_duration) ||
!data.ReadSamplingPeriod(&sampling_period) ||
!ValidateSamples(samples, modules.size()))
return false;
*out = base::StackSamplingProfiler::CallStackProfile();
out->modules = std::move(modules);
out->samples = std::move(samples);
out->profile_duration = profile_duration;
out->sampling_period = sampling_period;
return true;
}
};
template <>
struct EnumTraits<metrics::mojom::Process,
metrics::CallStackProfileParams::Process> {
static metrics::mojom::Process ToMojom(
metrics::CallStackProfileParams::Process process) {
switch (process) {
case metrics::CallStackProfileParams::Process::UNKNOWN_PROCESS:
return metrics::mojom::Process::UNKNOWN_PROCESS;
case metrics::CallStackProfileParams::Process::BROWSER_PROCESS:
return metrics::mojom::Process::BROWSER_PROCESS;
case metrics::CallStackProfileParams::Process::RENDERER_PROCESS:
return metrics::mojom::Process::RENDERER_PROCESS;
case metrics::CallStackProfileParams::Process::GPU_PROCESS:
return metrics::mojom::Process::GPU_PROCESS;
case metrics::CallStackProfileParams::Process::UTILITY_PROCESS:
return metrics::mojom::Process::UTILITY_PROCESS;
case metrics::CallStackProfileParams::Process::ZYGOTE_PROCESS:
return metrics::mojom::Process::ZYGOTE_PROCESS;
case metrics::CallStackProfileParams::Process::SANDBOX_HELPER_PROCESS:
return metrics::mojom::Process::SANDBOX_HELPER_PROCESS;
case metrics::CallStackProfileParams::Process::PPAPI_PLUGIN_PROCESS:
return metrics::mojom::Process::PPAPI_PLUGIN_PROCESS;
case metrics::CallStackProfileParams::Process::PPAPI_BROKER_PROCESS:
return metrics::mojom::Process::PPAPI_BROKER_PROCESS;
}
NOTREACHED();
return metrics::mojom::Process::UNKNOWN_PROCESS;
}
static bool FromMojom(metrics::mojom::Process process,
metrics::CallStackProfileParams::Process* out) {
switch (process) {
case metrics::mojom::Process::UNKNOWN_PROCESS:
*out = metrics::CallStackProfileParams::Process::UNKNOWN_PROCESS;
return true;
case metrics::mojom::Process::BROWSER_PROCESS:
*out = metrics::CallStackProfileParams::Process::BROWSER_PROCESS;
return true;
case metrics::mojom::Process::RENDERER_PROCESS:
*out = metrics::CallStackProfileParams::Process::RENDERER_PROCESS;
return true;
case metrics::mojom::Process::GPU_PROCESS:
*out = metrics::CallStackProfileParams::Process::GPU_PROCESS;
return true;
case metrics::mojom::Process::UTILITY_PROCESS:
*out = metrics::CallStackProfileParams::Process::UTILITY_PROCESS;
return true;
case metrics::mojom::Process::ZYGOTE_PROCESS:
*out = metrics::CallStackProfileParams::Process::ZYGOTE_PROCESS;
return true;
case metrics::mojom::Process::SANDBOX_HELPER_PROCESS:
*out = metrics::CallStackProfileParams::Process::SANDBOX_HELPER_PROCESS;
return true;
case metrics::mojom::Process::PPAPI_PLUGIN_PROCESS:
*out = metrics::CallStackProfileParams::Process::PPAPI_PLUGIN_PROCESS;
return true;
case metrics::mojom::Process::PPAPI_BROKER_PROCESS:
*out = metrics::CallStackProfileParams::Process::PPAPI_BROKER_PROCESS;
return true;
}
return false;
}
};
template <>
struct EnumTraits<metrics::mojom::Thread,
metrics::CallStackProfileParams::Thread> {
static metrics::mojom::Thread ToMojom(
metrics::CallStackProfileParams::Thread thread) {
switch (thread) {
case metrics::CallStackProfileParams::Thread::UNKNOWN_THREAD:
return metrics::mojom::Thread::UNKNOWN_THREAD;
case metrics::CallStackProfileParams::Thread::UI_THREAD:
return metrics::mojom::Thread::UI_THREAD;
case metrics::CallStackProfileParams::Thread::FILE_THREAD:
return metrics::mojom::Thread::FILE_THREAD;
case metrics::CallStackProfileParams::Thread::FILE_USER_BLOCKING_THREAD:
return metrics::mojom::Thread::FILE_USER_BLOCKING_THREAD;
case metrics::CallStackProfileParams::Thread::PROCESS_LAUNCHER_THREAD:
return metrics::mojom::Thread::PROCESS_LAUNCHER_THREAD;
case metrics::CallStackProfileParams::Thread::CACHE_THREAD:
return metrics::mojom::Thread::CACHE_THREAD;
case metrics::CallStackProfileParams::Thread::IO_THREAD:
return metrics::mojom::Thread::IO_THREAD;
case metrics::CallStackProfileParams::Thread::DB_THREAD:
return metrics::mojom::Thread::DB_THREAD;
case metrics::CallStackProfileParams::Thread::GPU_MAIN_THREAD:
return metrics::mojom::Thread::GPU_MAIN_THREAD;
case metrics::CallStackProfileParams::Thread::RENDER_THREAD:
return metrics::mojom::Thread::RENDER_THREAD;
case metrics::CallStackProfileParams::Thread::UTILITY_THREAD:
return metrics::mojom::Thread::UTILITY_THREAD;
}
NOTREACHED();
return metrics::mojom::Thread::UNKNOWN_THREAD;
}
static bool FromMojom(metrics::mojom::Thread thread,
metrics::CallStackProfileParams::Thread* out) {
switch (thread) {
case metrics::mojom::Thread::UNKNOWN_THREAD:
*out = metrics::CallStackProfileParams::Thread::UNKNOWN_THREAD;
return true;
case metrics::mojom::Thread::UI_THREAD:
*out = metrics::CallStackProfileParams::Thread::UI_THREAD;
return true;
case metrics::mojom::Thread::FILE_THREAD:
*out = metrics::CallStackProfileParams::Thread::FILE_THREAD;
return true;
case metrics::mojom::Thread::FILE_USER_BLOCKING_THREAD:
*out =
metrics::CallStackProfileParams::Thread::FILE_USER_BLOCKING_THREAD;
return true;
case metrics::mojom::Thread::PROCESS_LAUNCHER_THREAD:
*out = metrics::CallStackProfileParams::Thread::PROCESS_LAUNCHER_THREAD;
return true;
case metrics::mojom::Thread::CACHE_THREAD:
*out = metrics::CallStackProfileParams::Thread::CACHE_THREAD;
return true;
case metrics::mojom::Thread::IO_THREAD:
*out = metrics::CallStackProfileParams::Thread::IO_THREAD;
return true;
case metrics::mojom::Thread::DB_THREAD:
*out = metrics::CallStackProfileParams::Thread::DB_THREAD;
return true;
case metrics::mojom::Thread::GPU_MAIN_THREAD:
*out = metrics::CallStackProfileParams::Thread::GPU_MAIN_THREAD;
return true;
case metrics::mojom::Thread::RENDER_THREAD:
*out = metrics::CallStackProfileParams::Thread::RENDER_THREAD;
return true;
case metrics::mojom::Thread::UTILITY_THREAD:
*out = metrics::CallStackProfileParams::Thread::UTILITY_THREAD;
return true;
}
return false;
}
};
template <>
struct EnumTraits<metrics::mojom::Trigger,
metrics::CallStackProfileParams::Trigger> {
static metrics::mojom::Trigger ToMojom(
metrics::CallStackProfileParams::Trigger trigger) {
switch (trigger) {
case metrics::CallStackProfileParams::Trigger::UNKNOWN:
return metrics::mojom::Trigger::UNKNOWN;
case metrics::CallStackProfileParams::Trigger::PROCESS_STARTUP:
return metrics::mojom::Trigger::PROCESS_STARTUP;
case metrics::CallStackProfileParams::Trigger::JANKY_TASK:
return metrics::mojom::Trigger::JANKY_TASK;
case metrics::CallStackProfileParams::Trigger::THREAD_HUNG:
return metrics::mojom::Trigger::THREAD_HUNG;
case metrics::CallStackProfileParams::Trigger::PERIODIC_COLLECTION:
return metrics::mojom::Trigger::PERIODIC_COLLECTION;
}
NOTREACHED();
return metrics::mojom::Trigger::UNKNOWN;
}
static bool FromMojom(metrics::mojom::Trigger trigger,
metrics::CallStackProfileParams::Trigger* out) {
switch (trigger) {
case metrics::mojom::Trigger::UNKNOWN:
*out = metrics::CallStackProfileParams::Trigger::UNKNOWN;
return true;
case metrics::mojom::Trigger::PROCESS_STARTUP:
*out = metrics::CallStackProfileParams::Trigger::PROCESS_STARTUP;
return true;
case metrics::mojom::Trigger::JANKY_TASK:
*out = metrics::CallStackProfileParams::Trigger::JANKY_TASK;
return true;
case metrics::mojom::Trigger::THREAD_HUNG:
*out = metrics::CallStackProfileParams::Trigger::THREAD_HUNG;
return true;
case metrics::mojom::Trigger::PERIODIC_COLLECTION:
*out = metrics::CallStackProfileParams::Trigger::PERIODIC_COLLECTION;
return true;
}
return false;
}
};
template <>
struct StructTraits<metrics::mojom::CallStackProfileParamsDataView,
metrics::CallStackProfileParams> {
static metrics::CallStackProfileParams::Process process(
const metrics::CallStackProfileParams& params) {
return params.process;
}
static metrics::CallStackProfileParams::Thread thread(
const metrics::CallStackProfileParams& params) {
return params.thread;
}
static metrics::CallStackProfileParams::Trigger trigger(
const metrics::CallStackProfileParams& params) {
return params.trigger;
}
static metrics::CallStackProfileParams::SampleOrderingSpec ordering_spec(
const metrics::CallStackProfileParams& params) {
return params.ordering_spec;
}
static bool Read(metrics::mojom::CallStackProfileParamsDataView data,
metrics::CallStackProfileParams* out) {
metrics::CallStackProfileParams::Process process;
metrics::CallStackProfileParams::Thread thread;
metrics::CallStackProfileParams::Trigger trigger;
metrics::CallStackProfileParams::SampleOrderingSpec ordering_spec;
if (!data.ReadProcess(&process) || !data.ReadThread(&thread) ||
!data.ReadTrigger(&trigger) || !data.ReadOrderingSpec(&ordering_spec)) {
return false;
}
*out = metrics::CallStackProfileParams(process, thread, trigger,
ordering_spec);
return true;
}
};
template <>
struct EnumTraits<metrics::mojom::SampleOrderingSpec,
metrics::CallStackProfileParams::SampleOrderingSpec> {
static metrics::mojom::SampleOrderingSpec ToMojom(
metrics::CallStackProfileParams::SampleOrderingSpec spec) {
switch (spec) {
case metrics::CallStackProfileParams::SampleOrderingSpec::MAY_SHUFFLE:
return metrics::mojom::SampleOrderingSpec::MAY_SHUFFLE;
case metrics::CallStackProfileParams::SampleOrderingSpec::PRESERVE_ORDER:
return metrics::mojom::SampleOrderingSpec::PRESERVE_ORDER;
}
NOTREACHED();
return metrics::mojom::SampleOrderingSpec::MAY_SHUFFLE;
}
static bool FromMojom(
metrics::mojom::SampleOrderingSpec spec,
metrics::CallStackProfileParams::SampleOrderingSpec* out) {
switch (spec) {
case metrics::mojom::SampleOrderingSpec::MAY_SHUFFLE:
*out = metrics::CallStackProfileParams::SampleOrderingSpec::MAY_SHUFFLE;
return true;
case metrics::mojom::SampleOrderingSpec::PRESERVE_ORDER:
*out =
metrics::CallStackProfileParams::SampleOrderingSpec::PRESERVE_ORDER;
return true;
}
return false;
}
};
} // namespace mojo
#endif // COMPONENTS_METRICS_PUBLIC_CPP_CALL_STACK_PROFILE_STRUCT_TRAITS_H_