910e62b5创建于 1月15日历史提交
// 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 SERVICES_NETWORK_TEST_TRUST_TOKEN_REQUEST_HANDLER_H_
#define SERVICES_NETWORK_TEST_TRUST_TOKEN_REQUEST_HANDLER_H_

#include <optional>
#include <set>
#include <string>
#include <string_view>

#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "net/http/http_request_headers.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/trust_tokens/types.h"
#include "url/gurl.h"
namespace network {
namespace test {

struct TrustTokenSignedRequest {
  GURL destination;
  net::HttpRequestHeaders headers;
};

// TrustTokenRequestHandler encapsulates server-side Trust Tokens issuance and
// redemption logic and implements some integrity and correctness checks for
// requests subsequently signed with keys bound to token redemptions.
//
// It's thread-safe so that the methods can be called by test code directly and
// by net::EmbeddedTestServer handlers.
class TrustTokenRequestHandler {
 public:
  struct Options;  // Definition below.
  explicit TrustTokenRequestHandler(Options options);

  // The default constructor uses reasonable default options.
  TrustTokenRequestHandler();

  ~TrustTokenRequestHandler();

  // TODO(davidvc): Provide a way to specify when keys expire.

  enum class ServerOperationOutcome {
    kExecuteOperationAsNormal,
    kUnconditionalFailure,
  };

  struct Options final {
    Options();
    ~Options();
    Options(const Options&);
    Options& operator=(const Options&);

    // The number of issuance key pairs to provide via key commitment results.
    int num_keys = 1;

    // The protocol version with which to parameterize the server-side
    // cryptographic logic. We return this value in key commitment results.
    std::string protocol_version = internal::ProtocolVersionToString(
        mojom::TrustTokenProtocolVersion::kTrustTokenV3Pmb);

    // The key commitment ID.
    int id = 1;

    // The number of tokens to sign per issuance operation; this value is also
    // provided to the client as part of key commitment results.
    int batch_size = 10;

    // If set to |kUnconditionalFailure|, returns a failure response for the
    // corresponding operation even if the operation would have succeeded had
    // the server been operating correctly.
    ServerOperationOutcome issuance_outcome =
        ServerOperationOutcome::kExecuteOperationAsNormal;
    ServerOperationOutcome redemption_outcome =
        ServerOperationOutcome::kExecuteOperationAsNormal;

    // The following two fields specify operating systems on which to specify
    // that the browser should attempt platform-provided trust token issuance
    // instead of sending requests directly to the issuer's server, and the
    // fallback behavior when these operations are unavailable. This information
    // will be included in GetKeyCommitmentRecord's returned commitments.
    std::set<mojom::TrustTokenKeyCommitmentResult::Os>
        specify_platform_issuance_on;
    mojom::TrustTokenKeyCommitmentResult::UnavailableLocalOperationFallback
        unavailable_local_operation_fallback =
            mojom::TrustTokenKeyCommitmentResult::
                UnavailableLocalOperationFallback::kReturnWithError;
  };

  // Updates the handler's options, resetting its internal state.
  void UpdateOptions(Options options);

  // Returns a key commitment record suitable for inserting into a {issuer:
  // commitment} dictionary passed to the network service via
  // NetworkService::SetTrustTokenKeyCommitments. This comprises |num_keys|
  // token verification keys, a protocol version of |protocol_version|, an ID of
  // |id| and  a batch size of |batch_size| (or none if |batch_size| is
  // nullopt).
  std::string GetKeyCommitmentRecord() const;

  // Given a base64-encoded issuance request, processes the
  // request and returns either nullopt (on error) or a base64-encoded response.
  std::optional<std::string> Issue(std::string_view issuance_request);

  // Given a base64-encoded redemption request, processes the
  // request and returns either nullopt (on error) or a string containing
  // the metadata values.
  std::optional<std::string> Redeem(std::string_view redemption_request);

  // Stores a representation of a signed request with the given destination and
  // headers in a manner that can be retrieved for inspection by calling
  // |last_incoming_signed_request|.
  void RecordSignedRequest(const GURL& destination,
                           const net::HttpRequestHeaders& headers);

  // Returns the public key hashes received in prior redemption requests.
  std::set<std::string> hashes_of_redemption_bound_public_keys() const;

  // Returns a structured representation of the last signed request received.
  std::optional<TrustTokenSignedRequest> last_incoming_signed_request() const;

 private:
  struct Rep;  // Contains state internal to this class's implementation.

  // Guards this class's internal state. This makes sure we're reading writes to
  // the state that occur while handling requests, which takes place off of the
  // main sequence due to how net::EmbeddedTestServer works.
  mutable base::Lock mutex_;
  std::unique_ptr<Rep> rep_ GUARDED_BY(mutex_);
};

}  // namespace test
}  // namespace network

#endif  // SERVICES_NETWORK_TEST_TRUST_TOKEN_REQUEST_HANDLER_H_