| // 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_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); |
| |
| url_signal_handler_.reset(); |
| ukm_database_.reset(); |
| } |
| |
| void UkmDataManagerImpl::InitializeForTesting( |
| std::unique_ptr<UkmDatabase> ukm_database, |
| UkmObserver* ukm_observer) { |
| InitiailizeImpl(std::move(ukm_database), ukm_observer); |
| } |
| |
| void UkmDataManagerImpl::Initialize(const base::FilePath& database_path, |
| UkmObserver* ukm_observer) { |
| InitiailizeImpl(std::make_unique<UkmDatabaseImpl>(database_path), |
| ukm_observer); |
| } |
| |
| void UkmDataManagerImpl::InitiailizeImpl( |
| std::unique_ptr<UkmDatabase> ukm_database, |
| UkmObserver* ukm_observer) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_); |
| DCHECK(!ukm_database_); |
| DCHECK(!ukm_observer_); |
| |
| ukm_observer_ = ukm_observer; |
| ukm_observer_->set_ukm_data_manager(this); |
| |
| 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_); |
| ukm_observer_->StartObserving(ukm_config); |
| } |
| |
| void UkmDataManagerImpl::PauseOrResumeObservation(bool pause) { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_); |
| ukm_observer_->PauseOrResumeObservation(pause); |
| } |
| |
| UkmDatabase* UkmDataManagerImpl::GetUkmDatabase() { |
| DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_check_); |
| DCHECK(ukm_database_); |
| return ukm_database_.get(); |
| } |
| |
| 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 |