network_state_handler.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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->IsFavorite() && 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->IsFavorite()) 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::ClearLastErrorForNetwork( 357 const std::string& service_path) { 358 NetworkState* network = GetModifiableNetworkState(service_path); 359 if (network) 360 network->clear_last_error(); 361} 362 363void NetworkStateHandler::SetCheckPortalList( 364 const std::string& check_portal_list) { 365 NET_LOG_EVENT("SetCheckPortalList", check_portal_list); 366 shill_property_handler_->SetCheckPortalList(check_portal_list); 367} 368 369const FavoriteState* NetworkStateHandler::GetEAPForEthernet( 370 const std::string& service_path) const { 371 const NetworkState* network = GetNetworkState(service_path); 372 if (!network) { 373 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path); 374 return NULL; 375 } 376 if (network->type() != shill::kTypeEthernet) { 377 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path); 378 return NULL; 379 } 380 if (!network->IsConnectedState()) 381 return NULL; 382 383 // The same EAP service is shared for all ethernet services/devices. 384 // However EAP is used/enabled per device and only if the connection was 385 // successfully established. 386 const DeviceState* device = GetDeviceState(network->device_path()); 387 if (!device) { 388 NET_LOG_ERROR( 389 "GetEAPForEthernet", 390 base::StringPrintf("Unknown device %s of connected ethernet service %s", 391 network->device_path().c_str(), 392 service_path.c_str())); 393 return NULL; 394 } 395 if (!device->eap_authentication_completed()) 396 return NULL; 397 398 FavoriteStateList list; 399 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap), 400 &list); 401 if (list.empty()) { 402 NET_LOG_ERROR("GetEAPForEthernet", 403 base::StringPrintf( 404 "Ethernet service %s connected using EAP, but no " 405 "EAP service found.", 406 service_path.c_str())); 407 return NULL; 408 } 409 DCHECK(list.size() == 1); 410 return list.front(); 411} 412 413void NetworkStateHandler::GetNetworkStatePropertiesForTest( 414 base::DictionaryValue* dictionary) const { 415 for (ManagedStateList::const_iterator iter = network_list_.begin(); 416 iter != network_list_.end(); ++iter) { 417 base::DictionaryValue* network_dict = new base::DictionaryValue; 418 (*iter)->AsNetworkState()->GetProperties(network_dict); 419 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict); 420 } 421} 422 423//------------------------------------------------------------------------------ 424// ShillPropertyHandler::Delegate overrides 425 426void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, 427 const base::ListValue& entries) { 428 ManagedStateList* managed_list = GetManagedList(type); 429 NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type), 430 base::StringPrintf("%" PRIuS, entries.GetSize())); 431 // Create a map of existing entries. Assumes all entries in |managed_list| 432 // are unique. 433 std::map<std::string, ManagedState*> managed_map; 434 for (ManagedStateList::iterator iter = managed_list->begin(); 435 iter != managed_list->end(); ++iter) { 436 ManagedState* managed = *iter; 437 DCHECK(!ContainsKey(managed_map, managed->path())); 438 managed_map[managed->path()] = managed; 439 } 440 // Clear the list (pointers are temporarily owned by managed_map). 441 managed_list->clear(); 442 // Updates managed_list and request updates for new entries. 443 std::set<std::string> list_entries; 444 for (base::ListValue::const_iterator iter = entries.begin(); 445 iter != entries.end(); ++iter) { 446 std::string path; 447 (*iter)->GetAsString(&path); 448 if (path.empty() || path == shill::kFlimflamServicePath) { 449 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path); 450 continue; 451 } 452 std::map<std::string, ManagedState*>::iterator found = 453 managed_map.find(path); 454 ManagedState* managed; 455 if (found == managed_map.end()) { 456 if (list_entries.count(path) != 0) { 457 NET_LOG_ERROR("Duplicate entry in list", path); 458 continue; 459 } 460 managed = ManagedState::Create(type, path); 461 managed_list->push_back(managed); 462 } else { 463 managed = found->second; 464 managed_list->push_back(managed); 465 managed_map.erase(found); 466 } 467 list_entries.insert(path); 468 } 469 // Delete any remaining entries in managed_map. 470 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); 471} 472 473void NetworkStateHandler::ProfileListChanged() { 474 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties"); 475 for (ManagedStateList::iterator iter = favorite_list_.begin(); 476 iter != favorite_list_.end(); ++iter) { 477 shill_property_handler_->RequestProperties( 478 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path()); 479 } 480} 481 482void NetworkStateHandler::UpdateManagedStateProperties( 483 ManagedState::ManagedType type, 484 const std::string& path, 485 const base::DictionaryValue& properties) { 486 ManagedStateList* managed_list = GetManagedList(type); 487 ManagedState* managed = GetModifiableManagedState(managed_list, path); 488 if (!managed) { 489 if (type != ManagedState::MANAGED_TYPE_FAVORITE) { 490 // The network has been removed from the list of visible networks. 491 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path); 492 return; 493 } 494 // A Favorite may not have been created yet if it was added later (e.g. 495 // through ConfigureService) since ServiceCompleteList updates are not 496 // emitted. Add and update the state here. 497 managed = new FavoriteState(path); 498 managed_list->push_back(managed); 499 } 500 managed->set_update_received(); 501 502 std::string desc = GetManagedStateLogType(managed) + " Properties Received"; 503 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed)); 504 505 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 506 UpdateNetworkStateProperties(managed->AsNetworkState(), properties); 507 } else { 508 // Device, Favorite 509 for (base::DictionaryValue::Iterator iter(properties); 510 !iter.IsAtEnd(); iter.Advance()) { 511 managed->PropertyChanged(iter.key(), iter.value()); 512 } 513 managed->InitialPropertiesReceived(properties); 514 } 515 managed->set_update_requested(false); 516} 517 518void NetworkStateHandler::UpdateNetworkStateProperties( 519 NetworkState* network, 520 const base::DictionaryValue& properties) { 521 DCHECK(network); 522 bool network_property_updated = false; 523 std::string prev_connection_state = network->connection_state(); 524 for (base::DictionaryValue::Iterator iter(properties); 525 !iter.IsAtEnd(); iter.Advance()) { 526 if (network->PropertyChanged(iter.key(), iter.value())) 527 network_property_updated = true; 528 } 529 network_property_updated |= network->InitialPropertiesReceived(properties); 530 // Notify observers of NetworkState changes. 531 if (network_property_updated || network->update_requested()) { 532 // Signal connection state changed after all properties have been updated. 533 if (ConnectionStateChanged(network, prev_connection_state)) 534 OnNetworkConnectionStateChanged(network); 535 NET_LOG_EVENT("NetworkPropertiesUpdated", GetManagedStateLogName(network)); 536 NotifyNetworkPropertiesUpdated(network); 537 } 538} 539 540void NetworkStateHandler::UpdateNetworkServiceProperty( 541 const std::string& service_path, 542 const std::string& key, 543 const base::Value& value) { 544 // Update any associated FavoriteState. 545 ManagedState* favorite = 546 GetModifiableManagedState(&favorite_list_, service_path); 547 bool changed = false; 548 if (favorite) 549 changed |= favorite->PropertyChanged(key, value); 550 551 // Update the NetworkState. 552 NetworkState* network = GetModifiableNetworkState(service_path); 553 if (!network) 554 return; 555 std::string prev_connection_state = network->connection_state(); 556 std::string prev_profile_path = network->profile_path(); 557 changed |= network->PropertyChanged(key, value); 558 if (!changed) 559 return; 560 561 if (key == shill::kStateProperty) { 562 if (ConnectionStateChanged(network, prev_connection_state)) { 563 OnNetworkConnectionStateChanged(network); 564 // If the connection state changes, other properties such as IPConfig 565 // may have changed, so request a full update. 566 RequestUpdateForNetwork(service_path); 567 } 568 } else { 569 std::string value_str; 570 value.GetAsString(&value_str); 571 // Some property changes are noisy and not interesting: 572 // * Wifi SignalStrength 573 // * WifiFrequencyList updates 574 // * Device property changes to "/" (occurs before a service is removed) 575 if (key != shill::kSignalStrengthProperty && 576 key != shill::kWifiFrequencyListProperty && 577 (key != shill::kDeviceProperty || value_str != "/")) { 578 std::string log_event = "NetworkPropertyUpdated"; 579 // Trigger a default network update for interesting changes only. 580 if (network->path() == default_network_path_) { 581 NotifyDefaultNetworkChanged(network); 582 log_event = "Default" + log_event; 583 } 584 // Log event. 585 std::string detail = network->name() + "." + key; 586 detail += " = " + network_event_log::ValueAsString(value); 587 network_event_log::LogLevel log_level; 588 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) { 589 log_level = network_event_log::LOG_LEVEL_ERROR; 590 } else { 591 log_level = network_event_log::LOG_LEVEL_EVENT; 592 } 593 NET_LOG_LEVEL(log_level, log_event, detail); 594 } 595 } 596 597 // All property updates signal 'NetworkPropertiesUpdated'. 598 NotifyNetworkPropertiesUpdated(network); 599 600 // If added to a Profile, request a full update so that a FavoriteState 601 // gets created. 602 if (prev_profile_path.empty() && !network->profile_path().empty()) 603 RequestUpdateForNetwork(service_path); 604} 605 606void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path, 607 const std::string& key, 608 const base::Value& value) { 609 DeviceState* device = GetModifiableDeviceState(device_path); 610 if (!device) 611 return; 612 if (!device->PropertyChanged(key, value)) 613 return; 614 615 std::string detail = device->name() + "." + key; 616 detail += " = " + network_event_log::ValueAsString(value); 617 NET_LOG_EVENT("DevicePropertyUpdated", detail); 618 619 NotifyDeviceListChanged(); 620 621 if (key == shill::kScanningProperty && device->scanning() == false) 622 ScanCompleted(device->type()); 623 if (key == shill::kEapAuthenticationCompletedProperty) { 624 // Notify a change for each Ethernet service using this device. 625 NetworkStateList ethernet_services; 626 GetNetworkListByType(NetworkTypePattern::Ethernet(), ðernet_services); 627 for (NetworkStateList::const_iterator it = ethernet_services.begin(); 628 it != ethernet_services.end(); ++it) { 629 const NetworkState* ethernet_service = *it; 630 if (ethernet_service->update_received() || 631 ethernet_service->device_path() != device->path()) { 632 continue; 633 } 634 RequestUpdateForNetwork(ethernet_service->path()); 635 } 636 } 637} 638 639void NetworkStateHandler::CheckPortalListChanged( 640 const std::string& check_portal_list) { 641 check_portal_list_ = check_portal_list; 642} 643 644void NetworkStateHandler::TechnologyListChanged() { 645 // Eventually we would like to replace Technology state with Device state. 646 // For now, treat technology state changes as device list changes. 647 NotifyDeviceListChanged(); 648} 649 650void NetworkStateHandler::ManagedStateListChanged( 651 ManagedState::ManagedType type) { 652 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 653 // Notify observers that the list of networks has changed. 654 NET_LOG_EVENT("NetworkListChanged", 655 base::StringPrintf("Size:%" PRIuS, network_list_.size())); 656 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 657 NetworkListChanged()); 658 // Update UMA stats. 659 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", network_list_.size()); 660 } else if (type == ManagedState::MANAGED_TYPE_FAVORITE) { 661 NET_LOG_DEBUG("FavoriteListChanged", 662 base::StringPrintf("Size:%" PRIuS, favorite_list_.size())); 663 // The FavoriteState list only changes when the NetworkState list changes, 664 // so no need to signal observers here again. 665 666 // Update UMA stats. 667 size_t shared = 0, unshared = 0; 668 for (ManagedStateList::iterator iter = favorite_list_.begin(); 669 iter != favorite_list_.end(); ++iter) { 670 FavoriteState* favorite = (*iter)->AsFavoriteState(); 671 if (!favorite->IsFavorite()) 672 continue; 673 if (favorite->IsPrivate()) 674 ++unshared; 675 else 676 ++shared; 677 } 678 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared); 679 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared); 680 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 681 NotifyDeviceListChanged(); 682 } else { 683 NOTREACHED(); 684 } 685} 686 687void NetworkStateHandler::DefaultNetworkServiceChanged( 688 const std::string& service_path) { 689 // Shill uses '/' for empty service path values; check explicitly for that. 690 const char* kEmptyServicePath = "/"; 691 if (service_path == kEmptyServicePath) 692 default_network_path_.clear(); 693 else 694 default_network_path_ = service_path; 695 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_); 696 const NetworkState* network = NULL; 697 if (!default_network_path_.empty()) { 698 network = GetNetworkState(default_network_path_); 699 if (!network) { 700 // If NetworkState is not available yet, do not notify observers here, 701 // they will be notified when the state is received. 702 NET_LOG_DEBUG("Default NetworkState not available", 703 default_network_path_); 704 return; 705 } 706 } 707 if (network && !network->IsConnectedState()) { 708 NET_LOG_ERROR( 709 "DefaultNetwork is not connected: " + network->connection_state(), 710 network->path()); 711 } 712 NotifyDefaultNetworkChanged(network); 713} 714 715//------------------------------------------------------------------------------ 716// Private methods 717 718void NetworkStateHandler::NotifyDeviceListChanged() { 719 NET_LOG_DEBUG("NotifyDeviceListChanged", 720 base::StringPrintf("Size:%" PRIuS, device_list_.size())); 721 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 722 DeviceListChanged()); 723} 724 725DeviceState* NetworkStateHandler::GetModifiableDeviceState( 726 const std::string& device_path) const { 727 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 728 if (!managed) 729 return NULL; 730 return managed->AsDeviceState(); 731} 732 733NetworkState* NetworkStateHandler::GetModifiableNetworkState( 734 const std::string& service_path) const { 735 ManagedState* managed = 736 GetModifiableManagedState(&network_list_, service_path); 737 if (!managed) 738 return NULL; 739 return managed->AsNetworkState(); 740} 741 742ManagedState* NetworkStateHandler::GetModifiableManagedState( 743 const ManagedStateList* managed_list, 744 const std::string& path) const { 745 for (ManagedStateList::const_iterator iter = managed_list->begin(); 746 iter != managed_list->end(); ++iter) { 747 ManagedState* managed = *iter; 748 if (managed->path() == path) 749 return managed; 750 } 751 return NULL; 752} 753 754NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 755 ManagedState::ManagedType type) { 756 switch (type) { 757 case ManagedState::MANAGED_TYPE_NETWORK: 758 return &network_list_; 759 case ManagedState::MANAGED_TYPE_FAVORITE: 760 return &favorite_list_; 761 case ManagedState::MANAGED_TYPE_DEVICE: 762 return &device_list_; 763 } 764 NOTREACHED(); 765 return NULL; 766} 767 768void NetworkStateHandler::OnNetworkConnectionStateChanged( 769 NetworkState* network) { 770 DCHECK(network); 771 std::string event = "NetworkConnectionStateChanged"; 772 if (network->path() == default_network_path_) { 773 event = "Default" + event; 774 if (!network->IsConnectedState()) { 775 NET_LOG_ERROR( 776 "DefaultNetwork is not connected: " + network->connection_state(), 777 network->path()); 778 } 779 } 780 NET_LOG_EVENT(event + ": " + network->connection_state(), 781 GetManagedStateLogName(network)); 782 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 783 NetworkConnectionStateChanged(network)); 784 if (network->path() == default_network_path_) 785 NotifyDefaultNetworkChanged(network); 786} 787 788void NetworkStateHandler::NotifyDefaultNetworkChanged( 789 const NetworkState* default_network) { 790 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 791 DefaultNetworkChanged(default_network)); 792} 793 794void NetworkStateHandler::NotifyNetworkPropertiesUpdated( 795 const NetworkState* network) { 796 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 797 NetworkPropertiesUpdated(network)); 798} 799 800void NetworkStateHandler::ScanCompleted(const std::string& type) { 801 size_t num_callbacks = scan_complete_callbacks_.count(type); 802 NET_LOG_EVENT("ScanCompleted", 803 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks)); 804 if (num_callbacks == 0) 805 return; 806 ScanCallbackList& callback_list = scan_complete_callbacks_[type]; 807 for (ScanCallbackList::iterator iter = callback_list.begin(); 808 iter != callback_list.end(); ++iter) { 809 (*iter).Run(); 810 } 811 scan_complete_callbacks_.erase(type); 812} 813 814std::string NetworkStateHandler::GetTechnologyForType( 815 const NetworkTypePattern& type) const { 816 if (type.MatchesType(shill::kTypeEthernet)) 817 return shill::kTypeEthernet; 818 819 if (type.MatchesType(shill::kTypeWifi)) 820 return shill::kTypeWifi; 821 822 if (type.Equals(NetworkTypePattern::Wimax())) 823 return shill::kTypeWimax; 824 825 // Prefer Wimax over Cellular only if it's available. 826 if (type.MatchesType(shill::kTypeWimax) && 827 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) { 828 return shill::kTypeWimax; 829 } 830 831 if (type.MatchesType(shill::kTypeCellular)) 832 return shill::kTypeCellular; 833 834 NOTREACHED(); 835 return std::string(); 836} 837 838} // namespace chromeos 839