chromium/chrome/browser/ash/policy/reporting/user_event_reporter_helper.cc

// Copyright 2021 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/ash/policy/reporting/user_event_reporter_helper.h"

#include <utility>

#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "base/task/sequenced_task_runner.h"
#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
#include "chrome/browser/ash/policy/core/device_cloud_policy_manager_ash.h"
#include "chrome/browser/ash/policy/core/reporting_user_tracker.h"
#include "chrome/browser/ash/settings/device_settings_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part_ash.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "components/reporting/client/report_queue_factory.h"
#include "components/reporting/proto/synced/record.pb.h"
#include "components/reporting/util/reporting_errors.h"
#include "components/reporting/util/status.h"
#include "components/user_manager/user_manager.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/sha2.h"
#include "third_party/protobuf/src/google/protobuf/message_lite.h"

namespace reporting {

UserEventReporterHelper::UserEventReporterHelper(Destination destination,
                                                 EventType event_type)
    : report_queue_(ReportQueueFactory::CreateSpeculativeReportQueue(
          [](Destination destination, EventType event_type) {
            SourceInfo source_info;
            source_info.set_source(SourceInfo::ASH);
            return ReportQueueConfiguration::Create(
                       {.event_type = event_type, .destination = destination})
                .SetSourceInfo(std::move(source_info));
          }(destination, event_type))) {}

UserEventReporterHelper::UserEventReporterHelper(
    std::unique_ptr<ReportQueue, base::OnTaskRunnerDeleter> report_queue)
    : report_queue_(std::move(report_queue)) {}

UserEventReporterHelper::~UserEventReporterHelper() = default;

bool UserEventReporterHelper::ShouldReportUser(const std::string& email) const {
  DCHECK_CURRENTLY_ON(::content::BrowserThread::UI);
  auto* reporting_user_tracker = g_browser_process->platform_part()
                                     ->browser_policy_connector_ash()
                                     ->GetDeviceCloudPolicyManager()
                                     ->reporting_user_tracker();
  return reporting_user_tracker->ShouldReportUser(email);
}

bool UserEventReporterHelper::ReportingEnabled(
    const std::string& policy_path) const {
  DCHECK_CURRENTLY_ON(::content::BrowserThread::UI);
  bool enabled = false;
  ash::CrosSettings::Get()->GetBoolean(policy_path, &enabled);
  return enabled;
}

bool UserEventReporterHelper::IsKioskUser() const {
  DCHECK_CURRENTLY_ON(::content::BrowserThread::UI);
  auto* const primary = user_manager::UserManager::Get()->GetPrimaryUser();
  if (!primary) {
    return false;
  }
  return primary->IsKioskType();
}

void UserEventReporterHelper::ReportEvent(
    std::unique_ptr<const google::protobuf::MessageLite> record,
    Priority priority,
    ReportQueue::EnqueueCallback enqueue_cb) {
  if (!report_queue_) {
    std::move(enqueue_cb)
        .Run(Status(error::UNAVAILABLE, "Reporting queue is null."));
    base::UmaHistogramEnumeration(reporting::kUmaUnavailableErrorReason,
                                  UnavailableErrorReason::REPORT_QUEUE_IS_NULL,
                                  UnavailableErrorReason::MAX_VALUE);
    return;
  }
  report_queue_->Enqueue(std::move(record), priority, std::move(enqueue_cb));
}

bool UserEventReporterHelper::IsCurrentUserNew() const {
  return user_manager::UserManager::Get()->IsCurrentUserNew();
}

// static
scoped_refptr<base::SequencedTaskRunner>
UserEventReporterHelper::valid_task_runner() {
  return ::content::GetUIThreadTaskRunner({});
}

// static
void UserEventReporterHelper::OnEnqueueDefault(Status status) {
  if (!status.ok()) {
    DVLOG(1) << "Could not enqueue event to reporting queue because of: "
             << status;
  }
}

std::string UserEventReporterHelper::GetDeviceDmToken() const {
  const enterprise_management::PolicyData* const policy_data =
      ash::DeviceSettingsService::Get()->policy_data();
  if (policy_data && policy_data->has_request_token()) {
    return policy_data->request_token();
  }
  return std::string();
}

std::string UserEventReporterHelper::GetUniqueUserIdForThisDevice(
    std::string_view user_email) const {
  const std::string device_dm_token = GetDeviceDmToken();
  return device_dm_token.empty() ? device_dm_token
                                 : crypto::SHA256HashString(base::StrCat(
                                       {user_email, device_dm_token}));
}
}  // namespace reporting