summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-15 08:47:32 +0000
committerpneubeck@chromium.org <pneubeck@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-15 08:47:32 +0000
commitc72ace84f51f1cfddb70beb4144fb0ec76b5f6a4 (patch)
tree00ead57531d1c9c413986c1ac6ba5bc80d1bc5f8
parent67101909b20c061b7ef1fde0b6f556037ea7f5c3 (diff)
downloadchromium_src-c72ace84f51f1cfddb70beb4144fb0ec76b5f6a4.zip
chromium_src-c72ace84f51f1cfddb70beb4144fb0ec76b5f6a4.tar.gz
chromium_src-c72ace84f51f1cfddb70beb4144fb0ec76b5f6a4.tar.bz2
Disconnect from unmanaged and shared network on login.
If the policy to prevent unmanaged and shared networks to autoconnect is enabled, then disconnect all such networks except Ethernet networks. This is enforced once after a user logs in 1) to allow mananged networks to autoconnect and 2) to prevent a previous user from foisting a network on the new user. BUG=365379 Review URL: https://codereview.chromium.org/280573002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270644 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chromeos/dbus/fake_shill_manager_client.cc14
-rw-r--r--chromeos/dbus/fake_shill_manager_client.h5
-rw-r--r--chromeos/dbus/shill_manager_client.h3
-rw-r--r--chromeos/network/client_cert_resolver_unittest.cc1
-rw-r--r--chromeos/network/managed_network_configuration_handler_impl.cc21
-rw-r--r--chromeos/network/managed_network_configuration_handler_impl.h3
-rw-r--r--chromeos/network/network_connection_handler.cc126
-rw-r--r--chromeos/network/network_connection_handler.h36
-rw-r--r--chromeos/network/network_connection_handler_unittest.cc161
-rw-r--r--chromeos/network/network_handler.cc6
-rw-r--r--chromeos/network/network_policy_observer.h8
-rw-r--r--chromeos/network/network_profile_handler.h1
12 files changed, 335 insertions, 50 deletions
diff --git a/chromeos/dbus/fake_shill_manager_client.cc b/chromeos/dbus/fake_shill_manager_client.cc
index 117f850..f7fb7f7 100644
--- a/chromeos/dbus/fake_shill_manager_client.cc
+++ b/chromeos/dbus/fake_shill_manager_client.cc
@@ -332,6 +332,13 @@ void FakeShillManagerClient::VerifyAndEncryptData(
void FakeShillManagerClient::ConnectToBestServices(
const base::Closure& callback,
const ErrorCallback& error_callback) {
+ if (best_service_.empty()) {
+ VLOG(1) << "No 'best' service set.";
+ return;
+ }
+
+ DBusThreadManager::Get()->GetShillServiceClient()->Connect(
+ dbus::ObjectPath(best_service_), callback, error_callback);
}
ShillManagerClient::TestInterface* FakeShillManagerClient::GetTestInterface() {
@@ -547,6 +554,11 @@ int FakeShillManagerClient::GetInteractiveDelay() const {
return interactive_delay_;
}
+void FakeShillManagerClient::SetBestServiceToConnect(
+ const std::string& service_path) {
+ best_service_ = service_path;
+}
+
void FakeShillManagerClient::SetupDefaultEnvironment() {
DBusThreadManager* dbus_manager = DBusThreadManager::Get();
ShillServiceClient::TestInterface* services =
@@ -898,8 +910,6 @@ base::ListValue* FakeShillManagerClient::GetEnabledServiceList(
LOG(ERROR) << "Properties not found for service: " << service_path;
continue;
}
- std::string name;
- properties->GetString(shill::kNameProperty, &name);
std::string type;
properties->GetString(shill::kTypeProperty, &type);
if (TechnologyEnabled(type))
diff --git a/chromeos/dbus/fake_shill_manager_client.h b/chromeos/dbus/fake_shill_manager_client.h
index 339e0d1..b235f93 100644
--- a/chromeos/dbus/fake_shill_manager_client.h
+++ b/chromeos/dbus/fake_shill_manager_client.h
@@ -103,6 +103,8 @@ class CHROMEOS_EXPORT FakeShillManagerClient
virtual void SortManagerServices() OVERRIDE;
virtual void SetupDefaultEnvironment() OVERRIDE;
virtual int GetInteractiveDelay() const OVERRIDE;
+ virtual void SetBestServiceToConnect(
+ const std::string& service_path) OVERRIDE;
private:
void AddServiceToWatchList(const std::string& service_path);
@@ -151,6 +153,9 @@ class CHROMEOS_EXPORT FakeShillManagerClient
// Track the default service for signaling Manager.DefaultService.
std::string default_service_;
+ // 'Best' service to connect to on ConnectToBestServices() calls.
+ std::string best_service_;
+
DISALLOW_COPY_AND_ASSIGN(FakeShillManagerClient);
};
diff --git a/chromeos/dbus/shill_manager_client.h b/chromeos/dbus/shill_manager_client.h
index d64772b..e9fc6b0 100644
--- a/chromeos/dbus/shill_manager_client.h
+++ b/chromeos/dbus/shill_manager_client.h
@@ -86,6 +86,9 @@ class CHROMEOS_EXPORT ShillManagerClient : public DBusClient {
// Returns the interactive delay specified on the command line, 0 for none.
virtual int GetInteractiveDelay() const = 0;
+ // Sets the 'best' service to connect to on a ConnectToBestServices call.
+ virtual void SetBestServiceToConnect(const std::string& service_path) = 0;
+
protected:
virtual ~TestInterface() {}
};
diff --git a/chromeos/network/client_cert_resolver_unittest.cc b/chromeos/network/client_cert_resolver_unittest.cc
index b3f51ca..2905fbd 100644
--- a/chromeos/network/client_cert_resolver_unittest.cc
+++ b/chromeos/network/client_cert_resolver_unittest.cc
@@ -21,6 +21,7 @@
#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/tpm_token_loader.h"
+#include "components/onc/onc_constants.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "net/base/crypto_module.h"
diff --git a/chromeos/network/managed_network_configuration_handler_impl.cc b/chromeos/network/managed_network_configuration_handler_impl.cc
index 5415a76..bf7e191 100644
--- a/chromeos/network/managed_network_configuration_handler_impl.cc
+++ b/chromeos/network/managed_network_configuration_handler_impl.cc
@@ -406,19 +406,21 @@ void ManagedNetworkConfigurationHandlerImpl::SetPolicy(
const NetworkProfile* profile =
network_profile_handler_->GetProfileForUserhash(userhash);
- if (!profile) {
+ if (profile) {
+ scoped_refptr<PolicyApplicator> applicator =
+ new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(),
+ *profile,
+ policies->per_network_config,
+ policies->global_network_config,
+ &modified_policies);
+ applicator->Run();
+ } else {
VLOG(1) << "The relevant Shill profile isn't initialized yet, postponing "
<< "policy application.";
- return;
+ // See OnProfileAdded.
}
- scoped_refptr<PolicyApplicator> applicator =
- new PolicyApplicator(weak_ptr_factory_.GetWeakPtr(),
- *profile,
- policies->per_network_config,
- policies->global_network_config,
- &modified_policies);
- applicator->Run();
+ FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_, PolicyChanged(userhash));
}
void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded(
@@ -429,6 +431,7 @@ void ManagedNetworkConfigurationHandlerImpl::OnProfileAdded(
if (!policies) {
VLOG(1) << "The relevant policy is not initialized, "
<< "postponing policy application.";
+ // See SetPolicy.
return;
}
diff --git a/chromeos/network/managed_network_configuration_handler_impl.h b/chromeos/network/managed_network_configuration_handler_impl.h
index 3580b6f..4ea2421 100644
--- a/chromeos/network/managed_network_configuration_handler_impl.h
+++ b/chromeos/network/managed_network_configuration_handler_impl.h
@@ -102,8 +102,9 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandlerImpl
private:
friend class ClientCertResolverTest;
- friend class NetworkHandler;
friend class ManagedNetworkConfigurationHandlerTest;
+ friend class NetworkConnectionHandlerTest;
+ friend class NetworkHandler;
struct Policies;
typedef std::map<std::string, linked_ptr<Policies> > UserToPoliciesMap;
diff --git a/chromeos/network/network_connection_handler.cc b/chromeos/network/network_connection_handler.cc
index f01cbe6..380a052 100644
--- a/chromeos/network/network_connection_handler.cc
+++ b/chromeos/network/network_connection_handler.cc
@@ -14,6 +14,7 @@
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_service_client.h"
#include "chromeos/network/client_cert_util.h"
+#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_handler_callbacks.h"
@@ -149,9 +150,11 @@ struct NetworkConnectionHandler::ConnectRequest {
NetworkConnectionHandler::NetworkConnectionHandler()
: cert_loader_(NULL),
network_state_handler_(NULL),
- network_configuration_handler_(NULL),
+ configuration_handler_(NULL),
logged_in_(false),
- certificates_loaded_(false) {
+ certificates_loaded_(false),
+ applied_autoconnect_policy_(false),
+ requested_connect_to_best_network_(false) {
}
NetworkConnectionHandler::~NetworkConnectionHandler() {
@@ -165,12 +168,10 @@ NetworkConnectionHandler::~NetworkConnectionHandler() {
void NetworkConnectionHandler::Init(
NetworkStateHandler* network_state_handler,
- NetworkConfigurationHandler* network_configuration_handler) {
- if (LoginState::IsInitialized()) {
+ NetworkConfigurationHandler* network_configuration_handler,
+ ManagedNetworkConfigurationHandler* managed_network_configuration_handler) {
+ if (LoginState::IsInitialized())
LoginState::Get()->AddObserver(this);
- logged_in_ = LoginState::Get()->IsUserLoggedIn();
- logged_in_time_ = base::TimeTicks::Now();
- }
if (CertLoader::IsInitialized()) {
cert_loader_ = CertLoader::Get();
@@ -189,15 +190,30 @@ void NetworkConnectionHandler::Init(
network_state_handler_ = network_state_handler;
network_state_handler_->AddObserver(this, FROM_HERE);
}
- network_configuration_handler_ = network_configuration_handler;
+ configuration_handler_ = network_configuration_handler;
+
+ if (managed_network_configuration_handler) {
+ managed_configuration_handler_ = managed_network_configuration_handler;
+ managed_configuration_handler_->AddObserver(this);
+ }
+
+ // After this point, the NetworkConnectionHandler is fully initialized (all
+ // handler references set, observers registered, ...).
+
+ if (LoginState::IsInitialized())
+ LoggedInStateChanged();
}
void NetworkConnectionHandler::LoggedInStateChanged() {
- if (LoginState::Get()->IsUserLoggedIn()) {
- logged_in_ = true;
- NET_LOG_EVENT("Logged In", "");
- logged_in_time_ = base::TimeTicks::Now();
- }
+ LoginState* login_state = LoginState::Get();
+ if (logged_in_ || !login_state->IsUserLoggedIn())
+ return;
+
+ NET_LOG_EVENT("Logged In", "");
+ logged_in_ = true;
+ logged_in_time_ = base::TimeTicks::Now();
+
+ DisconnectIfPolicyRequires();
}
void NetworkConnectionHandler::OnCertificatesLoaded(
@@ -208,11 +224,19 @@ void NetworkConnectionHandler::OnCertificatesLoaded(
if (queued_connect_) {
ConnectToQueuedNetwork();
} else if (initial_load) {
- // Once certificates have loaded, connect to the "best" available network.
- network_state_handler_->ConnectToBestWifiNetwork();
+ // Connecting to the "best" available network requires certificates to be
+ // loaded. Try to connect now.
+ ConnectToBestNetworkAfterLogin();
}
}
+void NetworkConnectionHandler::PolicyChanged(const std::string& userhash) {
+ // Ignore user policies.
+ if (!userhash.empty())
+ return;
+ DisconnectIfPolicyRequires();
+}
+
void NetworkConnectionHandler::ConnectToNetwork(
const std::string& service_path,
const base::Closure& success_callback,
@@ -287,7 +311,7 @@ void NetworkConnectionHandler::ConnectToNetwork(
// Request additional properties to check. VerifyConfiguredAndConnect will
// use only these properties, not cached properties, to ensure that they
// are up to date after any recent configuration.
- network_configuration_handler_->GetProperties(
+ configuration_handler_->GetProperties(
service_path,
base::Bind(&NetworkConnectionHandler::VerifyConfiguredAndConnect,
AsWeakPtr(), check_error_state),
@@ -495,7 +519,7 @@ void NetworkConnectionHandler::VerifyConfiguredAndConnect(
if (!config_properties.empty()) {
NET_LOG_EVENT("Configuring Network", service_path);
- network_configuration_handler_->SetProperties(
+ configuration_handler_->SetProperties(
service_path,
config_properties,
base::Bind(&NetworkConnectionHandler::CallShillConnect,
@@ -662,8 +686,9 @@ void NetworkConnectionHandler::CheckPendingRequest(
NET_LOG_EVENT("Connect Request Succeeded", service_path);
if (!request->profile_path.empty()) {
// If a profile path was specified, set it on a successful connection.
- network_configuration_handler_->SetNetworkProfile(
- service_path, request->profile_path,
+ configuration_handler_->SetNetworkProfile(
+ service_path,
+ request->profile_path,
base::Bind(&base::DoNothing),
chromeos::network_handler::ErrorCallback());
}
@@ -759,4 +784,67 @@ void NetworkConnectionHandler::HandleShillDisconnectSuccess(
success_callback.Run();
}
+void NetworkConnectionHandler::ConnectToBestNetworkAfterLogin() {
+ if (requested_connect_to_best_network_ || !applied_autoconnect_policy_ ||
+ !certificates_loaded_) {
+ return;
+ }
+
+ requested_connect_to_best_network_ = true;
+ network_state_handler_->ConnectToBestWifiNetwork();
+}
+
+void NetworkConnectionHandler::DisconnectIfPolicyRequires() {
+ if (applied_autoconnect_policy_ || !LoginState::Get()->IsUserLoggedIn())
+ return;
+
+ const base::DictionaryValue* global_network_config =
+ managed_configuration_handler_->GetGlobalConfigFromPolicy(std::string());
+ if (!global_network_config)
+ return;
+
+ applied_autoconnect_policy_ = true;
+
+ bool only_policy_autoconnect = false;
+ global_network_config->GetBooleanWithoutPathExpansion(
+ ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
+ &only_policy_autoconnect);
+
+ if (!only_policy_autoconnect)
+ return;
+
+ NET_LOG_DEBUG("DisconnectIfPolicyRequires",
+ "Disconnecting unmanaged and shared networks if any exist.");
+
+ // Get the list of unmanaged & shared networks that are connected or
+ // connecting.
+ NetworkStateHandler::NetworkStateList networks;
+ network_state_handler_->GetNetworkListByType(NetworkTypePattern::Wireless(),
+ &networks);
+ for (NetworkStateHandler::NetworkStateList::const_iterator it =
+ networks.begin();
+ it != networks.end();
+ ++it) {
+ const NetworkState* network = *it;
+ if (!(network->IsConnectingState() || network->IsConnectedState()))
+ break; // Connected and connecting networks are listed first.
+
+ if (network->IsPrivate())
+ continue;
+
+ const bool network_is_policy_managed =
+ !network->profile_path().empty() && !network->guid().empty() &&
+ managed_configuration_handler_->FindPolicyByGuidAndProfile(
+ network->guid(), network->profile_path());
+ if (network_is_policy_managed)
+ continue;
+
+ NET_LOG_EVENT("Disconnect Forced by Policy", network->path());
+ CallShillDisconnect(
+ network->path(), base::Closure(), network_handler::ErrorCallback());
+ }
+
+ ConnectToBestNetworkAfterLogin();
+}
+
} // namespace chromeos
diff --git a/chromeos/network/network_connection_handler.h b/chromeos/network/network_connection_handler.h
index b8e9a84..77db56f 100644
--- a/chromeos/network/network_connection_handler.h
+++ b/chromeos/network/network_connection_handler.h
@@ -19,6 +19,7 @@
#include "chromeos/login/login_state.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_handler_callbacks.h"
+#include "chromeos/network/network_policy_observer.h"
#include "chromeos/network/network_state_handler_observer.h"
namespace chromeos {
@@ -46,6 +47,7 @@ class CHROMEOS_EXPORT NetworkConnectionHandler
: public LoginState::Observer,
public CertLoader::Observer,
public NetworkStateHandlerObserver,
+ public NetworkPolicyObserver,
public base::SupportsWeakPtr<NetworkConnectionHandler> {
public:
// Constants for |error_name| from |error_callback| for Connect.
@@ -136,6 +138,9 @@ class CHROMEOS_EXPORT NetworkConnectionHandler
virtual void OnCertificatesLoaded(const net::CertificateList& cert_list,
bool initial_load) OVERRIDE;
+ // NetworkPolicyObserver
+ virtual void PolicyChanged(const std::string& userhash) OVERRIDE;
+
private:
friend class NetworkHandler;
friend class NetworkConnectionHandlerTest;
@@ -145,7 +150,9 @@ class CHROMEOS_EXPORT NetworkConnectionHandler
NetworkConnectionHandler();
void Init(NetworkStateHandler* network_state_handler,
- NetworkConfigurationHandler* network_configuration_handler);
+ NetworkConfigurationHandler* network_configuration_handler,
+ ManagedNetworkConfigurationHandler*
+ managed_network_configuration_handler);
ConnectRequest* GetPendingRequest(const std::string& service_path);
@@ -203,11 +210,28 @@ class CHROMEOS_EXPORT NetworkConnectionHandler
void HandleShillDisconnectSuccess(const std::string& service_path,
const base::Closure& success_callback);
+ // If the policy to prevent unmanaged & shared networks to autoconnect is
+ // enabled, then disconnect all such networks except wired networks. Does
+ // nothing on consecutive calls.
+ // This is enforced once after a user logs in 1) to allow mananged networks to
+ // autoconnect and 2) to prevent a previous user from foisting a network on
+ // the new user. Therefore, this function is called on startup, at login and
+ // when the device policy is changed.
+ void DisconnectIfPolicyRequires();
+
+ // Requests a connect to the 'best' available network once after login and
+ // after any disconnect required by policy is executed (see
+ // DisconnectIfPolicyRequires()). To include networks with client
+ // certificates, no request is sent until certificates are loaded. Therefore,
+ // this function is called on the initial certificate load and by
+ // DisconnectIfPolicyRequires().
+ void ConnectToBestNetworkAfterLogin();
// Local references to the associated handler instances.
CertLoader* cert_loader_;
NetworkStateHandler* network_state_handler_;
- NetworkConfigurationHandler* network_configuration_handler_;
+ NetworkConfigurationHandler* configuration_handler_;
+ ManagedNetworkConfigurationHandler* managed_configuration_handler_;
// Map of pending connect requests, used to prevent repeated attempts while
// waiting for Shill and to trigger callbacks on eventual success or failure.
@@ -219,6 +243,14 @@ class CHROMEOS_EXPORT NetworkConnectionHandler
bool certificates_loaded_;
base::TimeTicks logged_in_time_;
+ // Whether the autoconnect policy was applied already, see
+ // DisconnectIfPolicyRequires().
+ bool applied_autoconnect_policy_;
+
+ // Whether the handler already requested a 'ConnectToBestNetwork' after login,
+ // see ConnectToBestNetworkAfterLogin().
+ bool requested_connect_to_best_network_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkConnectionHandler);
};
diff --git a/chromeos/network/network_connection_handler_unittest.cc b/chromeos/network/network_connection_handler_unittest.cc
index 8725980..a9b5707 100644
--- a/chromeos/network/network_connection_handler_unittest.cc
+++ b/chromeos/network/network_connection_handler_unittest.cc
@@ -7,18 +7,24 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
+#include "base/json/json_reader.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "chromeos/cert_loader.h"
-#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_dbus_thread_manager.h"
+#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_manager_client.h"
+#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/dbus/shill_service_client.h"
+#include "chromeos/network/managed_network_configuration_handler_impl.h"
#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_profile_handler.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/onc/onc_utils.h"
#include "chromeos/tpm_token_loader.h"
+#include "components/onc/onc_constants.h"
#include "crypto/nss_util.h"
#include "crypto/nss_util_internal.h"
#include "net/base/net_errors.h"
@@ -46,8 +52,11 @@ namespace chromeos {
class NetworkConnectionHandlerTest : public testing::Test {
public:
- NetworkConnectionHandlerTest() : user_("userhash") {
- }
+ NetworkConnectionHandlerTest()
+ : user_("userhash"),
+ test_manager_client_(NULL),
+ test_service_client_(NULL) {}
+
virtual ~NetworkConnectionHandlerTest() {
}
@@ -68,26 +77,50 @@ class NetworkConnectionHandlerTest : public testing::Test {
CertLoader* cert_loader = CertLoader::Get();
cert_loader->force_hardware_backed_for_test();
- // Initialize DBusThreadManager with a stub implementation.
- DBusThreadManager::InitializeWithStub();
- base::RunLoop().RunUntilIdle();
- DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()
- ->ClearServices();
+ FakeDBusThreadManager* dbus_manager = new FakeDBusThreadManager;
+ dbus_manager->SetFakeClients();
+ DBusThreadManager::InitializeForTesting(dbus_manager);
+ test_manager_client_ =
+ dbus_manager->GetShillManagerClient()->GetTestInterface();
+ test_service_client_ =
+ dbus_manager->GetShillServiceClient()->GetTestInterface();
+
+ test_manager_client_->AddTechnology(shill::kTypeWifi, true /* enabled */);
+ dbus_manager->GetShillDeviceClient()->GetTestInterface()->AddDevice(
+ "/device/wifi1", shill::kTypeWifi, "wifi_device1");
+ test_manager_client_->AddTechnology(shill::kTypeCellular,
+ true /* enabled */);
+ dbus_manager->GetShillProfileClient()->GetTestInterface()->AddProfile(
+ "profile_path", std::string() /* shared profile */);
+
base::RunLoop().RunUntilIdle();
LoginState::Initialize();
network_state_handler_.reset(NetworkStateHandler::InitializeForTest());
- network_configuration_handler_.reset(
+ network_config_handler_.reset(
NetworkConfigurationHandler::InitializeForTest(
network_state_handler_.get()));
+ network_profile_handler_.reset(new NetworkProfileHandler());
+ network_profile_handler_->Init(network_state_handler_.get());
+
+ managed_config_handler_.reset(new ManagedNetworkConfigurationHandlerImpl());
+ managed_config_handler_->Init(network_state_handler_.get(),
+ network_profile_handler_.get(),
+ network_config_handler_.get());
+
network_connection_handler_.reset(new NetworkConnectionHandler);
network_connection_handler_->Init(network_state_handler_.get(),
- network_configuration_handler_.get());
+ network_config_handler_.get(),
+ managed_config_handler_.get());
+
+ base::RunLoop().RunUntilIdle();
}
virtual void TearDown() OVERRIDE {
+ managed_config_handler_.reset();
+ network_profile_handler_.reset();
network_connection_handler_.reset();
- network_configuration_handler_.reset();
+ network_config_handler_.reset();
network_state_handler_.reset();
CertLoader::Shutdown();
TPMTokenLoader::Shutdown();
@@ -152,8 +185,7 @@ class NetworkConnectionHandlerTest : public testing::Test {
const std::string& key) {
std::string result;
const base::DictionaryValue* properties =
- DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
- GetServiceProperties(service_path);
+ test_service_client_->GetServiceProperties(service_path);
if (properties)
properties->GetStringWithoutPathExpansion(key, &result);
return result;
@@ -164,6 +196,12 @@ class NetworkConnectionHandlerTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
+ void LoginToRegularUser() {
+ LoginState::Get()->SetLoggedInState(LoginState::LOGGED_IN_ACTIVE,
+ LoginState::LOGGED_IN_USER_REGULAR);
+ base::RunLoop().RunUntilIdle();
+ }
+
void ImportClientCertAndKey(const std::string& pkcs12_file,
net::NSSCertDatabase* nssdb,
net::CertificateList* loaded_certs) {
@@ -181,10 +219,47 @@ class NetworkConnectionHandlerTest : public testing::Test {
ASSERT_EQ(1U, loaded_certs->size());
}
+ void SetupPolicy() {
+ const char* kNetworkConfigs =
+ "[ { \"GUID\": \"wifi1\","
+ " \"Name\": \"wifi1\","
+ " \"Type\": \"WiFi\","
+ " \"WiFi\": {"
+ " \"Security\": \"WPA-PSK\","
+ " \"SSID\": \"wifi1\","
+ " \"Passphrase\": \"passphrase\""
+ " }"
+ "} ]";
+
+ std::string error;
+ scoped_ptr<base::Value> network_configs_value(
+ base::JSONReader::ReadAndReturnError(
+ kNetworkConfigs, base::JSON_ALLOW_TRAILING_COMMAS, NULL, &error));
+ ASSERT_TRUE(network_configs_value) << error;
+
+ base::ListValue* network_configs = NULL;
+ ASSERT_TRUE(network_configs_value->GetAsList(&network_configs));
+
+ base::DictionaryValue global_config;
+ global_config.SetBooleanWithoutPathExpansion(
+ ::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
+ true);
+
+ managed_config_handler_->SetPolicy(::onc::ONC_SOURCE_USER_POLICY,
+ "", // userhash
+ *network_configs,
+ global_config);
+ base::RunLoop().RunUntilIdle();
+ }
+
scoped_ptr<NetworkStateHandler> network_state_handler_;
- scoped_ptr<NetworkConfigurationHandler> network_configuration_handler_;
+ scoped_ptr<NetworkConfigurationHandler> network_config_handler_;
scoped_ptr<NetworkConnectionHandler> network_connection_handler_;
+ scoped_ptr<ManagedNetworkConfigurationHandlerImpl> managed_config_handler_;
+ scoped_ptr<NetworkProfileHandler> network_profile_handler_;
crypto::ScopedTestNSSChromeOSUser user_;
+ ShillManagerClient::TestInterface* test_manager_client_;
+ ShillServiceClient::TestInterface* test_service_client_;
scoped_ptr<net::NSSCertDatabaseChromeOS> test_nssdb_;
base::MessageLoopForUI message_loop_;
std::string result_;
@@ -328,4 +403,62 @@ TEST_F(NetworkConnectionHandlerTest,
EXPECT_EQ(NetworkConnectionHandler::kErrorNotConnected, GetResultAndReset());
}
+namespace {
+
+const char* kConfigUnmanagedSharedConnected =
+ "{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"online\" }";
+const char* kConfigManagedSharedConnectable =
+ "{ \"GUID\": \"wifi1\", \"Type\": \"wifi\", \"State\": \"idle\", "
+ " \"Connectable\": true }";
+
+} // namespace
+
+TEST_F(NetworkConnectionHandlerTest, ReconnectOnLoginEarlyPolicyLoading) {
+ EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
+ EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
+ test_manager_client_->SetBestServiceToConnect("wifi1");
+
+ // User login shouldn't trigger any change because policy is not loaded yet.
+ LoginToRegularUser();
+ EXPECT_EQ(shill::kStateOnline,
+ GetServiceStringProperty("wifi0", shill::kStateProperty));
+ EXPECT_EQ(shill::kStateIdle,
+ GetServiceStringProperty("wifi1", shill::kStateProperty));
+
+ // Policy application should disconnect from the shared and unmanaged network.
+ SetupPolicy();
+ EXPECT_EQ(shill::kStateIdle,
+ GetServiceStringProperty("wifi0", shill::kStateProperty));
+ EXPECT_EQ(shill::kStateIdle,
+ GetServiceStringProperty("wifi1", shill::kStateProperty));
+
+ // Certificate loading should trigger connecting to the 'best' network.
+ StartCertLoader();
+ EXPECT_EQ(shill::kStateIdle,
+ GetServiceStringProperty("wifi0", shill::kStateProperty));
+ EXPECT_EQ(shill::kStateOnline,
+ GetServiceStringProperty("wifi1", shill::kStateProperty));
+}
+
+TEST_F(NetworkConnectionHandlerTest, ReconnectOnLoginLatePolicyLoading) {
+ EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
+ EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
+ test_manager_client_->SetBestServiceToConnect("wifi1");
+
+ // User login and certificate loading shouldn't trigger any change until the
+ // policy is loaded.
+ LoginToRegularUser();
+ StartCertLoader();
+ EXPECT_EQ(shill::kStateOnline,
+ GetServiceStringProperty("wifi0", shill::kStateProperty));
+ EXPECT_EQ(shill::kStateIdle,
+ GetServiceStringProperty("wifi1", shill::kStateProperty));
+
+ SetupPolicy();
+ EXPECT_EQ(shill::kStateIdle,
+ GetServiceStringProperty("wifi0", shill::kStateProperty));
+ EXPECT_EQ(shill::kStateOnline,
+ GetServiceStringProperty("wifi1", shill::kStateProperty));
+}
+
} // namespace chromeos
diff --git a/chromeos/network/network_handler.cc b/chromeos/network/network_handler.cc
index ada863d..7d3c6f0 100644
--- a/chromeos/network/network_handler.cc
+++ b/chromeos/network/network_handler.cc
@@ -60,8 +60,10 @@ void NetworkHandler::Init() {
network_state_handler_.get(),
network_profile_handler_.get(),
network_configuration_handler_.get());
- network_connection_handler_->Init(network_state_handler_.get(),
- network_configuration_handler_.get());
+ network_connection_handler_->Init(
+ network_state_handler_.get(),
+ network_configuration_handler_.get(),
+ managed_network_configuration_handler_.get());
if (network_cert_migrator_)
network_cert_migrator_->Init(network_state_handler_.get());
if (client_cert_resolver_) {
diff --git a/chromeos/network/network_policy_observer.h b/chromeos/network/network_policy_observer.h
index c51982e..defbb26 100644
--- a/chromeos/network/network_policy_observer.h
+++ b/chromeos/network/network_policy_observer.h
@@ -13,7 +13,13 @@ namespace chromeos {
class NetworkPolicyObserver {
public:
- virtual void PolicyApplied(const std::string& service_path) = 0;
+ // Called when the policy for |userhash| was set (also when it was updated).
+ // Note that the policy might not have been applied yet at that time.
+ // An empty |userhash| designates the device policy.
+ virtual void PolicyChanged(const std::string& userhash) {};
+
+ // Called every time a network is create or updated because of a policy.
+ virtual void PolicyApplied(const std::string& service_path) {};
protected:
virtual ~NetworkPolicyObserver() {};
diff --git a/chromeos/network/network_profile_handler.h b/chromeos/network/network_profile_handler.h
index 15e4e63..a5c1d0a 100644
--- a/chromeos/network/network_profile_handler.h
+++ b/chromeos/network/network_profile_handler.h
@@ -61,6 +61,7 @@ class CHROMEOS_EXPORT NetworkProfileHandler
protected:
friend class ClientCertResolverTest;
+ friend class NetworkConnectionHandlerTest;
friend class NetworkHandler;
NetworkProfileHandler();