chromium/chrome/browser/ash/platform_keys/key_permissions/arc_key_permissions_manager_delegate_unittest.cc

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

#include "chrome/browser/ash/platform_keys/key_permissions/arc_key_permissions_manager_delegate.h"

#include <memory>
#include <string>

#include "ash/components/arc/arc_prefs.h"
#include "ash/components/arc/test/fake_app_instance.h"
#include "base/memory/raw_ptr.h"
#include "base/values.h"
#include "chrome/browser/ash/app_list/arc/arc_app_list_prefs.h"
#include "chrome/browser/ash/app_list/arc/arc_app_test.h"
#include "chrome/test/base/testing_profile.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/core/common/policy_map.h"
#include "components/policy/core/common/policy_service_impl.h"
#include "components/policy/core/common/policy_types.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace ash {
namespace platform_keys {

namespace {

constexpr char kTestArcPackageName1[] = "com.example.app1";
constexpr char kTestArcPackageName2[] = "com.example.app2";

}  // namespace

class MockArcKpmDelegateObserver : public ArcKpmDelegate::Observer {
 public:
  MockArcKpmDelegateObserver() = default;
  MockArcKpmDelegateObserver(const MockArcKpmDelegateObserver&) = delete;
  MockArcKpmDelegateObserver& operator=(const MockArcKpmDelegateObserver&) =
      delete;
  ~MockArcKpmDelegateObserver() override = default;

  MOCK_METHOD(void,
              OnArcUsageAllowanceForCorporateKeysChanged,
              (bool allowed),
              (override));
};

class ArcKeyPermissionsManagerDelegateTest : public testing::Test {
 public:
  ArcKeyPermissionsManagerDelegateTest() = default;
  ArcKeyPermissionsManagerDelegateTest(
      const ArcKeyPermissionsManagerDelegateTest& other) = delete;
  ArcKeyPermissionsManagerDelegateTest& operator=(
      const ArcKeyPermissionsManagerDelegateTest& other) = delete;
  ~ArcKeyPermissionsManagerDelegateTest() override = default;

  void SetUp() override {
    policy_provider_ = std::make_unique<
        testing::NiceMock<policy::MockConfigurationPolicyProvider>>();
    policy_provider_->SetDefaultReturns(
        /*is_initialization_complete_return=*/true,
        /*is_first_policy_load_complete_return=*/true);
    std::vector<
        raw_ptr<policy::ConfigurationPolicyProvider, VectorExperimental>>
        providers = {policy_provider_.get()};
    auto policy_service_ =
        std::make_unique<policy::PolicyServiceImpl>(providers);

    TestingProfile::Builder builder;
    builder.SetPolicyService(std::move(policy_service_));
    profile_ = builder.Build();

    arc_app_test_.SetUp(profile_.get());
    app_instance_ = std::make_unique<arc::FakeAppInstance>(
        arc_app_test_.arc_app_list_prefs());

    system_delegate_ = std::make_unique<SystemTokenArcKpmDelegate>();
    SystemTokenArcKpmDelegate::SetSystemTokenArcKpmDelegateForTesting(
        system_delegate_.get());

    CreatePrimaryUserDelegate();
  }

  void TearDown() override {
    arc_app_test_.TearDown();
    if (primary_user_delegate_) {
      ShutDownPrimaryUserDelegate();
    }
    system_delegate_.reset();
    profile_.reset();
  }

 protected:
  void InstallArcPackage(const std::string& package_name) {
    arc::mojom::ArcPackageInfo package;
    package.package_name = package_name;
    app_instance_->InstallPackage(package.Clone());
  }

  void UninstallArcPackage(const std::string& package_name) {
    app_instance_->UninstallPackage(package_name);
  }

  void SetCorporateUsageInPolicyForPackage(const std::string& package_name,
                                           bool allowed) {
    base::Value::Dict corporate_key_usage;
    corporate_key_usage.SetByDottedPath("allowCorporateKeyUsage", allowed);

    base::Value::Dict policy_value;
    policy_value.Set(package_name, base::Value(std::move(corporate_key_usage)));

    policy::PolicyMap policy_map;
    policy_map.Set(policy::key::kKeyPermissions, policy::POLICY_LEVEL_MANDATORY,
                   policy::POLICY_SCOPE_MACHINE, policy::POLICY_SOURCE_PLATFORM,
                   base::Value(policy_value.Clone()), nullptr);

    policy_provider_->UpdateChromePolicy(policy_map);
  }

