Skip to content

Commit

Permalink
Trigger ConnectToBestNetwork in more cases.
Browse files Browse the repository at this point in the history
ConnectToBestNetwork will now also be triggered after policy application and after client certificate patterns were resolved.
I.e. that managed networks will autoconnect more reliably.

BUG=424036

Review URL: https://codereview.chromium.org/701863002

Cr-Commit-Position: refs/heads/master@{#303457}
pneubeck authored and Commit bot committed Nov 10, 2014
1 parent fb8d6c3 commit 627248e
Showing 13 changed files with 852 additions and 231 deletions.
3 changes: 3 additions & 0 deletions chromeos/chromeos.gyp
Original file line number Diff line number Diff line change
@@ -275,6 +275,8 @@
'login/user_names.h',
'login_event_recorder.cc',
'login_event_recorder.h',
'network/auto_connect_handler.cc',
'network/auto_connect_handler.h',
'network/certificate_pattern.cc',
'network/certificate_pattern.h',
'network/client_cert_resolver.cc',
@@ -423,6 +425,7 @@
'ime/input_method_whitelist_unittest.cc',
'login/auth/key_unittest.cc',
'login/login_state_unittest.cc',
'network/auto_connect_handler_unittest.cc',
'network/client_cert_resolver_unittest.cc',
'network/geolocation_handler_unittest.cc',
'network/host_resolver_impl_chromeos_unittest.cc',
214 changes: 214 additions & 0 deletions chromeos/network/auto_connect_handler.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
// Copyright 2014 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/auto_connect_handler.h"

#include <string>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_service_client.h"
#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_event_log.h"
#include "chromeos/network/network_state.h"
#include "dbus/object_path.h"

namespace chromeos {

AutoConnectHandler::AutoConnectHandler()
: client_cert_resolver_(nullptr),
request_best_connection_pending_(false),
device_policy_applied_(false),
user_policy_applied_(false),
client_certs_resolved_(false),
applied_autoconnect_policy_(false) {
}

AutoConnectHandler::~AutoConnectHandler() {
if (client_cert_resolver_)
client_cert_resolver_->RemoveObserver(this);
if (LoginState::IsInitialized())
LoginState::Get()->RemoveObserver(this);
if (managed_configuration_handler_)
managed_configuration_handler_->RemoveObserver(this);
}

void AutoConnectHandler::Init(
ClientCertResolver* client_cert_resolver,
NetworkConnectionHandler* network_connection_handler,
NetworkStateHandler* network_state_handler,
ManagedNetworkConfigurationHandler* managed_network_configuration_handler) {
if (LoginState::IsInitialized())
LoginState::Get()->AddObserver(this);

client_cert_resolver_ = client_cert_resolver;
if (client_cert_resolver_)
client_cert_resolver_->AddObserver(this);

network_connection_handler_ = network_connection_handler;
if (network_connection_handler_)
network_connection_handler_->AddObserver(this);

network_state_handler_ = network_state_handler;

if (managed_network_configuration_handler) {
managed_configuration_handler_ = managed_network_configuration_handler;
managed_configuration_handler_->AddObserver(this);
}

if (LoginState::IsInitialized())
LoggedInStateChanged();
}

void AutoConnectHandler::LoggedInStateChanged() {
if (!LoginState::Get()->IsUserLoggedIn())
return;

// Disconnect before connecting, to ensure that we do not disconnect a network
// that we just connected.
DisconnectIfPolicyRequires();
NET_LOG_DEBUG("RequestBestConnection", "User logged in");
RequestBestConnection();
}

void AutoConnectHandler::ConnectToNetworkRequested(
const std::string& /*service_path*/) {
// Stop any pending request to connect to the best newtork.
request_best_connection_pending_ = false;
}

void AutoConnectHandler::PoliciesChanged(const std::string& userhash) {
// Ignore user policies.
if (!userhash.empty())
return;
DisconnectIfPolicyRequires();
}

void AutoConnectHandler::PoliciesApplied(const std::string& userhash) {
if (userhash.empty())
device_policy_applied_ = true;
else
user_policy_applied_ = true;

// Request to connect to the best network only if there is at least one
// managed network. Otherwise only process existing requests.
const ManagedNetworkConfigurationHandler::GuidToPolicyMap* managed_networks =
managed_configuration_handler_->GetNetworkConfigsFromPolicy(userhash);
DCHECK(managed_networks);
if (!managed_networks->empty()) {
NET_LOG_DEBUG("RequestBestConnection", "Policy applied");
RequestBestConnection();
} else {
CheckBestConnection();
}
}

void AutoConnectHandler::ResolveRequestCompleted(
bool network_properties_changed) {
client_certs_resolved_ = true;

// Only request to connect to the best network if network properties were
// actually changed. Otherwise only process existing requests.
if (network_properties_changed) {
NET_LOG_DEBUG("RequestBestConnection",
"Client certificate patterns resolved");
RequestBestConnection();
} else {
CheckBestConnection();
}
}

void AutoConnectHandler::RequestBestConnection() {
request_best_connection_pending_ = true;
CheckBestConnection();
}

void AutoConnectHandler::CheckBestConnection() {
// Return immediately if there is currently no request pending to change to
// the best network.
if (!request_best_connection_pending_)
return;

bool policy_application_running =
managed_configuration_handler_->IsAnyPolicyApplicationRunning();
bool client_cert_resolve_task_running =
client_cert_resolver_->IsAnyResolveTaskRunning();
VLOG(2) << "device policy applied: " << device_policy_applied_
<< "\nuser policy applied: " << user_policy_applied_
<< "\npolicy application running: " << policy_application_running
<< "\nclient cert patterns resolved: " << client_certs_resolved_
<< "\nclient cert resolve task running: "
<< client_cert_resolve_task_running;
if (!device_policy_applied_ || policy_application_running ||
client_cert_resolve_task_running) {
return;
}

if (LoginState::Get()->IsUserLoggedIn()) {
// Before changing connection after login, we wait at least for:
// - user policy applied at least once
// - client certificate patterns resolved
if (!user_policy_applied_ || !client_certs_resolved_)
return;
}

request_best_connection_pending_ = false;
NET_LOG_EVENT("ConnectToBestWifiNetwork", "");
network_state_handler_->ConnectToBestWifiNetwork();
}

void AutoConnectHandler::DisconnectIfPolicyRequires() {
if (applied_autoconnect_policy_ || !LoginState::Get()->IsUserLoggedIn())
return;

const base::DictionaryValue* global_network_config =
managed_configuration_handler_->GetGlobalConfigFromPolicy(
std::string() /* no username hash, device policy */);

if (!global_network_config)
return; // Device policy is not set, yet.

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)
DisconnectFromUnmanagedSharedWiFiNetworks();
}

void AutoConnectHandler::DisconnectFromUnmanagedSharedWiFiNetworks() {
NET_LOG_DEBUG("DisconnectFromUnmanagedSharedWiFiNetworks", "");

NetworkStateHandler::NetworkStateList networks;
network_state_handler_->GetVisibleNetworkListByType(
NetworkTypePattern::Wireless(), &networks);
for (const NetworkState* network : networks) {
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());
DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
dbus::ObjectPath(network->path()), base::Bind(&base::DoNothing),
base::Bind(&network_handler::ShillErrorCallbackFunction,
"AutoConnectHandler.Disconnect failed", network->path(),
network_handler::ErrorCallback()));
}
}

} // namespace chromeos
108 changes: 108 additions & 0 deletions chromeos/network/auto_connect_handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
// Copyright 2014 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_AUTO_CONNECT_HANDLER_H_
#define CHROMEOS_NETWORK_AUTO_CONNECT_HANDLER_H_

