Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(50)

Unified Diff: chromeos/network/network_configuration_handler.cc

Issue 708563005: Use setProperties for IP Config. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@issue_430113_internet_options_1
Patch Set: IPConfigType=Static applies to NameServer only config Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chromeos/network/network_configuration_handler.cc
diff --git a/chromeos/network/network_configuration_handler.cc b/chromeos/network/network_configuration_handler.cc
index 1ad09d80d046c05d4a67930f1b46324ac74da084..85a79c703d9ee69b37fd397bc887d552524e84db 100644
--- a/chromeos/network/network_configuration_handler.cc
+++ b/chromeos/network/network_configuration_handler.cc
@@ -20,6 +20,7 @@
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/network/network_device_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
@@ -34,8 +35,8 @@ namespace {
// Strip surrounding "" from keys (if present).
std::string StripQuotations(const std::string& in_str) {
size_t len = in_str.length();
- if (len >= 2 && in_str[0] == '"' && in_str[len-1] == '"')
- return in_str.substr(1, len-2);
+ if (len >= 2 && in_str[0] == '"' && in_str[len - 1] == '"')
+ return in_str.substr(1, len - 2);
return in_str;
}
@@ -44,8 +45,8 @@ void InvokeErrorCallback(const std::string& service_path,
const std::string& error_name) {
std::string error_msg = "Config Error: " + error_name;
NET_LOG_ERROR(error_msg, service_path);
- network_handler::RunErrorCallback(
- error_callback, service_path, error_name, error_msg);
+ network_handler::RunErrorCallback(error_callback, service_path, error_name,
+ error_msg);
}
void GetPropertiesCallback(
@@ -57,8 +58,7 @@ void GetPropertiesCallback(
if (call_status != DBUS_METHOD_CALL_SUCCESS) {
// Because network services are added and removed frequently, we will see
// failures regularly, so don't log these.
- network_handler::RunErrorCallback(error_callback,
- service_path,
+ network_handler::RunErrorCallback(error_callback, service_path,
network_handler::kDBusFailedError,
network_handler::kDBusFailedErrorMessage);
return;
@@ -82,23 +82,29 @@ void SetNetworkProfileErrorCallback(
const std::string& dbus_error_name,
const std::string& dbus_error_message) {
network_handler::ShillErrorCallbackFunction(
- "Config.SetNetworkProfile Failed: " + profile_path,
- service_path, error_callback,
- dbus_error_name, dbus_error_message);
+ "Config.SetNetworkProfile Failed: " + profile_path, service_path,
+ error_callback, dbus_error_name, dbus_error_message);
}
void LogConfigProperties(const std::string& desc,
const std::string& path,
const base::DictionaryValue& properties) {
- for (base::DictionaryValue::Iterator iter(properties);
- !iter.IsAtEnd(); iter.Advance()) {
+ for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
+ iter.Advance()) {
std::string v = "******";
if (!shill_property_util::IsPassphraseKey(iter.key()))
base::JSONWriter::Write(&iter.value(), &v);
- NET_LOG_DEBUG(desc, path + "." + iter.key() + "=" + v);
+ NET_LOG_DEBUG(desc, path + "." + iter.key() + "=" + v);
}
}
+bool PropertyRequiresIPConfigRefresh(const std::string& key) {
+ return key == shill::kStaticIPAddressProperty ||
+ key == shill::kStaticIPPrefixlenProperty ||
+ key == shill::kStaticIPGatewayProperty ||
+ key == shill::kStaticIPNameServersProperty;
+}
+
} // namespace
// Helper class to request from Shill the profile entries associated with a
@@ -119,12 +125,12 @@ class NetworkConfigurationHandler::ProfileEntryDeleter
guid_(guid),
source_(source),
callback_(callback),
- error_callback_(error_callback) {
- }
+ error_callback_(error_callback) {}
void Run() {
- DBusThreadManager::Get()->GetShillServiceClient()->
- GetLoadableProfileEntries(
+ DBusThreadManager::Get()
+ ->GetShillServiceClient()
+ ->GetLoadableProfileEntries(
dbus::ObjectPath(service_path_),
base::Bind(&ProfileEntryDeleter::GetProfileEntriesToDeleteCallback,
AsWeakPtr()));
@@ -135,46 +141,49 @@ class NetworkConfigurationHandler::ProfileEntryDeleter
DBusMethodCallStatus call_status,
const base::DictionaryValue& profile_entries) {
if (call_status != DBUS_METHOD_CALL_SUCCESS) {
- InvokeErrorCallback(
- service_path_, error_callback_, "GetLoadableProfileEntriesFailed");
+ InvokeErrorCallback(service_path_, error_callback_,
+ "GetLoadableProfileEntriesFailed");
// ProfileEntryDeleterCompleted will delete this.
owner_->ProfileEntryDeleterCompleted(service_path_, guid_, source_,
false /* failed */);
return;
}
- for (base::DictionaryValue::Iterator iter(profile_entries);
- !iter.IsAtEnd(); iter.Advance()) {
+ for (base::DictionaryValue::Iterator iter(profile_entries); !iter.IsAtEnd();
+ iter.Advance()) {
std::string profile_path = StripQuotations(iter.key());
std::string entry_path;
iter.value().GetAsString(&entry_path);
if (profile_path.empty() || entry_path.empty()) {
- NET_LOG_ERROR("Failed to parse Profile Entry", base::StringPrintf(
- "%s: %s", profile_path.c_str(), entry_path.c_str()));
+ NET_LOG_ERROR("Failed to parse Profile Entry",
+ base::StringPrintf("%s: %s", profile_path.c_str(),
+ entry_path.c_str()));
continue;
}
if (profile_delete_entries_.count(profile_path) != 0) {
- NET_LOG_ERROR("Multiple Profile Entries", base::StringPrintf(
- "%s: %s", profile_path.c_str(), entry_path.c_str()));
+ NET_LOG_ERROR("Multiple Profile Entries",
+ base::StringPrintf("%s: %s", profile_path.c_str(),
+ entry_path.c_str()));
continue;
}
- NET_LOG_DEBUG("Delete Profile Entry", base::StringPrintf(
- "%s: %s", profile_path.c_str(), entry_path.c_str()));
+ NET_LOG_DEBUG("Delete Profile Entry",
+ base::StringPrintf("%s: %s", profile_path.c_str(),
+ entry_path.c_str()));
profile_delete_entries_[profile_path] = entry_path;
DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
- dbus::ObjectPath(profile_path),
- entry_path,
+ dbus::ObjectPath(profile_path), entry_path,
base::Bind(&ProfileEntryDeleter::ProfileEntryDeletedCallback,
AsWeakPtr(), profile_path, entry_path),
- base::Bind(&ProfileEntryDeleter::ShillErrorCallback,
- AsWeakPtr(), profile_path, entry_path));
+ base::Bind(&ProfileEntryDeleter::ShillErrorCallback, AsWeakPtr(),
+ profile_path, entry_path));
}
}
void ProfileEntryDeletedCallback(const std::string& profile_path,
const std::string& entry) {
- NET_LOG_DEBUG("Profile Entry Deleted", base::StringPrintf(
- "%s: %s", profile_path.c_str(), entry.c_str()));
+ NET_LOG_DEBUG(
+ "Profile Entry Deleted",
+ base::StringPrintf("%s: %s", profile_path.c_str(), entry.c_str()));
profile_delete_entries_.erase(profile_path);
if (!profile_delete_entries_.empty())
return;
@@ -232,8 +241,8 @@ void NetworkConfigurationHandler::GetProperties(
NET_LOG_USER("GetProperties", service_path);
DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
dbus::ObjectPath(service_path),
- base::Bind(&GetPropertiesCallback,
- callback, error_callback, service_path));
+ base::Bind(&GetPropertiesCallback, callback, error_callback,
+ service_path));
}
void NetworkConfigurationHandler::SetProperties(
@@ -248,16 +257,48 @@ void NetworkConfigurationHandler::SetProperties(
return;
}
NET_LOG_USER("SetProperties", service_path);
- LogConfigProperties("SetProperty", service_path, properties);
+ // Copy |properties| to |properties_to_set| then iterate over |properties| and
+ // move any NULL properties to |properties_to_clear|, removing them from
+ // |properties_to_set|.
+ scoped_ptr<base::DictionaryValue> properties_to_set(properties.DeepCopy());
+ std::vector<std::string> properties_to_clear;
+ for (base::DictionaryValue::Iterator iter(properties); !iter.IsAtEnd();
+ iter.Advance()) {
+ const std::string& key = iter.key();
+ const base::Value& value = iter.value();
+ if (value.IsType(base::Value::TYPE_NULL)) {
+ properties_to_set->RemoveWithoutPathExpansion(key, nullptr);
+ properties_to_clear.push_back(key);
+ } else if (value.IsType(base::Value::TYPE_DICTIONARY)) {
pneubeck (no reviews) 2014/12/05 09:47:46 isn't this rather dangerous if you want to support
stevenjb 2015/01/08 00:44:39 Removed (for now at least) since we are using empt
+ // Also clear empty dictionaries.
+ const base::DictionaryValue* dictionary;
+ if (!value.GetAsDictionary(&dictionary) || dictionary->empty()) {
pneubeck (no reviews) 2014/12/05 09:47:46 this check for !GetAsDictionary after IsType(Dicti
stevenjb 2015/01/08 00:44:39 Acknowledged.
+ properties_to_set->RemoveWithoutPathExpansion(key, nullptr);
+ properties_to_clear.push_back(key);
+ }
+ }
+ }
+
+ // Copy input properties to pass to observers on completion.
scoped_ptr<base::DictionaryValue> properties_copy(properties.DeepCopy());
- DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
- dbus::ObjectPath(service_path), properties,
- base::Bind(&NetworkConfigurationHandler::SetPropertiesSuccessCallback,
- AsWeakPtr(), service_path, base::Passed(&properties_copy),
- source, callback),
- base::Bind(&NetworkConfigurationHandler::SetPropertiesErrorCallback,
- AsWeakPtr(), service_path, error_callback));
+
+ if (!properties_to_clear.empty()) {
+ // ClearProperties chains a Shill GetProperties request followed by a Shill
+ // ClearProperties request, so wait for those to complete before setting any
+ // properties.
+ ClearProperties(
pneubeck (no reviews) 2014/12/05 09:47:46 is this behavior covered in NCH unit tests already
stevenjb 2015/01/08 00:44:39 Removed for now.
+ service_path, properties_to_clear,
+ base::Bind(&NetworkConfigurationHandler::SendSetPropertiesToShill,
+ AsWeakPtr(), service_path, base::Passed(&properties_copy),
+ base::Passed(&properties_to_set), source, callback,
+ error_callback),
+ error_callback);
+ } else {
+ SendSetPropertiesToShill(service_path, properties_copy.Pass(),
+ properties_to_set.Pass(), source, callback,
+ error_callback);
+ }
}
void NetworkConfigurationHandler::ClearProperties(
@@ -271,17 +312,12 @@ void NetworkConfigurationHandler::ClearProperties(
return;
}
NET_LOG_USER("ClearProperties", service_path);
- for (std::vector<std::string>::const_iterator iter = names.begin();
- iter != names.end(); ++iter) {
- NET_LOG_DEBUG("ClearProperty", service_path + "." + *iter);
- }
- DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties(
+ // Shill triggers an error if we clear properties that are unset, so
+ // first get the current properties.
+ DBusThreadManager::Get()->GetShillServiceClient()->GetProperties(
dbus::ObjectPath(service_path),
- names,
- base::Bind(&NetworkConfigurationHandler::ClearPropertiesSuccessCallback,
- AsWeakPtr(), service_path, names, callback),
- base::Bind(&NetworkConfigurationHandler::ClearPropertiesErrorCallback,
- AsWeakPtr(), service_path, error_callback));
+ base::Bind(&NetworkConfigurationHandler::ClearPropertiesGetCallback,
+ AsWeakPtr(), service_path, names, callback, error_callback));
}
void NetworkConfigurationHandler::CreateConfiguration(
@@ -297,8 +333,7 @@ void NetworkConfigurationHandler::CreateConfiguration(
if (NetworkTypePattern::Ethernet().MatchesType(type)) {
InvokeErrorCallback(
shill_property_util::GetNetworkIdFromProperties(properties),
- error_callback,
- "ConfigureServiceForProfile: Invalid type: " + type);
+ error_callback, "ConfigureServiceForProfile: Invalid type: " + type);
return;
}
@@ -328,8 +363,8 @@ void NetworkConfigurationHandler::RemoveConfiguration(
// Service.Remove is not reliable. Instead, request the profile entries
// for the service and remove each entry.
if (ContainsKey(profile_entry_deleters_, service_path)) {
- InvokeErrorCallback(
- service_path, error_callback, "RemoveConfigurationInProgress");
+ InvokeErrorCallback(service_path, error_callback,
+ "RemoveConfigurationInProgress");
return;
}
@@ -369,13 +404,15 @@ NetworkConfigurationHandler::NetworkConfigurationHandler()
}
NetworkConfigurationHandler::~NetworkConfigurationHandler() {
- STLDeleteContainerPairSecondPointers(
- profile_entry_deleters_.begin(), profile_entry_deleters_.end());
+ STLDeleteContainerPairSecondPointers(profile_entry_deleters_.begin(),
+ profile_entry_deleters_.end());
}
void NetworkConfigurationHandler::Init(
- NetworkStateHandler* network_state_handler) {
+ NetworkStateHandler* network_state_handler,
+ NetworkDeviceHandler* network_device_handler) {
network_state_handler_ = network_state_handler;
+ network_device_handler_ = network_device_handler;
}
void NetworkConfigurationHandler::RunCreateNetworkCallback(
@@ -424,9 +461,44 @@ void NetworkConfigurationHandler::SetNetworkProfileCompleted(
OnConfigurationProfileChanged(service_path, profile_path, source));
}
+void NetworkConfigurationHandler::SendSetPropertiesToShill(
+ const std::string& service_path,
+ scoped_ptr<base::DictionaryValue> changed_properties,
+ scoped_ptr<base::DictionaryValue> properties_to_set,
+ NetworkConfigurationObserver::Source source,
+ const base::Closure& callback,
+ const network_handler::ErrorCallback& error_callback) {
+ if (properties_to_set->empty()) {
+ SetPropertiesSuccessCallback(service_path, changed_properties.Pass(),
+ source, callback);
+ return;
+ }
+
+ LogConfigProperties("SetProperty", service_path, *properties_to_set);
+ DBusThreadManager::Get()->GetShillServiceClient()->SetProperties(
+ dbus::ObjectPath(service_path), *properties_to_set,
+ base::Bind(&NetworkConfigurationHandler::SetPropertiesSuccessCallback,
+ AsWeakPtr(), service_path, base::Passed(&changed_properties),
+ source, callback),
+ base::Bind(&NetworkConfigurationHandler::SetPropertiesErrorCallback,
+ AsWeakPtr(), service_path, error_callback));
+
+ // If we set any properties that might affect IP config, request an IP config
+ // refresh after calling SetProperties. Note: it is possible (but unlikely and
+ // harmless) for both Set and Clear to trigger an IP Config refresh.
+ for (base::DictionaryValue::Iterator iter(*properties_to_set);
+ !iter.IsAtEnd(); iter.Advance()) {
+ const std::string& key = iter.key();
+ if (PropertyRequiresIPConfigRefresh(key)) {
+ RequestRefreshIPConfigs(service_path);
+ break;
+ }
+ }
+}
+
void NetworkConfigurationHandler::SetPropertiesSuccessCallback(
const std::string& service_path,
- scoped_ptr<base::DictionaryValue> set_properties,
+ scoped_ptr<base::DictionaryValue> changed_properties,
NetworkConfigurationObserver::Source source,
const base::Closure& callback) {
if (!callback.is_null())
@@ -438,7 +510,7 @@ void NetworkConfigurationHandler::SetPropertiesSuccessCallback(
FOR_EACH_OBSERVER(NetworkConfigurationObserver, observers_,
OnPropertiesSet(service_path, network_state->guid(),
- *set_properties, source));
+ *changed_properties, source));
network_state_handler_->RequestUpdateForNetwork(service_path);
}
@@ -448,21 +520,62 @@ void NetworkConfigurationHandler::SetPropertiesErrorCallback(
const std::string& dbus_error_name,
const std::string& dbus_error_message) {
network_handler::ShillErrorCallbackFunction(
- "Config.SetProperties Failed",
- service_path, error_callback,
+ "Config.SetProperties Failed", service_path, error_callback,
dbus_error_name, dbus_error_message);
// Some properties may have changed so request an update regardless.
network_state_handler_->RequestUpdateForNetwork(service_path);
}
+void NetworkConfigurationHandler::ClearPropertiesGetCallback(
+ const std::string& service_path,
+ const std::vector<std::string>& names,
+ const base::Closure& callback,
+ const network_handler::ErrorCallback& error_callback,
+ DBusMethodCallStatus call_status,
+ const base::DictionaryValue& properties) {
+ if (call_status != DBUS_METHOD_CALL_SUCCESS) {
+ network_handler::RunErrorCallback(error_callback, service_path,
+ network_handler::kDBusFailedError,
+ network_handler::kDBusFailedErrorMessage);
+ return;
+ }
+
+ // Clear only properties that are currently set. Also trigger an IP Configs
+ // refresh if necessary (see note in SendSetPropertiesToShill).
+ std::vector<std::string> properties_to_clear;
+ bool refresh_ip_configs = false;
+ for (const auto& key : names) {
+ if (properties.HasKey(key)) {
+ NET_LOG_DEBUG("ClearProperty", service_path + "." + key);
+ properties_to_clear.push_back(key);
+ if (PropertyRequiresIPConfigRefresh(key))
+ refresh_ip_configs = true;
+ } else {
+ NET_LOG_DEBUG("ClearProperty:Unset (Ignoring)", service_path + "." + key);
+ }
+ }
+
+ DBusThreadManager::Get()->GetShillServiceClient()->ClearProperties(
+ dbus::ObjectPath(service_path), properties_to_clear,
+ base::Bind(&NetworkConfigurationHandler::ClearPropertiesSuccessCallback,
+ AsWeakPtr(), service_path, properties_to_clear, callback),
+ base::Bind(&NetworkConfigurationHandler::ClearPropertiesErrorCallback,
+ AsWeakPtr(), service_path, error_callback));
+
+ // If we cleared any properties that might affect IP config, request an IP
+ // config refresh after calling ClearProperties.
+ if (refresh_ip_configs)
+ RequestRefreshIPConfigs(service_path);
+}
+
void NetworkConfigurationHandler::ClearPropertiesSuccessCallback(
const std::string& service_path,
const std::vector<std::string>& names,
const base::Closure& callback,
const base::ListValue& result) {
const std::string kClearPropertiesFailedError("Error.ClearPropertiesFailed");
- DCHECK(names.size() == result.GetSize())
- << "Incorrect result size from ClearProperties.";
+ if (names.size() != result.GetSize())
+ NET_LOG_ERROR("ClearProperties Result size != input", service_path);
for (size_t i = 0; i < result.GetSize(); ++i) {
bool success = false;
@@ -485,18 +598,31 @@ void NetworkConfigurationHandler::ClearPropertiesErrorCallback(
const std::string& dbus_error_name,
const std::string& dbus_error_message) {
network_handler::ShillErrorCallbackFunction(
- "Config.ClearProperties Failed",
- service_path, error_callback,
+ "Config.ClearProperties Failed", service_path, error_callback,
dbus_error_name, dbus_error_message);
// Some properties may have changed so request an update regardless.
network_state_handler_->RequestUpdateForNetwork(service_path);
}
+void NetworkConfigurationHandler::RequestRefreshIPConfigs(
+ const std::string& service_path) {
+ if (!network_device_handler_)
+ return;
+ const NetworkState* network_state =
+ network_state_handler_->GetNetworkState(service_path);
+ if (!network_state || network_state->device_path().empty())
+ return;
+ network_device_handler_->RequestRefreshIPConfigs(
+ network_state->device_path(), base::Bind(&base::DoNothing),
+ network_handler::ErrorCallback());
+}
+
// static
NetworkConfigurationHandler* NetworkConfigurationHandler::InitializeForTest(
- NetworkStateHandler* network_state_handler) {
+ NetworkStateHandler* network_state_handler,
+ NetworkDeviceHandler* network_device_handler) {
NetworkConfigurationHandler* handler = new NetworkConfigurationHandler();
- handler->Init(network_state_handler);
+ handler->Init(network_state_handler, network_device_handler);
return handler;
}

Powered by Google App Engine
This is Rietveld 408576698