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