network_state_handler.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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/guid.h" 10#include "base/location.h" 11#include "base/logging.h" 12#include "base/metrics/histogram.h" 13#include "base/stl_util.h" 14#include "base/strings/string_util.h" 15#include "base/strings/stringprintf.h" 16#include "base/values.h" 17#include "chromeos/network/device_state.h" 18#include "chromeos/network/favorite_state.h" 19#include "chromeos/network/managed_state.h" 20#include "chromeos/network/network_event_log.h" 21#include "chromeos/network/network_state.h" 22#include "chromeos/network/network_state_handler_observer.h" 23#include "chromeos/network/shill_property_handler.h" 24#include "third_party/cros_system_api/dbus/service_constants.h" 25 26namespace chromeos { 27 28namespace { 29 30bool ConnectionStateChanged(NetworkState* network, 31 const std::string& prev_connection_state) { 32 return (network->connection_state() != prev_connection_state) && 33 (network->connection_state() != shill::kStateIdle || 34 !prev_connection_state.empty()); 35} 36 37std::string GetManagedStateLogType(const ManagedState* state) { 38 switch (state->managed_type()) { 39 case ManagedState::MANAGED_TYPE_NETWORK: 40 return "Network"; 41 case ManagedState::MANAGED_TYPE_FAVORITE: 42 return "Favorite"; 43 case ManagedState::MANAGED_TYPE_DEVICE: 44 return "Device"; 45 } 46 NOTREACHED(); 47 return ""; 48} 49 50std::string GetManagedStateLogName(const ManagedState* state) { 51 if (!state) 52 return "None"; 53 return base::StringPrintf("%s (%s)", state->name().c_str(), 54 state->path().c_str()); 55} 56 57} // namespace 58 59const char NetworkStateHandler::kDefaultCheckPortalList[] = 60 "ethernet,wifi,cellular"; 61 62NetworkStateHandler::NetworkStateHandler() { 63} 64 65NetworkStateHandler::~NetworkStateHandler() { 66 STLDeleteContainerPointers(network_list_.begin(), network_list_.end()); 67 STLDeleteContainerPointers(favorite_list_.begin(), favorite_list_.end()); 68 STLDeleteContainerPointers(device_list_.begin(), device_list_.end()); 69} 70 71void NetworkStateHandler::InitShillPropertyHandler() { 72 shill_property_handler_.reset(new internal::ShillPropertyHandler(this)); 73 shill_property_handler_->Init(); 74} 75 76// static 77NetworkStateHandler* NetworkStateHandler::InitializeForTest() { 78 NetworkStateHandler* handler = new NetworkStateHandler(); 79 handler->InitShillPropertyHandler(); 80 return handler; 81} 82 83void NetworkStateHandler::AddObserver( 84 NetworkStateHandlerObserver* observer, 85 const tracked_objects::Location& from_here) { 86 observers_.AddObserver(observer); 87 network_event_log::internal::AddEntry( 88 from_here.file_name(), from_here.line_number(), 89 network_event_log::LOG_LEVEL_DEBUG, 90 "NetworkStateHandler::AddObserver", ""); 91} 92 93void NetworkStateHandler::RemoveObserver( 94 NetworkStateHandlerObserver* observer, 95 const tracked_objects::Location& from_here) { 96 observers_.RemoveObserver(observer); 97 network_event_log::internal::AddEntry( 98 from_here.file_name(), from_here.line_number(), 99 network_event_log::LOG_LEVEL_DEBUG, 100 "NetworkStateHandler::RemoveObserver", ""); 101} 102 103void NetworkStateHandler::UpdateManagerProperties() { 104 NET_LOG_USER("UpdateManagerProperties", ""); 105 shill_property_handler_->UpdateManagerProperties(); 106} 107 108NetworkStateHandler::TechnologyState NetworkStateHandler::GetTechnologyState( 109 const NetworkTypePattern& type) const { 110 std::string technology = GetTechnologyForType(type); 111 TechnologyState state; 112 if (shill_property_handler_->IsTechnologyEnabled(technology)) 113 state = TECHNOLOGY_ENABLED; 114 else if (shill_property_handler_->IsTechnologyEnabling(technology)) 115 state = TECHNOLOGY_ENABLING; 116 else if (shill_property_handler_->IsTechnologyUninitialized(technology)) 117 state = TECHNOLOGY_UNINITIALIZED; 118 else if (shill_property_handler_->IsTechnologyAvailable(technology)) 119 state = TECHNOLOGY_AVAILABLE; 120 else 121 state = TECHNOLOGY_UNAVAILABLE; 122 VLOG(2) << "GetTechnologyState: " << type.ToDebugString() << " = " << state; 123 return state; 124} 125 126void NetworkStateHandler::SetTechnologyEnabled( 127 const NetworkTypePattern& type, 128 bool enabled, 129 const network_handler::ErrorCallback& error_callback) { 130 ScopedVector<std::string> technologies = GetTechnologiesForType(type); 131 for (ScopedVector<std::string>::iterator it = technologies.begin(); 132 it != technologies.end(); ++it) { 133 std::string* technology = *it; 134 DCHECK(technology); 135 NET_LOG_USER("SetTechnologyEnabled", 136 base::StringPrintf("%s:%d", technology->c_str(), enabled)); 137 shill_property_handler_->SetTechnologyEnabled( 138 *technology, enabled, error_callback); 139 } 140 // Signal Device/Technology state changed. 141 NotifyDeviceListChanged(); 142} 143 144const DeviceState* NetworkStateHandler::GetDeviceState( 145 const std::string& device_path) const { 146 const DeviceState* device = GetModifiableDeviceState(device_path); 147 if (device && !device->update_received()) 148 return NULL; 149 return device; 150} 151 152const DeviceState* NetworkStateHandler::GetDeviceStateByType( 153 const NetworkTypePattern& type) const { 154 for (ManagedStateList::const_iterator iter = device_list_.begin(); 155 iter != device_list_.end(); ++iter) { 156 ManagedState* device = *iter; 157 if (!device->update_received()) 158 continue; 159 if (device->Matches(type)) 160 return device->AsDeviceState(); 161 } 162 return NULL; 163} 164 165bool NetworkStateHandler::GetScanningByType( 166 const NetworkTypePattern& type) const { 167 for (ManagedStateList::const_iterator iter = device_list_.begin(); 168 iter != device_list_.end(); ++iter) { 169 const DeviceState* device = (*iter)->AsDeviceState(); 170 DCHECK(device); 171 if (!device->update_received()) 172 continue; 173 if (device->Matches(type) && device->scanning()) 174 return true; 175 } 176 return false; 177} 178 179const NetworkState* NetworkStateHandler::GetNetworkState( 180 const std::string& service_path) const { 181 const NetworkState* network = GetModifiableNetworkState(service_path); 182 if (network && !network->update_received()) 183 return NULL; 184 return network; 185} 186 187const NetworkState* NetworkStateHandler::DefaultNetwork() const { 188 if (default_network_path_.empty()) 189 return NULL; 190 return GetNetworkState(default_network_path_); 191} 192 193const FavoriteState* NetworkStateHandler::DefaultFavoriteNetwork() const { 194 const NetworkState* default_network = DefaultNetwork(); 195 if (!default_network) 196 return NULL; 197 const FavoriteState* default_favorite = GetFavoriteStateFromServicePath( 198 default_network->path(), true /* configured_only */); 199 DCHECK(default_network->type() != shill::kTypeWifi || default_favorite) 200 << "No favorite for: " << default_network->path(); 201 DCHECK(!default_favorite || default_favorite->update_received()) 202 << "No update received for: " << default_network->path(); 203 return default_favorite; 204} 205 206const NetworkState* NetworkStateHandler::ConnectedNetworkByType( 207 const NetworkTypePattern& 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 (!network->update_received()) 213 continue; 214 if (!network->IsConnectedState()) 215 break; // Connected networks are listed first. 216 if (network->Matches(type)) 217 return network; 218 } 219 return NULL; 220} 221 222const NetworkState* NetworkStateHandler::ConnectingNetworkByType( 223 const NetworkTypePattern& type) const { 224 for (ManagedStateList::const_iterator iter = network_list_.begin(); 225 iter != network_list_.end(); ++iter) { 226 const NetworkState* network = (*iter)->AsNetworkState(); 227 DCHECK(network); 228 if (!network->update_received() || network->IsConnectedState()) 229 continue; 230 if (!network->IsConnectingState()) 231 break; // Connected and connecting networks are listed first. 232 if (network->Matches(type)) 233 return network; 234 } 235 return NULL; 236} 237 238const NetworkState* NetworkStateHandler::FirstNetworkByType( 239 const NetworkTypePattern& type) const { 240 for (ManagedStateList::const_iterator iter = network_list_.begin(); 241 iter != network_list_.end(); ++iter) { 242 const NetworkState* network = (*iter)->AsNetworkState(); 243 DCHECK(network); 244 if (!network->update_received()) 245 continue; 246 if (network->Matches(type)) 247 return network; 248 } 249 return NULL; 250} 251 252std::string NetworkStateHandler::FormattedHardwareAddressForType( 253 const NetworkTypePattern& type) const { 254 const DeviceState* device = NULL; 255 const NetworkState* network = ConnectedNetworkByType(type); 256 if (network) 257 device = GetDeviceState(network->device_path()); 258 else 259 device = GetDeviceStateByType(type); 260 if (!device) 261 return std::string(); 262 return network_util::FormattedMacAddress(device->mac_address()); 263} 264 265void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const { 266 GetNetworkListByType(NetworkTypePattern::Default(), list); 267} 268 269void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type, 270 NetworkStateList* list) const { 271 DCHECK(list); 272 list->clear(); 273 for (ManagedStateList::const_iterator iter = network_list_.begin(); 274 iter != network_list_.end(); ++iter) { 275 const NetworkState* network = (*iter)->AsNetworkState(); 276 DCHECK(network); 277 if (network->update_received() && network->Matches(type)) 278 list->push_back(network); 279 } 280} 281 282void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const { 283 GetDeviceListByType(NetworkTypePattern::Default(), list); 284} 285 286void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type, 287 DeviceStateList* list) const { 288 DCHECK(list); 289 list->clear(); 290 for (ManagedStateList::const_iterator iter = device_list_.begin(); 291 iter != device_list_.end(); ++iter) { 292 const DeviceState* device = (*iter)->AsDeviceState(); 293 DCHECK(device); 294 if (device->update_received() && device->Matches(type)) 295 list->push_back(device); 296 } 297} 298 299void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const { 300 GetFavoriteListByType(NetworkTypePattern::Default(), 301 true /* configured_only */, 302 false /* visible_only */, 303 0 /* no limit */, 304 list); 305} 306 307void NetworkStateHandler::GetFavoriteListByType(const NetworkTypePattern& type, 308 bool configured_only, 309 bool visible_only, 310 int limit, 311 FavoriteStateList* list) const { 312 DCHECK(list); 313 std::set<std::string> visible_networks; 314 if (visible_only) { 315 // Prepare a set of visible network service paths for fast lookup. 316 for (ManagedStateList::const_iterator iter = network_list_.begin(); 317 iter != network_list_.end(); ++iter) { 318 visible_networks.insert((*iter)->path()); 319 } 320 } 321 FavoriteStateList result; 322 list->clear(); 323 int count = 0; 324 for (ManagedStateList::const_iterator iter = favorite_list_.begin(); 325 iter != favorite_list_.end(); ++iter) { 326 const FavoriteState* favorite = (*iter)->AsFavoriteState(); 327 DCHECK(favorite); 328 if (!favorite->update_received() || !favorite->Matches(type)) 329 continue; 330 if (configured_only && !favorite->IsInProfile()) 331 continue; 332 if (visible_only && !ContainsKey(visible_networks, favorite->path())) 333 continue; 334 list->push_back(favorite); 335 if (limit > 0 && ++count >= limit) 336 break; 337 } 338} 339 340const FavoriteState* NetworkStateHandler::GetFavoriteStateFromServicePath( 341 const std::string& service_path, 342 bool configured_only) const { 343 ManagedState* managed = 344 GetModifiableManagedState(&favorite_list_, service_path); 345 if (!managed) 346 return NULL; 347 const FavoriteState* favorite = managed->AsFavoriteState(); 348 DCHECK(favorite); 349 if (!favorite->update_received() || 350 (configured_only && !favorite->IsInProfile())) { 351 return NULL; 352 } 353 return favorite; 354} 355 356const FavoriteState* NetworkStateHandler::GetFavoriteStateFromGuid( 357 const std::string& guid) const { 358 DCHECK(!guid.empty()); 359 for (ManagedStateList::const_iterator iter = favorite_list_.begin(); 360 iter != favorite_list_.end(); ++iter) { 361 const FavoriteState* favorite = (*iter)->AsFavoriteState(); 362 if (favorite->guid() == guid) 363 return favorite; 364 } 365 return NULL; 366} 367 368void NetworkStateHandler::RequestScan() const { 369 NET_LOG_USER("RequestScan", ""); 370 shill_property_handler_->RequestScan(); 371} 372 373void NetworkStateHandler::WaitForScan(const std::string& type, 374 const base::Closure& callback) { 375 scan_complete_callbacks_[type].push_back(callback); 376 if (!GetScanningByType(NetworkTypePattern::Primitive(type))) 377 RequestScan(); 378} 379 380void NetworkStateHandler::ConnectToBestWifiNetwork() { 381 NET_LOG_USER("ConnectToBestWifiNetwork", ""); 382 WaitForScan(shill::kTypeWifi, 383 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices, 384 shill_property_handler_->AsWeakPtr())); 385} 386 387void NetworkStateHandler::RequestUpdateForNetwork( 388 const std::string& service_path) { 389 NetworkState* network = GetModifiableNetworkState(service_path); 390 if (network) 391 network->set_update_requested(true); 392 NET_LOG_EVENT("RequestUpdate", service_path); 393 shill_property_handler_->RequestProperties( 394 ManagedState::MANAGED_TYPE_NETWORK, service_path); 395} 396 397void NetworkStateHandler::ClearLastErrorForNetwork( 398 const std::string& service_path) { 399 NetworkState* network = GetModifiableNetworkState(service_path); 400 if (network) 401 network->clear_last_error(); 402} 403 404void NetworkStateHandler::SetCheckPortalList( 405 const std::string& check_portal_list) { 406 NET_LOG_EVENT("SetCheckPortalList", check_portal_list); 407 shill_property_handler_->SetCheckPortalList(check_portal_list); 408} 409 410const FavoriteState* NetworkStateHandler::GetEAPForEthernet( 411 const std::string& service_path) const { 412 const NetworkState* network = GetNetworkState(service_path); 413 if (!network) { 414 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path); 415 return NULL; 416 } 417 if (network->type() != shill::kTypeEthernet) { 418 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path); 419 return NULL; 420 } 421 if (!network->IsConnectedState()) 422 return NULL; 423 424 // The same EAP service is shared for all ethernet services/devices. 425 // However EAP is used/enabled per device and only if the connection was 426 // successfully established. 427 const DeviceState* device = GetDeviceState(network->device_path()); 428 if (!device) { 429 NET_LOG_ERROR( 430 "GetEAPForEthernet", 431 base::StringPrintf("Unknown device %s of connected ethernet service %s", 432 network->device_path().c_str(), 433 service_path.c_str())); 434 return NULL; 435 } 436 if (!device->eap_authentication_completed()) 437 return NULL; 438 439 FavoriteStateList list; 440 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap), 441 true /* configured_only */, 442 false /* visible_only */, 443 1 /* limit */, 444 &list); 445 if (list.empty()) { 446 NET_LOG_ERROR("GetEAPForEthernet", 447 base::StringPrintf( 448 "Ethernet service %s connected using EAP, but no " 449 "EAP service found.", 450 service_path.c_str())); 451 return NULL; 452 } 453 return list.front(); 454} 455 456//------------------------------------------------------------------------------ 457// ShillPropertyHandler::Delegate overrides 458 459void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, 460 const base::ListValue& entries) { 461 ManagedStateList* managed_list = GetManagedList(type); 462 NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type), 463 base::StringPrintf("%" PRIuS, entries.GetSize())); 464 // Create a map of existing entries. Assumes all entries in |managed_list| 465 // are unique. 466 std::map<std::string, ManagedState*> managed_map; 467 for (ManagedStateList::iterator iter = managed_list->begin(); 468 iter != managed_list->end(); ++iter) { 469 ManagedState* managed = *iter; 470 DCHECK(!ContainsKey(managed_map, managed->path())); 471 managed_map[managed->path()] = managed; 472 } 473 // Clear the list (pointers are temporarily owned by managed_map). 474 managed_list->clear(); 475 // Updates managed_list and request updates for new entries. 476 std::set<std::string> list_entries; 477 for (base::ListValue::const_iterator iter = entries.begin(); 478 iter != entries.end(); ++iter) { 479 std::string path; 480 (*iter)->GetAsString(&path); 481 if (path.empty() || path == shill::kFlimflamServicePath) { 482 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path); 483 continue; 484 } 485 std::map<std::string, ManagedState*>::iterator found = 486 managed_map.find(path); 487 ManagedState* managed; 488 if (found == managed_map.end()) { 489 if (list_entries.count(path) != 0) { 490 NET_LOG_ERROR("Duplicate entry in list", path); 491 continue; 492 } 493 managed = ManagedState::Create(type, path); 494 managed_list->push_back(managed); 495 } else { 496 managed = found->second; 497 managed_list->push_back(managed); 498 managed_map.erase(found); 499 } 500 list_entries.insert(path); 501 } 502 // Delete any remaining entries in managed_map. 503 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); 504} 505 506void NetworkStateHandler::ProfileListChanged() { 507 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties"); 508 for (ManagedStateList::iterator iter = favorite_list_.begin(); 509 iter != favorite_list_.end(); ++iter) { 510 shill_property_handler_->RequestProperties( 511 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path()); 512 } 513} 514 515void NetworkStateHandler::UpdateManagedStateProperties( 516 ManagedState::ManagedType type, 517 const std::string& path, 518 const base::DictionaryValue& properties) { 519 ManagedStateList* managed_list = GetManagedList(type); 520 ManagedState* managed = GetModifiableManagedState(managed_list, path); 521 if (!managed) { 522 if (type != ManagedState::MANAGED_TYPE_FAVORITE) { 523 // The network has been removed from the list of visible networks. 524 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path); 525 return; 526 } 527 // A Favorite may not have been created yet if it was added later (e.g. 528 // through ConfigureService) since ServiceCompleteList updates are not 529 // emitted. Add and update the state here. 530 managed = ManagedState::Create(type, path); 531 managed_list->push_back(managed); 532 } 533 managed->set_update_received(); 534 535 std::string desc = GetManagedStateLogType(managed) + " Properties Received"; 536 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed)); 537 538 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 539 UpdateNetworkStateProperties(managed->AsNetworkState(), properties); 540 } else { 541 // Device, Favorite 542 for (base::DictionaryValue::Iterator iter(properties); 543 !iter.IsAtEnd(); iter.Advance()) { 544 managed->PropertyChanged(iter.key(), iter.value()); 545 } 546 managed->InitialPropertiesReceived(properties); 547 } 548 UpdateGuid(managed); 549 managed->set_update_requested(false); 550} 551 552void NetworkStateHandler::UpdateNetworkStateProperties( 553 NetworkState* network, 554 const base::DictionaryValue& properties) { 555 DCHECK(network); 556 bool network_property_updated = false; 557 std::string prev_connection_state = network->connection_state(); 558 for (base::DictionaryValue::Iterator iter(properties); 559 !iter.IsAtEnd(); iter.Advance()) { 560 if (network->PropertyChanged(iter.key(), iter.value())) 561 network_property_updated = true; 562 } 563 network_property_updated |= network->InitialPropertiesReceived(properties); 564 // Notify observers of NetworkState changes. 565 if (network_property_updated || network->update_requested()) { 566 // Signal connection state changed after all properties have been updated. 567 if (ConnectionStateChanged(network, prev_connection_state)) 568 OnNetworkConnectionStateChanged(network); 569 NET_LOG_EVENT("NetworkPropertiesUpdated", GetManagedStateLogName(network)); 570 NotifyNetworkPropertiesUpdated(network); 571 } 572} 573 574void NetworkStateHandler::UpdateNetworkServiceProperty( 575 const std::string& service_path, 576 const std::string& key, 577 const base::Value& value) { 578 // Update any associated FavoriteState. 579 ManagedState* favorite = 580 GetModifiableManagedState(&favorite_list_, service_path); 581 bool changed = false; 582 if (favorite) 583 changed |= favorite->PropertyChanged(key, value); 584 585 // Update the NetworkState. 586 NetworkState* network = GetModifiableNetworkState(service_path); 587 if (!network) 588 return; 589 std::string prev_connection_state = network->connection_state(); 590 std::string prev_profile_path = network->profile_path(); 591 changed |= network->PropertyChanged(key, value); 592 if (!changed) 593 return; 594 595 if (key == shill::kStateProperty) { 596 if (ConnectionStateChanged(network, prev_connection_state)) { 597 OnNetworkConnectionStateChanged(network); 598 // If the connection state changes, other properties such as IPConfig 599 // may have changed, so request a full update. 600 RequestUpdateForNetwork(service_path); 601 } 602 } else { 603 std::string value_str; 604 value.GetAsString(&value_str); 605 // Some property changes are noisy and not interesting: 606 // * Wifi SignalStrength 607 // * WifiFrequencyList updates 608 // * Device property changes to "/" (occurs before a service is removed) 609 if (key != shill::kSignalStrengthProperty && 610 key != shill::kWifiFrequencyListProperty && 611 (key != shill::kDeviceProperty || value_str != "/")) { 612 std::string log_event = "NetworkPropertyUpdated"; 613 // Trigger a default network update for interesting changes only. 614 if (network->path() == default_network_path_) { 615 NotifyDefaultNetworkChanged(network); 616 log_event = "Default" + log_event; 617 } 618 // Log event. 619 std::string detail = network->name() + "." + key; 620 detail += " = " + network_event_log::ValueAsString(value); 621 network_event_log::LogLevel log_level; 622 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) { 623 log_level = network_event_log::LOG_LEVEL_ERROR; 624 } else { 625 log_level = network_event_log::LOG_LEVEL_EVENT; 626 } 627 NET_LOG_LEVEL(log_level, log_event, detail); 628 } 629 } 630 631 // All property updates signal 'NetworkPropertiesUpdated'. 632 NotifyNetworkPropertiesUpdated(network); 633 634 // If added to a Profile, request a full update so that a FavoriteState 635 // gets created. 636 if (prev_profile_path.empty() && !network->profile_path().empty()) 637 RequestUpdateForNetwork(service_path); 638} 639 640void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path, 641 const std::string& key, 642 const base::Value& value) { 643 DeviceState* device = GetModifiableDeviceState(device_path); 644 if (!device) 645 return; 646 if (!device->PropertyChanged(key, value)) 647 return; 648 649 std::string detail = device->name() + "." + key; 650 detail += " = " + network_event_log::ValueAsString(value); 651 NET_LOG_EVENT("DevicePropertyUpdated", detail); 652 653 NotifyDeviceListChanged(); 654 655 if (key == shill::kScanningProperty && device->scanning() == false) 656 ScanCompleted(device->type()); 657 if (key == shill::kEapAuthenticationCompletedProperty) { 658 // Notify a change for each Ethernet service using this device. 659 NetworkStateList ethernet_services; 660 GetNetworkListByType(NetworkTypePattern::Ethernet(), ðernet_services); 661 for (NetworkStateList::const_iterator it = ethernet_services.begin(); 662 it != ethernet_services.end(); ++it) { 663 const NetworkState* ethernet_service = *it; 664 if (ethernet_service->update_received() || 665 ethernet_service->device_path() != device->path()) { 666 continue; 667 } 668 RequestUpdateForNetwork(ethernet_service->path()); 669 } 670 } 671} 672 673void NetworkStateHandler::UpdateIPConfigProperties( 674 ManagedState::ManagedType type, 675 const std::string& path, 676 const std::string& ip_config_path, 677 const base::DictionaryValue& properties) { 678 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 679 NetworkState* network = GetModifiableNetworkState(path); 680 if (!network) 681 return; 682 network->IPConfigPropertiesChanged(properties); 683 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 684 DeviceState* device = GetModifiableDeviceState(path); 685 if (!device) 686 return; 687 device->IPConfigPropertiesChanged(ip_config_path, properties); 688 } 689} 690 691void NetworkStateHandler::CheckPortalListChanged( 692 const std::string& check_portal_list) { 693 check_portal_list_ = check_portal_list; 694} 695 696void NetworkStateHandler::TechnologyListChanged() { 697 // Eventually we would like to replace Technology state with Device state. 698 // For now, treat technology state changes as device list changes. 699 NotifyDeviceListChanged(); 700} 701 702void NetworkStateHandler::ManagedStateListChanged( 703 ManagedState::ManagedType type) { 704 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 705 // Notify observers that the list of networks has changed. 706 NET_LOG_EVENT("NetworkListChanged", 707 base::StringPrintf("Size:%" PRIuS, network_list_.size())); 708 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 709 NetworkListChanged()); 710 // Update UMA stats. 711 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", network_list_.size()); 712 } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) { 713 NET_LOG_DEBUG("FavoriteListChanged", 714 base::StringPrintf("Size:%" PRIuS, favorite_list_.size())); 715 // The FavoriteState list only changes when the NetworkState list changes, 716 // so no need to signal observers here again. 717 718 // Update UMA stats. 719 size_t shared = 0, unshared = 0; 720 for (ManagedStateList::iterator iter = favorite_list_.begin(); 721 iter != favorite_list_.end(); ++iter) { 722 FavoriteState* favorite = (*iter)->AsFavoriteState(); 723 if (!favorite->IsInProfile()) 724 continue; 725 if (favorite->IsPrivate()) 726 ++unshared; 727 else 728 ++shared; 729 } 730 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared); 731 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared); 732 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 733 std::string devices; 734 for (ManagedStateList::const_iterator iter = device_list_.begin(); 735 iter != device_list_.end(); ++iter) { 736 if (iter != device_list_.begin()) 737 devices += ", "; 738 devices += (*iter)->name(); 739 } 740 NET_LOG_EVENT("DeviceList:", devices); 741 NotifyDeviceListChanged(); 742 } else { 743 NOTREACHED(); 744 } 745} 746 747void NetworkStateHandler::DefaultNetworkServiceChanged( 748 const std::string& service_path) { 749 // Shill uses '/' for empty service path values; check explicitly for that. 750 const char* kEmptyServicePath = "/"; 751 if (service_path == kEmptyServicePath) 752 default_network_path_.clear(); 753 else 754 default_network_path_ = service_path; 755 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_); 756 const NetworkState* network = NULL; 757 if (!default_network_path_.empty()) { 758 network = GetNetworkState(default_network_path_); 759 if (!network) { 760 // If NetworkState is not available yet, do not notify observers here, 761 // they will be notified when the state is received. 762 NET_LOG_DEBUG("Default NetworkState not available", 763 default_network_path_); 764 return; 765 } 766 } 767 if (network && !network->IsConnectedState()) { 768 NET_LOG_ERROR( 769 "DefaultNetwork is not connected: " + network->connection_state(), 770 network->path()); 771 } 772 NotifyDefaultNetworkChanged(network); 773} 774 775//------------------------------------------------------------------------------ 776// Private methods 777 778void NetworkStateHandler::UpdateGuid(ManagedState* managed) { 779 if (managed->managed_type() == ManagedState::MANAGED_TYPE_FAVORITE) { 780 FavoriteState* favorite = managed->AsFavoriteState(); 781 std::string specifier = favorite->GetSpecifier(); 782 if (!favorite->guid().empty()) { 783 // If the favorite is saved in a profile, remove the entry from the map. 784 // Otherwise ensure that the entry matches the specified GUID. 785 if (favorite->IsInProfile()) 786 specifier_guid_map_.erase(specifier); 787 else 788 specifier_guid_map_[specifier] = favorite->guid(); 789 return; 790 } 791 // Ensure that the FavoriteState has a valid GUID. 792 std::string guid; 793 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier); 794 if (iter != specifier_guid_map_.end()) { 795 guid = iter->second; 796 } else { 797 guid = base::GenerateGUID(); 798 specifier_guid_map_[specifier] = guid; 799 } 800 favorite->SetGuid(guid); 801 NetworkState* network = GetModifiableNetworkState(favorite->path()); 802 if (network) 803 network->SetGuid(guid); 804 } else if (managed->managed_type() == ManagedState::MANAGED_TYPE_NETWORK) { 805 // If the GUID is not set and a corresponding FavoriteState exists, get the 806 // GUID from the FavoriteState. Otherwise it will get set when the Favorite 807 // is created. 808 NetworkState* network = managed->AsNetworkState(); 809 if (!network->guid().empty()) 810 return; 811 // ShillPropertyHandler will always call UpdateManagedStateProperties with 812 // type FAVORITE before type NETWORK, so there should always be a 813 // corresponding FavoriteState here. 814 FavoriteState* favorite = GetModifiableFavoriteState(network->path()); 815 DCHECK(favorite); 816 if (favorite && !favorite->guid().empty()) 817 network->SetGuid(favorite->guid()); 818 } 819} 820 821void NetworkStateHandler::NotifyDeviceListChanged() { 822 NET_LOG_DEBUG("NotifyDeviceListChanged", 823 base::StringPrintf("Size:%" PRIuS, device_list_.size())); 824 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 825 DeviceListChanged()); 826} 827 828DeviceState* NetworkStateHandler::GetModifiableDeviceState( 829 const std::string& device_path) const { 830 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 831 if (!managed) 832 return NULL; 833 return managed->AsDeviceState(); 834} 835 836NetworkState* NetworkStateHandler::GetModifiableNetworkState( 837 const std::string& service_path) const { 838 ManagedState* managed = 839 GetModifiableManagedState(&network_list_, service_path); 840 if (!managed) 841 return NULL; 842 return managed->AsNetworkState(); 843} 844 845FavoriteState* NetworkStateHandler::GetModifiableFavoriteState( 846 const std::string& service_path) const { 847 ManagedState* managed = 848 GetModifiableManagedState(&favorite_list_, service_path); 849 if (!managed) 850 return NULL; 851 return managed->AsFavoriteState(); 852} 853 854ManagedState* NetworkStateHandler::GetModifiableManagedState( 855 const ManagedStateList* managed_list, 856 const std::string& path) const { 857 for (ManagedStateList::const_iterator iter = managed_list->begin(); 858 iter != managed_list->end(); ++iter) { 859 ManagedState* managed = *iter; 860 if (managed->path() == path) 861 return managed; 862 } 863 return NULL; 864} 865 866NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 867 ManagedState::ManagedType type) { 868 switch (type) { 869 case ManagedState::MANAGED_TYPE_NETWORK: 870 return &network_list_; 871 case ManagedState::MANAGED_TYPE_FAVORITE: 872 return &favorite_list_; 873 case ManagedState::MANAGED_TYPE_DEVICE: 874 return &device_list_; 875 } 876 NOTREACHED(); 877 return NULL; 878} 879 880void NetworkStateHandler::OnNetworkConnectionStateChanged( 881 NetworkState* network) { 882 DCHECK(network); 883 std::string event = "NetworkConnectionStateChanged"; 884 if (network->path() == default_network_path_) { 885 event = "Default" + event; 886 if (!network->IsConnectedState()) { 887 NET_LOG_ERROR( 888 "DefaultNetwork is not connected: " + network->connection_state(), 889 network->path()); 890 } 891 } 892 NET_LOG_EVENT(event + ": " + network->connection_state(), 893 GetManagedStateLogName(network)); 894 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 895 NetworkConnectionStateChanged(network)); 896 if (network->path() == default_network_path_) 897 NotifyDefaultNetworkChanged(network); 898} 899 900void NetworkStateHandler::NotifyDefaultNetworkChanged( 901 const NetworkState* default_network) { 902 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 903 DefaultNetworkChanged(default_network)); 904} 905 906void NetworkStateHandler::NotifyNetworkPropertiesUpdated( 907 const NetworkState* network) { 908 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 909 NetworkPropertiesUpdated(network)); 910} 911 912void NetworkStateHandler::ScanCompleted(const std::string& type) { 913 size_t num_callbacks = scan_complete_callbacks_.count(type); 914 NET_LOG_EVENT("ScanCompleted", 915 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks)); 916 if (num_callbacks == 0) 917 return; 918 ScanCallbackList& callback_list = scan_complete_callbacks_[type]; 919 for (ScanCallbackList::iterator iter = callback_list.begin(); 920 iter != callback_list.end(); ++iter) { 921 (*iter).Run(); 922 } 923 scan_complete_callbacks_.erase(type); 924} 925 926std::string NetworkStateHandler::GetTechnologyForType( 927 const NetworkTypePattern& type) const { 928 if (type.MatchesType(shill::kTypeEthernet)) 929 return shill::kTypeEthernet; 930 931 if (type.MatchesType(shill::kTypeWifi)) 932 return shill::kTypeWifi; 933 934 if (type.Equals(NetworkTypePattern::Wimax())) 935 return shill::kTypeWimax; 936 937 // Prefer Wimax over Cellular only if it's available. 938 if (type.MatchesType(shill::kTypeWimax) && 939 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) { 940 return shill::kTypeWimax; 941 } 942 943 if (type.MatchesType(shill::kTypeCellular)) 944 return shill::kTypeCellular; 945 946 NOTREACHED(); 947 return std::string(); 948} 949 950ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType( 951 const NetworkTypePattern& type) const { 952 ScopedVector<std::string> technologies; 953 if (type.MatchesType(shill::kTypeEthernet)) 954 technologies.push_back(new std::string(shill::kTypeEthernet)); 955 if (type.MatchesType(shill::kTypeWifi)) 956 technologies.push_back(new std::string(shill::kTypeWifi)); 957 if (type.MatchesType(shill::kTypeWimax)) 958 technologies.push_back(new std::string(shill::kTypeWimax)); 959 if (type.MatchesType(shill::kTypeCellular)) 960 technologies.push_back(new std::string(shill::kTypeCellular)); 961 if (type.MatchesType(shill::kTypeBluetooth)) 962 technologies.push_back(new std::string(shill::kTypeBluetooth)); 963 if (type.MatchesType(shill::kTypeVPN)) 964 technologies.push_back(new std::string(shill::kTypeVPN)); 965 966 CHECK_GT(technologies.size(), 0ul); 967 return technologies.Pass(); 968} 969 970} // namespace chromeos 971