// Copyright 2017 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 "components/arc/arc_util.h" #include #include #include "ash/public/cpp/app_types.h" #include "base/base_switches.h" #include "base/command_line.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/test/scoped_feature_list.h" #include "components/signin/core/account_id/account_id.h" #include "components/user_manager/fake_user_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "components/user_manager/user.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/test/test_windows.h" #include "ui/aura/window.h" namespace arc { namespace { // If an instance is created, based on the value passed to the constructor, // EnableARC feature is enabled/disabled in the scope. class ScopedArcFeature { public: explicit ScopedArcFeature(bool enabled) { constexpr char kArcFeatureName[] = "EnableARC"; if (enabled) { feature_list.InitFromCommandLine(kArcFeatureName, std::string()); } else { feature_list.InitFromCommandLine(std::string(), kArcFeatureName); } } ~ScopedArcFeature() = default; private: base::test::ScopedFeatureList feature_list; DISALLOW_COPY_AND_ASSIGN(ScopedArcFeature); }; // Fake user that can be created with a specified type. class FakeUser : public user_manager::User { public: explicit FakeUser(user_manager::UserType user_type) : User(AccountId::FromUserEmailGaiaId("user@test.com", "1234567890")), user_type_(user_type) {} ~FakeUser() override = default; // user_manager::User: user_manager::UserType GetType() const override { return user_type_; } private: const user_manager::UserType user_type_; DISALLOW_COPY_AND_ASSIGN(FakeUser); }; using ArcUtilTest = testing::Test; TEST_F(ArcUtilTest, IsArcAvailable_None) { auto* command_line = base::CommandLine::ForCurrentProcess(); command_line->InitFromArgv({"", "--arc-availability=none"}); EXPECT_FALSE(IsArcAvailable()); // If --arc-availability flag is set to "none", even if Finch experiment is // turned on, ARC cannot be used. { ScopedArcFeature feature(true); EXPECT_FALSE(IsArcAvailable()); } } // Test --arc-available with EnableARC feature combination. TEST_F(ArcUtilTest, IsArcAvailable_Installed) { auto* command_line = base::CommandLine::ForCurrentProcess(); // If ARC is not installed, IsArcAvailable() should return false, // regardless of EnableARC feature. command_line->InitFromArgv({""}); // Not available, by-default. EXPECT_FALSE(IsArcAvailable()); EXPECT_FALSE(IsArcKioskAvailable()); { ScopedArcFeature feature(true); EXPECT_FALSE(IsArcAvailable()); EXPECT_FALSE(IsArcKioskAvailable()); } { ScopedArcFeature feature(false); EXPECT_FALSE(IsArcAvailable()); EXPECT_FALSE(IsArcKioskAvailable()); } // If ARC is installed, IsArcAvailable() should return true when EnableARC // feature is set. command_line->InitFromArgv({"", "--arc-available"}); // Not available, by-default, too. EXPECT_FALSE(IsArcAvailable()); // ARC is available in kiosk mode if installed. EXPECT_TRUE(IsArcKioskAvailable()); { ScopedArcFeature feature(true); EXPECT_TRUE(IsArcAvailable()); EXPECT_TRUE(IsArcKioskAvailable()); } { ScopedArcFeature feature(false); EXPECT_FALSE(IsArcAvailable()); EXPECT_TRUE(IsArcKioskAvailable()); } // If ARC is installed, IsArcAvailable() should return true when EnableARC // feature is set. command_line->InitFromArgv({"", "--arc-availability=installed"}); // Not available, by-default, too. EXPECT_FALSE(IsArcAvailable()); // ARC is available in kiosk mode if installed. EXPECT_TRUE(IsArcKioskAvailable()); { ScopedArcFeature feature(true); EXPECT_TRUE(IsArcAvailable()); EXPECT_TRUE(IsArcKioskAvailable()); } { ScopedArcFeature feature(false); EXPECT_FALSE(IsArcAvailable()); EXPECT_TRUE(IsArcKioskAvailable()); } } TEST_F(ArcUtilTest, IsArcAvailable_OfficiallySupported) { // Regardless of FeatureList, IsArcAvailable() should return true. auto* command_line = base::CommandLine::ForCurrentProcess(); command_line->InitFromArgv({"", "--enable-arc"}); EXPECT_TRUE(IsArcAvailable()); EXPECT_TRUE(IsArcKioskAvailable()); command_line->InitFromArgv({"", "--arc-availability=officially-supported"}); EXPECT_TRUE(IsArcAvailable()); EXPECT_TRUE(IsArcKioskAvailable()); } // TODO(hidehiko): Add test for IsArcKioskMode(). // It depends on UserManager, but a utility to inject fake instance is // available only in chrome/. To use it in components/, refactoring is needed. TEST_F(ArcUtilTest, IsArcOptInVerificationDisabled) { auto* command_line = base::CommandLine::ForCurrentProcess(); command_line->InitFromArgv({""}); EXPECT_FALSE(IsArcOptInVerificationDisabled()); command_line->InitFromArgv({"", "--disable-arc-opt-in-verification"}); EXPECT_TRUE(IsArcOptInVerificationDisabled()); } TEST_F(ArcUtilTest, IsArcAppWindow) { std::unique_ptr window( aura::test::CreateTestWindowWithId(0, nullptr)); EXPECT_FALSE(IsArcAppWindow(window.get())); window->SetProperty(aura::client::kAppType, static_cast(ash::AppType::CHROME_APP)); EXPECT_FALSE(IsArcAppWindow(window.get())); window->SetProperty(aura::client::kAppType, static_cast(ash::AppType::ARC_APP)); EXPECT_TRUE(IsArcAppWindow(window.get())); EXPECT_FALSE(IsArcAppWindow(nullptr)); } TEST_F(ArcUtilTest, IsArcAllowedForUser) { user_manager::FakeUserManager* fake_user_manager = new user_manager::FakeUserManager(); user_manager::ScopedUserManager scoped_user_manager( base::WrapUnique(fake_user_manager)); struct { user_manager::UserType user_type; bool expected_allowed; } const kTestCases[] = { {user_manager::USER_TYPE_REGULAR, true}, {user_manager::USER_TYPE_GUEST, false}, {user_manager::USER_TYPE_PUBLIC_ACCOUNT, true}, {user_manager::USER_TYPE_SUPERVISED, false}, {user_manager::USER_TYPE_KIOSK_APP, false}, {user_manager::USER_TYPE_CHILD, false}, {user_manager::USER_TYPE_ARC_KIOSK_APP, true}, {user_manager::USER_TYPE_ACTIVE_DIRECTORY, true}, }; for (const auto& test_case : kTestCases) { const FakeUser user(test_case.user_type); EXPECT_EQ(test_case.expected_allowed, IsArcAllowedForUser(&user)) << "User type=" << test_case.user_type; } // An ephemeral user is a logged in user but unknown to UserManager when // ephemeral policy is set. fake_user_manager->SetEphemeralUsersEnabled(true); fake_user_manager->UserLoggedIn( AccountId::FromUserEmailGaiaId("test@test.com", "9876543210"), "test@test.com-hash", false /* browser_restart */, false /* is_child */); const user_manager::User* ephemeral_user = fake_user_manager->GetActiveUser(); ASSERT_TRUE(ephemeral_user); ASSERT_TRUE(fake_user_manager->IsUserCryptohomeDataEphemeral( ephemeral_user->GetAccountId())); // Ephemeral user is also allowed for ARC. EXPECT_TRUE(IsArcAllowedForUser(ephemeral_user)); } TEST_F(ArcUtilTest, IsArcAllowedForChildUserWithExperiment) { auto* command_line = base::CommandLine::ForCurrentProcess(); command_line->InitFromArgv( {"", "--enable-features=ArcAvailableForChildAccount"}); base::test::ScopedFeatureList feature_list; feature_list.InitFromCommandLine( command_line->GetSwitchValueASCII(switches::kEnableFeatures), command_line->GetSwitchValueASCII(switches::kDisableFeatures)); const FakeUser user(user_manager::USER_TYPE_CHILD); EXPECT_TRUE(IsArcAllowedForUser(&user)); } TEST_F(ArcUtilTest, ArcStartModeDefault) { auto* command_line = base::CommandLine::ForCurrentProcess(); command_line->InitFromArgv({"", "--arc-availability=installed"}); EXPECT_FALSE(ShouldArcAlwaysStart()); EXPECT_TRUE(IsPlayStoreAvailable()); } TEST_F(ArcUtilTest, ArcStartModeWithoutPlayStore) { auto* command_line = base::CommandLine::ForCurrentProcess(); command_line->InitFromArgv( {"", "--arc-availability=installed", "--arc-start-mode=always-start-with-no-play-store"}); EXPECT_TRUE(ShouldArcAlwaysStart()); EXPECT_FALSE(IsPlayStoreAvailable()); } } // namespace } // namespace arc