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_IDENTIFIABILITY_METRIC_BUILDER_H_
6 #define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_METRIC_BUILDER_H_
7 
8 #include <cstdint>
9 
10 #include "base/metrics/ukm_source_id.h"
11 #include "services/metrics/public/cpp/ukm_entry_builder_base.h"
12 #include "third_party/blink/public/common/common_export.h"
13 #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
14 
15 namespace blink {
16 
17 // IdentifiabilityMetricBuilder builds an identifiability metric encoded into a
18 // UkmEntry.
19 //
20 // This UkmEntry can be recorded via a UkmRecorder.
21 //
22 // # Encoding
23 //
24 // All identifiability metrics are represented using the tuple
25 //
26 //     < identifiable_surface_type, input, output >.
27 //
28 // A typical URL-Keyed-Metrics (UKM) entry looks like the following:
29 //
30 //     struct UkmEntry {
31 //       int64 source_id;
32 //       uint64 event_hash;
33 //       map<uint64,int64> metrics;
34 //     };
35 //
36 // (From //services/metrics/public/mojom/ukm_interface.mojom)
37 //
38 // This class encodes the former into the latter.
39 //
40 // The |source_id| is one that is known to UKM. Follow UKM guidelines for how to
41 // generate or determine the |source_id| corresponding to a document or URL.
42 //
43 // The |event_hash| is a digest of the UKM event name via
44 // |base::HashMetricName()|. For identifiability metrics, this is always
45 // UINT64_C(287024497009309687) which corresponds to 'Identifiability'.
46 //
47 // Metrics for *regular* UKM consist of a mapping from a metric ID to a metric
48 // value. The metric ID is a digest of the metric name as determined by
49 // base::DigestForMetrics(), similar to how an |event_hash| is derived from the
50 // event name.
51 //
52 // However, for identifiability metrics, the method for generating metric IDs
53 // is:
54 //
55 //     metrics_hash = (input << 8) | identifiable_surface_type;
56 //
57 // The |identifiable_surface_type| is an enumeration identifying the input
58 // identifier defined in |IdentifiableSurface::Type|.
59 //
60 // We lose the 8 MSBs of |input|. Retaining the lower bits allow us to use small
61 // (i.e. under 56-bits) numbers as-is without losing information.
62 //
63 // The |IdentifiableSurface| class encapsulates this translation.
64 //
65 // The |metrics| field in |UkmEntry| thus contains a mapping from the resulting
66 // |metric_hash| to the output of the identifiable surface encoded into 64-bits.
67 //
68 // To generate a 64-bit hash of a random binary blob, use
69 // |blink::DigestForMetrics()|. For numbers with fewer than 56
70 // significant bits, you can use the number itself as the input hash.
71 //
72 // As mentioned in |identifiability_metrics.h|, this function is **not** a
73 // cryptographic hash function. While it is expected to have a reasonable
74 // distribution for a uniform input, it should be assumed that finding
75 // collisions is trivial.
76 //
77 // E.g.:
78 //
79 // 1. A simple web exposed API that's represented using a |WebFeature|
80 //    constant. Values are defined in
81 //    blink/public/mojom/web_feature/web_feature.mojom.
82 //
83 //        identifiable_surface = IdentifiableSurface::FromTypeAndInput(
84 //            IdentifiableSurface::Type::kWebFeature,
85 //            blink::mojom::WebFeature::kDeviceOrientationSecureOrigin);
86 //        output = DigestForMetrics(result_as_binary_blob);
87 //
88 // 2. A surface that takes a non-trivial input represented as a binary blob:
89 //
90 //        identifiable_surface = IdentifiableSurface::FromTypeAndInput(
91 //            IdentifiableSurface::Type::kFancySurface,
92 //            DigestForMetrics(input_as_binary_blob));
93 //        output = DigestForMetrics(result_as_binary_blob);
94 class BLINK_COMMON_EXPORT IdentifiabilityMetricBuilder
95     : public ukm::internal::UkmEntryBuilderBase {
96  public:
97   // Construct a metrics builder for the given |source_id|. The source must be
98   // known to UKM.
99   explicit IdentifiabilityMetricBuilder(base::UkmSourceId source_id);
100   ~IdentifiabilityMetricBuilder() override;
101 
102   // Set the metric using a previously constructed |IdentifiableSurface|.
103   IdentifiabilityMetricBuilder& Set(IdentifiableSurface surface,
104                                     int64_t result);
105 
106   // Set the metric using a surface type, input and result.
107   IdentifiabilityMetricBuilder& Set(IdentifiableSurface::Type surface_type,
108                                     int64_t input,
109                                     int64_t result);
110 };
111 
112 }  // namespace blink
113 
114 #endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_METRIC_BUILDER_H_
115