summaryrefslogtreecommitdiffstats
path: root/chromeos/network
diff options
context:
space:
mode:
authorpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-07 21:08:13 +0000
committerpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-05-07 21:08:13 +0000
commit38c960262439b3618bf1169fd50a3cd768cadc32 (patch)
treeee3a28e95b2eaafc93d38983163f254e659872d3 /chromeos/network
parentba203410be684238da645b7f8be15ae2541dba04 (diff)
downloadchromium_src-38c960262439b3618bf1169fd50a3cd768cadc32.zip
chromium_src-38c960262439b3618bf1169fd50a3cd768cadc32.tar.gz
chromium_src-38c960262439b3618bf1169fd50a3cd768cadc32.tar.bz2
Adding a NetworkProfileHandler used by ManagedNetworkConfigurationHandler.
This handler tracks Shill's profiles. Currently only the ManagedNetworkConfigurationHandler is making use of this handler but it is also required for upcoming changes to proxy handling in ChromeOS. In the ONC validator only an LOG(ERROR) was fixed to LOG(WARNING) if the flag error_on_missing_field=false. BUG=157696 TEST=managed_network_configuration_handler_unittest.cc, networking_private_apitest.cc Review URL: https://chromiumcodereview.appspot.com/13957012 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@198798 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chromeos/network')
-rw-r--r--chromeos/network/managed_network_configuration_handler.cc363
-rw-r--r--chromeos/network/managed_network_configuration_handler.h50
-rw-r--r--chromeos/network/managed_network_configuration_handler_unittest.cc255
-rw-r--r--chromeos/network/network_profile.cc26
-rw-r--r--chromeos/network/network_profile.h38
-rw-r--r--chromeos/network/network_profile_handler.cc233
-rw-r--r--chromeos/network/network_profile_handler.h88
-rw-r--r--chromeos/network/network_profile_handler_stub.h22
-rw-r--r--chromeos/network/network_profile_observer.h30
-rw-r--r--chromeos/network/onc/onc_validator.cc55
-rw-r--r--chromeos/network/onc/onc_validator.h4
11 files changed, 904 insertions, 260 deletions
diff --git a/chromeos/network/managed_network_configuration_handler.cc b/chromeos/network/managed_network_configuration_handler.cc
index a7e7d62..ea772f6 100644
--- a/chromeos/network/managed_network_configuration_handler.cc
+++ b/chromeos/network/managed_network_configuration_handler.cc
@@ -15,6 +15,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
+#include "base/string_util.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_method_call_status.h"
#include "chromeos/dbus/dbus_thread_manager.h"
@@ -24,6 +25,8 @@
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_profile.h"
+#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_ui_data.h"
@@ -40,8 +43,6 @@ namespace chromeos {
namespace {
-ManagedNetworkConfigurationHandler* g_configuration_handler_instance = NULL;
-
const char kLogModule[] = "ManagedNetworkConfigurationHandler";
// These are error strings used for error callbacks. None of these error
@@ -53,28 +54,26 @@ const char kNetworkAlreadyConfiguredMessage[] =
const char kNetworkAlreadyConfigured[] = "Error.NetworkAlreadyConfigured";
const char kPoliciesNotInitializedMessage[] = "Policies not initialized.";
const char kPoliciesNotInitialized[] = "Error.PoliciesNotInitialized";
-const char kServicePath[] = "servicePath";
+const char kProfileNotInitializedMessage[] = "Profile not initialized.";
+const char kProfileNotInitialized[] = "Error.ProflieNotInitialized";
const char kSetOnUnconfiguredNetworkMessage[] =
"Unable to modify properties of an unconfigured network.";
const char kSetOnUnconfiguredNetwork[] = "Error.SetCalledOnUnconfiguredNetwork";
-const char kUIDataErrorMessage[] = "UI data contains errors.";
-const char kUIDataError[] = "Error.UIData";
+const char kUnknownProfilePathMessage[] = "Profile path is unknown.";
+const char kUnknownProfilePath[] = "Error.UnknownProfilePath";
const char kUnknownServicePathMessage[] = "Service path is unknown.";
const char kUnknownServicePath[] = "Error.UnknownServicePath";
-enum ProfileType {
- PROFILE_NONE, // Not in any profile.
- PROFILE_SHARED, // In the shared profile, shared by all users on device.
- PROFILE_USER // In the user profile, not visible to other users.
-};
-
-const char kSharedProfilePath[] = "/profile/default";
-const char kUserProfilePath[] = "/profile/chronos/shill";
-
// This fake credential contains a random postfix which is extremly unlikely to
// be used by any user.
const char kFakeCredential[] = "FAKE_CREDENTIAL_VPaJDV9x";
+std::string ToDebugString(onc::ONCSource source,
+ const std::string& userhash) {
+ return source == onc::ONC_SOURCE_USER_POLICY ?
+ ("user policy of " + userhash) : "device policy";
+}
+
void RunErrorCallback(const std::string& service_path,
const std::string& error_name,
const std::string& error_message,
@@ -182,28 +181,29 @@ void RemoveFakeCredentials(
// path, |policy| is interpreted as the user or device policy and |settings| as
// the user or shared settings.
scoped_ptr<base::DictionaryValue> CreateShillConfiguration(
- const std::string& profile_path,
+ const NetworkProfile& profile,
const std::string& guid,
const base::DictionaryValue* policy,
const base::DictionaryValue* settings) {
scoped_ptr<base::DictionaryValue> effective;
-
onc::ONCSource onc_source;
if (policy) {
- if (profile_path == kSharedProfilePath) {
+ if (profile.type() == NetworkProfile::TYPE_SHARED) {
effective = onc::MergeSettingsAndPoliciesToEffective(
NULL, // no user policy
policy, // device policy
NULL, // no user settings
settings); // shared settings
onc_source = onc::ONC_SOURCE_DEVICE_POLICY;
- } else {
+ } else if (profile.type() == NetworkProfile::TYPE_USER) {
effective = onc::MergeSettingsAndPoliciesToEffective(
policy, // user policy
NULL, // no device policy
settings, // user settings
NULL); // no shared settings
onc_source = onc::ONC_SOURCE_USER_POLICY;
+ } else {
+ NOTREACHED();
}
} else if (settings) {
effective.reset(settings->DeepCopy());
@@ -224,7 +224,7 @@ scoped_ptr<base::DictionaryValue> CreateShillConfiguration(
*effective));
shill_dictionary->SetStringWithoutPathExpansion(flimflam::kProfileProperty,
- profile_path);
+ profile.path);
scoped_ptr<NetworkUIData> ui_data;
if (policy)
@@ -283,9 +283,9 @@ bool IsPolicyMatching(const base::DictionaryValue& policy,
// Returns the policy of |policies| matching |onc_network_part|, if any
// exists. Returns NULL otherwise.
const base::DictionaryValue* FindMatchingPolicy(
- const ManagedNetworkConfigurationHandler::PolicyMap &policies,
+ const ManagedNetworkConfigurationHandler::GuidToPolicyMap &policies,
const base::DictionaryValue& onc_network_part) {
- for (ManagedNetworkConfigurationHandler::PolicyMap::const_iterator it =
+ for (ManagedNetworkConfigurationHandler::GuidToPolicyMap::const_iterator it =
policies.begin(); it != policies.end(); ++it) {
if (IsPolicyMatching(*it->second, onc_network_part))
return it->second;
@@ -293,6 +293,16 @@ const base::DictionaryValue* FindMatchingPolicy(
return NULL;
}
+const base::DictionaryValue* GetByGUID(
+ const ManagedNetworkConfigurationHandler::GuidToPolicyMap &policies,
+ const std::string& guid) {
+ ManagedNetworkConfigurationHandler::GuidToPolicyMap::const_iterator it =
+ policies.find(guid);
+ if (it == policies.end())
+ return NULL;
+ return it->second;
+}
+
void TranslatePropertiesToOncAndRunCallback(
const network_handler::DictionaryResultCallback& callback,
const std::string& service_path,
@@ -306,10 +316,15 @@ void TranslatePropertiesToOncAndRunCallback(
} // namespace
+static ManagedNetworkConfigurationHandler*
+g_configuration_handler_instance = NULL;
+
// static
-void ManagedNetworkConfigurationHandler::Initialize() {
+void ManagedNetworkConfigurationHandler::Initialize(
+ NetworkProfileHandler* profile_handler) {
CHECK(!g_configuration_handler_instance);
- g_configuration_handler_instance = new ManagedNetworkConfigurationHandler;
+ g_configuration_handler_instance =
+ new ManagedNetworkConfigurationHandler(profile_handler);
}
// static
@@ -331,10 +346,11 @@ ManagedNetworkConfigurationHandler* ManagedNetworkConfigurationHandler::Get() {
}
void ManagedNetworkConfigurationHandler::GetManagedProperties(
+ const std::string& userhash,
const std::string& service_path,
const network_handler::DictionaryResultCallback& callback,
const network_handler::ErrorCallback& error_callback) {
- if (!user_policies_initialized_ || !device_policies_initialized_) {
+ if (!GetPoliciesForUser(userhash) || !GetPoliciesForUser(std::string())) {
RunErrorCallback(service_path,
kPoliciesNotInitialized,
kPoliciesNotInitializedMessage,
@@ -357,15 +373,13 @@ void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback(
const std::string& service_path,
const base::DictionaryValue& shill_properties) {
std::string profile_path;
- ProfileType profile_type = PROFILE_NONE;
- if (shill_properties.GetStringWithoutPathExpansion(
- flimflam::kProfileProperty, &profile_path)) {
- if (profile_path == kSharedProfilePath)
- profile_type = PROFILE_SHARED;
- else if (!profile_path.empty())
- profile_type = PROFILE_USER;
- } else {
- VLOG(1) << "No profile path for service " << service_path << ".";
+ shill_properties.GetStringWithoutPathExpansion(flimflam::kProfileProperty,
+ &profile_path);
+ const NetworkProfile* profile =
+ profile_handler_->GetProfileForPath(profile_path);
+ if (!profile) {
+ VLOG(1) << "No or no known profile received for service "
+ << service_path << ".";
}
scoped_ptr<NetworkUIData> ui_data = GetUIData(shill_properties);
@@ -373,12 +387,14 @@ void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback(
const base::DictionaryValue* user_settings = NULL;
const base::DictionaryValue* shared_settings = NULL;
- if (ui_data) {
- if (profile_type == PROFILE_SHARED)
+ if (ui_data && profile) {
+ if (profile->type() == NetworkProfile::TYPE_SHARED)
shared_settings = ui_data->user_settings();
- else if (profile_type == PROFILE_USER)
+ else if (profile->type() == NetworkProfile::TYPE_USER)
user_settings = ui_data->user_settings();
- } else if (profile_type != PROFILE_NONE) {
+ else
+ NOTREACHED();
+ } else if (profile) {
LOG(WARNING) << "Service " << service_path << " of profile "
<< profile_path << " contains no or no valid UIData.";
// TODO(pneubeck): add a conversion of user configured entries of old
@@ -397,13 +413,22 @@ void ManagedNetworkConfigurationHandler::GetManagedPropertiesCallback(
const base::DictionaryValue* user_policy = NULL;
const base::DictionaryValue* device_policy = NULL;
- if (!guid.empty()) {
- // We already checked that the policies were initialized. No need to do that
- // again.
- if (profile_type == PROFILE_SHARED)
- device_policy = device_policies_by_guid_[guid];
- else if (profile_type == PROFILE_USER)
- user_policy = user_policies_by_guid_[guid];
+ if (!guid.empty() && profile) {
+ const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
+ if (!policies) {
+ RunErrorCallback(service_path,
+ kPoliciesNotInitialized,
+ kPoliciesNotInitializedMessage,
+ error_callback);
+ return;
+ }
+ const base::DictionaryValue* policy = GetByGUID(*policies, guid);
+ if (profile->type() == NetworkProfile::TYPE_SHARED)
+ device_policy = policy;
+ else if (profile->type() == NetworkProfile::TYPE_USER)
+ user_policy = policy;
+ else
+ NOTREACHED();
}
// This call also removes credentials from policies.
@@ -456,6 +481,29 @@ void ManagedNetworkConfigurationHandler::SetProperties(
return;
}
+ const std::string& profile_path = state->profile_path();
+ const NetworkProfile *profile =
+ profile_handler_->GetProfileForPath(profile_path);
+ if (!profile) {
+ RunErrorCallback(service_path,
+ kUnknownProfilePath,
+ kUnknownProfilePathMessage,
+ error_callback);
+ return;
+ }
+
+ VLOG(2) << "SetProperties: Found GUID " << guid << " and profile "
+ << profile->ToDebugString();
+
+ const GuidToPolicyMap* policies = GetPoliciesForProfile(*profile);
+ if (!policies) {
+ RunErrorCallback(service_path,
+ kPoliciesNotInitialized,
+ kPoliciesNotInitializedMessage,
+ error_callback);
+ return;
+ }
+
// Validate the ONC dictionary. We are liberal and ignore unknown field
// names. User settings are only partial ONC, thus we ignore missing fields.
onc::Validator validator(false, // Ignore unknown fields.
@@ -471,7 +519,6 @@ void ManagedNetworkConfigurationHandler::SetProperties(
&validation_result);
if (validation_result == onc::Validator::INVALID) {
- LOG(ERROR) << "ONC user settings are invalid and couldn't be repaired.";
RunErrorCallback(service_path,
kInvalidUserSettings,
kInvalidUserSettingsMessage,
@@ -481,30 +528,11 @@ void ManagedNetworkConfigurationHandler::SetProperties(
if (validation_result == onc::Validator::VALID_WITH_WARNINGS)
LOG(WARNING) << "Validation of ONC user settings produced warnings.";
- VLOG(2) << "SetProperties: Found GUID " << guid << " and profile "
- << state->profile_path();
-
- const PolicyMap* policies_by_guid =
- GetPoliciesForProfile(state->profile_path());
-
- if (!policies_by_guid) {
- RunErrorCallback(service_path,
- kPoliciesNotInitialized,
- kPoliciesNotInitializedMessage,
- error_callback);
- return;
- }
-
- const base::DictionaryValue* policy = NULL;
- PolicyMap::const_iterator it = policies_by_guid->find(guid);
- if (it != policies_by_guid->end())
- policy = it->second;
-
+ const base::DictionaryValue* policy = GetByGUID(*policies, guid);
VLOG(2) << "This configuration is " << (policy ? "" : "not ") << "managed.";
scoped_ptr<base::DictionaryValue> shill_dictionary(
- CreateShillConfiguration(state->profile_path(), guid, policy,
- &user_settings));
+ CreateShillConfiguration(*profile, guid, policy, &user_settings));
NetworkConfigurationHandler::Get()->SetProperties(service_path,
*shill_dictionary,
@@ -531,13 +559,12 @@ void ManagedNetworkConfigurationHandler::Disconnect(
}
void ManagedNetworkConfigurationHandler::CreateConfiguration(
+ const std::string& userhash,
const base::DictionaryValue& properties,
const network_handler::StringResultCallback& callback,
const network_handler::ErrorCallback& error_callback) const {
- std::string profile_path = kUserProfilePath;
- const PolicyMap* policies_by_guid = GetPoliciesForProfile(profile_path);
-
- if (!policies_by_guid) {
+ const GuidToPolicyMap* policies = GetPoliciesForUser(userhash);
+ if (!policies) {
RunErrorCallback("",
kPoliciesNotInitialized,
kPoliciesNotInitializedMessage,
@@ -545,13 +572,22 @@ void ManagedNetworkConfigurationHandler::CreateConfiguration(
return;
}
- if (FindMatchingPolicy(*policies_by_guid, properties)) {
+ if (FindMatchingPolicy(*policies, properties)) {
RunErrorCallback("",
kNetworkAlreadyConfigured,
kNetworkAlreadyConfiguredMessage,
error_callback);
}
+ const NetworkProfile* profile =
+ profile_handler_->GetProfileForUserhash(userhash);
+ if (!profile) {
+ RunErrorCallback("",
+ kProfileNotInitialized,
+ kProfileNotInitializedMessage,
+ error_callback);
+ }
+
// TODO(pneubeck): In case of WiFi, check that no other configuration for the
// same {SSID, mode, security} exists. We don't support such multiple
// configurations, yet.
@@ -559,9 +595,8 @@ void ManagedNetworkConfigurationHandler::CreateConfiguration(
// Generate a new GUID for this configuration. Ignore the maybe provided GUID
// in |properties| as it is not our own and from an untrusted source.
std::string guid = base::GenerateGUID();
-
scoped_ptr<base::DictionaryValue> shill_dictionary(
- CreateShillConfiguration(profile_path, guid, NULL /*no policy*/,
+ CreateShillConfiguration(*profile, guid, NULL /*no policy*/,
&properties));
NetworkConfigurationHandler::Get()->CreateConfiguration(*shill_dictionary,
@@ -586,20 +621,20 @@ void ManagedNetworkConfigurationHandler::RemoveConfiguration(
class ManagedNetworkConfigurationHandler::PolicyApplicator
: public base::RefCounted<PolicyApplicator> {
public:
- typedef ManagedNetworkConfigurationHandler::PolicyMap PolicyMap;
+ typedef ManagedNetworkConfigurationHandler::GuidToPolicyMap GuidToPolicyMap;
// |modified_policies| must not be NULL and will be empty afterwards.
PolicyApplicator(base::WeakPtr<ManagedNetworkConfigurationHandler> handler,
- const std::string& profile,
+ const NetworkProfile& profile,
std::set<std::string>* modified_policies)
: handler_(handler),
- profile_path_(profile) {
+ profile_(profile) {
remaining_policies_.swap(*modified_policies);
}
void Run() {
DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
- dbus::ObjectPath(profile_path_),
+ dbus::ObjectPath(profile_.path),
base::Bind(&PolicyApplicator::GetProfileProperties, this),
base::Bind(&LogErrorMessage, FROM_HERE));
}
@@ -610,15 +645,15 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
void GetProfileProperties(const base::DictionaryValue& profile_properties) {
if (!handler_) {
LOG(WARNING) << "Handler destructed during policy application to profile "
- << profile_path_;
+ << profile_.ToDebugString();
return;
}
- VLOG(2) << "Received properties for profile " << profile_path_;
+ VLOG(2) << "Received properties for profile " << profile_.ToDebugString();
const base::ListValue* entries = NULL;
if (!profile_properties.GetListWithoutPathExpansion(
flimflam::kEntriesProperty, &entries)) {
- LOG(ERROR) << "Profile " << profile_path_
+ LOG(ERROR) << "Profile " << profile_.ToDebugString()
<< " doesn't contain the property "
<< flimflam::kEntriesProperty;
return;
@@ -631,10 +666,10 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
std::ostringstream entry_failure;
DBusThreadManager::Get()->GetShillProfileClient()->GetEntry(
- dbus::ObjectPath(profile_path_),
- entry,
- base::Bind(&PolicyApplicator::GetEntry, this, entry),
- base::Bind(&LogErrorMessage, FROM_HERE));
+ dbus::ObjectPath(profile_.path),
+ entry,
+ base::Bind(&PolicyApplicator::GetEntry, this, entry),
+ base::Bind(&LogErrorMessage, FROM_HERE));
}
}
@@ -642,12 +677,12 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
const base::DictionaryValue& entry_properties) {
if (!handler_) {
LOG(WARNING) << "Handler destructed during policy application to profile "
- << profile_path_;
+ << profile_.ToDebugString();
return;
}
VLOG(2) << "Received properties for entry " << entry << " of profile "
- << profile_path_;
+ << profile_.ToDebugString();
scoped_ptr<base::DictionaryValue> onc_part(
onc::TranslateShillServiceToONCPart(
@@ -657,8 +692,8 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
std::string old_guid;
if (!onc_part->GetStringWithoutPathExpansion(onc::network_config::kGUID,
&old_guid)) {
- LOG(WARNING) << "Entry " << entry << " of profile " << profile_path_
- << " doesn't contain a GUID.";
+ LOG(WARNING) << "Entry " << entry << " of profile "
+ << profile_.ToDebugString() << " doesn't contain a GUID.";
// This might be an entry of an older ChromeOS version. Assume it to be
// unmanaged.
return;
@@ -666,7 +701,8 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
scoped_ptr<NetworkUIData> ui_data = GetUIData(entry_properties);
if (!ui_data) {
- VLOG(1) << "Entry " << entry << " of profile " << profile_path_
+ VLOG(1) << "Entry " << entry << " of profile "
+ << profile_.ToDebugString()
<< " contains no or no valid UIData.";
// This might be an entry of an older ChromeOS version. Assume it to be
// unmanaged.
@@ -679,22 +715,20 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
// The relevant policy must have been initialized, otherwise we hadn't Run
// this PolicyApplicator.
- const PolicyMap& policies_by_guid =
- *handler_->GetPoliciesForProfile(profile_path_);
+ const GuidToPolicyMap& policies =
+ *handler_->GetPoliciesForProfile(profile_);
const base::DictionaryValue* new_policy = NULL;
if (was_managed) {
// If we have a GUID that might match a current policy, do a lookup using
// that GUID at first. In particular this is necessary, as some networks
// can't be matched to policies by properties (e.g. VPN).
- PolicyMap::const_iterator it = policies_by_guid.find(old_guid);
- if (it != policies_by_guid.end())
- new_policy = it->second;
+ new_policy = GetByGUID(policies, old_guid);
}
if (!new_policy) {
// If we didn't find a policy by GUID, still a new policy might match.
- new_policy = FindMatchingPolicy(policies_by_guid, *onc_part);
+ new_policy = FindMatchingPolicy(policies, *onc_part);
}
if (new_policy) {
@@ -721,7 +755,7 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
// Update the existing configuration with the maybe changed
// policy. Thereby the GUID might change.
scoped_ptr<base::DictionaryValue> shill_dictionary =
- CreateShillConfiguration(profile_path_, new_guid, new_policy,
+ CreateShillConfiguration(profile_, new_guid, new_policy,
ui_data->user_settings());
NetworkConfigurationHandler::Get()->CreateConfiguration(
*shill_dictionary,
@@ -747,42 +781,47 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
void DeleteEntry(const std::string& entry) {
DBusThreadManager::Get()->GetShillProfileClient()->DeleteEntry(
- dbus::ObjectPath(profile_path_),
+ dbus::ObjectPath(profile_.path),
entry,
base::Bind(&base::DoNothing),
base::Bind(&LogErrorMessage, FROM_HERE));
}
virtual ~PolicyApplicator() {
+ if (!handler_) {
+ LOG(WARNING) << "Handler destructed during policy application to profile "
+ << profile_.ToDebugString();
+ return;
+ }
+
if (remaining_policies_.empty())
return;
VLOG(2) << "Create new managed network configurations in profile"
- << profile_path_ << ".";
+ << profile_.ToDebugString() << ".";
// All profile entries were compared to policies. |configureGUIDs_| contains
// all matched policies. From the remainder of policies, new configurations
// have to be created.
// The relevant policy must have been initialized, otherwise we hadn't Run
// this PolicyApplicator.
- const PolicyMap& policies_by_guid =
- *handler_->GetPoliciesForProfile(profile_path_);
+ const GuidToPolicyMap& policies =
+ *handler_->GetPoliciesForProfile(profile_);
for (std::set<std::string>::iterator it = remaining_policies_.begin();
it != remaining_policies_.end(); ++it) {
- PolicyMap::const_iterator policy_it = policies_by_guid.find(*it);
- if (policy_it == policies_by_guid.end()) {
+ const base::DictionaryValue* policy = GetByGUID(policies, *it);
+ if (!policy) {
LOG(ERROR) << "Policy " << *it << " doesn't exist anymore.";
continue;
}
- const base::DictionaryValue* policy = policy_it->second;
-
VLOG(1) << "Creating new configuration managed by policy " << *it
- << " in profile " << profile_path_ << ".";
+ << " in profile " << profile_.ToDebugString() << ".";
scoped_ptr<base::DictionaryValue> shill_dictionary =
- CreateShillConfiguration(profile_path_, *it, policy, NULL);
+ CreateShillConfiguration(profile_, *it, policy,
+ NULL /* no user settings */);
NetworkConfigurationHandler::Get()->CreateConfiguration(
*shill_dictionary,
base::Bind(&IgnoreString),
@@ -792,31 +831,25 @@ class ManagedNetworkConfigurationHandler::PolicyApplicator
std::set<std::string> remaining_policies_;
base::WeakPtr<ManagedNetworkConfigurationHandler> handler_;
- std::string profile_path_;
+ NetworkProfile profile_;
DISALLOW_COPY_AND_ASSIGN(PolicyApplicator);
};
void ManagedNetworkConfigurationHandler::SetPolicy(
onc::ONCSource onc_source,
+ const std::string& userhash,
const base::ListValue& network_configs_onc) {
- VLOG(1) << "Setting policies for ONC source "
- << onc::GetSourceAsString(onc_source) << ".";
-
- PolicyMap* policies;
- std::string profile;
- if (onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY) {
- policies = &user_policies_by_guid_;
- profile = kUserProfilePath;
- user_policies_initialized_ = true;
- } else {
- policies = &device_policies_by_guid_;
- profile = kSharedProfilePath;
- device_policies_initialized_ = true;
- }
+ VLOG(1) << "Setting policies from " << ToDebugString(onc_source, userhash)
+ << ".";
+
+ // |userhash| must be empty for device policies.
+ DCHECK(onc_source != chromeos::onc::ONC_SOURCE_DEVICE_POLICY ||
+ userhash.empty());
+ GuidToPolicyMap& policies = policies_by_user_[userhash];
- PolicyMap old_policies;
- policies->swap(old_policies);
+ GuidToPolicyMap old_policies;
+ policies.swap(old_policies);
// This stores all GUIDs of policies that have changed or are new.
std::set<std::string> modified_policies;
@@ -831,14 +864,14 @@ void ManagedNetworkConfigurationHandler::SetPolicy(
network->GetStringWithoutPathExpansion(onc::network_config::kGUID, &guid);
DCHECK(!guid.empty());
- if (policies->count(guid) > 0) {
- LOG(ERROR) << "ONC from " << onc::GetSourceAsString(onc_source)
+ if (policies.count(guid) > 0) {
+ LOG(ERROR) << "ONC from " << ToDebugString(onc_source, userhash)
<< " contains several entries for the same GUID "
<< guid << ".";
- delete (*policies)[guid];
+ delete policies[guid];
}
const base::DictionaryValue* new_entry = network->DeepCopy();
- (*policies)[guid] = new_entry;
+ policies[guid] = new_entry;
const base::DictionaryValue* old_entry = old_policies[guid];
if (!old_entry || !old_entry->Equals(new_entry))
@@ -847,34 +880,80 @@ void ManagedNetworkConfigurationHandler::SetPolicy(
STLDeleteValues(&old_policies);
+ const NetworkProfile* profile =
+ profile_handler_->GetProfileForUserhash(userhash);
+ if (!profile) {
+ VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
+ << "policy application.";
+ return;
+ }
+
scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator(
weak_ptr_factory_.GetWeakPtr(),
- profile,
+ *profile,
&modified_policies);
applicator->Run();
}
-const ManagedNetworkConfigurationHandler::PolicyMap*
-ManagedNetworkConfigurationHandler::GetPoliciesForProfile(
- const std::string& profile) const {
- if (profile == kSharedProfilePath) {
- if (device_policies_initialized_)
- return &device_policies_by_guid_;
- } else if (user_policies_initialized_) {
- return &user_policies_by_guid_;
+void ManagedNetworkConfigurationHandler::OnProfileAdded(
+ const NetworkProfile& profile) {
+ VLOG(1) << "Adding profile " << profile.ToDebugString() << "'.";
+
+ const GuidToPolicyMap* policies = GetPoliciesForProfile(profile);
+ if (!policies) {
+ VLOG(1) << "The relevant policy is not initialized, "
+ << "postponing policy application.";
+ return;
}
- return NULL;
+
+ std::set<std::string> policy_guids;
+ for (GuidToPolicyMap::const_iterator it = policies->begin();
+ it != policies->end(); ++it) {
+ policy_guids.insert(it->first);
+ }
+
+ scoped_refptr<PolicyApplicator> applicator = new PolicyApplicator(
+ weak_ptr_factory_.GetWeakPtr(),
+ profile,
+ &policy_guids);
+ applicator->Run();
+}
+
+void ManagedNetworkConfigurationHandler::OnProfileRemoved(
+ const NetworkProfile& profile) {
+ // Nothing to do in this case.
+}
+
+const ManagedNetworkConfigurationHandler::GuidToPolicyMap*
+ManagedNetworkConfigurationHandler::GetPoliciesForUser(
+ const std::string& userhash) const {
+ UserToPoliciesMap::const_iterator it = policies_by_user_.find(userhash);
+ if (it == policies_by_user_.end())
+ return NULL;
+ return &it->second;
}
-ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler()
- : user_policies_initialized_(false),
- device_policies_initialized_(false),
+const ManagedNetworkConfigurationHandler::GuidToPolicyMap*
+ManagedNetworkConfigurationHandler::GetPoliciesForProfile(
+ const NetworkProfile& profile) const {
+ DCHECK(profile.type() != NetworkProfile::TYPE_SHARED ||
+ profile.userhash.empty());
+ return GetPoliciesForUser(profile.userhash);
+}
+
+ManagedNetworkConfigurationHandler::ManagedNetworkConfigurationHandler(
+ NetworkProfileHandler* profile_handler)
+ : profile_handler_(profile_handler),
weak_ptr_factory_(this) {
+ profile_handler_->AddObserver(this);
}
ManagedNetworkConfigurationHandler::~ManagedNetworkConfigurationHandler() {
- STLDeleteValues(&user_policies_by_guid_);
- STLDeleteValues(&device_policies_by_guid_);
+ profile_handler_->RemoveObserver(this);
+ for (UserToPoliciesMap::iterator it = policies_by_user_.begin();
+ it != policies_by_user_.end(); ++it) {
+ STLDeleteValues(&it->second);
+ }
}
} // namespace chromeos
diff --git a/chromeos/network/managed_network_configuration_handler.h b/chromeos/network/managed_network_configuration_handler.h
index e563fe4..db7e47d 100644
--- a/chromeos/network/managed_network_configuration_handler.h
+++ b/chromeos/network/managed_network_configuration_handler.h
@@ -14,6 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_profile_observer.h"
#include "chromeos/network/onc/onc_constants.h"
namespace base {
@@ -23,6 +24,8 @@ class ListValue;
namespace chromeos {
+class NetworkProfileHandler;
+
// The ManagedNetworkConfigurationHandler class is used to create and configure
// networks in ChromeOS using ONC and takes care of network policies.
//
@@ -48,12 +51,14 @@ namespace chromeos {
// that is suitable for logging. None of the error message text is meant for
// user consumption.
-class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler {
+class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler
+ : public NetworkProfileObserver {
public:
- typedef std::map<std::string, const base::DictionaryValue*> PolicyMap;
+ typedef std::map<std::string, const base::DictionaryValue*> GuidToPolicyMap;
+ typedef std::map<std::string, GuidToPolicyMap> UserToPoliciesMap;
// Initializes the singleton.
- static void Initialize();
+ static void Initialize(NetworkProfileHandler* profile_handler);
// Returns if the singleton is initialized.
static bool IsInitialized();
@@ -71,8 +76,10 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler {
const network_handler::ErrorCallback& error_callback) const;
// Provides the managed properties of the network with |service_path| to
- // |callback|.
+ // |callback|. |userhash| is only used to ensure that the user's policy is
+ // already applied.
void GetManagedProperties(
+ const std::string& userhash,
const std::string& service_path,
const network_handler::DictionaryResultCallback& callback,
const network_handler::ErrorCallback& error_callback);
@@ -105,8 +112,10 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler {
// Initially configures an unconfigured network with the given user settings
// and returns the new identifier to |callback| if successful. Fails if the
// network was already configured by a call to this function or because of a
- // policy.
+ // policy. The new configuration will be owned by user |userhash|. If
+ // |userhash| is empty, the new configuration will be shared.
void CreateConfiguration(
+ const std::string& userhash,
const base::DictionaryValue& properties,
const network_handler::StringResultCallback& callback,
const network_handler::ErrorCallback& error_callback) const;
@@ -123,16 +132,22 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler {
// |network_configs_onc| as the current policy of |onc_source|. The network
// configurations of the policy will be applied (not necessarily immediately)
// to Shill's profiles and enforced in future configurations until the policy
- // associated with |onc_source| is changed again with this function.
- // This function doesn't validate the policy. The caller must ensure validity.
+ // associated with |onc_source| is changed again with this function. For
+ // device policies, |userhash| must be empty.
void SetPolicy(onc::ONCSource onc_source,
+ const std::string& userhash,
const base::ListValue& network_configs_onc);
+ // NetworkProfileObserver overrides
+ virtual void OnProfileAdded(const NetworkProfile& profile) OVERRIDE;
+ virtual void OnProfileRemoved(const NetworkProfile& profile) OVERRIDE;
+
private:
class PolicyApplicator;
- ManagedNetworkConfigurationHandler();
- ~ManagedNetworkConfigurationHandler();
+ explicit ManagedNetworkConfigurationHandler(
+ NetworkProfileHandler* profile_handler);
+ virtual ~ManagedNetworkConfigurationHandler();
void GetManagedPropertiesCallback(
const network_handler::DictionaryResultCallback& callback,
@@ -140,14 +155,17 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandler {
const std::string& service_path,
const base::DictionaryValue& shill_properties);
- const PolicyMap* GetPoliciesForProfile(const std::string& profile) const;
+ const GuidToPolicyMap* GetPoliciesForUser(const std::string& userhash) const;
+ const GuidToPolicyMap* GetPoliciesForProfile(
+ const NetworkProfile& profile) const;
+
+ // The DictionaryValues of the nested maps are owned by this class and are
+ // explicitly deleted where necessary. If present, the empty string maps to
+ // the device policy.
+ UserToPoliciesMap policies_by_user_;
- // The entries of these maps are owned by this class and are explicitly
- // deleted where necessary.
- PolicyMap user_policies_by_guid_;
- PolicyMap device_policies_by_guid_;
- bool user_policies_initialized_;
- bool device_policies_initialized_;
+ // A local reference to the policy handler singleton.
+ NetworkProfileHandler* profile_handler_;
// For Shill client callbacks
base::WeakPtrFactory<ManagedNetworkConfigurationHandler> weak_ptr_factory_;
diff --git a/chromeos/network/managed_network_configuration_handler_unittest.cc b/chromeos/network/managed_network_configuration_handler_unittest.cc
index def9204..3c17809 100644
--- a/chromeos/network/managed_network_configuration_handler_unittest.cc
+++ b/chromeos/network/managed_network_configuration_handler_unittest.cc
@@ -15,6 +15,7 @@
#include "chromeos/dbus/mock_shill_service_client.h"
#include "chromeos/dbus/shill_profile_client_stub.h"
#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_profile_handler_stub.h"
#include "chromeos/network/onc/onc_test_utils.h"
#include "chromeos/network/onc/onc_utils.h"
#include "dbus/object_path.h"
@@ -33,6 +34,8 @@ using ::testing::_;
namespace test_utils = ::chromeos::onc::test_utils;
+namespace chromeos {
+
namespace {
std::string ValueToString(const base::Value* value) {
@@ -41,6 +44,10 @@ std::string ValueToString(const base::Value* value) {
return str.str();
}
+const char kSharedProfilePath[] = "/profile/default";
+const char kUser1[] = "user1";
+const char kUser1ProfilePath[] = "/profile/user1/shill";
+
// Matcher to match base::Value.
MATCHER_P(IsEqualTo,
value,
@@ -49,10 +56,80 @@ MATCHER_P(IsEqualTo,
return value->Equals(&arg);
}
-} // namespace
+class ShillProfileTestClient {
+ public:
+ typedef ShillClientHelper::DictionaryValueCallbackWithoutStatus
+ DictionaryValueCallbackWithoutStatus;
+ typedef ShillClientHelper::ErrorCallback ErrorCallback;
+
+ void AddProfile(const std::string& profile_path,
+ const std::string& userhash) {
+ if (profile_entries_.HasKey(profile_path))
+ return;
+
+ base::DictionaryValue* profile = new base::DictionaryValue;
+ profile_entries_.SetWithoutPathExpansion(profile_path, profile);
+ profile_to_user_[profile_path] = userhash;
+ }
+ void AddEntry(const std::string& profile_path,
+ const std::string& entry_path,
+ const base::DictionaryValue& entry) {
+ base::DictionaryValue* entries = NULL;
+ profile_entries_.GetDictionaryWithoutPathExpansion(profile_path, &entries);
+ ASSERT_TRUE(entries);
+
+ base::DictionaryValue* new_entry = entry.DeepCopy();
+ new_entry->SetStringWithoutPathExpansion(flimflam::kProfileProperty,
+ profile_path);
+ entries->SetWithoutPathExpansion(entry_path, new_entry);
+ }
-namespace chromeos {
+ void GetProperties(const dbus::ObjectPath& profile_path,
+ const DictionaryValueCallbackWithoutStatus& callback,
+ const ErrorCallback& error_callback) {
+ base::DictionaryValue* entries = NULL;
+ profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(),
+ &entries);
+ ASSERT_TRUE(entries);
+
+ scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue);
+ base::ListValue* entry_paths = new base::ListValue;
+ result->SetWithoutPathExpansion(flimflam::kEntriesProperty,
+ entry_paths);
+ for (base::DictionaryValue::Iterator it(*entries); !it.IsAtEnd();
+ it.Advance()) {
+ entry_paths->AppendString(it.key());
+ }
+
+ ASSERT_GT(profile_to_user_.count(profile_path.value()), 0UL);
+ const std::string& userhash = profile_to_user_[profile_path.value()];
+ result->SetStringWithoutPathExpansion(shill::kUserHashProperty, userhash);
+
+ callback.Run(*result);
+ }
+
+ void GetEntry(const dbus::ObjectPath& profile_path,
+ const std::string& entry_path,
+ const DictionaryValueCallbackWithoutStatus& callback,
+ const ErrorCallback& error_callback) {
+ base::DictionaryValue* entries = NULL;
+ profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(),
+ &entries);
+ ASSERT_TRUE(entries);
+
+ base::DictionaryValue* entry = NULL;
+ entries->GetDictionaryWithoutPathExpansion(entry_path, &entry);
+ ASSERT_TRUE(entry);
+ callback.Run(*entry);
+ }
+
+ protected:
+ base::DictionaryValue profile_entries_;
+ std::map<std::string, std::string> profile_to_user_;
+};
+
+} // namespace
class ManagedNetworkConfigurationHandlerTest : public testing::Test {
public:
@@ -76,15 +153,15 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test {
.WillRepeatedly(Return(&mock_profile_client_));
ON_CALL(mock_profile_client_, GetProperties(_,_,_))
- .WillByDefault(Invoke(&stub_profile_client_,
- &ShillProfileClientStub::GetProperties));
+ .WillByDefault(Invoke(&profiles_stub_,
+ &ShillProfileTestClient::GetProperties));
ON_CALL(mock_profile_client_, GetEntry(_,_,_,_))
- .WillByDefault(Invoke(&stub_profile_client_,
- &ShillProfileClientStub::GetEntry));
+ .WillByDefault(Invoke(&profiles_stub_,
+ &ShillProfileTestClient::GetEntry));
NetworkConfigurationHandler::Initialize();
- ManagedNetworkConfigurationHandler::Initialize();
+ ManagedNetworkConfigurationHandler::Initialize(&stub_profile_handler_);
message_loop_.RunUntilIdle();
}
@@ -94,16 +171,29 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test {
DBusThreadManager::Shutdown();
}
+ void VerifyAndClearExpectations() {
+ Mock::VerifyAndClearExpectations(&mock_manager_client_);
+ Mock::VerifyAndClearExpectations(&mock_service_client_);
+ Mock::VerifyAndClearExpectations(&mock_profile_client_);
+ }
+
+ void InitializeStandardProfiles() {
+ profiles_stub_.AddProfile(kUser1ProfilePath, kUser1);
+ stub_profile_handler_.AddProfile(NetworkProfile(kUser1ProfilePath, kUser1));
+ stub_profile_handler_.AddProfile(
+ NetworkProfile(kSharedProfilePath, std::string()));
+ }
+
void SetUpEntry(const std::string& path_to_shill_json,
const std::string& profile_path,
const std::string& entry_path) {
- stub_profile_client_.AddEntry(
- profile_path,
- entry_path,
- *test_utils::ReadTestDictionary(path_to_shill_json));
+ scoped_ptr<base::DictionaryValue> entry =
+ test_utils::ReadTestDictionary(path_to_shill_json);
+ profiles_stub_.AddEntry(profile_path, entry_path, *entry);
}
void SetPolicy(onc::ONCSource onc_source,
+ const std::string& userhash,
const std::string& path_to_onc) {
scoped_ptr<base::DictionaryValue> policy;
if (path_to_onc.empty())
@@ -115,7 +205,8 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test {
policy->GetListWithoutPathExpansion(
onc::toplevel_config::kNetworkConfigurations, &network_configs);
- managed_handler()->SetPolicy(onc::ONC_SOURCE_USER_POLICY, *network_configs);
+ managed_handler()->SetPolicy(
+ onc::ONC_SOURCE_USER_POLICY, userhash, *network_configs);
}
ManagedNetworkConfigurationHandler* managed_handler() {
@@ -126,63 +217,67 @@ class ManagedNetworkConfigurationHandlerTest : public testing::Test {
StrictMock<MockShillManagerClient> mock_manager_client_;
StrictMock<MockShillServiceClient> mock_service_client_;
StrictMock<MockShillProfileClient> mock_profile_client_;
- ShillProfileClientStub stub_profile_client_;
+ NetworkProfileHandlerStub stub_profile_handler_;
+ ShillProfileTestClient profiles_stub_;
MessageLoop message_loop_;
private:
DISALLOW_COPY_AND_ASSIGN(ManagedNetworkConfigurationHandlerTest);
};
+TEST_F(ManagedNetworkConfigurationHandlerTest, ProfileInitialization) {
+ InitializeStandardProfiles();
+ message_loop_.RunUntilIdle();
+}
+
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnconfigured) {
+ InitializeStandardProfiles();
scoped_ptr<base::DictionaryValue> expected_shill_properties =
test_utils::ReadTestDictionary(
"policy/shill_policy_on_unconfigured_wifi1.json");
EXPECT_CALL(mock_profile_client_,
- GetProperties(dbus::ObjectPath("/profile/chronos/shill"),
- _, _)).Times(1);
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
EXPECT_CALL(mock_manager_client_,
ConfigureServiceForProfile(
- dbus::ObjectPath("/profile/chronos/shill"),
+ dbus::ObjectPath(kUser1ProfilePath),
IsEqualTo(expected_shill_properties.get()),
- _, _)).Times(1);
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "policy/policy_wifi1.onc");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
message_loop_.RunUntilIdle();
}
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmodified) {
- EXPECT_CALL(mock_profile_client_,
- GetProperties(_, _, _)).Times(1);
+ InitializeStandardProfiles();
+ EXPECT_CALL(mock_profile_client_, GetProperties(_, _, _));
- EXPECT_CALL(mock_manager_client_,
- ConfigureServiceForProfile(_, _, _, _)).Times(1);
+ EXPECT_CALL(mock_manager_client_, ConfigureServiceForProfile(_, _, _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "policy/policy_wifi1.onc");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
message_loop_.RunUntilIdle();
- Mock::VerifyAndClearExpectations(&mock_profile_client_);
- Mock::VerifyAndClearExpectations(&mock_manager_client_);
+ VerifyAndClearExpectations();
SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json",
- "/profile/chronos/shill",
+ kUser1ProfilePath,
"some_entry_path");
- EXPECT_CALL(mock_profile_client_,
- GetProperties(_, _, _)).Times(1);
+ EXPECT_CALL(mock_profile_client_, GetProperties(_, _, _));
EXPECT_CALL(mock_profile_client_,
- GetEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ GetEntry(dbus::ObjectPath(kUser1ProfilePath),
"some_entry_path",
- _, _)).Times(1);
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "policy/policy_wifi1.onc");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
message_loop_.RunUntilIdle();
}
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnmanaged) {
+ InitializeStandardProfiles();
SetUpEntry("policy/shill_unmanaged_user_wifi1.json",
- "/profile/chronos/shill",
+ kUser1ProfilePath,
"old_entry_path");
scoped_ptr<base::DictionaryValue> expected_shill_properties =
@@ -190,27 +285,27 @@ TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyManageUnmanaged) {
"policy/shill_policy_on_unmanaged_user_wifi1.json");
EXPECT_CALL(mock_profile_client_,
- GetProperties(dbus::ObjectPath("/profile/chronos/shill"),
- _, _)).Times(1);
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
EXPECT_CALL(mock_profile_client_,
- GetEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ GetEntry(dbus::ObjectPath(kUser1ProfilePath),
"old_entry_path",
- _, _)).Times(1);
+ _, _));
EXPECT_CALL(mock_manager_client_,
ConfigureServiceForProfile(
- dbus::ObjectPath("/profile/chronos/shill"),
+ dbus::ObjectPath(kUser1ProfilePath),
IsEqualTo(expected_shill_properties.get()),
- _, _)).Times(1);
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "policy/policy_wifi1.onc");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
message_loop_.RunUntilIdle();
}
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedNewGUID) {
+ InitializeStandardProfiles();
SetUpEntry("policy/shill_managed_wifi1.json",
- "/profile/chronos/shill",
+ kUser1ProfilePath,
"old_entry_path");
scoped_ptr<base::DictionaryValue> expected_shill_properties =
@@ -223,27 +318,27 @@ TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUpdateManagedNewGUID) {
flimflam::kPassphraseProperty, NULL);
EXPECT_CALL(mock_profile_client_,
- GetProperties(dbus::ObjectPath("/profile/chronos/shill"),
- _, _)).Times(1);
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
EXPECT_CALL(mock_profile_client_,
- GetEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ GetEntry(dbus::ObjectPath(kUser1ProfilePath),
"old_entry_path",
- _, _)).Times(1);
+ _, _));
EXPECT_CALL(mock_manager_client_,
ConfigureServiceForProfile(
- dbus::ObjectPath("/profile/chronos/shill"),
+ dbus::ObjectPath(kUser1ProfilePath),
IsEqualTo(expected_shill_properties.get()),
- _, _)).Times(1);
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "policy/policy_wifi1.onc");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
message_loop_.RunUntilIdle();
}
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyReapplyToManaged) {
+ InitializeStandardProfiles();
SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json",
- "/profile/chronos/shill",
+ kUser1ProfilePath,
"old_entry_path");
scoped_ptr<base::DictionaryValue> expected_shill_properties =
@@ -256,62 +351,84 @@ TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyReapplyToManaged) {
flimflam::kPassphraseProperty, NULL);
EXPECT_CALL(mock_profile_client_,
- GetProperties(dbus::ObjectPath("/profile/chronos/shill"),
- _, _)).Times(1);
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
EXPECT_CALL(mock_profile_client_,
- GetEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ GetEntry(dbus::ObjectPath(kUser1ProfilePath),
"old_entry_path",
- _, _)).Times(1);
+ _, _));
EXPECT_CALL(mock_manager_client_,
ConfigureServiceForProfile(
- dbus::ObjectPath("/profile/chronos/shill"),
+ dbus::ObjectPath(kUser1ProfilePath),
IsEqualTo(expected_shill_properties.get()),
- _, _)).Times(1);
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "policy/policy_wifi1.onc");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
message_loop_.RunUntilIdle();
}
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyUnmanageManaged) {
+ InitializeStandardProfiles();
SetUpEntry("policy/shill_policy_on_unmanaged_user_wifi1.json",
- "/profile/chronos/shill",
+ kUser1ProfilePath,
"old_entry_path");
EXPECT_CALL(mock_profile_client_,
- GetProperties(dbus::ObjectPath("/profile/chronos/shill"),
- _, _)).Times(1);
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
EXPECT_CALL(mock_profile_client_,
- GetEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ GetEntry(dbus::ObjectPath(kUser1ProfilePath),
"old_entry_path",
- _, _)).Times(1);
+ _, _));
EXPECT_CALL(mock_profile_client_,
- DeleteEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ DeleteEntry(dbus::ObjectPath(kUser1ProfilePath),
"old_entry_path",
- _, _)).Times(1);
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "");
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "");
message_loop_.RunUntilIdle();
}
TEST_F(ManagedNetworkConfigurationHandlerTest, SetPolicyIgnoreUnmanaged) {
+ InitializeStandardProfiles();
SetUpEntry("policy/shill_unmanaged_user_wifi1.json",
- "/profile/chronos/shill",
+ kUser1ProfilePath,
"old_entry_path");
EXPECT_CALL(mock_profile_client_,
- GetProperties(dbus::ObjectPath("/profile/chronos/shill"),
- _, _)).Times(1);
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
EXPECT_CALL(mock_profile_client_,
- GetEntry(dbus::ObjectPath("/profile/chronos/shill"),
+ GetEntry(dbus::ObjectPath(kUser1ProfilePath),
"old_entry_path",
- _, _)).Times(1);
+ _, _));
+
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "");
+ message_loop_.RunUntilIdle();
+}
+
+TEST_F(ManagedNetworkConfigurationHandlerTest, LateProfileLoading) {
+ SetPolicy(onc::ONC_SOURCE_USER_POLICY, kUser1, "policy/policy_wifi1.onc");
+
+ message_loop_.RunUntilIdle();
+ VerifyAndClearExpectations();
+
+ scoped_ptr<base::DictionaryValue> expected_shill_properties =
+ test_utils::ReadTestDictionary(
+ "policy/shill_policy_on_unconfigured_wifi1.json");
+
+ EXPECT_CALL(mock_profile_client_,
+ GetProperties(dbus::ObjectPath(kUser1ProfilePath), _, _));
+
+ EXPECT_CALL(mock_manager_client_,
+ ConfigureServiceForProfile(
+ dbus::ObjectPath(kUser1ProfilePath),
+ IsEqualTo(expected_shill_properties.get()),
+ _, _));
- SetPolicy(onc::ONC_SOURCE_USER_POLICY, "");
+ InitializeStandardProfiles();
message_loop_.RunUntilIdle();
}
diff --git a/chromeos/network/network_profile.cc b/chromeos/network/network_profile.cc
new file mode 100644
index 0000000..97b7ce5
--- /dev/null
+++ b/chromeos/network/network_profile.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2013 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 "chromeos/network/network_profile.h"
+
+#include "base/logging.h"
+#include "base/stringprintf.h"
+
+namespace chromeos {
+
+std::string NetworkProfile::ToDebugString() const {
+ std::string result;
+ if (type() == NetworkProfile::TYPE_SHARED) {
+ return base::StringPrintf("NetworkProfile(SHARED, %s)",
+ path.c_str());
+ } else if (type() == NetworkProfile::TYPE_USER) {
+ return base::StringPrintf("NetworkProfile(USER, %s, %s)",
+ path.c_str(),
+ userhash.c_str());
+ }
+ NOTREACHED();
+ return std::string();
+}
+
+} // namespace chromeos
diff --git a/chromeos/network/network_profile.h b/chromeos/network/network_profile.h
new file mode 100644
index 0000000..fc11a0c
--- /dev/null
+++ b/chromeos/network/network_profile.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2013 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.
+
+#ifndef CHROMEOS_NETWORK_NETWORK_PROFILE_H_
+#define CHROMEOS_NETWORK_NETWORK_PROFILE_H_
+
+#include <string>
+
+#include "chromeos/chromeos_export.h"
+
+namespace chromeos {
+
+struct CHROMEOS_EXPORT NetworkProfile {
+ enum Type {
+ TYPE_SHARED, // Shared by all users on the device.
+ TYPE_USER // Not visible to other users.
+ };
+
+ NetworkProfile(const std::string& profile_path,
+ const std::string& user_hash)
+ : path(profile_path),
+ userhash(user_hash) {
+ }
+
+ std::string path;
+ std::string userhash; // Only set for user profiles.
+
+ Type type() const {
+ return userhash.empty() ? TYPE_SHARED : TYPE_USER;
+ }
+
+ std::string ToDebugString() const;
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_NETWORK_PROFILE_H_
diff --git a/chromeos/network/network_profile_handler.cc b/chromeos/network/network_profile_handler.cc
new file mode 100644
index 0000000..30c8fde
--- /dev/null
+++ b/chromeos/network/network_profile_handler.cc
@@ -0,0 +1,233 @@
+// Copyright (c) 2013 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 "chromeos/network/network_profile_handler.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/string_util.h"
+#include "base/values.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill_profile_client.h"
+#include "chromeos/network/network_profile_observer.h"
+#include "dbus/object_path.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+static NetworkProfileHandler* g_profile_handler_instance = NULL;
+
+namespace {
+
+bool ConvertListValueToStringVector(const base::ListValue& string_list,
+ std::vector<std::string>* result) {
+ for (size_t i = 0; i < string_list.GetSize(); ++i) {
+ std::string str;
+ if (!string_list.GetString(i, &str))
+ return false;
+ result->push_back(str);
+ }
+ return true;
+}
+
+void LogProfileRequestError(const std::string& profile_path,
+ const std::string& error_name,
+ const std::string& error_message) {
+ LOG(ERROR) << "Error when requesting properties for profile "
+ << profile_path << ": " << error_message;
+}
+
+class ProfilePathEquals {
+ public:
+ explicit ProfilePathEquals(const std::string& path)
+ : path_(path) {
+ }
+
+ bool operator()(const NetworkProfile& profile) {
+ return profile.path == path_;
+ }
+
+ private:
+ std::string path_;
+};
+
+class NetworkProfileHandlerImpl : public NetworkProfileHandler {
+ public:
+ NetworkProfileHandlerImpl() {
+ DBusThreadManager::Get()->GetShillManagerClient()->
+ AddPropertyChangedObserver(this);
+
+ // Request the initial profile list.
+ DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
+ base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ virtual ~NetworkProfileHandlerImpl() {
+ DBusThreadManager::Get()->GetShillManagerClient()->
+ RemovePropertyChangedObserver(this);
+ }
+};
+
+} // namespace
+
+// static
+NetworkProfileHandler* NetworkProfileHandler::Initialize() {
+ CHECK(!g_profile_handler_instance);
+ g_profile_handler_instance = new NetworkProfileHandlerImpl();
+ return g_profile_handler_instance;
+}
+
+// static
+bool NetworkProfileHandler::IsInitialized() {
+ return g_profile_handler_instance;
+}
+
+// static
+void NetworkProfileHandler::Shutdown() {
+ CHECK(g_profile_handler_instance);
+ delete g_profile_handler_instance;
+ g_profile_handler_instance = NULL;
+}
+
+// static
+NetworkProfileHandler* NetworkProfileHandler::Get() {
+ CHECK(g_profile_handler_instance);
+ return g_profile_handler_instance;
+}
+
+void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+void NetworkProfileHandler::GetManagerPropertiesCallback(
+ DBusMethodCallStatus call_status,
+ const base::DictionaryValue& properties) {
+ if (DBUS_METHOD_CALL_FAILURE) {
+ LOG(ERROR) << "Error when requesting manager properties.";
+ return;
+ }
+
+ const base::Value* profiles = NULL;
+ properties.GetWithoutPathExpansion(flimflam::kProfilesProperty, &profiles);
+ if (!profiles) {
+ LOG(ERROR) << "Manager properties returned from Shill don't contain "
+ << "the field " << flimflam::kProfilesProperty;
+ return;
+ }
+ OnPropertyChanged(flimflam::kProfilesProperty, *profiles);
+}
+
+void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
+ const base::Value& value) {
+ if (name != flimflam::kProfilesProperty)
+ return;
+
+ const base::ListValue* profiles_value = NULL;
+ value.GetAsList(&profiles_value);
+ DCHECK(profiles_value);
+
+ std::vector<std::string> new_profile_paths;
+ bool result = ConvertListValueToStringVector(*profiles_value,
+ &new_profile_paths);
+ DCHECK(result);
+
+ // Search for removed profiles.
+ std::vector<std::string> removed_profile_paths;
+ for (ProfileList::const_iterator it = profiles_.begin();
+ it != profiles_.end(); ++it) {
+ if (std::find(new_profile_paths.begin(),
+ new_profile_paths.end(),
+ it->path) == new_profile_paths.end()) {
+ removed_profile_paths.push_back(it->path);
+ }
+ }
+
+ for (std::vector<std::string>::const_iterator it =
+ removed_profile_paths.begin();
+ it != removed_profile_paths.end(); ++it) {
+ RemoveProfile(*it);
+ }
+
+ for (std::vector<std::string>::const_iterator it = new_profile_paths.begin();
+ it != new_profile_paths.end(); ++it) {
+ // Skip known profiles. The associated userhash should never change.
+ if (GetProfileForPath(*it))
+ continue;
+
+ VLOG(2) << "Requesting properties of profile path " << *it << ".";
+ DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
+ dbus::ObjectPath(*it),
+ base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback,
+ weak_ptr_factory_.GetWeakPtr(),
+ *it),
+ base::Bind(&LogProfileRequestError, *it));
+ }
+}
+
+void NetworkProfileHandler::GetProfilePropertiesCallback(
+ const std::string& profile_path,
+ const base::DictionaryValue& properties) {
+ std::string userhash;
+ properties.GetStringWithoutPathExpansion(shill::kUserHashProperty,
+ &userhash);
+
+ AddProfile(NetworkProfile(profile_path, userhash));
+}
+
+void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
+ VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
+ profiles_.push_back(profile);
+ FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
+ OnProfileAdded(profiles_.back()));
+}
+
+void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
+ VLOG(2) << "Removing profile for path " << profile_path << ".";
+ ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
+ ProfilePathEquals(profile_path));
+ if (found == profiles_.end())
+ return;
+ NetworkProfile profile = *found;
+ profiles_.erase(found);
+ FOR_EACH_OBSERVER(NetworkProfileObserver, observers_,
+ OnProfileRemoved(profile));
+}
+
+const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
+ const std::string& profile_path) const {
+ ProfileList::const_iterator found =
+ std::find_if(profiles_.begin(), profiles_.end(),
+ ProfilePathEquals(profile_path));
+
+ if (found == profiles_.end())
+ return NULL;
+ return &*found;
+}
+
+const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
+ const std::string& userhash) const {
+ for (NetworkProfileHandler::ProfileList::const_iterator it =
+ profiles_.begin();
+ it != profiles_.end(); ++it) {
+ if (it->userhash == userhash)
+ return &*it;
+ }
+ return NULL;
+}
+
+NetworkProfileHandler::NetworkProfileHandler()
+ : weak_ptr_factory_(this) {
+}
+
+NetworkProfileHandler::~NetworkProfileHandler() {
+}
+
+} // namespace chromeos
diff --git a/chromeos/network/network_profile_handler.h b/chromeos/network/network_profile_handler.h
new file mode 100644
index 0000000..9dbc5d4
--- /dev/null
+++ b/chromeos/network/network_profile_handler.h
@@ -0,0 +1,88 @@
+// Copyright (c) 2013 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.
+
+#ifndef CHROMEOS_NETWORK_NETWORK_PROFILE_HANDLER_H_
+#define CHROMEOS_NETWORK_NETWORK_PROFILE_HANDLER_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/dbus_method_call_status.h"
+#include "chromeos/dbus/shill_property_changed_observer.h"
+#include "chromeos/network/network_profile.h"
+
+namespace base {
+class DictionaryValue;
+}
+
+namespace chromeos {
+
+class NetworkProfileObserver;
+
+class CHROMEOS_EXPORT NetworkProfileHandler
+ : public ShillPropertyChangedObserver {
+ public:
+ typedef std::vector<NetworkProfile> ProfileList;
+
+ // Initializes the singleton and registers it for DBus events.
+ static NetworkProfileHandler* Initialize();
+
+ // Returns if the singleton is initialized.
+ static bool IsInitialized();
+
+ // Unregisters the singleton from DBus events and destroys it.
+ static void Shutdown();
+
+ // Initialize() must be called before this.
+ static NetworkProfileHandler* Get();
+
+ void AddObserver(NetworkProfileObserver* observer);
+ void RemoveObserver(NetworkProfileObserver* observer);
+
+ void RequestInitialProfileList();
+ void GetManagerPropertiesCallback(DBusMethodCallStatus call_status,
+ const base::DictionaryValue& properties);
+
+ // ShillPropertyChangedObserver overrides
+ virtual void OnPropertyChanged(const std::string& name,
+ const base::Value& value) OVERRIDE;
+
+ void GetProfilePropertiesCallback(const std::string& profile_path,
+ const base::DictionaryValue& properties);
+
+ const NetworkProfile* GetProfileForPath(
+ const std::string& profile_path) const;
+ const NetworkProfile* GetProfileForUserhash(
+ const std::string& userhash) const;
+
+ protected:
+ // We make the de-/constructor protected to prevent their usage except in
+ // tests by deriving a stub (see NetworkProfileHandlerStub). Outside of tests,
+ // the singleton should be retrieved with the static Get() function.
+ NetworkProfileHandler();
+ virtual ~NetworkProfileHandler();
+
+ void AddProfile(const NetworkProfile& profile);
+ void RemoveProfile(const std::string& profile_path);
+
+ private:
+ ProfileList profiles_;
+ ObserverList<NetworkProfileObserver> observers_;
+
+ protected:
+ // For Shill client callbacks
+ base::WeakPtrFactory<NetworkProfileHandler> weak_ptr_factory_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NetworkProfileHandler);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_NETWORK_PROFILE_HANDLER_H_
diff --git a/chromeos/network/network_profile_handler_stub.h b/chromeos/network/network_profile_handler_stub.h
new file mode 100644
index 0000000..b136028
--- /dev/null
+++ b/chromeos/network/network_profile_handler_stub.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2013 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.
+
+#ifndef CHROMEOS_NETWORK_NETWORK_PROFILE_HANDLER_STUB_H_
+#define CHROMEOS_NETWORK_NETWORK_PROFILE_HANDLER_STUB_H_
+
+#include "chromeos/chromeos_export.h"
+#include "chromeos/network/network_profile_handler.h"
+
+namespace chromeos {
+
+class CHROMEOS_EXPORT NetworkProfileHandlerStub
+ : public NetworkProfileHandler {
+ public:
+ using NetworkProfileHandler::AddProfile;
+ using NetworkProfileHandler::RemoveProfile;
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_NETWORK_PROFILE_HANDLER_STUB_H_
diff --git a/chromeos/network/network_profile_observer.h b/chromeos/network/network_profile_observer.h
new file mode 100644
index 0000000..87a7b19
--- /dev/null
+++ b/chromeos/network/network_profile_observer.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2013 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.
+
+#ifndef CHROMEOS_NETWORK_NETWORK_PROFILE_OBSERVER_H_
+#define CHROMEOS_NETWORK_NETWORK_PROFILE_OBSERVER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace chromeos {
+
+struct NetworkProfile;
+
+class NetworkProfileObserver {
+ public:
+ virtual void OnProfileAdded(const NetworkProfile& profile) = 0;
+ virtual void OnProfileRemoved(const NetworkProfile& profile) = 0;
+
+ protected:
+ virtual ~NetworkProfileObserver() {}
+
+ private:
+ DISALLOW_ASSIGN(NetworkProfileObserver);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_NETWORK_NETWORK_PROFILE_OBSERVER_H_
diff --git a/chromeos/network/onc/onc_validator.cc b/chromeos/network/onc/onc_validator.cc
index 43ccf7d..23af30a 100644
--- a/chromeos/network/onc/onc_validator.cc
+++ b/chromeos/network/onc/onc_validator.cc
@@ -92,7 +92,7 @@ scoped_ptr<base::Value> Validator::MapValue(
const base::Value& onc_value,
bool* error) {
if (onc_value.GetType() != signature.onc_type) {
- LOG(ERROR) << ErrorHeader() << "Found value '" << onc_value
+ LOG(ERROR) << MessageHeader() << "Found value '" << onc_value
<< "' of type '" << ValueTypeToString(onc_value.GetType())
<< "', but type '" << ValueTypeToString(signature.onc_type)
<< "' is required.";
@@ -168,8 +168,8 @@ scoped_ptr<base::Value> Validator::MapField(
if (current_field_unknown) {
error_or_warning_found_ = *found_unknown_field = true;
- std::string message = MessageHeader(error_on_unknown_field_)
- + "Field name '" + field_name + "' is unknown.";
+ std::string message = MessageHeader() + "Field name '" + field_name +
+ "' is unknown.";
if (error_on_unknown_field_)
LOG(ERROR) << message;
else
@@ -250,7 +250,7 @@ bool Validator::ValidateRecommendedField(
if (!managed_onc_) {
error_or_warning_found_ = true;
- LOG(WARNING) << WarningHeader() << "Found the field '" << onc::kRecommended
+ LOG(WARNING) << MessageHeader() << "Found the field '" << onc::kRecommended
<< "' in an unmanaged ONC. Removing it.";
return true;
}
@@ -281,9 +281,8 @@ bool Validator::ValidateRecommendedField(
if (found_error) {
error_or_warning_found_ = true;
path_.push_back(onc::kRecommended);
- std::string message = MessageHeader(error_on_wrong_recommended_) +
- "The " + error_cause + " field '" + field_name +
- "' cannot be recommended.";
+ std::string message = MessageHeader() + "The " + error_cause +
+ " field '" + field_name + "' cannot be recommended.";
path_.pop_back();
if (error_on_wrong_recommended_) {
LOG(ERROR) << message;
@@ -330,7 +329,7 @@ bool Validator::FieldExistsAndHasNoValidValue(
std::string valid_values_str =
"[" + JoinStringRange(valid_values, it, ", ") + "]";
path_.push_back(field_name);
- LOG(ERROR) << ErrorHeader() << "Found value '" << actual_value <<
+ LOG(ERROR) << MessageHeader() << "Found value '" << actual_value <<
"', but expected one of the values " << valid_values_str;
path_.pop_back();
return true;
@@ -347,7 +346,7 @@ bool Validator::FieldExistsAndIsNotInRange(const base::DictionaryValue& object,
}
error_or_warning_found_ = true;
path_.push_back(field_name);
- LOG(ERROR) << ErrorHeader() << "Found value '" << actual_value
+ LOG(ERROR) << MessageHeader() << "Found value '" << actual_value
<< "', but expected a value in the range [" << lower_bound
<< ", " << upper_bound << "] (boundaries inclusive)";
path_.pop_back();
@@ -364,7 +363,7 @@ bool Validator::FieldExistsAndIsEmpty(const base::DictionaryValue& object,
error_or_warning_found_ = true;
path_.push_back(field_name);
- LOG(ERROR) << ErrorHeader() << "Found an empty string, but expected a "
+ LOG(ERROR) << MessageHeader() << "Found an empty string, but expected a "
<< "non-empty string.";
path_.pop_back();
return true;
@@ -375,8 +374,12 @@ bool Validator::RequireField(const base::DictionaryValue& dict,
if (dict.HasKey(field_name))
return true;
error_or_warning_found_ = true;
- LOG(ERROR) << ErrorHeader() << "The required field '" << field_name
- << "' is missing.";
+ std::string message = MessageHeader() + "The required field '" + field_name +
+ "' is missing.";
+ if (error_on_missing_field_)
+ LOG(ERROR) << message;
+ else
+ LOG(WARNING) << message;
return false;
}
@@ -386,7 +389,7 @@ bool Validator::CertPatternInDevicePolicy(const std::string& cert_type) {
if (cert_type == certificate::kPattern &&
onc_source_ == ONC_SOURCE_DEVICE_POLICY) {
error_or_warning_found_ = true;
- LOG(ERROR) << ErrorHeader() << "Client certificate patterns are "
+ LOG(ERROR) << MessageHeader() << "Client certificate patterns are "
<< "prohibited in ONC device policies.";
return true;
}
@@ -414,9 +417,9 @@ bool Validator::ValidateToplevelConfiguration(
!result->HasKey(kNetworkConfigurations) &&
!result->HasKey(kCertificates)) {
error_or_warning_found_ = true;
- std::string message = MessageHeader(error_on_missing_field_) +
- "Neither the field '" + kNetworkConfigurations + "' nor '" +
- kCertificates + "is present, but at least one is required.";
+ std::string message = MessageHeader() + "Neither the field '" +
+ kNetworkConfigurations + "' nor '" + kCertificates +
+ "is present, but at least one is required.";
if (error_on_missing_field_)
LOG(ERROR) << message;
else
@@ -459,7 +462,7 @@ bool Validator::ValidateNetworkConfiguration(
type != network_type::kWiFi &&
type != network_type::kEthernet) {
error_or_warning_found_ = true;
- LOG(ERROR) << ErrorHeader() << "Networks of type '"
+ LOG(ERROR) << MessageHeader() << "Networks of type '"
<< type << "' are prohibited in ONC device policies.";
return false;
}
@@ -659,9 +662,9 @@ bool Validator::ValidateCertificatePattern(
!result->HasKey(kIssuerCARef)) {
error_or_warning_found_ = true;
allRequiredExist = false;
- std::string message = MessageHeader(error_on_missing_field_) +
- "None of the fields '" + kSubject + "', '" + kIssuer + "', and '" +
- kIssuerCARef + "' is present, but at least one is required.";
+ std::string message = MessageHeader() + "None of the fields '" + kSubject +
+ "', '" + kIssuer + "', and '" + kIssuerCARef +
+ "' is present, but at least one is required.";
if (error_on_missing_field_)
LOG(ERROR) << message;
else
@@ -751,7 +754,7 @@ bool Validator::ValidateCertificate(
if (onc_source_ == ONC_SOURCE_DEVICE_POLICY &&
(type == kServer || type == kAuthority)) {
error_or_warning_found_ = true;
- LOG(ERROR) << ErrorHeader() << "Server and authority certificates are "
+ LOG(ERROR) << MessageHeader() << "Server and authority certificates are "
<< "prohibited in ONC device policies.";
return false;
}
@@ -772,15 +775,7 @@ bool Validator::ValidateCertificate(
return !error_on_missing_field_ || allRequiredExist;
}
-std::string Validator::WarningHeader() {
- return MessageHeader(false);
-}
-
-std::string Validator::ErrorHeader() {
- return MessageHeader(true);
-}
-
-std::string Validator::MessageHeader(bool is_error) {
+std::string Validator::MessageHeader() {
std::string path = path_.empty() ? "toplevel" : JoinString(path_, ".");
std::string message = "At " + path + ": ";
return message;
diff --git a/chromeos/network/onc/onc_validator.h b/chromeos/network/onc/onc_validator.h
index 1de930b..539224f 100644
--- a/chromeos/network/onc/onc_validator.h
+++ b/chromeos/network/onc/onc_validator.h
@@ -217,9 +217,7 @@ class CHROMEOS_EXPORT Validator : public Mapper {
bool CertPatternInDevicePolicy(const std::string& cert_type);
- std::string WarningHeader();
- std::string ErrorHeader();
- std::string MessageHeader(bool is_error);
+ std::string MessageHeader();
const bool error_on_unknown_field_;
const bool error_on_wrong_recommended_;