OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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/network/network_state_handler.h" | |
6 | |
7 #include <algorithm> | |
pneubeck (no reviews)
2012/10/25 14:42:17
unused?
stevenjb
2012/10/25 22:05:22
Removed
| |
8 | |
9 #include "base/bind.h" | |
10 #include "base/stl_util.h" | |
11 #include "base/string_util.h" | |
12 #include "base/values.h" | |
13 #include "chromeos/dbus/dbus_thread_manager.h" | |
14 #include "chromeos/dbus/shill_device_client.h" | |
15 #include "chromeos/dbus/shill_ipconfig_client.h" | |
16 #include "chromeos/dbus/shill_manager_client.h" | |
17 #include "chromeos/dbus/shill_service_client.h" | |
18 #include "chromeos/network/device_state.h" | |
19 #include "chromeos/network/managed_state.h" | |
20 #include "chromeos/network/network_state.h" | |
21 #include "chromeos/network/network_state_handler_observer.h" | |
22 #include "chromeos/network/network_service_observer.h" | |
23 #include "dbus/object_path.h" | |
24 | |
25 namespace { | |
26 | |
27 void ErrorCallbackFunction(const std::string& error_name, | |
28 const std::string& error_message) { | |
29 // TODO(stevenjb): Add error logging. | |
30 LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message; | |
31 } | |
32 | |
33 const base::ListValue* GetListValue(const std::string& key, | |
34 const base::Value& value) { | |
35 const base::ListValue* vlist = NULL; | |
36 if (!value.GetAsList(&vlist)) { | |
37 LOG(ERROR) << "Error parsing key as list: " << key; | |
38 return NULL; | |
39 } | |
40 return vlist; | |
41 } | |
42 | |
43 } | |
44 | |
45 namespace chromeos { | |
46 | |
47 NetworkStateHandler::NetworkStateHandler() | |
48 : shill_manager_(DBusThreadManager::Get()->GetShillManagerClient()), | |
49 weak_ptr_factory_(this) { | |
50 } | |
51 | |
52 NetworkStateHandler::~NetworkStateHandler() { | |
53 STLDeleteContainerPointers(network_list_.begin(), network_list_.end()); | |
54 // Delete network service observers. | |
55 STLDeleteContainerPairSecondPointers( | |
56 observed_networks_.begin(), observed_networks_.end()); | |
57 CHECK(shill_manager_ == DBusThreadManager::Get()->GetShillManagerClient()); | |
58 shill_manager_->RemovePropertyChangedObserver(this); | |
59 } | |
60 | |
61 void NetworkStateHandler::Init() { | |
62 shill_manager_->GetProperties( | |
63 base::Bind(&NetworkStateHandler::ManagerPropertiesCallback, | |
64 weak_ptr_factory_.GetWeakPtr())); | |
65 shill_manager_->AddPropertyChangedObserver(this); | |
66 } | |
67 | |
68 void NetworkStateHandler::AddObserver(NetworkStateHandlerObserver* observer) { | |
69 observers_.AddObserver(observer); | |
70 } | |
71 | |
72 void NetworkStateHandler::RemoveObserver( | |
73 NetworkStateHandlerObserver* observer) { | |
74 observers_.RemoveObserver(observer); | |
75 } | |
76 | |
77 bool NetworkStateHandler::TechnologyAvailable( | |
78 const std::string& technology) const { | |
79 return available_technologies_.find(technology) != | |
80 available_technologies_.end(); | |
81 } | |
82 | |
83 bool NetworkStateHandler::TechnologyEnabled( | |
84 const std::string& technology) const { | |
85 return enabled_technologies_.find(technology) != | |
86 enabled_technologies_.end(); | |
87 } | |
88 | |
89 void NetworkStateHandler::SetTechnologyEnabled(const std::string& technology, | |
90 bool enabled) { | |
91 if (enabled) { | |
92 shill_manager_->EnableTechnology(technology, | |
93 base::Bind(&base::DoNothing), | |
94 base::Bind(&ErrorCallbackFunction)); | |
95 } else { | |
96 shill_manager_->DisableTechnology(technology, | |
97 base::Bind(&base::DoNothing), | |
98 base::Bind(&ErrorCallbackFunction)); | |
99 } | |
100 } | |
101 | |
102 const DeviceState* NetworkStateHandler::GetDeviceState( | |
103 const std::string& path) const { | |
104 return const_cast<NetworkStateHandler*>(this)->GetModifiableDeviceState(path); | |
pneubeck (no reviews)
2012/10/25 14:42:17
I understand that for public functions. But why wo
stevenjb
2012/10/25 22:05:22
Yeah, I see your point. It seems a bit awkward, bu
| |
105 } | |
106 | |
107 const DeviceState* NetworkStateHandler::GetDeviceStateByType( | |
108 const std::string& type) const { | |
109 for (DeviceStateList::const_iterator iter = device_list_.begin(); | |
110 iter != device_list_.end(); ++iter) { | |
111 const DeviceState* device = *iter; | |
112 if (device->type() == type) | |
113 return device; | |
114 } | |
115 return NULL; | |
116 } | |
117 | |
118 const NetworkState* NetworkStateHandler::GetNetworkState( | |
119 const std::string& path) const { | |
120 return const_cast<NetworkStateHandler*>(this)->GetModifiableNetworkState( | |
121 path); | |
122 } | |
123 | |
124 const NetworkState* NetworkStateHandler::ActiveNetwork() const { | |
125 if (network_list_.empty()) | |
126 return NULL; | |
127 const NetworkState* network = network_list_.front(); | |
128 if (!network->IsConnectedState()) | |
129 return NULL; | |
130 return network; | |
131 } | |
132 | |
133 const NetworkState* NetworkStateHandler::ConnectedNetworkByType( | |
134 const std::string& type) const { | |
135 for (NetworkStateList::const_iterator iter = network_list_.begin(); | |
136 iter != network_list_.end(); ++iter) { | |
137 const NetworkState* network = *iter; | |
138 if (!network->IsConnectedState()) | |
139 break; // Connected networks are listed first. | |
140 if (network->type() == type) | |
141 return network; | |
142 } | |
143 return NULL; | |
144 } | |
145 | |
146 const NetworkState* NetworkStateHandler::ConnectingNetworkByType( | |
147 const std::string& type) const { | |
148 for (NetworkStateList::const_iterator iter = network_list_.begin(); | |
149 iter != network_list_.end(); ++iter) { | |
150 const NetworkState* network = *iter; | |
151 if (network->IsConnectedState()) | |
152 continue; | |
153 if (!network->IsConnectingState()) | |
154 break; // Connected and connecting networks are listed first. | |
155 if (network->type() == type || | |
156 (type.empty() && type != flimflam::kTypeEthernet)) { | |
157 return network; | |
158 } | |
159 } | |
160 return NULL; | |
161 } | |
162 | |
163 std::string NetworkStateHandler::HardwareAddress( | |
164 const std::string& type) const { | |
165 std::string result; | |
166 const NetworkState* network = ConnectedNetworkByType(type); | |
167 if (network) { | |
168 const DeviceState* device = GetDeviceState(network->device_path()); | |
169 if (device) | |
170 result = device->mac_address(); | |
171 } | |
172 StringToUpperASCII(&result); | |
173 return result; | |
174 } | |
175 | |
176 std::string NetworkStateHandler::HardwareAddressFormatted( | |
177 const std::string& type) const { | |
178 std::string address = HardwareAddress(type); | |
179 if (address.size() % 2 != 0) | |
180 return address; | |
181 std::string result; | |
182 for (size_t i = 0; i < address.size(); ++i) { | |
183 if ((i != 0) && (i % 2 == 0)) | |
184 result.push_back(':'); | |
185 result.push_back(address[i]); | |
186 } | |
187 return result; | |
188 } | |
189 | |
190 const NetworkStateHandler::NetworkStateList& | |
191 NetworkStateHandler::GetNetworkList() const { | |
192 RequestScan(); | |
pneubeck (no reviews)
2012/10/25 14:42:17
Why not expose RequestScan publicly and remove it
stevenjb
2012/10/25 22:05:22
We decidedly to explicitly not expose RequestScan.
| |
193 return network_list_; | |
194 } | |
195 | |
196 void NetworkStateHandler::OnPropertyChanged(const std::string& key, | |
197 const base::Value& value) { | |
198 if (ManagerPropertyChanged(key, value)) | |
199 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
200 NetworkManagerChanged(key)); | |
201 } | |
202 | |
203 //------------------------------------------------------------------------------ | |
204 // Private methods | |
205 | |
206 DeviceState* NetworkStateHandler::GetModifiableDeviceState( | |
207 const std::string& path) { | |
208 for (DeviceStateList::iterator iter = device_list_.begin(); | |
209 iter != device_list_.end(); ++iter) { | |
210 DeviceState* device = *iter; | |
211 if (device->path() == path) | |
212 return device; | |
213 } | |
214 return NULL; | |
215 } | |
216 | |
217 NetworkState* NetworkStateHandler::GetModifiableNetworkState( | |
218 const std::string& path) { | |
219 for (NetworkStateList::iterator iter = network_list_.begin(); | |
220 iter != network_list_.end(); ++iter) { | |
221 NetworkState* network = *iter; | |
222 if (network->path() == path) | |
223 return network; | |
224 } | |
225 return NULL; | |
226 } | |
227 | |
228 void NetworkStateHandler::ManagerPropertiesCallback( | |
229 DBusMethodCallStatus call_status, | |
230 const base::DictionaryValue& properties) { | |
231 if (call_status != DBUS_METHOD_CALL_SUCCESS) { | |
232 LOG(ERROR) << "Failed to get Manager properties:" << call_status; | |
233 return; | |
234 } | |
235 bool notify = false; | |
236 for (base::DictionaryValue::key_iterator iter = properties.begin_keys(); | |
pneubeck (no reviews)
2012/10/25 14:42:17
You could use DictionaryValue::Iterator in this ca
stevenjb
2012/10/25 22:05:22
I'd never seen that before. Nice.
Done.
| |
237 iter != properties.end_keys(); ++iter) { | |
238 const std::string& key = *iter; | |
239 const base::Value* value; | |
240 bool res = properties.GetWithoutPathExpansion(key, &value); | |
241 if (res) | |
242 notify |= ManagerPropertyChanged(key, *value); | |
243 else | |
244 LOG(ERROR) << "Error getting value for key: " << key; | |
245 } | |
246 if (notify) { | |
247 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
248 NetworkManagerChanged(std::string())); | |
249 } | |
250 } | |
251 | |
252 bool NetworkStateHandler::ManagerPropertyChanged(const std::string& key, | |
253 const base::Value& value) { | |
254 bool notify_manager_changed = false; | |
255 if (key == flimflam::kServicesProperty) { | |
256 const base::ListValue* vlist = GetListValue(key, value); | |
257 if (vlist) { | |
258 UpdateManagedList(ManagedState::MANAGED_TYPE_NETWORK, *vlist); | |
259 // Do not send an UpdateManagerChanged notification to observers. | |
260 // An UpdateNetworkList notification will be sent when the service list | |
261 // updates have completed. | |
262 } | |
263 } else if (key == flimflam::kDevicesProperty) { | |
264 const ListValue* vlist = GetListValue(key, value); | |
265 if (vlist) { | |
266 UpdateManagedList(ManagedState::MANAGED_TYPE_DEVICE, *vlist); | |
267 notify_manager_changed = true; | |
268 } | |
269 } else if (key == flimflam::kAvailableTechnologiesProperty) { | |
270 const base::ListValue* vlist = GetListValue(key, value); | |
271 if (vlist ) { | |
272 UpdateAvailableTechnologies(*vlist); | |
273 notify_manager_changed = true; | |
274 } | |
275 } else if (key == flimflam::kEnabledTechnologiesProperty) { | |
276 const base::ListValue* vlist = GetListValue(key, value); | |
277 if (vlist) { | |
278 UpdateEnabledTechnologies(*vlist); | |
279 notify_manager_changed = true; | |
280 } | |
281 } | |
282 return notify_manager_changed; | |
283 } | |
284 | |
285 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( | |
286 ManagedState::ManagedType type) { | |
287 // Use reinterpret_cast here to avoid copying the list to a list of identical | |
pneubeck (no reviews)
2012/10/25 14:42:17
Copying a vector<*> of about 10 entries should be
stevenjb
2012/10/25 22:05:22
I have had difficulty stepping through templated f
| |
288 // base class pointers. | |
289 switch(type) { | |
290 case ManagedState::MANAGED_TYPE_NETWORK: | |
291 return reinterpret_cast<ManagedStateList*>(&network_list_); | |
292 case ManagedState::MANAGED_TYPE_DEVICE: | |
293 return reinterpret_cast<ManagedStateList*>(&device_list_); | |
294 } | |
295 return NULL; | |
296 } | |
297 | |
298 void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, | |
299 const base::ListValue& entries) { | |
300 ManagedStateList* managed_list = GetManagedList(type); | |
301 VLOG(2) << "UpdateManagedList: " << type; | |
302 // Create a map of existing entries. | |
303 std::map<std::string, ManagedState*> managed_map; | |
304 for (ManagedStateList::iterator iter = managed_list->begin(); | |
305 iter != managed_list->end(); ++iter) { | |
306 ManagedState* managed = *iter; | |
307 managed_map[managed->path()] = managed; | |
308 } | |
309 // Clear the list (pointers are owned by managed_map). | |
310 managed_list->clear(); | |
311 // Updates managed_list and request updates for new entries. | |
312 for (base::ListValue::const_iterator iter = entries.begin(); | |
313 iter != entries.end(); ++iter) { | |
314 std::string path; | |
315 (*iter)->GetAsString(&path); | |
316 if (path.empty()) | |
317 continue; | |
318 std::map<std::string, ManagedState*>::iterator found = | |
319 managed_map.find(path); | |
320 bool request_properties = false; | |
321 if (found == managed_map.end()) { | |
322 request_properties = true; | |
323 managed_list->push_back(ManagedState::Create(type, path)); | |
324 } else { | |
325 ManagedState* managed = found->second; | |
326 managed_list->push_back(managed); | |
327 managed_map.erase(found); | |
328 } | |
329 if (request_properties) { | |
330 ++pending_updates_[type]; | |
331 RequestProperties(type, path); | |
332 } | |
333 } | |
334 // Delete any remaning entries in managed_map. | |
335 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); | |
336 } | |
337 | |
338 void NetworkStateHandler::UpdateObservedNetworkServices() { | |
339 // Watch any connected or connecting networks. | |
340 NetworkServiceObserverMap new_observed; | |
341 for (NetworkStateList::const_iterator iter = network_list_.begin(); | |
342 iter != network_list_.end(); ++iter) { | |
343 const NetworkState* network = *iter; | |
344 if (!network->IsConnectedState() && !network->IsConnectingState()) | |
pneubeck (no reviews)
2012/10/25 14:42:17
Doesn't this also mean, that we cannot observe e.g
stevenjb
2012/10/25 22:05:22
Shill does not update the strength or other proper
| |
345 break; // Connected and connecting networks are listed first. | |
346 const std::string& path = network->path(); | |
347 NetworkServiceObserverMap::iterator iter = observed_networks_.find(path); | |
348 if (iter != observed_networks_.end()) { | |
349 new_observed[path] = observed_networks_[path]; | |
350 } else { | |
351 new_observed[path] = new NetworkServiceObserver( | |
352 path, base::Bind(&NetworkStateHandler::NetworkServicePropertyChanged, | |
353 weak_ptr_factory_.GetWeakPtr())); | |
354 } | |
355 observed_networks_.erase(path); | |
356 } | |
357 VLOG(2) << "UpdateObservedNetworkServices, new observed: " | |
358 << new_observed.size(); | |
359 // Delete network service observers still in observed_networks_. | |
360 STLDeleteContainerPairSecondPointers( | |
361 observed_networks_.begin(), observed_networks_.end()); | |
362 observed_networks_.swap(new_observed); | |
363 // Notify observers that the list of networks has changed. | |
364 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
365 NetworkListChanged(network_list_)); | |
366 // Notify observers if the active network has changed. | |
367 const NetworkState* new_active_network = | |
368 network_list_.empty() ? NULL : network_list_.front(); | |
369 if (new_active_network->path() != active_network_path_) { | |
370 active_network_path_ = new_active_network->path(); | |
371 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
372 ActiveNetworkChanged(new_active_network)); | |
373 } | |
374 } | |
375 | |
376 void NetworkStateHandler::UpdateAvailableTechnologies( | |
377 const base::ListValue& technologies) { | |
378 available_technologies_.clear(); | |
379 for (base::ListValue::const_iterator iter = technologies.begin(); | |
380 iter != technologies.end(); ++iter) { | |
381 std::string technology; | |
382 (*iter)->GetAsString(&technology); | |
383 if (technology.empty()) | |
384 continue; | |
385 available_technologies_.insert(technology); | |
386 } | |
387 } | |
388 | |
389 void NetworkStateHandler::UpdateEnabledTechnologies( | |
390 const base::ListValue& technologies) { | |
391 enabled_technologies_.clear(); | |
392 for (base::ListValue::const_iterator iter = technologies.begin(); | |
393 iter != technologies.end(); ++iter) { | |
394 std::string technology; | |
395 (*iter)->GetAsString(&technology); | |
396 if (technology.empty()) | |
397 continue; | |
398 enabled_technologies_.insert(technology); | |
399 } | |
400 } | |
401 | |
402 void NetworkStateHandler::RequestProperties(ManagedState::ManagedType type, | |
403 const std::string& path) { | |
404 switch(type) { | |
405 case ManagedState::MANAGED_TYPE_NETWORK: | |
406 DBusThreadManager::Get()->GetShillServiceClient()->GetProperties( | |
407 dbus::ObjectPath(path), | |
408 base::Bind(&NetworkStateHandler::GetPropertiesCallback, | |
409 weak_ptr_factory_.GetWeakPtr(), | |
410 type, path)); | |
411 break; | |
412 case ManagedState::MANAGED_TYPE_DEVICE: | |
413 DBusThreadManager::Get()->GetShillDeviceClient()->GetProperties( | |
414 dbus::ObjectPath(path), | |
415 base::Bind(&NetworkStateHandler::GetPropertiesCallback, | |
416 weak_ptr_factory_.GetWeakPtr(), | |
417 type, path)); | |
418 break; | |
419 } | |
420 } | |
421 | |
422 void NetworkStateHandler::GetPropertiesCallback( | |
423 ManagedState::ManagedType type, | |
424 const std::string& path, | |
425 DBusMethodCallStatus call_status, | |
426 const base::DictionaryValue& properties) { | |
427 VLOG(2) << "GetPropertiesCallback: " << type << " : " << path; | |
428 --pending_updates_[type]; | |
429 if (call_status != DBUS_METHOD_CALL_SUCCESS) { | |
430 LOG(ERROR) << "Failed to get properties for: " << path | |
431 << ": " << call_status; | |
432 return; | |
433 } | |
434 bool found = false; | |
435 ManagedStateList* list = GetManagedList(type); | |
436 for (ManagedStateList::iterator iter = list->begin(); | |
pneubeck (no reviews)
2012/10/25 14:42:17
Here, you could use
ManagedState* managed = GetMod
stevenjb
2012/10/25 22:05:22
I've been trying to keep Type specific code out of
| |
437 iter != list->end(); ++iter) { | |
438 ManagedState* managed = *iter; | |
439 if (managed->path() == path) { | |
440 ParseProperties(managed, properties); | |
441 found = true; | |
442 break; | |
443 } | |
444 } | |
445 if (!found) | |
446 LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!"; | |
447 // Notify observers only when all updates for that type have completed. | |
448 if (type == ManagedState::MANAGED_TYPE_NETWORK && | |
449 pending_updates_[type] == 0) { | |
450 UpdateObservedNetworkServices(); | |
451 } | |
452 } | |
453 | |
454 void NetworkStateHandler::ParseProperties( | |
455 ManagedState* managed, | |
456 const base::DictionaryValue& properties) { | |
457 for (base::DictionaryValue::key_iterator iter = properties.begin_keys(); | |
pneubeck (no reviews)
2012/10/25 14:42:17
DictionaryValue::Iterator
stevenjb
2012/10/25 22:05:22
Done.
| |
458 iter != properties.end_keys(); ++iter) { | |
459 bool success = false; | |
460 const std::string& key = *iter; | |
461 // Handle IPConfig here since it requires additional complexity that is | |
462 // better handled here than in NetworkService::PropertyChanged (e.g. | |
pneubeck (no reviews)
2012/10/25 14:42:17
NetworkState::PropertyChanged?
stevenjb
2012/10/25 22:05:22
Done.
| |
463 // observer notification). | |
464 if (key == shill::kIPConfigProperty) { | |
465 DCHECK(managed->managed_type() == ManagedState::MANAGED_TYPE_NETWORK); | |
466 std::string ip_config_path; | |
467 if (properties.GetStringWithoutPathExpansion(key, &ip_config_path)) { | |
468 DBusThreadManager::Get()->GetShillIPConfigClient()->GetProperties( | |
pneubeck (no reviews)
2012/10/25 14:42:17
This means, that the state can even be inconsisten
stevenjb
2012/10/25 22:05:22
That's always true; shill will send us single prop
| |
469 dbus::ObjectPath(ip_config_path), | |
470 base::Bind(&NetworkStateHandler::GetIPConfigCallback, | |
471 weak_ptr_factory_.GetWeakPtr(), | |
472 managed->path())); | |
473 success = true; | |
474 } | |
475 } else { | |
476 const base::Value* value; | |
477 if (properties.GetWithoutPathExpansion(key, &value)) | |
478 success = managed->PropertyChanged(key, *value); | |
479 } | |
480 if (!success) | |
481 LOG(ERROR) << "Error getting value for key: " << key; | |
482 } | |
483 } | |
484 | |
485 void NetworkStateHandler::NetworkServicePropertyChanged( | |
486 const std::string& path, | |
487 const std::string& key, | |
488 const base::Value& value) { | |
489 NetworkState* network = GetModifiableNetworkState(path); | |
490 if (!network) | |
491 return; | |
492 if (network->PropertyChanged(key, value)) { | |
493 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
494 NetworkServicePropertyChanged(network, key)); | |
495 if (network == network_list_.front() && key == flimflam::kStateProperty) { | |
496 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
497 ActiveNetworkStateChanged(network)); | |
498 } | |
499 } | |
500 } | |
501 | |
502 void NetworkStateHandler::GetIPConfigCallback( | |
503 const std::string& path, | |
pneubeck (no reviews)
2012/10/25 14:42:17
this could be both ipconfig path or service path,
stevenjb
2012/10/25 22:05:22
Done.
| |
504 DBusMethodCallStatus call_status, | |
505 const base::DictionaryValue& properties) { | |
506 if (call_status != DBUS_METHOD_CALL_SUCCESS) { | |
507 LOG(ERROR) << "Failed to get IP properties for: " << path; | |
508 return; | |
509 } | |
510 bool success = false; | |
511 for (base::DictionaryValue::key_iterator iter = properties.begin_keys(); | |
pneubeck (no reviews)
2012/10/25 14:42:17
DictionaryValue::Iterator
stevenjb
2012/10/25 22:05:22
Actually, no need to iterate, this can just be pro
| |
512 iter != properties.end_keys(); ++iter) { | |
513 const std::string& key = *iter; | |
514 if (key == flimflam::kAddressProperty) { | |
515 std::string ip_config; | |
516 properties.GetStringWithoutPathExpansion(key, &ip_config); | |
517 NetworkState* network = GetModifiableNetworkState(path); | |
518 if (network) { | |
519 network->set_ip_config(ip_config); | |
520 success = true; | |
521 } | |
522 break; | |
523 } | |
524 } | |
525 if (success) { | |
526 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, | |
527 NetworkManagerChanged(shill::kIPConfigProperty)); | |
528 } | |
529 } | |
530 | |
531 void NetworkStateHandler::RequestScan() const { | |
532 if (TechnologyEnabled(flimflam::kTypeWifi)) { | |
533 shill_manager_->RequestScan(flimflam::kTypeWifi, | |
pneubeck (no reviews)
2012/10/25 14:42:17
According to manager-api.txt you can simply use ""
stevenjb
2012/10/25 22:05:22
Ah, that's new. This was copied from NetworkLibrar
| |
534 base::Bind(&base::DoNothing), | |
535 base::Bind(&ErrorCallbackFunction)); | |
536 } | |
537 if (TechnologyEnabled(flimflam::kTypeWimax)) { | |
538 shill_manager_->RequestScan(flimflam::kTypeWimax, | |
539 base::Bind(&base::DoNothing), | |
540 base::Bind(&ErrorCallbackFunction)); | |
541 } | |
542 } | |
543 | |
544 } // namespace chromeos | |
OLD | NEW |