File: ukm_database_client.cc

package info (click to toggle)
chromium 138.0.7204.157-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,864 kB
  • sloc: cpp: 34,936,859; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,967; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (135 lines) | stat: -rw-r--r-- 4,514 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// 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 "chrome/browser/segmentation_platform/ukm_database_client.h"

#include "base/check_is_test.h"
#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/synchronization/lock.h"
#include "chrome/browser/browser_process.h"
#include "chrome/common/chrome_paths.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/segmentation_platform/internal/dummy_ukm_data_manager.h"
#include "components/segmentation_platform/internal/signals/ukm_observer.h"
#include "components/segmentation_platform/internal/ukm_data_manager_impl.h"
#include "components/segmentation_platform/public/features.h"
#include "components/ukm/ukm_service.h"

namespace segmentation_platform {

UkmDatabaseClient::UkmDatabaseClient() {
  if (base::FeatureList::IsEnabled(
          segmentation_platform::features::kSegmentationPlatformUkmEngine)) {
    ukm_data_manager_ = std::make_unique<UkmDataManagerImpl>();
  } else {
    ukm_data_manager_ = std::make_unique<DummyUkmDataManager>();
  }
}

UkmDatabaseClient::~UkmDatabaseClient() = default;

segmentation_platform::UkmDataManager* UkmDatabaseClient::GetUkmDataManager() {
  CHECK(ukm_data_manager_);
  return ukm_data_manager_.get();
}

void UkmDatabaseClient::PreProfileInit(bool in_memory_database) {
  // Skip if already initialized. This method is called multiple times to ensure
  // the client is initialized in tests.
  if (initialized_) {
    return;
  }
  initialized_ = true;

  if (ukm_recorder_for_testing_) {
    ukm_observer_ = std::make_unique<UkmObserver>(ukm_recorder_for_testing_);
  } else if (g_browser_process->GetMetricsServicesManager()) {
    // GetMetricsServicesManager() can be null only in unit tests.
    ukm_observer_ = std::make_unique<UkmObserver>(
        g_browser_process->GetMetricsServicesManager()->GetUkmService());
  } else {
    CHECK_IS_TEST();
  }

  // Path service is setup at early startup.
  base::FilePath local_data_dir;
  bool result = base::PathService::Get(chrome::DIR_USER_DATA, &local_data_dir);
  DCHECK(result);
  ukm_data_manager_->Initialize(
      local_data_dir.Append(FILE_PATH_LITERAL("segmentation_platform/ukm_db")),
      in_memory_database);
  if (ukm_observer_) {
    ukm_data_manager_->StartObservation(ukm_observer_.get());
  } else {
    CHECK_IS_TEST();
  }
}

void UkmDatabaseClient::TearDownForTesting() {
  ukm_data_manager_.reset();
  ukm_observer_.reset();
  ukm_recorder_for_testing_ = nullptr;
}

void UkmDatabaseClient::PostMessageLoopRun() {
  // UkmService is destroyed in BrowserProcessImpl::TearDown(), which happens
  // after all the extra main parts get PostMainMessageLoopRun(). So, it is safe
  // to stop the observer here. The profiles can still be active and
  // UkmDataManager needs to be available. This does not tear down the
  // UkmDataManager, but only stops observing UKM.
  if (ukm_observer_) {
    // Some of the content browser implementations do not invoke
    // PreProfileInit().
    ukm_observer_->StopObserving();
  }
}

// static
UkmDatabaseClientHolder& UkmDatabaseClientHolder::GetInstance() {
  static base::NoDestructor<UkmDatabaseClientHolder> instance;
  return *instance;
}

// static
UkmDatabaseClient& UkmDatabaseClientHolder::GetClientInstance(
    Profile* profile) {
  UkmDatabaseClientHolder& instance = GetInstance();
  base::AutoLock l(instance.lock_);
  if (!instance.clients_for_testing_.empty()) {
    CHECK_IS_TEST();
    CHECK(profile);
    CHECK(instance.clients_for_testing_.count(profile));
    return *instance.clients_for_testing_[profile];
  }
  return *instance.main_client_;
}

// static
void UkmDatabaseClientHolder::SetUkmClientForTesting(
    Profile* profile,
    UkmDatabaseClient* client) {
  UkmDatabaseClientHolder& instance = GetInstance();
  instance.SetUkmClientForTestingInternal(profile, client);
}

UkmDatabaseClientHolder::UkmDatabaseClientHolder()
    : main_client_(std::make_unique<UkmDatabaseClient>()) {}

UkmDatabaseClientHolder::~UkmDatabaseClientHolder() = default;

void UkmDatabaseClientHolder::SetUkmClientForTestingInternal(
    Profile* profile,
    UkmDatabaseClient* client) {
  base::AutoLock l(lock_);
  CHECK(profile);
  if (client) {
    clients_for_testing_[profile] = client;
  } else {
    clients_for_testing_.erase(profile);
  }
}

}  // namespace segmentation_platform