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 NotifyDevicePropertiesUpdated(device); 615 616 if (key == shill::kScanningProperty && device->scanning() == false) 617 ScanCompleted(device->type()); 618 if (key == shill::kEapAuthenticationCompletedProperty) { 619 // Notify a change for each Ethernet service using this device. 620 NetworkStateList ethernet_services; 621 GetNetworkListByType(NetworkTypePattern::Ethernet(), 622 false /* configured_only */, 623 false /* visible_only */, 624 0 /* no limit */, 625 ðernet_services); 626 for (NetworkStateList::const_iterator it = ethernet_services.begin(); 627 it != ethernet_services.end(); ++it) { 628 const NetworkState* ethernet_service = *it; 629 if (ethernet_service->update_received() || 630 ethernet_service->device_path() != device->path()) { 631 continue; 632 } 633 RequestUpdateForNetwork(ethernet_service->path()); 634 } 635 } 636 } 637 638 void NetworkStateHandler::UpdateIPConfigProperties( 639 ManagedState::ManagedType type, 640 const std::string& path, 641 const std::string& ip_config_path, 642 const base::DictionaryValue& properties) { 643 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 644 NetworkState* network = GetModifiableNetworkState(path); 645 if (!network) 646 return; 647 network->IPConfigPropertiesChanged(properties); 648 NotifyNetworkPropertiesUpdated(network); 649 if (network->path() == default_network_path_) 650 NotifyDefaultNetworkChanged(network); 651 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 652 DeviceState* device = GetModifiableDeviceState(path); 653 if (!device) 654 return; 655 device->IPConfigPropertiesChanged(ip_config_path, properties); 656 NotifyDevicePropertiesUpdated(device); 657 if (!default_network_path_.empty()) { 658 const NetworkState* default_network = 659 GetNetworkState(default_network_path_); 660 if (default_network && default_network->device_path() == path) 661 NotifyDefaultNetworkChanged(default_network); 662 } 663 } 664 } 665 666 void NetworkStateHandler::CheckPortalListChanged( 667 const std::string& check_portal_list) { 668 check_portal_list_ = check_portal_list; 669 } 670 671 void NetworkStateHandler::TechnologyListChanged() { 672 // Eventually we would like to replace Technology state with Device state. 673 // For now, treat technology state changes as device list changes. 674 NotifyDeviceListChanged(); 675 } 676 677 void NetworkStateHandler::ManagedStateListChanged( 678 ManagedState::ManagedType type) { 679 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 680 SortNetworkList(); 681 UpdateNetworkStats(); 682 // Notify observers that the list of networks has changed. 683 NET_LOG_EVENT("NOTIFY:NetworkListChanged", 684 base::StringPrintf("Size:%" PRIuS, network_list_.size())); 685 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 686 NetworkListChanged()); 687 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 688 std::string devices; 689 for (ManagedStateList::const_iterator iter = device_list_.begin(); 690 iter != device_list_.end(); ++iter) { 691 if (iter != device_list_.begin()) 692 devices += ", "; 693 devices += (*iter)->name(); 694 } 695 NET_LOG_EVENT("DeviceList", devices); 696 NotifyDeviceListChanged(); 697 } else { 698 NOTREACHED(); 699 } 700 } 701 702 void NetworkStateHandler::SortNetworkList() { 703 // Note: usually active networks will precede inactive networks, however 704 // this may briefly be untrue during state transitions (e.g. a network may 705 // transition to idle before the list is updated). 706 ManagedStateList active, non_wifi_visible, wifi_visible, hidden, new_networks; 707 for (ManagedStateList::iterator iter = network_list_.begin(); 708 iter != network_list_.end(); ++iter) { 709 NetworkState* network = (*iter)->AsNetworkState(); 710 if (!network->update_received()) { 711 new_networks.push_back(network); 712 continue; 713 } 714 if (network->IsConnectedState() || network->IsConnectingState()) { 715 active.push_back(network); 716 continue; 717 } 718 if (network->visible()) { 719 if (NetworkTypePattern::WiFi().MatchesType(network->type())) 720 wifi_visible.push_back(network); 721 else 722 non_wifi_visible.push_back(network); 723 } else { 724 hidden.push_back(network); 725 } 726 } 727 network_list_.clear(); 728 network_list_.insert(network_list_.end(), active.begin(), active.end()); 729 network_list_.insert( 730 network_list_.end(), non_wifi_visible.begin(), non_wifi_visible.end()); 731 network_list_.insert( 732 network_list_.end(), wifi_visible.begin(), wifi_visible.end()); 733 network_list_.insert(network_list_.end(), hidden.begin(), hidden.end()); 734 network_list_.insert( 735 network_list_.end(), new_networks.begin(), new_networks.end()); 736 network_list_sorted_ = true; 737 } 738 739 void NetworkStateHandler::UpdateNetworkStats() { 740 size_t shared = 0, unshared = 0, visible = 0; 741 for (ManagedStateList::iterator iter = network_list_.begin(); 742 iter != network_list_.end(); ++iter) { 743 NetworkState* network = (*iter)->AsNetworkState(); 744 if (network->visible()) 745 ++visible; 746 if (network->IsInProfile()) { 747 if (network->IsPrivate()) 748 ++unshared; 749 else 750 ++shared; 751 } 752 } 753 UMA_HISTOGRAM_COUNTS_100("Networks.Visible", visible); 754 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedShared", shared); 755 UMA_HISTOGRAM_COUNTS_100("Networks.RememberedUnshared", unshared); 756 } 757 758 void NetworkStateHandler::DefaultNetworkServiceChanged( 759 const std::string& service_path) { 760 // Shill uses '/' for empty service path values; check explicitly for that. 761 const char* kEmptyServicePath = "/"; 762 std::string new_service_path = 763 (service_path != kEmptyServicePath) ? service_path : ""; 764 if (new_service_path == default_network_path_) 765 return; 766 767 default_network_path_ = service_path; 768 NET_LOG_EVENT("DefaultNetworkServiceChanged:", default_network_path_); 769 const NetworkState* network = NULL; 770 if (!default_network_path_.empty()) { 771 network = GetNetworkState(default_network_path_); 772 if (!network) { 773 // If NetworkState is not available yet, do not notify observers here, 774 // they will be notified when the state is received. 775 NET_LOG_DEBUG("Default NetworkState not available", 776 default_network_path_); 777 return; 778 } 779 } 780 if (network && !network->IsConnectedState()) { 781 NET_LOG_ERROR( 782 "DefaultNetwork is not connected: " + network->connection_state(), 783 network->path()); 784 } 785 NotifyDefaultNetworkChanged(network); 786 } 787 788 //------------------------------------------------------------------------------ 789 // Private methods 790 791 void NetworkStateHandler::UpdateGuid(NetworkState* network) { 792 std::string specifier = network->GetSpecifier(); 793 DCHECK(!specifier.empty()); 794 if (!network->guid().empty()) { 795 // If the network is saved in a profile, remove the entry from the map. 796 // Otherwise ensure that the entry matches the specified GUID. (e.g. in 797 // case a visible network with a specified guid gets configured with a 798 // new guid). 799 if (network->IsInProfile()) 800 specifier_guid_map_.erase(specifier); 801 else 802 specifier_guid_map_[specifier] = network->guid(); 803 return; 804 } 805 // Ensure that the NetworkState has a valid GUID. 806 std::string guid; 807 SpecifierGuidMap::iterator iter = specifier_guid_map_.find(specifier); 808 if (iter != specifier_guid_map_.end()) { 809 guid = iter->second; 810 } else { 811 guid = base::GenerateGUID(); 812 specifier_guid_map_[specifier] = guid; 813 } 814 network->SetGuid(guid); 815 } 816 817 void NetworkStateHandler::NotifyDeviceListChanged() { 818 NET_LOG_DEBUG("NOTIFY:DeviceListChanged", 819 base::StringPrintf("Size:%" PRIuS, device_list_.size())); 820 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 821 DeviceListChanged()); 822 } 823 824 DeviceState* NetworkStateHandler::GetModifiableDeviceState( 825 const std::string& device_path) const { 826 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 827 if (!managed) 828 return NULL; 829 return managed->AsDeviceState(); 830 } 831 832 NetworkState* NetworkStateHandler::GetModifiableNetworkState( 833 const std::string& service_path) const { 834 ManagedState* managed = 835 GetModifiableManagedState(&network_list_, service_path); 836 if (!managed) 837 return NULL; 838 return managed->AsNetworkState(); 839 } 840 841 ManagedState* NetworkStateHandler::GetModifiableManagedState( 842 const ManagedStateList* managed_list, 843 const std::string& path) const { 844 for (ManagedStateList::const_iterator iter = managed_list->begin(); 845 iter != managed_list->end(); ++iter) { 846 ManagedState* managed = *iter; 847 if (managed->path() == path) 848 return managed; 849 } 850 return NULL; 851 } 852 853 NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 854 ManagedState::ManagedType type) { 855 switch (type) { 856 case ManagedState::MANAGED_TYPE_NETWORK: 857 return &network_list_; 858 case ManagedState::MANAGED_TYPE_DEVICE: 859 return &device_list_; 860 } 861 NOTREACHED(); 862 return NULL; 863 } 864 865 void NetworkStateHandler::OnNetworkConnectionStateChanged( 866 NetworkState* network) { 867 DCHECK(network); 868 std::string event = "NetworkConnectionStateChanged"; 869 if (network->path() == default_network_path_) { 870 event = "Default" + event; 871 if (!network->IsConnectedState()) { 872 NET_LOG_EVENT( 873 "DefaultNetwork is not connected: " + network->connection_state(), 874 network->path()); 875 default_network_path_.clear(); 876 SortNetworkList(); 877 NotifyDefaultNetworkChanged(NULL); 878 } 879 } 880 NET_LOG_EVENT("NOTIFY:" + event + ": " + network->connection_state(), 881 GetLogName(network)); 882 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 883 NetworkConnectionStateChanged(network)); 884 if (network->path() == default_network_path_) 885 NotifyDefaultNetworkChanged(network); 886 } 887 888 void NetworkStateHandler::NotifyDefaultNetworkChanged( 889 const NetworkState* default_network) { 890 NET_LOG_EVENT("NOTIFY:DefaultNetworkChanged", GetLogName(default_network)); 891 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 892 DefaultNetworkChanged(default_network)); 893 } 894 895 void NetworkStateHandler::NotifyNetworkPropertiesUpdated( 896 const NetworkState* network) { 897 NET_LOG_DEBUG("NOTIFY:NetworkPropertiesUpdated", GetLogName(network)); 898 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 899 NetworkPropertiesUpdated(network)); 900 } 901 902 void NetworkStateHandler::NotifyDevicePropertiesUpdated( 903 const DeviceState* device) { 904 NET_LOG_DEBUG("NOTIFY:DevicePropertiesUpdated", GetLogName(device)); 905 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 906 DevicePropertiesUpdated(device)); 907 } 908 909 void NetworkStateHandler::ScanCompleted(const std::string& type) { 910 size_t num_callbacks = scan_complete_callbacks_.count(type); 911 NET_LOG_EVENT("ScanCompleted", 912 base::StringPrintf("%s:%" PRIuS, type.c_str(), num_callbacks)); 913 if (num_callbacks == 0) 914 return; 915 ScanCallbackList& callback_list = scan_complete_callbacks_[type]; 916 for (ScanCallbackList::iterator iter = callback_list.begin(); 917 iter != callback_list.end(); ++iter) { 918 (*iter).Run(); 919 } 920 scan_complete_callbacks_.erase(type); 921 } 922 923 std::string NetworkStateHandler::GetTechnologyForType( 924 const NetworkTypePattern& type) const { 925 if (type.MatchesType(shill::kTypeEthernet)) 926 return shill::kTypeEthernet; 927 928 if (type.MatchesType(shill::kTypeWifi)) 929 return shill::kTypeWifi; 930 931 if (type.Equals(NetworkTypePattern::Wimax())) 932 return shill::kTypeWimax; 933 934 // Prefer Wimax over Cellular only if it's available. 935 if (type.MatchesType(shill::kTypeWimax) && 936 shill_property_handler_->IsTechnologyAvailable(shill::kTypeWimax)) { 937 return shill::kTypeWimax; 938 } 939 940 if (type.MatchesType(shill::kTypeCellular)) 941 return shill::kTypeCellular; 942 943 NOTREACHED(); 944 return std::string(); 945 } 946 947 ScopedVector<std::string> NetworkStateHandler::GetTechnologiesForType( 948 const NetworkTypePattern& type) const { 949 ScopedVector<std::string> technologies; 950 if (type.MatchesType(shill::kTypeEthernet)) 951 technologies.push_back(new std::string(shill::kTypeEthernet)); 952 if (type.MatchesType(shill::kTypeWifi)) 953 technologies.push_back(new std::string(shill::kTypeWifi)); 954 if (type.MatchesType(shill::kTypeWimax)) 955 technologies.push_back(new std::string(shill::kTypeWimax)); 956 if (type.MatchesType(shill::kTypeCellular)) 957 technologies.push_back(new std::string(shill::kTypeCellular)); 958 if (type.MatchesType(shill::kTypeBluetooth)) 959 technologies.push_back(new std::string(shill::kTypeBluetooth)); 960 if (type.MatchesType(shill::kTypeVPN)) 961 technologies.push_back(new std::string(shill::kTypeVPN)); 962 963 CHECK_GT(technologies.size(), 0ul); 964 return technologies.Pass(); 965 } 966 967 } // namespace chromeos 968