network_change_notifier_chromeos.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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 <string> 6 7#include "base/basictypes.h" 8#include "base/bind.h" 9#include "base/string_util.h" 10#include "chromeos/dbus/dbus_thread_manager.h" 11#include "chromeos/network/network_change_notifier_chromeos.h" 12#include "chromeos/network/network_state.h" 13#include "chromeos/network/network_state_handler.h" 14#include "net/base/network_change_notifier.h" 15#include "net/dns/dns_config_service_posix.h" 16#include "third_party/cros_system_api/dbus/service_constants.h" 17 18namespace chromeos { 19 20// DNS config services on Chrome OS are signalled by the network state handler 21// rather than relying on watching files in /etc. 22class NetworkChangeNotifierChromeos::DnsConfigService 23 : public net::internal::DnsConfigServicePosix { 24 public: 25 DnsConfigService(); 26 virtual ~DnsConfigService(); 27 28 // net::internal::DnsConfigService() overrides. 29 virtual bool StartWatching() OVERRIDE; 30 31 virtual void OnNetworkChange(); 32}; 33 34NetworkChangeNotifierChromeos::DnsConfigService::DnsConfigService() { 35} 36 37NetworkChangeNotifierChromeos::DnsConfigService::~DnsConfigService() { 38} 39 40bool NetworkChangeNotifierChromeos::DnsConfigService::StartWatching() { 41 // DNS config changes are handled and notified by the network state handlers. 42 return true; 43} 44 45void NetworkChangeNotifierChromeos::DnsConfigService::OnNetworkChange() { 46 InvalidateConfig(); 47 InvalidateHosts(); 48 ReadNow(); 49} 50 51NetworkChangeNotifierChromeos::NetworkChangeNotifierChromeos() 52 : NetworkChangeNotifier(NetworkChangeCalculatorParamsChromeos()), 53 connection_type_(CONNECTION_NONE) { 54} 55 56NetworkChangeNotifierChromeos::~NetworkChangeNotifierChromeos() { 57} 58 59void NetworkChangeNotifierChromeos::Initialize() { 60 DBusThreadManager::Get()->GetPowerManagerClient()->AddObserver(this); 61 NetworkHandler::Get()->network_state_handler()->AddObserver(this); 62 63 dns_config_service_.reset(new DnsConfigService()); 64 dns_config_service_->WatchConfig( 65 base::Bind(net::NetworkChangeNotifier::SetDnsConfig)); 66 67 // Update initial connection state. 68 DefaultNetworkChanged( 69 NetworkHandler::Get()->network_state_handler()->DefaultNetwork()); 70} 71 72void NetworkChangeNotifierChromeos::Shutdown() { 73 dns_config_service_.reset(); 74 NetworkHandler::Get()->network_state_handler()->RemoveObserver(this); 75 DBusThreadManager::Get()->GetPowerManagerClient()->RemoveObserver(this); 76} 77 78net::NetworkChangeNotifier::ConnectionType 79NetworkChangeNotifierChromeos::GetCurrentConnectionType() const { 80 return connection_type_; 81} 82 83void NetworkChangeNotifierChromeos::SystemResumed( 84 const base::TimeDelta& sleep_duration) { 85 // Force invalidation of network resources on resume. 86 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); 87} 88 89 90void NetworkChangeNotifierChromeos::DefaultNetworkChanged( 91 const chromeos::NetworkState* default_network) { 92 bool connection_type_changed = false; 93 bool ip_address_changed = false; 94 bool dns_changed = false; 95 96 UpdateState(default_network, &connection_type_changed, 97 &ip_address_changed, &dns_changed); 98 99 if (connection_type_changed) 100 NetworkChangeNotifier::NotifyObserversOfConnectionTypeChange(); 101 if (ip_address_changed) 102 NetworkChangeNotifier::NotifyObserversOfIPAddressChange(); 103 if (dns_changed) 104 dns_config_service_->OnNetworkChange(); 105} 106 107void NetworkChangeNotifierChromeos::UpdateState( 108 const chromeos::NetworkState* default_network, 109 bool* connection_type_changed, 110 bool* ip_address_changed, 111 bool* dns_changed) { 112 *connection_type_changed = false; 113 *ip_address_changed = false; 114 *dns_changed = false; 115 if (!default_network || !default_network->IsConnectedState()) { 116 // If we lost a default network, we must update our state and notify 117 // observers, otherwise we have nothing to do. (Under normal circumstances, 118 // we should never get duplicate no default network notifications). 119 if (connection_type_ != CONNECTION_NONE) { 120 VLOG(1) << "Lost default network!"; 121 *ip_address_changed = true; 122 *dns_changed = true; 123 *connection_type_changed = true; 124 connection_type_ = CONNECTION_NONE; 125 service_path_.clear(); 126 ip_address_.clear(); 127 dns_servers_.clear(); 128 } 129 return; 130 } 131 132 // We do have a default network and it is connected. 133 net::NetworkChangeNotifier::ConnectionType new_connection_type = 134 ConnectionTypeFromShill(default_network->type(), 135 default_network->technology()); 136 if (new_connection_type != connection_type_) { 137 VLOG(1) << "Connection type changed from " << connection_type_ << " -> " 138 << new_connection_type; 139 *connection_type_changed = true; 140 } 141 if (default_network->path() != service_path_) { 142 VLOG(1) << "Service path changed from " << service_path_ << " -> " 143 << default_network->path(); 144 // If we had a default network service change, network resources 145 // must always be invalidated. 146 *ip_address_changed = true; 147 *dns_changed = true; 148 } 149 if (default_network->ip_address() != ip_address_) { 150 VLOG(1) << "IP Address changed from " << ip_address_ << " -> " 151 << default_network->ip_address(); 152 *ip_address_changed = true; 153 } 154 if (default_network->dns_servers() != dns_servers_) { 155 VLOG(1) << "DNS servers changed.\n" 156 << "Old DNS servers were: " 157 << JoinString(dns_servers_, ",") << "\n" 158 << "New DNS servers are: " 159 << JoinString(default_network->dns_servers(), ","); 160 *dns_changed = true; 161 } 162 163 connection_type_ = new_connection_type; 164 service_path_ = default_network->path(); 165 ip_address_ = default_network->ip_address(); 166 dns_servers_ = default_network->dns_servers(); 167} 168 169// static 170net::NetworkChangeNotifier::ConnectionType 171NetworkChangeNotifierChromeos::ConnectionTypeFromShill( 172 const std::string& type, const std::string& technology) { 173 if (type == flimflam::kTypeEthernet) 174 return CONNECTION_ETHERNET; 175 else if (type == flimflam::kTypeWifi) 176 return CONNECTION_WIFI; 177 else if (type == flimflam::kTypeWimax) 178 return CONNECTION_4G; 179 180 if (type != flimflam::kTypeCellular) 181 return CONNECTION_UNKNOWN; 182 183 // For cellular types, mapping depends on the technology. 184 if (technology == flimflam::kNetworkTechnologyEvdo || 185 technology == flimflam::kNetworkTechnologyGsm || 186 technology == flimflam::kNetworkTechnologyUmts || 187 technology == flimflam::kNetworkTechnologyHspa) { 188 return CONNECTION_3G; 189 } else if (technology == flimflam::kNetworkTechnologyHspaPlus || 190 technology == flimflam::kNetworkTechnologyLte || 191 technology == flimflam::kNetworkTechnologyLteAdvanced) { 192 return CONNECTION_4G; 193 } else { 194 return CONNECTION_2G; // Default cellular type is 2G. 195 } 196} 197 198// static 199net::NetworkChangeNotifier::NetworkChangeCalculatorParams 200NetworkChangeNotifierChromeos::NetworkChangeCalculatorParamsChromeos() { 201 NetworkChangeCalculatorParams params; 202 // Delay values arrived at by simple experimentation and adjusted so as to 203 // produce a single signal when switching between network connections. 204 params.ip_address_offline_delay_ = base::TimeDelta::FromMilliseconds(4000); 205 params.ip_address_online_delay_ = base::TimeDelta::FromMilliseconds(1000); 206 params.connection_type_offline_delay_ = 207 base::TimeDelta::FromMilliseconds(500); 208 params.connection_type_online_delay_ = base::TimeDelta::FromMilliseconds(500); 209 return params; 210} 211 212} // namespace chromeos 213