File: cellular_policy_handler.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (227 lines) | stat: -rw-r--r-- 9,891 bytes parent folder | download | duplicates (3)
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
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROMEOS_ASH_COMPONENTS_NETWORK_CELLULAR_POLICY_HANDLER_H_
#define CHROMEOS_ASH_COMPONENTS_NETWORK_CELLULAR_POLICY_HANDLER_H_

#include <optional>

#include "base/component_export.h"
#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "base/values.h"
#include "chromeos/ash/components/network/cellular_esim_profile_handler.h"
#include "chromeos/ash/components/network/network_state_handler.h"
#include "chromeos/ash/components/network/network_state_handler_observer.h"
#include "chromeos/ash/components/network/policy_util.h"
#include "net/base/backoff_entry.h"

namespace dbus {
class ObjectPath;
}  // namespace dbus

namespace ash {

class CellularESimInstaller;
class CellularInhibitor;
class NetworkProfileHandler;
class NetworkStateHandler;
class ManagedCellularPrefHandler;
class ManagedNetworkConfigurationHandler;
enum class HermesResponseStatus;

// This class encapsulates the logic for installing eSIM profiles configured by
// policy. Installation requests are added to a queue, and each request will be
// retried a fixed number of times with a retry delay between each attempt.
class COMPONENT_EXPORT(CHROMEOS_NETWORK) CellularPolicyHandler
    : public HermesManagerClient::Observer,
      public CellularESimProfileHandler::Observer,
      public NetworkStateHandlerObserver {
 public:
  CellularPolicyHandler();
  CellularPolicyHandler(const CellularPolicyHandler&) = delete;
  CellularPolicyHandler& operator=(const CellularPolicyHandler&) = delete;
  ~CellularPolicyHandler() override;

  void Init(CellularESimProfileHandler* cellular_esim_profile_handler,
            CellularESimInstaller* cellular_esim_installer,
            CellularInhibitor* cellular_inhibitor,
            NetworkProfileHandler* network_profile_handler,
            NetworkStateHandler* network_state_handler,
            ManagedCellularPrefHandler* managed_cellular_pref_handler,
            ManagedNetworkConfigurationHandler*
                managed_network_configuration_handler);

  // Installs the policy eSIM profile defined in |onc_config|. The Shill service
  // configuration will be updated to match the GUID provided by |onc_config|
  // and to include the ICCID of the installed profile. Installations are
  // performed using a queue, and each installation will be retried a fix number
  // of times.
  void InstallESim(const base::Value::Dict& onc_config);

 private:
  // This enum allows us to treat a retry differently depending on what the
  // reason for retrying is.
  enum class InstallRetryReason {
    kMissingNonCellularConnectivity = 0,
    kInternalError = 1,
    kUserError = 2,
    kOther = 3,
  };

  // HermesUserErrorCodes indicate errors made by the user. These can be due
  // to bad input or a valid input that has already been successfully processed.
  // In such errors, we do not attempt to retry.
  const std::array<HermesResponseStatus, 4> kHermesUserErrorCodes = {
      HermesResponseStatus::kErrorAlreadyDisabled,
      HermesResponseStatus::kErrorAlreadyEnabled,
      HermesResponseStatus::kErrorInvalidActivationCode,
      HermesResponseStatus::kErrorInvalidIccid};

  // HermesInternalErrorCodes indicate system failure during the installation
  // process. These error can happen due to code bugs or reasons unrelated to
  // user input. In these cases, we retry using an exponental backoff policy to
  // attempt the installation again.
  const std::array<HermesResponseStatus, 7> kHermesInternalErrorCodes = {
      HermesResponseStatus::kErrorUnknown,
      HermesResponseStatus::kErrorInternalLpaFailure,
      HermesResponseStatus::kErrorWrongState,
      HermesResponseStatus::kErrorSendApduFailure,
      HermesResponseStatus::kErrorUnexpectedModemManagerState,
      HermesResponseStatus::kErrorModemMessageProcessing,
      HermesResponseStatus::kErrorPendingProfile};

  friend class CellularPolicyHandlerTest;

  // Represents policy eSIM install request parameters. Requests are queued and
  // processed one at a time. |activation_code| represents the SM-DP+ activation
  // code that will be used to install the eSIM profile, and |onc_config| is the
  // ONC configuration of the cellular policy.
  struct InstallPolicyESimRequest {
    InstallPolicyESimRequest(policy_util::SmdxActivationCode activation_code,
                             const base::Value::Dict& onc_config);
    InstallPolicyESimRequest(const InstallPolicyESimRequest&) = delete;
    InstallPolicyESimRequest& operator=(const InstallPolicyESimRequest&) =
        delete;
    ~InstallPolicyESimRequest();

    const policy_util::SmdxActivationCode activation_code;
    base::Value::Dict onc_config;
    net::BackoffEntry retry_backoff;
  };

  // HermesManagerClient::Observer:
  void OnAvailableEuiccListChanged() override;

  // CellularESimProfileHandler::Observer:
  void OnESimProfileListUpdated() override;

  // NetworkStateHandlerObserver:
  void DeviceListChanged() override;
  void OnShuttingDown() override;

  // These functions implement the functionality necessary to interact with the
  // queue of policy eSIM installation requests.
  void ResumeInstallIfNeeded();
  void ProcessRequests();
  void ScheduleRetryAndProcessRequests(
      std::unique_ptr<InstallPolicyESimRequest> request,
      InstallRetryReason reason);
  void PushRequestAndProcess(std::unique_ptr<InstallPolicyESimRequest> request);
  void PopRequest();
  void PopAndProcessRequests();

  // Attempts to install the first request in the queue. This function is
  // responsible for ensuring that both a cellular device and Hermes are
  // available. Further, this function will also refresh the list of installed
  // eSIM profiles so that we can properly determine whether an eSIM profile has
  // already been installed for the request.
  void AttemptInstallESim();

  // Actually responsible for kicking off the installation process. This
  // function will configure the Shill service that corresponds to the profile
  // that will be installed, and will ensure that we have non-cellular internet
  // connectivity.
  void PerformInstallESim(const dbus::ObjectPath& euicc_path,
                          base::Value::Dict new_shill_properties);

  void OnRefreshProfileList(
      const dbus::ObjectPath& euicc_path,
      base::Value::Dict new_shill_properties,
      std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock);
  void OnConfigureESimService(std::optional<dbus::ObjectPath> service_path);
  void OnInhibitedForRefreshSmdxProfiles(
      const dbus::ObjectPath& euicc_path,
      base::Value::Dict new_shill_properties,
      std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock);
  void OnRefreshSmdxProfiles(
      const dbus::ObjectPath& euicc_path,
      base::Value::Dict new_shill_properties,
      std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock,
      base::TimeTicks start_time,
      HermesResponseStatus status,
      const std::vector<dbus::ObjectPath>& profile_paths);
  void CompleteRefreshSmdxProfiles(
      const dbus::ObjectPath& euicc_path,
      base::Value::Dict new_shill_properties,
      std::unique_ptr<CellularInhibitor::InhibitLock> inhibit_lock,
      HermesResponseStatus status,
      const std::vector<dbus::ObjectPath>& profile_paths);
  void OnESimProfileInstallAttemptComplete(
      HermesResponseStatus hermes_status,
      std::optional<dbus::ObjectPath> profile_path,
      std::optional<std::string> service_path);
  void OnWaitTimeout();

  base::Value::Dict GetNewShillProperties();
  const policy_util::SmdxActivationCode& GetCurrentActivationCode() const;
  std::optional<dbus::ObjectPath> FindExistingMatchingESimProfile(
      const std::string& iccid);
  // Return std::nullopt if no or empty iccid is found in the policy ONC.
  std::optional<std::string> GetIccidFromPolicyONC();
  bool HasNonCellularInternetConnectivity();
  InstallRetryReason HermesResponseStatusToRetryReason(
      HermesResponseStatus status) const;

  raw_ptr<CellularESimProfileHandler> cellular_esim_profile_handler_ = nullptr;
  raw_ptr<CellularESimInstaller> cellular_esim_installer_ = nullptr;
  raw_ptr<CellularInhibitor> cellular_inhibitor_ = nullptr;
  raw_ptr<NetworkProfileHandler> network_profile_handler_ = nullptr;
  raw_ptr<NetworkStateHandler> network_state_handler_ = nullptr;
  base::ScopedObservation<NetworkStateHandler, NetworkStateHandlerObserver>
      network_state_handler_observer_{this};
  raw_ptr<ManagedCellularPrefHandler, DanglingUntriaged>
      managed_cellular_pref_handler_ = nullptr;
  raw_ptr<ManagedNetworkConfigurationHandler, DanglingUntriaged>
      managed_network_configuration_handler_ = nullptr;

  bool is_installing_ = false;

  // While Hermes is the source of truth for the EUICC state, Chrome maintains a
  // cache of the installed eSIM profiles. To ensure we properly detect when a
  // profile has already been installed for a particular request we force a
  // refresh of the profile cache before each installation.
  bool need_refresh_profile_list_ = true;

  base::circular_deque<std::unique_ptr<InstallPolicyESimRequest>>
      remaining_install_requests_;

  base::OneShotTimer wait_timer_;

  base::ScopedObservation<HermesManagerClient, HermesManagerClient::Observer>
      hermes_observation_{this};
  base::ScopedObservation<CellularESimProfileHandler,
                          CellularESimProfileHandler::Observer>
      cellular_esim_profile_handler_observation_{this};

  base::WeakPtrFactory<CellularPolicyHandler> weak_ptr_factory_{this};
};

}  // namespace ash

#endif  // CHROMEOS_ASH_COMPONENTS_NETWORK_CELLULAR_POLICY_HANDLER_H_