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