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. | |
stevenjb
2017/05/01 18:26:11
s/Testst/Tests/
Also... yuck. We're adding complex
Kyle Horimoto
2017/05/01 21:14:43
Done.
| |
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(); | |
stevenjb
2017/05/01 18:26:11
No need for local
Kyle Horimoto
2017/05/01 21:14:43
Done.
| |
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( | |
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(); | |
stevenjb
2017/05/01 18:26:11
You're doing an extra lookup here. Instead set an
Kyle Horimoto
2017/05/01 21:14:43
Done.
| |
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()) { | |
stevenjb
2017/05/01 18:26:11
Invert logic?
Kyle Horimoto
2017/05/01 21:14:43
Done.
| |
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)) { | |
stevenjb
2017/05/01 18:26:11
Invert and continue
Kyle Horimoto
2017/05/01 21:14:43
Done.
| |
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 DCHECK(!tether_guid_to_timer_map_.find(tether_network_guid) | |
194 ->second->IsRunning()); | |
195 | |
196 PA_LOG(INFO) << "Starting host scan cache timer for Tether network with GUID " | |
197 << tether_network_guid << ". Will fire in " | |
198 << kNumMinutesBeforeCacheEntryExpires << " minutes."; | |
199 | |
200 tether_guid_to_timer_map_[tether_network_guid]->Start( | |
stevenjb
2017/05/01 18:26:11
Duplicate lookup in DCHECK. (Less critical, but st
Kyle Horimoto
2017/05/01 21:14:43
Done.
| |
201 FROM_HERE, | |
202 base::TimeDelta::FromMinutes(kNumMinutesBeforeCacheEntryExpires), | |
203 base::Bind(&HostScanCache::OnTimerFired, weak_ptr_factory_.GetWeakPtr(), | |
204 tether_network_guid)); | |
205 } | |
206 | |
207 void HostScanCache::OnTimerFired(const std::string& tether_network_guid) { | |
208 if (active_host_->GetTetherNetworkGuid() == tether_network_guid) { | |
209 // Log as a warning. This situation should be uncommon in practice since | |
210 // KeepAliveScheduler should schedule a new keep-alive status update every | |
211 // 4 minutes. | |
212 PA_LOG(WARNING) << "Timer fired for Tether network GUID " | |
213 << tether_network_guid << ", but the corresponding device " | |
214 << "is the active host. Restarting timer."; | |
215 | |
216 // If the Timer which fired corresponds to the active host, do not remove | |
217 // the cache entry. The active host must always remain in the cache so that | |
218 // the UI can reflect that it is the connecting/connected network. In this | |
219 // case, just restart the timer. | |
220 StartTimer(tether_network_guid); | |
221 return; | |
222 } | |
223 | |
224 PA_LOG(INFO) << "Timer fired for Tether network GUID " << tether_network_guid | |
225 << ". Removing stale scan result."; | |
226 RemoveHostScanResult(tether_network_guid); | |
227 } | |
228 | |
229 } // namespace tether | |
230 | |
231 } // namespace chromeos | |
OLD | NEW |