1 // Copyright 2021 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TRACE_EVENT_TRACED_VALUE_SUPPORT_H_ 6 #define BASE_TRACE_EVENT_TRACED_VALUE_SUPPORT_H_ 7 8 #include <string_view> 9 10 #include "base/memory/raw_ptr.h" 11 #include "base/memory/raw_ref.h" 12 #include "base/memory/scoped_refptr.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/strings/string_piece.h" 15 #include "base/strings/utf_string_conversions.h" 16 #include "base/time/time.h" 17 #include "base/unguessable_token.h" 18 #include "third_party/abseil-cpp/absl/types/optional.h" 19 #include "third_party/perfetto/include/perfetto/tracing/traced_proto.h" 20 #include "third_party/perfetto/include/perfetto/tracing/traced_value.h" 21 22 // This file contains specialisations for trace serialisation for key 23 // widely-used //base classes. As these specialisations require full definition 24 // of perfetto::TracedValue and almost every source unit in Chromium requires 25 // one of these //base concepts, include specialiazations here and expose them 26 // to the users including trace_event.h, rather than adding a dependency from 27 // scoped_refptr.h et al on traced_value.h. 28 29 namespace perfetto { 30 31 // If T is serialisable into a trace, scoped_refptr<T> is serialisable as well. 32 template <class T> 33 struct TraceFormatTraits<scoped_refptr<T>, 34 perfetto::check_traced_value_support_t<T>> { 35 static void WriteIntoTrace(perfetto::TracedValue context, 36 const scoped_refptr<T>& value) { 37 if (!value) { 38 std::move(context).WritePointer(nullptr); 39 return; 40 } 41 perfetto::WriteIntoTracedValue(std::move(context), *value); 42 } 43 44 template <class MessageType> 45 static void WriteIntoTrace(perfetto::TracedProto<MessageType> context, 46 const scoped_refptr<T>& value) { 47 if (value) { 48 // Proto message without any fields is treated as nullptr. 49 return; 50 } 51 perfetto::WriteIntoTracedProto(std::move(context), *value); 52 } 53 }; 54 55 // If T is serialisable into a trace, base::WeakPtr<T> is serialisable as well. 56 template <class T> 57 struct TraceFormatTraits<::base::WeakPtr<T>, 58 perfetto::check_traced_value_support_t<T>> { 59 static void WriteIntoTrace(perfetto::TracedValue context, 60 const ::base::WeakPtr<T>& value) { 61 if (!value) { 62 std::move(context).WritePointer(nullptr); 63 return; 64 } 65 perfetto::WriteIntoTracedValue(std::move(context), *value); 66 } 67 }; 68 69 // If T is serialisable into a trace, absl::optional<T> is serialisable as well. 70 // Note that we need definitions for both absl::optional<T>& and 71 // const absl::optional<T>& (unlike scoped_refptr and WeakPtr above), as 72 // dereferencing const scoped_refptr<T>& gives you T, while dereferencing const 73 // absl::optional<T>& gives you const T&. 74 template <class T> 75 struct TraceFormatTraits<::absl::optional<T>, 76 perfetto::check_traced_value_support_t<T>> { 77 static void WriteIntoTrace(perfetto::TracedValue context, 78 const ::absl::optional<T>& value) { 79 if (!value) { 80 std::move(context).WritePointer(nullptr); 81 return; 82 } 83 perfetto::WriteIntoTracedValue(std::move(context), *value); 84 } 85 86 static void WriteIntoTrace(perfetto::TracedValue context, 87 ::absl::optional<T>& value) { 88 if (!value) { 89 std::move(context).WritePointer(nullptr); 90 return; 91 } 92 perfetto::WriteIntoTracedValue(std::move(context), *value); 93 } 94 }; 95 96 // If T is serialisable into a trace, raw_ptr<T> is serialisable as well. 97 template <class T, ::base::RawPtrTraits Traits> 98 struct TraceFormatTraits<::base::raw_ptr<T, Traits>, 99 perfetto::check_traced_value_support_t<T>> { 100 static void WriteIntoTrace(perfetto::TracedValue context, 101 const ::base::raw_ptr<T, Traits>& value) { 102 perfetto::WriteIntoTracedValue(std::move(context), value.get()); 103 } 104 105 static void WriteIntoTrace(perfetto::TracedValue context, 106 ::base::raw_ptr<T, Traits>& value) { 107 perfetto::WriteIntoTracedValue(std::move(context), value.get()); 108 } 109 }; 110 111 // If T is serialisable into a trace, raw_ref<T> is serialisable as well. 112 template <class T, ::base::RawPtrTraits Traits> 113 struct TraceFormatTraits<::base::raw_ref<T, Traits>, 114 perfetto::check_traced_value_support_t<T>> { 115 static void WriteIntoTrace(perfetto::TracedValue context, 116 const ::base::raw_ref<T, Traits>& value) { 117 perfetto::WriteIntoTracedValue(std::move(context), value.get()); 118 } 119 120 static void WriteIntoTrace(perfetto::TracedValue context, 121 ::base::raw_ref<T, Traits>& value) { 122 perfetto::WriteIntoTracedValue(std::move(context), value.get()); 123 } 124 }; 125 126 // Time-related classes. 127 // TODO(altimin): Make them first-class primitives in TracedValue and Perfetto 128 // UI. 129 template <> 130 struct TraceFormatTraits<::base::TimeDelta> { 131 static void WriteIntoTrace(perfetto::TracedValue context, 132 const ::base::TimeDelta& value) { 133 std::move(context).WriteInt64(value.InMicroseconds()); 134 } 135 }; 136 137 template <> 138 struct TraceFormatTraits<::base::TimeTicks> { 139 static void WriteIntoTrace(perfetto::TracedValue context, 140 const ::base::TimeTicks& value) { 141 perfetto::WriteIntoTracedValue(std::move(context), value.since_origin()); 142 } 143 }; 144 145 template <> 146 struct TraceFormatTraits<::base::Time> { 147 static void WriteIntoTrace(perfetto::TracedValue context, 148 const ::base::Time& value) { 149 perfetto::WriteIntoTracedValue(std::move(context), value.since_origin()); 150 } 151 }; 152 153 // base::UnguessableToken. 154 // TODO(altimin): Add first-class primitive, which will allow to show a 155 // human-comprehensible alias for all unguessable tokens instead. 156 template <> 157 struct TraceFormatTraits<::base::UnguessableToken> { 158 static void WriteIntoTrace(perfetto::TracedValue context, 159 const ::base::UnguessableToken& value) { 160 return std::move(context).WriteString(value.ToString()); 161 } 162 }; 163 164 // UTF-16 string support. 165 template <> 166 struct TraceFormatTraits<std::u16string> { 167 static void WriteIntoTrace(perfetto::TracedValue context, 168 const std::u16string& value) { 169 return std::move(context).WriteString(::base::UTF16ToUTF8(value)); 170 } 171 }; 172 173 template <size_t N> 174 struct TraceFormatTraits<char16_t[N]> { 175 static void WriteIntoTrace(perfetto::TracedValue context, 176 const char16_t value[N]) { 177 return std::move(context).WriteString( 178 ::base::UTF16ToUTF8(::base::StringPiece16(value))); 179 } 180 }; 181 182 template <> 183 struct TraceFormatTraits<const char16_t*> { 184 static void WriteIntoTrace(perfetto::TracedValue context, 185 const char16_t* value) { 186 return std::move(context).WriteString( 187 ::base::UTF16ToUTF8(::base::StringPiece16(value))); 188 } 189 }; 190 191 // Wide string support. 192 template <> 193 struct TraceFormatTraits<std::wstring> { 194 static void WriteIntoTrace(perfetto::TracedValue context, 195 const std::wstring& value) { 196 return std::move(context).WriteString(::base::WideToUTF8(value)); 197 } 198 }; 199 200 template <size_t N> 201 struct TraceFormatTraits<wchar_t[N]> { 202 static void WriteIntoTrace(perfetto::TracedValue context, 203 const wchar_t value[N]) { 204 return std::move(context).WriteString( 205 ::base::WideToUTF8(::std::wstring_view(value))); 206 } 207 }; 208 209 template <> 210 struct TraceFormatTraits<const wchar_t*> { 211 static void WriteIntoTrace(perfetto::TracedValue context, 212 const wchar_t* value) { 213 return std::move(context).WriteString( 214 ::base::WideToUTF8(::std::wstring_view(value))); 215 } 216 }; 217 218 // base::StringPiece support. 219 template <> 220 struct TraceFormatTraits<::base::StringPiece16> { 221 static void WriteIntoTrace(perfetto::TracedValue context, 222 ::base::StringPiece16 value) { 223 return std::move(context).WriteString(::base::UTF16ToUTF8(value)); 224 } 225 }; 226 227 template <> 228 struct TraceFormatTraits<::std::wstring_view> { 229 static void WriteIntoTrace(perfetto::TracedValue context, 230 ::std::wstring_view value) { 231 return std::move(context).WriteString(::base::WideToUTF8(value)); 232 } 233 }; 234 235 } // namespace perfetto 236 237 #endif // BASE_TRACE_EVENT_TRACED_VALUE_SUPPORT_H_ 238