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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/ash/components/network/managed_cellular_pref_handler.h"
#include "ash/constants/ash_features.h"
#include "ash/constants/ash_pref_names.h"
#include "base/check.h"
#include "base/values.h"
#include "chromeos/ash/components/network/network_event_log.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/policy_util.h"
#include "components/onc/onc_constants.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/scoped_user_pref_update.h"
namespace ash {
namespace {
constexpr char kESimMetadataPolicyMissingKey[] = "PolicyMissing";
} // namespace
// static
void ManagedCellularPrefHandler::RegisterLocalStatePrefs(
PrefRegistrySimple* registry) {
registry->RegisterDictionaryPref(prefs::kManagedCellularESimMetadata);
registry->RegisterDictionaryPref(prefs::kManagedCellularIccidSmdpPair);
registry->RegisterDictionaryPref(prefs::kApnMigratedIccids);
}
ManagedCellularPrefHandler::ManagedCellularPrefHandler() = default;
ManagedCellularPrefHandler::~ManagedCellularPrefHandler() = default;
void ManagedCellularPrefHandler::Init(
NetworkStateHandler* network_state_handler) {
network_state_handler_ = network_state_handler;
}
void ManagedCellularPrefHandler::SetDevicePrefs(PrefService* device_prefs) {
device_prefs_ = device_prefs;
if (!device_prefs_ ||
device_prefs_->HasPrefPath(prefs::kManagedCellularESimMetadata)) {
return;
}
MigrateExistingPrefs();
}
void ManagedCellularPrefHandler::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void ManagedCellularPrefHandler::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
bool ManagedCellularPrefHandler::HasObserver(Observer* observer) const {
return observer_list_.HasObserver(observer);
}
void ManagedCellularPrefHandler::NotifyManagedCellularPrefChanged() {
for (auto& observer : observer_list_)
observer.OnManagedCellularPrefChanged();
}
void ManagedCellularPrefHandler::AddESimMetadata(
const std::string& iccid,
const std::string& name,
const policy_util::SmdxActivationCode& activation_code,
bool sync_stub_networks) {
DCHECK(!name.empty());
DCHECK(!activation_code.value().empty());
if (!device_prefs_) {
NET_LOG(ERROR) << "Device pref not available yet";
return;
}
auto esim_metadata =
base::Value::Dict()
.Set(::onc::network_config::kName, name)
.Set(activation_code.type() ==
policy_util::SmdxActivationCode::Type::SMDP
? ::onc::cellular::kSMDPAddress
: ::onc::cellular::kSMDSAddress,
activation_code.value())
.Set(kESimMetadataPolicyMissingKey, false);
const base::Value::Dict* existing_esim_metadata = GetESimMetadata(iccid);
if (existing_esim_metadata && *existing_esim_metadata == esim_metadata) {
return;
}
NET_LOG(EVENT) << "Adding eSIM metadata to device prefs, ICCID: " << iccid
<< ", name: " << name
<< ", activation code: " << activation_code.ToString();
ScopedDictPrefUpdate update(device_prefs_,
prefs::kManagedCellularESimMetadata);
update->Set(iccid, std::move(esim_metadata));
if (sync_stub_networks) {
network_state_handler_->SyncStubCellularNetworks();
}
NotifyManagedCellularPrefChanged();
}
const base::Value::Dict* ManagedCellularPrefHandler::GetESimMetadata(
const std::string& iccid) {
if (!device_prefs_) {
NET_LOG(ERROR) << "Device pref not available yet";
return nullptr;
}
const base::Value::Dict& esim_metadata =
device_prefs_->GetDict(prefs::kManagedCellularESimMetadata);
return esim_metadata.FindDict(iccid);
}
void ManagedCellularPrefHandler::RemoveESimMetadata(const std::string& iccid) {
if (!device_prefs_) {
NET_LOG(ERROR) << "Device pref not available yet";
return;
}
const base::Value::Dict& esim_metadata =
device_prefs_->GetDict(prefs::kManagedCellularESimMetadata);
if (!esim_metadata.contains(iccid)) {
return;
}
NET_LOG(EVENT) << "Removing eSIM metadata from device prefs, ICCID: "
<< iccid;
ScopedDictPrefUpdate update(device_prefs_,
prefs::kManagedCellularESimMetadata);
update->Remove(iccid);
network_state_handler_->SyncStubCellularNetworks();
NotifyManagedCellularPrefChanged();
}
bool ManagedCellularPrefHandler::IsESimManaged(const std::string& iccid) {
const base::Value::Dict* esim_metadata = GetESimMetadata(iccid);
if (!esim_metadata) {
return false;
}
std::optional<bool> policy_missing =
esim_metadata->FindBool(kESimMetadataPolicyMissingKey);
// The eSIM is considered managed if the |kESimMetadataPolicyMissingKey| is
// missing or if the value associated with the key is |false|. This key may be
// missing since it was added after metadata initially was. For more
// information see b/361421631.
if (!policy_missing.has_value()) {
return true;
}
return !policy_missing.value();
}
void ManagedCellularPrefHandler::SetPolicyMissing(const std::string& iccid) {
const base::Value::Dict* existing_esim_metadata = GetESimMetadata(iccid);
if (!existing_esim_metadata) {
return;
}
base::Value::Dict esim_metadata = existing_esim_metadata->Clone();
esim_metadata.Set(kESimMetadataPolicyMissingKey, true);
NET_LOG(EVENT) << "Setting the policy missing flag for eSIM metadata in "
<< "device prefs with ICCID: " << iccid;
ScopedDictPrefUpdate update(device_prefs_,
prefs::kManagedCellularESimMetadata);
update->Set(iccid, std::move(esim_metadata));
network_state_handler_->SyncStubCellularNetworks();
NotifyManagedCellularPrefChanged();
}
void ManagedCellularPrefHandler::AddApnMigratedIccid(const std::string& iccid) {
if (!device_prefs_) {
NET_LOG(ERROR) << "Device pref not available yet.";
return;
}
if (ContainsApnMigratedIccid(iccid)) {
NET_LOG(ERROR)
<< "AddApnMigratedIccid: Called with already migrated network, iccid: "
<< iccid;
return;
}
NET_LOG(EVENT)
<< "AddApnMigratedIccid: Adding migrated network to device pref, iccid: "
<< iccid;
ScopedDictPrefUpdate update(device_prefs_, prefs::kApnMigratedIccids);
update->SetByDottedPath(iccid, true);
}
bool ManagedCellularPrefHandler::ContainsApnMigratedIccid(
const std::string& iccid) const {
if (!device_prefs_) {
NET_LOG(ERROR) << "Device pref not available yet.";
return false;
}
const base::Value::Dict& apn_migrated_iccids =
device_prefs_->GetDict(prefs::kApnMigratedIccids);
return apn_migrated_iccids.FindBool(iccid).value_or(false);
}
void ManagedCellularPrefHandler::MigrateExistingPrefs() {
DCHECK(device_prefs_);
NET_LOG(EVENT) << "Starting migration of existing ICCID and SM-DP+ pairs";
const base::Value::Dict& existing_prefs =
device_prefs_->GetDict(prefs::kManagedCellularIccidSmdpPair);
for (const auto [iccid, value] : existing_prefs) {
const std::string& smdp_activation_code = value.GetString();
if (smdp_activation_code.empty()) {
NET_LOG(ERROR) << "Failed to migrate ICCID and SM-DP+ pair due to "
<< "missing activation code";
continue;
}
ScopedDictPrefUpdate update(device_prefs_,
prefs::kManagedCellularESimMetadata);
update->Set(iccid, base::Value::Dict().Set(::onc::cellular::kSMDPAddress,
smdp_activation_code));
NET_LOG(EVENT) << "Successfully migrated ICCID and SM-DP+ pair";
}
NET_LOG(EVENT) << "Finished migration of existing ICCID and SM-DP+ pairs";
}
} // namespace ash
|