Chromium Code Reviews| Index: components/metrics/call_stack_profile_struct_traits.h |
| diff --git a/components/metrics/call_stack_profile_struct_traits.h b/components/metrics/call_stack_profile_struct_traits.h |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b5f47ed2f2bc4805ca40b7ea725509f87b39031f |
| --- /dev/null |
| +++ b/components/metrics/call_stack_profile_struct_traits.h |
| @@ -0,0 +1,157 @@ |
| +// 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_CALL_STACK_PROFILE_STRUCT_TRAITS_H_ |
| +#define COMPONENTS_METRICS_CALL_STACK_PROFILE_STRUCT_TRAITS_H_ |
| + |
| +#include <vector> |
| + |
| +#include "base/files/file_path.h" |
| +#include "base/optional.h" |
| +#include "base/profiler/stack_sampling_profiler.h" |
| +#include "components/metrics/call_stack_profile_collector.mojom.h" |
| + |
| +namespace mojo { |
| + |
| +template <> |
| +struct StructTraits<metrics::mojom::CallStackModule, |
| + 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::CallStackFrame, |
| + base::StackSamplingProfiler::Frame> { |
| + static const uint64_t instruction_pointer( |
| + const base::StackSamplingProfiler::Frame& frame) { |
| + return frame.instruction_pointer; |
| + } |
| + static const 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(); |
| + |
| + // The module_index field must be checked to be in the valid range when |
| + // reading CallStackProfile. |
| + *out = base::StackSamplingProfiler::Frame(data.instruction_pointer(), |
| + module_index); |
| + return true; |
| + } |
| +}; |
| + |
| +template <> |
| +struct StructTraits<metrics::mojom::CallStackProfile, |
| + base::StackSamplingProfiler::CallStackProfile> { |
| + static const std::vector<base::StackSamplingProfiler::Module>& modules( |
| + const base::StackSamplingProfiler::CallStackProfile& profile, |
| + void* context) { |
| + Context* typed_context = static_cast<Context*>(context); |
| + if (!typed_context->modules) |
| + typed_context->modules = profile.modules; |
| + return *typed_context->modules; |
| + } |
| + static const std::vector<base::StackSamplingProfiler::Sample>& samples( |
| + const base::StackSamplingProfiler::CallStackProfile& profile, |
| + void* context) { |
| + Context* typed_context = static_cast<Context*>(context); |
| + if (!typed_context->samples) |
| + typed_context->samples = profile.samples; |
| + return *typed_context->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 void* SetUpContext( |
| + const base::StackSamplingProfiler::CallStackProfile& input) { |
| + return new Context; |
| + } |
| + static void TearDownContext( |
| + const base::StackSamplingProfiler::CallStackProfile& input, |
| + void* context) { |
| + delete static_cast<Context*>(context); |
| + } |
| + |
| + 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) { |
| + 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; |
| + } |
| + |
| + private: |
| + struct Context { |
| + base::Optional<std::vector<base::StackSamplingProfiler::Module>> modules; |
|
sky
2016/08/17 21:01:33
How come this is optional? The mojom doesn't have
Mike Wittman
2016/08/17 22:40:15
I'm using Optional to determine if these fields ha
Mike Wittman
2016/08/17 23:20:57
Actually, I don't believe I need Context at all...
|
| + base::Optional<std::vector<base::StackSamplingProfiler::Sample>> samples; |
| + }; |
| +}; |
| + |
| +} // mojo |
| + |
| +#endif // COMPONENTS_METRICS_CALL_STACK_PROFILE_STRUCT_TRAITS_H_ |