#include <string>

#include "base/macros.h"
#include "chromeos/chromeos_export.h"
#include "chromeos/login/login_state.h"
#include "chromeos/network/client_cert_resolver.h"
#include "chromeos/network/network_connection_handler.h"
#include "chromeos/network/network_handler.h"
#include "chromeos/network/network_policy_observer.h"

namespace chromeos {

class CHROMEOS_EXPORT AutoConnectHandler
: public LoginState::Observer,
public NetworkPolicyObserver,
public NetworkConnectionHandler::Observer,
public ClientCertResolver::Observer {
public:
~AutoConnectHandler() override;

// LoginState::Observer
void LoggedInStateChanged() override;

// NetworkConnectionHandler::Observer
void ConnectToNetworkRequested(const std::string& service_path) override;

// NetworkPolicyObserver
void PoliciesChanged(const std::string& userhash) override;
void PoliciesApplied(const std::string& userhash) override;

// ClientCertResolver::Observer
void ResolveRequestCompleted(bool network_properties_changed) override;

private:
friend class NetworkHandler;
friend class AutoConnectHandlerTest;

AutoConnectHandler();

void Init(ClientCertResolver* client_cert_resolver,
NetworkConnectionHandler* network_connection_handler,
NetworkStateHandler* network_state_handler,
ManagedNetworkConfigurationHandler*
managed_network_configuration_handler);

// If the user logged in already and the policy to prevent unmanaged & shared
// networks to autoconnect is enabled, then disconnects all such networks
// except wired networks. It will do this only once after the user logged in
// and the device policy was available.
// 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 at login and when the
// device policy is changed.
void DisconnectIfPolicyRequires();

// Disconnects from all unmanaged and shared WiFi networks that are currently
// connected or connecting.
void DisconnectFromUnmanagedSharedWiFiNetworks();

// Requests and if possible connects to the 'best' available network, see
// CheckBestConnection().
void RequestBestConnection();

// If a request to connect to the best network is pending and all requirements
// are fulfilled (like policy loaded, certificate patterns being resolved),
// then this will call ConnectToBestWifiNetwork of |network_state_handler_|.
void CheckBestConnection();

// Local references to the associated handler instances.
ClientCertResolver* client_cert_resolver_;
NetworkConnectionHandler* network_connection_handler_;
NetworkStateHandler* network_state_handler_;
ManagedNetworkConfigurationHandler* managed_configuration_handler_;

// Whether a request to connect to the best network is pending. If true, once
// all requirements are met (like policy loaded, certificate patterns being
// resolved), the request is forwarded to the |network_state_handler_|.
bool request_best_connection_pending_;

// Whether the device policy, which might be empty, is already applied.
bool device_policy_applied_;

// Whether the user policy of the first user who logged in is already applied.
// The policy might be empty.
bool user_policy_applied_;

// Whether at least once client certificate patterns were checked and if any
// existed resolved. Even if there are no certificate patterns, this will be
// eventually true.
bool client_certs_resolved_;

// Whether the autoconnect policy was applied already, see
// DisconnectIfPolicyRequires().
bool applied_autoconnect_policy_;

DISALLOW_COPY_AND_ASSIGN(AutoConnectHandler);
};

} // namespace chromeos

