network_traffic_annotation.h 16 KB

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