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