chromium/ash/components/arc/net/always_on_vpn_manager_unittest.cc

// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/components/arc/net/always_on_vpn_manager.h"

#include <string_view>

#include "ash/components/arc/arc_prefs.h"
#include "base/functional/bind.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "chromeos/ash/components/dbus/shill/shill_manager_client.h"
#include "chromeos/ash/components/network/network_handler_test_helper.h"
#include "components/prefs/testing_pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace {

constexpr const char kVpnPackage[] = "com.android.vpn";
const base::Value kVpnPackageValue(kVpnPackage);

void OnGetProperties(bool* success_out,
                     std::string* package_name_out,
                     base::OnceClosure callback,
                     std::optional<base::Value::Dict> result) {
  *success_out = result.has_value();
  if (result) {
    const std::string* value =
        result->FindString(shill::kAlwaysOnVpnPackageProperty);
    if (value != nullptr)
      *package_name_out = *value;
  }
  std::move(callback).Run();
}

std::string GetAlwaysOnPackageName() {
  bool success = false;
  std::string package_name;
  ash::ShillManagerClient* shill_manager = ash::ShillManagerClient::Get();
  base::RunLoop run_loop;
  shill_manager->GetProperties(
      base::BindOnce(&OnGetProperties, base::Unretained(&success),
                     base::Unretained(&package_name), run_loop.QuitClosure()));
  run_loop.Run();
  EXPECT_TRUE(success);
  return package_name;
}

}  // namespace

namespace arc {
namespace {

class AlwaysOnVpnManagerTest : public testing::Test {
 public:
  AlwaysOnVpnManagerTest() = default;

  AlwaysOnVpnManagerTest(const AlwaysOnVpnManagerTest&) = delete;
  AlwaysOnVpnManagerTest& operator=(const AlwaysOnVpnManagerTest&) = delete;

  void SetUp() override {
    arc::prefs::RegisterProfilePrefs(pref_service()->registry());
  }

  TestingPrefServiceSimple* pref_service() { return &pref_service_; }

 private:
  content::BrowserTaskEnvironment task_environment_;
  ash::NetworkHandlerTestHelper network_handler_test_helper_;
  TestingPrefServiceSimple pref_service_;
};

TEST_F(AlwaysOnVpnManagerTest, SetPackageWhileLockdownUnset) {
  auto always_on_manager = std::make_unique<AlwaysOnVpnManager>(
      pref_service(), /*delay_lockdown_until_vpn_connected=*/false);

  EXPECT_EQ(std::string(), GetAlwaysOnPackageName());

  pref_service()->Set(arc::prefs::kAlwaysOnVpnPackage, kVpnPackageValue);

  EXPECT_EQ(std::string(), GetAlwaysOnPackageName());
}

TEST_F(AlwaysOnVpnManagerTest, SetPackageWhileLockdownTrue) {
  pref_service()->Set(arc::prefs::kAlwaysOnVpnLockdown, base::Value(true));

  auto always_on_manager = std::make_unique<AlwaysOnVpnManager>(
      pref_service(), /*delay_lockdown_until_vpn_connected=*/false);

  EXPECT_EQ(std::string(), GetAlwaysOnPackageName());

  pref_service()->Set(arc::prefs::kAlwaysOnVpnPackage, kVpnPackageValue);

  EXPECT_EQ(kVpnPackage, GetAlwaysOnPackageName());

  pref_service()->Set(arc::prefs::kAlwaysOnVpnPackage,
                      base::Value(std::string_view()));

  EXPECT_EQ(std::string(), GetAlwaysOnPackageName());
}

TEST_F(AlwaysOnVpnManagerTest, SetPackageThatsAlreadySetAtBoot) {
  pref_service()->Set(arc::prefs::kAlwaysOnVpnLockdown, base::Value(true));
  pref_service()->Set(arc::prefs::kAlwaysOnVpnPackage, kVpnPackageValue);

  auto always_on_manager = std::make_unique<AlwaysOnVpnManager>(
      pref_service(), /*delay_lockdown_until_vpn_connected=*/false);

  EXPECT_EQ(kVpnPackage, GetAlwaysOnPackageName());
}

TEST_F(AlwaysOnVpnManagerTest, SetLockdown) {
  pref_service()->Set(arc::prefs::kAlwaysOnVpnPackage, kVpnPackageValue);

  auto always_on_manager = std::make_unique<AlwaysOnVpnManager>(
      pref_service(), /*delay_lockdown_until_vpn_connected=*/false);

  pref_service()->Set(arc::prefs::kAlwaysOnVpnLockdown, base::Value(true));

  EXPECT_EQ(kVpnPackage, GetAlwaysOnPackageName());

  pref_service()->Set(arc::prefs::kAlwaysOnVpnLockdown, base::Value(false));

  EXPECT_EQ(std::string(), GetAlwaysOnPackageName());
}

// Verify that the shill::kAlwaysOnVpnPackageProperty property is not set if the
// browser user traffic is restricted by the AlwaysOnVpnPreConnectUrlAllowlist
// preference.
TEST_F(AlwaysOnVpnManagerTest, EnforceAlwaysOnVpnPreConnectUrlAllowlist) {
  auto always_on_manager = std::make_unique<AlwaysOnVpnManager>(
      pref_service(), /*delay_lockdown_until_vpn_connected=*/false);

  pref_service()->Set(arc::prefs::kAlwaysOnVpnLockdown, base::Value(true));
  pref_service()->Set(arc::prefs::kAlwaysOnVpnPackage, kVpnPackageValue);
  EXPECT_EQ(kVpnPackage, GetAlwaysOnPackageName());

  always_on_manager->SetDelayLockdownUntilVpnConnectedState(/*enabled=*/true);
  EXPECT_EQ(std::string(), GetAlwaysOnPackageName());

  always_on_manager->SetDelayLockdownUntilVpnConnectedState(
      /*enabled=*/false);
  EXPECT_EQ(kVpnPackage, GetAlwaysOnPackageName());
}

}  // namespace
}  // namespace arc