blob: a48ba6e588dc0416bdfd0e18bbbe35f62ad105ad [file] [log] [blame]
// Copyright 2016 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 <memory>
#include "base/bind_helpers.h"
#include "base/optional.h"
#include "base/test/task_environment.h"
#include "chromeos/constants/chromeos_pref_names.h"
#include "chromeos/dbus/shill/shill_clients.h"
#include "chromeos/dbus/shill/shill_manager_client.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_connection_handler.h"
#include "chromeos/network/network_connection_handler_impl.h"
#include "chromeos/network/network_metadata_observer.h"
#include "chromeos/network/network_metadata_store.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/network_state_test_helper.h"
#include "components/account_id/account_id.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
namespace chromeos {
class TestNetworkMetadataObserver : public NetworkMetadataObserver {
public:
TestNetworkMetadataObserver() = default;
~TestNetworkMetadataObserver() override = default;
// NetworkConnectionObserver
void OnFirstConnectionToNetwork(const std::string& guid) override {
connections_.insert(guid);
}
void OnNetworkUpdate(const std::string& guid,
base::DictionaryValue* set_properties) override {
if (!updates_.contains(guid)) {
updates_[guid] = 1;
} else {
updates_[guid]++;
}
}
bool HasConnected(const std::string& guid) {
return connections_.count(guid) != 0;
}
int GetNumberOfUpdates(const std::string& guid) {
if (!updates_.contains(guid)) {
return 0;
}
return updates_[guid];
}
private:
std::set<std::string> connections_;
base::flat_map<std::string, int> updates_;
};
class NetworkMetadataStoreTest : public ::testing::Test {
public:
NetworkMetadataStoreTest() {
network_configuration_handler_ =
NetworkConfigurationHandler::InitializeForTest(
helper_.network_state_handler(),
nullptr /* network_device_handler */);
network_connection_handler_.reset(new NetworkConnectionHandlerImpl());
network_connection_handler_->Init(helper_.network_state_handler(),
network_configuration_handler_, nullptr);
network_state_handler_ = helper_.network_state_handler();
NetworkHandler::Initialize();
user_prefs_ =
std::make_unique<sync_preferences::TestingPrefServiceSyncable>();
device_prefs_ = std::make_unique<TestingPrefServiceSimple>();
NetworkMetadataStore::RegisterPrefs(user_prefs_->registry());
NetworkMetadataStore::RegisterPrefs(device_prefs_->registry());
auto fake_user_manager = std::make_unique<user_manager::FakeUserManager>();
auto account_id = AccountId::FromUserEmail("account@test.com");
auto second_account_id = AccountId::FromUserEmail("account2@test.com");
primary_user_ = fake_user_manager->AddUser(account_id);
secondary_user_ = fake_user_manager->AddUser(second_account_id);
scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>(
std::move(fake_user_manager));
metadata_store_ = std::make_unique<NetworkMetadataStore>(
network_configuration_handler_, network_connection_handler_.get(),
network_state_handler_, user_prefs_.get(), device_prefs_.get(),
/*is_enterprise_enrolled=*/false);
metadata_observer_ = std::make_unique<TestNetworkMetadataObserver>();
metadata_store_->AddObserver(metadata_observer_.get());
}
~NetworkMetadataStoreTest() override {
network_state_handler_ = nullptr;
metadata_store_.reset();
metadata_observer_.reset();
user_prefs_.reset();
device_prefs_.reset();
network_configuration_handler_ = nullptr;
network_connection_handler_.reset();
scoped_user_manager_.reset();
NetworkHandler::Shutdown();
}
void SetUp() override {
SetIsEnterpriseEnrolled(false);
LoginUser(primary_user_);
}
// This creates a new NetworkMetadataStore object.
void SetIsEnterpriseEnrolled(bool is_enterprise_enrolled) {
metadata_store_.reset(new NetworkMetadataStore(
network_configuration_handler_, network_connection_handler_.get(),
network_state_handler_, user_prefs_.get(), device_prefs_.get(),
is_enterprise_enrolled));
metadata_store_->AddObserver(metadata_observer_.get());
}
void LoginUser(const user_manager::User* user) {
UserManager()->UserLoggedIn(user->GetAccountId(), user->username_hash(),
true /* browser_restart */,
false /* is_child */);
UserManager()->SwitchActiveUser(user->GetAccountId());
}
user_manager::FakeUserManager* UserManager() {
return static_cast<user_manager::FakeUserManager*>(
user_manager::UserManager::Get());
}
std::string ConfigureService(const std::string& shill_json_string) {
return helper_.ConfigureService(shill_json_string);
}
sync_preferences::TestingPrefServiceSyncable* user_prefs() {
return user_prefs_.get();
}
TestingPrefServiceSimple* device_prefs() { return device_prefs_.get(); }
NetworkMetadataStore* metadata_store() { return metadata_store_.get(); }
TestNetworkMetadataObserver* metadata_observer() {
return metadata_observer_.get();
}
NetworkConnectionHandler* network_connection_handler() {
return network_connection_handler_.get();
}
NetworkConfigurationHandler* network_configuration_handler() {
return network_configuration_handler_;
}
NetworkStateHandler* network_state_handler() {
return network_state_handler_;
}
protected:
const user_manager::User* primary_user_;
const user_manager::User* secondary_user_;
private:
base::test::SingleThreadTaskEnvironment task_environment_;
NetworkStateTestHelper helper_{false /* use_default_devices_and_services */};
NetworkConfigurationHandler* network_configuration_handler_;
std::unique_ptr<NetworkConnectionHandler> network_connection_handler_;
NetworkStateHandler* network_state_handler_;
std::unique_ptr<TestingPrefServiceSimple> device_prefs_;
std::unique_ptr<sync_preferences::TestingPrefServiceSyncable> user_prefs_;
std::unique_ptr<NetworkMetadataStore> metadata_store_;
std::unique_ptr<TestNetworkMetadataObserver> metadata_observer_;
std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
DISALLOW_COPY_AND_ASSIGN(NetworkMetadataStoreTest);
};
namespace {
const char* kGuid = "wifi0";
const char* kConfigWifi0Connectable =
"{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"idle\", "
" \"Connectable\": true }";
const char* kConfigWifi1Shared =
"{ \"GUID\": \"wifi0\", \"Type\": \"wifi\", \"State\": \"idle\", "
" \"Connectable\": true, \"Profile\": \"/profile/default\" }";
} // namespace
TEST_F(NetworkMetadataStoreTest, FirstConnect) {
std::string service_path = ConfigureService(kConfigWifi0Connectable);
ASSERT_TRUE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_FALSE(metadata_observer()->HasConnected(kGuid));
network_connection_handler()->ConnectToNetwork(
service_path, base::DoNothing(), base::DoNothing(),
true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_TRUE(metadata_observer()->HasConnected(kGuid));
}
TEST_F(NetworkMetadataStoreTest, FirstConnect_AfterBadPassword) {
std::string service_path = ConfigureService(kConfigWifi0Connectable);
network_state_handler()->SetErrorForTest(service_path,
shill::kErrorBadPassphrase);
metadata_store()->ConnectFailed(service_path, shill::kErrorConnectFailed);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_TRUE(metadata_store()->GetHasBadPassword(kGuid));
ASSERT_FALSE(metadata_observer()->HasConnected(kGuid));
base::RunLoop().RunUntilIdle();
network_state_handler()->SetErrorForTest(service_path, "");
network_connection_handler()->ConnectToNetwork(
service_path, base::DoNothing(), base::DoNothing(),
true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_FALSE(metadata_store()->GetHasBadPassword(kGuid));
ASSERT_TRUE(metadata_observer()->HasConnected(kGuid));
}
TEST_F(NetworkMetadataStoreTest, BadPassword_AfterSuccessfulConnection) {
std::string service_path = ConfigureService(kConfigWifi0Connectable);
network_connection_handler()->ConnectToNetwork(
service_path, base::DoNothing(), base::DoNothing(),
true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_FALSE(metadata_store()->GetHasBadPassword(kGuid));
ASSERT_TRUE(metadata_observer()->HasConnected(kGuid));
network_state_handler()->SetErrorForTest(service_path,
shill::kErrorBadPassphrase);
metadata_store()->ConnectFailed(service_path, shill::kErrorConnectFailed);
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(metadata_store()->GetHasBadPassword(kGuid));
}
TEST_F(NetworkMetadataStoreTest, ConfigurationCreated) {
std::string service_path = ConfigureService(kConfigWifi0Connectable);
metadata_store()->OnConfigurationCreated(service_path, kGuid);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(metadata_store()->GetIsCreatedByUser(kGuid));
}
TEST_F(NetworkMetadataStoreTest, ConfigurationCreated_HiddenNetwork) {
metadata_store()->OnConfigurationCreated("service_path", kGuid);
// Network only exists after the OnConfigurationCreated has been called.
std::string service_path = ConfigureService(kConfigWifi0Connectable);
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(metadata_store()->GetIsCreatedByUser(kGuid));
}
TEST_F(NetworkMetadataStoreTest, ConfigurationUpdated) {
std::string service_path = ConfigureService(kConfigWifi0Connectable);
network_connection_handler()->ConnectToNetwork(
service_path, base::DoNothing(), base::DoNothing(),
true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
base::RunLoop().RunUntilIdle();
metadata_store()->SetIsConfiguredBySync(kGuid);
ASSERT_FALSE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_TRUE(metadata_store()->GetIsConfiguredBySync(kGuid));
ASSERT_EQ(0, metadata_observer()->GetNumberOfUpdates(kGuid));
base::DictionaryValue properties;
properties.SetKey(shill::kSecurityProperty, base::Value(shill::kSecurityPsk));
properties.SetKey(shill::kPassphraseProperty, base::Value("secret"));
network_configuration_handler()->SetShillProperties(
service_path, properties, base::DoNothing(), base::DoNothing());
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_FALSE(metadata_store()->GetIsConfiguredBySync(kGuid));
ASSERT_EQ(1, metadata_observer()->GetNumberOfUpdates(kGuid));
}
TEST_F(NetworkMetadataStoreTest, SharedConfigurationUpdatedByOtherUser) {
std::string service_path = ConfigureService(kConfigWifi1Shared);
metadata_store()->OnConfigurationCreated(service_path, kGuid);
base::RunLoop().RunUntilIdle();
ASSERT_EQ(0, metadata_observer()->GetNumberOfUpdates(kGuid));
ASSERT_FALSE(metadata_store()->GetIsFieldExternallyModified(
kGuid, shill::kProxyConfigProperty));
LoginUser(secondary_user_);
base::DictionaryValue other_properties;
other_properties.SetKey(shill::kAutoConnectProperty, base::Value(true));
other_properties.SetKey(shill::kProxyConfigProperty,
base::Value("proxy_details"));
network_configuration_handler()->SetShillProperties(
service_path, other_properties, base::DoNothing(), base::DoNothing());
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(metadata_store()->GetIsFieldExternallyModified(
kGuid, shill::kProxyConfigProperty));
LoginUser(primary_user_);
base::DictionaryValue owner_properties;
owner_properties.SetKey(shill::kProxyConfigProperty,
base::Value("new_proxy_details"));
network_configuration_handler()->SetShillProperties(
service_path, owner_properties, base::DoNothing(), base::DoNothing());
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(metadata_store()->GetIsFieldExternallyModified(
kGuid, shill::kProxyConfigProperty));
}
TEST_F(NetworkMetadataStoreTest, ConfigurationRemoved) {
std::string service_path = ConfigureService(kConfigWifi0Connectable);
network_connection_handler()->ConnectToNetwork(
service_path, base::DoNothing(), base::DoNothing(),
true /* check_error_state */, ConnectCallbackMode::ON_COMPLETED);
base::RunLoop().RunUntilIdle();
metadata_store()->SetIsConfiguredBySync(kGuid);
ASSERT_FALSE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_TRUE(metadata_store()->GetIsConfiguredBySync(kGuid));
network_configuration_handler()->RemoveConfiguration(
service_path, /*remove_confirmer=*/base::nullopt, base::DoNothing(),
base::DoNothing());
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(metadata_store()->GetLastConnectedTimestamp(kGuid).is_zero());
ASSERT_FALSE(metadata_store()->GetIsConfiguredBySync(kGuid));
}
TEST_F(NetworkMetadataStoreTest, OwnOobeNetworks) {
UserManager()->LogoutAllUsers();
ConfigureService(kConfigWifi1Shared);
base::RunLoop().RunUntilIdle();
LoginUser(primary_user_);
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
UserManager()->set_is_current_user_new(true);
UserManager()->set_is_current_user_owner(true);
metadata_store()->LoggedInStateChanged();
ASSERT_TRUE(metadata_store()->GetIsCreatedByUser(kGuid));
}
TEST_F(NetworkMetadataStoreTest, OwnOobeNetworks_EnterpriseEnrolled) {
SetIsEnterpriseEnrolled(true);
UserManager()->LogoutAllUsers();
ConfigureService(kConfigWifi1Shared);
base::RunLoop().RunUntilIdle();
LoginUser(primary_user_);
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
UserManager()->set_is_current_user_new(true);
UserManager()->set_is_current_user_owner(true);
metadata_store()->LoggedInStateChanged();
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
}
TEST_F(NetworkMetadataStoreTest, OwnOobeNetworks_NotOwner) {
UserManager()->LogoutAllUsers();
ConfigureService(kConfigWifi1Shared);
base::RunLoop().RunUntilIdle();
LoginUser(primary_user_);
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
UserManager()->set_is_current_user_new(true);
UserManager()->set_is_current_user_owner(false);
metadata_store()->LoggedInStateChanged();
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
}
TEST_F(NetworkMetadataStoreTest, OwnOobeNetworks_NotFirstLogin) {
UserManager()->LogoutAllUsers();
ConfigureService(kConfigWifi1Shared);
base::RunLoop().RunUntilIdle();
LoginUser(primary_user_);
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
UserManager()->set_is_current_user_new(false);
UserManager()->set_is_current_user_owner(true);
metadata_store()->LoggedInStateChanged();
ASSERT_FALSE(metadata_store()->GetIsCreatedByUser(kGuid));
}
} // namespace chromeos