blob: 78dd57f52826ca720f5a99ef55133be704327b17 [file] [log] [blame] [edit]
// Copyright 2024 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "missive/util/server_configuration_controller.h"
#include <base/check.h>
#include <base/functional/bind.h>
#include <base/logging.h>
#include <base/memory/scoped_refptr.h>
#include <base/sequence_checker.h>
#include <base/strings/strcat.h>
#include <base/task/thread_pool.h>
#include <base/thread_annotations.h>
#include "missive/analytics/metrics.h"
namespace reporting {
ServerConfigurationController::BlockedDestinations::BlockedDestinations() {
// When creating the object populate all the destinations to be non-blocked.
ClearDestinations();
}
void ServerConfigurationController::BlockedDestinations::ClearDestinations() {
for (int destination = 0; destination < Destination_ARRAYSIZE;
++destination) {
blocked_destinations_[destination].store(false);
}
}
bool ServerConfigurationController::BlockedDestinations::get(
Destination destination) const {
CHECK_LT(destination, Destination_ARRAYSIZE);
return blocked_destinations_[destination].load();
}
void ServerConfigurationController::BlockedDestinations::blocked(
Destination destination, bool blocked) {
CHECK_LT(destination, Destination_ARRAYSIZE);
const bool was_blocked = blocked_destinations_[destination].exchange(blocked);
LOG_IF(WARNING, was_blocked != blocked)
<< "Destination " << Destination_Name(destination) << " switched to "
<< (blocked ? "blocked" : "unblocked");
}
// static
scoped_refptr<ServerConfigurationController>
ServerConfigurationController::Create(bool is_enabled_) {
return base::WrapRefCounted(new ServerConfigurationController(is_enabled_));
}
ServerConfigurationController::ServerConfigurationController(bool is_enabled)
: DynamicFlag("blocking_destinations_enabled", is_enabled) {}
ServerConfigurationController::~ServerConfigurationController() = default;
void ServerConfigurationController::UpdateConfiguration(
ListOfBlockedDestinations destinations, HealthModule::Recorder recorder) {
// Clear the destination list. The browser code already checks if the lists
// are equal so there is no need to do that here.
blocked_destinations_.ClearDestinations();
// Update the list stored locally and emit a new health module record if
// enabled.
for (const auto destination : destinations.destinations()) {
CHECK(Destination_IsValid(destination));
auto current_destination = Destination(destination);
if (recorder) {
auto* const blocked_destination_list_record =
recorder->mutable_blocked_destinations_updated_call();
blocked_destination_list_record->add_destinations(current_destination);
}
blocked_destinations_.blocked(current_destination, true);
}
}
bool ServerConfigurationController::IsDestinationBlocked(
Destination destination) {
// If the flag is not enabled then we don't block any records.
if (!is_enabled()) {
return false;
}
// Check if the destination has been blocked by the configuration file. If it
// hasn't we just return false, if it has been blocked then we update the UMA
// counter and generate a health module record if enabled.
if (!blocked_destinations_.get(destination)) {
return false;
}
// If the destination is blocked we want to log that we blocked a record
// to our UMA metrics.
analytics::Metrics::SendEnumToUMA(
/*name=*/kConfigFileRecordBlocked, destination, Destination_ARRAYSIZE);
return true;
}
} // namespace reporting