blob: 20fdf8b5c05a1487bc5238098bfb15c8a9edaa74 [file] [log] [blame]
// Copyright 2021 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/cellular_policy_handler.h"
#include <memory>
#include "ash/constants/ash_features.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "chromeos/dbus/hermes/hermes_clients.h"
#include "chromeos/dbus/shill/shill_clients.h"
#include "chromeos/network/cellular_connection_handler.h"
#include "chromeos/network/cellular_esim_installer.h"
#include "chromeos/network/cellular_inhibitor.h"
#include "chromeos/network/fake_network_connection_handler.h"
#include "chromeos/network/managed_network_configuration_handler.h"
#include "chromeos/network/network_configuration_handler.h"
#include "chromeos/network/network_connection_handler.h"
#include "chromeos/network/network_device_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/network/shill_property_util.h"
#include "chromeos/network/test_cellular_esim_profile_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/shill/dbus-constants.h"
namespace chromeos {
namespace {
const char kTestEuiccPath[] = "/org/chromium/Hermes/Euicc/0";
const char kTestEuiccPath2[] = "/org/chromium/Hermes/Euicc/1";
const char kTestEid[] = "12345678901234567890123456789012";
const char kTestEid2[] = "12345678901234567890123456789000";
const char kCellularGuid[] = "cellular_guid";
const char kICCID[] = "1000000000000000002";
void CheckShillConfiguration(bool is_installed) {
std::string service_path =
ShillServiceClient::Get()->GetTestInterface()->FindServiceMatchingGUID(
kCellularGuid);
const base::Value* properties =
ShillServiceClient::Get()->GetTestInterface()->GetServiceProperties(
service_path);
if (!is_installed) {
EXPECT_EQ(properties, nullptr);
return;
}
const std::string* guid = properties->FindStringKey(shill::kGuidProperty);
EXPECT_EQ(kCellularGuid, *guid);
// UIData should not be empty if cellular service is configured.
const std::string* ui_data_value =
properties->FindStringKey(shill::kUIDataProperty);
EXPECT_NE(*ui_data_value, std::string());
const std::string* iccid = properties->FindStringKey(shill::kIccidProperty);
EXPECT_EQ(kICCID, *iccid);
}
std::string GenerateCellularPolicy(const std::string& smdp_address) {
return base::StringPrintf(
R"({"GUID": "%s", "Type": "Cellular",
"Name": "cellular1",
"Cellular": { "SMDPAddress": "%s"}})",
kCellularGuid, smdp_address.c_str());
}
} // namespace
class CellularPolicyHandlerTest : public testing::Test {
protected:
CellularPolicyHandlerTest() = default;
~CellularPolicyHandlerTest() override = default;
// testing::Test
void SetUp() override {
shill_clients::InitializeFakes();
hermes_clients::InitializeFakes();
network_state_handler_ = NetworkStateHandler::InitializeForTest();
network_device_handler_ = NetworkDeviceHandler::InitializeForTesting(
network_state_handler_.get());
network_profile_handler_ = NetworkProfileHandler::InitializeForTesting();
network_connection_handler_ =
std::make_unique<FakeNetworkConnectionHandler>();
cellular_inhibitor_ = std::make_unique<CellularInhibitor>();
cellular_inhibitor_->Init(network_state_handler_.get(),
network_device_handler_.get());
cellular_esim_profile_handler_ =
std::make_unique<TestCellularESimProfileHandler>();
cellular_esim_profile_handler_->Init(network_state_handler_.get(),
cellular_inhibitor_.get());
cellular_connection_handler_ =
std::make_unique<CellularConnectionHandler>();
cellular_connection_handler_->Init(network_state_handler_.get(),
cellular_inhibitor_.get(),
cellular_esim_profile_handler_.get());
cellular_esim_installer_ = std::make_unique<CellularESimInstaller>();
cellular_esim_installer_->Init(
cellular_connection_handler_.get(), cellular_inhibitor_.get(),
network_connection_handler_.get(), network_profile_handler_.get(),
network_state_handler_.get());
network_configuration_handler_ =
base::WrapUnique<NetworkConfigurationHandler>(
NetworkConfigurationHandler::InitializeForTest(
network_state_handler_.get(), network_device_handler_.get()));
managed_network_configuration_handler_ =
ManagedNetworkConfigurationHandler::InitializeForTesting(
network_state_handler_.get(), network_profile_handler_.get(),
network_device_handler_.get(), network_configuration_handler_.get(),
/*UIProxyConfigService=*/nullptr);
cellular_policy_handler_ = std::make_unique<CellularPolicyHandler>();
cellular_policy_handler_->Init(
cellular_esim_installer_.get(), network_profile_handler_.get(),
managed_network_configuration_handler_.get());
SetupEuicc();
}
void SetupEuicc() {
HermesManagerClient::Get()->GetTestInterface()->ClearEuiccs();
HermesManagerClient::Get()->GetTestInterface()->AddEuicc(
dbus::ObjectPath(kTestEuiccPath), kTestEid, /*is_active=*/true,
/*physical_slot=*/0);
base::RunLoop().RunUntilIdle();
}
// testing::Test
void TearDown() override {
cellular_policy_handler_.reset();
cellular_esim_installer_.reset();
cellular_esim_profile_handler_.reset();
cellular_connection_handler_.reset();
cellular_inhibitor_.reset();
network_configuration_handler_.reset();
managed_network_configuration_handler_.reset();
network_profile_handler_.reset();
network_device_handler_.reset();
network_state_handler_.reset();
network_connection_handler_.reset();
hermes_clients::Shutdown();
shill_clients::Shutdown();
}
void InstallESimPolicy(const std::string& onc_json,
const std::string& activation_code,
bool expect_install_success) {
base::Value policy = onc::ReadDictionaryFromJson(onc_json);
cellular_policy_handler_->InstallESim(
activation_code, base::Value::AsDictionaryValue(policy));
FastForwardProfileRefreshDelay();
base::RunLoop().RunUntilIdle();
if (expect_install_success) {
EXPECT_LE(1u, network_connection_handler_->connect_calls().size());
network_connection_handler_->connect_calls()
.back()
.InvokeSuccessCallback();
} else {
EXPECT_LE(0u, network_connection_handler_->connect_calls().size());
}
base::RunLoop().RunUntilIdle();
}
void FastForwardProfileRefreshDelay() {
const base::TimeDelta kProfileRefreshCallbackDelay =
base::TimeDelta::FromMilliseconds(150);
// Connect can result in two profile refresh calls before and after
// enabling profile. Fast forward by delay after refresh.
task_environment_.FastForwardBy(2 * kProfileRefreshCallbackDelay);
}
private:
base::test::TaskEnvironment task_environment_{
base::test::TaskEnvironment::TimeSource::MOCK_TIME};
std::unique_ptr<NetworkStateHandler> network_state_handler_;
std::unique_ptr<NetworkDeviceHandler> network_device_handler_;
std::unique_ptr<CellularConnectionHandler> cellular_connection_handler_;
std::unique_ptr<CellularInhibitor> cellular_inhibitor_;
std::unique_ptr<TestCellularESimProfileHandler>
cellular_esim_profile_handler_;
std::unique_ptr<FakeNetworkConnectionHandler> network_connection_handler_;
std::unique_ptr<CellularESimInstaller> cellular_esim_installer_;
std::unique_ptr<NetworkProfileHandler> network_profile_handler_;
std::unique_ptr<NetworkConfigurationHandler> network_configuration_handler_;
std::unique_ptr<ManagedNetworkConfigurationHandler>
managed_network_configuration_handler_;
std::unique_ptr<CellularPolicyHandler> cellular_policy_handler_;
};
TEST_F(CellularPolicyHandlerTest, InstallProfileSuccess) {
const std::string policy =
GenerateCellularPolicy(HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode());
// Verify esim profile get installed successfully when installing policy esim
// with a fake SMDP address.
InstallESimPolicy(policy,
HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode(),
/*expect_install_success=*/true);
CheckShillConfiguration(/*is_installed=*/true);
}
TEST_F(CellularPolicyHandlerTest, InstallProfileFailure) {
// Verify esim profile doesn't get installed when installing policy esim
// with a invalid SMDP address.
const std::string policy = GenerateCellularPolicy("000");
InstallESimPolicy(policy,
/*activation_code=*/std::string(),
/*expect_install_success=*/false);
CheckShillConfiguration(/*is_installed=*/false);
}
TEST_F(CellularPolicyHandlerTest, InstallOnExternalEUICC) {
// Verify esim profile get installed successfully when installing policy
// on the external EUICC.
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(ash::features::kCellularUseExternalEuicc);
HermesManagerClient::Get()->GetTestInterface()->AddEuicc(
dbus::ObjectPath(kTestEuiccPath2), kTestEid2, /*is_active=*/true,
/*physical_slot=*/1);
base::RunLoop().RunUntilIdle();
const std::string policy =
GenerateCellularPolicy(HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode());
InstallESimPolicy(policy,
HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode(),
/*expect_install_success=*/true);
CheckShillConfiguration(/*is_installed=*/true);
}
TEST_F(CellularPolicyHandlerTest, InstallNoEUICCAvailable) {
// Verify esim profile doesn't get installed when installing policy esim
// with no available EUICC.
HermesManagerClient::Get()->GetTestInterface()->ClearEuiccs();
base::RunLoop().RunUntilIdle();
const std::string policy =
GenerateCellularPolicy(HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode());
InstallESimPolicy(policy,
HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode(),
/*expect_install_success=*/false);
CheckShillConfiguration(/*is_installed=*/false);
}
TEST_F(CellularPolicyHandlerTest, UpdateSMDPAddress) {
// Verify that the first request should be invalidated when the second
// request is queued.
std::string policy = GenerateCellularPolicy("000");
InstallESimPolicy(policy,
/*activation_code=*/"000",
/*expect_install_success=*/false);
policy = GenerateCellularPolicy(HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode());
InstallESimPolicy(policy,
HermesEuiccClient::Get()
->GetTestInterface()
->GenerateFakeActivationCode(),
/*expect_install_success=*/true);
CheckShillConfiguration(/*is_installed=*/true);
}
} // namespace chromeos