// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/metrics/chromeos_metrics_provider.h"

#include <stddef.h>
#include <string>
#include <vector>

#include "base/barrier_closure.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/arc/arc_session_manager.h"
#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/pref_names.h"
#include "chromeos/system/statistics_provider.h"
#include "components/metrics/metrics_service.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "components/user_manager/user_manager.h"
#include "components/variations/service/variations_field_trial_creator.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "third_party/metrics_proto/chrome_user_metrics_extension.pb.h"
#include "ui/display/display.h"
#include "ui/events/event_utils.h"

using metrics::ChromeUserMetricsExtension;
using metrics::SampledProfile;
using metrics::SystemProfileProto;
typedef SystemProfileProto::Hardware::Bluetooth::PairedDevice PairedDevice;

namespace {

PairedDevice::Type AsBluetoothDeviceType(
    device::BluetoothDeviceType device_type) {
  switch (device_type) {
    case device::BluetoothDeviceType::UNKNOWN:
      return PairedDevice::DEVICE_UNKNOWN;
    case device::BluetoothDeviceType::COMPUTER:
      return PairedDevice::DEVICE_COMPUTER;
    case device::BluetoothDeviceType::PHONE:
      return PairedDevice::DEVICE_PHONE;
    case device::BluetoothDeviceType::MODEM:
      return PairedDevice::DEVICE_MODEM;
    case device::BluetoothDeviceType::AUDIO:
      return PairedDevice::DEVICE_AUDIO;
    case device::BluetoothDeviceType::CAR_AUDIO:
      return PairedDevice::DEVICE_CAR_AUDIO;
    case device::BluetoothDeviceType::VIDEO:
      return PairedDevice::DEVICE_VIDEO;
    case device::BluetoothDeviceType::PERIPHERAL:
      return PairedDevice::DEVICE_PERIPHERAL;
    case device::BluetoothDeviceType::JOYSTICK:
      return PairedDevice::DEVICE_JOYSTICK;
    case device::BluetoothDeviceType::GAMEPAD:
      return PairedDevice::DEVICE_GAMEPAD;
    case device::BluetoothDeviceType::KEYBOARD:
      return PairedDevice::DEVICE_KEYBOARD;
    case device::BluetoothDeviceType::MOUSE:
      return PairedDevice::DEVICE_MOUSE;
    case device::BluetoothDeviceType::TABLET:
      return PairedDevice::DEVICE_TABLET;
    case device::BluetoothDeviceType::KEYBOARD_MOUSE_COMBO:
      return PairedDevice::DEVICE_KEYBOARD_MOUSE_COMBO;
  }

  NOTREACHED();
  return PairedDevice::DEVICE_UNKNOWN;
}

void IncrementPrefValue(const char* path) {
  PrefService* pref = g_browser_process->local_state();
  DCHECK(pref);
  int value = pref->GetInteger(path);
  pref->SetInteger(path, value + 1);
}

// Called on a background thread to load hardware class information.
std::string GetFullHardwareClassOnBackgroundThread() {
  std::string full_hardware_class;
  chromeos::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
      "hardware_class", &full_hardware_class);
  return full_hardware_class;
}

}  // namespace

namespace features {

// Populates hardware class field in system_profile proto with the
// short hardware class if enabled. If disabled, hardware class will have same
// value as full hardware class.
const base::Feature kUmaShortHWClass{"UmaShortHWClass",
                                     base::FEATURE_ENABLED_BY_DEFAULT};

}  // namespace features

ChromeOSMetricsProvider::ChromeOSMetricsProvider()
    : registered_user_count_at_log_initialization_(false),
      user_count_at_log_initialization_(0),
      weak_ptr_factory_(this) {}

ChromeOSMetricsProvider::~ChromeOSMetricsProvider() {
}

// static
void ChromeOSMetricsProvider::RegisterPrefs(PrefRegistrySimple* registry) {
  registry->RegisterIntegerPref(prefs::kStabilityOtherUserCrashCount, 0);
  registry->RegisterIntegerPref(prefs::kStabilityKernelCrashCount, 0);
  registry->RegisterIntegerPref(prefs::kStabilitySystemUncleanShutdownCount, 0);
}

// static
void ChromeOSMetricsProvider::LogCrash(const std::string& crash_type) {
  if (crash_type == "user")
    IncrementPrefValue(prefs::kStabilityOtherUserCrashCount);
  else if (crash_type == "kernel")
    IncrementPrefValue(prefs::kStabilityKernelCrashCount);
  else if (crash_type == "uncleanshutdown")
    IncrementPrefValue(prefs::kStabilitySystemUncleanShutdownCount);
  else
    NOTREACHED() << "Unexpected Chrome OS crash type " << crash_type;

  // Wake up metrics logs sending if necessary now that new
  // log data is available.
  g_browser_process->metrics_service()->OnApplicationNotIdle();
}

