blob: d01d511e07a925fa5faeb63cbad5b209af31276b [file] [log] [blame]
// 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