  void CreatePrimaryUserDelegate() {
    primary_user_delegate_ =
        std::make_unique<UserPrivateTokenArcKpmDelegate>(profile_.get());

    primary_user_delegate_->AddObserver(&mock_arc_kpm_delegate_observer_);
  }

  void ShutDownPrimaryUserDelegate() {
    primary_user_delegate_->RemoveObserver(&mock_arc_kpm_delegate_observer_);
    primary_user_delegate_->Shutdown();
    primary_user_delegate_.reset();
  }

  SystemTokenArcKpmDelegate* system_delegate() {
    return system_delegate_.get();
  }

  UserPrivateTokenArcKpmDelegate* user_delegate() {
    return primary_user_delegate_.get();
  }

  Profile* profile() { return profile_.get(); }

  testing::StrictMock<MockArcKpmDelegateObserver>
      mock_arc_kpm_delegate_observer_;

 private:
  content::BrowserTaskEnvironment task_environment_;
  std::unique_ptr<policy::MockConfigurationPolicyProvider> policy_provider_;
  ArcAppTest arc_app_test_;
  std::unique_ptr<arc::FakeAppInstance> app_instance_;
  std::unique_ptr<TestingProfile> profile_;
  std::unique_ptr<SystemTokenArcKpmDelegate> system_delegate_;
  std::unique_ptr<UserPrivateTokenArcKpmDelegate> primary_user_delegate_;
};

TEST_F(ArcKeyPermissionsManagerDelegateTest, Basic) {
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(true))
      .Times(1);
  InstallArcPackage(kTestArcPackageName1);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/true);

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, NoArcPackageInstalled) {
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(testing::_))
      .Times(0);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/true);

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, KeyPermissionsPolicyNotSet) {
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(testing::_))
      .Times(0);
  InstallArcPackage(kTestArcPackageName1);

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest,
       PolicyAndInstalledPackages_NoMatch) {
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(testing::_))
      .Times(0);
  InstallArcPackage(kTestArcPackageName1);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName2, /*allowed=*/true);

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, UninstallArcPackage) {
  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(true))
      .Times(1);
  InstallArcPackage(kTestArcPackageName1);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/true);
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), true);

  testing::Mock::VerifyAndClearExpectations(&mock_arc_kpm_delegate_observer_);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(false))
      .Times(1);
  UninstallArcPackage(kTestArcPackageName1);
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, UninstallIrrelevantArcPackage) {
  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(true))
      .Times(1);
  InstallArcPackage(kTestArcPackageName1);
  InstallArcPackage(kTestArcPackageName2);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/true);
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), true);

  testing::Mock::VerifyAndClearExpectations(&mock_arc_kpm_delegate_observer_);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(testing::_))
      .Times(0);
  UninstallArcPackage(kTestArcPackageName2);
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, ChangeKeyPermissionsPolicy) {
  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(true))
      .Times(1);
  InstallArcPackage(kTestArcPackageName1);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/true);
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), true);

  testing::Mock::VerifyAndClearExpectations(&mock_arc_kpm_delegate_observer_);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(false))
      .Times(1);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/false);
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, ArcDisabled) {
  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(true))
      .Times(1);
  InstallArcPackage(kTestArcPackageName1);
  SetCorporateUsageInPolicyForPackage(kTestArcPackageName1, /*allowed=*/true);

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), true);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), true);

  testing::Mock::VerifyAndClearExpectations(&mock_arc_kpm_delegate_observer_);

  EXPECT_CALL(mock_arc_kpm_delegate_observer_,
              OnArcUsageAllowanceForCorporateKeysChanged(false))
      .Times(1);
  profile()->GetPrefs()->SetBoolean(arc::prefs::kArcEnabled, false);

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
  EXPECT_EQ(user_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

TEST_F(ArcKeyPermissionsManagerDelegateTest, NoPrimaryDelegate) {
  ShutDownPrimaryUserDelegate();

  EXPECT_EQ(system_delegate()->AreCorporateKeysAllowedForArcUsage(), false);
}

}  // namespace platform_keys
}  // namespace ash