Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: chromeos/components/tether/tether_disconnector.cc

Issue 2857853005: [CrOS Tether] Create TetherDisconnector, which disconnects from active tethering sessions. (Closed)
Patch Set: Test updated. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 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 #include "chromeos/components/tether/tether_disconnector.h"
6
7 #include "base/values.h"
8 #include "chromeos/components/tether/active_host.h"
9 #include "chromeos/components/tether/device_id_tether_network_guid_map.h"
10 #include "chromeos/components/tether/network_configuration_remover.h"
11 #include "chromeos/components/tether/tether_connector.h"
12 #include "chromeos/components/tether/tether_host_fetcher.h"
13 #include "chromeos/network/network_connection_handler.h"
14 #include "chromeos/network/network_state.h"
15 #include "chromeos/network/network_state_handler.h"
16 #include "components/proximity_auth/logging/logging.h"
17
18 namespace chromeos {
19
20 namespace tether {
21
22 TetherDisconnector::DisconnectCallbacks::DisconnectCallbacks(
23 const base::Closure& success_callback,
24 const network_handler::StringResultCallback& error_callback)
25 : success_callback(success_callback), error_callback(error_callback) {}
26
27 TetherDisconnector::DisconnectCallbacks::~DisconnectCallbacks() {}
28
29 TetherDisconnector::DisconnectCallbacks::DisconnectCallbacks(
30 const DisconnectCallbacks& other)
31 : success_callback(other.success_callback),
32 error_callback(other.error_callback) {}
33
34 TetherDisconnector::TetherDisconnector(
35 NetworkConnectionHandler* network_connection_handler,
36 NetworkStateHandler* network_state_handler,
37 ActiveHost* active_host,
38 BleConnectionManager* ble_connection_manager,
39 NetworkConfigurationRemover* network_configuration_remover,
40 TetherConnector* tether_connector,
41 DeviceIdTetherNetworkGuidMap* device_id_tether_network_guid_map,
42 TetherHostFetcher* tether_host_fetcher)
43 : network_connection_handler_(network_connection_handler),
44 network_state_handler_(network_state_handler),
45 active_host_(active_host),
46 ble_connection_manager_(ble_connection_manager),
47 network_configuration_remover_(network_configuration_remover),
48 tether_connector_(tether_connector),
49 device_id_tether_network_guid_map_(device_id_tether_network_guid_map),
50 tether_host_fetcher_(tether_host_fetcher),
51 weak_ptr_factory_(this) {}
52
53 TetherDisconnector::~TetherDisconnector() {
54 for (auto& it : device_id_to_operations_map_) {
55 it.second->RemoveObserver(this);
56 }
57 }
58
59 void TetherDisconnector::DisconnectFromNetwork(
60 const std::string& tether_network_guid,
61 const base::Closure& success_callback,
62 const network_handler::StringResultCallback& error_callback) {
63 DCHECK(!tether_network_guid.empty());
64
65 ActiveHost::ActiveHostStatus status = active_host_->GetActiveHostStatus();
66 std::string active_tether_network_guid = active_host_->GetTetherNetworkGuid();
67 std::string active_wifi_network_guid = active_host_->GetWifiNetworkGuid();
68
69 if (status == ActiveHost::ActiveHostStatus::DISCONNECTED) {
70 PA_LOG(ERROR) << "Disconnect requested for Tether network with GUID "
71 << tether_network_guid << ", but no device is connected.";
72 error_callback.Run(NetworkConnectionHandler::kErrorNotConnected);
73 return;
74 }
75
76 if (tether_network_guid != active_tether_network_guid) {
77 PA_LOG(ERROR) << "Disconnect requested for Tether network with GUID "
78 << tether_network_guid << ", but that device is not the "
79 << "active host.";
80 error_callback.Run(NetworkConnectionHandler::kErrorNotConnected);
81 return;
82 }
83
84 if (status == ActiveHost::ActiveHostStatus::CONNECTING) {
85 // Note: CancelConnectionAttempt() internally sets the active host to be
86 // disconnected.
87 if (tether_connector_->CancelConnectionAttempt(tether_network_guid)) {
88 PA_LOG(INFO) << "Disconnect requested for Tether network with GUID "
89 << tether_network_guid << ", which had not yet connected. "
90 << "Canceled in-progress connection attempt.";
91 success_callback.Run();
92 return;
93 }
94
95 PA_LOG(ERROR) << "Disconnect requested for Tether network with GUID "
96 << tether_network_guid << " (not yet connected), but "
97 << "canceling connection attempt failed.";
98 error_callback.Run(NetworkConnectionHandler::kErrorDisconnectFailed);
99 return;
100 }
101
102 DCHECK(!active_wifi_network_guid.empty());
103 DisconnectActiveWifiConnection(tether_network_guid, active_wifi_network_guid,
104 success_callback, error_callback);
105 }
106
107 void TetherDisconnector::DisconnectActiveWifiConnection(
108 const std::string& tether_network_guid,
109 const std::string& wifi_network_guid,
110 const base::Closure& success_callback,
111 const network_handler::StringResultCallback& error_callback) {
112 // First, disconnect the active host so that the user gets visual indication
113 // that the disconnection is in progress as quickly as possible.
114 // TODO(hansberry): This will result in the Tether network becoming
115 // disconnected, but the Wi-Fi network will still be connected until the
116 // DisconnectNetwork() call below completes. This will result in a jarring UI
117 // transition which needs to be fixed.
118 active_host_->SetActiveHostDisconnected();
119
120 const NetworkState* wifi_network_state =
121 network_state_handler_->GetNetworkStateFromGuid(wifi_network_guid);
122 if (wifi_network_state) {
123 // Cache the callbacks in |wifi_guid_to_callbacks_map_|. The disconnection
124 // process is asynchronous, so these callbacks must be saved until the
125 // disconnection is complete.
126 wifi_guid_to_callbacks_map_.emplace(
127 wifi_network_guid,
128 DisconnectCallbacks(success_callback, error_callback));
129 network_connection_handler_->DisconnectNetwork(
130 wifi_network_state->path(),
131 base::Bind(&TetherDisconnector::OnSuccessfulWifiDisconnect,
132 weak_ptr_factory_.GetWeakPtr(), wifi_network_guid),
133 base::Bind(&TetherDisconnector::OnFailedWifiDisconnect,
134 weak_ptr_factory_.GetWeakPtr(), wifi_network_guid));
135 } else {
136 PA_LOG(ERROR) << "Wi-Fi NetworkState for GUID " << wifi_network_guid << " "
137 << "was not registered. Cannot disconnect.";
138 error_callback.Run(NetworkConnectionHandler::kErrorDisconnectFailed);
139 }
140
141 // In addition to disconnecting from the Wi-Fi network, this device must also
142 // send a DisconnectTetheringRequest to the tether host so that it can shut
143 // down its Wi-Fi hotspot if it is no longer in use.
144 const std::string device_id =
145 device_id_tether_network_guid_map_->GetDeviceIdForTetherNetworkGuid(
146 tether_network_guid);
147 tether_host_fetcher_->FetchTetherHost(
148 device_id, base::Bind(&TetherDisconnector::OnTetherHostFetched,
149 weak_ptr_factory_.GetWeakPtr(), device_id));
150 }
151
152 void TetherDisconnector::OnOperationFinished(const std::string& device_id,
153 bool success) {
154 if (success) {
155 PA_LOG(INFO) << "Successfully sent DisconnectTetheringRequest to device "
156 << "with ID "
157 << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id);
158 } else {
159 PA_LOG(ERROR) << "Failed to send DisconnectTetheringRequest to device "
160 << "with ID "
161 << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(
162 device_id);
163 }
164
165 // Regardless of success/failure, unregister as a listener and delete the
166 // operation.
167 auto it = device_id_to_operations_map_.find(device_id);
168 DCHECK(it != device_id_to_operations_map_.end());
169 it->second->RemoveObserver(this);
170 device_id_to_operations_map_.erase(it);
171 }
172
173 void TetherDisconnector::OnSuccessfulWifiDisconnect(
174 const std::string& wifi_network_guid) {
175 PA_LOG(INFO) << "Successfully disconnected from Wi-Fi network with GUID "
176 << wifi_network_guid << ".";
177 CleanUpAfterWifiDisconnection(true /* success */, wifi_network_guid);
178 }
179
180 void TetherDisconnector::OnFailedWifiDisconnect(
181 const std::string& wifi_network_guid,
182 const std::string& error_name,
183 std::unique_ptr<base::DictionaryValue> error_data) {
184 PA_LOG(ERROR) << "Failed to disconnect from Wi-Fi network with GUID "
185 << wifi_network_guid << ". Error name: " << error_name;
186 CleanUpAfterWifiDisconnection(false /* success */, wifi_network_guid);
187 }
188
189 void TetherDisconnector::CleanUpAfterWifiDisconnection(
190 bool success,
191 const std::string& wifi_network_guid) {
192 auto it = wifi_guid_to_callbacks_map_.find(wifi_network_guid);
193 DCHECK(it != wifi_guid_to_callbacks_map_.end());
194
195 if (success)
196 it->second.success_callback.Run();
197 else {
198 it->second.error_callback.Run(
199 NetworkConnectionHandler::kErrorDisconnectFailed);
200 }
201
202 wifi_guid_to_callbacks_map_.erase(wifi_network_guid);
203 network_configuration_remover_->RemoveNetworkConfiguration(wifi_network_guid);
204 }
205
206 void TetherDisconnector::OnTetherHostFetched(
207 const std::string& device_id,
208 std::unique_ptr<cryptauth::RemoteDevice> tether_host) {
209 if (!tether_host) {
210 PA_LOG(ERROR) << "Could not fetch device with ID "
211 << cryptauth::RemoteDevice::TruncateDeviceIdForLogs(device_id)
212 << ". Unable to send DisconnectTetheringRequest.";
213 return;
214 }
215
216 std::unique_ptr<DisconnectTetheringOperation> operation =
217 DisconnectTetheringOperation::Factory::NewInstance(
218 *tether_host, ble_connection_manager_);
219 // Start the operation; OnOperationFinished() will be called when finished.
220 operation->AddObserver(this);
221 operation->Initialize();
222 device_id_to_operations_map_.emplace(device_id, std::move(operation));
223 }
224
225 } // namespace tether
226
227 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698