network_state_handler.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/format_macros.h" 8#include "base/stl_util.h" 9#include "base/string_util.h" 10#include "base/stringprintf.h" 11#include "base/values.h" 12#include "chromeos/network/device_state.h" 13#include "chromeos/network/managed_state.h" 14#include "chromeos/network/network_event_log.h" 15#include "chromeos/network/network_state.h" 16#include "chromeos/network/network_state_handler_observer.h" 17#include "chromeos/network/shill_property_handler.h" 18#include "third_party/cros_system_api/dbus/service_constants.h" 19 20namespace { 21 22const char kLogModule[] = "NetworkStateHandler"; 23 24// Returns true if |network->type()| == |match_type|, or it matches one of the 25// following special match types: 26// * kMatchTypeDefault matches any network (i.e. the first instance) 27// * kMatchTypeNonVirtual matches non virtual networks 28// * kMatchTypeWireless matches wireless networks 29// * kMatchTypeMobile matches cellular or wimax networks 30bool ManagedStateMatchesType(const chromeos::ManagedState* managed, 31 const std::string& match_type) { 32 const std::string& type = managed->type(); 33 if (match_type == chromeos::NetworkStateHandler::kMatchTypeDefault) 34 return true; 35 if (match_type == type) 36 return true; 37 if (match_type == chromeos::NetworkStateHandler::kMatchTypeNonVirtual && 38 type != flimflam::kTypeVPN) { 39 return true; 40 } 41 if (match_type == chromeos::NetworkStateHandler::kMatchTypeWireless && 42 type != flimflam::kTypeEthernet && type != flimflam::kTypeVPN) { 43 return true; 44 } 45 if (match_type == chromeos::NetworkStateHandler::kMatchTypeMobile && 46 (type == flimflam::kTypeCellular || type == flimflam::kTypeWimax)) { 47 return true; 48 } 49 return false; 50} 51 52std::string ValueAsString(const base::Value& value) { 53 if (value.GetType() == base::Value::TYPE_BOOLEAN) { 54 bool bval = false; 55 value.GetAsBoolean(&bval); 56 return bval ? "true" : "false"; 57 } else if (value.GetType() == base::Value::TYPE_INTEGER) { 58 int intval = 0; 59 value.GetAsInteger(&intval); 60 return base::StringPrintf("%d", intval); 61 } else if (value.GetType() == base::Value::TYPE_DOUBLE) { 62 double dval = 0; 63 value.GetAsDouble(&dval); 64 return base::StringPrintf("%g", dval); 65 } else if (value.GetType() == base::Value::TYPE_STRING) { 66 std::string vstr; 67 value.GetAsString(&vstr); 68 return vstr; 69 } 70 return ""; 71} 72 73} // namespace 74 75namespace chromeos { 76 77const char NetworkStateHandler::kMatchTypeDefault[] = "default"; 78const char NetworkStateHandler::kMatchTypeWireless[] = "wireless"; 79const char NetworkStateHandler::kMatchTypeMobile[] = "mobile"; 80const char NetworkStateHandler::kMatchTypeNonVirtual[] = "non-virtual"; 81 82static NetworkStateHandler* g_network_state_handler = NULL; 83 84NetworkStateHandler::NetworkStateHandler() { 85} 86 87NetworkStateHandler::~NetworkStateHandler() { 88 STLDeleteContainerPointers(network_list_.begin(), network_list_.end()); 89 STLDeleteContainerPointers(device_list_.begin(), device_list_.end()); 90} 91 92void NetworkStateHandler::InitShillPropertyHandler() { 93 shill_property_handler_.reset(new internal::ShillPropertyHandler(this)); 94 shill_property_handler_->Init(); 95} 96 97// static 98void NetworkStateHandler::Initialize() { 99 CHECK(!g_network_state_handler); 100 g_network_state_handler = new NetworkStateHandler(); 101 g_network_state_handler->InitShillPropertyHandler(); 102} 103 104// static 105bool NetworkStateHandler::IsInitialized() { 106 return g_network_state_handler != NULL; 107} 108 109// static 110void NetworkStateHandler::Shutdown() { 111 CHECK(g_network_state_handler); 112 delete g_network_state_handler; 113 g_network_state_handler = NULL; 114} 115 116// static 117NetworkStateHandler* NetworkStateHandler::Get() { 118 CHECK(g_network_state_handler) 119 << "NetworkStateHandler::Get() called before Initialize()"; 120 return g_network_state_handler; 121} 122 123void NetworkStateHandler::AddObserver(NetworkStateHandlerObserver* observer) { 124 observers_.AddObserver(observer); 125} 126 127void NetworkStateHandler::RemoveObserver( 128 NetworkStateHandlerObserver* observer) { 129 observers_.RemoveObserver(observer); 130} 131 132bool NetworkStateHandler::TechnologyAvailable(const std::string& type) const { 133 if (type == kMatchTypeMobile) { 134 return shill_property_handler_->TechnologyAvailable(flimflam::kTypeWimax) || 135 shill_property_handler_->TechnologyAvailable(flimflam::kTypeCellular); 136 } 137 return shill_property_handler_->TechnologyAvailable(type); 138} 139 140bool NetworkStateHandler::TechnologyEnabled(const std::string& type) const { 141 if (type == kMatchTypeMobile) { 142 return shill_property_handler_->TechnologyEnabled(flimflam::kTypeWimax) || 143 shill_property_handler_->TechnologyEnabled(flimflam::kTypeCellular); 144 } 145 return shill_property_handler_->TechnologyEnabled(type); 146} 147 148bool NetworkStateHandler::TechnologyUninitialized( 149 const std::string& type) const { 150 if (type == kMatchTypeMobile) { 151 return 152 shill_property_handler_->TechnologyUninitialized( 153 flimflam::kTypeWimax) || 154 shill_property_handler_->TechnologyUninitialized( 155 flimflam::kTypeCellular); 156 } 157 return shill_property_handler_->TechnologyUninitialized(type); 158} 159 160 161void NetworkStateHandler::SetTechnologyEnabled( 162 const std::string& type, 163 bool enabled, 164 const network_handler::ErrorCallback& error_callback) { 165 if (type == kMatchTypeMobile) { 166 shill_property_handler_->SetTechnologyEnabled( 167 flimflam::kTypeCellular, enabled, error_callback); 168 shill_property_handler_->SetTechnologyEnabled( 169 flimflam::kTypeWimax, enabled, error_callback); 170 } else { 171 shill_property_handler_->SetTechnologyEnabled( 172 type, enabled, error_callback); 173 } 174} 175 176const DeviceState* NetworkStateHandler::GetDeviceState( 177 const std::string& device_path) const { 178 return GetModifiableDeviceState(device_path); 179} 180 181const DeviceState* NetworkStateHandler::GetDeviceStateByType( 182 const std::string& type) const { 183 for (ManagedStateList::const_iterator iter = device_list_.begin(); 184 iter != device_list_.end(); ++iter) { 185 ManagedState* device = *iter; 186 if (ManagedStateMatchesType(device, type)) 187 return device->AsDeviceState(); 188 } 189 return NULL; 190} 191 192bool NetworkStateHandler::GetScanningByType(const std::string& type) const { 193 for (ManagedStateList::const_iterator iter = device_list_.begin(); 194 iter != device_list_.end(); ++iter) { 195 const DeviceState* device = (*iter)->AsDeviceState(); 196 DCHECK(device); 197 if (ManagedStateMatchesType(device, type) && device->scanning()) 198 return true; 199 } 200 return false; 201} 202 203const NetworkState* NetworkStateHandler::GetNetworkState( 204 const std::string& service_path) const { 205 return GetModifiableNetworkState(service_path); 206} 207 208const NetworkState* NetworkStateHandler::DefaultNetwork() const { 209 if (network_list_.empty()) 210 return NULL; 211 const NetworkState* network = network_list_.front()->AsNetworkState(); 212 DCHECK(network); 213 if (!network->IsConnectedState()) 214 return NULL; 215 return network; 216} 217 218const NetworkState* NetworkStateHandler::ConnectedNetworkByType( 219 const std::string& type) const { 220 for (ManagedStateList::const_iterator iter = network_list_.begin(); 221 iter != network_list_.end(); ++iter) { 222 const NetworkState* network = (*iter)->AsNetworkState(); 223 DCHECK(network); 224 if (!network->IsConnectedState()) 225 break; // Connected networks are listed first. 226 if (ManagedStateMatchesType(network, type)) 227 return network; 228 } 229 return NULL; 230} 231 232const NetworkState* NetworkStateHandler::ConnectingNetworkByType( 233 const std::string& type) const { 234 for (ManagedStateList::const_iterator iter = network_list_.begin(); 235 iter != network_list_.end(); ++iter) { 236 const NetworkState* network = (*iter)->AsNetworkState(); 237 DCHECK(network); 238 if (network->IsConnectedState()) 239 continue; 240 if (!network->IsConnectingState()) 241 break; // Connected and connecting networks are listed first. 242 if (ManagedStateMatchesType(network, type)) 243 return network; 244 } 245 return NULL; 246} 247 248const NetworkState* NetworkStateHandler::FirstNetworkByType( 249 const std::string& type) const { 250 for (ManagedStateList::const_iterator iter = network_list_.begin(); 251 iter != network_list_.end(); ++iter) { 252 const NetworkState* network = (*iter)->AsNetworkState(); 253 DCHECK(network); 254 if (ManagedStateMatchesType(network, type)) 255 return network; 256 } 257 return NULL; 258} 259 260std::string NetworkStateHandler::HardwareAddressForType( 261 const std::string& type) const { 262 std::string result; 263 const NetworkState* network = ConnectedNetworkByType(type); 264 if (network) { 265 const DeviceState* device = GetDeviceState(network->device_path()); 266 if (device) 267 result = device->mac_address(); 268 } 269 StringToUpperASCII(&result); 270 return result; 271} 272 273std::string NetworkStateHandler::FormattedHardwareAddressForType( 274 const std::string& type) const { 275 std::string address = HardwareAddressForType(type); 276 if (address.size() % 2 != 0) 277 return address; 278 std::string result; 279 for (size_t i = 0; i < address.size(); ++i) { 280 if ((i != 0) && (i % 2 == 0)) 281 result.push_back(':'); 282 result.push_back(address[i]); 283 } 284 return result; 285} 286 287void NetworkStateHandler::GetNetworkList(NetworkStateList* list) const { 288 DCHECK(list); 289 NetworkStateList result; 290 list->clear(); 291 for (ManagedStateList::const_iterator iter = network_list_.begin(); 292 iter != network_list_.end(); ++iter) { 293 const NetworkState* network = (*iter)->AsNetworkState(); 294 DCHECK(network); 295 list->push_back(network); 296 } 297} 298 299void NetworkStateHandler::RequestScan() const { 300 shill_property_handler_->RequestScan(); 301} 302 303//------------------------------------------------------------------------------ 304// ShillPropertyHandler::Delegate overrides 305 306void NetworkStateHandler::UpdateManagedList(ManagedState::ManagedType type, 307 const base::ListValue& entries) { 308 ManagedStateList* managed_list = GetManagedList(type); 309 VLOG(2) << "UpdateManagedList: " << type; 310 // Create a map of existing entries. 311 std::map<std::string, ManagedState*> managed_map; 312 for (ManagedStateList::iterator iter = managed_list->begin(); 313 iter != managed_list->end(); ++iter) { 314 ManagedState* managed = *iter; 315 managed_map[managed->path()] = managed; 316 } 317 // Clear the list (pointers are owned by managed_map). 318 managed_list->clear(); 319 // Updates managed_list and request updates for new entries. 320 for (base::ListValue::const_iterator iter = entries.begin(); 321 iter != entries.end(); ++iter) { 322 std::string path; 323 (*iter)->GetAsString(&path); 324 DCHECK(!path.empty()); 325 std::map<std::string, ManagedState*>::iterator found = 326 managed_map.find(path); 327 bool request_properties = false; 328 ManagedState* managed; 329 bool is_observing = shill_property_handler_->IsObservingNetwork(path); 330 if (found == managed_map.end()) { 331 request_properties = true; 332 managed = ManagedState::Create(type, path); 333 managed_list->push_back(managed); 334 } else { 335 managed = found->second; 336 managed_list->push_back(managed); 337 managed_map.erase(found); 338 if (!managed->is_observed() && is_observing) 339 request_properties = true; 340 } 341 if (is_observing) 342 managed->set_is_observed(true); 343 if (request_properties) 344 shill_property_handler_->RequestProperties(type, path); 345 } 346 // Delete any remaning entries in managed_map. 347 STLDeleteContainerPairSecondPointers(managed_map.begin(), managed_map.end()); 348} 349 350void NetworkStateHandler::UpdateManagedStateProperties( 351 ManagedState::ManagedType type, 352 const std::string& path, 353 const base::DictionaryValue& properties) { 354 ManagedState* managed = GetModifiableManagedState(GetManagedList(type), path); 355 if (!managed) { 356 LOG(ERROR) << "GetPropertiesCallback: " << path << " Not found!"; 357 return; 358 } 359 bool network_property_updated = false; 360 std::string prev_connection_state; 361 if (type == ManagedState::MANAGED_TYPE_NETWORK) 362 prev_connection_state = managed->AsNetworkState()->connection_state(); 363 for (base::DictionaryValue::Iterator iter(properties); 364 iter.HasNext(); iter.Advance()) { 365 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 366 if (managed->PropertyChanged(iter.key(), iter.value())) 367 network_property_updated = true; 368 } else { 369 managed->PropertyChanged(iter.key(), iter.value()); 370 } 371 } 372 // Notify observers. 373 if (network_property_updated) { 374 NetworkState* network = managed->AsNetworkState(); 375 DCHECK(network); 376 // Signal connection state changed after all properties have been updated. 377 if (network->connection_state() != prev_connection_state) 378 OnNetworkConnectionStateChanged(network); 379 NetworkPropertiesUpdated(network); 380 } 381 network_event_log::AddEntry( 382 kLogModule, "PropertiesReceived", 383 base::StringPrintf("%s (%s)", path.c_str(), managed->name().c_str())); 384} 385 386void NetworkStateHandler::UpdateNetworkServiceProperty( 387 const std::string& service_path, 388 const std::string& key, 389 const base::Value& value) { 390 NetworkState* network = GetModifiableNetworkState(service_path); 391 if (!network) 392 return; 393 std::string prev_connection_state = network->connection_state(); 394 if (!network->PropertyChanged(key, value)) 395 return; 396 if (network->connection_state() != prev_connection_state) 397 OnNetworkConnectionStateChanged(network); 398 399 NetworkPropertiesUpdated(network); 400 401 std::string detail = network->name() + "." + key; 402 std::string vstr = ValueAsString(value); 403 if (!vstr.empty()) 404 detail += " = " + vstr; 405 network_event_log::AddEntry(kLogModule, "NetworkPropertyUpdated", detail); 406} 407 408void NetworkStateHandler::UpdateNetworkServiceIPAddress( 409 const std::string& service_path, 410 const std::string& ip_address) { 411 NetworkState* network = GetModifiableNetworkState(service_path); 412 if (!network) 413 return; 414 std::string detail = network->name() + ".IPAddress = " + ip_address; 415 network_event_log::AddEntry(kLogModule, "NetworkIPChanged", detail); 416 network->set_ip_address(ip_address); 417 NetworkPropertiesUpdated(network); 418} 419 420void NetworkStateHandler::UpdateDeviceProperty(const std::string& device_path, 421 const std::string& key, 422 const base::Value& value) { 423 DeviceState* device = GetModifiableDeviceState(device_path); 424 if (!device) 425 return; 426 if (!device->PropertyChanged(key, value)) 427 return; 428 429 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 430 DeviceListChanged()); 431 432 std::string detail = device->name() + "." + key; 433 std::string vstr = ValueAsString(value); 434 if (!vstr.empty()) 435 detail += " = " + vstr; 436 network_event_log::AddEntry(kLogModule, "DevicePropertyUpdated", detail); 437} 438 439void NetworkStateHandler::ManagerPropertyChanged() { 440 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 441 NetworkManagerChanged()); 442} 443 444void NetworkStateHandler::ManagedStateListChanged( 445 ManagedState::ManagedType type) { 446 if (type == ManagedState::MANAGED_TYPE_NETWORK) { 447 // Notify observers that the list of networks has changed. 448 network_event_log::AddEntry( 449 kLogModule, "NetworkListChanged", 450 base::StringPrintf("Size: %"PRIuS, network_list_.size())); 451 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 452 NetworkListChanged()); 453 // The list order may have changed, so check if the default network changed. 454 if (CheckDefaultNetworkChanged()) 455 OnDefaultNetworkChanged(); 456 } else if (type == ManagedState::MANAGED_TYPE_DEVICE) { 457 network_event_log::AddEntry( 458 kLogModule, "DeviceListChanged", 459 base::StringPrintf("Size: %"PRIuS, device_list_.size())); 460 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 461 DeviceListChanged()); 462 } else { 463 NOTREACHED(); 464 } 465} 466 467//------------------------------------------------------------------------------ 468// Private methods 469 470DeviceState* NetworkStateHandler::GetModifiableDeviceState( 471 const std::string& device_path) const { 472 ManagedState* managed = GetModifiableManagedState(&device_list_, device_path); 473 if (!managed) 474 return NULL; 475 return managed->AsDeviceState(); 476} 477 478NetworkState* NetworkStateHandler::GetModifiableNetworkState( 479 const std::string& service_path) const { 480 ManagedState* managed = 481 GetModifiableManagedState(&network_list_, service_path); 482 if (!managed) 483 return NULL; 484 return managed->AsNetworkState(); 485} 486 487ManagedState* NetworkStateHandler::GetModifiableManagedState( 488 const ManagedStateList* managed_list, 489 const std::string& path) const { 490 for (ManagedStateList::const_iterator iter = managed_list->begin(); 491 iter != managed_list->end(); ++iter) { 492 ManagedState* managed = *iter; 493 if (managed->path() == path) 494 return managed; 495 } 496 return NULL; 497} 498 499NetworkStateHandler::ManagedStateList* NetworkStateHandler::GetManagedList( 500 ManagedState::ManagedType type) { 501 switch (type) { 502 case ManagedState::MANAGED_TYPE_NETWORK: 503 return &network_list_; 504 case ManagedState::MANAGED_TYPE_DEVICE: 505 return &device_list_; 506 } 507 NOTREACHED(); 508 return NULL; 509} 510 511void NetworkStateHandler::OnNetworkConnectionStateChanged( 512 NetworkState* network) { 513 DCHECK(network); 514 std::string desc = base::StringPrintf( 515 "%s: %s", network->path().c_str(), network->connection_state().c_str()); 516 network_event_log::AddEntry( 517 kLogModule, "NetworkConnectionStateChanged", desc); 518 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 519 NetworkConnectionStateChanged(network)); 520 if (CheckDefaultNetworkChanged() || network->path() == default_network_path_) 521 OnDefaultNetworkChanged(); 522} 523 524bool NetworkStateHandler::CheckDefaultNetworkChanged() { 525 std::string new_default_network_path; 526 const NetworkState* new_default_network = DefaultNetwork(); 527 if (new_default_network) 528 new_default_network_path = new_default_network->path(); 529 if (new_default_network_path == default_network_path_) 530 return false; 531 default_network_path_ = new_default_network_path; 532 return true; 533} 534 535void NetworkStateHandler::OnDefaultNetworkChanged() { 536 const NetworkState* default_network = DefaultNetwork(); 537 network_event_log::AddEntry( 538 kLogModule, "DefaultNetworkChanged", 539 default_network ? default_network->path() : "None"); 540 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 541 DefaultNetworkChanged(default_network)); 542} 543 544void NetworkStateHandler::NetworkPropertiesUpdated( 545 const NetworkState* network) { 546 if (network->path() == connecting_network_ && !network->IsConnectingState()) 547 connecting_network_.clear(); 548 FOR_EACH_OBSERVER(NetworkStateHandlerObserver, observers_, 549 NetworkPropertiesUpdated(network)); 550} 551 552} // namespace chromeos 553