| // 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 |