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