mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-11-24 22:36:09 +03:00
312 lines
13 KiB
C
312 lines
13 KiB
C
|
// Copyright 2017 The Chromium Authors. All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style license that can be
|
||
|
// found in the LICENSE file.
|
||
|
|
||
|
#ifndef NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
|
||
|
#define NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
|
||
|
|
||
|
#include "base/logging.h"
|
||
|
#include "build/build_config.h"
|
||
|
|
||
|
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 static_cast<uint32_t>((recursive_hash<N - 1>(str) * 31 + str[N - 1]) %
|
||
|
138003713);
|
||
|
}
|
||
|
|
||
|
// 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 {
|
||
|
|
||
|
// 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();
|
||
|
return net::NetworkTrafficAnnotationTag({TRAFFIC_ANNOTATION_UNINITIALIZED});
|
||
|
}
|
||
|
};
|
||
|
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
|
||
|
};
|
||
|
|
||
|
// 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
|
||
|
// tools/traffic_annotation/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/690323): 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(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(
|
||
|
{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; }
|
||
|
};
|
||
|
|
||
|
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 !defined(OS_WIN) && !defined(OS_LINUX) && !defined(OS_CHROMEOS)
|
||
|
#define TRAFFIC_ANNOTATION_WITHOUT_PROTO(ANNOTATION_ID) \
|
||
|
net::DefineNetworkTrafficAnnotation(ANNOTATION_ID, "No proto yet.")
|
||
|
#endif
|
||
|
|
||
|
#define NO_TRAFFIC_ANNOTATION_YET \
|
||
|
net::DefineNetworkTrafficAnnotation("undefined", "Nothing here yet.")
|
||
|
|
||
|
#define NO_PARTIAL_TRAFFIC_ANNOTATION_YET \
|
||
|
net::DefinePartialNetworkTrafficAnnotation("undefined", "undefined", \
|
||
|
"Nothing here yet.")
|
||
|
|
||
|
#define MISSING_TRAFFIC_ANNOTATION \
|
||
|
net::DefineNetworkTrafficAnnotation( \
|
||
|
"missing", "Function called without traffic annotation.")
|
||
|
|
||
|
#endif // NET_TRAFFIC_ANNOTATION_NETWORK_TRAFFIC_ANNOTATION_H_
|