• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
6 #define NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
7 
8 #include <cstdint>
9 
10 #include "base/check.h"
11 #include "base/notreached.h"
12 #include "build/build_config.h"
13 #include "build/chromeos_buildflags.h"
14 
15 #if BUILDFLAG(IS_ANDROID)
16 #include "base/android/scoped_java_ref.h"
17 #endif
18 
19 namespace {
20 
21 // Recursively compute hash code of the given string as a constant expression.
22 template <int N>
recursive_hash(const char * str)23 constexpr uint32_t recursive_hash(const char* str) {
24   return (recursive_hash<N - 1>(str) * 31u +
25           static_cast<uint32_t>(str[N - 1])) %
26          138003713u;
27 }
28 
29 // Recursion stopper for the above function. Note that string of size 0 will
30 // result in compile error.
31 template <>
32 constexpr uint32_t recursive_hash<1>(const char* str) {
33   return static_cast<uint32_t>(*str);
34 }
35 
36 // Entry point to function that computes hash as constant expression.
37 #define COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(S) \
38   static_cast<int32_t>(recursive_hash<sizeof(S) - 1>(S))
39 
40 constexpr int TRAFFIC_ANNOTATION_UNINITIALIZED = -1;
41 
42 }  // namespace
43 
44 namespace net {
45 
46 struct PartialNetworkTrafficAnnotationTag;
47 
48 // Defined types for network traffic annotation tags.
49 struct NetworkTrafficAnnotationTag {
50   const int32_t unique_id_hash_code;
51 
52   bool operator==(const NetworkTrafficAnnotationTag& other) const {
53     return unique_id_hash_code == other.unique_id_hash_code;
54   }
55 
NotReachedNetworkTrafficAnnotationTag56   static NetworkTrafficAnnotationTag NotReached() {
57     NOTREACHED();
58     return net::NetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_UNINITIALIZED);
59   }
60 
61   // These functions are wrappers around the (private) constructor, so we can
62   // easily find the constructor's call-sites with a script.
63   template <size_t N1, size_t N2>
64   friend constexpr NetworkTrafficAnnotationTag DefineNetworkTrafficAnnotation(
65       const char (&unique_id)[N1],
66       const char (&proto)[N2]);
67 
68   template <size_t N1, size_t N2>
69   friend NetworkTrafficAnnotationTag CompleteNetworkTrafficAnnotation(
70       const char (&unique_id)[N1],
71       const PartialNetworkTrafficAnnotationTag& partial_annotation,
72       const char (&proto)[N2]);
73 
74   template <size_t N1, size_t N2, size_t N3>
75   friend NetworkTrafficAnnotationTag BranchedCompleteNetworkTrafficAnnotation(
76       const char (&unique_id)[N1],
77       const char (&group_id)[N2],
78       const PartialNetworkTrafficAnnotationTag& partial_annotation,
79       const char (&proto)[N3]);
80 
81 #if BUILDFLAG(IS_ANDROID)
82   // Allows C++ methods to receive a Java NetworkTrafficAnnotationTag via JNI,
83   // and convert it to the C++ version.
84   static NetworkTrafficAnnotationTag FromJavaAnnotation(
85       int32_t unique_id_hash_code);
86 #endif
87 
88   friend struct MutableNetworkTrafficAnnotationTag;
89 
90  private:
NetworkTrafficAnnotationTagNetworkTrafficAnnotationTag91   constexpr explicit NetworkTrafficAnnotationTag(int32_t unique_id_hash_code_)
92       : unique_id_hash_code(unique_id_hash_code_) {}
93 };
94 
95 struct PartialNetworkTrafficAnnotationTag {
96   const int32_t unique_id_hash_code;
97 
98 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
99   // |completing_id_hash_code| holds a reference to the hash coded unique id
100   // of a network traffic annotation (or group id of several network traffic
101   // annotations) that complete a partial network annotation. Please refer to
102   // the description of DefinePartialNetworkTrafficAnnotation function for more
103   // details.
104   // This value is used by the clang tools to find linkage between partial
105   // annotations and their completing parts, and is used in debug mode to check
106   // if an intended completing part is added to a partial network annotation.
107   const int32_t completing_id_hash_code;
108 #endif
109 
110   // This function is a wrapper around the (private) constructor, so we can
111   // easily find the constructor's call-sites with a script.
112   template <size_t N1, size_t N2, size_t N3>
113   friend constexpr PartialNetworkTrafficAnnotationTag
114   DefinePartialNetworkTrafficAnnotation(const char (&unique_id)[N1],
115                                         const char (&completing_id)[N2],
116                                         const char (&proto)[N3]);
117 
118   friend struct MutablePartialNetworkTrafficAnnotationTag;
119 
120  private:
121 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
PartialNetworkTrafficAnnotationTagPartialNetworkTrafficAnnotationTag122   constexpr PartialNetworkTrafficAnnotationTag(int32_t unique_id_hash_code_,
123                                                int32_t completing_id_hash_code_)
124       : unique_id_hash_code(unique_id_hash_code_),
125         completing_id_hash_code(completing_id_hash_code_) {}
126 #else
127   constexpr explicit PartialNetworkTrafficAnnotationTag(
128       int32_t unique_id_hash_code_)
129       : unique_id_hash_code(unique_id_hash_code_) {}
130 #endif
131 };
132 
133 // Function to convert a network traffic annotation's unique id and protobuf
134 // text into a NetworkTrafficAnnotationTag.
135 //
136 // This function serves as a tag that can be discovered and extracted via
137 // clang tools. This allows reviewing all network traffic that is generated
138 // and annotated by Chrome.
139 //
140 // |unique_id| should be a string that uniquely identifies this annotation
141 // across all of Chromium source code. |unique_id| should be kept unchanged
142 // as long as possible as its hashed value will be used for differnt logging,
143 // debugging, or auditing tasks. Unique ids should include only alphanumeric
144 // characters and underline.
145 // |proto| is a text-encoded NetworkTrafficAnnotation protobuf (see
146 // chrome/browser/privacy/traffic_annotation.proto)
147 //
148 // An empty and a sample template for the text-encoded protobuf can be found in
149 // tools/traffic_annotation/sample_traffic_annotation.cc.
150 // TODO(crbug.com/690323): Add tools to check annotation text's format during
151 // presubmit checks.
152 template <size_t N1, size_t N2>
DefineNetworkTrafficAnnotation(const char (& unique_id)[N1],const char (& proto)[N2])153 constexpr NetworkTrafficAnnotationTag DefineNetworkTrafficAnnotation(
154     const char (&unique_id)[N1],
155     const char (&proto)[N2]) {
156   return NetworkTrafficAnnotationTag(
157       COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(unique_id));
158 }
159 
160 // There are cases where the network traffic annotation cannot be fully
161 // specified in one place. For example, in one place we know the trigger of a
162 // network request and in another place we know the data that will be sent. In
163 // these cases, we prefer that both parts of the annotation appear in context so
164 // that they are updated if code changes. The following functions help splitting
165 // the network traffic annotation into two pieces. Please refer to
166 // tools/traffic_annotation/sample_traffic_annotation.cc for usage samples.
167 
168 // This function can be used to define a partial annotation that will be
169 // completed later. The completing annotation can be defined with either of
170 // 'CompleteNetworkTrafficAnnotation' or
171 // 'BranchedCompleteNetworkTrafficAnnotation' functions. In case of
172 // CompleteNetworkTrafficAnnotation, |completing_id| is the unique id of the
173 // annotation that will complete it. In the case of
174 // BranchedCompleteNetworkTrafficAnnotation, |completing_id| is the group id
175 // of the completing annotations.
176 template <size_t N1, size_t N2, size_t N3>
177 constexpr PartialNetworkTrafficAnnotationTag
DefinePartialNetworkTrafficAnnotation(const char (& unique_id)[N1],const char (& completing_id)[N2],const char (& proto)[N3])178 DefinePartialNetworkTrafficAnnotation(const char (&unique_id)[N1],
179                                       const char (&completing_id)[N2],
180                                       const char (&proto)[N3]) {
181 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
182   return PartialNetworkTrafficAnnotationTag(
183       COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(unique_id),
184       COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(completing_id));
185 #else
186   return PartialNetworkTrafficAnnotationTag(
187       COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(unique_id));
188 #endif
189 }
190 
191 // This function can be used to define a completing partial annotation. This
192 // annotation adds details to another annotation that is defined before.
193 // |partial_annotation| is the PartialNetworkTrafficAnnotationTag returned
194 // by a call to DefinePartialNetworkTrafficAnnotation().
195 template <size_t N1, size_t N2>
CompleteNetworkTrafficAnnotation(const char (& unique_id)[N1],const PartialNetworkTrafficAnnotationTag & partial_annotation,const char (& proto)[N2])196 NetworkTrafficAnnotationTag CompleteNetworkTrafficAnnotation(
197     const char (&unique_id)[N1],
198     const PartialNetworkTrafficAnnotationTag& partial_annotation,
199     const char (&proto)[N2]) {
200 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
201   DCHECK(partial_annotation.completing_id_hash_code ==
202              COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(unique_id) ||
203          partial_annotation.unique_id_hash_code ==
204              COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("test_partial") ||
205          partial_annotation.unique_id_hash_code ==
206              COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("undefined"));
207 #endif
208   return NetworkTrafficAnnotationTag(partial_annotation.unique_id_hash_code);
209 }
210 
211 // This function can be used to define a completing partial annotation that is
212 // branched into several annotations. In this case, |group_id| is a common id
213 // that is used by all members of the branch and referenced by partial
214 // annotation that is completed by them.
215 template <size_t N1, size_t N2, size_t N3>
BranchedCompleteNetworkTrafficAnnotation(const char (& unique_id)[N1],const char (& group_id)[N2],const PartialNetworkTrafficAnnotationTag & partial_annotation,const char (& proto)[N3])216 NetworkTrafficAnnotationTag BranchedCompleteNetworkTrafficAnnotation(
217     const char (&unique_id)[N1],
218     const char (&group_id)[N2],
219     const PartialNetworkTrafficAnnotationTag& partial_annotation,
220     const char (&proto)[N3]) {
221 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
222   DCHECK(partial_annotation.completing_id_hash_code ==
223              COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(group_id) ||
224          partial_annotation.unique_id_hash_code ==
225              COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("test_partial") ||
226          partial_annotation.unique_id_hash_code ==
227              COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH("undefined"));
228 #endif
229   return NetworkTrafficAnnotationTag(
230       COMPUTE_NETWORK_TRAFFIC_ANNOTATION_ID_HASH(unique_id));
231 }
232 
233 // Example for joining N x 1 partial annotations:
234 // N functions foo1(), ..., fooN() call one function bar(). Each
235 // foo...() function defines part of a network traffic annotation.
236 // These N partial annotations are combined with a second part in
237 // bar().
238 //
239 // void foo1() {
240 //   auto tag = DefinePartialNetworkTrafficAnnotation(
241 //       "call_by_foo1", "completion_by_bar", [partial_proto]);
242 //   bar(tag);
243 // }
244 // void foo2() {
245 //   auto tag = DefinePartialNetworkTrafficAnnotation(
246 //       "call_by_foo2", "completion_by_bar", [partial_proto]);
247 //   bar(tag);
248 // }
249 // void bar(PartialNetworkTrafficAnnotationTag tag) {
250 //   auto final_tag = CompleteNetworkTrafficAnnotation(
251 //     "completion_by_bar", tag, [rest_of_proto]);
252 //   // final_tag matches the value of tag (which is hash code of
253 //   // "call_by_fooX" where X can be 1 or 2).
254 //   net::URLFetcher::Create(..., final_tag);
255 // }
256 
257 // Example for joining 1 x N partial annotations:
258 // A function foo() calls a function bar(bool param), that sends
259 // different network requests depending on param. Both functions
260 // define parts of the network traffic annotation.
261 //
262 // void foo(bool param) {
263 //   auto tag = DefinePartialNetworkTrafficAnnotation(
264 //       "call_by_foo1", "completion_by_bar", [partial_proto]);
265 //   bar(param, tag);
266 // }
267 // void bar(bool param, PartialNetworkTrafficAnnotationTag tag) {
268 //   if (param) {
269 //     auto final_tag = BranchedCompleteNetworkTrafficAnnotation(
270 //       "call_bool_branch_1", "completion_by_bar", tag, [rest_of_proto]);
271 //     // final_tag is hash code of "call_bool_branch_1".
272 //     net::URLFetcher::Create(url1, ..., final_tag);
273 //   } else {
274 //     auto final_tag = BranchedCompleteNetworkTrafficAnnotation(
275 //       "call_bool_branch_2", "completion_by_bar", tag, [rest_of_proto]);
276 //     // final_tag is hash code of "call_bool_branch_2".
277 //     net::URLFetcher::Create(url2, ..., final_tag);
278 //   }
279 // }
280 
281 // Please do not use this unless uninitialized annotations are required.
282 // Mojo interfaces for this class and the next one are defined in
283 // '/services/network/public/mojom'.
284 struct MutableNetworkTrafficAnnotationTag {
MutableNetworkTrafficAnnotationTagMutableNetworkTrafficAnnotationTag285   MutableNetworkTrafficAnnotationTag()
286       : unique_id_hash_code(TRAFFIC_ANNOTATION_UNINITIALIZED) {}
MutableNetworkTrafficAnnotationTagMutableNetworkTrafficAnnotationTag287   explicit MutableNetworkTrafficAnnotationTag(
288       const NetworkTrafficAnnotationTag& traffic_annotation)
289       : unique_id_hash_code(traffic_annotation.unique_id_hash_code) {}
290 
291   int32_t unique_id_hash_code;
292 
293   bool operator==(const MutableNetworkTrafficAnnotationTag& other) const {
294     return unique_id_hash_code == other.unique_id_hash_code;
295   }
296 
NetworkTrafficAnnotationTagMutableNetworkTrafficAnnotationTag297   explicit operator NetworkTrafficAnnotationTag() const {
298     DCHECK(is_valid());
299     return NetworkTrafficAnnotationTag(unique_id_hash_code);
300   }
301 
is_validMutableNetworkTrafficAnnotationTag302   bool is_valid() const {
303     return unique_id_hash_code != TRAFFIC_ANNOTATION_UNINITIALIZED;
304   }
305 
resetMutableNetworkTrafficAnnotationTag306   void reset() { unique_id_hash_code = TRAFFIC_ANNOTATION_UNINITIALIZED; }
307 
308   // This function is a wrapper around the private constructor, so we can easily
309   // find the constructor's call-sites with a script.
310   friend MutableNetworkTrafficAnnotationTag
311   CreateMutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code);
312 
313  private:
MutableNetworkTrafficAnnotationTagMutableNetworkTrafficAnnotationTag314   explicit MutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code_)
315       : unique_id_hash_code(unique_id_hash_code_) {}
316 };
317 
318 inline MutableNetworkTrafficAnnotationTag
CreateMutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code)319 CreateMutableNetworkTrafficAnnotationTag(int32_t unique_id_hash_code) {
320   return MutableNetworkTrafficAnnotationTag(unique_id_hash_code);
321 }
322 
323 struct MutablePartialNetworkTrafficAnnotationTag {
324 #if !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
MutablePartialNetworkTrafficAnnotationTagMutablePartialNetworkTrafficAnnotationTag325   MutablePartialNetworkTrafficAnnotationTag()
326       : unique_id_hash_code(TRAFFIC_ANNOTATION_UNINITIALIZED),
327         completing_id_hash_code(TRAFFIC_ANNOTATION_UNINITIALIZED) {}
MutablePartialNetworkTrafficAnnotationTagMutablePartialNetworkTrafficAnnotationTag328   explicit MutablePartialNetworkTrafficAnnotationTag(
329       const PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
330       : unique_id_hash_code(partial_traffic_annotation.unique_id_hash_code),
331         completing_id_hash_code(
332             partial_traffic_annotation.completing_id_hash_code) {}
333 
334   int32_t unique_id_hash_code;
335   int32_t completing_id_hash_code;
336 
PartialNetworkTrafficAnnotationTagMutablePartialNetworkTrafficAnnotationTag337   explicit operator PartialNetworkTrafficAnnotationTag() const {
338     DCHECK(is_valid());
339     return PartialNetworkTrafficAnnotationTag(unique_id_hash_code,
340                                               completing_id_hash_code);
341   }
342 
is_validMutablePartialNetworkTrafficAnnotationTag343   bool is_valid() const {
344     return unique_id_hash_code != TRAFFIC_ANNOTATION_UNINITIALIZED &&
345            completing_id_hash_code != TRAFFIC_ANNOTATION_UNINITIALIZED;
346   }
347 
resetMutablePartialNetworkTrafficAnnotationTag348   void reset() {
349     unique_id_hash_code = TRAFFIC_ANNOTATION_UNINITIALIZED;
350     completing_id_hash_code = TRAFFIC_ANNOTATION_UNINITIALIZED;
351   }
352 #else
353   MutablePartialNetworkTrafficAnnotationTag()
354       : unique_id_hash_code(TRAFFIC_ANNOTATION_UNINITIALIZED) {}
355   explicit MutablePartialNetworkTrafficAnnotationTag(
356       const PartialNetworkTrafficAnnotationTag& partial_traffic_annotation)
357       : unique_id_hash_code(partial_traffic_annotation.unique_id_hash_code) {}
358 
359   int32_t unique_id_hash_code;
360 
361   explicit operator PartialNetworkTrafficAnnotationTag() const {
362     return PartialNetworkTrafficAnnotationTag(unique_id_hash_code);
363   }
364 
365   bool is_valid() const {
366     return unique_id_hash_code != TRAFFIC_ANNOTATION_UNINITIALIZED;
367   }
368 
369   void reset() { unique_id_hash_code = TRAFFIC_ANNOTATION_UNINITIALIZED; }
370 #endif  // !defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)
371 };
372 
373 }  // namespace net
374 
375 // Placeholder for unannotated usages.
376 #if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
377 #define TRAFFIC_ANNOTATION_WITHOUT_PROTO(ANNOTATION_ID) \
378   net::DefineNetworkTrafficAnnotation(ANNOTATION_ID, "No proto yet.")
379 #endif
380 
381 // These annotations are unavailable on desktop Linux + Windows. They are
382 // available on other platforms, since we only audit network annotations on
383 // Linux & Windows.
384 //
385 // On Linux and Windows, use MISSING_TRAFFIC_ANNOTATION or
386 // TRAFFIC_ANNOTATION_FOR_TESTS.
387 // TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
388 // complete.
389 #if !BUILDFLAG(IS_WIN) && \
390     !(BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS))
391 
392 #define NO_TRAFFIC_ANNOTATION_YET \
393   net::DefineNetworkTrafficAnnotation("undefined", "Nothing here yet.")
394 
395 #endif
396 
397 #define MISSING_TRAFFIC_ANNOTATION     \
398   net::DefineNetworkTrafficAnnotation( \
399       "missing", "Function called without traffic annotation.")
400 
401 #endif  // NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
402