1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_IP_PROTECTION_ANDROID_BLIND_SIGN_MESSAGE_ANDROID_IMPL_H_
#define COMPONENTS_IP_PROTECTION_ANDROID_BLIND_SIGN_MESSAGE_ANDROID_IMPL_H_
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include "base/containers/queue.h"
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/types/expected.h"
#include "components/ip_protection/android/android_auth_client_lib/cpp/ip_protection_auth_client_interface.h"
#include "net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_message_interface.h"
#include "net/third_party/quiche/src/quiche/blind_sign_auth/proto/auth_and_sign.pb.h"
#include "net/third_party/quiche/src/quiche/blind_sign_auth/proto/get_initial_data.pb.h"
namespace ip_protection {
// Uses the IpProtectionAuthClient to make IPC calls to service implementing IP
// Protection for async requests in BlindSignAuth. DoRequest makes an IPC
// request for either GetInitialData or AuthAndSign and if successful, receives
// a response body which is returned in a BlindSignMessageResponse along with a
// status_code of `absl::StatusCode::kOk`. An AuthRequestError is returned if
// otherwise and is mapped to an `absl::Status`.
//
// AuthRequestError will either be transient, persistent, or other (some failure
// not explicitly communicated by the service). AuthRequestError::kTransient
// maps to absl::Unavailable given that the client can retry the failing call.
// AuthRequestError::kPersistent maps to absl::FailedPreconditionError
// indicating that the request cannot be retried. AuthRequestError::kOther
// is for all other errors that are unexpected and therefore maps to
// absl::Unavailable so the request can be retried with backoff.
//
// See go/canonical-codes for more information on error codes.
class BlindSignMessageAndroidImpl : public quiche::BlindSignMessageInterface {
public:
// A request that has been queued, waiting for an internal
// IpProtectionAuthClient to become ready.
//
// Public for testing.
using PendingRequest = std::tuple<quiche::BlindSignMessageRequestType,
std::string,
quiche::BlindSignMessageCallback>;
// Factory signature for creating IpProtectionAuthClient(Interface)s.
//
// Public for testing.
using ClientFactory = void(
base::OnceCallback<ip_protection::android::
IpProtectionAuthClientInterface::ClientCreated>);
BlindSignMessageAndroidImpl();
~BlindSignMessageAndroidImpl() override;
// quiche::BlindSignMessageInterface implementation:
void DoRequest(quiche::BlindSignMessageRequestType request_type,
std::optional<std::string_view> authorization_header,
const std::string& body,
quiche::BlindSignMessageCallback callback) override;
// Set the auth client factory to be used when an auth client needs to be
// created.
void SetIpProtectionAuthClientFactoryForTesting(
base::RepeatingCallback<ClientFactory> factory) {
CHECK(factory);
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
client_factory_ = std::move(factory);
}
ip_protection::android::IpProtectionAuthClientInterface*
GetIpProtectionAuthClientForTesting() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return ip_protection_auth_client_.get();
}
const base::queue<PendingRequest>& GetPendingRequestsForTesting() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
return pending_requests_;
}
private:
using IpProtectionAuthClientInterface =
ip_protection::android::IpProtectionAuthClientInterface;
// Request to bind to the Android IP Protection service by creating a
// connected instance of `ip_protection_auth_client_`.
void CreateIpProtectionAuthClient();
// Makes either a GetInitialDataRequest or AuthAndSignRequest to the signing
// server using `ip_protection_auth_client_`.
void SendRequest(quiche::BlindSignMessageRequestType request_type,
const std::string& body,
quiche::BlindSignMessageCallback callback);
// Processes queued requests once `ip_protection_auth_client_` becomes
// available.
void ProcessPendingRequests();
void OnCreateIpProtectionAuthClientComplete(
base::TimeTicks start_time,
base::expected<std::unique_ptr<IpProtectionAuthClientInterface>,
std::string> ip_protection_auth_client);
template <typename ResponseType>
void OnSendRequestComplete(
base::WeakPtr<IpProtectionAuthClientInterface>
requesting_ip_protection_auth_client,
quiche::BlindSignMessageCallback callback,
base::TimeTicks start_time,
base::expected<ResponseType, ip_protection::android::AuthRequestError>
response);
SEQUENCE_CHECKER(sequence_checker_);
// The factory method for creating an IpProtectionAuthClient(Interface). Can
// be reconfigured by tests (See SetIpProtectionAuthClientFactoryForTesting).
// Must not be null.
base::RepeatingCallback<ClientFactory> client_factory_;
std::unique_ptr<IpProtectionAuthClientInterface> ip_protection_auth_client_
GUARDED_BY_CONTEXT(sequence_checker_) = nullptr;
// Queue of incoming requests waiting for `ip_protection_auth_client_` to
// connect to the Android IP Protection service. Once an instance is
// connected, the queue should be empty.
base::queue<PendingRequest> pending_requests_;
base::WeakPtrFactory<BlindSignMessageAndroidImpl> weak_ptr_factory_{this};
};
} // namespace ip_protection
#endif // COMPONENTS_IP_PROTECTION_ANDROID_BLIND_SIGN_MESSAGE_ANDROID_IMPL_H_
|