Chromium Code Reviews| OLD | NEW |
|---|---|
| (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/host_scan_cache.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/memory/ptr_util.h" | |
| 11 #include "chromeos/components/tether/active_host.h" | |
| 12 #include "chromeos/components/tether/device_id_tether_network_guid_map.h" | |
| 13 #include "chromeos/components/tether/tether_host_response_recorder.h" | |
| 14 #include "chromeos/network/network_state_handler.h" | |
| 15 #include "components/proximity_auth/logging/logging.h" | |
| 16 | |
| 17 namespace chromeos { | |
| 18 | |
| 19 namespace tether { | |
| 20 | |
| 21 HostScanCache::TimerFactoryImpl::TimerFactoryImpl() {} | |
| 22 | |
| 23 HostScanCache::TimerFactoryImpl::~TimerFactoryImpl() {} | |
| 24 | |
| 25 std::unique_ptr<base::Timer> | |
| 26 HostScanCache::TimerFactoryImpl::CreateOneShotTimer( | |
| 27 const std::string& tether_network_guid) { | |
| 28 // Note: |tether_network_guid| is ignored and is only used in the | |
| 29 // HostScanCacheTestst. | |
| 30 return base::MakeUnique<base::OneShotTimer>(); | |
| 31 } | |
| 32 | |
| 33 HostScanCache::HostScanCache( | |
| 34 NetworkStateHandler* network_state_handler, | |
| 35 ActiveHost* active_host, | |
| 36 TetherHostResponseRecorder* tether_host_response_recorder, | |
| 37 DeviceIdTetherNetworkGuidMap* device_id_tether_network_guid_map) | |
| 38 : HostScanCache(base::MakeUnique<TimerFactoryImpl>(), | |
| 39 network_state_handler, | |
| 40 active_host, | |
| 41 tether_host_response_recorder, | |
| 42 device_id_tether_network_guid_map) {} | |
| 43 | |
| 44 HostScanCache::HostScanCache( | |
| 45 std::unique_ptr<TimerFactory> timer_factory, | |
| 46 NetworkStateHandler* network_state_handler, | |
| 47 ActiveHost* active_host, | |
| 48 TetherHostResponseRecorder* tether_host_response_recorder, | |
| 49 DeviceIdTetherNetworkGuidMap* device_id_tether_network_guid_map) | |
| 50 : timer_factory_(std::move(timer_factory)), | |
| 51 network_state_handler_(network_state_handler), | |
| 52 active_host_(active_host), | |
| 53 tether_host_response_recorder_(tether_host_response_recorder), | |
| 54 device_id_tether_network_guid_map_(device_id_tether_network_guid_map), | |
| 55 weak_ptr_factory_(this) { | |
| 56 tether_host_response_recorder_->AddObserver(this); | |
| 57 } | |
| 58 | |
| 59 HostScanCache::~HostScanCache() { | |
| 60 tether_host_response_recorder_->RemoveObserver(this); | |
| 61 } | |
| 62 | |
| 63 void HostScanCache::SetHostScanResult(const std::string& tether_network_guid, | |
| 64 const std::string& device_name, | |
| 65 const std::string& carrier, | |
| 66 int battery_percentage, | |
| 67 int signal_strength) { | |
| 68 DCHECK(!tether_network_guid.empty()); | |
| 69 | |
| 70 bool not_in_map = tether_guid_to_timer_map_.find(tether_network_guid) == | |
| 71 tether_guid_to_timer_map_.end(); | |
| 72 | |
| 73 if (not_in_map) { | |
| 74 // Add the Tether network to NetworkStateHandler and create an associated | |
| 75 // Timer. | |
| 76 network_state_handler_->AddTetherNetworkState( | |
| 77 tether_network_guid, device_name, carrier, battery_percentage, | |
| 78 signal_strength, HasConnectedToHost(tether_network_guid)); | |
| 79 tether_guid_to_timer_map_.emplace( | |
|
Ryan Hansberry
2017/04/28 22:31:04
I think it would be clearer to do this in StartTim
Kyle Horimoto
2017/04/28 22:45:04
StartTimer() is also called in the case where the
| |
| 80 tether_network_guid, | |
| 81 timer_factory_->CreateOneShotTimer(tether_network_guid)); | |
| 82 | |
| 83 PA_LOG(INFO) << "Added scan result for Tether network with GUID " | |
| 84 << tether_network_guid << ". Device name: " << device_name | |
| 85 << ", carrier: " << carrier | |
| 86 << ", battery percentage: " << battery_percentage | |
| 87 << ", signal strength: " << signal_strength; | |
| 88 } else { | |
| 89 // Update the existing network and stop the associated Timer. | |
| 90 network_state_handler_->UpdateTetherNetworkProperties( | |
| 91 tether_network_guid, carrier, battery_percentage, signal_strength); | |
| 92 tether_guid_to_timer_map_[tether_network_guid]->Stop(); | |
| 93 | |
| 94 PA_LOG(INFO) << "Updated scan result for Tether network with GUID " | |
| 95 << tether_network_guid << ". New carrier: " << carrier << ", " | |
| 96 << "new battery percentage: " << battery_percentage << ", " | |
| 97 << "new signal strength: " << signal_strength; | |
| 98 } | |
| 99 | |
| 100 StartTimer(tether_network_guid); | |
| 101 } | |
| 102 | |
| 103 bool HostScanCache::RemoveHostScanResult( | |
| 104 const std::string& tether_network_guid) { | |
| 105 DCHECK(!tether_network_guid.empty()); | |
| 106 | |
| 107 auto it = tether_guid_to_timer_map_.find(tether_network_guid); | |
| 108 if (it == tether_guid_to_timer_map_.end()) { | |
| 109 PA_LOG(ERROR) << "Attempted to remove a host scan result which does not " | |
| 110 << "exist in the cache. GUID: " << tether_network_guid; | |
| 111 return false; | |
| 112 } | |
| 113 | |
| 114 if (active_host_->GetTetherNetworkGuid() == tether_network_guid) { | |
| 115 PA_LOG(ERROR) << "RemoveHostScanResult() called for Tether network with " | |
| 116 << "GUID " << tether_network_guid << ", but the " | |
| 117 << "corresponding device is the active host. Not removing " | |
| 118 << "this scan result from the cache."; | |
| 119 return false; | |
| 120 } | |
| 121 | |
| 122 tether_guid_to_timer_map_.erase(it); | |
| 123 return network_state_handler_->RemoveTetherNetworkState(tether_network_guid); | |
| 124 } | |
| 125 | |
| 126 void HostScanCache::ClearCacheExceptForActiveHost() { | |
| 127 // Create a list of all Tether network GUIDs serving as keys to | |
| 128 // |tether_guid_to_timer_map_|. | |
| 129 std::vector<std::string> tether_network_guids; | |
| 130 tether_network_guids.reserve(tether_guid_to_timer_map_.size()); | |
| 131 for (auto& it : tether_guid_to_timer_map_) | |
| 132 tether_network_guids.push_back(it.first); | |
| 133 | |
| 134 std::string active_host_tether_guid = active_host_->GetTetherNetworkGuid(); | |
| 135 if (!active_host_tether_guid.empty()) { | |
| 136 PA_LOG(INFO) << "Clearing all " << tether_guid_to_timer_map_.size() | |
| 137 << "entries from the cache."; | |
| 138 } else { | |
| 139 PA_LOG(INFO) << "Clearing " << (tether_guid_to_timer_map_.size() - 1) << " " | |
| 140 << "of the " << tether_guid_to_timer_map_.size() << " " | |
| 141 << "entries from the cache. Not removing the entry " | |
| 142 << "corresponding to the Tether network with GUID " | |
| 143 << active_host_tether_guid << " because it represents the " | |
| 144 << "active host."; | |
| 145 } | |
| 146 | |
| 147 // Iterate through the keys, removing all scan results not corresponding to | |
| 148 // the active host. Iteration is done via a list of pre-computed keys instead | |
| 149 // if iterating through the map because RemoteHostScanResult() will remove | |
| 150 // key/value pairs from the map, which would invalidate the map iterator. | |
| 151 for (auto& tether_network_guid : tether_network_guids) { | |
| 152 if (active_host_->GetTetherNetworkGuid() == tether_network_guid) { | |
| 153 // Do not remove the active host from the cache. | |
| 154 continue; | |
| 155 } | |
| 156 | |
| 157 RemoveHostScanResult(tether_network_guid); | |
| 158 } | |
| 159 } | |
| 160 | |
| 161 void HostScanCache::OnPreviouslyConnectedHostIdsChanged() { | |
| 162 for (auto& map_entry : tether_guid_to_timer_map_) { | |
| 163 const std::string& tether_network_guid = map_entry.first; | |
| 164 if (HasConnectedToHost(tether_network_guid)) { | |
| 165 // If a the current device has connected to the Tether network with GUID | |
| 166 // |tether_network_guid|, alert |network_state_handler_|. Note that this | |
| 167 // function is a no-op if it is called on a network which already has its | |
| 168 // HasConnectedToHost property set to true. | |
| 169 bool update_successful = | |
| 170 network_state_handler_->SetTetherNetworkHasConnectedToHost( | |
| 171 tether_network_guid); | |
| 172 | |
| 173 if (update_successful) { | |
| 174 PA_LOG(INFO) << "Successfully set the HasConnectedToHost property of " | |
| 175 << "the Tether network with GUID " << tether_network_guid | |
| 176 << " to true."; | |
| 177 } | |
| 178 } | |
| 179 } | |
| 180 } | |
| 181 | |
| 182 bool HostScanCache::HasConnectedToHost(const std::string& tether_network_guid) { | |
| 183 std::string device_id = | |
| 184 device_id_tether_network_guid_map_->GetDeviceIdForTetherNetworkGuid( | |
| 185 tether_network_guid); | |
| 186 std::vector<std::string> connected_device_ids = | |
| 187 tether_host_response_recorder_->GetPreviouslyConnectedHostIds(); | |
| 188 return std::find(connected_device_ids.begin(), connected_device_ids.end(), | |
| 189 device_id) != connected_device_ids.end(); | |
| 190 } | |
| 191 | |
| 192 void HostScanCache::StartTimer(const std::string& tether_network_guid) { | |
| 193 // Check that a Timer exists in |tether_guid_to_timer_map_| and that it is not | |
|
Ryan Hansberry
2017/04/28 22:31:04
nit: This comment isn't really needed.
Kyle Horimoto
2017/04/28 22:45:04
Done.
| |
| 194 // currently running. | |
| 195 DCHECK(!tether_guid_to_timer_map_.find(tether_network_guid) | |
| 196 ->second->IsRunning()); | |
| 197 | |
| 198 PA_LOG(INFO) << "Starting host scan cache timer for Tether network with GUID " | |
| 199 << tether_network_guid << ". Will fire in " | |
| 200 << kNumMinutesBeforeCacheEntryExpires << " minutes."; | |
| 201 | |
| 202 tether_guid_to_timer_map_[tether_network_guid]->Start( | |
| 203 FROM_HERE, | |
| 204 base::TimeDelta::FromMinutes(kNumMinutesBeforeCacheEntryExpires), | |
| 205 base::Bind(&HostScanCache::OnTimerFired, weak_ptr_factory_.GetWeakPtr(), | |
| 206 tether_network_guid)); | |
| 207 } | |
| 208 | |
| 209 void HostScanCache::OnTimerFired(const std::string& tether_network_guid) { | |
| 210 if (active_host_->GetTetherNetworkGuid() == tether_network_guid) { | |
| 211 // Log as a warning. This situation should be uncommon in practice since | |
| 212 // KeepAliveScheduler should schedule a new keep-alive status update every | |
| 213 // 4 minutes. | |
| 214 PA_LOG(WARNING) << "Timer fired for Tether network GUID " | |
| 215 << tether_network_guid << ", but the corresponding device " | |
| 216 << "is the active host. Restarting timer."; | |
| 217 | |
| 218 // If the Timer which fired corresponds to the active host, do not remove | |
| 219 // the cache entry. The active host must always remain in the cache so that | |
| 220 // the UI can reflect that it is the connecting/connected network. In this | |
| 221 // case, just restart the timer. | |
| 222 StartTimer(tether_network_guid); | |
| 223 return; | |
| 224 } | |
| 225 | |
| 226 PA_LOG(INFO) << "Timer fired for Tether network GUID " << tether_network_guid | |
| 227 << ". Removing stale scan result."; | |
| 228 | |
| 229 // Otherwise, the scan resulst are stale. Remove them. | |
| 230 RemoveHostScanResult(tether_network_guid); | |
| 231 } | |
| 232 | |
| 233 } // namespace tether | |
| 234 | |
| 235 } // namespace chromeos | |
| OLD | NEW |