blob: 57438d2dcaf533683c2c90dbd50453db16a745ae [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/ukm_data_manager_impl.h"
#include "base/check_is_test.h"
#include "base/check_op.h"
#include "base/task/sequenced_task_runner.h"
#include "components/segmentation_platform/internal/database/ukm_database_impl.h"
#include "components/segmentation_platform/internal/signals/ukm_config.h"
#include "components/segmentation_platform/internal/signals/ukm_observer.h"
#include "components/segmentation_platform/internal/signals/url_signal_handler.h"
namespace segmentation_platform {
namespace {
// Delay for running clean up task from startup.
const base::TimeDelta kDatabaseCleanupDelayStartup = base::Minutes(2);
// Periodic interval between two cleanup tasks.
const base::TimeDelta kDatabaseCleanupDelayNormal = base::Days(1);
// Number of days to keep UKM metrics in database.
constexpr base::TimeDelta kUkmEntriesTTL = base::Days(30);
} // namespace
UkmDataManagerImpl::UkmDataManagerImpl() = default;
UkmDataManagerImpl::~UkmDataManagerImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
DCHECK_EQ(ref_count_, 0);
if (ukm_observer_) {
ukm_observer_->set_ukm_data_manager(nullptr);
}
url_signal_handler_.reset();
ukm_database_.reset();
}
void UkmDataManagerImpl::InitializeForTesting(
std::unique_ptr<UkmDatabase> ukm_database,
UkmObserver* ukm_observer) {
InitiailizeImpl(std::move(ukm_database));
StartObservation(ukm_observer);
}
void UkmDataManagerImpl::Initialize(const base::FilePath& database_path,
bool in_memory) {
InitiailizeImpl(std::make_unique<UkmDatabaseImpl>(database_path, in_memory));
}
void UkmDataManagerImpl::StartObservation(UkmObserver* ukm_observer) {
ukm_observer_ = ukm_observer;
ukm_observer_->set_ukm_data_manager(this);
}
void UkmDataManagerImpl::InitiailizeImpl(
std::unique_ptr<UkmDatabase> ukm_database) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
DCHECK(!ukm_database_);
DCHECK(!ukm_observer_);
ukm_database_ = std::move(ukm_database);
// TODO(ssid): Move this call to constructor to make it clear any transaction
// is posted after initialization.
ukm_database_->InitDatabase(base::DoNothing());
GetOrCreateUrlHandler();
base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&UkmDataManagerImpl::RunCleanupTask,
weak_factory_.GetWeakPtr()),
kDatabaseCleanupDelayStartup);
}
bool UkmDataManagerImpl::IsUkmEngineEnabled() {
// DummyUkmDataManager is created when UKM engine is disabled.
return true;
}
UrlSignalHandler* UkmDataManagerImpl::GetOrCreateUrlHandler() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
DCHECK(ukm_database_);
if (!url_signal_handler_) {
url_signal_handler_ =
std::make_unique<UrlSignalHandler>(ukm_database_.get());
}
return url_signal_handler_.get();
}
void UkmDataManagerImpl::StartObservingUkm(const UkmConfig& ukm_config) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
// TODO(b/290821132): Remove this check.
if (!ukm_observer_) {
CHECK_IS_TEST();
return;
}
ukm_observer_->StartObserving(ukm_config);
}
void UkmDataManagerImpl::PauseOrResumeObservation(bool pause) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
// TODO(b/290821132): Remove this check.
if (!ukm_observer_) {
// On iOS the eg tests do not set this flag.
#if !BUILDFLAG(IS_IOS)
CHECK_IS_TEST();
#endif
return;
}
ukm_observer_->PauseOrResumeObservation(pause);
}
UkmDatabase* UkmDataManagerImpl::GetUkmDatabase() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
DCHECK(ukm_database_);
return ukm_database_.get();
}
bool UkmDataManagerImpl::HasUkmDatabase() {
return ukm_database_ ? true : false;
}
void UkmDataManagerImpl::OnEntryAdded(ukm::mojom::UkmEntryPtr entry) {
ukm_database_->StoreUkmEntry(std::move(entry));
}
void UkmDataManagerImpl::OnUkmSourceUpdated(ukm::SourceId source_id,
const std::vector<GURL>& urls) {
if (url_signal_handler_)
url_signal_handler_->OnUkmSourceUpdated(source_id, urls);
}
void UkmDataManagerImpl::AddRef() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
ref_count_++;
}
void UkmDataManagerImpl::RemoveRef() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_);
DCHECK_GT(ref_count_, 0);
ref_count_--;
}
void UkmDataManagerImpl::RunCleanupTask() {
DCHECK(ukm_database_);
ukm_database_->DeleteEntriesOlderThan(base::Time::Now() - kUkmEntriesTTL);
// Consider waiting for the above task to finish successfully before posting
// the next one.
base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
FROM_HERE,
base::BindOnce(&UkmDataManagerImpl::RunCleanupTask,
weak_factory_.GetWeakPtr()),
kDatabaseCleanupDelayNormal);
}
} // namespace segmentation_platform