blob: 7a3d8784bf99eb97771c200c52c48624319c11e1 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/sync_device_info/local_device_info_util.h"
#include <string_view>
#include "base/barrier_closure.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/location.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "ui/base/device_form_factor.h"
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chromeos/ash/components/system/statistics_provider.h"
#endif
namespace syncer {
// Declared here but defined in platform-specific files.
std::string GetPersonalizableDeviceNameInternal();
#if BUILDFLAG(IS_CHROMEOS)
std::string GetChromeOSDeviceNameFromType();
#endif
LocalDeviceNameInfo::LocalDeviceNameInfo() = default;
LocalDeviceNameInfo::LocalDeviceNameInfo(const LocalDeviceNameInfo& other) =
default;
LocalDeviceNameInfo::~LocalDeviceNameInfo() = default;
namespace {
void OnLocalDeviceNameInfoReady(
base::OnceCallback<void(LocalDeviceNameInfo)> callback,
std::unique_ptr<LocalDeviceNameInfo> name_info) {
std::move(callback).Run(std::move(*name_info));
}
void OnHardwareInfoReady(LocalDeviceNameInfo* name_info_ptr,
base::ScopedClosureRunner done_closure,
base::SysInfo::HardwareInfo hardware_info) {
name_info_ptr->manufacturer_name = std::move(hardware_info.manufacturer);
#if BUILDFLAG(IS_CHROMEOS)
// For ChromeOS the returned model values are product code names like Eve. We
// want to use generic names like Chromebook.
name_info_ptr->model_name = GetChromeOSDeviceNameFromType();
#else
name_info_ptr->model_name = std::move(hardware_info.model);
#endif
}
void OnPersonalizableDeviceNameReady(LocalDeviceNameInfo* name_info_ptr,
base::ScopedClosureRunner done_closure,
std::string personalizable_name) {
name_info_ptr->personalizable_name = std::move(personalizable_name);
}
void OnMachineStatisticsLoaded(LocalDeviceNameInfo* name_info_ptr,
base::ScopedClosureRunner done_closure) {
#if BUILDFLAG(IS_CHROMEOS_ASH)
// |full_hardware_class| is set on Chrome OS devices if the user has UMA
// enabled. Otherwise |full_hardware_class| is set to an empty string.
if (const std::optional<std::string_view> full_hardware_class =
ash::system::StatisticsProvider::GetInstance()->GetMachineStatistic(
ash::system::kHardwareClassKey)) {
name_info_ptr->full_hardware_class =
std::string(full_hardware_class.value());
}
#else
name_info_ptr->full_hardware_class = "";
#endif
}
} // namespace
sync_pb::SyncEnums::DeviceType GetLocalDeviceType() {
#if BUILDFLAG(IS_CHROMEOS)
return sync_pb::SyncEnums_DeviceType_TYPE_CROS;
#elif BUILDFLAG(IS_LINUX)
return sync_pb::SyncEnums_DeviceType_TYPE_LINUX;
#elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
switch (ui::GetDeviceFormFactor()) {
case ui::DEVICE_FORM_FACTOR_TABLET:
return sync_pb::SyncEnums_DeviceType_TYPE_TABLET;
case ui::DEVICE_FORM_FACTOR_PHONE:
return sync_pb::SyncEnums_DeviceType_TYPE_PHONE;
default:
return sync_pb::SyncEnums_DeviceType_TYPE_OTHER;
}
#elif BUILDFLAG(IS_MAC)
return sync_pb::SyncEnums_DeviceType_TYPE_MAC;
#elif BUILDFLAG(IS_WIN)
return sync_pb::SyncEnums_DeviceType_TYPE_WIN;
#else
return sync_pb::SyncEnums_DeviceType_TYPE_OTHER;
#endif
}
DeviceInfo::OsType GetLocalDeviceOSType() {
#if BUILDFLAG(IS_CHROMEOS_ASH)
return DeviceInfo::OsType::kChromeOsAsh;
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
return DeviceInfo::OsType::kChromeOsLacros;
#elif BUILDFLAG(IS_LINUX)
return DeviceInfo::OsType::kLinux;
#elif BUILDFLAG(IS_ANDROID)
return DeviceInfo::OsType::kAndroid;
#elif BUILDFLAG(IS_IOS)
return DeviceInfo::OsType::kIOS;
#elif BUILDFLAG(IS_MAC)
return DeviceInfo::OsType::kMac;
#elif BUILDFLAG(IS_WIN)
return DeviceInfo::OsType::kWindows;
#elif BUILDFLAG(IS_FUCHSIA)
return DeviceInfo::OsType::kFuchsia;
#else
#error Please handle your new device OS here.
#endif
}
DeviceInfo::FormFactor GetLocalDeviceFormFactor() {
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || \
BUILDFLAG(IS_WIN)
return DeviceInfo::FormFactor::kDesktop;
#elif BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
return ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET
? DeviceInfo::FormFactor::kTablet
: DeviceInfo::FormFactor::kPhone;
#elif BUILDFLAG(IS_FUCHSIA)
return DeviceInfo::FormFactor::kUnknown;
#else
#error Please handle your new device OS here.
#endif
}
std::string GetPersonalizableDeviceNameBlocking() {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
std::string device_name = GetPersonalizableDeviceNameInternal();
if (device_name == "Unknown" || device_name.empty()) {
device_name = base::SysInfo::OperatingSystemName();
}
DCHECK(base::IsStringUTF8(device_name));
return device_name;
}
void GetLocalDeviceNameInfo(
base::OnceCallback<void(LocalDeviceNameInfo)> callback) {
auto name_info = std::make_unique<LocalDeviceNameInfo>();
LocalDeviceNameInfo* name_info_ptr = name_info.get();
auto done_closure = base::BarrierClosure(
/*num_closures=*/3,
base::BindOnce(&OnLocalDeviceNameInfoReady, std::move(callback),
std::move(name_info)));
base::SysInfo::GetHardwareInfo(
base::BindOnce(&OnHardwareInfoReady, name_info_ptr,
base::ScopedClosureRunner(done_closure)));
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Bind hwclass once the statistics are available on ChromeOS devices.
ash::system::StatisticsProvider::GetInstance()
->ScheduleOnMachineStatisticsLoaded(
base::BindOnce(&OnMachineStatisticsLoaded, name_info_ptr,
base::ScopedClosureRunner(done_closure)));
#else
OnMachineStatisticsLoaded(name_info_ptr,
base::ScopedClosureRunner(done_closure));
#endif
base::ThreadPool::PostTaskAndReplyWithResult(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::BindOnce(&GetPersonalizableDeviceNameBlocking),
base::BindOnce(&OnPersonalizableDeviceNameReady, name_info_ptr,
base::ScopedClosureRunner(done_closure)));
}
} // namespace syncer