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 
5 #ifndef CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_IMPL_H_
6 #define CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_IMPL_H_
7 
8 #include "base/memory/weak_ptr.h"
9 #include "chromeos/components/phonehub/phone_model.h"
10 #include "chromeos/components/phonehub/tether_controller.h"
11 #include "chromeos/services/multidevice_setup/public/cpp/multidevice_setup_client.h"
12 #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h"
13 #include "mojo/public/cpp/bindings/remote.h"
14 
15 namespace chromeos {
16 namespace phonehub {
17 namespace {
18 using multidevice_setup::MultiDeviceSetupClient;
19 }  // namespace
20 
21 class UserActionRecorder;
22 
23 // TetherController implementation which utilizes MultiDeviceSetupClient and
24 // CrosNetworkConfig in order to interact with Instant Tethering. If Instant
25 // Tethering is user disabled, AttemptConnection() will first enable the feature
26 // via the MultiDeviceSetupClient, then scan for an eligible phone via
27 // CrosNetworkConfig, and finally connect to the phone via CrosNetworkConfig. If
28 // Instant Tethering is enabled, but there is no visible Tether network,
29 // AttemptConnection() will first scan for an eligible phone via
30 // CrosNetworkConfig, and connect to the phone via CrosNetworkConfig. If Instant
31 // Tethering is enabled and there is a visible Tether Network previously fetched
32 // from observing CrosNetworkConfig, AttemptConnection() will just connect to
33 // the phone via CrosNetworkConfig. Disconnect() disconnects the Tether network
34 // if one exists.
35 class TetherControllerImpl
36     : public TetherController,
37       public PhoneModel::Observer,
38       public multidevice_setup::MultiDeviceSetupClient::Observer,
39       public chromeos::network_config::mojom::CrosNetworkConfigObserver {
40  public:
41   TetherControllerImpl(
42       PhoneModel* phone_model,
43       UserActionRecorder* user_action_recorder,
44       multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client);
45   ~TetherControllerImpl() override;
46 
47   // TetherController:
48   Status GetStatus() const override;
49   void ScanForAvailableConnection() override;
50   void AttemptConnection() override;
51   void Disconnect() override;
52 
53  private:
54   friend class TetherControllerImplTest;
55 
56   // Used to track AttemptConnection() and Disconnect() calls.
57   enum class ConnectDisconnectStatus {
58     // No AttemptConnection or Disconnect is in progress. The class still
59     // observes changes in the Tether network initiated externally (e.g in OS
60     // Settings), and causes changes to the |status_|.
61     kIdle = 0,
62 
63     // Used in AttemptConnection flow. Enabling the InstantTethering feature as
64     // it was previously disabled.
65     kTurningOnInstantTethering = 1,
66 
67     // Used in AttemptConnection flow. Requesting a scan has has no callback, so
68     // this state is changed upon observing tether network changes or device
69     // changes. If a visible Tether network is observed, the
70     // |connect_disconnect_status_| will change to kConnectingToEligiblePhone.
71     // If a visible Tether network is not observed by the time the Tether device
72     // stops scanning, the |connect_disconnect_status_| will change back to
73     // kIdle.
74     // Note: Calling ScanForAvailableConnection() will not set the
75     // |connect_disconnect_status_| to this value.
76     kScanningForEligiblePhone = 2,
77 
78     // Used in AttemptConnection flow. In the process of connecting to a Tether
79     // Network.
80     kConnectingToEligiblePhone = 3,
81 
82     // Used in Disconnect flow. Disconnects from the tether network.
83     kDisconnecting = 4,
84   };
85 
86   // Connector that uses CrosNetworkConfig to connect, disconnect, and get the
87   // network state list. This class is used for testing purposes.
88   class TetherNetworkConnector {
89    public:
90     using StartConnectCallback = base::OnceCallback<void(
91         network_config::mojom::StartConnectResult result,
92         const std::string& message)>;
93 
94     using StartDisconnectCallback = base::OnceCallback<void(bool)>;
95 
96     using GetNetworkStateListCallback = base::OnceCallback<void(
97         std::vector<network_config::mojom::NetworkStatePropertiesPtr>)>;
98 
99     TetherNetworkConnector();
100     TetherNetworkConnector(const TetherNetworkConnector&) = delete;
101     TetherNetworkConnector& operator=(const TetherNetworkConnector&) = delete;
102     virtual ~TetherNetworkConnector();
103 
104     virtual void StartConnect(const std::string& guid,
105                               StartConnectCallback callback);
106     virtual void StartDisconnect(const std::string& guid,
107                                  StartDisconnectCallback callback);
108     virtual void GetNetworkStateList(
109         network_config::mojom::NetworkFilterPtr filter,
110         GetNetworkStateListCallback callback);
111 
112    private:
113     mojo::Remote<network_config::mojom::CrosNetworkConfig> cros_network_config_;
114   };
115 
116   // Two parameter constructor made available for testing purposes. The one
117   // parameter constructor calls this constructor.
118   TetherControllerImpl(
119       PhoneModel* phone_model,
120       UserActionRecorder* user_action_recorder,
121       multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client,
122       std::unique_ptr<TetherControllerImpl::TetherNetworkConnector> connector);
123 
124   // PhoneModel::Observer:
125   void OnModelChanged() override;
126 
127   // multidevice_setup::MultiDeviceSetupClient::Observer:
128   void OnFeatureStatesChanged(const MultiDeviceSetupClient::FeatureStatesMap&
129                                   feature_states_map) override;
130 
131   // CrosNetworkConfigObserver:
132   void OnActiveNetworksChanged(
133       std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks)
134       override;
OnNetworkStateChanged(chromeos::network_config::mojom::NetworkStatePropertiesPtr network)135   void OnNetworkStateChanged(
136       chromeos::network_config::mojom::NetworkStatePropertiesPtr network)
137       override {}
138   void OnNetworkStateListChanged() override;
139   void OnDeviceStateListChanged() override;
OnVpnProvidersChanged()140   void OnVpnProvidersChanged() override {}
OnNetworkCertificatesChanged()141   void OnNetworkCertificatesChanged() override {}
142 
143   void AttemptTurningOnTethering();
144   void OnSetFeatureEnabled(bool success);
145   void PerformConnectionAttempt();
146   void StartConnect();
147   void OnStartConnectCompleted(network_config::mojom::StartConnectResult result,
148                                const std::string& message);
149   void OnDisconnectCompleted(bool success);
150   void FetchVisibleTetherNetwork();
151   void OnGetDeviceStateList(
152       std::vector<network_config::mojom::DeviceStatePropertiesPtr> devices);
153   void OnVisibleTetherNetworkFetched(
154       std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks);
155   void SetConnectDisconnectStatus(
156       ConnectDisconnectStatus connect_disconnect_status);
157   void UpdateStatus();
158   TetherController::Status ComputeStatus() const;
159 
160   PhoneModel* phone_model_;
161   UserActionRecorder* user_action_recorder_;
162   multidevice_setup::MultiDeviceSetupClient* multidevice_setup_client_;
163   ConnectDisconnectStatus connect_disconnect_status_ =
164       ConnectDisconnectStatus::kIdle;
165   Status status_ = Status::kIneligibleForFeature;
166 
167   network_config::mojom::NetworkStatePropertiesPtr tether_network_;
168 
169   std::unique_ptr<TetherNetworkConnector> connector_;
170   mojo::Receiver<network_config::mojom::CrosNetworkConfigObserver> receiver_{
171       this};
172   mojo::Remote<network_config::mojom::CrosNetworkConfig> cros_network_config_;
173 
174   base::WeakPtrFactory<TetherControllerImpl> weak_ptr_factory_{this};
175 };
176 
177 }  // namespace phonehub
178 }  // namespace chromeos
179 
180 #endif  // CHROMEOS_COMPONENTS_PHONEHUB_TETHER_CONTROLLER_IMPL_H_
181