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