ChromeOSMetricsProvider::EnrollmentStatus
ChromeOSMetricsProvider::GetEnrollmentStatus() {
  policy::BrowserPolicyConnectorChromeOS* connector =
      g_browser_process->platform_part()->browser_policy_connector_chromeos();
  if (!connector)
    return ERROR_GETTING_ENROLLMENT_STATUS;

  return connector->IsEnterpriseManaged() ? MANAGED : NON_MANAGED;
}

void ChromeOSMetricsProvider::Init() {
  if (base::FeatureList::IsEnabled(features::kUmaShortHWClass)) {
    hardware_class_ =
        variations::VariationsFieldTrialCreator::GetShortHardwareClass();
  }
  perf_provider_.Init();
}

void ChromeOSMetricsProvider::AsyncInit(const base::Closure& done_callback) {
  base::RepeatingClosure barrier = base::BarrierClosure(2, done_callback);
  InitTaskGetFullHardwareClass(barrier);
  InitTaskGetBluetoothAdapter(barrier);
}

void ChromeOSMetricsProvider::OnDidCreateMetricsLog() {
  registered_user_count_at_log_initialization_ = false;
  if (user_manager::UserManager::IsInitialized()) {
    registered_user_count_at_log_initialization_ = true;
    user_count_at_log_initialization_ =
        user_manager::UserManager::Get()->GetLoggedInUsers().size();
  }
}

void ChromeOSMetricsProvider::InitTaskGetFullHardwareClass(
    const base::Closure& callback) {
  // Run the (potentially expensive) task in the background to avoid blocking
  // the UI thread.
  base::PostTaskWithTraitsAndReplyWithResult(
      FROM_HERE,
      {base::MayBlock(), base::WithBaseSyncPrimitives(),
       base::TaskPriority::BEST_EFFORT,
       base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
      base::BindOnce(&GetFullHardwareClassOnBackgroundThread),
      base::BindOnce(&ChromeOSMetricsProvider::SetFullHardwareClass,
                     weak_ptr_factory_.GetWeakPtr(), callback));
}

void ChromeOSMetricsProvider::InitTaskGetBluetoothAdapter(
    const base::Closure& callback) {
  device::BluetoothAdapterFactory::GetAdapter(
      base::Bind(&ChromeOSMetricsProvider::SetBluetoothAdapter,
                 weak_ptr_factory_.GetWeakPtr(), callback));
}

void ChromeOSMetricsProvider::ProvideSystemProfileMetrics(
    metrics::SystemProfileProto* system_profile_proto) {
  WriteBluetoothProto(system_profile_proto);
  UpdateMultiProfileUserCount(system_profile_proto);

  metrics::SystemProfileProto::Hardware* hardware =
      system_profile_proto->mutable_hardware();
  hardware->set_hardware_class(hardware_class_);
  hardware->set_full_hardware_class(full_hardware_class_);
  display::Display::TouchSupport has_touch =
      ui::GetInternalDisplayTouchSupport();
  if (has_touch == display::Display::TouchSupport::AVAILABLE)
    hardware->set_internal_display_supports_touch(true);
  else if (has_touch == display::Display::TouchSupport::UNAVAILABLE)
    hardware->set_internal_display_supports_touch(false);
}

void ChromeOSMetricsProvider::ProvideStabilityMetrics(
    metrics::SystemProfileProto* system_profile_proto) {
  metrics::SystemProfileProto::Stability* stability_proto =
      system_profile_proto->mutable_stability();
  PrefService* pref = g_browser_process->local_state();
  int count = pref->GetInteger(prefs::kStabilityOtherUserCrashCount);
  if (count) {
    stability_proto->set_other_user_crash_count(count);
    pref->SetInteger(prefs::kStabilityOtherUserCrashCount, 0);
  }

  count = pref->GetInteger(prefs::kStabilityKernelCrashCount);
  if (count) {
    stability_proto->set_kernel_crash_count(count);
    pref->SetInteger(prefs::kStabilityKernelCrashCount, 0);
  }

  count = pref->GetInteger(prefs::kStabilitySystemUncleanShutdownCount);
  if (count) {
    stability_proto->set_unclean_system_shutdown_count(count);
    pref->SetInteger(prefs::kStabilitySystemUncleanShutdownCount, 0);
  }
}

void ChromeOSMetricsProvider::ProvidePreviousSessionData(
    metrics::ChromeUserMetricsExtension* uma_proto) {
  ProvideStabilityMetrics(uma_proto->mutable_system_profile());
  // The enrollment status and ARC state of a client are not likely to change
  // between browser restarts.  Hence, it's safe and useful to attach these
  // values to a previous session log.
  RecordEnrollmentStatus();
  RecordArcState();
}

void ChromeOSMetricsProvider::ProvideCurrentSessionData(
    metrics::ChromeUserMetricsExtension* uma_proto) {
  ProvideStabilityMetrics(uma_proto->mutable_system_profile());
  std::vector<SampledProfile> sampled_profiles;
  if (perf_provider_.GetSampledProfiles(&sampled_profiles)) {
    for (auto& profile : sampled_profiles) {
      uma_proto->add_sampled_profile()->Swap(&profile);
    }
  }

  RecordEnrollmentStatus();
  RecordArcState();
}

void ChromeOSMetricsProvider::WriteBluetoothProto(
    metrics::SystemProfileProto* system_profile_proto) {
  metrics::SystemProfileProto::Hardware* hardware =
      system_profile_proto->mutable_hardware();

  SystemProfileProto::Hardware::Bluetooth* bluetooth =
      hardware->mutable_bluetooth();

  bluetooth->set_is_present(adapter_->IsPresent());
  bluetooth->set_is_enabled(adapter_->IsPowered());

  device::BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
  for (device::BluetoothAdapter::DeviceList::iterator iter = devices.begin();
       iter != devices.end();
       ++iter) {
    device::BluetoothDevice* device = *iter;
    // Don't collect information about LE devices yet.
    if (!device->IsPaired())
      continue;

    PairedDevice* paired_device = bluetooth->add_paired_device();
    paired_device->set_bluetooth_class(device->GetBluetoothClass());
    paired_device->set_type(AsBluetoothDeviceType(device->GetDeviceType()));

    // |address| is xx:xx:xx:xx:xx:xx, extract the first three components and
    // pack into a uint32_t.
    std::string address = device->GetAddress();
    if (address.size() > 9 && address[2] == ':' && address[5] == ':' &&
        address[8] == ':') {
      std::string vendor_prefix_str;
      uint64_t vendor_prefix;

      base::RemoveChars(address.substr(0, 9), ":", &vendor_prefix_str);
      DCHECK_EQ(6U, vendor_prefix_str.size());
      base::HexStringToUInt64(vendor_prefix_str, &vendor_prefix);

      paired_device->set_vendor_prefix(vendor_prefix);
    }

    switch (device->GetVendorIDSource()) {
      case device::BluetoothDevice::VENDOR_ID_BLUETOOTH:
        paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_BLUETOOTH);
        break;
      case device::BluetoothDevice::VENDOR_ID_USB:
        paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_USB);
        break;
      default:
        paired_device->set_vendor_id_source(PairedDevice::VENDOR_ID_UNKNOWN);
    }

    paired_device->set_vendor_id(device->GetVendorID());
    paired_device->set_product_id(device->GetProductID());
    paired_device->set_device_id(device->GetDeviceID());
  }
}

