network_state_handler.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/logging.h" 11#include "base/metrics/histogram.h" 12#include "base/stl_util.h" 13#include "base/strings/string_util.h" 14#include "base/strings/stringprintf.h" 15#include "base/values.h" 16#include "chromeos/network/device_state.h" 17#include "chromeos/network/favorite_state.h" 18#include "chromeos/network/managed_state.h" 19#include "chromeos/network/network_event_log.h" 20#include "chromeos/network/network_state.h" 21#include "chromeos/network/network_state_handler_observer.h" 22#include "chromeos/network/shill_property_handler.h" 23#include "chromeos/network/shill_property_util.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 std::string technology = GetTechnologyForType(type); 131 NET_LOG_USER("SetTechnologyEnabled", 132 base::StringPrintf("%s:%d", technology.c_str(), enabled)); 133 shill_property_handler_->SetTechnologyEnabled( 134 technology, enabled, error_callback); 135 // Signal Device/Technology state changed. 136 NotifyDeviceListChanged(); 137} 138 139const DeviceState* NetworkStateHandler::GetDeviceState( 140 const std::string& device_path) const { 141 const DeviceState* device = GetModifiableDeviceState(device_path); 142 if (device && !device->update_received()) 143 return NULL; 144 return device; 145} 146 147const DeviceState* NetworkStateHandler::GetDeviceStateByType( 148 const NetworkTypePattern& type) const { 149 for (ManagedStateList::const_iterator iter = device_list_.begin(); 150 iter != device_list_.end(); ++iter) { 151 ManagedState* device = *iter; 152 if (!device->update_received()) 153 continue; 154 if (device->Matches(type)) 155 return device->AsDeviceState(); 156 } 157 return NULL; 158} 159 160bool NetworkStateHandler::GetScanningByType( 161 const NetworkTypePattern& type) const { 162 for (ManagedStateList::const_iterator iter = device_list_.begin(); 163 iter != device_list_.end(); ++iter) { 164 const DeviceState* device = (*iter)->AsDeviceState(); 165 DCHECK(device); 166 if (!device->update_received()) 167 continue; 168 if (device->Matches(type) && device->scanning()) 169 return true; 170 } 171 return false; 172} 173 174const NetworkState* NetworkStateHandler::GetNetworkState( 175 const std::string& service_path) const { 176 const NetworkState* network = GetModifiableNetworkState(service_path); 177 if (network && !network->update_received()) 178 return NULL; 179 return network; 180} 181 182const NetworkState* NetworkStateHandler::DefaultNetwork() const { 183 if (default_network_path_.empty()) 184 return NULL; 185 return GetNetworkState(default_network_path_); 186} 187 188const FavoriteState* NetworkStateHandler::DefaultFavoriteNetwork() const { 189 const NetworkState* default_network = DefaultNetwork(); 190 if (!default_network) 191 return NULL; 192 const FavoriteState* default_favorite = 193 GetFavoriteState(default_network->path()); 194 DCHECK(default_network->type() != shill::kTypeWifi || 195 default_favorite) << "No favorite for: " << default_network->path(); 196 DCHECK(!default_favorite || default_favorite->update_received()) 197 << "No update received for: " << default_network->path(); 198 return default_favorite; 199} 200 201const NetworkState* NetworkStateHandler::ConnectedNetworkByType( 202 const NetworkTypePattern& type) const { 203 for (ManagedStateList::const_iterator iter = network_list_.begin(); 204 iter != network_list_.end(); ++iter) { 205 const NetworkState* network = (*iter)->AsNetworkState(); 206 DCHECK(network); 207 if (!network->update_received()) 208 continue; 209 if (!network->IsConnectedState()) 210 break; // Connected networks are listed first. 211 if (network->Matches(type)) 212 return network; 213 } 214 return NULL; 215} 216 217const NetworkState* NetworkStateHandler::ConnectingNetworkByType( 218 const NetworkTypePattern& type) const { 219 for (ManagedStateList::const_iterator iter = network_list_.begin(); 220 iter != network_list_.end(); ++iter) { 221 const NetworkState* network = (*iter)->AsNetworkState(); 222 DCHECK(network); 223 if (!network->update_received() || network->IsConnectedState()) 224 continue; 225 if (!network->IsConnectingState()) 226 break; // Connected and connecting networks are listed first. 227 if (network->Matches(type)) 228 return network; 229 } 230 return NULL; 231} 232 233const NetworkState* NetworkStateHandler::FirstNetworkByType( 234 const NetworkTypePattern& type) const { 235 for (ManagedStateList::const_iterator iter = network_list_.begin(); 236 iter != network_list_.end(); ++iter) { 237 const NetworkState* network = (*iter)->AsNetworkState(); 238 DCHECK(network); 239 if (!network->update_received()) 240 continue; 241 if (network->Matches(type)) 242 return network; 243 } 244 return NULL; 245} 246 247std::string NetworkStateHandler::FormattedHardwareAddressForType( 248 const NetworkTypePattern& type) const { 249 const DeviceState* device = NULL; 250 const NetworkState* network = ConnectedNetworkByType(type); 251 if (network) 252 device = GetDeviceState(network->device_path()); 253 else 254 device = GetDeviceStateByType(type); 255 if (!device) 256 return std::string(); 257 return device->GetFormattedMacAddress(); 258} 259 260void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const { 261 GetNetworkListByType(NetworkTypePattern::Default(), list); 262} 263 264void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type, 265 NetworkStateList* list) const { 266 DCHECK(list); 267 list->clear(); 268 for (ManagedStateList::const_iterator iter = network_list_.begin(); 269 iter != network_list_.end(); ++iter) { 270 const NetworkState* network = (*iter)->AsNetworkState(); 271 DCHECK(network); 272 if (network->update_received() && network->Matches(type)) 273 list->push_back(network); 274 } 275} 276 277void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const { 278 GetDeviceListByType(NetworkTypePattern::Default(), list); 279} 280 281void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type, 282 DeviceStateList* list) const { 283 DCHECK(list); 284 list->clear(); 285 for (ManagedStateList::const_iterator iter = device_list_.begin(); 286 iter != device_list_.end(); ++iter) { 287 const DeviceState* device = (*iter)->AsDeviceState(); 288 DCHECK(device); 289 if (device->update_received() && device->Matches(type)) 290 list->push_back(device); 291 } 292} 293 294void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const { 295 GetFavoriteListByType(NetworkTypePattern::Default(), list); 296} 297 298void NetworkStateHandler::GetFavoriteListByType(const NetworkTypePattern& type, 299 FavoriteStateList* list) const { 300 DCHECK(list); 301 FavoriteStateList result; 302 list->clear(); 303 for (ManagedStateList::const_iterator iter = favorite_list_.begin(); 304 iter != favorite_list_.end(); ++iter) { 305 const FavoriteState* favorite = (*iter)->AsFavoriteState(); 306 DCHECK(favorite); 307 if (favorite->update_received() && favorite->is_favorite() && 308 favorite->Matches(type)) { 309 list->push_back(favorite); 310 } 311 } 312} 313 314const FavoriteState* NetworkStateHandler::GetFavoriteState( 315 const std::string& service_path) const { 316 ManagedState* managed = 317 GetModifiableManagedState(&favorite_list_, service_path); 318 if (!managed) 319 return NULL; 320 const FavoriteState* favorite = managed->AsFavoriteState(); 321 DCHECK(favorite); 322 if (!favorite->update_received() || !favorite->is_favorite()) 323 return NULL; 324 return favorite; 325} 326 327void NetworkStateHandler::RequestScan() const { 328 NET_LOG_USER("RequestScan", ""); 329 shill_property_handler_->RequestScan(); 330} 331 332void NetworkStateHandler::WaitForScan(const std::string& type, 333 const base::Closure& callback) { 334 scan_complete_callbacks_[type].push_back(callback); 335 if (!GetScanningByType(NetworkTypePattern::Primitive(type))) 336 RequestScan(); 337} 338 339void NetworkStateHandler::ConnectToBestWifiNetwork() { 340 NET_LOG_USER("ConnectToBestWifiNetwork", ""); 341 WaitForScan(shill::kTypeWifi, 342 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices, 343 shill_property_handler_->AsWeakPtr())); 344} 345 346void NetworkStateHandler::RequestUpdateForNetwork( 347 const std::string& service_path) { 348 NetworkState* network = GetModifiableNetworkState(service_path); 349 if (network) 350 network->set_update_requested(true); 351 NET_LOG_EVENT("RequestUpdate", service_path); 352 shill_property_handler_->RequestProperties( 353 ManagedState::MANAGED_TYPE_NETWORK, service_path); 354} 355 356void NetworkStateHandler::RequestUpdateForAllNetworks() { 357 NET_LOG_EVENT("RequestUpdateForAllNetworks", ""); 358 for (ManagedStateList::iterator iter = network_list_.begin(); 359 iter != network_list_.end(); ++iter) { 360 ManagedState* network = *iter; 361 network->set_update_requested(true); 362 shill_property_handler_->RequestProperties( 363 ManagedState::MANAGED_TYPE_NETWORK, network->path()); 364 } 365} 366 367void NetworkStateHandler::ClearLastErrorForNetwork( 368 const std::string& service_path) { 369 NetworkState* network = GetModifiableNetworkState(service_path); 370 if (network) 371 network->clear_last_error(); 372} 373 374void NetworkStateHandler::SetCheckPortalList( 375 const std::string& check_portal_list) { 376 NET_LOG_EVENT("SetCheckPortalList", check_portal_list); 377 shill_property_handler_->SetCheckPortalList(check_portal_list); 378} 379 380const FavoriteState* NetworkStateHandler::GetEAPForEthernet( 381 const std::string& service_path) const { 382 const NetworkState* network = GetNetworkState(service_path); 383 if (!network) { 384 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path); 385 return NULL; 386 } 387 if (network->type() != shill::kTypeEthernet) { 388 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path); 389 return NULL; 390 } 391 if (!network->IsConnectedState()) 392 return NULL; 393 394 // The same EAP service is shared for all ethernet services/devices. 395 // However EAP is used/enabled per device and only if the connection was 396 // successfully established. 397 const DeviceState* device = GetDeviceState(network->device_path()); 398 if (!device) { 399 NET_LOG_ERROR( 400 "GetEAPForEthernet", 401 base::StringPrintf("Unknown device %s of connected ethernet service %s", 402 network->device_path().c_str(), 403 service_path.c_str())); 404 return NULL; 405 } 406 if (!device->eap_authentication_completed()) 407 return NULL; 408 409 FavoriteStateList list; 410 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap), 411 &list); 412 if (list.empty()) { 413 NET_LOG_ERROR("GetEAPForEthernet", 414 base::StringPrintf( 415 "Ethernet service %s connected using EAP, but no " 416 "EAP service found.", 417 service_path.c_str())); 418 return NULL; 419 } 420 DCHECK(list.size() == 1); 421 return list.front(); 422} 423 424void NetworkStateHandler::GetNetworkStatePropertiesForTest( 425 base::DictionaryValue* dictionary) const { 426 for (ManagedStateList::const_iterator iter = network_list_.begin(); 427 iter != network_list_.end(); ++iter) { 428 base::DictionaryValue* network_dict = new base::DictionaryValue; 429 (*iter)->AsNetworkState()->GetProperties(network_dict); 430 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict); 431 } 432} 433 434//------------------------------------------------------------------------------ 435// ShillPropertyHandler::Delegate overrides 436 437void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, 438 const base::ListValue& entries) { 439 ManagedStateList* managed_list = GetManagedList(type); 440 NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type), 441 base::StringPrintf("%" PRIuS, entries.GetSize())); 442 // Create a map of existing entries. Assumes all entries in |managed_list| 443 // are unique. 444 std::map<std::string, ManagedState*> managed_map; 445 for (ManagedStateList::iterator iter = managed_list->begin(); 446 iter != managed_list->end(); ++iter) { 447 ManagedState* managed = *iter; 448 DCHECK(!ContainsKey(managed_map, managed->path())); 449 managed_map[managed->path()] = managed; 450 } 451 // Clear the list (pointers are temporarily owned by managed_map). 452 managed_list->clear(); 453 // Updates managed_list and request updates for new entries. 454 std::set<std::string> list_entries; 455 for (base::ListValue::const_iterator iter = entries.begin(); 456 iter != entries.end(); ++iter) { 457 std::string path; 458 (*iter)->GetAsString(&path); 459 if (path.empty() || path == shill::kFlimflamServicePath) { 460 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path); 461 continue; 462 } 463 std::map<std::string, ManagedState*>::iterator found = 464 managed_map.find(path); 465 ManagedState* managed; 466 if (found == managed_map.end()) { 467 if (list_entries.count(path) != 0) { 468 NET_LOG_ERROR("Duplicate entry in list", path); 469 continue; 470 } 471 managed = ManagedState::Create(type, path); 472 managed_list->push_back(managed); 473 } else { 474 managed = found->second; 475 managed_list->push_back(managed); 476 managed_map.erase(found); 477 } 478 list_entries.insert(path); 479 } 480 // Delete any remaining entries in managed_map. 481 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); 482} 483 484void NetworkStateHandler::ProfileListChanged() { 485 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties"); 486 for (ManagedStateList::iterator iter = network_list_.begin(); 487 iter != network_list_.end(); ++iter) { 488 shill_property_handler_->RequestProperties( 489 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path()); 490 } 491} 492 493void NetworkStateHandler::UpdateManagedStateProperties( 494 ManagedState::ManagedType type, 495 const std::string& path, 496 const base::DictionaryValue& properties) { 497 ManagedStateList* managed_list = GetManagedList(type); 498 ManagedState* managed = GetModifiableManagedState(managed_list, path); 499 if (!managed) { 500 if (type != ManagedState::MANAGED_TYPE_FAVORITE) { 501 // The network has been removed from the list of visible networks. 502 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path); 503 return; 504 } 505 // A Favorite may not have been created yet if it was added later (e.g. 506 // through ConfigureService) since ServiceCompleteList updates are not 507 // emitted. Add and update the state here. 508 managed = new FavoriteState(path); 509 managed_list->push_back(managed); 510 } 511 managed->set_update_received(); 512 513 std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived"; 514 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed)); 515 516 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 517 UpdateNetworkStateProperties(managed->AsNetworkState(), properties); 518 } else { 519 // Device, Favorite 520 for (base::DictionaryValue::Iterator iter(properties); 521 !iter.IsAtEnd(); iter.Advance()) { 522 managed->PropertyChanged(iter.key(), iter.value()); 523 } 524 managed->InitialPropertiesReceived(properties); 525 } 526 managed->set_update_requested(false); 527} 528 529void NetworkStateHandler::UpdateNetworkStateProperties( 530 NetworkState* network, 531 const base::DictionaryValue& properties) { 532 DCHECK(network); 533 bool network_property_updated = false; 534 std::string prev_connection_state = network->connection_state(); 535 for (base::DictionaryValue::Iterator iter(properties); 536 !iter.IsAtEnd(); iter.Advance()) { 537 if (network->PropertyChanged(iter.key(), iter.value())) 538 network_property_updated = true; 539 } 540 network_property_updated |= network->InitialPropertiesReceived(properties); 541 // Notify observers of NetworkState changes. 542 if (network_property_updated || network->update_requested()) { 543 // Signal connection state changed after all properties have been updated. 544 if (ConnectionStateChanged(network, prev_connection_state)) 545 OnNetworkConnectionStateChanged(network); 546 NET_LOG_EVENT("NetworkPropertiesUpdated", GetManagedStateLogName(network)); 547 NotifyNetworkPropertiesUpdated(network); 548 } 549} 550 551void NetworkStateHandler::UpdateNetworkServiceProperty( 552 const std::string& service_path, 553 const std::string& key, 554 const base::Value& value) { 555 // Update any associated FavoriteState. 556 ManagedState* favorite = 557 GetModifiableManagedState(&favorite_list_, service_path); 558 bool changed = false; 559 if (favorite) 560 changed |= favorite->PropertyChanged(key, value); 561 562 // Update the NetworkState. 563 NetworkState* network = GetModifiableNetworkState(service_path); 564 if (!network) 565 return; 566 std::string prev_connection_state = network->connection_state(); 567 std::string prev_profile_path = network->profile_path(); 568 changed |= network->PropertyChanged(key, value); 569 if (!changed) 570 return; 571 572 if (key == shill::kStateProperty) { 573 if (ConnectionStateChanged(network, prev_connection_state)) { 574 OnNetworkConnectionStateChanged(network); 575 // If the connection state changes, other properties such as IPConfig 576 // may have changed, so request a full update. 577 RequestUpdateForNetwork(service_path); 578 } 579 } else { 580 std::string value_str; 581 value.GetAsString(&value_str); 582 // Some property changes are noisy and not interesting: 583 // * Wifi SignalStrength 584 // * WifiFrequencyList updates 585 // * Device property changes to "/" (occurs before a service is removed) 586 if (key != shill::kSignalStrengthProperty && 587 key != shill::kWifiFrequencyListProperty && 588 (key != shill::kDeviceProperty || value_str != "/")) { 589 std::string log_event = "NetworkPropertyUpdated"; 590 // Trigger a default network update for interesting changes only. 591 if (network->path() == default_network_path_) { 592 NotifyDefaultNetworkChanged(network); 593 log_event = "Default" + log_event; 594 } 595 // Log event. 596 std::string detail = network->name() + "." + key; 597 detail += " = " + network_event_log::ValueAsString(value); 598 network_event_log::LogLevel log_level; 599 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) { 600 log_level = network_event_log::LOG_LEVEL_ERROR; 601 } else { 602 log_level = network_event_log::LOG_LEVEL_EVENT; 603 } 604 NET_LOG_LEVEL(log_level, log_event, detail); 605 } 606 } 607 608 // All property updates signal 'NetworkPropertiesUpdated'. 609 NotifyNetworkPropertiesUpdated(network); 610 611 // If added to a Profile, request a full update so that a FavoriteState 612 // gets created. 613 if (prev_profile_path.empty() && !network->profile_path().empty()) 614 RequestUpdateForNetwork(service_path); 615} 616 617void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path, 618 const std::string& key, 619 const base::Value& value) { 620 DeviceState* device = GetModifiableDeviceState(device_path); 621 if (!device) 622 return; 623 if (!device->PropertyChanged(key, value)) 624 return; 625 626 std::string detail = device->name() + "." + key; 627 detail += " = " + network_event_log::ValueAsString(value); 628 NET_LOG_EVENT("DevicePropertyUpdated", detail); 629 630 NotifyDeviceListChanged(); 631 632 if (key == shill::kScanningProperty && device->scanning() == false) 633 ScanCompleted(device->type()); 634 if (key == shill::kEapAuthenticationCompletedProperty) { 635 // Notify a change for each Ethernet service using this device. 636 NetworkStateList ethernet_services; 637 GetNetworkListByType(NetworkTypePattern::Ethernet(), ðernet_services); 638 for (NetworkStateList::const_iterator it = ethernet_services.begin(); 639 it != ethernet_services.end(); ++it) { 640 const NetworkState* ethernet_service = *it; 641 if (ethernet_service->update_received() || 642 ethernet_service->device_path() != device->path()) { 643 continue; 644 } 645 RequestUpdateForNetwork(ethernet_service->path()); 646 } 647 } 648} 649 650void NetworkStateHandler::CheckPortalListChanged( 651 const std::string& check_portal_list) { 652 check_portal_list_ = check_portal_list; 653} 654 655void NetworkStateHandler::TechnologyListChanged() { 656 // Eventually we would like to replace Technology state with Device state. 657 // For now, treat technology state changes as device list changes. 658 NotifyDeviceListChanged(); 659} 660 661void NetworkStateHandler::ManagedStateListChanged( 662 ManagedState::ManagedType type) { 663 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 664 // Notify observers that the list of networks has changed. 665 NET_LOG_EVENT("NetworkListChanged", 666 base::StringPrintf("Size:%" PRIuS, network_list_.size())); 667 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 668 NetworkListChanged()); 669 // Update UMA stats. 670 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", network_list_.size()); 671 } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) { 672 NET_LOG_DEBUG("FavoriteListChanged", 673 base::StringPrintf("Size:%" PRIuS, favorite_list_.size())); 674 // The FavoriteState list only changes when the NetworkState list changes, 675 // so no need to signal observers here again. 676 677 // Update UMA stats. 678 size_t shared = 0, unshared = 0; 679 for (ManagedStateList::iterator iter = favorite_list_.begin(); 680 iter != favorite_list_.end(); ++iter) { 681 FavoriteState* favorite = (*iter)->AsFavoriteState(); 682 if (!favorite->is_favorite()) 683 continue; 684 if (favorite->IsPrivate()) 685 ++unshared; 686 else 687 ++shared; 688 } 689 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared); 690 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared); 691 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 692 NotifyDeviceListChanged(); 693 } else { 694 NOTREACHED(); 695 } 696} 697 698void NetworkStateHandler::DefaultNetworkServiceChanged( 699 const std::string& service_path) { 700 // Shill uses '/' for empty service path values; check explicitly for that. 701 const char* kEmptyServicePath = "/"; 702 if (service_path == kEmptyServicePath) 703 default_network_path_.clear(); 704 else 705 default_network_path_ = service_path; 706 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_); 707 const NetworkState* network = NULL; 708 if (!default_network_path_.empty()) { 709 network = GetNetworkState(default_network_path_); 710 if (!network) { 711 // If NetworkState is not available yet, do not notify observers here, 712 // they will be notified when the state is received. 713 NET_LOG_DEBUG("Default NetworkState not available", 714 default_network_path_); 715 return; 716 } 717 } 718 if (network && !network->IsConnectedState()) { 719 NET_LOG_ERROR( 720 "DefaultNetwork is not connected: " + network->connection_state(), 721 network->path()); 722 } 723 NotifyDefaultNetworkChanged(network); 724} 725 726//------------------------------------------------------------------------------ 727// Private methods 728 729void NetworkStateHandler::NotifyDeviceListChanged() { 730 NET_LOG_DEBUG("NotifyDeviceListChanged", 731 base::StringPrintf("Size:%" PRIuS, device_list_.size())); 732 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 733 DeviceListChanged()); 734} 735 736DeviceState* NetworkStateHandler::GetModifiableDeviceState( 737 const std::string& device_path) const { 738 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 739 if (!managed) 740 return NULL; 741 return managed->AsDeviceState(); 742} 743 744NetworkState* NetworkStateHandler::GetModifiableNetworkState( 745 const std::string& service_path) const { 746 ManagedState* managed = 747 GetModifiableManagedState(&network_list_, service_path); 748 if (!managed) 749 return NULL; 750 return managed->AsNetworkState(); 751} 752 753ManagedState* NetworkStateHandler::GetModifiableManagedState( 754 const ManagedStateList* managed_list, 755 const std::string& path) const { 756 for (ManagedStateList::const_iterator iter = managed_list->begin(); 757 iter != managed_list->end(); ++iter) { 758 ManagedState* managed = *iter; 759 if (managed->path() == path) 760 return managed; 761 } 762 return NULL; 763} 764 765NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 766 ManagedState::ManagedType type) { 767 switch (type) { 768 case ManagedState::MANAGED_TYPE_NETWORK: 769 return &network_list_; 770 case ManagedState::MANAGED_TYPE_FAVORITE: 771 return &favorite_list_; 772 case ManagedState::MANAGED_TYPE_DEVICE: 773 return &device_list_; 774 } 775 NOTREACHED(); 776 return NULL; 777} 778 779void NetworkStateHandler::OnNetworkConnectionStateChanged( 780 NetworkState* network) { 781 DCHECK(network); 782 std::string event = "NetworkConnectionStateChanged"; 783 if (network->path() == default_network_path_) { 784 event = "Default" + event; 785 if (!network->IsConnectedState()) { 786 NET_LOG_ERROR( 787 "DefaultNetwork is not connected: " + network->connection_state(), 788 network->path()); 789 } 790 } 791 NET_LOG_EVENT(event + ": " + network->connection_state(), 792 GetManagedStateLogName(network)); 793 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 794 NetworkConnectionStateChanged(network)); 795 if (network->path() == default_network_path_) 796 NotifyDefaultNetworkChanged(network); 797} 798 799void NetworkStateHandler::NotifyDefaultNetworkChanged( 800 const NetworkState* default_network) { 801 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 802 DefaultNetworkChanged(default_network)); 803} 804 805void NetworkStateHandler::NotifyNetworkPropertiesUpdated( 806 const NetworkState* network) { 807 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 808 NetworkPropertiesUpdated(network)); 809} 810 811void NetworkStateHandler::ScanCompleted(const std::string& type) { 812 size_t num_callbacks = scan_complete_callbacks_.count(type); 813 NET_LOG_EVENT("ScanCompleted", 814 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks)); 815 if (num_callbacks == 0) 816 return; 817 ScanCallbackList& callback_list = scan_complete_callbacks_[type]; 818 for (ScanCallbackList::iterator iter = callback_list.begin(); 819 iter != callback_list.end(); ++iter) { 820 (*iter).Run(); 821 } 822 scan_complete_callbacks_.erase(type); 823} 824 825std::string NetworkStateHandler::GetTechnologyForType( 826 const NetworkTypePattern& type) const { 827 if (type.MatchesType(shill::kTypeEthernet)) 828 return shill::kTypeEthernet; 829 830 if (type.MatchesType(shill::kTypeWifi)) 831 return shill::kTypeWifi; 832 833 if (type.Equals(NetworkTypePattern::Wimax())) 834 return shill::kTypeWimax; 835 836 // Prefer Wimax over Cellular only if it's available. 837 if (type.MatchesType(shill::kTypeWimax) && 838 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) { 839 return shill::kTypeWimax; 840 } 841 842 if (type.MatchesType(shill::kTypeCellular)) 843 return shill::kTypeCellular; 844 845 NOTREACHED(); 846 return std::string(); 847} 848 849} // namespace chromeos 850