| OLD | NEW |
| (Empty) |
| 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 "chrome/browser/chromeos/cros/network_library_impl_cros.h" | |
| 6 | |
| 7 #include "base/bind.h" | |
| 8 #include "base/command_line.h" | |
| 9 #include "base/json/json_writer.h" // for debug output only. | |
| 10 #include "base/metrics/histogram.h" | |
| 11 #include "base/stl_util.h" | |
| 12 #include "base/values.h" | |
| 13 #include "chrome/browser/chromeos/cros/native_network_constants.h" | |
| 14 #include "chrome/browser/chromeos/cros/native_network_parser.h" | |
| 15 #include "chrome/browser/chromeos/settings/cros_settings.h" | |
| 16 #include "chrome/common/chrome_switches.h" | |
| 17 #include "chromeos/network/cros_network_functions.h" | |
| 18 #include "chromeos/network/network_state_handler.h" | |
| 19 #include "chromeos/network/network_util.h" | |
| 20 #include "content/public/browser/browser_thread.h" | |
| 21 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 22 | |
| 23 using content::BrowserThread; | |
| 24 | |
| 25 namespace chromeos { | |
| 26 | |
| 27 // Structure used to pass IP parameter info to a DoSetIPParameters callback, | |
| 28 // since Bind only takes up to six parameters. | |
| 29 struct NetworkLibraryImplCros::IPParameterInfo { | |
| 30 std::string address; | |
| 31 std::string netmask; | |
| 32 std::string gateway; | |
| 33 std::string name_servers; | |
| 34 int dhcp_usage_mask; | |
| 35 }; | |
| 36 | |
| 37 //////////////////////////////////////////////////////////////////////////// | |
| 38 | |
| 39 NetworkLibraryImplCros::NetworkLibraryImplCros() | |
| 40 : NetworkLibraryImplBase(), | |
| 41 weak_ptr_factory_(this) { | |
| 42 } | |
| 43 | |
| 44 NetworkLibraryImplCros::~NetworkLibraryImplCros() { | |
| 45 STLDeleteValues(&monitored_networks_); | |
| 46 STLDeleteValues(&monitored_devices_); | |
| 47 } | |
| 48 | |
| 49 void NetworkLibraryImplCros::Init() { | |
| 50 // First, get the currently available networks. This data is cached | |
| 51 // on the connman side, so the call should be quick. | |
| 52 VLOG(1) << "Requesting initial network manager info from libcros."; | |
| 53 CrosRequestNetworkManagerProperties( | |
| 54 base::Bind(&NetworkLibraryImplCros::NetworkManagerUpdate, | |
| 55 weak_ptr_factory_.GetWeakPtr())); | |
| 56 network_manager_watcher_.reset(CrosMonitorNetworkManagerProperties( | |
| 57 base::Bind(&NetworkLibraryImplCros::NetworkManagerStatusChangedHandler, | |
| 58 weak_ptr_factory_.GetWeakPtr()))); | |
| 59 // Always have at least one device obsever so that device updates are | |
| 60 // always received. | |
| 61 network_device_observer_.reset(new NetworkLibraryDeviceObserver()); | |
| 62 } | |
| 63 | |
| 64 bool NetworkLibraryImplCros::IsCros() const { | |
| 65 return true; | |
| 66 } | |
| 67 | |
| 68 ////////////////////////////////////////////////////////////////////////////// | |
| 69 // NetworkLibraryImplBase implementation. | |
| 70 | |
| 71 void NetworkLibraryImplCros::MonitorNetworkStart( | |
| 72 const std::string& service_path) { | |
| 73 if (monitored_networks_.find(service_path) == monitored_networks_.end()) { | |
| 74 CrosNetworkWatcher* watcher = CrosMonitorNetworkServiceProperties( | |
| 75 base::Bind(&NetworkLibraryImplCros::UpdateNetworkStatus, | |
| 76 weak_ptr_factory_.GetWeakPtr()), | |
| 77 service_path); | |
| 78 monitored_networks_[service_path] = watcher; | |
| 79 } | |
| 80 } | |
| 81 | |
| 82 void NetworkLibraryImplCros::MonitorNetworkStop( | |
| 83 const std::string& service_path) { | |
| 84 NetworkWatcherMap::iterator iter = monitored_networks_.find(service_path); | |
| 85 if (iter != monitored_networks_.end()) { | |
| 86 delete iter->second; | |
| 87 monitored_networks_.erase(iter); | |
| 88 } | |
| 89 } | |
| 90 | |
| 91 void NetworkLibraryImplCros::MonitorNetworkDeviceStart( | |
| 92 const std::string& device_path) { | |
| 93 if (monitored_devices_.find(device_path) == monitored_devices_.end()) { | |
| 94 CrosNetworkWatcher* watcher = CrosMonitorNetworkDeviceProperties( | |
| 95 base::Bind(&NetworkLibraryImplCros::UpdateNetworkDeviceStatus, | |
| 96 weak_ptr_factory_.GetWeakPtr()), | |
| 97 device_path); | |
| 98 monitored_devices_[device_path] = watcher; | |
| 99 } | |
| 100 } | |
| 101 | |
| 102 void NetworkLibraryImplCros::MonitorNetworkDeviceStop( | |
| 103 const std::string& device_path) { | |
| 104 NetworkWatcherMap::iterator iter = monitored_devices_.find(device_path); | |
| 105 if (iter != monitored_devices_.end()) { | |
| 106 delete iter->second; | |
| 107 monitored_devices_.erase(iter); | |
| 108 } | |
| 109 } | |
| 110 | |
| 111 void NetworkLibraryImplCros::UpdateNetworkStatus( | |
| 112 const std::string& path, const std::string& key, const Value& value) { | |
| 113 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 114 Network* network = FindNetworkByPath(path); | |
| 115 if (network) { | |
| 116 VLOG(2) << "UpdateNetworkStatus: " << network->name() << "." << key; | |
| 117 bool prev_connected = network->connected(); | |
| 118 if (!network->UpdateStatus(key, value, NULL)) { | |
| 119 LOG(WARNING) << "UpdateNetworkStatus: Error updating: " | |
| 120 << path << "." << key; | |
| 121 } | |
| 122 if (key == flimflam::kProfileProperty) | |
| 123 SetProfileTypeFromPath(network); | |
| 124 // If we just connected, this may have been added to remembered list. | |
| 125 if (!prev_connected && network->connected()) | |
| 126 RequestRememberedNetworksUpdate(); | |
| 127 NotifyNetworkChanged(network); | |
| 128 // Anything observing the manager needs to know about any service change. | |
| 129 NotifyNetworkManagerChanged(false); // Not forced. | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 void NetworkLibraryImplCros::UpdateNetworkDeviceStatus( | |
| 134 const std::string& path, const std::string& key, const Value& value) { | |
| 135 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 136 NetworkDevice* device = FindNetworkDeviceByPath(path); | |
| 137 if (device) { | |
| 138 VLOG(2) << "UpdateNetworkDeviceStatus: " << device->name() << "." << key; | |
| 139 PropertyIndex index = PROPERTY_INDEX_UNKNOWN; | |
| 140 if (device->UpdateStatus(key, value, &index)) { | |
| 141 if (device->type() == TYPE_CELLULAR) { | |
| 142 if (!UpdateCellularDeviceStatus(device, index)) | |
| 143 return; // Update aborted, skip notify. | |
| 144 } | |
| 145 } else { | |
| 146 VLOG(1) << "UpdateNetworkDeviceStatus: Failed to update: " | |
| 147 << path << "." << key; | |
| 148 } | |
| 149 if (device->type() == TYPE_WIFI && device->scanning() != wifi_scanning_) { | |
| 150 wifi_scanning_ = device->scanning(); | |
| 151 NotifyNetworkManagerChanged(false); // Not forced. | |
| 152 } | |
| 153 // Notify only observers on device property change. | |
| 154 NotifyNetworkDeviceChanged(device, index); | |
| 155 // If a device's power state changes, new properties may become defined. | |
| 156 if (index == PROPERTY_INDEX_POWERED) { | |
| 157 CrosRequestNetworkDeviceProperties( | |
| 158 path, | |
| 159 base::Bind(&NetworkLibraryImplCros::NetworkDeviceUpdate, | |
| 160 weak_ptr_factory_.GetWeakPtr())); | |
| 161 } | |
| 162 } | |
| 163 } | |
| 164 | |
| 165 bool NetworkLibraryImplCros::UpdateCellularDeviceStatus(NetworkDevice* device, | |
| 166 PropertyIndex index) { | |
| 167 if (index == PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING) { | |
| 168 if (IsCellularAlwaysInRoaming()) { | |
| 169 if (!device->data_roaming_allowed()) | |
| 170 SetCellularDataRoamingAllowed(true); | |
| 171 } else { | |
| 172 bool settings_value; | |
| 173 if ((CrosSettings::Get()->GetBoolean( | |
| 174 kSignedDataRoamingEnabled, &settings_value)) && | |
| 175 (device->data_roaming_allowed() != settings_value)) { | |
| 176 // Switch back to signed settings value. | |
| 177 SetCellularDataRoamingAllowed(settings_value); | |
| 178 return false; | |
| 179 } | |
| 180 } | |
| 181 } else if (index == PROPERTY_INDEX_SIM_LOCK) { | |
| 182 // We only ever request a sim unlock when we wish to enable the device. | |
| 183 if (!device->is_sim_locked() && !cellular_enabled()) | |
| 184 EnableCellularNetworkDevice(true); | |
| 185 } | |
| 186 return true; | |
| 187 } | |
| 188 | |
| 189 ///////////////////////////////////////////////////////////////////////////// | |
| 190 // NetworkLibraryImplBase connect implementation. | |
| 191 | |
| 192 void NetworkLibraryImplCros::CallConfigureService(const std::string& identifier, | |
| 193 const DictionaryValue* info) { | |
| 194 CrosConfigureService(*info); | |
| 195 } | |
| 196 | |
| 197 void NetworkLibraryImplCros::NetworkConnectCallback( | |
| 198 const std::string& service_path, | |
| 199 NetworkMethodErrorType error, | |
| 200 const std::string& error_message) { | |
| 201 NetworkConnectStatus status; | |
| 202 if (error == NETWORK_METHOD_ERROR_NONE) { | |
| 203 status = CONNECT_SUCCESS; | |
| 204 } else { | |
| 205 LOG(WARNING) << "Error from ServiceConnect callback for: " | |
| 206 << service_path | |
| 207 << " Error: " << error << " Message: " << error_message; | |
| 208 if (error_message == flimflam::kErrorPassphraseRequiredMsg) { | |
| 209 status = CONNECT_BAD_PASSPHRASE; | |
| 210 } else { | |
| 211 status = CONNECT_FAILED; | |
| 212 } | |
| 213 } | |
| 214 Network* network = FindNetworkByPath(service_path); | |
| 215 if (!network) { | |
| 216 LOG(ERROR) << "No network for path: " << service_path; | |
| 217 return; | |
| 218 } | |
| 219 NetworkConnectCompleted(network, status); | |
| 220 } | |
| 221 | |
| 222 void NetworkLibraryImplCros::CallConnectToNetwork(Network* network) { | |
| 223 DCHECK(network); | |
| 224 CrosRequestNetworkServiceConnect( | |
| 225 network->service_path(), | |
| 226 base::Bind(&NetworkLibraryImplCros::NetworkConnectCallback, | |
| 227 weak_ptr_factory_.GetWeakPtr())); | |
| 228 } | |
| 229 | |
| 230 void NetworkLibraryImplCros::WifiServiceUpdateAndConnect( | |
| 231 const std::string& service_path, | |
| 232 const base::DictionaryValue* properties) { | |
| 233 if (properties) { | |
| 234 Network* network = ParseNetwork(service_path, *properties); | |
| 235 CHECK_EQ(network->type(), TYPE_WIFI); | |
| 236 ConnectToWifiNetworkUsingConnectData(static_cast<WifiNetwork*>(network)); | |
| 237 } | |
| 238 } | |
| 239 | |
| 240 void NetworkLibraryImplCros::CallRequestWifiNetworkAndConnect( | |
| 241 const std::string& ssid, ConnectionSecurity security) { | |
| 242 // Asynchronously request service properties and call | |
| 243 // WifiServiceUpdateAndConnect. | |
| 244 CrosRequestHiddenWifiNetworkProperties( | |
| 245 ssid, | |
| 246 SecurityToString(security), | |
| 247 base::Bind(&NetworkLibraryImplCros::WifiServiceUpdateAndConnect, | |
| 248 weak_ptr_factory_.GetWeakPtr())); | |
| 249 } | |
| 250 | |
| 251 void NetworkLibraryImplCros::VPNServiceUpdateAndConnect( | |
| 252 const std::string& service_path, | |
| 253 const base::DictionaryValue* properties) { | |
| 254 if (properties) { | |
| 255 VLOG(1) << "Connecting to new VPN Service: " << service_path; | |
| 256 Network* network = ParseNetwork(service_path, *properties); | |
| 257 CHECK_EQ(network->type(), TYPE_VPN); | |
| 258 ConnectToVirtualNetworkUsingConnectData( | |
| 259 static_cast<VirtualNetwork*>(network)); | |
| 260 } else { | |
| 261 LOG(WARNING) << "Unable to create VPN Service: " << service_path; | |
| 262 } | |
| 263 } | |
| 264 | |
| 265 void NetworkLibraryImplCros::CallRequestVirtualNetworkAndConnect( | |
| 266 const std::string& service_name, | |
| 267 const std::string& server_hostname, | |
| 268 ProviderType provider_type) { | |
| 269 CrosRequestVirtualNetworkProperties( | |
| 270 service_name, | |
| 271 server_hostname, | |
| 272 ProviderTypeToString(provider_type), | |
| 273 base::Bind(&NetworkLibraryImplCros::VPNServiceUpdateAndConnect, | |
| 274 weak_ptr_factory_.GetWeakPtr())); | |
| 275 } | |
| 276 | |
| 277 void NetworkLibraryImplCros::CallDeleteRememberedNetwork( | |
| 278 const std::string& profile_path, | |
| 279 const std::string& service_path) { | |
| 280 CrosDeleteServiceFromProfile(profile_path, service_path); | |
| 281 } | |
| 282 | |
| 283 ////////////////////////////////////////////////////////////////////////////// | |
| 284 // NetworkLibrary implementation. | |
| 285 | |
| 286 void NetworkLibraryImplCros::ChangePin(const std::string& old_pin, | |
| 287 const std::string& new_pin) { | |
| 288 const NetworkDevice* cellular = FindCellularDevice(); | |
| 289 if (!cellular) { | |
| 290 NOTREACHED() << "Calling ChangePin method w/o cellular device."; | |
| 291 return; | |
| 292 } | |
| 293 sim_operation_ = SIM_OPERATION_CHANGE_PIN; | |
| 294 CrosRequestChangePin( | |
| 295 cellular->device_path(), old_pin, new_pin, | |
| 296 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
| 297 weak_ptr_factory_.GetWeakPtr())); | |
| 298 } | |
| 299 | |
| 300 void NetworkLibraryImplCros::ChangeRequirePin(bool require_pin, | |
| 301 const std::string& pin) { | |
| 302 VLOG(1) << "ChangeRequirePin require_pin: " << require_pin | |
| 303 << " pin: " << pin; | |
| 304 const NetworkDevice* cellular = FindCellularDevice(); | |
| 305 if (!cellular) { | |
| 306 NOTREACHED() << "Calling ChangeRequirePin method w/o cellular device."; | |
| 307 return; | |
| 308 } | |
| 309 sim_operation_ = SIM_OPERATION_CHANGE_REQUIRE_PIN; | |
| 310 CrosRequestRequirePin( | |
| 311 cellular->device_path(), pin, require_pin, | |
| 312 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
| 313 weak_ptr_factory_.GetWeakPtr())); | |
| 314 } | |
| 315 | |
| 316 void NetworkLibraryImplCros::EnterPin(const std::string& pin) { | |
| 317 const NetworkDevice* cellular = FindCellularDevice(); | |
| 318 if (!cellular) { | |
| 319 NOTREACHED() << "Calling EnterPin method w/o cellular device."; | |
| 320 return; | |
| 321 } | |
| 322 sim_operation_ = SIM_OPERATION_ENTER_PIN; | |
| 323 CrosRequestEnterPin(cellular->device_path(), pin, | |
| 324 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
| 325 weak_ptr_factory_.GetWeakPtr())); | |
| 326 } | |
| 327 | |
| 328 void NetworkLibraryImplCros::UnblockPin(const std::string& puk, | |
| 329 const std::string& new_pin) { | |
| 330 const NetworkDevice* cellular = FindCellularDevice(); | |
| 331 if (!cellular) { | |
| 332 NOTREACHED() << "Calling UnblockPin method w/o cellular device."; | |
| 333 return; | |
| 334 } | |
| 335 sim_operation_ = SIM_OPERATION_UNBLOCK_PIN; | |
| 336 CrosRequestUnblockPin( | |
| 337 cellular->device_path(), puk, new_pin, | |
| 338 base::Bind(&NetworkLibraryImplCros::PinOperationCallback, | |
| 339 weak_ptr_factory_.GetWeakPtr())); | |
| 340 } | |
| 341 | |
| 342 void NetworkLibraryImplCros::PinOperationCallback( | |
| 343 const std::string& path, | |
| 344 NetworkMethodErrorType error, | |
| 345 const std::string& error_message) { | |
| 346 PinOperationError pin_error; | |
| 347 VLOG(1) << "PinOperationCallback, error: " << error | |
| 348 << " error_msg: " << error_message; | |
| 349 if (error == chromeos::NETWORK_METHOD_ERROR_NONE) { | |
| 350 pin_error = PIN_ERROR_NONE; | |
| 351 VLOG(1) << "Pin operation completed successfuly"; | |
| 352 } else { | |
| 353 if (error_message == flimflam::kErrorIncorrectPinMsg || | |
| 354 error_message == flimflam::kErrorPinRequiredMsg) { | |
| 355 pin_error = PIN_ERROR_INCORRECT_CODE; | |
| 356 } else if (error_message == flimflam::kErrorPinBlockedMsg) { | |
| 357 pin_error = PIN_ERROR_BLOCKED; | |
| 358 } else { | |
| 359 pin_error = PIN_ERROR_UNKNOWN; | |
| 360 NOTREACHED() << "Unknown PIN error: " << error_message; | |
| 361 } | |
| 362 } | |
| 363 NotifyPinOperationCompleted(pin_error); | |
| 364 } | |
| 365 | |
| 366 void NetworkLibraryImplCros::RequestCellularScan() { | |
| 367 const NetworkDevice* cellular = FindCellularDevice(); | |
| 368 if (!cellular) { | |
| 369 NOTREACHED() << "Calling RequestCellularScan method w/o cellular device."; | |
| 370 return; | |
| 371 } | |
| 372 CrosProposeScan(cellular->device_path()); | |
| 373 } | |
| 374 | |
| 375 void NetworkLibraryImplCros::RequestCellularRegister( | |
| 376 const std::string& network_id) { | |
| 377 const NetworkDevice* cellular = FindCellularDevice(); | |
| 378 if (!cellular) { | |
| 379 NOTREACHED() << "Calling CellularRegister method w/o cellular device."; | |
| 380 return; | |
| 381 } | |
| 382 CrosRequestCellularRegister( | |
| 383 cellular->device_path(), network_id, | |
| 384 base::Bind(&NetworkLibraryImplCros::CellularRegisterCallback, | |
| 385 weak_ptr_factory_.GetWeakPtr())); | |
| 386 } | |
| 387 | |
| 388 void NetworkLibraryImplCros::CellularRegisterCallback( | |
| 389 const std::string& path, | |
| 390 NetworkMethodErrorType error, | |
| 391 const std::string& error_message) { | |
| 392 // TODO(dpolukhin): Notify observers about network registration status | |
| 393 // but not UI doesn't assume such notification so just ignore result. | |
| 394 } | |
| 395 | |
| 396 void NetworkLibraryImplCros::SetCellularDataRoamingAllowed(bool new_value) { | |
| 397 const NetworkDevice* cellular = FindCellularDevice(); | |
| 398 if (!cellular) { | |
| 399 NOTREACHED() << "Calling SetCellularDataRoamingAllowed method " | |
| 400 "w/o cellular device."; | |
| 401 return; | |
| 402 } | |
| 403 base::FundamentalValue value(new_value); | |
| 404 CrosSetNetworkDeviceProperty(cellular->device_path(), | |
| 405 flimflam::kCellularAllowRoamingProperty, | |
| 406 value); | |
| 407 } | |
| 408 | |
| 409 void NetworkLibraryImplCros::SetCarrier( | |
| 410 const std::string& carrier, | |
| 411 const NetworkOperationCallback& completed) { | |
| 412 const NetworkDevice* cellular = FindCellularDevice(); | |
| 413 if (!cellular) { | |
| 414 NOTREACHED() << "Calling SetCarrier method w/o cellular device."; | |
| 415 return; | |
| 416 } | |
| 417 CrosSetCarrier(cellular->device_path(), carrier, completed); | |
| 418 } | |
| 419 | |
| 420 bool NetworkLibraryImplCros::IsCellularAlwaysInRoaming() { | |
| 421 const NetworkDevice* cellular = FindCellularDevice(); | |
| 422 if (!cellular) { | |
| 423 NOTREACHED() << "Calling IsCellularAlwaysInRoaming method " | |
| 424 "w/o cellular device."; | |
| 425 return false; | |
| 426 } | |
| 427 return cellular->provider_requires_roaming(); | |
| 428 } | |
| 429 | |
| 430 void NetworkLibraryImplCros::RequestNetworkScan() { | |
| 431 if (wifi_enabled()) | |
| 432 CrosRequestNetworkScan(flimflam::kTypeWifi); | |
| 433 | |
| 434 if (wimax_enabled()) | |
| 435 CrosRequestNetworkScan(flimflam::kTypeWimax); | |
| 436 | |
| 437 // Make sure all Manager info is up to date. This will also update | |
| 438 // remembered networks and visible services. | |
| 439 CrosRequestNetworkManagerProperties( | |
| 440 base::Bind(&NetworkLibraryImplCros::NetworkManagerUpdate, | |
| 441 weak_ptr_factory_.GetWeakPtr())); | |
| 442 } | |
| 443 | |
| 444 void NetworkLibraryImplCros::RefreshIPConfig(Network* network) { | |
| 445 DCHECK(network); | |
| 446 CrosRequestNetworkDeviceProperties( | |
| 447 network->device_path(), | |
| 448 base::Bind(&NetworkLibraryImplCros::RefreshIPConfigCallback, | |
| 449 weak_ptr_factory_.GetWeakPtr())); | |
| 450 } | |
| 451 | |
| 452 void NetworkLibraryImplCros::RefreshIPConfigCallback( | |
| 453 const std::string& device_path, | |
| 454 const base::DictionaryValue* properties) { | |
| 455 const ListValue* ips = NULL; | |
| 456 if (!properties->GetListWithoutPathExpansion( | |
| 457 flimflam::kIPConfigsProperty, &ips)) | |
| 458 return; | |
| 459 | |
| 460 for (size_t i = 0; i < ips->GetSize(); i++) { | |
| 461 std::string ipconfig_path; | |
| 462 if (!ips->GetString(i, &ipconfig_path)) | |
| 463 continue; | |
| 464 CrosRequestIPConfigRefresh(ipconfig_path); | |
| 465 } | |
| 466 } | |
| 467 | |
| 468 void NetworkLibraryImplCros::DisconnectFromNetwork(const Network* network) { | |
| 469 DCHECK(network); | |
| 470 // Asynchronous disconnect request. Network state will be updated through | |
| 471 // the network manager once disconnect completes. | |
| 472 CrosRequestNetworkServiceDisconnect(network->service_path()); | |
| 473 } | |
| 474 | |
| 475 void NetworkLibraryImplCros::CallEnableNetworkDeviceType( | |
| 476 ConnectionType device, bool enable) { | |
| 477 busy_devices_ |= 1 << device; | |
| 478 CrosRequestNetworkDeviceEnable(ConnectionTypeToString(device), enable); | |
| 479 if (device == TYPE_WIFI && enable) | |
| 480 RequestNetworkScan(); | |
| 481 } | |
| 482 | |
| 483 void NetworkLibraryImplCros::CallRemoveNetwork(const Network* network) { | |
| 484 const std::string& service_path = network->service_path(); | |
| 485 if (network->connected()) | |
| 486 CrosRequestNetworkServiceDisconnect(service_path); | |
| 487 CrosRequestRemoveNetworkService(service_path); | |
| 488 } | |
| 489 | |
| 490 void NetworkLibraryImplCros::GetIPConfigsCallback( | |
| 491 const NetworkGetIPConfigsCallback& callback, | |
| 492 HardwareAddressFormat format, | |
| 493 const NetworkIPConfigVector& ipconfig_vector, | |
| 494 const std::string& hardware_address) { | |
| 495 std::string hardware_address_tmp = hardware_address; | |
| 496 for (size_t i = 0; i < hardware_address_tmp.size(); ++i) | |
| 497 hardware_address_tmp[i] = toupper(hardware_address_tmp[i]); | |
| 498 if (format == FORMAT_COLON_SEPARATED_HEX) { | |
| 499 if (hardware_address_tmp.size() % 2 == 0) { | |
| 500 std::string output; | |
| 501 for (size_t i = 0; i < hardware_address_tmp.size(); ++i) { | |
| 502 if ((i != 0) && (i % 2 == 0)) | |
| 503 output.push_back(':'); | |
| 504 output.push_back(hardware_address_tmp[i]); | |
| 505 } | |
| 506 hardware_address_tmp.swap(output); | |
| 507 } | |
| 508 } else { | |
| 509 DCHECK_EQ(format, FORMAT_RAW_HEX); | |
| 510 } | |
| 511 callback.Run(ipconfig_vector, hardware_address_tmp); | |
| 512 } | |
| 513 | |
| 514 void NetworkLibraryImplCros::GetIPConfigs( | |
| 515 const std::string& device_path, | |
| 516 HardwareAddressFormat format, | |
| 517 const NetworkGetIPConfigsCallback& callback) { | |
| 518 CrosListIPConfigs(device_path, | |
| 519 base::Bind(&NetworkLibraryImplCros::GetIPConfigsCallback, | |
| 520 weak_ptr_factory_.GetWeakPtr(), | |
| 521 callback, | |
| 522 format)); | |
| 523 } | |
| 524 | |
| 525 void NetworkLibraryImplCros::SetIPParameters(const std::string& service_path, | |
| 526 const std::string& address, | |
| 527 const std::string& netmask, | |
| 528 const std::string& gateway, | |
| 529 const std::string& name_servers, | |
| 530 int dhcp_usage_mask) { | |
| 531 if (service_path.empty()) | |
| 532 return; | |
| 533 | |
| 534 VLOG(1) << "Setting IP parameters: " | |
| 535 << "address: " << address | |
| 536 << (dhcp_usage_mask & USE_DHCP_ADDRESS ? | |
| 537 " (ignored)" : " (in use)") | |
| 538 << "netmask: " << netmask | |
| 539 << (dhcp_usage_mask & USE_DHCP_NETMASK ? | |
| 540 " (ignored)" : " (in use)") | |
| 541 << "gateway: " << gateway | |
| 542 << (dhcp_usage_mask & USE_DHCP_GATEWAY ? | |
| 543 " (ignored)" : " (in use)") | |
| 544 << "name_servers: " << name_servers | |
| 545 << (dhcp_usage_mask & USE_DHCP_NAME_SERVERS ? | |
| 546 " (ignored)" : " (in use)"); | |
| 547 | |
| 548 // Have to pass these in a structure, since Bind only takes up to six | |
| 549 // parameters. | |
| 550 IPParameterInfo info; | |
| 551 info.address = address; | |
| 552 info.netmask = netmask; | |
| 553 info.gateway = gateway; | |
| 554 info.name_servers = name_servers; | |
| 555 info.dhcp_usage_mask = dhcp_usage_mask; | |
| 556 chromeos::NetworkPropertiesCallback callback = | |
| 557 base::Bind(&NetworkLibraryImplCros::SetIPParametersCallback, | |
| 558 weak_ptr_factory_.GetWeakPtr(), info); | |
| 559 | |
| 560 CrosRequestNetworkServiceProperties(service_path, callback); | |
| 561 } | |
| 562 | |
| 563 void NetworkLibraryImplCros::RequestNetworkServiceProperties( | |
| 564 const std::string& service_path, | |
| 565 const NetworkServicePropertiesCallback& callback) { | |
| 566 chromeos::CrosRequestNetworkServiceProperties(service_path, callback); | |
| 567 } | |
| 568 | |
| 569 ///////////////////////////////////////////////////////////////////////////// | |
| 570 // Network Manager functions. | |
| 571 | |
| 572 void NetworkLibraryImplCros::NetworkManagerStatusChangedHandler( | |
| 573 const std::string& path, | |
| 574 const std::string& key, | |
| 575 const Value& value) { | |
| 576 if (!NetworkManagerStatusChanged(key, &value)) { | |
| 577 LOG(ERROR) << "Invalid key-value pair, key: " << key << " type: " | |
| 578 << value.GetType(); | |
| 579 } | |
| 580 } | |
| 581 | |
| 582 // This processes all Manager update messages. | |
| 583 bool NetworkLibraryImplCros::NetworkManagerStatusChanged( | |
| 584 const std::string& key, const Value* value) { | |
| 585 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 586 base::TimeTicks start = base::TimeTicks::Now(); | |
| 587 VLOG(1) << "NetworkManagerStatusChanged: KEY=" << key; | |
| 588 int index = NativeNetworkParser::property_mapper()->Get(key); | |
| 589 switch (index) { | |
| 590 case PROPERTY_INDEX_STATE: | |
| 591 // Currently we ignore the network manager state. | |
| 592 break; | |
| 593 case PROPERTY_INDEX_AVAILABLE_TECHNOLOGIES: { | |
| 594 const ListValue* vlist = NULL; | |
| 595 if (!value->GetAsList(&vlist)) | |
| 596 return false; | |
| 597 UpdateAvailableTechnologies(vlist); | |
| 598 break; | |
| 599 } | |
| 600 case PROPERTY_INDEX_UNINITIALIZED_TECHNOLOGIES: { | |
| 601 const ListValue* vlist = NULL; | |
| 602 if (!value->GetAsList(&vlist)) | |
| 603 return false; | |
| 604 UpdateTechnologies(vlist, &uninitialized_devices_); | |
| 605 break; | |
| 606 } | |
| 607 case PROPERTY_INDEX_ENABLED_TECHNOLOGIES: { | |
| 608 const ListValue* vlist = NULL; | |
| 609 if (!value->GetAsList(&vlist)) | |
| 610 return false; | |
| 611 UpdateEnabledTechnologies(vlist); | |
| 612 break; | |
| 613 } | |
| 614 case PROPERTY_INDEX_DEFAULT_TECHNOLOGY: | |
| 615 // Currently we ignore DefaultTechnology. | |
| 616 break; | |
| 617 case PROPERTY_INDEX_ACTIVE_PROFILE: { | |
| 618 std::string prev = active_profile_path_; | |
| 619 DCHECK_EQ(value->GetType(), Value::TYPE_STRING); | |
| 620 value->GetAsString(&active_profile_path_); | |
| 621 VLOG(1) << "Active Profile: " << active_profile_path_; | |
| 622 if (active_profile_path_ != prev && | |
| 623 active_profile_path_ != kSharedProfilePath) | |
| 624 SwitchToPreferredNetwork(); | |
| 625 break; | |
| 626 } | |
| 627 case PROPERTY_INDEX_PROFILES: { | |
| 628 const ListValue* vlist = NULL; | |
| 629 if (!value->GetAsList(&vlist)) | |
| 630 return false; | |
| 631 UpdateRememberedNetworks(vlist); | |
| 632 break; | |
| 633 } | |
| 634 case PROPERTY_INDEX_SERVICES: { | |
| 635 const ListValue* vlist = NULL; | |
| 636 if (!value->GetAsList(&vlist)) | |
| 637 return false; | |
| 638 UpdateNetworkServiceList(vlist); | |
| 639 break; | |
| 640 } | |
| 641 case PROPERTY_INDEX_SERVICE_WATCH_LIST: { | |
| 642 const ListValue* vlist = NULL; | |
| 643 if (!value->GetAsList(&vlist)) | |
| 644 return false; | |
| 645 UpdateWatchedNetworkServiceList(vlist); | |
| 646 break; | |
| 647 } | |
| 648 case PROPERTY_INDEX_DEVICE: | |
| 649 case PROPERTY_INDEX_DEVICES: { | |
| 650 const ListValue* vlist = NULL; | |
| 651 if (!value->GetAsList(&vlist)) | |
| 652 return false; | |
| 653 UpdateNetworkDeviceList(vlist); | |
| 654 break; | |
| 655 } | |
| 656 case PROPERTY_INDEX_CHECK_PORTAL_LIST: { | |
| 657 DCHECK_EQ(value->GetType(), Value::TYPE_STRING); | |
| 658 value->GetAsString(&check_portal_list_); | |
| 659 break; | |
| 660 } | |
| 661 case PROPERTY_INDEX_PORTAL_URL: | |
| 662 case PROPERTY_INDEX_ARP_GATEWAY: | |
| 663 // Currently we ignore PortalURL and ArpGateway. | |
| 664 break; | |
| 665 default: | |
| 666 VLOG(2) << "Manager: Unhandled key: " << key; | |
| 667 break; | |
| 668 } | |
| 669 base::TimeDelta delta = base::TimeTicks::Now() - start; | |
| 670 VLOG(2) << "NetworkManagerStatusChanged: time: " | |
| 671 << delta.InMilliseconds() << " ms."; | |
| 672 HISTOGRAM_TIMES("CROS_NETWORK_UPDATE", delta); | |
| 673 return true; | |
| 674 } | |
| 675 | |
| 676 void NetworkLibraryImplCros::NetworkManagerUpdate( | |
| 677 const std::string& manager_path, | |
| 678 const base::DictionaryValue* properties) { | |
| 679 if (!properties) { | |
| 680 LOG(ERROR) << "Error retrieving manager properties: " << manager_path; | |
| 681 return; | |
| 682 } | |
| 683 VLOG(1) << "Received NetworkManagerUpdate."; | |
| 684 | |
| 685 for (DictionaryValue::Iterator iter(*properties); !iter.IsAtEnd(); | |
| 686 iter.Advance()) { | |
| 687 if (!NetworkManagerStatusChanged(iter.key(), &iter.value())) { | |
| 688 LOG(ERROR) << "Invalid key-value pair, key: " << iter.key() << " type: " | |
| 689 << iter.value().GetType(); | |
| 690 } | |
| 691 } | |
| 692 // If there is no Profiles entry, request remembered networks here. | |
| 693 if (!properties->HasKey(flimflam::kProfilesProperty)) | |
| 694 RequestRememberedNetworksUpdate(); | |
| 695 } | |
| 696 | |
| 697 //////////////////////////////////////////////////////////////////////////// | |
| 698 | |
| 699 void NetworkLibraryImplCros::UpdateTechnologies( | |
| 700 const ListValue* technologies, int* bitfieldp) { | |
| 701 DCHECK(bitfieldp); | |
| 702 if (!technologies) | |
| 703 return; | |
| 704 int bitfield = 0; | |
| 705 for (ListValue::const_iterator iter = technologies->begin(); | |
| 706 iter != technologies->end(); ++iter) { | |
| 707 std::string technology; | |
| 708 (*iter)->GetAsString(&technology); | |
| 709 if (!technology.empty()) { | |
| 710 ConnectionType type = | |
| 711 NativeNetworkParser::ParseConnectionType(technology); | |
| 712 bitfield |= 1 << type; | |
| 713 } | |
| 714 } | |
| 715 *bitfieldp = bitfield; | |
| 716 NotifyNetworkManagerChanged(false); // Not forced. | |
| 717 } | |
| 718 | |
| 719 void NetworkLibraryImplCros::UpdateAvailableTechnologies( | |
| 720 const ListValue* technologies) { | |
| 721 UpdateTechnologies(technologies, &available_devices_); | |
| 722 } | |
| 723 | |
| 724 void NetworkLibraryImplCros::UpdateEnabledTechnologies( | |
| 725 const ListValue* technologies) { | |
| 726 int old_enabled_devices = enabled_devices_; | |
| 727 UpdateTechnologies(technologies, &enabled_devices_); | |
| 728 busy_devices_ &= ~(old_enabled_devices ^ enabled_devices_); | |
| 729 if (!ethernet_enabled()) | |
| 730 ethernet_ = NULL; | |
| 731 if (!wifi_enabled()) { | |
| 732 active_wifi_ = NULL; | |
| 733 wifi_networks_.clear(); | |
| 734 } | |
| 735 if (!cellular_enabled()) { | |
| 736 active_cellular_ = NULL; | |
| 737 cellular_networks_.clear(); | |
| 738 } | |
| 739 } | |
| 740 | |
| 741 //////////////////////////////////////////////////////////////////////////// | |
| 742 | |
| 743 // Update all network lists, and request associated service updates. | |
| 744 void NetworkLibraryImplCros::UpdateNetworkServiceList( | |
| 745 const ListValue* services) { | |
| 746 // Copy the list of existing networks to "old" and clear the map and lists. | |
| 747 NetworkMap old_network_map = network_map_; | |
| 748 ClearNetworks(); | |
| 749 // Clear the list of update requests. | |
| 750 int network_priority_order = 0; | |
| 751 network_update_requests_.clear(); | |
| 752 // |services| represents a complete list of visible networks. | |
| 753 for (ListValue::const_iterator iter = services->begin(); | |
| 754 iter != services->end(); ++iter) { | |
| 755 std::string service_path; | |
| 756 (*iter)->GetAsString(&service_path); | |
| 757 if (!service_path.empty()) { | |
| 758 // If we find the network in "old", add it immediately to the map | |
| 759 // and lists. Otherwise it will get added when NetworkServiceUpdate | |
| 760 // calls ParseNetwork. | |
| 761 NetworkMap::iterator found = old_network_map.find(service_path); | |
| 762 if (found != old_network_map.end()) { | |
| 763 AddNetwork(found->second); | |
| 764 old_network_map.erase(found); | |
| 765 } | |
| 766 // Always request network updates. | |
| 767 // TODO(stevenjb): Investigate why we are missing updates then | |
| 768 // rely on watched network updates and only request updates here for | |
| 769 // new networks. | |
| 770 // Use update_request map to store network priority. | |
| 771 network_update_requests_[service_path] = network_priority_order++; | |
| 772 VLOG(2) << "UpdateNetworkServiceList, Service: " << service_path; | |
| 773 CrosRequestNetworkServiceProperties( | |
| 774 service_path, | |
| 775 base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, | |
| 776 weak_ptr_factory_.GetWeakPtr())); | |
| 777 } | |
| 778 } | |
| 779 | |
| 780 // Iterate through list of remaining networks that are no longer in the | |
| 781 // list and delete them or update their status and re-add them to the list. | |
| 782 for (NetworkMap::iterator iter = old_network_map.begin(); | |
| 783 iter != old_network_map.end(); ++iter) { | |
| 784 Network* network = iter->second; | |
| 785 VLOG(2) << "Delete Network: " << network->name() | |
| 786 << " State = " << network->GetStateString() | |
| 787 << " connecting = " << network->connecting() | |
| 788 << " connection_started = " << network->connection_started(); | |
| 789 WifiNetwork* wifi = NULL; | |
| 790 if (network->type() == TYPE_WIFI) | |
| 791 wifi = static_cast<WifiNetwork*>(network); | |
| 792 if (network->failed() && network->notify_failure()) { | |
| 793 // We have not notified observers of a connection failure yet. | |
| 794 AddNetwork(network); | |
| 795 } else if (network->connecting() && network->connection_started() && | |
| 796 !(wifi && wifi->hidden_ssid())) { | |
| 797 // Network was in connecting state; set state to failed, but not if it | |
| 798 // had a hidden SSID (since that won't appear in the scanning list). | |
| 799 VLOG(2) << "Removed network was connecting: " << network->name(); | |
| 800 network->SetState(STATE_FAILURE); | |
| 801 AddNetwork(network); | |
| 802 } else { | |
| 803 VLOG(2) << "Deleting removed network: " << network->name() | |
| 804 << " State = " << network->GetStateString(); | |
| 805 DeleteNetwork(network); | |
| 806 } | |
| 807 } | |
| 808 // If the last network has disappeared, nothing else will | |
| 809 // have notified observers, so do it now. | |
| 810 if (services->empty()) | |
| 811 NotifyNetworkManagerChanged(true); // Forced update | |
| 812 } | |
| 813 | |
| 814 // Request updates for watched networks. Does not affect network lists. | |
| 815 // Existing networks will be updated. There should not be any new networks | |
| 816 // in this list, but if there are they will be added appropriately. | |
| 817 void NetworkLibraryImplCros::UpdateWatchedNetworkServiceList( | |
| 818 const ListValue* services) { | |
| 819 for (ListValue::const_iterator iter = services->begin(); | |
| 820 iter != services->end(); ++iter) { | |
| 821 std::string service_path; | |
| 822 (*iter)->GetAsString(&service_path); | |
| 823 if (!service_path.empty()) { | |
| 824 VLOG(1) << "Watched Service: " << service_path; | |
| 825 CrosRequestNetworkServiceProperties( | |
| 826 service_path, | |
| 827 base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, | |
| 828 weak_ptr_factory_.GetWeakPtr())); | |
| 829 } | |
| 830 } | |
| 831 } | |
| 832 | |
| 833 void NetworkLibraryImplCros::NetworkServiceUpdate( | |
| 834 const std::string& service_path, | |
| 835 const base::DictionaryValue* properties) { | |
| 836 if (!properties) | |
| 837 return; // Network no longer in visible list, ignore. | |
| 838 VLOG(2) << "NetworkServiceUpdate: " << service_path; | |
| 839 ParseNetwork(service_path, *properties); | |
| 840 } | |
| 841 | |
| 842 // Called from NetworkServiceUpdate and WifiServiceUpdateAndConnect. | |
| 843 Network* NetworkLibraryImplCros::ParseNetwork( | |
| 844 const std::string& service_path, const DictionaryValue& info) { | |
| 845 Network* network = FindNetworkByPath(service_path); | |
| 846 if (!network) { | |
| 847 NativeNetworkParser parser; | |
| 848 network = parser.CreateNetworkFromInfo(service_path, info); | |
| 849 AddNetwork(network); | |
| 850 } else { | |
| 851 // Erase entry from network_unique_id_map_ in case unique id changes. | |
| 852 if (!network->unique_id().empty()) | |
| 853 network_unique_id_map_.erase(network->unique_id()); | |
| 854 if (network->network_parser()) { | |
| 855 ConnectionState old_state = network->state(); | |
| 856 network->network_parser()->UpdateNetworkFromInfo(info, network); | |
| 857 if (old_state != network->state()) { | |
| 858 VLOG(1) << "ParseNetwork: " << network->name() | |
| 859 << " State: " << old_state << " -> " << network->state(); | |
| 860 } | |
| 861 } | |
| 862 } | |
| 863 | |
| 864 if (!network->unique_id().empty()) | |
| 865 network_unique_id_map_[network->unique_id()] = network; | |
| 866 | |
| 867 SetProfileTypeFromPath(network); | |
| 868 | |
| 869 UpdateActiveNetwork(network); | |
| 870 | |
| 871 // Copy remembered credentials if required. | |
| 872 Network* remembered = FindRememberedFromNetwork(network); | |
| 873 if (remembered) | |
| 874 network->CopyCredentialsFromRemembered(remembered); | |
| 875 | |
| 876 // Find and erase entry in update_requests, and set network priority. | |
| 877 PriorityMap::iterator found2 = network_update_requests_.find(service_path); | |
| 878 if (found2 != network_update_requests_.end()) { | |
| 879 network->priority_order_ = found2->second; | |
| 880 network_update_requests_.erase(found2); | |
| 881 } else { | |
| 882 // TODO(stevenjb): Enable warning once UpdateNetworkServiceList is fixed. | |
| 883 // LOG(WARNING) << "ParseNetwork called with no update request entry: " | |
| 884 // << service_path; | |
| 885 } | |
| 886 | |
| 887 VLOG(2) << "ParseNetwork: " << network->name() | |
| 888 << " path: " << network->service_path() | |
| 889 << " profile: " << network->profile_path_; | |
| 890 NotifyNetworkManagerChanged(false); // Not forced. | |
| 891 return network; | |
| 892 } | |
| 893 | |
| 894 //////////////////////////////////////////////////////////////////////////// | |
| 895 | |
| 896 void NetworkLibraryImplCros::UpdateRememberedNetworks( | |
| 897 const ListValue* profiles) { | |
| 898 VLOG(1) << "UpdateRememberedNetworks"; | |
| 899 // Update the list of profiles. | |
| 900 NetworkProfileList old_profile_list; | |
| 901 old_profile_list.swap(profile_list_); | |
| 902 | |
| 903 for (ListValue::const_iterator iter = profiles->begin(); | |
| 904 iter != profiles->end(); ++iter) { | |
| 905 std::string profile_path; | |
| 906 (*iter)->GetAsString(&profile_path); | |
| 907 if (profile_path.empty()) { | |
| 908 LOG(WARNING) << "Bad or empty profile path."; | |
| 909 continue; | |
| 910 } | |
| 911 NetworkProfileType profile_type; | |
| 912 if (profile_path == kSharedProfilePath) | |
| 913 profile_type = PROFILE_SHARED; | |
| 914 else | |
| 915 profile_type = PROFILE_USER; | |
| 916 AddProfile(profile_path, profile_type); | |
| 917 } | |
| 918 bool lists_equal = old_profile_list.size() == profile_list_.size() && | |
| 919 std::equal(profile_list_.begin(), profile_list_.end(), | |
| 920 old_profile_list.begin(), AreProfilePathsEqual); | |
| 921 | |
| 922 RequestRememberedNetworksUpdate(); | |
| 923 if (!lists_equal) | |
| 924 NotifyNetworkProfileObservers(); | |
| 925 } | |
| 926 | |
| 927 void NetworkLibraryImplCros::RequestRememberedNetworksUpdate() { | |
| 928 VLOG(1) << "RequestRememberedNetworksUpdate"; | |
| 929 // Delete all remembered networks. We delete them because | |
| 930 // RequestNetworkProfileProperties is asynchronous and may invoke | |
| 931 // UpdateRememberedServiceList multiple times (once per profile). | |
| 932 // We can do this safely because we do not save any local state for | |
| 933 // remembered networks. This list updates infrequently. | |
| 934 DeleteRememberedNetworks(); | |
| 935 // Request remembered networks from each profile. Later entries will | |
| 936 // override earlier entries, so default/local entries will override | |
| 937 // user entries (as desired). | |
| 938 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
| 939 iter != profile_list_.end(); ++iter) { | |
| 940 NetworkProfile& profile = *iter; | |
| 941 VLOG(1) << " Requesting Profile: " << profile.path; | |
| 942 CrosRequestNetworkProfileProperties( | |
| 943 profile.path, | |
| 944 base::Bind(&NetworkLibraryImplCros::UpdateProfile, | |
| 945 weak_ptr_factory_.GetWeakPtr())); | |
| 946 } | |
| 947 } | |
| 948 | |
| 949 void NetworkLibraryImplCros::UpdateProfile( | |
| 950 const std::string& profile_path, | |
| 951 const base::DictionaryValue* properties) { | |
| 952 if (!properties) { | |
| 953 LOG(ERROR) << "Error retrieving profile: " << profile_path; | |
| 954 return; | |
| 955 } | |
| 956 VLOG(1) << "UpdateProfile for path: " << profile_path; | |
| 957 const ListValue* profile_entries(NULL); | |
| 958 properties->GetList(flimflam::kEntriesProperty, &profile_entries); | |
| 959 if (!profile_entries) { | |
| 960 LOG(ERROR) << "'Entries' property is missing."; | |
| 961 return; | |
| 962 } | |
| 963 | |
| 964 NetworkProfileList::iterator iter1; | |
| 965 for (iter1 = profile_list_.begin(); iter1 != profile_list_.end(); ++iter1) { | |
| 966 if (iter1->path == profile_path) | |
| 967 break; | |
| 968 } | |
| 969 if (iter1 == profile_list_.end()) { | |
| 970 // This can happen if shill gets restarted while Chrome is running. | |
| 971 LOG(WARNING) << "Profile not in list: " << profile_path; | |
| 972 return; | |
| 973 } | |
| 974 NetworkProfile& profile = *iter1; | |
| 975 // |profile_entries| is a list of remembered networks from |profile_path|. | |
| 976 profile.services.clear(); | |
| 977 for (ListValue::const_iterator iter2 = profile_entries->begin(); | |
| 978 iter2 != profile_entries->end(); ++iter2) { | |
| 979 std::string service_path; | |
| 980 (*iter2)->GetAsString(&service_path); | |
| 981 if (service_path.empty()) { | |
| 982 LOG(WARNING) << "Empty service path in profile."; | |
| 983 continue; | |
| 984 } | |
| 985 VLOG(2) << " Remembered service: " << service_path; | |
| 986 // Add service to profile list. | |
| 987 profile.services.insert(service_path); | |
| 988 // Request update for remembered network. | |
| 989 // Shill does not set the Profile property for remembered networks, but only | |
| 990 // for the active networks, so we provide |profile_path| to the callback. | |
| 991 CrosRequestNetworkProfileEntryProperties( | |
| 992 profile_path, | |
| 993 service_path, | |
| 994 base::Bind(&NetworkLibraryImplCros::RememberedNetworkServiceUpdate, | |
| 995 weak_ptr_factory_.GetWeakPtr(), | |
| 996 profile_path)); | |
| 997 } | |
| 998 } | |
| 999 | |
| 1000 void NetworkLibraryImplCros::RememberedNetworkServiceUpdate( | |
| 1001 const std::string& profile_path, | |
| 1002 const std::string& service_path, | |
| 1003 const base::DictionaryValue* properties) { | |
| 1004 VLOG(2) << "RememberedNetworkServiceUpdate: profile: " << profile_path | |
| 1005 << " service: " << service_path | |
| 1006 << (properties == NULL ? " got removed" : " got updated"); | |
| 1007 if (properties) { | |
| 1008 ParseRememberedNetwork(profile_path, service_path, *properties); | |
| 1009 } else { | |
| 1010 // Remove this service from the respective Profile::services list. | |
| 1011 for (NetworkProfileList::iterator iter = profile_list_.begin(); | |
| 1012 iter != profile_list_.end(); ++iter) { | |
| 1013 NetworkProfile& profile = *iter; | |
| 1014 if (profile.path != profile_path) | |
| 1015 continue; | |
| 1016 | |
| 1017 if (profile.services.erase(service_path) != 0) { | |
| 1018 VLOG(1) << "Removed service path: " << service_path | |
| 1019 << " from Profile::services of: " << profile_path; | |
| 1020 } | |
| 1021 break; | |
| 1022 } | |
| 1023 } | |
| 1024 } | |
| 1025 | |
| 1026 // Returns NULL if |service_path| refers to a network that is not a | |
| 1027 // remembered type. Called from RememberedNetworkServiceUpdate. | |
| 1028 Network* NetworkLibraryImplCros::ParseRememberedNetwork( | |
| 1029 const std::string& profile_path, | |
| 1030 const std::string& service_path, | |
| 1031 const DictionaryValue& info) { | |
| 1032 Network* remembered; | |
| 1033 NetworkMap::iterator found = remembered_network_map_.find(service_path); | |
| 1034 if (found != remembered_network_map_.end()) { | |
| 1035 remembered = found->second; | |
| 1036 if (remembered->network_parser()) | |
| 1037 remembered->network_parser()->UpdateNetworkFromInfo(info, remembered); | |
| 1038 } else { | |
| 1039 NativeNetworkParser parser; | |
| 1040 remembered = parser.CreateNetworkFromInfo(service_path, info); | |
| 1041 if (remembered->type() == TYPE_WIFI || remembered->type() == TYPE_VPN) { | |
| 1042 if (!ValidateAndAddRememberedNetwork(remembered)) | |
| 1043 return NULL; | |
| 1044 } else { | |
| 1045 LOG(WARNING) << "Ignoring remembered network: " << service_path | |
| 1046 << " Type: " << ConnectionTypeToString(remembered->type()); | |
| 1047 delete remembered; | |
| 1048 return NULL; | |
| 1049 } | |
| 1050 } | |
| 1051 | |
| 1052 remembered->set_profile_path(profile_path); | |
| 1053 SetProfileTypeFromPath(remembered); | |
| 1054 | |
| 1055 VLOG(2) << "ParseRememberedNetwork: " << remembered->name() | |
| 1056 << " path: " << remembered->service_path() | |
| 1057 << " profile: " << remembered->profile_path_; | |
| 1058 NotifyNetworkManagerChanged(false); // Not forced. | |
| 1059 | |
| 1060 if (remembered->type() == TYPE_VPN) { | |
| 1061 // VPNs are only stored in profiles. If we don't have a network for it, | |
| 1062 // request one. | |
| 1063 if (!FindNetworkByUniqueId(remembered->unique_id())) { | |
| 1064 VirtualNetwork* vpn = static_cast<VirtualNetwork*>(remembered); | |
| 1065 std::string provider_type = ProviderTypeToString(vpn->provider_type()); | |
| 1066 VLOG(2) << "Requesting VPN: " << vpn->name() | |
| 1067 << " Server: " << vpn->server_hostname() | |
| 1068 << " Type: " << provider_type; | |
| 1069 CrosRequestVirtualNetworkProperties( | |
| 1070 vpn->name(), | |
| 1071 vpn->server_hostname(), | |
| 1072 provider_type, | |
| 1073 base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, | |
| 1074 weak_ptr_factory_.GetWeakPtr())); | |
| 1075 } | |
| 1076 } | |
| 1077 | |
| 1078 return remembered; | |
| 1079 } | |
| 1080 | |
| 1081 //////////////////////////////////////////////////////////////////////////// | |
| 1082 // NetworkDevice list management functions. | |
| 1083 | |
| 1084 // Update device list, and request associated device updates. | |
| 1085 // |devices| represents a complete list of devices. | |
| 1086 void NetworkLibraryImplCros::UpdateNetworkDeviceList(const ListValue* devices) { | |
| 1087 NetworkDeviceMap old_device_map = device_map_; | |
| 1088 device_map_.clear(); | |
| 1089 VLOG(2) << "Updating Device List."; | |
| 1090 for (ListValue::const_iterator iter = devices->begin(); | |
| 1091 iter != devices->end(); ++iter) { | |
| 1092 std::string device_path; | |
| 1093 (*iter)->GetAsString(&device_path); | |
| 1094 if (!device_path.empty()) { | |
| 1095 NetworkDeviceMap::iterator found = old_device_map.find(device_path); | |
| 1096 if (found != old_device_map.end()) { | |
| 1097 VLOG(2) << " Adding existing device: " << device_path; | |
| 1098 CHECK(found->second) << "Attempted to add NULL device pointer"; | |
| 1099 device_map_[device_path] = found->second; | |
| 1100 old_device_map.erase(found); | |
| 1101 } | |
| 1102 CrosRequestNetworkDeviceProperties( | |
| 1103 device_path, | |
| 1104 base::Bind(&NetworkLibraryImplCros::NetworkDeviceUpdate, | |
| 1105 weak_ptr_factory_.GetWeakPtr())); | |
| 1106 } | |
| 1107 } | |
| 1108 // Delete any old devices that no longer exist. | |
| 1109 for (NetworkDeviceMap::iterator iter = old_device_map.begin(); | |
| 1110 iter != old_device_map.end(); ++iter) { | |
| 1111 DeleteDeviceFromDeviceObserversMap(iter->first); | |
| 1112 // Delete device. | |
| 1113 delete iter->second; | |
| 1114 } | |
| 1115 } | |
| 1116 | |
| 1117 void NetworkLibraryImplCros::NetworkDeviceUpdate( | |
| 1118 const std::string& device_path, | |
| 1119 const base::DictionaryValue* properties) { | |
| 1120 if (!properties) { | |
| 1121 // device no longer exists. | |
| 1122 DeleteDevice(device_path); | |
| 1123 } else { | |
| 1124 ParseNetworkDevice(device_path, *properties); | |
| 1125 } | |
| 1126 } | |
| 1127 | |
| 1128 void NetworkLibraryImplCros::ParseNetworkDevice(const std::string& device_path, | |
| 1129 const DictionaryValue& info) { | |
| 1130 NetworkDeviceMap::iterator found = device_map_.find(device_path); | |
| 1131 NetworkDevice* device; | |
| 1132 if (found != device_map_.end()) { | |
| 1133 device = found->second; | |
| 1134 device->device_parser()->UpdateDeviceFromInfo(info, device); | |
| 1135 } else { | |
| 1136 NativeNetworkDeviceParser parser; | |
| 1137 device = parser.CreateDeviceFromInfo(device_path, info); | |
| 1138 VLOG(2) << " Adding device: " << device_path; | |
| 1139 if (device) { | |
| 1140 device_map_[device_path] = device; | |
| 1141 } | |
| 1142 CHECK(device) << "Attempted to add NULL device for path: " << device_path; | |
| 1143 } | |
| 1144 VLOG(2) << "ParseNetworkDevice:" << device->name(); | |
| 1145 | |
| 1146 // Re-synchronize the roaming setting with the device property if required. | |
| 1147 if (device && device->type() == TYPE_CELLULAR) | |
| 1148 UpdateCellularDeviceStatus(device, PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING); | |
| 1149 | |
| 1150 if (device && device->type() == TYPE_WIFI) | |
| 1151 wifi_scanning_ = device->scanning(); | |
| 1152 | |
| 1153 NotifyNetworkManagerChanged(false); // Not forced. | |
| 1154 AddNetworkDeviceObserver(device_path, network_device_observer_.get()); | |
| 1155 } | |
| 1156 | |
| 1157 void NetworkLibraryImplCros::SetIPParametersCallback( | |
| 1158 const IPParameterInfo& info, | |
| 1159 const std::string& service_path, | |
| 1160 const base::DictionaryValue* properties) { | |
| 1161 // crbug.com/146616 will fix this once we have better | |
| 1162 // handling of shill errors. | |
| 1163 if (!properties) | |
| 1164 return; | |
| 1165 | |
| 1166 Network* network = FindNetworkByPath(service_path); | |
| 1167 if (!network) | |
| 1168 return; | |
| 1169 | |
| 1170 // Find the properties we're going to set, and minimize the DBus calls below | |
| 1171 // by not clearing if it's already cleared, and not setting if it's already | |
| 1172 // set to the same value. Also, don't reconnect at the end if nothing changed. | |
| 1173 bool something_changed = false; | |
| 1174 std::string current_address; | |
| 1175 int32 current_prefixlen = -1; | |
| 1176 std::string current_gateway; | |
| 1177 std::string current_name_servers; | |
| 1178 bool address_exists = properties->GetStringWithoutPathExpansion( | |
| 1179 shill::kStaticIPAddressProperty, | |
| 1180 ¤t_address); | |
| 1181 VLOG_IF(2, address_exists) << shill::kStaticIPAddressProperty | |
| 1182 << "=" << current_address; | |
| 1183 bool prefixlen_exists = properties->GetIntegerWithoutPathExpansion( | |
| 1184 shill::kStaticIPPrefixlenProperty, | |
| 1185 ¤t_prefixlen); | |
| 1186 VLOG_IF(2, prefixlen_exists) << shill::kStaticIPPrefixlenProperty | |
| 1187 << "=" << current_prefixlen; | |
| 1188 bool gateway_exists = properties->GetStringWithoutPathExpansion( | |
| 1189 shill::kStaticIPGatewayProperty, | |
| 1190 ¤t_gateway); | |
| 1191 VLOG_IF(2, gateway_exists) << shill::kStaticIPGatewayProperty | |
| 1192 << "=" << current_gateway; | |
| 1193 bool name_servers_exist = properties->GetStringWithoutPathExpansion( | |
| 1194 shill::kStaticIPNameServersProperty, | |
| 1195 ¤t_name_servers); | |
| 1196 VLOG_IF(2, name_servers_exist) << shill::kStaticIPNameServersProperty | |
| 1197 << "=" << current_name_servers; | |
| 1198 | |
| 1199 if (info.dhcp_usage_mask & USE_DHCP_ADDRESS) { | |
| 1200 if (address_exists) { | |
| 1201 something_changed = true; | |
| 1202 CrosClearNetworkServiceProperty(service_path, | |
| 1203 shill::kStaticIPAddressProperty); | |
| 1204 VLOG(2) << "Clearing " << shill::kStaticIPAddressProperty; | |
| 1205 } | |
| 1206 } else if (current_address != info.address) { | |
| 1207 base::StringValue value(info.address); | |
| 1208 VLOG(2) << "Setting " << shill::kStaticIPAddressProperty | |
| 1209 << " to " << info.address; | |
| 1210 something_changed = true; | |
| 1211 CrosSetNetworkServiceProperty(service_path, | |
| 1212 shill::kStaticIPAddressProperty, | |
| 1213 value); | |
| 1214 } | |
| 1215 | |
| 1216 if (info.dhcp_usage_mask & USE_DHCP_NETMASK) { | |
| 1217 if (prefixlen_exists) { | |
| 1218 something_changed = true; | |
| 1219 CrosClearNetworkServiceProperty(service_path, | |
| 1220 shill::kStaticIPPrefixlenProperty); | |
| 1221 VLOG(2) << "Clearing " << shill::kStaticIPPrefixlenProperty; | |
| 1222 } | |
| 1223 } else { | |
| 1224 int prefixlen = network_util::NetmaskToPrefixLength(info.netmask); | |
| 1225 if (prefixlen == -1) { | |
| 1226 VLOG(1) << "IPConfig prefix length is invalid for netmask " | |
| 1227 << info.netmask; | |
| 1228 } else if (current_prefixlen != prefixlen) { | |
| 1229 base::FundamentalValue value(prefixlen); | |
| 1230 VLOG(2) << "Setting " << shill::kStaticIPPrefixlenProperty | |
| 1231 << " to " << prefixlen; | |
| 1232 something_changed = true; | |
| 1233 CrosSetNetworkServiceProperty(service_path, | |
| 1234 shill::kStaticIPPrefixlenProperty, | |
| 1235 value); | |
| 1236 } | |
| 1237 } | |
| 1238 | |
| 1239 if (info.dhcp_usage_mask & USE_DHCP_GATEWAY) { | |
| 1240 if (gateway_exists) { | |
| 1241 something_changed = true; | |
| 1242 CrosClearNetworkServiceProperty(service_path, | |
| 1243 shill::kStaticIPGatewayProperty); | |
| 1244 VLOG(2) << "Clearing " << shill::kStaticIPGatewayProperty; | |
| 1245 } | |
| 1246 } else if (current_gateway != info.gateway){ | |
| 1247 base::StringValue value(info.gateway); | |
| 1248 VLOG(2) << "Setting " << shill::kStaticIPGatewayProperty | |
| 1249 << " to " << info.gateway; | |
| 1250 something_changed = true; | |
| 1251 CrosSetNetworkServiceProperty(service_path, | |
| 1252 shill::kStaticIPGatewayProperty, | |
| 1253 value); | |
| 1254 } | |
| 1255 | |
| 1256 if (info.dhcp_usage_mask & USE_DHCP_NAME_SERVERS) { | |
| 1257 if (name_servers_exist) { | |
| 1258 something_changed = true; | |
| 1259 CrosClearNetworkServiceProperty(service_path, | |
| 1260 shill::kStaticIPNameServersProperty); | |
| 1261 VLOG(2) << "Clearing " << shill::kStaticIPNameServersProperty; | |
| 1262 | |
| 1263 // Notify that the network changed, so that the DNS cache can be | |
| 1264 // cleared properly. | |
| 1265 NotifyNetworkChanged(network); | |
| 1266 } | |
| 1267 } else if (current_name_servers != info.name_servers){ | |
| 1268 base::StringValue value(info.name_servers); | |
| 1269 VLOG(2) << "Setting " << shill::kStaticIPNameServersProperty | |
| 1270 << " to " << info.name_servers; | |
| 1271 something_changed = true; | |
| 1272 CrosSetNetworkServiceProperty(service_path, | |
| 1273 shill::kStaticIPNameServersProperty, | |
| 1274 value); | |
| 1275 | |
| 1276 // Notify that the network changed, so that the DNS cache can be | |
| 1277 // cleared properly. | |
| 1278 NotifyNetworkChanged(network); | |
| 1279 } | |
| 1280 | |
| 1281 if (!something_changed) | |
| 1282 return; | |
| 1283 | |
| 1284 // Ensure NetworkStateHandler properties are up-to-date. | |
| 1285 if (NetworkHandler::IsInitialized()) { | |
| 1286 NetworkHandler::Get()->network_state_handler()->RequestUpdateForNetwork( | |
| 1287 service_path); | |
| 1288 } | |
| 1289 | |
| 1290 // Attempt to refresh its IP parameters, so that the changes to the service | |
| 1291 // properties can take effect. | |
| 1292 if (network->connecting_or_connected()) | |
| 1293 RefreshIPConfig(network); | |
| 1294 } | |
| 1295 | |
| 1296 // static | |
| 1297 bool NetworkLibraryImplCros::AreProfilePathsEqual(const NetworkProfile& a, | |
| 1298 const NetworkProfile& b) { | |
| 1299 return a.path == b.path; | |
| 1300 } | |
| 1301 | |
| 1302 } // namespace chromeos | |
| OLD | NEW |