network_state_handler.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 (network_list_.empty()) 184 return NULL; 185 const NetworkState* network = network_list_.front()->AsNetworkState(); 186 DCHECK(network); 187 if (!network->update_received() || !network->IsConnectedState()) 188 return NULL; 189 return network; 190} 191 192const FavoriteState* NetworkStateHandler::DefaultFavoriteNetwork() const { 193 const NetworkState* default_network = DefaultNetwork(); 194 if (!default_network) 195 return NULL; 196 const FavoriteState* default_favorite = 197 GetFavoriteState(default_network->path()); 198 DCHECK(default_favorite); 199 DCHECK(default_favorite->update_received()); 200 return default_favorite; 201} 202 203const NetworkState* NetworkStateHandler::ConnectedNetworkByType( 204 const NetworkTypePattern& type) const { 205 for (ManagedStateList::const_iterator iter = network_list_.begin(); 206 iter != network_list_.end(); ++iter) { 207 const NetworkState* network = (*iter)->AsNetworkState(); 208 DCHECK(network); 209 if (!network->update_received()) 210 continue; 211 if (!network->IsConnectedState()) 212 break; // Connected networks are listed first. 213 if (network->Matches(type)) 214 return network; 215 } 216 return NULL; 217} 218 219const NetworkState* NetworkStateHandler::ConnectingNetworkByType( 220 const NetworkTypePattern& type) const { 221 for (ManagedStateList::const_iterator iter = network_list_.begin(); 222 iter != network_list_.end(); ++iter) { 223 const NetworkState* network = (*iter)->AsNetworkState(); 224 DCHECK(network); 225 if (!network->update_received() || network->IsConnectedState()) 226 continue; 227 if (!network->IsConnectingState()) 228 break; // Connected and connecting networks are listed first. 229 if (network->Matches(type)) 230 return network; 231 } 232 return NULL; 233} 234 235const NetworkState* NetworkStateHandler::FirstNetworkByType( 236 const NetworkTypePattern& type) const { 237 for (ManagedStateList::const_iterator iter = network_list_.begin(); 238 iter != network_list_.end(); ++iter) { 239 const NetworkState* network = (*iter)->AsNetworkState(); 240 DCHECK(network); 241 if (!network->update_received()) 242 continue; 243 if (network->Matches(type)) 244 return network; 245 } 246 return NULL; 247} 248 249std::string NetworkStateHandler::FormattedHardwareAddressForType( 250 const NetworkTypePattern& type) const { 251 const DeviceState* device = NULL; 252 const NetworkState* network = ConnectedNetworkByType(type); 253 if (network) 254 device = GetDeviceState(network->device_path()); 255 else 256 device = GetDeviceStateByType(type); 257 if (!device) 258 return std::string(); 259 return device->GetFormattedMacAddress(); 260} 261 262void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const { 263 GetNetworkListByType(NetworkTypePattern::Default(), list); 264} 265 266void NetworkStateHandler::GetNetworkListByType(const NetworkTypePattern& type, 267 NetworkStateList* list) const { 268 DCHECK(list); 269 list->clear(); 270 for (ManagedStateList::const_iterator iter = network_list_.begin(); 271 iter != network_list_.end(); ++iter) { 272 const NetworkState* network = (*iter)->AsNetworkState(); 273 DCHECK(network); 274 if (network->update_received() && network->Matches(type)) 275 list->push_back(network); 276 } 277} 278 279void NetworkStateHandler::GetDeviceList(DeviceStateList* list) const { 280 GetDeviceListByType(NetworkTypePattern::Default(), list); 281} 282 283void NetworkStateHandler::GetDeviceListByType(const NetworkTypePattern& type, 284 DeviceStateList* list) const { 285 DCHECK(list); 286 list->clear(); 287 for (ManagedStateList::const_iterator iter = device_list_.begin(); 288 iter != device_list_.end(); ++iter) { 289 const DeviceState* device = (*iter)->AsDeviceState(); 290 DCHECK(device); 291 if (device->update_received() && device->Matches(type)) 292 list->push_back(device); 293 } 294} 295 296void NetworkStateHandler::GetFavoriteList(FavoriteStateList* list) const { 297 GetFavoriteListByType(NetworkTypePattern::Default(), list); 298} 299 300void NetworkStateHandler::GetFavoriteListByType(const NetworkTypePattern& type, 301 FavoriteStateList* list) const { 302 DCHECK(list); 303 FavoriteStateList result; 304 list->clear(); 305 for (ManagedStateList::const_iterator iter = favorite_list_.begin(); 306 iter != favorite_list_.end(); ++iter) { 307 const FavoriteState* favorite = (*iter)->AsFavoriteState(); 308 DCHECK(favorite); 309 if (favorite->update_received() && favorite->is_favorite() && 310 favorite->Matches(type)) { 311 list->push_back(favorite); 312 } 313 } 314} 315 316const FavoriteState* NetworkStateHandler::GetFavoriteState( 317 const std::string& service_path) const { 318 ManagedState* managed = 319 GetModifiableManagedState(&favorite_list_, service_path); 320 if (!managed) 321 return NULL; 322 const FavoriteState* favorite = managed->AsFavoriteState(); 323 DCHECK(favorite); 324 if (!favorite->update_received() || !favorite->is_favorite()) 325 return NULL; 326 return favorite; 327} 328 329void NetworkStateHandler::RequestScan() const { 330 NET_LOG_USER("RequestScan", ""); 331 shill_property_handler_->RequestScan(); 332} 333 334void NetworkStateHandler::WaitForScan(const std::string& type, 335 const base::Closure& callback) { 336 scan_complete_callbacks_[type].push_back(callback); 337 if (!GetScanningByType(NetworkTypePattern::Primitive(type))) 338 RequestScan(); 339} 340 341void NetworkStateHandler::ConnectToBestWifiNetwork() { 342 NET_LOG_USER("ConnectToBestWifiNetwork", ""); 343 WaitForScan(shill::kTypeWifi, 344 base::Bind(&internal::ShillPropertyHandler::ConnectToBestServices, 345 shill_property_handler_->AsWeakPtr())); 346} 347 348void NetworkStateHandler::RequestUpdateForNetwork( 349 const std::string& service_path) { 350 NetworkState* network = GetModifiableNetworkState(service_path); 351 if (network) 352 network->set_update_requested(true); 353 NET_LOG_EVENT("RequestUpdate", service_path); 354 shill_property_handler_->RequestProperties( 355 ManagedState::MANAGED_TYPE_NETWORK, service_path); 356} 357 358void NetworkStateHandler::RequestUpdateForAllNetworks() { 359 NET_LOG_EVENT("RequestUpdateForAllNetworks", ""); 360 for (ManagedStateList::iterator iter = network_list_.begin(); 361 iter != network_list_.end(); ++iter) { 362 ManagedState* network = *iter; 363 network->set_update_requested(true); 364 shill_property_handler_->RequestProperties( 365 ManagedState::MANAGED_TYPE_NETWORK, network->path()); 366 } 367} 368 369void NetworkStateHandler::SetCheckPortalList( 370 const std::string& check_portal_list) { 371 NET_LOG_EVENT("SetCheckPortalList", check_portal_list); 372 shill_property_handler_->SetCheckPortalList(check_portal_list); 373} 374 375const FavoriteState* NetworkStateHandler::GetEAPForEthernet( 376 const std::string& service_path) const { 377 const NetworkState* network = GetNetworkState(service_path); 378 if (!network) { 379 NET_LOG_ERROR("GetEAPForEthernet", "Unknown service path " + service_path); 380 return NULL; 381 } 382 if (network->type() != shill::kTypeEthernet) { 383 NET_LOG_ERROR("GetEAPForEthernet", "Not of type Ethernet: " + service_path); 384 return NULL; 385 } 386 if (!network->IsConnectedState()) 387 return NULL; 388 389 // The same EAP service is shared for all ethernet services/devices. 390 // However EAP is used/enabled per device and only if the connection was 391 // successfully established. 392 const DeviceState* device = GetDeviceState(network->device_path()); 393 if (!device) { 394 NET_LOG_ERROR( 395 "GetEAPForEthernet", 396 base::StringPrintf("Unknown device %s of connected ethernet service %s", 397 network->device_path().c_str(), 398 service_path.c_str())); 399 return NULL; 400 } 401 if (!device->eap_authentication_completed()) 402 return NULL; 403 404 FavoriteStateList list; 405 GetFavoriteListByType(NetworkTypePattern::Primitive(shill::kTypeEthernetEap), 406 &list); 407 if (list.empty()) { 408 NET_LOG_ERROR("GetEAPForEthernet", 409 base::StringPrintf( 410 "Ethernet service %s connected using EAP, but no " 411 "EAP service found.", 412 service_path.c_str())); 413 return NULL; 414 } 415 DCHECK(list.size() == 1); 416 return list.front(); 417} 418 419void NetworkStateHandler::GetNetworkStatePropertiesForTest( 420 base::DictionaryValue* dictionary) const { 421 for (ManagedStateList::const_iterator iter = network_list_.begin(); 422 iter != network_list_.end(); ++iter) { 423 base::DictionaryValue* network_dict = new base::DictionaryValue; 424 (*iter)->AsNetworkState()->GetProperties(network_dict); 425 dictionary->SetWithoutPathExpansion((*iter)->path(), network_dict); 426 } 427} 428 429//------------------------------------------------------------------------------ 430// ShillPropertyHandler::Delegate overrides 431 432void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, 433 const base::ListValue& entries) { 434 ManagedStateList* managed_list = GetManagedList(type); 435 NET_LOG_DEBUG(base::StringPrintf("UpdateManagedList:%d", type), 436 base::StringPrintf("%" PRIuS, entries.GetSize())); 437 // Create a map of existing entries. Assumes all entries in |managed_list| 438 // are unique. 439 std::map<std::string, ManagedState*> managed_map; 440 for (ManagedStateList::iterator iter = managed_list->begin(); 441 iter != managed_list->end(); ++iter) { 442 ManagedState* managed = *iter; 443 DCHECK(!ContainsKey(managed_map, managed->path())); 444 managed_map[managed->path()] = managed; 445 } 446 // Clear the list (pointers are temporarily owned by managed_map). 447 managed_list->clear(); 448 // Updates managed_list and request updates for new entries. 449 std::set<std::string> list_entries; 450 for (base::ListValue::const_iterator iter = entries.begin(); 451 iter != entries.end(); ++iter) { 452 std::string path; 453 (*iter)->GetAsString(&path); 454 if (path.empty() || path == shill::kFlimflamServicePath) { 455 NET_LOG_ERROR(base::StringPrintf("Bad path in list:%d", type), path); 456 continue; 457 } 458 std::map<std::string, ManagedState*>::iterator found = 459 managed_map.find(path); 460 ManagedState* managed; 461 if (found == managed_map.end()) { 462 if (list_entries.count(path) != 0) { 463 NET_LOG_ERROR("Duplicate entry in list", path); 464 continue; 465 } 466 managed = ManagedState::Create(type, path); 467 managed_list->push_back(managed); 468 } else { 469 managed = found->second; 470 managed_list->push_back(managed); 471 managed_map.erase(found); 472 } 473 list_entries.insert(path); 474 } 475 // Delete any remaining entries in managed_map. 476 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); 477} 478 479void NetworkStateHandler::ProfileListChanged() { 480 NET_LOG_EVENT("ProfileListChanged", "Re-Requesting Network Properties"); 481 for (ManagedStateList::iterator iter = network_list_.begin(); 482 iter != network_list_.end(); ++iter) { 483 shill_property_handler_->RequestProperties( 484 ManagedState::MANAGED_TYPE_NETWORK, (*iter)->path()); 485 } 486} 487 488void NetworkStateHandler::UpdateManagedStateProperties( 489 ManagedState::ManagedType type, 490 const std::string& path, 491 const base::DictionaryValue& properties) { 492 ManagedStateList* managed_list = GetManagedList(type); 493 ManagedState* managed = GetModifiableManagedState(managed_list, path); 494 if (!managed) { 495 if (type != ManagedState::MANAGED_TYPE_FAVORITE) { 496 // The network has been removed from the list of visible networks. 497 NET_LOG_DEBUG("UpdateManagedStateProperties: Not found", path); 498 return; 499 } 500 // A Favorite may not have been created yet if it was added later (e.g. 501 // through ConfigureService) since ServiceCompleteList updates are not 502 // emitted. Add and update the state here. 503 managed = new FavoriteState(path); 504 managed_list->push_back(managed); 505 } 506 managed->set_update_received(); 507 508 std::string desc = GetManagedStateLogType(managed) + " PropertiesReceived"; 509 NET_LOG_DEBUG(desc, GetManagedStateLogName(managed)); 510 511 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 512 UpdateNetworkStateProperties(managed->AsNetworkState(), properties); 513 } else { 514 // Device, Favorite 515 for (base::DictionaryValue::Iterator iter(properties); 516 !iter.IsAtEnd(); iter.Advance()) { 517 managed->PropertyChanged(iter.key(), iter.value()); 518 } 519 managed->InitialPropertiesReceived(properties); 520 } 521 managed->set_update_requested(false); 522} 523 524void NetworkStateHandler::UpdateNetworkStateProperties( 525 NetworkState* network, 526 const base::DictionaryValue& properties) { 527 DCHECK(network); 528 bool network_property_updated = false; 529 std::string prev_connection_state = network->connection_state(); 530 for (base::DictionaryValue::Iterator iter(properties); 531 !iter.IsAtEnd(); iter.Advance()) { 532 if (network->PropertyChanged(iter.key(), iter.value())) 533 network_property_updated = true; 534 } 535 network_property_updated |= network->InitialPropertiesReceived(properties); 536 // Notify observers of NetworkState changes. 537 if (network_property_updated || network->update_requested()) { 538 // Signal connection state changed after all properties have been updated. 539 if (ConnectionStateChanged(network, prev_connection_state)) 540 OnNetworkConnectionStateChanged(network); 541 NetworkPropertiesUpdated(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 // Trigger a default network update for interesting changes only. 584 if (network->path() == default_network_path_) 585 OnDefaultNetworkChanged(); 586 // Log interesting event. 587 std::string detail = network->name() + "." + key; 588 detail += " = " + network_event_log::ValueAsString(value); 589 network_event_log::LogLevel log_level; 590 if (key == shill::kErrorProperty || key == shill::kErrorDetailsProperty) { 591 log_level = network_event_log::LOG_LEVEL_ERROR; 592 } else { 593 log_level = network_event_log::LOG_LEVEL_EVENT; 594 } 595 NET_LOG_LEVEL(log_level, "NetworkPropertyUpdated", detail); 596 } 597 } 598 599 // All property updates signal 'NetworkPropertiesUpdated'. 600 NetworkPropertiesUpdated(network); 601 602 // If added to a Profile, request a full update so that a FavoriteState 603 // gets created. 604 if (prev_profile_path.empty() && !network->profile_path().empty()) 605 RequestUpdateForNetwork(service_path); 606} 607 608void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path, 609 const std::string& key, 610 const base::Value& value) { 611 DeviceState* device = GetModifiableDeviceState(device_path); 612 if (!device) 613 return; 614 if (!device->PropertyChanged(key, value)) 615 return; 616 617 std::string detail = device->name() + "." + key; 618 detail += " = " + network_event_log::ValueAsString(value); 619 NET_LOG_EVENT("DevicePropertyUpdated", detail); 620 621 NotifyDeviceListChanged(); 622 623 if (key == shill::kScanningProperty && device->scanning() == false) 624 ScanCompleted(device->type()); 625 if (key == shill::kEapAuthenticationCompletedProperty) { 626 // Notify a change for each Ethernet service using this device. 627 NetworkStateList ethernet_services; 628 GetNetworkListByType(NetworkTypePattern::Ethernet(), ðernet_services); 629 for (NetworkStateList::const_iterator it = ethernet_services.begin(); 630 it != ethernet_services.end(); ++it) { 631 const NetworkState* ethernet_service = *it; 632 if (ethernet_service->update_received() || 633 ethernet_service->device_path() != device->path()) { 634 continue; 635 } 636 RequestUpdateForNetwork(ethernet_service->path()); 637 } 638 } 639} 640 641void NetworkStateHandler::CheckPortalListChanged( 642 const std::string& check_portal_list) { 643 check_portal_list_ = check_portal_list; 644} 645 646void NetworkStateHandler::TechnologyListChanged() { 647 // Eventually we would like to replace Technology state with Device state. 648 // For now, treat technology state changes as device list changes. 649 NotifyDeviceListChanged(); 650} 651 652void NetworkStateHandler::ManagedStateListChanged( 653 ManagedState::ManagedType type) { 654 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 655 // Notify observers that the list of networks has changed. 656 NET_LOG_EVENT("NetworkListChanged", 657 base::StringPrintf("Size:%" PRIuS, network_list_.size())); 658 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 659 NetworkListChanged()); 660 // The list order may have changed, so check if the default network changed. 661 if (CheckDefaultNetworkChanged()) 662 OnDefaultNetworkChanged(); 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->is_favorite()) 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 692//------------------------------------------------------------------------------ 693// Private methods 694 695void NetworkStateHandler::NotifyDeviceListChanged() { 696 NET_LOG_DEBUG("NotifyDeviceListChanged", 697 base::StringPrintf("Size:%" PRIuS, device_list_.size())); 698 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 699 DeviceListChanged()); 700} 701 702DeviceState* NetworkStateHandler::GetModifiableDeviceState( 703 const std::string& device_path) const { 704 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 705 if (!managed) 706 return NULL; 707 return managed->AsDeviceState(); 708} 709 710NetworkState* NetworkStateHandler::GetModifiableNetworkState( 711 const std::string& service_path) const { 712 ManagedState* managed = 713 GetModifiableManagedState(&network_list_, service_path); 714 if (!managed) 715 return NULL; 716 return managed->AsNetworkState(); 717} 718 719ManagedState* NetworkStateHandler::GetModifiableManagedState( 720 const ManagedStateList* managed_list, 721 const std::string& path) const { 722 for (ManagedStateList::const_iterator iter = managed_list->begin(); 723 iter != managed_list->end(); ++iter) { 724 ManagedState* managed = *iter; 725 if (managed->path() == path) 726 return managed; 727 } 728 return NULL; 729} 730 731NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 732 ManagedState::ManagedType type) { 733 switch (type) { 734 case ManagedState::MANAGED_TYPE_NETWORK: 735 return &network_list_; 736 case ManagedState::MANAGED_TYPE_FAVORITE: 737 return &favorite_list_; 738 case ManagedState::MANAGED_TYPE_DEVICE: 739 return &device_list_; 740 } 741 NOTREACHED(); 742 return NULL; 743} 744 745void NetworkStateHandler::OnNetworkConnectionStateChanged( 746 NetworkState* network) { 747 DCHECK(network); 748 NET_LOG_EVENT("NetworkConnectionStateChanged", base::StringPrintf( 749 "%s:%s", GetManagedStateLogName(network).c_str(), 750 network->connection_state().c_str())); 751 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 752 NetworkConnectionStateChanged(network)); 753 if (CheckDefaultNetworkChanged() || network->path() == default_network_path_) 754 OnDefaultNetworkChanged(); 755} 756 757bool NetworkStateHandler::CheckDefaultNetworkChanged() { 758 std::string new_default_network_path; 759 const NetworkState* new_default_network = DefaultNetwork(); 760 if (new_default_network) 761 new_default_network_path = new_default_network->path(); 762 if (new_default_network_path == default_network_path_) 763 return false; 764 default_network_path_ = new_default_network_path; 765 return true; 766} 767 768void NetworkStateHandler::OnDefaultNetworkChanged() { 769 const NetworkState* default_network = DefaultNetwork(); 770 NET_LOG_EVENT("DefaultNetworkChanged", 771 GetManagedStateLogName(default_network)); 772 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 773 DefaultNetworkChanged(default_network)); 774} 775 776void NetworkStateHandler::NetworkPropertiesUpdated( 777 const NetworkState* network) { 778 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 779 NetworkPropertiesUpdated(network)); 780} 781 782void NetworkStateHandler::ScanCompleted(const std::string& type) { 783 size_t num_callbacks = scan_complete_callbacks_.count(type); 784 NET_LOG_EVENT("ScanCompleted", 785 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks)); 786 if (num_callbacks == 0) 787 return; 788 ScanCallbackList& callback_list = scan_complete_callbacks_[type]; 789 for (ScanCallbackList::iterator iter = callback_list.begin(); 790 iter != callback_list.end(); ++iter) { 791 (*iter).Run(); 792 } 793 scan_complete_callbacks_.erase(type); 794} 795 796std::string NetworkStateHandler::GetTechnologyForType( 797 const NetworkTypePattern& type) const { 798 if (type.MatchesType(shill::kTypeEthernet)) 799 return shill::kTypeEthernet; 800 801 if (type.MatchesType(shill::kTypeWifi)) 802 return shill::kTypeWifi; 803 804 if (type.Equals(NetworkTypePattern::Wimax())) 805 return shill::kTypeWimax; 806 807 // Prefer Wimax over Cellular only if it's available. 808 if (type.MatchesType(shill::kTypeWimax) && 809 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) { 810 return shill::kTypeWimax; 811 } 812 813 if (type.MatchesType(shill::kTypeCellular)) 814 return shill::kTypeCellular; 815 816 NOTREACHED(); 817 return std::string(); 818} 819 820} // namespace chromeos 821