esim_manager.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ash/services/cellular_setup/esim_manager.h"
  5. #include <sstream>
  6. #include "ash/constants/ash_features.h"
  7. #include "ash/services/cellular_setup/esim_profile.h"
  8. #include "ash/services/cellular_setup/euicc.h"
  9. #include "ash/services/cellular_setup/public/mojom/esim_manager.mojom.h"
  10. #include "base/strings/utf_string_conversions.h"
  11. #include "chromeos/ash/components/dbus/hermes/hermes_manager_client.h"
  12. #include "chromeos/ash/components/network/network_event_log.h"
  13. #include "chromeos/ash/components/network/network_handler.h"
  14. #include "components/device_event_log/device_event_log.h"
  15. #include "dbus/object_path.h"
  16. #include "third_party/cros_system_api/dbus/hermes/dbus-constants.h"
  17. namespace ash::cellular_setup {
  18. namespace {
  19. // The Stork SM-DS Prod server used to fetch pending ESim profiles.
  20. const char kStorkSmdsServerAddress[] = "prod.smds.rsp.goog";
  21. void LogEuiccPaths(const std::set<dbus::ObjectPath>& new_euicc_paths) {
  22. if (new_euicc_paths.empty()) {
  23. NET_LOG(EVENT) << "EUICC list updated; no EUICCs present";
  24. return;
  25. }
  26. std::stringstream ss("[");
  27. for (const auto& new_path : new_euicc_paths)
  28. ss << new_path.value() << ", ";
  29. ss.seekp(-2, ss.cur); // Remove last ", " from the stream.
  30. ss << "]";
  31. NET_LOG(EVENT) << "EUICC list updated; paths: " << ss.str();
  32. }
  33. } // namespace
  34. // static
  35. std::string ESimManager::GetRootSmdsAddress() {
  36. // An empty string indicates that the root GSMA address should be used.
  37. return features::IsUseStorkSmdsServerAddressEnabled()
  38. ? kStorkSmdsServerAddress
  39. : std::string();
  40. }
  41. ESimManager::ESimManager()
  42. : ESimManager(NetworkHandler::Get()->cellular_connection_handler(),
  43. NetworkHandler::Get()->cellular_esim_installer(),
  44. NetworkHandler::Get()->cellular_esim_profile_handler(),
  45. NetworkHandler::Get()->cellular_esim_uninstall_handler(),
  46. NetworkHandler::Get()->cellular_inhibitor(),
  47. NetworkHandler::Get()->network_connection_handler(),
  48. NetworkHandler::Get()->network_state_handler()) {}
  49. ESimManager::ESimManager(
  50. CellularConnectionHandler* cellular_connection_handler,
  51. CellularESimInstaller* cellular_esim_installer,
  52. CellularESimProfileHandler* cellular_esim_profile_handler,
  53. CellularESimUninstallHandler* cellular_esim_uninstall_handler,
  54. CellularInhibitor* cellular_inhibitor,
  55. NetworkConnectionHandler* network_connection_handler,
  56. NetworkStateHandler* network_state_handler)
  57. : cellular_connection_handler_(cellular_connection_handler),
  58. cellular_esim_installer_(cellular_esim_installer),
  59. cellular_esim_profile_handler_(cellular_esim_profile_handler),
  60. cellular_esim_uninstall_handler_(cellular_esim_uninstall_handler),
  61. cellular_inhibitor_(cellular_inhibitor),
  62. network_connection_handler_(network_connection_handler),
  63. network_state_handler_(network_state_handler) {
  64. HermesManagerClient::Get()->AddObserver(this);
  65. HermesEuiccClient::Get()->AddObserver(this);
  66. cellular_esim_profile_handler_->AddObserver(this);
  67. OnESimProfileListUpdated();
  68. }
  69. ESimManager::~ESimManager() {
  70. HermesManagerClient::Get()->RemoveObserver(this);
  71. HermesEuiccClient::Get()->RemoveObserver(this);
  72. cellular_esim_profile_handler_->RemoveObserver(this);
  73. }
  74. void ESimManager::AddObserver(
  75. mojo::PendingRemote<mojom::ESimManagerObserver> observer) {
  76. observers_.Add(std::move(observer));
  77. }
  78. void ESimManager::GetAvailableEuiccs(GetAvailableEuiccsCallback callback) {
  79. std::vector<mojo::PendingRemote<mojom::Euicc>> euicc_list;
  80. for (auto const& euicc : available_euiccs_)
  81. euicc_list.push_back(euicc->CreateRemote());
  82. std::move(callback).Run(std::move(euicc_list));
  83. }
  84. void ESimManager::OnAvailableEuiccListChanged() {
  85. UpdateAvailableEuiccs();
  86. }
  87. void ESimManager::OnEuiccPropertyChanged(const dbus::ObjectPath& euicc_path,
  88. const std::string& property_name) {
  89. Euicc* euicc = GetEuiccFromPath(euicc_path);
  90. // Skip notifying observers if the euicc object is not tracked.
  91. if (!euicc)
  92. return;
  93. // Profile lists are handled in OnESimProfileListUpdated notification from
  94. // CellularESimProfileHandler.
  95. if (property_name == hermes::euicc::kPendingProfilesProperty ||
  96. property_name == hermes::euicc::kInstalledProfilesProperty) {
  97. return;
  98. }
  99. euicc->UpdateProperties();
  100. for (auto& observer : observers_)
  101. observer->OnEuiccChanged(euicc->CreateRemote());
  102. }
  103. void ESimManager::OnESimProfileListUpdated() {
  104. // Force update available euiccs in case OnAvailableEuiccListChanged on this
  105. // class was not called before this handler
  106. UpdateAvailableEuiccs();
  107. std::vector<CellularESimProfile> esim_profile_states =
  108. cellular_esim_profile_handler_->GetESimProfiles();
  109. for (auto& euicc : available_euiccs_) {
  110. euicc->UpdateProfileList(esim_profile_states);
  111. }
  112. }
  113. void ESimManager::BindReceiver(
  114. mojo::PendingReceiver<mojom::ESimManager> receiver) {
  115. NET_LOG(EVENT) << "ESimManager::BindReceiver()";
  116. receivers_.Add(this, std::move(receiver));
  117. }
  118. void ESimManager::NotifyESimProfileChanged(ESimProfile* esim_profile) {
  119. for (auto& observer : observers_)
  120. observer->OnProfileChanged(esim_profile->CreateRemote());
  121. }
  122. void ESimManager::NotifyESimProfileListChanged(Euicc* euicc) {
  123. for (auto& observer : observers_)
  124. observer->OnProfileListChanged(euicc->CreateRemote());
  125. }
  126. void ESimManager::UpdateAvailableEuiccs() {
  127. NET_LOG(DEBUG) << "Updating available Euiccs";
  128. std::set<dbus::ObjectPath> new_euicc_paths;
  129. bool available_euiccs_changed = false;
  130. for (auto& euicc_path : HermesManagerClient::Get()->GetAvailableEuiccs()) {
  131. available_euiccs_changed |= CreateEuiccIfNew(euicc_path);
  132. new_euicc_paths.insert(euicc_path);
  133. }
  134. available_euiccs_changed |= RemoveUntrackedEuiccs(new_euicc_paths);
  135. if (!available_euiccs_changed)
  136. return;
  137. LogEuiccPaths(new_euicc_paths);
  138. for (auto& observer : observers_)
  139. observer->OnAvailableEuiccListChanged();
  140. }
  141. bool ESimManager::RemoveUntrackedEuiccs(
  142. const std::set<dbus::ObjectPath> new_euicc_paths) {
  143. bool removed = false;
  144. for (auto euicc_it = available_euiccs_.begin();
  145. euicc_it != available_euiccs_.end();) {
  146. if (new_euicc_paths.find((*euicc_it)->path()) == new_euicc_paths.end()) {
  147. removed = true;
  148. euicc_it = available_euiccs_.erase(euicc_it);
  149. } else {
  150. euicc_it++;
  151. }
  152. }
  153. return removed;
  154. }
  155. bool ESimManager::CreateEuiccIfNew(const dbus::ObjectPath& euicc_path) {
  156. Euicc* euicc_info = GetEuiccFromPath(euicc_path);
  157. if (euicc_info)
  158. return false;
  159. available_euiccs_.push_back(std::make_unique<Euicc>(euicc_path, this));
  160. return true;
  161. }
  162. Euicc* ESimManager::GetEuiccFromPath(const dbus::ObjectPath& path) {
  163. for (auto& euicc : available_euiccs_) {
  164. if (euicc->path() == path) {
  165. return euicc.get();
  166. }
  167. }
  168. return nullptr;
  169. }
  170. } // namespace ash::cellular_setup