network_state_handler.cc revision 7d4cd473f85ac64c3747c96c277f9e506a0d2246
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 "base/bind.h" 8#include "base/format_macros.h" 9#include "base/location.h" 10#include "base/stl_util.h" 11#include "base/strings/string_util.h" 12#include "base/strings/stringprintf.h" 13#include "base/values.h" 14#include "chromeos/network/device_state.h" 15#include "chromeos/network/managed_state.h" 16#include "chromeos/network/network_event_log.h" 17#include "chromeos/network/network_state.h" 18#include "chromeos/network/network_state_handler_observer.h" 19#include "chromeos/network/shill_property_handler.h" 20#include "third_party/cros_system_api/dbus/service_constants.h" 21 22namespace { 23 24// Returns true if |network->type()| == |match_type|, or it matches one of the 25// following special match types: 26// * kMatchTypeDefault matches any network (i.e. the first instance) 27// * kMatchTypeNonVirtual matches non virtual networks 28// * kMatchTypeWireless matches wireless networks 29// * kMatchTypeMobile matches cellular or wimax networks 30bool ManagedStateMatchesType(const chromeos::ManagedState* managed, 31 const std::string& match_type) { 32 const std::string& type = managed->type(); 33 if (match_type == chromeos::NetworkStateHandler::kMatchTypeDefault) 34 return true; 35 if (match_type == type) 36 return true; 37 if (match_type == chromeos::NetworkStateHandler::kMatchTypeNonVirtual && 38 type != flimflam::kTypeVPN) { 39 return true; 40 } 41 if (match_type == chromeos::NetworkStateHandler::kMatchTypeWireless && 42 type != flimflam::kTypeEthernet && type != flimflam::kTypeVPN) { 43 return true; 44 } 45 if (match_type == chromeos::NetworkStateHandler::kMatchTypeMobile && 46 (type == flimflam::kTypeCellular || type == flimflam::kTypeWimax)) { 47 return true; 48 } 49 return false; 50} 51 52bool ConnectionStateChanged(chromeos::NetworkState* network, 53 const std::string& prev_connection_state) { 54 return (network->connection_state() != prev_connection_state) && 55 (network->connection_state() != flimflam::kStateIdle || 56 !prev_connection_state.empty()); 57} 58 59std::string GetManagedStateLogName(const chromeos::ManagedState* state) { 60 if (!state) 61 return "None"; 62 return base::StringPrintf("%s (%s)", state->name().c_str(), 63 state->path().c_str()); 64} 65 66} // namespace 67 68namespace chromeos { 69 70const char NetworkStateHandler::kMatchTypeDefault[] = "default"; 71const char NetworkStateHandler::kMatchTypeWireless[] = "wireless"; 72const char NetworkStateHandler::kMatchTypeMobile[] = "mobile"; 73const char NetworkStateHandler::kMatchTypeNonVirtual[] = "non-virtual"; 74const char NetworkStateHandler::kDefaultCheckPortalList[] = 75 "ethernet,wifi,cellular"; 76 77NetworkStateHandler::NetworkStateHandler() { 78} 79 80NetworkStateHandler::~NetworkStateHandler() { 81 STLDeleteContainerPointers(network_list_.begin(), network_list_.end()); 82 STLDeleteContainerPointers(device_list_.begin(), device_list_.end()); 83} 84 85void NetworkStateHandler::InitShillPropertyHandler() { 86 shill_property_handler_.reset(new internal::ShillPropertyHandler(this)); 87 shill_property_handler_->Init(); 88} 89 90// static 91NetworkStateHandler* NetworkStateHandler::InitializeForTest() { 92 NetworkStateHandler* handler = new NetworkStateHandler(); 93 handler->InitShillPropertyHandler(); 94 return handler; 95} 96 97void NetworkStateHandler::AddObserver( 98 NetworkStateHandlerObserver* observer, 99 const tracked_objects::Location& from_here) { 100 observers_.AddObserver(observer); 101 network_event_log::internal::AddEntry( 102 from_here.file_name(), from_here.line_number(), 103 network_event_log::LOG_LEVEL_DEBUG, 104 "NetworkStateHandler::AddObserver", ""); 105} 106 107void NetworkStateHandler::RemoveObserver( 108 NetworkStateHandlerObserver* observer, 109 const tracked_objects::Location& from_here) { 110 observers_.RemoveObserver(observer); 111 network_event_log::internal::AddEntry( 112 from_here.file_name(), from_here.line_number(), 113 network_event_log::LOG_LEVEL_DEBUG, 114 "NetworkStateHandler::RemoveObserver", ""); 115} 116 117NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState( 118 const std::string& type) const { 119 std::string technology = GetTechnologyForType(type); 120 TechnologyState state; 121 if (shill_property_handler_->IsTechnologyEnabled(technology)) 122 state = TECHNOLOGY_ENABLED; 123 else if (shill_property_handler_->IsTechnologyEnabling(technology)) 124 state = TECHNOLOGY_ENABLING; 125 else if (shill_property_handler_->IsTechnologyUninitialized(technology)) 126 state = TECHNOLOGY_UNINITIALIZED; 127 else if (shill_property_handler_->IsTechnologyAvailable(technology)) 128 state = TECHNOLOGY_AVAILABLE; 129 else 130 state = TECHNOLOGY_UNAVAILABLE; 131 VLOG(2) << "GetTechnologyState: " << type << " = " << state; 132 return state; 133} 134 135void NetworkStateHandler::SetTechnologyEnabled( 136 const std::string& type, 137 bool enabled, 138 const network_handler::ErrorCallback& error_callback) { 139 std::string technology = GetTechnologyForType(type); 140 NET_LOG_USER("SetTechnologyEnabled", 141 base::StringPrintf("%s:%d", technology.c_str(), enabled)); 142 shill_property_handler_->SetTechnologyEnabled( 143 technology, enabled, error_callback); 144 // Signal Technology state changed -> ENABLING 145 NotifyManagerPropertyChanged(); 146} 147 148const DeviceState* NetworkStateHandler::GetDeviceState( 149 const std::string& device_path) const { 150 return GetModifiableDeviceState(device_path); 151} 152 153const DeviceState* NetworkStateHandler::GetDeviceStateByType( 154 const std::string& type) const { 155 for (ManagedStateList::const_iterator iter = device_list_.begin(); 156 iter != device_list_.end(); ++iter) { 157 ManagedState* device = *iter; 158 if (ManagedStateMatchesType(device, type)) 159 return device->AsDeviceState(); 160 } 161 return NULL; 162} 163 164bool NetworkStateHandler::GetScanningByType(const std::string& type) const { 165 for (ManagedStateList::const_iterator iter = device_list_.begin(); 166 iter != device_list_.end(); ++iter) { 167 const DeviceState* device = (*iter)->AsDeviceState(); 168 DCHECK(device); 169 if (ManagedStateMatchesType(device, type) && device->scanning()) 170 return true; 171 } 172 return false; 173} 174 175const NetworkState* NetworkStateHandler::GetNetworkState( 176 const std::string& service_path) const { 177 return GetModifiableNetworkState(service_path); 178} 179 180const NetworkState* NetworkStateHandler::DefaultNetwork() const { 181 if (network_list_.empty()) 182 return NULL; 183 const NetworkState* network = network_list_.front()->AsNetworkState(); 184 DCHECK(network); 185 if (!network->IsConnectedState()) 186 return NULL; 187 return network; 188} 189 190const NetworkState* NetworkStateHandler::ConnectedNetworkByType( 191 const std::string& type) const { 192 for (ManagedStateList::const_iterator iter = network_list_.begin(); 193 iter != network_list_.end(); ++iter) { 194 const NetworkState* network = (*iter)->AsNetworkState(); 195 DCHECK(network); 196 if (!network->IsConnectedState()) 197 break; // Connected networks are listed first. 198 if (ManagedStateMatchesType(network, type)) 199 return network; 200 } 201 return NULL; 202} 203 204const NetworkState* NetworkStateHandler::ConnectingNetworkByType( 205 const std::string& type) const { 206 for (ManagedStateList::const_iterator iter = network_list_.begin(); 207 iter != network_list_.end(); ++iter) { 208 const NetworkState* network = (*iter)->AsNetworkState(); 209 DCHECK(network); 210 if (network->IsConnectedState()) 211 continue; 212 if (!network->IsConnectingState()) 213 break; // Connected and connecting networks are listed first. 214 if (ManagedStateMatchesType(network, type)) 215 return network; 216 } 217 return NULL; 218} 219 220const NetworkState* NetworkStateHandler::FirstNetworkByType( 221 const std::string& type) const { 222 for (ManagedStateList::const_iterator iter = network_list_.begin(); 223 iter != network_list_.end(); ++iter) { 224 const NetworkState* network = (*iter)->AsNetworkState(); 225 DCHECK(network); 226 if (ManagedStateMatchesType(network, type)) 227 return network; 228 } 229 return NULL; 230} 231 232std::string NetworkStateHandler::HardwareAddressForType( 233 const std::string& type) const { 234 std::string result; 235 const NetworkState* network = ConnectedNetworkByType(type); 236 if (network) { 237 const DeviceState* device = GetDeviceState(network->device_path()); 238 if (device) 239 result = device->mac_address(); 240 } 241 StringToUpperASCII(&result); 242 return result; 243} 244 245std::string NetworkStateHandler::FormattedHardwareAddressForType( 246 const std::string& type) const { 247 std::string address = HardwareAddressForType(type); 248 if (address.size() % 2 != 0) 249 return address; 250 std::string result; 251 for (size_t i = 0; i < address.size(); ++i) { 252 if ((i != 0) && (i % 2 == 0)) 253 result.push_back(':'); 254 result.push_back(address[i]); 255 } 256 return result; 257} 258 259void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const { 260 DCHECK(list); 261 NetworkStateList result; 262 list->clear(); 263 for (ManagedStateList::const_iterator iter = network_list_.begin(); 264 iter != network_list_.end(); ++iter) { 265 const NetworkState* network = (*iter)->AsNetworkState(); 266 DCHECK(network); 267 list->push_back(network); 268 } 269} 270 271void NetworkStateHandler::RequestScan() const { 272 NET_LOG_USER("RequestScan", ""); 273 shill_property_handler_->RequestScan(); 274} 275 276void NetworkStateHandler::WaitForScan(const std::string& type, 277 const base::Closure& callback) { 278 scan_complete_callbacks_[type].push_back(callback); 279 if (!GetScanningByType(type)) 280 RequestScan(); 281} 282 283void NetworkStateHandler::ConnectToBestWifiNetwork() { 284 NET_LOG_USER("ConnectToBestWifiNetwork", ""); 285 WaitForScan(flimflam::kTypeWifi, 286 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices, 287 shill_property_handler_->AsWeakPtr())); 288} 289 290bool NetworkStateHandler::RequestUpdateForNetwork( 291 const std::string& service_path) { 292 NetworkState* network = GetModifiableNetworkState(service_path); 293 if (!network) 294 return false; // Only request an update for known networks. 295 network->set_update_requested(true); 296 NET_LOG_EVENT("RequestUpdate", service_path); 297 shill_property_handler_->RequestProperties( 298 ManagedState::MANAGED_TYPE_NETWORK, service_path); 299 return true; 300} 301 302void NetworkStateHandler::RequestUpdateForAllNetworks() { 303 NET_LOG_EVENT("RequestUpdateForAllNetworks", ""); 304 for (ManagedStateList::iterator iter = network_list_.begin(); 305 iter != network_list_.end(); ++iter) { 306 ManagedState* network = *iter; 307 network->set_update_requested(true); 308 shill_property_handler_->RequestProperties( 309 ManagedState::MANAGED_TYPE_NETWORK, network->path()); 310 } 311} 312 313void NetworkStateHandler::SetConnectingNetwork( 314 const std::string& service_path) { 315 connecting_network_ = service_path; 316 const NetworkState* network = GetNetworkState(service_path); 317 if (network) 318 NET_LOG_EVENT("SetConnectingNetwork", GetManagedStateLogName(network)); 319 else 320 NET_LOG_ERROR("SetConnectingNetwork to unknown network", service_path); 321} 322 323void NetworkStateHandler::SetCheckPortalList( 324 const std::string& check_portal_list) { 325 NET_LOG_EVENT("SetCheckPortalList", check_portal_list); 326 shill_property_handler_->SetCheckPortalList(check_portal_list); 327} 328 329void NetworkStateHandler::GetNetworkStatePropertiesForTest( 330 base::DictionaryValue* dictionary) const { 331 for (ManagedStateList::const_iterator iter = network_list_.begin(); 332 iter != network_list_.end(); ++iter) { 333 base::DictionaryValue* network_dict = new base::DictionaryValue; 334 (*iter)->AsNetworkState()->GetProperties(network_dict); 335 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict); 336 } 337} 338 339//------------------------------------------------------------------------------ 340// ShillPropertyHandler::Delegate overrides 341 342void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, 343 const base::ListValue& entries) { 344 ManagedStateList* managed_list = GetManagedList(type); 345 VLOG(2) << "UpdateManagedList: " << type; 346 // Create a map of existing entries. 347 std::map<std::string, ManagedState*> managed_map; 348 for (ManagedStateList::iterator iter = managed_list->begin(); 349 iter != managed_list->end(); ++iter) { 350 ManagedState* managed = *iter; 351 managed_map[managed->path()] = managed; 352 } 353 // Clear the list (pointers are owned by managed_map). 354 managed_list->clear(); 355 // Updates managed_list and request updates for new entries. 356 for (base::ListValue::const_iterator iter = entries.begin(); 357 iter != entries.end(); ++iter) { 358 std::string path; 359 (*iter)->GetAsString(&path); 360 DCHECK(!path.empty()); 361 std::map<std::string, ManagedState*>::iterator found = 362 managed_map.find(path); 363 bool request_properties = false; 364 ManagedState* managed; 365 bool is_observing = shill_property_handler_->IsObservingNetwork(path); 366 if (found == managed_map.end()) { 367 request_properties = true; 368 managed = ManagedState::Create(type, path); 369 managed_list->push_back(managed); 370 } else { 371 managed = found->second; 372 managed_list->push_back(managed); 373 managed_map.erase(found); 374 if (!managed->is_observed() && is_observing) 375 request_properties = true; 376 } 377 if (is_observing) 378 managed->set_is_observed(true); 379 if (request_properties) 380 shill_property_handler_->RequestProperties(type, path); 381 } 382 // Delete any remaning entries in managed_map. 383 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); 384} 385 386void NetworkStateHandler::ProfileListChanged() { 387 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties"); 388 for (ManagedStateList::iterator iter = network_list_.begin(); 389 iter != network_list_.end(); ++iter) { 390 shill_property_handler_->RequestProperties( 391 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path()); 392 } 393} 394 395void NetworkStateHandler::UpdateManagedStateProperties( 396 ManagedState::ManagedType type, 397 const std::string& path, 398 const base::DictionaryValue& properties) { 399 ManagedState* managed = GetModifiableManagedState(GetManagedList(type), path); 400 if (!managed) { 401 LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!"; 402 return; 403 } 404 bool network_property_updated = false; 405 std::string prev_connection_state; 406 if (type == ManagedState::MANAGED_TYPE_NETWORK) 407 prev_connection_state = managed->AsNetworkState()->connection_state(); 408 for (base::DictionaryValue::Iterator iter(properties); 409 !iter.IsAtEnd(); iter.Advance()) { 410 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 411 if (managed->PropertyChanged(iter.key(), iter.value())) 412 network_property_updated = true; 413 } else { 414 managed->PropertyChanged(iter.key(), iter.value()); 415 } 416 } 417 managed->InitialPropertiesReceived(); 418 NET_LOG_DEBUG("PropertiesReceived", GetManagedStateLogName(managed)); 419 // Notify observers. 420 if (network_property_updated || managed->update_requested()) { 421 NetworkState* network = managed->AsNetworkState(); 422 DCHECK(network); 423 // Signal connection state changed after all properties have been updated. 424 if (ConnectionStateChanged(network, prev_connection_state)) 425 OnNetworkConnectionStateChanged(network); 426 NetworkPropertiesUpdated(network); 427 } 428 managed->set_update_requested(false); 429} 430 431void NetworkStateHandler::UpdateNetworkServiceProperty( 432 const std::string& service_path, 433 const std::string& key, 434 const base::Value& value) { 435 NetworkState* network = GetModifiableNetworkState(service_path); 436 if (!network) 437 return; 438 std::string prev_connection_state = network->connection_state(); 439 if (!network->PropertyChanged(key, value)) 440 return; 441 442 if (key == flimflam::kStateProperty) { 443 if (ConnectionStateChanged(network, prev_connection_state)) 444 OnNetworkConnectionStateChanged(network); 445 } else { 446 if (network->path() == default_network_path_ && 447 key != flimflam::kSignalStrengthProperty) { 448 // WiFi signal strength updates are too noisy, so don't 449 // trigger default network updates for those changes. 450 OnDefaultNetworkChanged(); 451 } 452 std::string detail = network->name() + "." + key; 453 detail += " = " + network_event_log::ValueAsString(value); 454 network_event_log::LogLevel log_level = network_event_log::LOG_LEVEL_EVENT; 455 if (key == flimflam::kErrorProperty || key == shill::kErrorDetailsProperty) 456 log_level = network_event_log::LOG_LEVEL_ERROR; 457 else if (key == flimflam::kSignalStrengthProperty) 458 log_level = network_event_log::LOG_LEVEL_DEBUG; 459 NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail); 460 } 461 NetworkPropertiesUpdated(network); 462} 463 464void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path, 465 const std::string& key, 466 const base::Value& value) { 467 DeviceState* device = GetModifiableDeviceState(device_path); 468 if (!device) 469 return; 470 if (!device->PropertyChanged(key, value)) 471 return; 472 473 std::string detail = device->name() + "." + key; 474 detail += " = " + network_event_log::ValueAsString(value); 475 NET_LOG_EVENT("DevicePropertyUpdated", detail); 476 477 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 478 DeviceListChanged()); 479 480 if (key == flimflam::kScanningProperty && device->scanning() == false) 481 ScanCompleted(device->type()); 482} 483 484void NetworkStateHandler::CheckPortalListChanged( 485 const std::string& check_portal_list) { 486 check_portal_list_ = check_portal_list; 487} 488 489void NetworkStateHandler::NotifyManagerPropertyChanged() { 490 NET_LOG_DEBUG("NotifyManagerPropertyChanged", ""); 491 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 492 NetworkManagerChanged()); 493} 494 495void NetworkStateHandler::ManagedStateListChanged( 496 ManagedState::ManagedType type) { 497 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 498 // Notify observers that the list of networks has changed. 499 NET_LOG_EVENT("NetworkListChanged", 500 base::StringPrintf("Size:%"PRIuS, network_list_.size())); 501 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 502 NetworkListChanged()); 503 // The list order may have changed, so check if the default network changed. 504 if (CheckDefaultNetworkChanged()) 505 OnDefaultNetworkChanged(); 506 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 507 NET_LOG_DEBUG("DeviceListChanged", 508 base::StringPrintf("Size:%"PRIuS, device_list_.size())); 509 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 510 DeviceListChanged()); 511 } else { 512 NOTREACHED(); 513 } 514} 515 516//------------------------------------------------------------------------------ 517// Private methods 518 519DeviceState* NetworkStateHandler::GetModifiableDeviceState( 520 const std::string& device_path) const { 521 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 522 if (!managed) 523 return NULL; 524 return managed->AsDeviceState(); 525} 526 527NetworkState* NetworkStateHandler::GetModifiableNetworkState( 528 const std::string& service_path) const { 529 ManagedState* managed = 530 GetModifiableManagedState(&network_list_, service_path); 531 if (!managed) 532 return NULL; 533 return managed->AsNetworkState(); 534} 535 536ManagedState* NetworkStateHandler::GetModifiableManagedState( 537 const ManagedStateList* managed_list, 538 const std::string& path) const { 539 for (ManagedStateList::const_iterator iter = managed_list->begin(); 540 iter != managed_list->end(); ++iter) { 541 ManagedState* managed = *iter; 542 if (managed->path() == path) 543 return managed; 544 } 545 return NULL; 546} 547 548NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 549 ManagedState::ManagedType type) { 550 switch (type) { 551 case ManagedState::MANAGED_TYPE_NETWORK: 552 return &network_list_; 553 case ManagedState::MANAGED_TYPE_DEVICE: 554 return &device_list_; 555 } 556 NOTREACHED(); 557 return NULL; 558} 559 560void NetworkStateHandler::OnNetworkConnectionStateChanged( 561 NetworkState* network) { 562 DCHECK(network); 563 NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf( 564 "%s:%s", GetManagedStateLogName(network).c_str(), 565 network->connection_state().c_str())); 566 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 567 NetworkConnectionStateChanged(network)); 568 if (CheckDefaultNetworkChanged() || network->path() == default_network_path_) 569 OnDefaultNetworkChanged(); 570} 571 572bool NetworkStateHandler::CheckDefaultNetworkChanged() { 573 std::string new_default_network_path; 574 const NetworkState* new_default_network = DefaultNetwork(); 575 if (new_default_network) 576 new_default_network_path = new_default_network->path(); 577 if (new_default_network_path == default_network_path_) 578 return false; 579 default_network_path_ = new_default_network_path; 580 return true; 581} 582 583void NetworkStateHandler::OnDefaultNetworkChanged() { 584 const NetworkState* default_network = DefaultNetwork(); 585 NET_LOG_EVENT("DefaultNetworkChanged", 586 GetManagedStateLogName(default_network)); 587 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 588 DefaultNetworkChanged(default_network)); 589} 590 591void NetworkStateHandler::NetworkPropertiesUpdated( 592 const NetworkState* network) { 593 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 594 NetworkPropertiesUpdated(network)); 595 // If |connecting_network_| transitions to a non-idle, non-connecting state, 596 // clear it *after* signalling observers. 597 if (network->path() == connecting_network_ && 598 !network->IsConnectingState() && 599 network->connection_state() != flimflam::kStateIdle) { 600 connecting_network_.clear(); 601 NET_LOG_EVENT("ClearConnectingNetwork", base::StringPrintf( 602 "%s:%s", GetManagedStateLogName(network).c_str(), 603 network->connection_state().c_str())); 604 } 605} 606 607void NetworkStateHandler::ScanCompleted(const std::string& type) { 608 size_t num_callbacks = scan_complete_callbacks_.count(type); 609 NET_LOG_EVENT("ScanCompleted", 610 base::StringPrintf("%s:%"PRIuS, type.c_str(), num_callbacks)); 611 if (num_callbacks == 0) 612 return; 613 ScanCallbackList& callback_list = scan_complete_callbacks_[type]; 614 for (ScanCallbackList::iterator iter = callback_list.begin(); 615 iter != callback_list.end(); ++iter) { 616 (*iter).Run(); 617 } 618 scan_complete_callbacks_.erase(type); 619} 620 621std::string NetworkStateHandler::GetTechnologyForType( 622 const std::string& type) const { 623 if (type == kMatchTypeMobile) { 624 if (shill_property_handler_->IsTechnologyAvailable(flimflam::kTypeWimax)) 625 return flimflam::kTypeWimax; 626 else 627 return flimflam::kTypeCellular; 628 } 629 if (type == kMatchTypeDefault || type == kMatchTypeNonVirtual || 630 type == kMatchTypeWireless) { 631 NOTREACHED(); 632 return flimflam::kTypeWifi; 633 } 634 return type; 635} 636 637} // namespace chromeos 638