chromium/chrome/browser/lacros/metrics_reporting_observer.cc

// Copyright 2020 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/lacros/metrics_reporting_observer.h"

#include "base/check.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/metrics/metrics_reporting_state.h"
#include "chromeos/lacros/lacros_service.h"
#include "chromeos/startup/browser_params_proxy.h"
#include "components/metrics/metrics_pref_names.h"
#include "components/metrics/metrics_service.h"
#include "components/metrics/metrics_state_manager.h"

namespace {

// Called within Lacros after startup to delay the metrics enablement change as
// turning off the metric might be a fluke, but disabling would cause the
// entropy value to change, which will result in a metrics package loss.
void ChangeMetricsReportingStateOnLacrosStart() {
  // We should not call the function |ChangeMetricsReportingState| if nothing
  // has changed.
  const bool new_enabled =
      chromeos::BrowserParamsProxy::Get()->AshMetricsEnabled();
  const bool old_enabled = g_browser_process->local_state()->GetBoolean(
      metrics::prefs::kMetricsReportingEnabled);

  if (new_enabled == old_enabled) {
    return;
  }

  ChangeMetricsReportingState(
      new_enabled,
      ChangeMetricsReportingStateCalledFrom::kCrosMetricsInitializedFromAsh);
}

}  // namespace

class MetricsServiceProxyImpl
    : public MetricsReportingObserver::MetricsServiceProxy {
 public:
  explicit MetricsServiceProxyImpl(metrics::MetricsService* metrics_service)
      : metrics_service_(metrics_service) {}

  MetricsServiceProxyImpl(const MetricsServiceProxyImpl&) = delete;
  MetricsServiceProxyImpl& operator=(const MetricsReportingObserver&) = delete;

  ~MetricsServiceProxyImpl() override = default;

  void SetReportingEnabled(bool enabled) override {
    ChangeMetricsReportingState(enabled);
  }

  void SetExternalClientId(const std::string& client_id) override {
    metrics_service_->SetExternalClientId(client_id);
  }

  void RecreateClientIdIfNecessary() override {
    if (metrics_service_->IsMetricsReportingEnabled())
      metrics_service_->ResetClientId();
  }

 private:
  raw_ptr<metrics::MetricsService> metrics_service_;
};

std::unique_ptr<MetricsReportingObserver>
MetricsReportingObserver::CreateObserver(
    metrics::MetricsService* metrics_service) {
  return std::make_unique<MetricsReportingObserver>(
      std::make_unique<MetricsServiceProxyImpl>(metrics_service));
}

MetricsReportingObserver::MetricsReportingObserver(
    std::unique_ptr<MetricsServiceProxy> metrics_service)
    : metrics_service_(std::move(metrics_service)) {
  DCHECK(metrics_service_);
  auto* lacros_service = chromeos::LacrosService::Get();

  if (lacros_service->IsSupported<crosapi::mojom::MetricsReporting>()) {
    lacros_service->BindMetricsReporting(
        metrics_reporting_remote_.BindNewPipeAndPassReceiver());
    metrics_reporting_remote_->AddObserver(
        receiver_.BindNewPipeAndPassRemoteWithVersion());
  }
}

MetricsReportingObserver::~MetricsReportingObserver() = default;

void MetricsReportingObserver::InitSettingsFromAsh() {
  auto* lacros_service = chromeos::LacrosService::Get();
  if (!lacros_service->IsSupported<crosapi::mojom::MetricsReporting>()) {
    LOG(WARNING) << "MetricsReporting API not available";
    return;
  }

  ChangeMetricsReportingStateOnLacrosStart();
}

void MetricsReportingObserver::OnMetricsReportingChanged(
    bool enabled,
    const std::optional<std::string>& client_id) {
  if (enabled) {
    if (client_id) {
      metrics_service_->SetExternalClientId(client_id.value());
    } else {
      LOG(WARNING) << "UMA client id should have been provided, but wasn't. "
                      "A random id will be used.";
    }
  }
  metrics_service_->SetReportingEnabled(enabled);
  if (enabled) {
    metrics_service_->RecreateClientIdIfNecessary();
  }
}