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