| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/chromeos/cros/network_library_impl_cros.h" |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/json/json_writer.h" // for debug output only. |
| #include "base/metrics/histogram.h" |
| #include "base/stl_util.h" |
| #include "base/values.h" |
| #include "chrome/browser/chromeos/cros/native_network_constants.h" |
| #include "chrome/browser/chromeos/cros/native_network_parser.h" |
| #include "chrome/browser/chromeos/settings/cros_settings.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chromeos/network/cros_network_functions.h" |
| #include "chromeos/network/network_state_handler.h" |
| #include "chromeos/network/network_util.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "third_party/cros_system_api/dbus/service_constants.h" |
| |
| using content::BrowserThread; |
| |
| namespace chromeos { |
| |
| // Structure used to pass IP parameter info to a DoSetIPParameters callback, |
| // since Bind only takes up to six parameters. |
| struct NetworkLibraryImplCros::IPParameterInfo { |
| std::string address; |
| std::string netmask; |
| std::string gateway; |
| std::string name_servers; |
| int dhcp_usage_mask; |
| }; |
| |
| //////////////////////////////////////////////////////////////////////////// |
| |
| NetworkLibraryImplCros::NetworkLibraryImplCros() |
| : NetworkLibraryImplBase(), |
| weak_ptr_factory_(this) { |
| } |
| |
| NetworkLibraryImplCros::~NetworkLibraryImplCros() { |
| STLDeleteValues(&monitored_networks_); |
| STLDeleteValues(&monitored_devices_); |
| } |
| |
| void NetworkLibraryImplCros::Init() { |
| // First, get the currently available networks. This data is cached |
| // on the connman side, so the call should be quick. |
| VLOG(1) << "Requesting initial network manager info from libcros."; |
| CrosRequestNetworkManagerProperties( |
| base::Bind(&NetworkLibraryImplCros::NetworkManagerUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| network_manager_watcher_.reset(CrosMonitorNetworkManagerProperties( |
| base::Bind(&NetworkLibraryImplCros::NetworkManagerStatusChangedHandler, |
| weak_ptr_factory_.GetWeakPtr()))); |
| // Always have at least one device obsever so that device updates are |
| // always received. |
| network_device_observer_.reset(new NetworkLibraryDeviceObserver()); |
| } |
| |
| bool NetworkLibraryImplCros::IsCros() const { |
| return true; |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // NetworkLibraryImplBase implementation. |
| |
| void NetworkLibraryImplCros::MonitorNetworkStart( |
| const std::string& service_path) { |
| if (monitored_networks_.find(service_path) == monitored_networks_.end()) { |
| CrosNetworkWatcher* watcher = CrosMonitorNetworkServiceProperties( |
| base::Bind(&NetworkLibraryImplCros::UpdateNetworkStatus, |
| weak_ptr_factory_.GetWeakPtr()), |
| service_path); |
| monitored_networks_[service_path] = watcher; |
| } |
| } |
| |
| void NetworkLibraryImplCros::MonitorNetworkStop( |
| const std::string& service_path) { |
| NetworkWatcherMap::iterator iter = monitored_networks_.find(service_path); |
| if (iter != monitored_networks_.end()) { |
| delete iter->second; |
| monitored_networks_.erase(iter); |
| } |
| } |
| |
| void NetworkLibraryImplCros::MonitorNetworkDeviceStart( |
| const std::string& device_path) { |
| if (monitored_devices_.find(device_path) == monitored_devices_.end()) { |
| CrosNetworkWatcher* watcher = CrosMonitorNetworkDeviceProperties( |
| base::Bind(&NetworkLibraryImplCros::UpdateNetworkDeviceStatus, |
| weak_ptr_factory_.GetWeakPtr()), |
| device_path); |
| monitored_devices_[device_path] = watcher; |
| } |
| } |
| |
| void NetworkLibraryImplCros::MonitorNetworkDeviceStop( |
| const std::string& device_path) { |
| NetworkWatcherMap::iterator iter = monitored_devices_.find(device_path); |
| if (iter != monitored_devices_.end()) { |
| delete iter->second; |
| monitored_devices_.erase(iter); |
| } |
| } |
| |
| void NetworkLibraryImplCros::UpdateNetworkStatus( |
| const std::string& path, const std::string& key, const Value& value) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| Network* network = FindNetworkByPath(path); |
| if (network) { |
| VLOG(2) << "UpdateNetworkStatus: " << network->name() << "." << key; |
| bool prev_connected = network->connected(); |
| if (!network->UpdateStatus(key, value, NULL)) { |
| LOG(WARNING) << "UpdateNetworkStatus: Error updating: " |
| << path << "." << key; |
| } |
| if (key == flimflam::kProfileProperty) |
| SetProfileTypeFromPath(network); |
| // If we just connected, this may have been added to remembered list. |
| if (!prev_connected && network->connected()) |
| RequestRememberedNetworksUpdate(); |
| NotifyNetworkChanged(network); |
| // Anything observing the manager needs to know about any service change. |
| NotifyNetworkManagerChanged(false); // Not forced. |
| } |
| } |
| |
| void NetworkLibraryImplCros::UpdateNetworkDeviceStatus( |
| const std::string& path, const std::string& key, const Value& value) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| NetworkDevice* device = FindNetworkDeviceByPath(path); |
| if (device) { |
| VLOG(2) << "UpdateNetworkDeviceStatus: " << device->name() << "." << key; |
| PropertyIndex index = PROPERTY_INDEX_UNKNOWN; |
| if (device->UpdateStatus(key, value, &index)) { |
| if (device->type() == TYPE_CELLULAR) { |
| if (!UpdateCellularDeviceStatus(device, index)) |
| return; // Update aborted, skip notify. |
| } |
| } else { |
| VLOG(1) << "UpdateNetworkDeviceStatus: Failed to update: " |
| << path << "." << key; |
| } |
| if (device->type() == TYPE_WIFI && device->scanning() != wifi_scanning_) { |
| wifi_scanning_ = device->scanning(); |
| NotifyNetworkManagerChanged(false); // Not forced. |
| } |
| // Notify only observers on device property change. |
| NotifyNetworkDeviceChanged(device, index); |
| // If a device's power state changes, new properties may become defined. |
| if (index == PROPERTY_INDEX_POWERED) { |
| CrosRequestNetworkDeviceProperties( |
| path, |
| base::Bind(&NetworkLibraryImplCros::NetworkDeviceUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| } |
| |
| bool NetworkLibraryImplCros::UpdateCellularDeviceStatus(NetworkDevice* device, |
| PropertyIndex index) { |
| if (index == PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING) { |
| if (IsCellularAlwaysInRoaming()) { |
| if (!device->data_roaming_allowed()) |
| SetCellularDataRoamingAllowed(true); |
| } else { |
| bool settings_value; |
| if ((CrosSettings::Get()->GetBoolean( |
| kSignedDataRoamingEnabled, &settings_value)) && |
| (device->data_roaming_allowed() != settings_value)) { |
| // Switch back to signed settings value. |
| SetCellularDataRoamingAllowed(settings_value); |
| return false; |
| } |
| } |
| } else if (index == PROPERTY_INDEX_SIM_LOCK) { |
| // We only ever request a sim unlock when we wish to enable the device. |
| if (!device->is_sim_locked() && !cellular_enabled()) |
| EnableCellularNetworkDevice(true); |
| } |
| return true; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| // NetworkLibraryImplBase connect implementation. |
| |
| void NetworkLibraryImplCros::CallConfigureService(const std::string& identifier, |
| const DictionaryValue* info) { |
| CrosConfigureService(*info); |
| } |
| |
| void NetworkLibraryImplCros::NetworkConnectCallback( |
| const std::string& service_path, |
| NetworkMethodErrorType error, |
| const std::string& error_message) { |
| NetworkConnectStatus status; |
| if (error == NETWORK_METHOD_ERROR_NONE) { |
| status = CONNECT_SUCCESS; |
| } else { |
| LOG(WARNING) << "Error from ServiceConnect callback for: " |
| << service_path |
| << " Error: " << error << " Message: " << error_message; |
| if (error_message == flimflam::kErrorPassphraseRequiredMsg) { |
| status = CONNECT_BAD_PASSPHRASE; |
| } else { |
| status = CONNECT_FAILED; |
| } |
| } |
| Network* network = FindNetworkByPath(service_path); |
| if (!network) { |
| LOG(ERROR) << "No network for path: " << service_path; |
| return; |
| } |
| NetworkConnectCompleted(network, status); |
| } |
| |
| void NetworkLibraryImplCros::CallConnectToNetwork(Network* network) { |
| DCHECK(network); |
| CrosRequestNetworkServiceConnect( |
| network->service_path(), |
| base::Bind(&NetworkLibraryImplCros::NetworkConnectCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::WifiServiceUpdateAndConnect( |
| const std::string& service_path, |
| const base::DictionaryValue* properties) { |
| if (properties) { |
| Network* network = ParseNetwork(service_path, *properties); |
| CHECK_EQ(network->type(), TYPE_WIFI); |
| ConnectToWifiNetworkUsingConnectData(static_cast<WifiNetwork*>(network)); |
| } |
| } |
| |
| void NetworkLibraryImplCros::CallRequestWifiNetworkAndConnect( |
| const std::string& ssid, ConnectionSecurity security) { |
| // Asynchronously request service properties and call |
| // WifiServiceUpdateAndConnect. |
| CrosRequestHiddenWifiNetworkProperties( |
| ssid, |
| SecurityToString(security), |
| base::Bind(&NetworkLibraryImplCros::WifiServiceUpdateAndConnect, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::VPNServiceUpdateAndConnect( |
| const std::string& service_path, |
| const base::DictionaryValue* properties) { |
| if (properties) { |
| VLOG(1) << "Connecting to new VPN Service: " << service_path; |
| Network* network = ParseNetwork(service_path, *properties); |
| CHECK_EQ(network->type(), TYPE_VPN); |
| ConnectToVirtualNetworkUsingConnectData( |
| static_cast<VirtualNetwork*>(network)); |
| } else { |
| LOG(WARNING) << "Unable to create VPN Service: " << service_path; |
| } |
| } |
| |
| void NetworkLibraryImplCros::CallRequestVirtualNetworkAndConnect( |
| const std::string& service_name, |
| const std::string& server_hostname, |
| ProviderType provider_type) { |
| CrosRequestVirtualNetworkProperties( |
| service_name, |
| server_hostname, |
| ProviderTypeToString(provider_type), |
| base::Bind(&NetworkLibraryImplCros::VPNServiceUpdateAndConnect, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::CallDeleteRememberedNetwork( |
| const std::string& profile_path, |
| const std::string& service_path) { |
| CrosDeleteServiceFromProfile(profile_path, service_path); |
| } |
| |
| ////////////////////////////////////////////////////////////////////////////// |
| // NetworkLibrary implementation. |
| |
| void NetworkLibraryImplCros::ChangePin(const std::string& old_pin, |
| const std::string& new_pin) { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling ChangePin method w/o cellular device."; |
| return; |
| } |
| sim_operation_ = SIM_OPERATION_CHANGE_PIN; |
| CrosRequestChangePin( |
| cellular->device_path(), old_pin, new_pin, |
| base::Bind(&NetworkLibraryImplCros::PinOperationCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::ChangeRequirePin(bool require_pin, |
| const std::string& pin) { |
| VLOG(1) << "ChangeRequirePin require_pin: " << require_pin |
| << " pin: " << pin; |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling ChangeRequirePin method w/o cellular device."; |
| return; |
| } |
| sim_operation_ = SIM_OPERATION_CHANGE_REQUIRE_PIN; |
| CrosRequestRequirePin( |
| cellular->device_path(), pin, require_pin, |
| base::Bind(&NetworkLibraryImplCros::PinOperationCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::EnterPin(const std::string& pin) { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling EnterPin method w/o cellular device."; |
| return; |
| } |
| sim_operation_ = SIM_OPERATION_ENTER_PIN; |
| CrosRequestEnterPin(cellular->device_path(), pin, |
| base::Bind(&NetworkLibraryImplCros::PinOperationCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::UnblockPin(const std::string& puk, |
| const std::string& new_pin) { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling UnblockPin method w/o cellular device."; |
| return; |
| } |
| sim_operation_ = SIM_OPERATION_UNBLOCK_PIN; |
| CrosRequestUnblockPin( |
| cellular->device_path(), puk, new_pin, |
| base::Bind(&NetworkLibraryImplCros::PinOperationCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::PinOperationCallback( |
| const std::string& path, |
| NetworkMethodErrorType error, |
| const std::string& error_message) { |
| PinOperationError pin_error; |
| VLOG(1) << "PinOperationCallback, error: " << error |
| << " error_msg: " << error_message; |
| if (error == chromeos::NETWORK_METHOD_ERROR_NONE) { |
| pin_error = PIN_ERROR_NONE; |
| VLOG(1) << "Pin operation completed successfuly"; |
| } else { |
| if (error_message == flimflam::kErrorIncorrectPinMsg || |
| error_message == flimflam::kErrorPinRequiredMsg) { |
| pin_error = PIN_ERROR_INCORRECT_CODE; |
| } else if (error_message == flimflam::kErrorPinBlockedMsg) { |
| pin_error = PIN_ERROR_BLOCKED; |
| } else { |
| pin_error = PIN_ERROR_UNKNOWN; |
| NOTREACHED() << "Unknown PIN error: " << error_message; |
| } |
| } |
| NotifyPinOperationCompleted(pin_error); |
| } |
| |
| void NetworkLibraryImplCros::RequestCellularScan() { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling RequestCellularScan method w/o cellular device."; |
| return; |
| } |
| CrosProposeScan(cellular->device_path()); |
| } |
| |
| void NetworkLibraryImplCros::RequestCellularRegister( |
| const std::string& network_id) { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling CellularRegister method w/o cellular device."; |
| return; |
| } |
| CrosRequestCellularRegister( |
| cellular->device_path(), network_id, |
| base::Bind(&NetworkLibraryImplCros::CellularRegisterCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::CellularRegisterCallback( |
| const std::string& path, |
| NetworkMethodErrorType error, |
| const std::string& error_message) { |
| // TODO(dpolukhin): Notify observers about network registration status |
| // but not UI doesn't assume such notification so just ignore result. |
| } |
| |
| void NetworkLibraryImplCros::SetCellularDataRoamingAllowed(bool new_value) { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling SetCellularDataRoamingAllowed method " |
| "w/o cellular device."; |
| return; |
| } |
| base::FundamentalValue value(new_value); |
| CrosSetNetworkDeviceProperty(cellular->device_path(), |
| flimflam::kCellularAllowRoamingProperty, |
| value); |
| } |
| |
| void NetworkLibraryImplCros::SetCarrier( |
| const std::string& carrier, |
| const NetworkOperationCallback& completed) { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling SetCarrier method w/o cellular device."; |
| return; |
| } |
| CrosSetCarrier(cellular->device_path(), carrier, completed); |
| } |
| |
| bool NetworkLibraryImplCros::IsCellularAlwaysInRoaming() { |
| const NetworkDevice* cellular = FindCellularDevice(); |
| if (!cellular) { |
| NOTREACHED() << "Calling IsCellularAlwaysInRoaming method " |
| "w/o cellular device."; |
| return false; |
| } |
| return cellular->provider_requires_roaming(); |
| } |
| |
| void NetworkLibraryImplCros::RequestNetworkScan() { |
| if (wifi_enabled()) |
| CrosRequestNetworkScan(flimflam::kTypeWifi); |
| |
| if (wimax_enabled()) |
| CrosRequestNetworkScan(flimflam::kTypeWimax); |
| |
| // Make sure all Manager info is up to date. This will also update |
| // remembered networks and visible services. |
| CrosRequestNetworkManagerProperties( |
| base::Bind(&NetworkLibraryImplCros::NetworkManagerUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::RefreshIPConfig(Network* network) { |
| DCHECK(network); |
| CrosRequestNetworkDeviceProperties( |
| network->device_path(), |
| base::Bind(&NetworkLibraryImplCros::RefreshIPConfigCallback, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| |
| void NetworkLibraryImplCros::RefreshIPConfigCallback( |
| const std::string& device_path, |
| const base::DictionaryValue* properties) { |
| const ListValue* ips = NULL; |
| if (!properties->GetListWithoutPathExpansion( |
| flimflam::kIPConfigsProperty, &ips)) |
| return; |
| |
| for (size_t i = 0; i < ips->GetSize(); i++) { |
| std::string ipconfig_path; |
| if (!ips->GetString(i, &ipconfig_path)) |
| continue; |
| CrosRequestIPConfigRefresh(ipconfig_path); |
| } |
| } |
| |
| void NetworkLibraryImplCros::DisconnectFromNetwork(const Network* network) { |
| DCHECK(network); |
| // Asynchronous disconnect request. Network state will be updated through |
| // the network manager once disconnect completes. |
| CrosRequestNetworkServiceDisconnect(network->service_path()); |
| } |
| |
| void NetworkLibraryImplCros::CallEnableNetworkDeviceType( |
| ConnectionType device, bool enable) { |
| busy_devices_ |= 1 << device; |
| CrosRequestNetworkDeviceEnable(ConnectionTypeToString(device), enable); |
| if (device == TYPE_WIFI && enable) |
| RequestNetworkScan(); |
| } |
| |
| void NetworkLibraryImplCros::CallRemoveNetwork(const Network* network) { |
| const std::string& service_path = network->service_path(); |
| if (network->connected()) |
| CrosRequestNetworkServiceDisconnect(service_path); |
| CrosRequestRemoveNetworkService(service_path); |
| } |
| |
| void NetworkLibraryImplCros::GetIPConfigsCallback( |
| const NetworkGetIPConfigsCallback& callback, |
| HardwareAddressFormat format, |
| const NetworkIPConfigVector& ipconfig_vector, |
| const std::string& hardware_address) { |
| std::string hardware_address_tmp = hardware_address; |
| for (size_t i = 0; i < hardware_address_tmp.size(); ++i) |
| hardware_address_tmp[i] = toupper(hardware_address_tmp[i]); |
| if (format == FORMAT_COLON_SEPARATED_HEX) { |
| if (hardware_address_tmp.size() % 2 == 0) { |
| std::string output; |
| for (size_t i = 0; i < hardware_address_tmp.size(); ++i) { |
| if ((i != 0) && (i % 2 == 0)) |
| output.push_back(':'); |
| output.push_back(hardware_address_tmp[i]); |
| } |
| hardware_address_tmp.swap(output); |
| } |
| } else { |
| DCHECK_EQ(format, FORMAT_RAW_HEX); |
| } |
| callback.Run(ipconfig_vector, hardware_address_tmp); |
| } |
| |
| void NetworkLibraryImplCros::GetIPConfigs( |
| const std::string& device_path, |
| HardwareAddressFormat format, |
| const NetworkGetIPConfigsCallback& callback) { |
| CrosListIPConfigs(device_path, |
| base::Bind(&NetworkLibraryImplCros::GetIPConfigsCallback, |
| weak_ptr_factory_.GetWeakPtr(), |
| callback, |
| format)); |
| } |
| |
| void NetworkLibraryImplCros::SetIPParameters(const std::string& service_path, |
| const std::string& address, |
| const std::string& netmask, |
| const std::string& gateway, |
| const std::string& name_servers, |
| int dhcp_usage_mask) { |
| if (service_path.empty()) |
| return; |
| |
| VLOG(1) << "Setting IP parameters: " |
| << "address: " << address |
| << (dhcp_usage_mask & USE_DHCP_ADDRESS ? |
| " (ignored)" : " (in use)") |
| << "netmask: " << netmask |
| << (dhcp_usage_mask & USE_DHCP_NETMASK ? |
| " (ignored)" : " (in use)") |
| << "gateway: " << gateway |
| << (dhcp_usage_mask & USE_DHCP_GATEWAY ? |
| " (ignored)" : " (in use)") |
| << "name_servers: " << name_servers |
| << (dhcp_usage_mask & USE_DHCP_NAME_SERVERS ? |
| " (ignored)" : " (in use)"); |
| |
| // Have to pass these in a structure, since Bind only takes up to six |
| // parameters. |
| IPParameterInfo info; |
| info.address = address; |
| info.netmask = netmask; |
| info.gateway = gateway; |
| info.name_servers = name_servers; |
| info.dhcp_usage_mask = dhcp_usage_mask; |
| chromeos::NetworkPropertiesCallback callback = |
| base::Bind(&NetworkLibraryImplCros::SetIPParametersCallback, |
| weak_ptr_factory_.GetWeakPtr(), info); |
| |
| CrosRequestNetworkServiceProperties(service_path, callback); |
| } |
| |
| void NetworkLibraryImplCros::RequestNetworkServiceProperties( |
| const std::string& service_path, |
| const NetworkServicePropertiesCallback& callback) { |
| chromeos::CrosRequestNetworkServiceProperties(service_path, callback); |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////// |
| // Network Manager functions. |
| |
| void NetworkLibraryImplCros::NetworkManagerStatusChangedHandler( |
| const std::string& path, |
| const std::string& key, |
| const Value& value) { |
| if (!NetworkManagerStatusChanged(key, &value)) { |
| LOG(ERROR) << "Invalid key-value pair, key: " << key << " type: " |
| << value.GetType(); |
| } |
| } |
| |
| // This processes all Manager update messages. |
| bool NetworkLibraryImplCros::NetworkManagerStatusChanged( |
| const std::string& key, const Value* value) { |
| CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| base::TimeTicks start = base::TimeTicks::Now(); |
| VLOG(1) << "NetworkManagerStatusChanged: KEY=" << key; |
| int index = NativeNetworkParser::property_mapper()->Get(key); |
| switch (index) { |
| case PROPERTY_INDEX_STATE: |
| // Currently we ignore the network manager state. |
| break; |
| case PROPERTY_INDEX_AVAILABLE_TECHNOLOGIES: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateAvailableTechnologies(vlist); |
| break; |
| } |
| case PROPERTY_INDEX_UNINITIALIZED_TECHNOLOGIES: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateTechnologies(vlist, &uninitialized_devices_); |
| break; |
| } |
| case PROPERTY_INDEX_ENABLED_TECHNOLOGIES: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateEnabledTechnologies(vlist); |
| break; |
| } |
| case PROPERTY_INDEX_DEFAULT_TECHNOLOGY: |
| // Currently we ignore DefaultTechnology. |
| break; |
| case PROPERTY_INDEX_ACTIVE_PROFILE: { |
| std::string prev = active_profile_path_; |
| DCHECK_EQ(value->GetType(), Value::TYPE_STRING); |
| value->GetAsString(&active_profile_path_); |
| VLOG(1) << "Active Profile: " << active_profile_path_; |
| if (active_profile_path_ != prev && |
| active_profile_path_ != kSharedProfilePath) |
| SwitchToPreferredNetwork(); |
| break; |
| } |
| case PROPERTY_INDEX_PROFILES: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateRememberedNetworks(vlist); |
| break; |
| } |
| case PROPERTY_INDEX_SERVICES: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateNetworkServiceList(vlist); |
| break; |
| } |
| case PROPERTY_INDEX_SERVICE_WATCH_LIST: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateWatchedNetworkServiceList(vlist); |
| break; |
| } |
| case PROPERTY_INDEX_DEVICE: |
| case PROPERTY_INDEX_DEVICES: { |
| const ListValue* vlist = NULL; |
| if (!value->GetAsList(&vlist)) |
| return false; |
| UpdateNetworkDeviceList(vlist); |
| break; |
| } |
| case PROPERTY_INDEX_CHECK_PORTAL_LIST: { |
| DCHECK_EQ(value->GetType(), Value::TYPE_STRING); |
| value->GetAsString(&check_portal_list_); |
| break; |
| } |
| case PROPERTY_INDEX_PORTAL_URL: |
| case PROPERTY_INDEX_ARP_GATEWAY: |
| // Currently we ignore PortalURL and ArpGateway. |
| break; |
| default: |
| VLOG(2) << "Manager: Unhandled key: " << key; |
| break; |
| } |
| base::TimeDelta delta = base::TimeTicks::Now() - start; |
| VLOG(2) << "NetworkManagerStatusChanged: time: " |
| << delta.InMilliseconds() << " ms."; |
| HISTOGRAM_TIMES("CROS_NETWORK_UPDATE", delta); |
| return true; |
| } |
| |
| void NetworkLibraryImplCros::NetworkManagerUpdate( |
| const std::string& manager_path, |
| const base::DictionaryValue* properties) { |
| if (!properties) { |
| LOG(ERROR) << "Error retrieving manager properties: " << manager_path; |
| return; |
| } |
| VLOG(1) << "Received NetworkManagerUpdate."; |
| |
| for (DictionaryValue::Iterator iter(*properties); !iter.IsAtEnd(); |
| iter.Advance()) { |
| if (!NetworkManagerStatusChanged(iter.key(), &iter.value())) { |
| LOG(ERROR) << "Invalid key-value pair, key: " << iter.key() << " type: " |
| << iter.value().GetType(); |
| } |
| } |
| // If there is no Profiles entry, request remembered networks here. |
| if (!properties->HasKey(flimflam::kProfilesProperty)) |
| RequestRememberedNetworksUpdate(); |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| |
| void NetworkLibraryImplCros::UpdateTechnologies( |
| const ListValue* technologies, int* bitfieldp) { |
| DCHECK(bitfieldp); |
| if (!technologies) |
| return; |
| int bitfield = 0; |
| for (ListValue::const_iterator iter = technologies->begin(); |
| iter != technologies->end(); ++iter) { |
| std::string technology; |
| (*iter)->GetAsString(&technology); |
| if (!technology.empty()) { |
| ConnectionType type = |
| NativeNetworkParser::ParseConnectionType(technology); |
| bitfield |= 1 << type; |
| } |
| } |
| *bitfieldp = bitfield; |
| NotifyNetworkManagerChanged(false); // Not forced. |
| } |
| |
| void NetworkLibraryImplCros::UpdateAvailableTechnologies( |
| const ListValue* technologies) { |
| UpdateTechnologies(technologies, &available_devices_); |
| } |
| |
| void NetworkLibraryImplCros::UpdateEnabledTechnologies( |
| const ListValue* technologies) { |
| int old_enabled_devices = enabled_devices_; |
| UpdateTechnologies(technologies, &enabled_devices_); |
| busy_devices_ &= ~(old_enabled_devices ^ enabled_devices_); |
| if (!ethernet_enabled()) |
| ethernet_ = NULL; |
| if (!wifi_enabled()) { |
| active_wifi_ = NULL; |
| wifi_networks_.clear(); |
| } |
| if (!cellular_enabled()) { |
| active_cellular_ = NULL; |
| cellular_networks_.clear(); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| |
| // Update all network lists, and request associated service updates. |
| void NetworkLibraryImplCros::UpdateNetworkServiceList( |
| const ListValue* services) { |
| // Copy the list of existing networks to "old" and clear the map and lists. |
| NetworkMap old_network_map = network_map_; |
| ClearNetworks(); |
| // Clear the list of update requests. |
| int network_priority_order = 0; |
| network_update_requests_.clear(); |
| // |services| represents a complete list of visible networks. |
| for (ListValue::const_iterator iter = services->begin(); |
| iter != services->end(); ++iter) { |
| std::string service_path; |
| (*iter)->GetAsString(&service_path); |
| if (!service_path.empty()) { |
| // If we find the network in "old", add it immediately to the map |
| // and lists. Otherwise it will get added when NetworkServiceUpdate |
| // calls ParseNetwork. |
| NetworkMap::iterator found = old_network_map.find(service_path); |
| if (found != old_network_map.end()) { |
| AddNetwork(found->second); |
| old_network_map.erase(found); |
| } |
| // Always request network updates. |
| // TODO(stevenjb): Investigate why we are missing updates then |
| // rely on watched network updates and only request updates here for |
| // new networks. |
| // Use update_request map to store network priority. |
| network_update_requests_[service_path] = network_priority_order++; |
| VLOG(2) << "UpdateNetworkServiceList, Service: " << service_path; |
| CrosRequestNetworkServiceProperties( |
| service_path, |
| base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| |
| // Iterate through list of remaining networks that are no longer in the |
| // list and delete them or update their status and re-add them to the list. |
| for (NetworkMap::iterator iter = old_network_map.begin(); |
| iter != old_network_map.end(); ++iter) { |
| Network* network = iter->second; |
| VLOG(2) << "Delete Network: " << network->name() |
| << " State = " << network->GetStateString() |
| << " connecting = " << network->connecting() |
| << " connection_started = " << network->connection_started(); |
| WifiNetwork* wifi = NULL; |
| if (network->type() == TYPE_WIFI) |
| wifi = static_cast<WifiNetwork*>(network); |
| if (network->failed() && network->notify_failure()) { |
| // We have not notified observers of a connection failure yet. |
| AddNetwork(network); |
| } else if (network->connecting() && network->connection_started() && |
| !(wifi && wifi->hidden_ssid())) { |
| // Network was in connecting state; set state to failed, but not if it |
| // had a hidden SSID (since that won't appear in the scanning list). |
| VLOG(2) << "Removed network was connecting: " << network->name(); |
| network->SetState(STATE_FAILURE); |
| AddNetwork(network); |
| } else { |
| VLOG(2) << "Deleting removed network: " << network->name() |
| << " State = " << network->GetStateString(); |
| DeleteNetwork(network); |
| } |
| } |
| // If the last network has disappeared, nothing else will |
| // have notified observers, so do it now. |
| if (services->empty()) |
| NotifyNetworkManagerChanged(true); // Forced update |
| } |
| |
| // Request updates for watched networks. Does not affect network lists. |
| // Existing networks will be updated. There should not be any new networks |
| // in this list, but if there are they will be added appropriately. |
| void NetworkLibraryImplCros::UpdateWatchedNetworkServiceList( |
| const ListValue* services) { |
| for (ListValue::const_iterator iter = services->begin(); |
| iter != services->end(); ++iter) { |
| std::string service_path; |
| (*iter)->GetAsString(&service_path); |
| if (!service_path.empty()) { |
| VLOG(1) << "Watched Service: " << service_path; |
| CrosRequestNetworkServiceProperties( |
| service_path, |
| base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| } |
| |
| void NetworkLibraryImplCros::NetworkServiceUpdate( |
| const std::string& service_path, |
| const base::DictionaryValue* properties) { |
| if (!properties) |
| return; // Network no longer in visible list, ignore. |
| VLOG(2) << "NetworkServiceUpdate: " << service_path; |
| ParseNetwork(service_path, *properties); |
| } |
| |
| // Called from NetworkServiceUpdate and WifiServiceUpdateAndConnect. |
| Network* NetworkLibraryImplCros::ParseNetwork( |
| const std::string& service_path, const DictionaryValue& info) { |
| Network* network = FindNetworkByPath(service_path); |
| if (!network) { |
| NativeNetworkParser parser; |
| network = parser.CreateNetworkFromInfo(service_path, info); |
| AddNetwork(network); |
| } else { |
| // Erase entry from network_unique_id_map_ in case unique id changes. |
| if (!network->unique_id().empty()) |
| network_unique_id_map_.erase(network->unique_id()); |
| if (network->network_parser()) { |
| ConnectionState old_state = network->state(); |
| network->network_parser()->UpdateNetworkFromInfo(info, network); |
| if (old_state != network->state()) { |
| VLOG(1) << "ParseNetwork: " << network->name() |
| << " State: " << old_state << " -> " << network->state(); |
| } |
| } |
| } |
| |
| if (!network->unique_id().empty()) |
| network_unique_id_map_[network->unique_id()] = network; |
| |
| SetProfileTypeFromPath(network); |
| |
| UpdateActiveNetwork(network); |
| |
| // Copy remembered credentials if required. |
| Network* remembered = FindRememberedFromNetwork(network); |
| if (remembered) |
| network->CopyCredentialsFromRemembered(remembered); |
| |
| // Find and erase entry in update_requests, and set network priority. |
| PriorityMap::iterator found2 = network_update_requests_.find(service_path); |
| if (found2 != network_update_requests_.end()) { |
| network->priority_order_ = found2->second; |
| network_update_requests_.erase(found2); |
| } else { |
| // TODO(stevenjb): Enable warning once UpdateNetworkServiceList is fixed. |
| // LOG(WARNING) << "ParseNetwork called with no update request entry: " |
| // << service_path; |
| } |
| |
| VLOG(2) << "ParseNetwork: " << network->name() |
| << " path: " << network->service_path() |
| << " profile: " << network->profile_path_; |
| NotifyNetworkManagerChanged(false); // Not forced. |
| return network; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| |
| void NetworkLibraryImplCros::UpdateRememberedNetworks( |
| const ListValue* profiles) { |
| VLOG(1) << "UpdateRememberedNetworks"; |
| // Update the list of profiles. |
| NetworkProfileList old_profile_list; |
| old_profile_list.swap(profile_list_); |
| |
| for (ListValue::const_iterator iter = profiles->begin(); |
| iter != profiles->end(); ++iter) { |
| std::string profile_path; |
| (*iter)->GetAsString(&profile_path); |
| if (profile_path.empty()) { |
| LOG(WARNING) << "Bad or empty profile path."; |
| continue; |
| } |
| NetworkProfileType profile_type; |
| if (profile_path == kSharedProfilePath) |
| profile_type = PROFILE_SHARED; |
| else |
| profile_type = PROFILE_USER; |
| AddProfile(profile_path, profile_type); |
| } |
| bool lists_equal = old_profile_list.size() == profile_list_.size() && |
| std::equal(profile_list_.begin(), profile_list_.end(), |
| old_profile_list.begin(), AreProfilePathsEqual); |
| |
| RequestRememberedNetworksUpdate(); |
| if (!lists_equal) |
| NotifyNetworkProfileObservers(); |
| } |
| |
| void NetworkLibraryImplCros::RequestRememberedNetworksUpdate() { |
| VLOG(1) << "RequestRememberedNetworksUpdate"; |
| // Delete all remembered networks. We delete them because |
| // RequestNetworkProfileProperties is asynchronous and may invoke |
| // UpdateRememberedServiceList multiple times (once per profile). |
| // We can do this safely because we do not save any local state for |
| // remembered networks. This list updates infrequently. |
| DeleteRememberedNetworks(); |
| // Request remembered networks from each profile. Later entries will |
| // override earlier entries, so default/local entries will override |
| // user entries (as desired). |
| for (NetworkProfileList::iterator iter = profile_list_.begin(); |
| iter != profile_list_.end(); ++iter) { |
| NetworkProfile& profile = *iter; |
| VLOG(1) << " Requesting Profile: " << profile.path; |
| CrosRequestNetworkProfileProperties( |
| profile.path, |
| base::Bind(&NetworkLibraryImplCros::UpdateProfile, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| |
| void NetworkLibraryImplCros::UpdateProfile( |
| const std::string& profile_path, |
| const base::DictionaryValue* properties) { |
| if (!properties) { |
| LOG(ERROR) << "Error retrieving profile: " << profile_path; |
| return; |
| } |
| VLOG(1) << "UpdateProfile for path: " << profile_path; |
| const ListValue* profile_entries(NULL); |
| properties->GetList(flimflam::kEntriesProperty, &profile_entries); |
| if (!profile_entries) { |
| LOG(ERROR) << "'Entries' property is missing."; |
| return; |
| } |
| |
| NetworkProfileList::iterator iter1; |
| for (iter1 = profile_list_.begin(); iter1 != profile_list_.end(); ++iter1) { |
| if (iter1->path == profile_path) |
| break; |
| } |
| if (iter1 == profile_list_.end()) { |
| // This can happen if shill gets restarted while Chrome is running. |
| LOG(WARNING) << "Profile not in list: " << profile_path; |
| return; |
| } |
| NetworkProfile& profile = *iter1; |
| // |profile_entries| is a list of remembered networks from |profile_path|. |
| profile.services.clear(); |
| for (ListValue::const_iterator iter2 = profile_entries->begin(); |
| iter2 != profile_entries->end(); ++iter2) { |
| std::string service_path; |
| (*iter2)->GetAsString(&service_path); |
| if (service_path.empty()) { |
| LOG(WARNING) << "Empty service path in profile."; |
| continue; |
| } |
| VLOG(2) << " Remembered service: " << service_path; |
| // Add service to profile list. |
| profile.services.insert(service_path); |
| // Request update for remembered network. |
| // Shill does not set the Profile property for remembered networks, but only |
| // for the active networks, so we provide |profile_path| to the callback. |
| CrosRequestNetworkProfileEntryProperties( |
| profile_path, |
| service_path, |
| base::Bind(&NetworkLibraryImplCros::RememberedNetworkServiceUpdate, |
| weak_ptr_factory_.GetWeakPtr(), |
| profile_path)); |
| } |
| } |
| |
| void NetworkLibraryImplCros::RememberedNetworkServiceUpdate( |
| const std::string& profile_path, |
| const std::string& service_path, |
| const base::DictionaryValue* properties) { |
| VLOG(2) << "RememberedNetworkServiceUpdate: profile: " << profile_path |
| << " service: " << service_path |
| << (properties == NULL ? " got removed" : " got updated"); |
| if (properties) { |
| ParseRememberedNetwork(profile_path, service_path, *properties); |
| } else { |
| // Remove this service from the respective Profile::services list. |
| for (NetworkProfileList::iterator iter = profile_list_.begin(); |
| iter != profile_list_.end(); ++iter) { |
| NetworkProfile& profile = *iter; |
| if (profile.path != profile_path) |
| continue; |
| |
| if (profile.services.erase(service_path) != 0) { |
| VLOG(1) << "Removed service path: " << service_path |
| << " from Profile::services of: " << profile_path; |
| } |
| break; |
| } |
| } |
| } |
| |
| // Returns NULL if |service_path| refers to a network that is not a |
| // remembered type. Called from RememberedNetworkServiceUpdate. |
| Network* NetworkLibraryImplCros::ParseRememberedNetwork( |
| const std::string& profile_path, |
| const std::string& service_path, |
| const DictionaryValue& info) { |
| Network* remembered; |
| NetworkMap::iterator found = remembered_network_map_.find(service_path); |
| if (found != remembered_network_map_.end()) { |
| remembered = found->second; |
| if (remembered->network_parser()) |
| remembered->network_parser()->UpdateNetworkFromInfo(info, remembered); |
| } else { |
| NativeNetworkParser parser; |
| remembered = parser.CreateNetworkFromInfo(service_path, info); |
| if (remembered->type() == TYPE_WIFI || remembered->type() == TYPE_VPN) { |
| if (!ValidateAndAddRememberedNetwork(remembered)) |
| return NULL; |
| } else { |
| LOG(WARNING) << "Ignoring remembered network: " << service_path |
| << " Type: " << ConnectionTypeToString(remembered->type()); |
| delete remembered; |
| return NULL; |
| } |
| } |
| |
| remembered->set_profile_path(profile_path); |
| SetProfileTypeFromPath(remembered); |
| |
| VLOG(2) << "ParseRememberedNetwork: " << remembered->name() |
| << " path: " << remembered->service_path() |
| << " profile: " << remembered->profile_path_; |
| NotifyNetworkManagerChanged(false); // Not forced. |
| |
| if (remembered->type() == TYPE_VPN) { |
| // VPNs are only stored in profiles. If we don't have a network for it, |
| // request one. |
| if (!FindNetworkByUniqueId(remembered->unique_id())) { |
| VirtualNetwork* vpn = static_cast<VirtualNetwork*>(remembered); |
| std::string provider_type = ProviderTypeToString(vpn->provider_type()); |
| VLOG(2) << "Requesting VPN: " << vpn->name() |
| << " Server: " << vpn->server_hostname() |
| << " Type: " << provider_type; |
| CrosRequestVirtualNetworkProperties( |
| vpn->name(), |
| vpn->server_hostname(), |
| provider_type, |
| base::Bind(&NetworkLibraryImplCros::NetworkServiceUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| |
| return remembered; |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| // NetworkDevice list management functions. |
| |
| // Update device list, and request associated device updates. |
| // |devices| represents a complete list of devices. |
| void NetworkLibraryImplCros::UpdateNetworkDeviceList(const ListValue* devices) { |
| NetworkDeviceMap old_device_map = device_map_; |
| device_map_.clear(); |
| VLOG(2) << "Updating Device List."; |
| for (ListValue::const_iterator iter = devices->begin(); |
| iter != devices->end(); ++iter) { |
| std::string device_path; |
| (*iter)->GetAsString(&device_path); |
| if (!device_path.empty()) { |
| NetworkDeviceMap::iterator found = old_device_map.find(device_path); |
| if (found != old_device_map.end()) { |
| VLOG(2) << " Adding existing device: " << device_path; |
| CHECK(found->second) << "Attempted to add NULL device pointer"; |
| device_map_[device_path] = found->second; |
| old_device_map.erase(found); |
| } |
| CrosRequestNetworkDeviceProperties( |
| device_path, |
| base::Bind(&NetworkLibraryImplCros::NetworkDeviceUpdate, |
| weak_ptr_factory_.GetWeakPtr())); |
| } |
| } |
| // Delete any old devices that no longer exist. |
| for (NetworkDeviceMap::iterator iter = old_device_map.begin(); |
| iter != old_device_map.end(); ++iter) { |
| DeleteDeviceFromDeviceObserversMap(iter->first); |
| // Delete device. |
| delete iter->second; |
| } |
| } |
| |
| void NetworkLibraryImplCros::NetworkDeviceUpdate( |
| const std::string& device_path, |
| const base::DictionaryValue* properties) { |
| if (!properties) { |
| // device no longer exists. |
| DeleteDevice(device_path); |
| } else { |
| ParseNetworkDevice(device_path, *properties); |
| } |
| } |
| |
| void NetworkLibraryImplCros::ParseNetworkDevice(const std::string& device_path, |
| const DictionaryValue& info) { |
| NetworkDeviceMap::iterator found = device_map_.find(device_path); |
| NetworkDevice* device; |
| if (found != device_map_.end()) { |
| device = found->second; |
| device->device_parser()->UpdateDeviceFromInfo(info, device); |
| } else { |
| NativeNetworkDeviceParser parser; |
| device = parser.CreateDeviceFromInfo(device_path, info); |
| VLOG(2) << " Adding device: " << device_path; |
| if (device) { |
| device_map_[device_path] = device; |
| } |
| CHECK(device) << "Attempted to add NULL device for path: " << device_path; |
| } |
| VLOG(2) << "ParseNetworkDevice:" << device->name(); |
| |
| // Re-synchronize the roaming setting with the device property if required. |
| if (device && device->type() == TYPE_CELLULAR) |
| UpdateCellularDeviceStatus(device, PROPERTY_INDEX_CELLULAR_ALLOW_ROAMING); |
| |
| if (device && device->type() == TYPE_WIFI) |
| wifi_scanning_ = device->scanning(); |
| |
| NotifyNetworkManagerChanged(false); // Not forced. |
| AddNetworkDeviceObserver(device_path, network_device_observer_.get()); |
| } |
| |
| void NetworkLibraryImplCros::SetIPParametersCallback( |
| const IPParameterInfo& info, |
| const std::string& service_path, |
| const base::DictionaryValue* properties) { |
| // crbug.com/146616 will fix this once we have better |
| // handling of shill errors. |
| if (!properties) |
| return; |
| |
| Network* network = FindNetworkByPath(service_path); |
| if (!network) |
| return; |
| |
| // Find the properties we're going to set, and minimize the DBus calls below |
| // by not clearing if it's already cleared, and not setting if it's already |
| // set to the same value. Also, don't reconnect at the end if nothing changed. |
| bool something_changed = false; |
| std::string current_address; |
| int32 current_prefixlen = -1; |
| std::string current_gateway; |
| std::string current_name_servers; |
| bool address_exists = properties->GetStringWithoutPathExpansion( |
| shill::kStaticIPAddressProperty, |
| ¤t_address); |
| VLOG_IF(2, address_exists) << shill::kStaticIPAddressProperty |
| << "=" << current_address; |
| bool prefixlen_exists = properties->GetIntegerWithoutPathExpansion( |
| shill::kStaticIPPrefixlenProperty, |
| ¤t_prefixlen); |
| VLOG_IF(2, prefixlen_exists) << shill::kStaticIPPrefixlenProperty |
| << "=" << current_prefixlen; |
| bool gateway_exists = properties->GetStringWithoutPathExpansion( |
| shill::kStaticIPGatewayProperty, |
| ¤t_gateway); |
| VLOG_IF(2, gateway_exists) << shill::kStaticIPGatewayProperty |
| << "=" << current_gateway; |
| bool name_servers_exist = properties->GetStringWithoutPathExpansion( |
| shill::kStaticIPNameServersProperty, |
| ¤t_name_servers); |
| VLOG_IF(2, name_servers_exist) << shill::kStaticIPNameServersProperty |
| << "=" << current_name_servers; |
| |
| if (info.dhcp_usage_mask & USE_DHCP_ADDRESS) { |
| if (address_exists) { |
| something_changed = true; |
| CrosClearNetworkServiceProperty(service_path, |
| shill::kStaticIPAddressProperty); |
| VLOG(2) << "Clearing " << shill::kStaticIPAddressProperty; |
| } |
| } else if (current_address != info.address) { |
| base::StringValue value(info.address); |
| VLOG(2) << "Setting " << shill::kStaticIPAddressProperty |
| << " to " << info.address; |
| something_changed = true; |
| CrosSetNetworkServiceProperty(service_path, |
| shill::kStaticIPAddressProperty, |
| value); |
| } |
| |
| if (info.dhcp_usage_mask & USE_DHCP_NETMASK) { |
| if (prefixlen_exists) { |
| something_changed = true; |
| CrosClearNetworkServiceProperty(service_path, |
| shill::kStaticIPPrefixlenProperty); |
| VLOG(2) << "Clearing " << shill::kStaticIPPrefixlenProperty; |
| } |
| } else { |
| int prefixlen = network_util::NetmaskToPrefixLength(info.netmask); |
| if (prefixlen == -1) { |
| VLOG(1) << "IPConfig prefix length is invalid for netmask " |
| << info.netmask; |
| } else if (current_prefixlen != prefixlen) { |
| base::FundamentalValue value(prefixlen); |
| VLOG(2) << "Setting " << shill::kStaticIPPrefixlenProperty |
| << " to " << prefixlen; |
| something_changed = true; |
| CrosSetNetworkServiceProperty(service_path, |
| shill::kStaticIPPrefixlenProperty, |
| value); |
| } |
| } |
| |
| if (info.dhcp_usage_mask & USE_DHCP_GATEWAY) { |
| if (gateway_exists) { |
| something_changed = true; |
| CrosClearNetworkServiceProperty(service_path, |
| shill::kStaticIPGatewayProperty); |
| VLOG(2) << "Clearing " << shill::kStaticIPGatewayProperty; |
| } |
| } else if (current_gateway != info.gateway){ |
| base::StringValue value(info.gateway); |
| VLOG(2) << "Setting " << shill::kStaticIPGatewayProperty |
| << " to " << info.gateway; |
| something_changed = true; |
| CrosSetNetworkServiceProperty(service_path, |
| shill::kStaticIPGatewayProperty, |
| value); |
| } |
| |
| if (info.dhcp_usage_mask & USE_DHCP_NAME_SERVERS) { |
| if (name_servers_exist) { |
| something_changed = true; |
| CrosClearNetworkServiceProperty(service_path, |
| shill::kStaticIPNameServersProperty); |
| VLOG(2) << "Clearing " << shill::kStaticIPNameServersProperty; |
| |
| // Notify that the network changed, so that the DNS cache can be |
| // cleared properly. |
| NotifyNetworkChanged(network); |
| } |
| } else if (current_name_servers != info.name_servers){ |
| base::StringValue value(info.name_servers); |
| VLOG(2) << "Setting " << shill::kStaticIPNameServersProperty |
| << " to " << info.name_servers; |
| something_changed = true; |
| CrosSetNetworkServiceProperty(service_path, |
| shill::kStaticIPNameServersProperty, |
| value); |
| |
| // Notify that the network changed, so that the DNS cache can be |
| // cleared properly. |
| NotifyNetworkChanged(network); |
| } |
| |
| if (!something_changed) |
| return; |
| |
| // Ensure NetworkStateHandler properties are up-to-date. |
| if (NetworkHandler::IsInitialized()) { |
| NetworkHandler::Get()->network_state_handler()->RequestUpdateForNetwork( |
| service_path); |
| } |
| |
| // Attempt to refresh its IP parameters, so that the changes to the service |
| // properties can take effect. |
| if (network->connecting_or_connected()) |
| RefreshIPConfig(network); |
| } |
| |
| // static |
| bool NetworkLibraryImplCros::AreProfilePathsEqual(const NetworkProfile& a, |
| const NetworkProfile& b) { |
| return a.path == b.path; |
| } |
| |
| } // namespace chromeos |