blob: 8353c9b518f2d1e02b411bacc4a0f9eef646bcb4 [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.
#include "components/reporting/client/report_queue_configuration.h"
#include <string>
#include <utility>
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/types/expected.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/status_macros.h"
#include "components/reporting/util/statusor.h"
#include "components/reporting/util/wrapped_rate_limiter.h"
namespace reporting {
ReportQueueConfiguration::Builder::Builder(
const ReportQueueConfiguration::Settings& settings)
: final_value_(base::WrapUnique<ReportQueueConfiguration>(
new ReportQueueConfiguration())) {
if (auto status = final_value_.value()->SetEventType(settings.event_type);
!status.ok()) {
final_value_ = base::unexpected(std::move(status));
return;
}
if (auto status = final_value_.value()->SetDestination(settings.destination);
!status.ok()) {
final_value_ = base::unexpected(std::move(status));
return;
}
if (settings.reserved_space != 0L) {
if (auto status =
final_value_.value()->SetReservedSpace(settings.reserved_space);
!status.ok()) {
final_value_ = base::unexpected(std::move(status));
return;
}
}
}
ReportQueueConfiguration::Builder::Builder(
ReportQueueConfiguration::Builder&& other) = default;
ReportQueueConfiguration::Builder::~Builder() = default;
ReportQueueConfiguration::Builder
ReportQueueConfiguration::Builder::SetPolicyCheckCallback(
ReportQueueConfiguration::PolicyCheckCallback policy_check_callback) {
if (final_value_.has_value()) {
auto status =
final_value_.value()->SetPolicyCheckCallback(policy_check_callback);
if (!status.ok()) {
final_value_ = base::unexpected(std::move(status));
}
}
return std::move(*this);
}
ReportQueueConfiguration::Builder
ReportQueueConfiguration::Builder::SetRateLimiter(
std::unique_ptr<RateLimiterInterface> rate_limiter) {
if (final_value_.has_value()) {
auto status = final_value_.value()->SetRateLimiter(std::move(rate_limiter));
if (!status.ok()) {
final_value_ = base::unexpected(std::move(status));
}
}
return std::move(*this);
}
ReportQueueConfiguration::Builder ReportQueueConfiguration::Builder::SetDMToken(
std::string_view dm_token) {
if (final_value_.has_value()) {
auto status = final_value_.value()->SetDMToken(dm_token);
if (!status.ok()) {
final_value_ = base::unexpected(std::move(status));
}
}
return std::move(*this);
}
ReportQueueConfiguration::Builder
ReportQueueConfiguration::Builder::SetSourceInfo(
std::optional<SourceInfo> source_info) {
if (final_value_.has_value()) {
auto status = final_value_.value()->SetSourceInfo(std::move(source_info));
if (!status.ok()) {
final_value_ = base::unexpected(std::move(status));
}
}
return std::move(*this);
}
StatusOr<std::unique_ptr<ReportQueueConfiguration>>
ReportQueueConfiguration::Builder::Build() {
auto result = std::move(final_value_);
final_value_ = base::unexpected(
Status(error::ALREADY_EXISTS, "Configuration has already been returned"));
return result;
}
ReportQueueConfiguration::ReportQueueConfiguration() = default;
ReportQueueConfiguration::~ReportQueueConfiguration() = default;
// Factory for generating a ReportQueueConfiguration.
ReportQueueConfiguration::Builder ReportQueueConfiguration::Create(
const ReportQueueConfiguration::Settings& settings) {
return Builder(settings);
}
// static
StatusOr<std::unique_ptr<ReportQueueConfiguration>>
ReportQueueConfiguration::Create(
std::string_view dm_token,
Destination destination,
PolicyCheckCallback policy_check_callback,
std::unique_ptr<RateLimiterInterface> rate_limiter,
int64_t reserved_space) {
return ReportQueueConfiguration::Create({.event_type = EventType::kDevice,
.destination = destination,
.reserved_space = reserved_space})
.SetPolicyCheckCallback(policy_check_callback)
.SetRateLimiter(std::move(rate_limiter))
.SetDMToken(dm_token)
.Build();
}
Status ReportQueueConfiguration::SetPolicyCheckCallback(
PolicyCheckCallback policy_check_callback) {
if (!policy_check_callback_.is_null()) {
return Status(error::ALREADY_EXISTS, "PolicyCheckCallback cannot be reset");
}
if (policy_check_callback.is_null()) {
return Status(error::INVALID_ARGUMENT,
"PolicyCheckCallback must not be null");
}
policy_check_callback_ = std::move(policy_check_callback);
return Status::StatusOK();
}
Status ReportQueueConfiguration::SetEventType(EventType event_type) {
event_type_ = event_type;
return Status::StatusOK();
}
Status ReportQueueConfiguration::CheckPolicy() const {
if (policy_check_callback_.is_null()) {
return Status::StatusOK();
}
return policy_check_callback_.Run();
}
Status ReportQueueConfiguration::SetDMToken(std::string_view dm_token) {
dm_token_ = std::string(dm_token);
return Status::StatusOK();
}
Status ReportQueueConfiguration::SetDestination(Destination destination) {
if (destination == Destination::UNDEFINED_DESTINATION) {
return Status(error::INVALID_ARGUMENT, "Destination must be defined");
}
destination_ = destination;
return Status::StatusOK();
}
Status ReportQueueConfiguration::SetRateLimiter(
std::unique_ptr<RateLimiterInterface> rate_limiter) {
if (wrapped_rate_limiter_) {
return Status(error::ALREADY_EXISTS, "RateLimiter cannot be reset");
}
if (rate_limiter) {
wrapped_rate_limiter_ = WrappedRateLimiter::Create(std::move(rate_limiter));
is_event_allowed_cb_ = wrapped_rate_limiter_->async_acquire_cb();
}
return Status::StatusOK();
}
Status ReportQueueConfiguration::SetReservedSpace(int64_t reserved_space) {
if (reserved_space < 0L) {
return Status(error::INVALID_ARGUMENT,
"Must reserve non-zero amount of space");
}
reserved_space_ = reserved_space;
return Status::StatusOK();
}
Status ReportQueueConfiguration::SetSourceInfo(
std::optional<SourceInfo> source_info) {
if (source_info_.has_value()) {
return Status(error::ALREADY_EXISTS, "SourceInfo cannot be reset");
}
if (!source_info.has_value()) {
// No source info specified. Also the default.
source_info_ = std::nullopt;
return Status::StatusOK();
}
// Validate if the specified source info has a source set and a valid one if
// there is a version associated with it.
const auto& source_info_value = source_info.value();
if (!source_info_value.has_source() ||
(source_info_value.source() == SourceInfo::SOURCE_UNSPECIFIED &&
source_info_value.has_source_version())) {
return Status(error::INVALID_ARGUMENT, "Must specify valid source");
}
source_info_ = std::move(source_info);
return Status::StatusOK();
}
} // namespace reporting