#endif // CHROMEOS_NETWORK_AUTO_CONNECT_HANDLER_H_
475 changes: 475 additions & 0 deletions chromeos/network/auto_connect_handler_unittest.cc

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -404,7 +404,8 @@ void ManagedNetworkConfigurationHandlerImpl::SetPolicy(

STLDeleteValues(&old_per_network_config);
ApplyOrQueuePolicies(userhash, &modified_policies);
FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_, PolicyChanged(userhash));
FOR_EACH_OBSERVER(NetworkPolicyObserver, observers_,
PoliciesChanged(userhash));
}

bool ManagedNetworkConfigurationHandlerImpl::IsAnyPolicyApplicationRunning()
Original file line number Diff line number Diff line change
@@ -106,6 +106,7 @@ class CHROMEOS_EXPORT ManagedNetworkConfigurationHandlerImpl
void OnPoliciesApplied(const NetworkProfile& profile) override;

private:
friend class AutoConnectHandlerTest;
friend class ClientCertResolverTest;
friend class ManagedNetworkConfigurationHandlerTest;
friend class NetworkConnectionHandlerTest;
99 changes: 14 additions & 85 deletions chromeos/network/network_connection_handler.cc
Original file line number Diff line number Diff line change
@@ -152,9 +152,7 @@ NetworkConnectionHandler::NetworkConnectionHandler()
network_state_handler_(NULL),
configuration_handler_(NULL),
logged_in_(false),
certificates_loaded_(false),
applied_autoconnect_policy_(false),
requested_connect_to_best_network_(false) {
certificates_loaded_(false) {
}

NetworkConnectionHandler::~NetworkConnectionHandler() {
@@ -191,11 +189,7 @@ void NetworkConnectionHandler::Init(
network_state_handler_->AddObserver(this, FROM_HERE);
}
configuration_handler_ = network_configuration_handler;

if (managed_network_configuration_handler) {
managed_configuration_handler_ = managed_network_configuration_handler;
managed_configuration_handler_->AddObserver(this);
}
managed_configuration_handler_ = managed_network_configuration_handler;

// After this point, the NetworkConnectionHandler is fully initialized (all
// handler references set, observers registered, ...).
@@ -204,6 +198,14 @@ void NetworkConnectionHandler::Init(
LoggedInStateChanged();
}

void NetworkConnectionHandler::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}

void NetworkConnectionHandler::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}

