chromium/third_party/blink/public/common/privacy_budget/identifiable_token.h

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_H_
#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_H_

#include <cstdint>
#include <string_view>
#include <type_traits>

#include "base/containers/span.h"
#include "base/numerics/safe_conversions.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"

namespace blink {

// Constructs a token that can be used for reporting a metric or constructing an
// identifiable surface.
//
// The token construction is a single step conversion that takes one of several
// constrained inputs and emits a value. The method by which the value is
// constructed intentionally cannot be chained. If such behavior is required,
// then this class should be modified to accommodate the new use case rather
// than implementing custom chaining schemes at call sites.
//
// Once constructed, a token can only be consumed by
// IdentifiabiltyMetricsBuilder and IdentifiableSurface. For all others, it is a
// copyable, opaque token.
//
// Reliance on implicit conversion imposes limitations on how
// IdentifiableToken class is to be used. For example the following works:
//
//     std::string foo = ....;
//     IdentifiableToken sample(foo);
//
// .. due to the following implicit conversion:
//
//    1. std::string -> const std::string&
//             : lvalue -> lvalue reference + cv-qualification
//    2. const std::string& -> std::string_view
//             : user-defined conversion via constructor
//               std::string_view(const std::string&)
//
// However, when used within a builder expression, the user-defined conversion
// doesn't occur due to there not being a single user defined conversion from
// std::string -> IdentifiableToken. I.e. the following does not work:
//
//     std::string foo = ....;
//     IdentifiabilityMetricBuilder(...).Set(surface, foo);
//                                                    ^^^
//      The compiler can't deduce a two step user-defined conversion for |foo|.
//
// All overrides of the constructor should ensure that there exists a unique
// representation of the data type being sampled, and that the sample value is
// constructed based on this unique representation.
//
// TODO(asanka): Also require that the representation be portable.
//
// Extending IdentifiableToken to support more data types:
// -----------------------------------------------------------
//
// This class is intentionally placed in blink/public/common due to the
// requirement that these primitives be made available to both the renderer and
// the browser. However, it would be desirable to have renderer or browser
// specific functions for mapping common types in either domain into a sample.
//
// The recommended methods to do so are (one-of):
//
//   1. Use an existing byte span representation.
//
//      E.g.: Assuming |v| is a WTF::Vector
//          IdentifiabilityMetricBuilder(...).Set(...,
//              base::as_bytes(base::make_span(v.Data(), v.Size())));
//
//      Note again that serializing to a stream of bytes may not be sufficient
//      if the underlying types don't have a unique representation.
//
//   2. Construct a byte-wise unique representation and invoke
//      IdentifiableToken(ByteSpan) either explicitly or implicitly via
//      user-defined conversions.
//
// Note: Avoid doing template magic. There's already too much here. Templates
//       make it difficult to verify that the correct stable representation is
//       the one getting ingested into the reporting workflow.
//
//       Instead, explicitly invoke some wrapper that emits a ByteSpan (a.k.a.
//       base::span<const uint8_t>.
class IdentifiableToken {};

}  // namespace blink
#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_H_