| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/cobalt/bin/app/user_consent_watcher.h" |
| |
| #include <lib/fpromise/result.h> |
| #include <lib/syslog/cpp/macros.h> |
| #include <zircon/types.h> |
| |
| #include <optional> |
| |
| #include <src/lib/fostr/fidl/fuchsia/settings/formatting.h> |
| |
| #include "lib/async/cpp/task.h" |
| |
| namespace cobalt { |
| |
| UserConsentWatcher::UserConsentWatcher( |
| async_dispatcher_t *dispatcher, inspect::Node inspect_node, |
| std::shared_ptr<sys::ServiceDirectory> services, |
| std::function<void(const CobaltServiceInterface::DataCollectionPolicy &)> callback) |
| : dispatcher_(dispatcher), |
| inspect_node_(std::move(inspect_node)), |
| services_(services), |
| callback_(callback), |
| backoff_(/*initial_delay=*/zx::msec(100), /*retry_factor=*/2u, /*max_delay=*/zx::hour(1)) { |
| watch_successes_ = inspect_node_.CreateInt("successful_watches", 0); |
| watch_errors_ = inspect_node_.CreateInt("watch_errors", 0); |
| } |
| |
| void UserConsentWatcher::StartWatching() { |
| privacy_settings_ptr_ = services_->Connect<fuchsia::settings::Privacy>(); |
| privacy_settings_ptr_.set_error_handler([this](zx_status_t status) { |
| watch_errors_.Add(1); |
| FX_PLOGS(ERROR, status) << "Lost connection to fuchsia.settings.Privacy"; |
| RestartWatching(); |
| }); |
| |
| Watch(); |
| } |
| |
| void UserConsentWatcher::RestartWatching() { |
| ResetConsent(); |
| privacy_settings_ptr_.Unbind(); |
| |
| reconnect_task_.Reset([this] { StartWatching(); }); |
| async::PostDelayedTask( |
| dispatcher_, [reconnect = reconnect_task_.callback()] { reconnect(); }, backoff_.GetNext()); |
| } |
| |
| void UserConsentWatcher::Watch() { |
| privacy_settings_ptr_->Watch([this](fuchsia::settings::PrivacySettings settings) { |
| // Reset the exponential backoff since we successfully watched once. |
| backoff_.Reset(); |
| |
| watch_successes_.Add(1); |
| privacy_settings_ = std::move(settings); |
| Update(); |
| |
| // We watch for the next update, following the hanging get pattern. |
| Watch(); |
| }); |
| } |
| |
| void UserConsentWatcher::ResetConsent() { |
| privacy_settings_.clear_user_data_sharing_consent(); |
| Update(); |
| } |
| |
| CobaltServiceInterface::DataCollectionPolicy UserConsentWatcher::GetDataCollectionPolicy() { |
| if (!privacy_settings_.has_user_data_sharing_consent()) { |
| return CobaltServiceInterface::DataCollectionPolicy::DO_NOT_UPLOAD; |
| } |
| if (privacy_settings_.user_data_sharing_consent()) { |
| return CobaltServiceInterface::DataCollectionPolicy::COLLECT_AND_UPLOAD; |
| } |
| return CobaltServiceInterface::DataCollectionPolicy::DO_NOT_COLLECT; |
| } |
| |
| void UserConsentWatcher::Update() { |
| CobaltServiceInterface::DataCollectionPolicy policy = GetDataCollectionPolicy(); |
| current_policy_ = inspect_node_.CreateInt("data_collection_policy", static_cast<int>(policy)); |
| callback_(policy); |
| } |
| |
| } // namespace cobalt |