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