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