chromium/chrome/browser/metrics/usertype_by_devicetype_metrics_provider.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/metrics/usertype_by_devicetype_metrics_provider.h"

#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/ash/login/demo_mode/demo_session.h"
#include "chrome/browser/ash/policy/core/browser_policy_connector_ash.h"
#include "chrome/browser/ash/policy/core/user_cloud_policy_manager_ash.h"
#include "chrome/browser/ash/profiles/profile_helper.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_process_platform_part.h"
#include "chrome/browser/policy/profile_policy_connector.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profiles_state.h"
#include "chromeos/components/kiosk/kiosk_utils.h"
#include "chromeos/components/mgs/managed_guest_session_utils.h"
#include "components/session_manager/core/session_manager.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"

namespace {

namespace em = enterprise_management;

constexpr char kHistogramName[] = "ChromeOS.UserTypeByDeviceType.LogSegment";
const int kMgsOnUnmanagedDevice =
    UserTypeByDeviceTypeMetricsProvider::ConstructUmaValue(
        UserTypeByDeviceTypeMetricsProvider::UserSegment::kManagedGuestSession,
        policy::MarketSegment::UNKNOWN);

}  // namespace

UserTypeByDeviceTypeMetricsProvider::UserTypeByDeviceTypeMetricsProvider() {
  session_manager::SessionManager* session_manager =
      session_manager::SessionManager::Get();
  // The |session_manager| is nullptr only for unit tests.
  if (session_manager)
    session_manager->AddObserver(this);
}

UserTypeByDeviceTypeMetricsProvider::~UserTypeByDeviceTypeMetricsProvider() {
  session_manager::SessionManager* session_manager =
      session_manager::SessionManager::Get();
  // The |session_manager| is nullptr only for unit tests.
  if (session_manager)
    session_manager->RemoveObserver(this);
}

bool UserTypeByDeviceTypeMetricsProvider::ProvideHistograms() {
  if (!user_segment_ || !device_segment_)
    return false;

  int uma_val =
      ConstructUmaValue(user_segment_.value(), device_segment_.value());

  if (uma_val == kMgsOnUnmanagedDevice) {
    LOG(WARNING) << "Can't have MGS on unmanaged device!";
    return false;
  }

  base::UmaHistogramSparse(kHistogramName, uma_val);
  return true;
}

void UserTypeByDeviceTypeMetricsProvider::OnUserSessionStarted(
    bool is_primary_user) {
  if (!is_primary_user)
    return;

  if (!device_segment_) {
    // Calculate the device enrollment type. Should never change during this
    // session, so should only need to do it once.
    policy::BrowserPolicyConnectorAsh* connector =
        g_browser_process->platform_part()->browser_policy_connector_ash();
    device_segment_ = connector->GetEnterpriseMarketSegment();
  }

  const user_manager::User* primary_user =
      user_manager::UserManager::Get()->GetPrimaryUser();
  DCHECK(primary_user);
  DCHECK(primary_user->is_profile_created());
  Profile* profile = ash::ProfileHelper::Get()->GetProfileByUser(primary_user);
  DCHECK(profile);

  user_segment_ = GetUserSegment(profile);
}

UserTypeByDeviceTypeMetricsProvider::UserSegment
UserTypeByDeviceTypeMetricsProvider::GetUserSegment(Profile* profile) {
  if (profiles::IsDemoSession()) {
    return UserSegment::kDemoMode;
  }

  if (chromeos::IsManagedGuestSession()) {
    return UserSegment::kManagedGuestSession;
  }

  if (chromeos::IsKioskSession()) {
    return UserSegment::kKioskApp;
  }

  if (profile->IsOffTheRecord()) {
    return UserSegment::kUnmanaged;
  }

  const policy::UserCloudPolicyManagerAsh* user_cloud_policy_manager =
      profile->GetUserCloudPolicyManagerAsh();
  if (!user_cloud_policy_manager)
    return UserSegment::kUnmanaged;
  const em::PolicyData* policy =
      user_cloud_policy_manager->core()->store()->policy();
  if (!policy || !policy->has_metrics_log_segment())
    return UserSegment::kUnmanaged;
  switch (policy->metrics_log_segment()) {
    case em::PolicyData::UNSPECIFIED:
      return UserSegment::kUnmanaged;
    case em::PolicyData::K12:
      return UserSegment::kK12;
    case em::PolicyData::UNIVERSITY:
      return UserSegment::kUniversity;
    case em::PolicyData::NONPROFIT:
      return UserSegment::kNonProfit;
    case em::PolicyData::ENTERPRISE:
      return UserSegment::kEnterprise;
  }
  NOTREACHED_IN_MIGRATION();
  return UserSegment::kUnmanaged;
}

// static
int UserTypeByDeviceTypeMetricsProvider::ConstructUmaValue(
    UserSegment user,
    policy::MarketSegment device) {
  int user_val = static_cast<int>(user);
  int device_val = static_cast<int>(device);
  DCHECK(user_val < 0x10000) << "user_val is too high! " << user_val;
  DCHECK(device_val < 0x10000) << "device_val is too high! " << device_val;
  return user_val | (device_val << 16);
}

// static
const char* UserTypeByDeviceTypeMetricsProvider::GetHistogramNameForTesting() {
  return kHistogramName;
}