1 // Copyright 2020 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 5 #ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SURFACE_H_ 6 #define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SURFACE_H_ 7 8 #include <stdint.h> 9 10 #include <cstddef> 11 #include <functional> 12 #include <tuple> 13 14 #include "third_party/blink/public/common/common_export.h" 15 16 namespace blink { 17 18 // An identifiable surface. 19 // 20 // This class intends to be a lightweight wrapper over a simple integer. It 21 // exhibits the following characteristics: 22 // 23 // * All methods are constexpr. 24 // * Immutable. 25 // * Efficient enough to pass by value. 26 // 27 class IdentifiableSurface { 28 public: 29 // Type of identifiable surface. 30 // 31 // Even though the data type is uint64_t, we can only use 8 bits due to how we 32 // pack the surface type and a digest of the input into a 64 bits. See 33 // README.md in this directory for details on encoding. 34 // 35 // These values are used for aggregation across versions. Entries should not 36 // be renumbered and numeric values should never be reused. 37 enum class Type : uint64_t { 38 // This type is reserved for internal use and should not be used for 39 // reporting any identifiability metrics. 40 kReservedInternal = 0, 41 42 // Input is a mojom::WebFeature 43 kWebFeature = 1, 44 45 // We can use values up to and including |kMax|. 46 kMax = 0xff 47 }; 48 49 // Construct an IdentifiableSurface based on a precalculated metric hash. Can 50 // also be used as the first step in decoding an encoded metric hash. FromMetricHash(uint64_t metric_hash)51 static constexpr IdentifiableSurface FromMetricHash(uint64_t metric_hash) { 52 return IdentifiableSurface(metric_hash); 53 } 54 55 // Construct an IdentifiableSurface based on a surface type and an input hash. FromTypeAndInput(Type type,uint64_t input)56 static constexpr IdentifiableSurface FromTypeAndInput(Type type, 57 uint64_t input) { 58 return IdentifiableSurface(KeyFromSurfaceTypeAndInput(type, input)); 59 } 60 61 // Returns the UKM metric hash corresponding to this IdentifiableSurface. ToUkmMetricHash()62 constexpr uint64_t ToUkmMetricHash() const { return metric_hash_; } 63 64 // Returns the type of this IdentifiableSurface. GetType()65 constexpr Type GetType() const { 66 return std::get<0>(SurfaceTypeAndInputFromMetricKey(metric_hash_)); 67 } 68 69 // Returns the input hash for this IdentifiableSurface. 70 // 71 // The value that's returned can be different from what's used for 72 // constructing the IdentifiableSurface via FromTypeAndInput() if the input is 73 // >= 2^56. GetInputHash()74 constexpr uint64_t GetInputHash() const { 75 return std::get<1>(SurfaceTypeAndInputFromMetricKey(metric_hash_)); 76 } 77 78 private: 79 // Returns a 64-bit metric key given an IdentifiableSurfaceType and a 64 bit 80 // input digest. 81 // 82 // The returned key can be used as the metric hash when invoking 83 // UkmEntryBuilderBase::SetMetricInternal(). KeyFromSurfaceTypeAndInput(Type type,uint64_t input)84 static constexpr uint64_t KeyFromSurfaceTypeAndInput(Type type, 85 uint64_t input) { 86 uint64_t type_as_int = static_cast<uint64_t>(type); 87 return type_as_int | (input << 8); 88 } 89 90 // Returns the IdentifiableSurfaceType and the input hash given a metric key. 91 // 92 // This is approximately the inverse of MetricKeyFromSurfaceTypeAndInput(). 93 // See caveat in GetInputHash() about cases where the input hash can differ 94 // from that used to construct this IdentifiableSurface. SurfaceTypeAndInputFromMetricKey(uint64_t metric)95 static constexpr std::tuple<Type, uint64_t> SurfaceTypeAndInputFromMetricKey( 96 uint64_t metric) { 97 return std::make_tuple(static_cast<Type>(metric & 0xff), metric >> 8); 98 } 99 100 private: IdentifiableSurface(uint64_t metric_hash)101 constexpr explicit IdentifiableSurface(uint64_t metric_hash) 102 : metric_hash_(metric_hash) {} 103 uint64_t metric_hash_; 104 }; 105 106 constexpr bool operator<(const IdentifiableSurface& left, 107 const IdentifiableSurface& right) { 108 return left.ToUkmMetricHash() < right.ToUkmMetricHash(); 109 } 110 111 constexpr bool operator==(const IdentifiableSurface& left, 112 const IdentifiableSurface& right) { 113 return left.ToUkmMetricHash() == right.ToUkmMetricHash(); 114 } 115 116 constexpr bool operator!=(const IdentifiableSurface& left, 117 const IdentifiableSurface& right) { 118 return left.ToUkmMetricHash() != right.ToUkmMetricHash(); 119 } 120 121 // Hash function compatible with std::hash. 122 struct IdentifiableSurfaceHash { operatorIdentifiableSurfaceHash123 size_t operator()(const IdentifiableSurface& s) const { 124 return std::hash<uint64_t>{}(s.ToUkmMetricHash()); 125 } 126 }; 127 128 } // namespace blink 129 130 #endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SURFACE_H_ 131