Commit 38c96026 authored by pneubeck@chromium.org's avatar pneubeck@chromium.org

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
parent ba203410
......@@ -113,6 +113,7 @@
#include "chromeos/network/network_change_notifier_factory_chromeos.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state_handler.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
......@@ -325,8 +326,10 @@ class DBusServices {
GeolocationHandler::Initialize();
NetworkStateHandler::Initialize();
NetworkProfileHandler* profile_handler =
NetworkProfileHandler::Initialize();
NetworkConfigurationHandler::Initialize();
ManagedNetworkConfigurationHandler::Initialize();
ManagedNetworkConfigurationHandler::Initialize(profile_handler);
// Initialize the network change notifier for Chrome OS. The network
// change notifier starts to monitor changes from the power manager and
......@@ -370,6 +373,7 @@ class DBusServices {
ManagedNetworkConfigurationHandler::Shutdown();
NetworkConfigurationHandler::Shutdown();
NetworkProfileHandler::Shutdown();
NetworkStateHandler::Shutdown();
GeolocationHandler::Shutdown();
......
......@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "chrome/browser/extensions/extension_function_registry.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/api/networking_private.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_manager_client.h"
......@@ -100,7 +101,14 @@ bool NetworkingPrivateGetManagedPropertiesFunction::RunImpl() {
api::GetManagedProperties::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
// The profile of the requesting browser.
Profile* requesting_profile = profile();
// TODO(pneubeck): Use ProfileHelper to obtain the userhash, once it provides
// that functionality. crbug/238623.
std::string userhash = requesting_profile->GetPath().BaseName().value();
ManagedNetworkConfigurationHandler::Get()->GetManagedProperties(
userhash,
params->network_guid, // service path
base::Bind(&NetworkingPrivateGetManagedPropertiesFunction::Success,
this),
......
......@@ -4,6 +4,8 @@
#include "base/command_line.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/login/user.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/policy/network_configuration_updater.h"
#include "chrome/browser/extensions/extension_apitest.h"
#include "chrome/browser/policy/browser_policy_connector.h"
......@@ -13,6 +15,7 @@
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/cryptohome_client.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_profile_client.h"
......@@ -28,7 +31,18 @@ using testing::_;
namespace chromeos {
const char kUserProfilePath[] = "/profile/chronos/shill";
namespace {
const char kUser1ProfilePath[] = "/profile/user1/shill";
void AssignString(std::string* out,
DBusMethodCallStatus call_status,
const std::string& result) {
CHECK_EQ(call_status, DBUS_METHOD_CALL_SUCCESS);
*out = result;
}
} // namespace
class ExtensionNetworkingPrivateApiTest : public ExtensionApiTest {
public:
......@@ -38,6 +52,14 @@ class ExtensionNetworkingPrivateApiTest : public ExtensionApiTest {
command_line->AppendSwitchASCII(::switches::kWhitelistedExtensionID,
"epcifkihnkjgphfkloaaleeakhpmgdmn");
command_line->AppendSwitch(switches::kUseNewNetworkConfigurationHandlers);
// TODO(pneubeck): Remove the following hack, once the NetworkingPrivateAPI
// uses the ProfileHelper to obtain the userhash crbug/238623.
std::string login_user =
command_line->GetSwitchValueNative(switches::kLoginUser);
// Do the same as CryptohomeClientStubImpl::GetSanitizedUsername
std::string sanitized_user = login_user + "-profile";
command_line->AppendSwitchASCII(switches::kLoginProfile, sanitized_user);
}
bool RunNetworkingSubtest(const std::string& subtest) {
......@@ -55,28 +77,45 @@ class ExtensionNetworkingPrivateApiTest : public ExtensionApiTest {
ExtensionApiTest::SetUpInProcessBrowserTestFixture();
}
void InitializeSanitizedUsername() {
chromeos::UserManager* user_manager = chromeos::UserManager::Get();
chromeos::User* user = user_manager->GetActiveUser();
CHECK(user);
std::string userhash;
DBusThreadManager::Get()->GetCryptohomeClient()->GetSanitizedUsername(
user->email(),
base::Bind(&AssignString, &userhash_));
content::RunAllPendingInMessageLoop();
CHECK(!userhash_.empty());
}
virtual void SetUpOnMainThread() OVERRIDE {
ExtensionApiTest::SetUpOnMainThread();
content::RunAllPendingInMessageLoop();
InitializeSanitizedUsername();
ShillDeviceClient::TestInterface* device_test =
DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
ShillProfileClient::TestInterface* profile_test =
DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
profile_test->AddProfile(kUserProfilePath);
ShillServiceClient::TestInterface* service_test =
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
g_browser_process->browser_policy_connector()->
GetNetworkConfigurationUpdater()->OnUserPolicyInitialized(
false, "hash");
ShillDeviceClient::TestInterface* device_test =
DBusThreadManager::Get()->GetShillDeviceClient()->GetTestInterface();
false, userhash_);
device_test->ClearDevices();
service_test->ClearServices();
// Sends a notification about the added profile.
profile_test->AddProfile(kUser1ProfilePath, userhash_);
device_test->AddDevice("/device/stub_wifi_device1",
flimflam::kTypeWifi, "stub_wifi_device1");
device_test->AddDevice("/device/stub_cellular_device1",
flimflam::kTypeCellular, "stub_cellular_device1");
ShillServiceClient::TestInterface* service_test =
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface();
service_test->ClearServices();
const bool add_to_watchlist = true;
service_test->AddService("stub_ethernet", "eth0",
flimflam::kTypeEthernet, flimflam::kStateOnline,
......@@ -101,6 +140,10 @@ class ExtensionNetworkingPrivateApiTest : public ExtensionApiTest {
service_test->SetServiceProperty("stub_wifi2",
flimflam::kSignalStrengthProperty,
base::FundamentalValue(80));
service_test->SetServiceProperty("stub_wifi2",
flimflam::kProfileProperty,
base::StringValue(kUser1ProfilePath));
profile_test->AddService("stub_wifi2");
service_test->AddService("stub_cellular1", "cellular1",
flimflam::kTypeCellular, flimflam::kStateIdle,
......@@ -122,10 +165,13 @@ class ExtensionNetworkingPrivateApiTest : public ExtensionApiTest {
flimflam::kTypeVPN,
flimflam::kStateOnline,
add_to_watchlist);
content::RunAllPendingInMessageLoop();
}
protected:
policy::MockConfigurationPolicyProvider provider_;
std::string userhash_;
};
// Place each subtest into a separate browser test so that the stub networking
......@@ -190,25 +236,19 @@ IN_PROC_BROWSER_TEST_F(ExtensionNetworkingPrivateApiTest,
const std::string uidata_blob =
"{ \"user_settings\": {"
" \"WiFi\": {"
" \"Passphrase\": \"top secret\" }"
" \"Passphrase\": \"FAKE_CREDENTIAL_VPaJDV9x\" }"
" }"
"}";
service_test->SetServiceProperty("stub_wifi2",
flimflam::kGuidProperty,
base::StringValue("stub_wifi2"));
service_test->SetServiceProperty("stub_wifi2",
flimflam::kUIDataProperty,
base::StringValue(uidata_blob));
service_test->SetServiceProperty("stub_wifi2",
flimflam::kProfileProperty,
base::StringValue(kUserProfilePath));
service_test->SetServiceProperty("stub_wifi2",
flimflam::kAutoConnectProperty,
base::FundamentalValue(false));
ShillProfileClient::TestInterface* profile_test =
DBusThreadManager::Get()->GetShillProfileClient()->GetTestInterface();
// Update the profile entry.
profile_test->AddService("stub_wifi2");
content::RunAllPendingInMessageLoop();
......
......@@ -50,6 +50,7 @@ void NetworkConfigurationUpdaterImpl::OnUserPolicyInitialized(
bool allow_trusted_certs_from_policy,
const std::string& hashed_username) {
VLOG(1) << "User policy initialized.";
hashed_username_ = hashed_username;
if (allow_trusted_certs_from_policy)
SetAllowTrustedCertsFromPolicy();
ApplyNetworkConfiguration(chromeos::onc::ONC_SOURCE_USER_POLICY);
......@@ -93,7 +94,9 @@ void NetworkConfigurationUpdaterImpl::ApplyNetworkConfiguration(
ParseAndValidateOncForImport(
onc_blob, onc_source, "", &network_configs, &certificates);
network_config_handler_->SetPolicy(onc_source, network_configs);
std::string userhash = onc_source == chromeos::onc::ONC_SOURCE_USER_POLICY ?
hashed_username_ : std::string();
network_config_handler_->SetPolicy(onc_source, userhash, network_configs);
scoped_ptr<net::CertificateList> web_trust_certs(new net::CertificateList);
certificate_handler_->ImportCertificates(
......
......@@ -25,8 +25,6 @@ class PolicyMap;
// This implementation pushes policies to the
// ManagedNetworkConfigurationHandler. User policies are only pushed after
// OnUserPolicyInitialized() was called.
// TODO(pneubeck): Certificates are not implemented yet, they are silently
// ignored.
class NetworkConfigurationUpdaterImpl : public NetworkConfigurationUpdater {
public:
NetworkConfigurationUpdaterImpl(
......@@ -58,6 +56,9 @@ class NetworkConfigurationUpdaterImpl : public NetworkConfigurationUpdater {
// Pointer to the global singleton or mock provided to the constructor.
chromeos::ManagedNetworkConfigurationHandler* network_config_handler_;
// User hash of the user that the user policy applies to.
std::string hashed_username_;
scoped_ptr<chromeos::CertificateHandler> certificate_handler_;
DISALLOW_COPY_AND_ASSIGN(NetworkConfigurationUpdaterImpl);
......
......@@ -253,6 +253,11 @@
'network/network_handler_callbacks.h',
'network/network_ip_config.cc',
'network/network_ip_config.h',
'network/network_profile.cc',
'network/network_profile.h',
'network/network_profile_handler.cc',
'network/network_profile_handler.h',
'network/network_profile_observer.h',
'network/network_sms_handler.cc',
'network/network_sms_handler.h',
'network/network_state.cc',
......@@ -508,6 +513,7 @@
'network/network_change_notifier_chromeos_unittest.cc',
'network/network_configuration_handler_unittest.cc',
'network/network_event_log_unittest.cc',
'network/network_profile_handler_stub.h',
'network/network_sms_handler_unittest.cc',
'network/network_state_handler_unittest.cc',
'network/network_state_unittest.cc',
......
......@@ -56,6 +56,12 @@ class CHROMEOS_EXPORT ShillManagerClient {
virtual void AddGeoNetwork(const std::string& technology,
const base::DictionaryValue& network) = 0;
// Does not create an actual profile in the ProfileClient but update the
// profiles list and sends a notification to observers. This should only be
// called by the ProfileStub. In all other cases, use
// ShillProfileClient::TestInterface::AddProfile.
virtual void AddProfile(const std::string& profile_path) = 0;
// Used to reset all properties; does not notify observers.
virtual void ClearProperties() = 0;
......
......@@ -316,12 +316,15 @@ void ShillManagerClientStub::RemoveDevice(const std::string& device_path) {
}
void ShillManagerClientStub::ClearDevices() {
stub_properties_.Remove(flimflam::kDevicesProperty, NULL);
GetListProperty(flimflam::kDevicesProperty)->Clear();
CallNotifyObserversPropertyChanged(flimflam::kDevicesProperty, 0);
}
void ShillManagerClientStub::ClearServices() {
stub_properties_.Remove(flimflam::kServicesProperty, NULL);
stub_properties_.Remove(flimflam::kServiceWatchListProperty, NULL);
GetListProperty(flimflam::kServicesProperty)->Clear();
GetListProperty(flimflam::kServiceWatchListProperty)->Clear();
CallNotifyObserversPropertyChanged(flimflam::kServicesProperty, 0);
CallNotifyObserversPropertyChanged(flimflam::kServiceWatchListProperty, 0);
}
void ShillManagerClientStub::AddService(const std::string& service_path,
......@@ -426,6 +429,14 @@ void ShillManagerClientStub::AddGeoNetwork(
list_value->Append(network.DeepCopy());
}
void ShillManagerClientStub::AddProfile(const std::string& profile_path) {
const char* key = flimflam::kProfilesProperty;
if (GetListProperty(key)->AppendIfNotPresent(
new base::StringValue(profile_path))) {
CallNotifyObserversPropertyChanged(key, 0);
}
}
void ShillManagerClientStub::AddServiceToWatchList(
const std::string& service_path) {
if (GetListProperty(
......
......@@ -95,6 +95,7 @@ class ShillManagerClientStub : public ShillManagerClient,
bool initializing) OVERRIDE;
virtual void AddGeoNetwork(const std::string& technology,
const base::DictionaryValue& network) OVERRIDE;
virtual void AddProfile(const std::string& profile_path) OVERRIDE;
virtual void ClearProperties() OVERRIDE;
private:
......
......@@ -8,6 +8,7 @@
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_profile_client_stub.h"
#include "chromeos/dbus/shill_property_changed_observer.h"
#include "dbus/bus.h"
......
......@@ -45,7 +45,8 @@ class CHROMEOS_EXPORT ShillProfileClient {
// GetTestInterface(), only implemented in the stub implementation.
class TestInterface {
public:
virtual void AddProfile(const std::string& profile_path) = 0;
virtual void AddProfile(const std::string& profile_path,
const std::string& userhash) = 0;
virtual void AddEntry(const std::string& profile_path,
const std::string& entry_path,
const base::DictionaryValue& properties) = 0;
......@@ -60,7 +61,7 @@ class CHROMEOS_EXPORT ShillProfileClient {
// Factory function, creates a new instance which is owned by the caller.
// For normal usage, access the singleton via DBusThreadManager::Get().
static ShillProfileClient* Create(DBusClientImplementationType type,
dbus::Bus* bus);
dbus::Bus* bus);
// Adds a property changed |observer| for the profile at |profile_path|.
virtual void AddPropertyChangedObserver(
......
......@@ -10,6 +10,7 @@
#include "base/stl_util.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_property_changed_observer.h"
#include "chromeos/dbus/shill_service_client.h"
#include "dbus/bus.h"
......@@ -20,18 +21,15 @@
namespace chromeos {
struct ShillProfileClientStub::ProfileProperties {
base::DictionaryValue entries;
base::DictionaryValue properties;
};
namespace {
const char kSharedProfilePath[] = "/profile/default";
void PassEmptyDictionary(
const ShillProfileClient::DictionaryValueCallbackWithoutStatus& callback) {
base::DictionaryValue dictionary;
if (callback.is_null())
return;
callback.Run(dictionary);
}
void PassDictionary(
const ShillProfileClient::DictionaryValueCallbackWithoutStatus& callback,
const base::DictionaryValue* dictionary) {
......@@ -40,24 +38,14 @@ void PassDictionary(
callback.Run(*dictionary);
}
base::DictionaryValue* GetOrCreateDictionary(const std::string& key,
base::DictionaryValue* dict) {
base::DictionaryValue* nested_dict = NULL;
dict->GetDictionaryWithoutPathExpansion(key, &nested_dict);
if (!nested_dict) {
nested_dict = new base::DictionaryValue;
dict->SetWithoutPathExpansion(key, nested_dict);
}
return nested_dict;
}
} // namespace
ShillProfileClientStub::ShillProfileClientStub() {
AddProfile(kSharedProfilePath);
AddProfile(kSharedProfilePath, std::string());
}
ShillProfileClientStub::~ShillProfileClientStub() {
STLDeleteValues(&profiles_);
}
void ShillProfileClientStub::AddPropertyChangedObserver(
......@@ -74,14 +62,14 @@ void ShillProfileClientStub::GetProperties(
const dbus::ObjectPath& profile_path,
const DictionaryValueCallbackWithoutStatus& callback,
const ErrorCallback& error_callback) {
base::DictionaryValue* profile = GetProfile(profile_path, error_callback);
ProfileProperties* profile = GetProfile(profile_path, error_callback);
if (!profile)
return;
scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue);
scoped_ptr<base::DictionaryValue> properties(profile->properties.DeepCopy());
base::ListValue* entry_paths = new base::ListValue;
properties->SetWithoutPathExpansion(flimflam::kEntriesProperty, entry_paths);
for (base::DictionaryValue::Iterator it(*profile); !it.IsAtEnd();
for (base::DictionaryValue::Iterator it(profile->entries); !it.IsAtEnd();
it.Advance()) {
entry_paths->AppendString(it.key());
}
......@@ -96,12 +84,12 @@ void ShillProfileClientStub::GetEntry(
const std::string& entry_path,
const DictionaryValueCallbackWithoutStatus& callback,
const ErrorCallback& error_callback) {
base::DictionaryValue* profile = GetProfile(profile_path, error_callback);
ProfileProperties* profile = GetProfile(profile_path, error_callback);
if (!profile)
return;
base::DictionaryValue* entry = NULL;
profile->GetDictionaryWithoutPathExpansion(entry_path, &entry);
profile->entries.GetDictionaryWithoutPathExpansion(entry_path, &entry);
if (!entry) {
error_callback.Run("Error.InvalidProfileEntry", "Invalid profile entry");
return;
......@@ -116,11 +104,11 @@ void ShillProfileClientStub::DeleteEntry(const dbus::ObjectPath& profile_path,
const std::string& entry_path,
const base::Closure& callback,
const ErrorCallback& error_callback) {
base::DictionaryValue* profile = GetProfile(profile_path, error_callback);
ProfileProperties* profile = GetProfile(profile_path, error_callback);
if (!profile)
return;
if (!profile->RemoveWithoutPathExpansion(entry_path, NULL)) {
if (!profile->entries.RemoveWithoutPathExpansion(entry_path, NULL)) {
error_callback.Run("Error.InvalidProfileEntry", "Invalid profile entry");
return;
}
......@@ -132,18 +120,27 @@ ShillProfileClient::TestInterface* ShillProfileClientStub::GetTestInterface() {
return this;
}
void ShillProfileClientStub::AddProfile(const std::string& profile_path) {
profile_entries_.SetWithoutPathExpansion(profile_path,
new base::DictionaryValue);
void ShillProfileClientStub::AddProfile(const std::string& profile_path,
const std::string& userhash) {
if (GetProfile(dbus::ObjectPath(profile_path), ErrorCallback()))
return;
ProfileProperties* profile = new ProfileProperties;
profile->properties.SetStringWithoutPathExpansion(shill::kUserHashProperty,
userhash);
profiles_[profile_path] = profile;
DBusThreadManager::Get()->GetShillManagerClient()->GetTestInterface()->
AddProfile(profile_path);
}
void ShillProfileClientStub::AddEntry(const std::string& profile_path,
const std::string& entry_path,
const base::DictionaryValue& properties) {
base::DictionaryValue* profile = GetOrCreateDictionary(profile_path,
&profile_entries_);
profile->SetWithoutPathExpansion(entry_path,
properties.DeepCopy());
ProfileProperties* profile = GetProfile(dbus::ObjectPath(profile_path),
ErrorCallback());
DCHECK(profile);
profile->entries.SetWithoutPathExpansion(entry_path,
properties.DeepCopy());
}
bool ShillProfileClientStub::AddService(const std::string& service_path) {
......@@ -164,15 +161,17 @@ bool ShillProfileClientStub::AddService(const std::string& service_path) {
return true;
}
base::DictionaryValue* ShillProfileClientStub::GetProfile(
ShillProfileClientStub::ProfileProperties* ShillProfileClientStub::GetProfile(
const dbus::ObjectPath& profile_path,
const ErrorCallback& error_callback) {
base::DictionaryValue* profile = NULL;
profile_entries_.GetDictionaryWithoutPathExpansion(profile_path.value(),
&profile);
if (!profile)
error_callback.Run("Error.InvalidProfile", "Invalid profile");
return profile;
ProfileMap::const_iterator found = profiles_.find(profile_path.value());
if (found == profiles_.end()) {
if (!error_callback.is_null())
error_callback.Run("Error.InvalidProfile", "Invalid profile");
return NULL;
}
return found->second;
}
} // namespace chromeos
......@@ -5,9 +5,11 @@
#ifndef CHROMEOS_DBUS_SHILL_PROFILE_CLIENT_STUB_H_
#define CHROMEOS_DBUS_SHILL_PROFILE_CLIENT_STUB_H_
#include <map>
#include <string>
#include "base/basictypes.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_profile_client.h"
namespace chromeos {
......@@ -41,18 +43,23 @@ class ShillProfileClientStub : public ShillProfileClient,
virtual ShillProfileClient::TestInterface* GetTestInterface() OVERRIDE;
// ShillProfileClient::TestInterface overrides.
virtual void AddProfile(const std::string& profile_path) OVERRIDE;
virtual void AddProfile(const std::string& profile_path,
const std::string& userhash) OVERRIDE;
virtual void AddEntry(const std::string& profile_path,
const std::string& entry_path,
const base::DictionaryValue& properties) OVERRIDE;
virtual bool AddService(const std::string& service_path) OVERRIDE;
private:
base::DictionaryValue* GetProfile(const dbus::ObjectPath& profile_path,
const ErrorCallback& error_callback);
struct ProfileProperties;
typedef std::map<std::string, ProfileProperties*> ProfileMap;
// This maps profile path -> entry path -> Shill properties.
base::DictionaryValue profile_entries_;
ProfileProperties* GetProfile(const dbus::ObjectPath& profile_path,
const ErrorCallback& error_callback);
// The values are owned by this class and are explicitly destroyed where
// necessary.
ProfileMap profiles_;
DISALLOW_COPY_AND_ASSIGN(ShillProfileClientStub);
};
......
......@@ -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_;
......
// 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
// 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_
// 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
// 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_
// 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_
// 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_
......@@ -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;
......
......@@ -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_;
......
......@@ -2,7 +2,7 @@
"GUID": "policy_wifi1",
"Mode": "managed",
"Passphrase": "policy's passphrase",
"Profile": "/profile/chronos/shill",
"Profile": "/profile/user1/shill",
"SSID": "wifi1",
"Security": "psk",
"Type": "wifi",
......
......@@ -2,7 +2,7 @@
"GUID": "policy_wifi1",
"Mode": "managed",
"Passphrase": "user's passphrase",
"Profile": "/profile/chronos/shill",
"Profile": "/profile/user1/shill",
"SSID": "wifi1",
"Security": "psk",
"Type": "wifi",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment