| // 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); | |
| 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_ |