void ChromeOSMetricsProvider::UpdateMultiProfileUserCount(
    metrics::SystemProfileProto* system_profile_proto) {
  if (user_manager::UserManager::IsInitialized()) {
    size_t user_count =
        user_manager::UserManager::Get()->GetLoggedInUsers().size();

    // We invalidate the user count if it changed while the log was open.
    if (registered_user_count_at_log_initialization_ &&
        user_count != user_count_at_log_initialization_) {
      user_count = 0;
    }

    system_profile_proto->set_multi_profile_user_count(user_count);
  }
}

void ChromeOSMetricsProvider::SetBluetoothAdapter(
    base::Closure callback,
    scoped_refptr<device::BluetoothAdapter> adapter) {
  adapter_ = adapter;
  callback.Run();
}

void ChromeOSMetricsProvider::SetFullHardwareClass(
    base::Closure callback,
    std::string full_hardware_class) {
  if (!base::FeatureList::IsEnabled(features::kUmaShortHWClass)) {
    DCHECK(hardware_class_.empty());
    hardware_class_ = full_hardware_class;
  }
  full_hardware_class_ = full_hardware_class;
  callback.Run();
}

void ChromeOSMetricsProvider::RecordEnrollmentStatus() {
  UMA_STABILITY_HISTOGRAM_ENUMERATION(
      "UMA.EnrollmentStatus", GetEnrollmentStatus(), ENROLLMENT_STATUS_MAX);
}

void ChromeOSMetricsProvider::RecordArcState() {
  arc::ArcSessionManager* arc_session_manager = arc::ArcSessionManager::Get();
  if (arc_session_manager)
    arc_session_manager->RecordArcState();
}
