Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : */
5 :
6 : #ifndef Telemetry_Comms_h__
7 : #define Telemetry_Comms_h__
8 :
9 : #include "ipc/IPCMessageUtils.h"
10 : #include "nsITelemetry.h"
11 : #include "nsVariant.h"
12 : #include "mozilla/TimeStamp.h"
13 :
14 : namespace mozilla {
15 : namespace Telemetry {
16 :
17 : // Histogram accumulation types.
18 : enum HistogramID : uint32_t;
19 :
20 : struct Accumulation
21 : {
22 : mozilla::Telemetry::HistogramID mId;
23 : uint32_t mSample;
24 : };
25 :
26 1178 : struct KeyedAccumulation
27 : {
28 : mozilla::Telemetry::HistogramID mId;
29 : uint32_t mSample;
30 : nsCString mKey;
31 : };
32 :
33 : // Scalar accumulation types.
34 : enum class ScalarID : uint32_t;
35 :
36 : enum class ScalarActionType : uint32_t {
37 : eSet = 0,
38 : eAdd = 1,
39 : eSetMaximum = 2
40 : };
41 :
42 : typedef mozilla::Variant<uint32_t, bool, nsString> ScalarVariant;
43 :
44 0 : struct ScalarAction
45 : {
46 : ScalarID mId;
47 : ScalarActionType mActionType;
48 : // We need to wrap mData in a Maybe otherwise the IPC system
49 : // is unable to instantiate a ScalarAction.
50 : Maybe<ScalarVariant> mData;
51 : };
52 :
53 0 : struct KeyedScalarAction
54 : {
55 : ScalarID mId;
56 : ScalarActionType mActionType;
57 : nsCString mKey;
58 : // We need to wrap mData in a Maybe otherwise the IPC system
59 : // is unable to instantiate a ScalarAction.
60 : Maybe<ScalarVariant> mData;
61 : };
62 :
63 0 : struct EventExtraEntry {
64 : nsCString key;
65 : nsCString value;
66 : };
67 :
68 0 : struct ChildEventData {
69 : mozilla::TimeStamp timestamp;
70 : nsCString category;
71 : nsCString method;
72 : nsCString object;
73 : mozilla::Maybe<nsCString> value;
74 : nsTArray<EventExtraEntry> extra;
75 : };
76 :
77 : struct DiscardedData {
78 : uint32_t mDiscardedHistogramAccumulations;
79 : uint32_t mDiscardedKeyedHistogramAccumulations;
80 : uint32_t mDiscardedScalarActions;
81 : uint32_t mDiscardedKeyedScalarActions;
82 : uint32_t mDiscardedChildEvents;
83 : };
84 :
85 : } // namespace Telemetry
86 : } // namespace mozilla
87 :
88 : namespace IPC {
89 :
90 : template<>
91 : struct
92 : ParamTraits<mozilla::Telemetry::Accumulation>
93 : {
94 : typedef mozilla::Telemetry::Accumulation paramType;
95 :
96 668 : static void Write(Message* aMsg, const paramType& aParam)
97 : {
98 668 : aMsg->WriteUInt32(aParam.mId);
99 668 : WriteParam(aMsg, aParam.mSample);
100 668 : }
101 :
102 530 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
103 : {
104 1060 : if (!aMsg->ReadUInt32(aIter, reinterpret_cast<uint32_t*>(&(aResult->mId))) ||
105 530 : !ReadParam(aMsg, aIter, &(aResult->mSample))) {
106 0 : return false;
107 : }
108 :
109 530 : return true;
110 : }
111 : };
112 :
113 : template<>
114 : struct
115 : ParamTraits<mozilla::Telemetry::KeyedAccumulation>
116 : {
117 : typedef mozilla::Telemetry::KeyedAccumulation paramType;
118 :
119 236 : static void Write(Message* aMsg, const paramType& aParam)
120 : {
121 236 : aMsg->WriteUInt32(aParam.mId);
122 236 : WriteParam(aMsg, aParam.mSample);
123 236 : WriteParam(aMsg, aParam.mKey);
124 236 : }
125 :
126 177 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
127 : {
128 531 : if (!aMsg->ReadUInt32(aIter, reinterpret_cast<uint32_t*>(&(aResult->mId))) ||
129 354 : !ReadParam(aMsg, aIter, &(aResult->mSample)) ||
130 177 : !ReadParam(aMsg, aIter, &(aResult->mKey))) {
131 0 : return false;
132 : }
133 :
134 177 : return true;
135 : }
136 : };
137 :
138 : /**
139 : * IPC scalar data message serialization and de-serialization.
140 : */
141 : template<>
142 : struct
143 : ParamTraits<mozilla::Telemetry::ScalarAction>
144 : {
145 : typedef mozilla::Telemetry::ScalarAction paramType;
146 :
147 0 : static void Write(Message* aMsg, const paramType& aParam)
148 : {
149 : // Write the message type
150 0 : aMsg->WriteUInt32(static_cast<uint32_t>(aParam.mId));
151 0 : WriteParam(aMsg, static_cast<uint32_t>(aParam.mActionType));
152 :
153 0 : if (aParam.mData.isNothing()) {
154 0 : MOZ_CRASH("There is no data in the ScalarAction.");
155 : return;
156 : }
157 :
158 0 : if (aParam.mData->is<uint32_t>()) {
159 : // That's a nsITelemetry::SCALAR_COUNT.
160 0 : WriteParam(aMsg, static_cast<uint32_t>(nsITelemetry::SCALAR_COUNT));
161 0 : WriteParam(aMsg, aParam.mData->as<uint32_t>());
162 0 : } else if (aParam.mData->is<nsString>()) {
163 : // That's a nsITelemetry::SCALAR_STRING.
164 0 : WriteParam(aMsg, static_cast<uint32_t>(nsITelemetry::SCALAR_STRING));
165 0 : WriteParam(aMsg, aParam.mData->as<nsString>());
166 0 : } else if (aParam.mData->is<bool>()) {
167 : // That's a nsITelemetry::SCALAR_BOOLEAN.
168 0 : WriteParam(aMsg, static_cast<uint32_t>(nsITelemetry::SCALAR_BOOLEAN));
169 0 : WriteParam(aMsg, aParam.mData->as<bool>());
170 : } else {
171 0 : MOZ_CRASH("Unknown scalar type.");
172 : }
173 0 : }
174 :
175 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
176 : {
177 : // Read the scalar ID and the scalar type.
178 0 : uint32_t scalarType = 0;
179 0 : if (!aMsg->ReadUInt32(aIter, reinterpret_cast<uint32_t*>(&(aResult->mId))) ||
180 0 : !ReadParam(aMsg, aIter, reinterpret_cast<uint32_t*>(&(aResult->mActionType))) ||
181 0 : !ReadParam(aMsg, aIter, &scalarType)) {
182 0 : return false;
183 : }
184 :
185 : // De-serialize the data based on the scalar type.
186 0 : switch (scalarType)
187 : {
188 : case nsITelemetry::SCALAR_COUNT:
189 : {
190 0 : uint32_t data = 0;
191 : // De-serialize the data.
192 0 : if (!ReadParam(aMsg, aIter, &data)) {
193 0 : return false;
194 : }
195 0 : aResult->mData = mozilla::Some(mozilla::AsVariant(data));
196 0 : break;
197 : }
198 : case nsITelemetry::SCALAR_STRING:
199 : {
200 0 : nsString data;
201 : // De-serialize the data.
202 0 : if (!ReadParam(aMsg, aIter, &data)) {
203 0 : return false;
204 : }
205 0 : aResult->mData = mozilla::Some(mozilla::AsVariant(data));
206 0 : break;
207 : }
208 : case nsITelemetry::SCALAR_BOOLEAN:
209 : {
210 0 : bool data = false;
211 : // De-serialize the data.
212 0 : if (!ReadParam(aMsg, aIter, &data)) {
213 0 : return false;
214 : }
215 0 : aResult->mData = mozilla::Some(mozilla::AsVariant(data));
216 0 : break;
217 : }
218 : default:
219 0 : MOZ_ASSERT(false, "Unknown scalar type.");
220 : return false;
221 : }
222 :
223 0 : return true;
224 : }
225 : };
226 :
227 : /**
228 : * IPC keyed scalar data message serialization and de-serialization.
229 : */
230 : template<>
231 : struct
232 : ParamTraits<mozilla::Telemetry::KeyedScalarAction>
233 : {
234 : typedef mozilla::Telemetry::KeyedScalarAction paramType;
235 :
236 0 : static void Write(Message* aMsg, const paramType& aParam)
237 : {
238 : // Write the message type
239 0 : aMsg->WriteUInt32(static_cast<uint32_t>(aParam.mId));
240 0 : WriteParam(aMsg, static_cast<uint32_t>(aParam.mActionType));
241 0 : WriteParam(aMsg, aParam.mKey);
242 :
243 0 : if (aParam.mData.isNothing()) {
244 0 : MOZ_CRASH("There is no data in the KeyedScalarAction.");
245 : return;
246 : }
247 :
248 0 : if (aParam.mData->is<uint32_t>()) {
249 : // That's a nsITelemetry::SCALAR_COUNT.
250 0 : WriteParam(aMsg, static_cast<uint32_t>(nsITelemetry::SCALAR_COUNT));
251 0 : WriteParam(aMsg, aParam.mData->as<uint32_t>());
252 0 : } else if (aParam.mData->is<nsString>()) {
253 : // That's a nsITelemetry::SCALAR_STRING.
254 : // Keyed string scalars are not supported.
255 0 : MOZ_ASSERT(false, "Keyed String Scalar unable to be write from child process. Not supported.");
256 0 : } else if (aParam.mData->is<bool>()) {
257 : // That's a nsITelemetry::SCALAR_BOOLEAN.
258 0 : WriteParam(aMsg, static_cast<uint32_t>(nsITelemetry::SCALAR_BOOLEAN));
259 0 : WriteParam(aMsg, aParam.mData->as<bool>());
260 : } else {
261 0 : MOZ_CRASH("Unknown keyed scalar type.");
262 : }
263 0 : }
264 :
265 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
266 : {
267 : // Read the scalar ID and the scalar type.
268 0 : uint32_t scalarType = 0;
269 0 : if (!aMsg->ReadUInt32(aIter, reinterpret_cast<uint32_t*>(&(aResult->mId))) ||
270 0 : !ReadParam(aMsg, aIter, reinterpret_cast<uint32_t*>(&(aResult->mActionType))) ||
271 0 : !ReadParam(aMsg, aIter, &(aResult->mKey)) ||
272 0 : !ReadParam(aMsg, aIter, &scalarType)) {
273 0 : return false;
274 : }
275 :
276 : // De-serialize the data based on the scalar type.
277 0 : switch (scalarType)
278 : {
279 : case nsITelemetry::SCALAR_COUNT:
280 : {
281 0 : uint32_t data = 0;
282 : // De-serialize the data.
283 0 : if (!ReadParam(aMsg, aIter, &data)) {
284 0 : return false;
285 : }
286 0 : aResult->mData = mozilla::Some(mozilla::AsVariant(data));
287 0 : break;
288 : }
289 : case nsITelemetry::SCALAR_STRING:
290 : {
291 : // Keyed string scalars are not supported.
292 0 : MOZ_ASSERT(false, "Keyed String Scalar unable to be read from child process. Not supported.");
293 : return false;
294 : }
295 : case nsITelemetry::SCALAR_BOOLEAN:
296 : {
297 0 : bool data = false;
298 : // De-serialize the data.
299 0 : if (!ReadParam(aMsg, aIter, &data)) {
300 0 : return false;
301 : }
302 0 : aResult->mData = mozilla::Some(mozilla::AsVariant(data));
303 0 : break;
304 : }
305 : default:
306 0 : MOZ_ASSERT(false, "Unknown keyed scalar type.");
307 : return false;
308 : }
309 :
310 0 : return true;
311 : }
312 : };
313 :
314 : template<>
315 : struct
316 : ParamTraits<mozilla::Telemetry::ChildEventData>
317 : {
318 : typedef mozilla::Telemetry::ChildEventData paramType;
319 :
320 0 : static void Write(Message* aMsg, const paramType& aParam)
321 : {
322 0 : WriteParam(aMsg, aParam.timestamp);
323 0 : WriteParam(aMsg, aParam.category);
324 0 : WriteParam(aMsg, aParam.method);
325 0 : WriteParam(aMsg, aParam.object);
326 0 : WriteParam(aMsg, aParam.value);
327 0 : WriteParam(aMsg, aParam.extra);
328 0 : }
329 :
330 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
331 : {
332 0 : if (!ReadParam(aMsg, aIter, &(aResult->timestamp)) ||
333 0 : !ReadParam(aMsg, aIter, &(aResult->category)) ||
334 0 : !ReadParam(aMsg, aIter, &(aResult->method)) ||
335 0 : !ReadParam(aMsg, aIter, &(aResult->object)) ||
336 0 : !ReadParam(aMsg, aIter, &(aResult->value)) ||
337 0 : !ReadParam(aMsg, aIter, &(aResult->extra))) {
338 0 : return false;
339 : }
340 :
341 0 : return true;
342 : }
343 : };
344 :
345 : template<>
346 : struct
347 : ParamTraits<mozilla::Telemetry::EventExtraEntry>
348 : {
349 : typedef mozilla::Telemetry::EventExtraEntry paramType;
350 :
351 0 : static void Write(Message* aMsg, const paramType& aParam)
352 : {
353 0 : WriteParam(aMsg, aParam.key);
354 0 : WriteParam(aMsg, aParam.value);
355 0 : }
356 :
357 0 : static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
358 : {
359 0 : if (!ReadParam(aMsg, aIter, &(aResult->key)) ||
360 0 : !ReadParam(aMsg, aIter, &(aResult->value))) {
361 0 : return false;
362 : }
363 :
364 0 : return true;
365 : }
366 : };
367 :
368 : template<>
369 : struct
370 : ParamTraits<mozilla::Telemetry::DiscardedData>
371 : : public PlainOldDataSerializer<mozilla::Telemetry::DiscardedData>
372 : { };
373 :
374 : } // namespace IPC
375 :
376 : #endif // Telemetry_Comms_h__
|