blob: 1fecee48fdb2591901b8eaed0ab9922702474d5c [file] [log] [blame]
// Copyright 2022 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/segmentation_platform/internal/signals/ukm_observer.h"
#include <cstdint>
#include "components/segmentation_platform/internal/constants.h"
#include "components/segmentation_platform/internal/signals/ukm_config.h"
#include "components/segmentation_platform/internal/ukm_data_manager_impl.h"
#include "components/segmentation_platform/public/local_state_helper.h"
#include "components/ukm/ukm_recorder_impl.h"
#include "services/metrics/public/mojom/ukm_interface.mojom.h"
namespace segmentation_platform {
UkmObserver::UkmObserver(ukm::UkmRecorderImpl* ukm_recorder)
: ukm_recorder_(ukm_recorder), ukm_data_manager_(nullptr) {
// Listen to |OnUkmAllowedStateChanged| event.
ukm_recorder_->AddUkmRecorderObserver(base::flat_set<uint64_t>(), this);
}
UkmObserver::~UkmObserver() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
StopObserving();
}
void UkmObserver::StartObserving(const UkmConfig& config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
if (!config_) {
config_ = std::make_unique<UkmConfig>();
}
UkmConfig::MergeResult result = config_->Merge(config);
if (result == UkmConfig::NO_NEW_EVENT)
return;
ukm_recorder_->RemoveUkmRecorderObserver(this);
ukm_recorder_->AddUkmRecorderObserver(config_->GetRawObservedEvents(), this);
}
void UkmObserver::StopObserving() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
ukm_recorder_->RemoveUkmRecorderObserver(this);
}
void UkmObserver::OnEntryAdded(ukm::mojom::UkmEntryPtr entry) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
if (paused_ || !ukm_data_manager_)
return;
// Remove any metric from the entry that is not observed.
const base::flat_set<UkmMetricHash>* metrics_for_event =
config_->GetObservedMetrics(
UkmEventHash::FromUnsafeValue(entry->event_hash));
if (!metrics_for_event)
return;
base::EraseIf(entry->metrics, [&metrics_for_event](const auto& it) {
return !metrics_for_event->count(UkmMetricHash::FromUnsafeValue(it.first));
});
ukm_data_manager_->OnEntryAdded(std::move(entry));
}
void UkmObserver::OnUpdateSourceURL(ukm::SourceId source_id,
const std::vector<GURL>& urls) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
if (paused_ || !ukm_data_manager_)
return;
ukm_data_manager_->OnUkmSourceUpdated(source_id, urls);
}
void UkmObserver::PauseOrResumeObservation(bool pause) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
paused_ = pause;
}
void UkmObserver::OnUkmAllowedStateChanged(ukm::UkmConsentState state) {
InitalizeUkmAllowedState(state.Has(ukm::MSBB));
}
void UkmObserver::InitalizeUkmAllowedState(bool is_msbb_enabled) {
base::Time most_recent_allowed = LocalStateHelper::GetInstance().GetPrefTime(
kSegmentationUkmMostRecentAllowedTimeKey);
if (!is_msbb_enabled) {
if (most_recent_allowed != base::Time::Max()) {
LocalStateHelper::GetInstance().SetPrefTime(
kSegmentationUkmMostRecentAllowedTimeKey, base::Time::Max());
}
return;
}
// Update the most recent allowed time if needed.
if (most_recent_allowed.is_null() ||
most_recent_allowed == base::Time::Max()) {
LocalStateHelper::GetInstance().SetPrefTime(
kSegmentationUkmMostRecentAllowedTimeKey, base::Time::Now());
}
}
} // namespace segmentation_platform