void NetworkConnectionHandler::LoggedInStateChanged() {
LoginState* login_state = LoginState::Get();
if (logged_in_ || !login_state->IsUserLoggedIn())
@@ -212,29 +214,15 @@ void NetworkConnectionHandler::LoggedInStateChanged() {
NET_LOG_EVENT("Logged In", "");
logged_in_ = true;
logged_in_time_ = base::TimeTicks::Now();

DisconnectIfPolicyRequires();
}

void NetworkConnectionHandler::OnCertificatesLoaded(
const net::CertificateList& cert_list,
bool initial_load) {
certificates_loaded_ = true;
NET_LOG_EVENT("Certificates Loaded", "");
if (queued_connect_) {
if (queued_connect_)
ConnectToQueuedNetwork();
} else if (initial_load) {
// 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(
@@ -243,6 +231,9 @@ void NetworkConnectionHandler::ConnectToNetwork(
const network_handler::ErrorCallback& error_callback,
bool check_error_state) {
NET_LOG_USER("ConnectToNetwork", service_path);
FOR_EACH_OBSERVER(Observer, observers_,
ConnectToNetworkRequested(service_path));

// Clear any existing queued connect request.
queued_connect_.reset();
if (HasConnectingNetwork(service_path)) {
@@ -761,66 +752,4 @@ 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)
DisconnectFromUnmanagedSharedWiFiNetworks();

ConnectToBestNetworkAfterLogin();
}

void NetworkConnectionHandler::DisconnectFromUnmanagedSharedWiFiNetworks() {
NET_LOG_DEBUG("DisconnectFromUnmanagedSharedWiFiNetworks", "");

NetworkStateHandler::NetworkStateList networks;
network_state_handler_->GetVisibleNetworkListByType(
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());
}
}

} // namespace chromeos
52 changes: 19 additions & 33 deletions chromeos/network/network_connection_handler.h
Original file line number Diff line number Diff line change
@@ -5,12 +5,14 @@
#ifndef CHROMEOS_NETWORK_NETWORK_CONNECTION_HANDLER_H_
#define CHROMEOS_NETWORK_NETWORK_CONNECTION_HANDLER_H_

#include <map>
#include <set>
#include <string>

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chromeos/cert_loader.h"
@@ -19,7 +21,6 @@
#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,9 +47,21 @@ class CHROMEOS_EXPORT NetworkConnectionHandler
: public LoginState::Observer,
public CertLoader::Observer,
public NetworkStateHandlerObserver,
public NetworkPolicyObserver,
public base::SupportsWeakPtr<NetworkConnectionHandler> {
public:
class Observer {
public:
// Called if a connection to network |service_path| was requested, by
// calling ConnectToNetwork.
virtual void ConnectToNetworkRequested(const std::string& service_path) = 0;

protected:
virtual ~Observer() {}

private:
DISALLOW_ASSIGN(Observer);
};

// Constants for |error_name| from |error_callback| for Connect.

// No network matching |service_path| is found (hidden networks must be
@@ -93,6 +106,9 @@ class CHROMEOS_EXPORT NetworkConnectionHandler

virtual ~NetworkConnectionHandler();

void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);

// ConnectToNetwork() will start an asynchronous connection attempt.
// On success, |success_callback| will be called.
// On failure, |error_callback| will be called with |error_name| one of the
@@ -137,9 +153,6 @@ 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;
@@ -206,26 +219,7 @@ 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();

// Disconnects from all unmanaged and shared WiFi networks that are currently
// connected or connecting.
void DisconnectFromUnmanagedSharedWiFiNetworks();

// 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();
ObserverList<Observer> observers_;

// Local references to the associated handler instances.
CertLoader* cert_loader_;
@@ -243,14 +237,6 @@ 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);
};

