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