1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
// Copyright 2023 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/printing/ipp_client_info_calculator.h"
#include <cstdint>
#include <memory>
#include <string_view>
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "chrome/browser/ash/policy/core/device_attributes.h"
#include "chrome/browser/ash/policy/core/device_attributes_impl.h"
#include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h"
#include "components/version_info/version_info.h"
#include "printing/mojom/print.mojom.h"
namespace ash::printing {
namespace {
using ::printing::mojom::IppClientInfo;
using ::printing::mojom::IppClientInfoPtr;
constexpr char kOsInfoClientName[] = "ChromeOS";
constexpr char kDeviceDirectoryApiIdPlaceholder[] =
"${DEVICE_DIRECTORY_API_ID}";
constexpr char kDeviceSerialNumberPlaceholder[] = "${DEVICE_SERIAL_NUMBER}";
constexpr char kDeviceAssetIdPlaceholder[] = "${DEVICE_ASSET_ID}";
constexpr char kDeviceAnnotatedLocationPlaceholder[] =
"${DEVICE_ANNOTATED_LOCATION}";
// Replace device variables found in `str` with the provided values.
std::string ReplaceDeviceVariables(std::string template_with_vars,
std::string_view api_id,
std::string_view serial,
std::string_view asset_id,
std::string_view location) {
base::ReplaceSubstringsAfterOffset(&template_with_vars, 0,
kDeviceDirectoryApiIdPlaceholder, api_id);
base::ReplaceSubstringsAfterOffset(&template_with_vars, 0,
kDeviceSerialNumberPlaceholder, serial);
base::ReplaceSubstringsAfterOffset(&template_with_vars, 0,
kDeviceAssetIdPlaceholder, asset_id);
base::ReplaceSubstringsAfterOffset(
&template_with_vars, 0, kDeviceAnnotatedLocationPlaceholder, location);
return template_with_vars;
}
class IppClientInfoCalculatorImpl : public IppClientInfoCalculator {
public:
IppClientInfoCalculatorImpl(
std::unique_ptr<policy::DeviceAttributes> device_attributes,
const std::string& chrome_milestone)
: cros_settings_(CrosSettings::Get()),
device_attributes_(std::move(device_attributes)) {
// Calculate the initial client-info values. The admin-configured
// `client-info` value with device information can change later if the
// `kDevicePrintingClientNameTemplate` setting changes.
CalculateClientInfoWithDeviceValues();
CalculateClientInfoWithOSVersion(chrome_milestone);
// Recalculate `client-info` with device information when
// `kDevicePrintingClientNameTemplate` setting changes.
// base::Unretained(this) is safe here because the subscription is scoped to
// the lifetime of `this` already.
auto callback = base::BindRepeating(
&IppClientInfoCalculatorImpl::CalculateClientInfoWithDeviceValues,
base::Unretained(this));
client_name_template_subscription_ =
CrosSettings::Get()->AddSettingsObserver(
kDevicePrintingClientNameTemplate, std::move(callback));
}
private:
IppClientInfoPtr GetOsInfo() const override {
DCHECK(os_info_);
return os_info_.Clone();
}
IppClientInfoPtr GetDeviceInfo() const override {
return device_info_.Clone();
}
void CalculateClientInfoWithDeviceValues() {
std::string client_name_template = GetClientNameTemplateFromCrosSettings();
if (client_name_template.empty()) {
return;
}
std::string serial = device_attributes_->GetDeviceSerialNumber();
std::string asset_id = device_attributes_->GetDeviceAssetID();
std::string location = device_attributes_->GetDeviceAnnotatedLocation();
std::string directory_api_id = device_attributes_->GetDirectoryApiID();
std::string client_name =
ReplaceDeviceVariables(std::move(client_name_template),
directory_api_id, serial, asset_id, location);
device_info_ = IppClientInfo::New(IppClientInfo::ClientType::kOther,
std::move(client_name),
/*client_patches=*/std::nullopt,
/*client_string_version=*/std::string(),
/*client_version=*/std::nullopt);
}
void CalculateClientInfoWithOSVersion(const std::string& chrome_milestone) {
DCHECK(base::SysInfo::IsRunningOnChromeOS());
os_info_ = IppClientInfo::New(
IppClientInfo::ClientType::kOperatingSystem, kOsInfoClientName,
base::SysInfo::OperatingSystemVersion(), chrome_milestone,
/*client_version=*/std::nullopt);
}
std::string GetClientNameTemplateFromCrosSettings() {
std::string client_name_template;
cros_settings_->GetString(kDevicePrintingClientNameTemplate,
&client_name_template);
return client_name_template;
}
raw_ptr<const CrosSettings> cros_settings_;
std::unique_ptr<policy::DeviceAttributes> device_attributes_;
IppClientInfoPtr device_info_;
IppClientInfoPtr os_info_;
base::CallbackListSubscription client_name_template_subscription_;
};
} // namespace
std::unique_ptr<IppClientInfoCalculator> IppClientInfoCalculator::Create() {
return std::make_unique<IppClientInfoCalculatorImpl>(
std::make_unique<policy::DeviceAttributesImpl>(),
version_info::GetMajorVersionNumber());
}
std::unique_ptr<IppClientInfoCalculator>
IppClientInfoCalculator::CreateForTesting(
std::unique_ptr<policy::DeviceAttributes> device_attributes,
const std::string& chrome_milestone) {
return std::make_unique<IppClientInfoCalculatorImpl>(
std::move(device_attributes), chrome_milestone);
}
} // namespace ash::printing
|