108 changes: 0 additions & 108 deletions chromeos/network/network_connection_handler_unittest.cc
Original file line number Diff line number Diff line change
@@ -426,114 +426,6 @@ TEST_F(NetworkConnectionHandlerTest,
EXPECT_EQ(NetworkConnectionHandler::kErrorNotConnected, GetResultAndReset());
}

namespace {

const char* kConfigUnmanagedSharedConnected =
"{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"online\", "
" \"Security\": \"wpa\" }";
const char* kConfigManagedSharedConnectable =
"{ \"GUID\": \"wifi1\", \"Type\": \"wifi\", \"State\": \"idle\", "
" \"Connectable\": true, \"Security\": \"wpa\" }";

const char* kPolicy =
"[ { \"GUID\": \"wifi1\","
" \"Name\": \"wifi1\","
" \"Type\": \"WiFi\","
" \"WiFi\": {"
" \"Security\": \"WPA-PSK\","
" \"SSID\": \"wifi1\","
" \"Passphrase\": \"passphrase\""
" }"
"} ]";

} // namespace

TEST_F(NetworkConnectionHandlerTest, ReconnectOnCertLoading) {
EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));
test_manager_client_->SetBestServiceToConnect("wifi1");

// User login shouldn't trigger any change until the certificates and policy
// are loaded.
LoginToRegularUser();
EXPECT_EQ(shill::kStateOnline,
GetServiceStringProperty("wifi0", shill::kStateProperty));
EXPECT_EQ(shill::kStateIdle,
GetServiceStringProperty("wifi1", shill::kStateProperty));

// Applying the policy which restricts autoconnect should disconnect from the
// shared, unmanaged network.
base::DictionaryValue global_config;
global_config.SetBooleanWithoutPathExpansion(
::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
true);

SetupPolicy(kPolicy, global_config, false /* load as device policy */);
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, DisconnectOnPolicyLoading) {
EXPECT_TRUE(Configure(kConfigUnmanagedSharedConnected));
EXPECT_TRUE(Configure(kConfigManagedSharedConnectable));

// 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));

base::DictionaryValue global_config;
global_config.SetBooleanWithoutPathExpansion(
::onc::global_network_config::kAllowOnlyPolicyNetworksToAutoconnect,
true);

// Applying the policy which restricts autoconnect should disconnect from the
// shared, unmanaged network.
// Because no best service is set, the fake implementation of
// ConnectToBestServices will be a no-op.
SetupPolicy(kPolicy, global_config, false /* load as device policy */);
EXPECT_EQ(shill::kStateIdle,
GetServiceStringProperty("wifi0", shill::kStateProperty));
EXPECT_EQ(shill::kStateIdle,
GetServiceStringProperty("wifi1", shill::kStateProperty));
}

