blob: f67ed074393952f68a617bc366d81da2beb5aa1d [file] [log] [blame]
// 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 COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_CONFIGURATION_H_
#define COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_CONFIGURATION_H_
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include "base/functional/callback.h"
#include "components/reporting/proto/synced/record.pb.h"
#include "components/reporting/proto/synced/record_constants.pb.h"
#include "components/reporting/util/rate_limiter_interface.h"
#include "components/reporting/util/status.h"
#include "components/reporting/util/statusor.h"
#include "components/reporting/util/wrapped_rate_limiter.h"
namespace reporting {
// |EventType| enum is used to distinguish between user and device event types,
// and inherently determine the type of DM tokens (user vs device) generated.
enum class EventType { kDevice, kUser };
// ReportQueueConfiguration configures a report queue.
// |dm_token| if set will be attached to all records generated with this queue.
// Pass user DM tokens where applicable so the server can associate these events
// with the user. |event_type| describes the event type being reported and is
// indirectly used to retrieve DM tokens for downstream processing. Please use
// |EventType::kUser| for events that need to be associated with the current
// user. |destination| indicates what server side handler will be handling the
// records that are generated by the ReportQueueImpl. |policy_check_callback_|
// is a RepeatingCallback that verifies the specific report queue is allowed.
class ReportQueueConfiguration {
public:
// PolicyCheckCallbacks should return error::UNAUTHENTICATED if a policy check
// fails due to policies, any other error as appropriate, and OK if a policy
// check is successful.
using PolicyCheckCallback = base::RepeatingCallback<Status(void)>;
// Transient settings used by `ReportQueueConfiguration` instantiation.
struct Settings {
EventType event_type = EventType::kDevice;
Destination destination = Destination::UNDEFINED_DESTINATION;
int64_t reserved_space = 0L;
};
// Transient moveable helper class for composing `ReportQueueConfiguration`
// out of settings and then allowing to set non-trivial fields.
class Builder {
public:
explicit Builder(const Settings& settings);
Builder(Builder&&);
Builder& operator=(const Builder&) = delete;
~Builder();
// Modifiers for non-trivial fields.
Builder SetPolicyCheckCallback(PolicyCheckCallback policy_check_callback);
Builder SetRateLimiter(std::unique_ptr<RateLimiterInterface> rate_limiter);
Builder SetDMToken(std::string_view dm_token);
Builder SetSourceInfo(std::optional<SourceInfo> source_info);
// Finalizes the builder (no modifications are accepted after that) and
// outputs the final `ReportQueueConfiguration` or status.
StatusOr<std::unique_ptr<ReportQueueConfiguration>> Build();
private:
StatusOr<std::unique_ptr<ReportQueueConfiguration>> final_value_;
};
~ReportQueueConfiguration();
ReportQueueConfiguration(const ReportQueueConfiguration& other) = delete;
ReportQueueConfiguration& operator=(const ReportQueueConfiguration& other) =
delete;
// Factory for generating a `ReportQueueConfiguration`.
// The factory produces `Builder` thus allowing to set non-trivial fields.
// Once everything is set, `Builder` can be assigned (once!) using
// cast operator to `StatusOr<std::unique_ptr<ReportQueueConfiguration>>()`.
//
// Example usage:
// StatusOr<reporting::ReportQueueConfiguration> config_result =
// reporting::ReportQueueConfiguration::Create(
// {.event_type = EventType::kUser,
// .destination = Destination::HEART_BEAT})
// .SetRateLimiter(std::make_unique<RateLimiterTokenBucket>(
// /*max_level=*/1024,
// /*filling_time=*/base::Minutes(10)))
// .Build();
// if (!config_result.has_value()) {
// return config_result.error();
// }
// auto config = config_result.value();
static Builder Create(const Settings& settings);
// Deprecated and should not be used. Use `Create({settings})` instead.
//
// Factory for generating a ReportQueueConfiguration.
// If any of the parameters are invalid, will return error::INVALID_ARGUMENT.
// `dm_token` is valid when dm_token.is_valid() is true.
// `destination` is valid when it is any value other than
// Destination::UNDEFINED_DESTINATION.
// If `reserved_space` > 0, underlying Storage would only accept enqueue
// request if after it remaining amount of disk space will not drop below
// `reserved_space`. Intended for use by opportunistic queue.
static StatusOr<std::unique_ptr<ReportQueueConfiguration>> Create(
std::string_view dm_token,
Destination destination,
PolicyCheckCallback policy_check_callback,
std::unique_ptr<RateLimiterInterface> rate_limiter = nullptr,
int64_t reserved_space = 0L);
// Deprecated and should not be used. Use `Create({settings})` instead.
//
// Factory for generating a ReportQueueConfiguration.
// `event_type` is the type of event being reported, and is indirectly used to
// retrieve DM tokens for downstream processing when building the report
// queue. Using `EventType::kDevice` will skip DM token retrieval, so please
// use `EventType::kUser` for events that need to be associated with the
// current user. If any of the parameters are invalid, will return
// error::INVALID_ARGUMENT. `destination` is valid when it is any value other
// than Destination::UNDEFINED_DESTINATION.
// `reserved_space` is optional. If it is > 0, respective ReportQueue will be
// "opportunistic" - underlying Storage would only accept an enqueue request
// if after adding the new record remaining amount of disk space will not drop
// below `reserved_space`.
static StatusOr<std::unique_ptr<ReportQueueConfiguration>> Create(
EventType event_type,
Destination destination,
PolicyCheckCallback policy_check_callback,
std::unique_ptr<RateLimiterInterface> rate_limiter = nullptr,
int64_t reserved_space = 0L);
Destination destination() const { return destination_; }
std::string dm_token() { return dm_token_; }
EventType event_type() const { return event_type_; }
// Returns a repeating callback that checks whether an event of the given size
// is allowed by the attached rate limiter. If there is no rate limiter,
// allowed always.
WrappedRateLimiter::AsyncAcquireCb is_event_allowed_cb() const {
return is_event_allowed_cb_;
}
int64_t reserved_space() const { return reserved_space_; }
std::optional<SourceInfo> source_info() const { return source_info_; }
Status SetDMToken(std::string_view dm_token);
Status CheckPolicy() const;
private:
friend class Builder;
ReportQueueConfiguration();
Status SetEventType(EventType event_type);
Status SetDestination(Destination destination);
Status SetReservedSpace(int64_t reserved_space);
Status SetPolicyCheckCallback(PolicyCheckCallback policy_check_callback);
Status SetRateLimiter(std::unique_ptr<RateLimiterInterface> rate_limiter);
Status SetSourceInfo(std::optional<SourceInfo> source_info);
std::string dm_token_;
EventType event_type_;
Destination destination_;
PolicyCheckCallback policy_check_callback_;
WrappedRateLimiter::SmartPtr wrapped_rate_limiter_{
nullptr, base::OnTaskRunnerDeleter(nullptr)};
WrappedRateLimiter::AsyncAcquireCb is_event_allowed_cb_;
int64_t reserved_space_ = 0L; // By default queues are not opportunistic.
std::optional<SourceInfo> source_info_ = std::nullopt;
};
} // namespace reporting
#endif // COMPONENTS_REPORTING_CLIENT_REPORT_QUEUE_CONFIGURATION_H_