TEST_F(NetworkConnectionHandlerTest, ReconnectOnEmptyPolicyLoading) {
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));

// Apply an empty policy should trigger connecting to the 'best' network.
base::DictionaryValue global_config;
SetupPolicy(kPolicy, global_config, false /* load as device policy */);
EXPECT_EQ(shill::kStateIdle,
GetServiceStringProperty("wifi0", shill::kStateProperty));
EXPECT_EQ(shill::kStateOnline,
GetServiceStringProperty("wifi1", shill::kStateProperty));
}

} // namespace chromeos

#endif
8 changes: 8 additions & 0 deletions chromeos/network/network_handler.cc
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@

#include "base/threading/worker_pool.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/network/auto_connect_handler.h"
#include "chromeos/network/client_cert_resolver.h"
#include "chromeos/network/geolocation_handler.h"
#include "chromeos/network/managed_network_configuration_handler_impl.h"
@@ -38,6 +39,7 @@ NetworkHandler::NetworkHandler()
managed_network_configuration_handler_.reset(
new ManagedNetworkConfigurationHandlerImpl());
if (CertLoader::IsInitialized()) {
auto_connect_handler_.reset(new AutoConnectHandler());
network_cert_migrator_.reset(new NetworkCertMigrator());
client_cert_resolver_.reset(new ClientCertResolver());
}
@@ -71,6 +73,12 @@ void NetworkHandler::Init() {
client_cert_resolver_->Init(network_state_handler_.get(),
managed_network_configuration_handler_.get());
}
if (auto_connect_handler_) {
auto_connect_handler_->Init(client_cert_resolver_.get(),
network_connection_handler_.get(),
network_state_handler_.get(),
managed_network_configuration_handler_.get());
}
network_sms_handler_->Init();
geolocation_handler_->Init();
}
2 changes: 2 additions & 0 deletions chromeos/network/network_handler.h
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@

namespace chromeos {

class AutoConnectHandler;
class ClientCertResolver;
class GeolocationHandler;
class ManagedNetworkConfigurationHandler;
@@ -79,6 +80,7 @@ class CHROMEOS_EXPORT NetworkHandler {
scoped_ptr<ClientCertResolver> client_cert_resolver_;
scoped_ptr<NetworkActivationHandler> network_activation_handler_;
scoped_ptr<NetworkConnectionHandler> network_connection_handler_;
scoped_ptr<AutoConnectHandler> auto_connect_handler_;
scoped_ptr<NetworkSmsHandler> network_sms_handler_;
scoped_ptr<GeolocationHandler> geolocation_handler_;

9 changes: 5 additions & 4 deletions chromeos/network/network_policy_observer.h
Original file line number Diff line number Diff line change
@@ -13,10 +13,11 @@ namespace chromeos {

class NetworkPolicyObserver {
public:
// 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 when the policies for |userhash| were set (also when they were
// updated). An empty |userhash| designates the device policy.
// Note that the policies might be empty and might not have been applied yet
// at that time.
virtual void PoliciesChanged(const std::string& userhash) {}

// Called every time a policy application for |userhash| finished. This is
// only called once no more policies are pending for |userhash|.
1 change: 1 addition & 0 deletions chromeos/network/network_profile_handler.h
Original file line number Diff line number Diff line change
@@ -61,6 +61,7 @@ class CHROMEOS_EXPORT NetworkProfileHandler
static std::string GetSharedProfilePath();

protected:
friend class AutoConnectHandlerTest;
friend class ClientCertResolverTest;
friend class NetworkConnectionHandlerTest;
friend class NetworkHandler;

0 comments on commit 627248e

Please sign in to comment.