| // 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 <string> |
| |
| #include "base/auto_reset.h" |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/macros.h" |
| #include "base/memory/scoped_refptr.h" |
| #include "base/run_loop.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/chromeos/arc/arc_service_launcher.h" |
| #include "chrome/browser/chromeos/arc/arc_session_manager.h" |
| #include "chrome/browser/chromeos/arc/arc_util.h" |
| #include "chrome/browser/chromeos/arc/test/arc_data_removed_waiter.h" |
| #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h" |
| #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" |
| #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/extensions/api/tabs/tabs_api.h" |
| #include "chrome/browser/extensions/extension_function_test_utils.h" |
| #include "chrome/browser/extensions/extension_tab_util.h" |
| #include "chrome/browser/policy/profile_policy_connector.h" |
| #include "chrome/browser/policy/profile_policy_connector_factory.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" |
| #include "chrome/test/base/in_process_browser_test.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/account_id/account_id.h" |
| #include "components/arc/arc_prefs.h" |
| #include "components/arc/arc_service_manager.h" |
| #include "components/arc/arc_util.h" |
| #include "components/arc/session/arc_session_runner.h" |
| #include "components/arc/test/fake_arc_session.h" |
| #include "components/policy/core/common/cloud/device_management_service.h" |
| #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" |
| #include "components/policy/core/common/cloud/user_cloud_policy_manager.h" |
| #include "components/policy/core/common/policy_switches.h" |
| #include "components/prefs/pref_member.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/user_manager/scoped_user_manager.h" |
| #include "components/user_manager/user_manager.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/extension_builder.h" |
| #include "net/base/upload_bytes_element_reader.h" |
| #include "net/base/upload_data_stream.h" |
| #include "net/url_request/url_request_test_job.h" |
| #include "services/identity/public/cpp/identity_test_environment.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| namespace { |
| |
| // Set managed auth token for Android managed accounts. |
| constexpr char kManagedAuthToken[] = "managed-auth-token"; |
| // Set unmanaged auth token for other Android unmanaged accounts. |
| constexpr char kUnmanagedAuthToken[] = "unmanaged-auth-token"; |
| constexpr char kWellKnownConsumerName[] = "test@gmail.com"; |
| constexpr char kFakeUserName[] = "test@example.com"; |
| constexpr char kFakeGaiaId[] = "1234567890"; |
| |
| } // namespace |
| |
| namespace arc { |
| |
| // Waits for the "arc.enabled" preference value from true to false. |
| class ArcPlayStoreDisabledWaiter : public ArcSessionManager::Observer { |
| public: |
| ArcPlayStoreDisabledWaiter() { ArcSessionManager::Get()->AddObserver(this); } |
| |
| ~ArcPlayStoreDisabledWaiter() override { |
| ArcSessionManager::Get()->RemoveObserver(this); |
| } |
| |
| void Wait() { |
| base::RunLoop run_loop; |
| base::AutoReset<base::RunLoop*> reset(&run_loop_, &run_loop); |
| run_loop.Run(); |
| } |
| |
| private: |
| // ArcSessionManager::Observer override: |
| void OnArcPlayStoreEnabledChanged(bool enabled) override { |
| if (!enabled) { |
| DCHECK(run_loop_); |
| run_loop_->Quit(); |
| } |
| } |
| |
| base::RunLoop* run_loop_ = nullptr; |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcPlayStoreDisabledWaiter); |
| }; |
| |
| class ArcSessionManagerTest : public chromeos::MixinBasedInProcessBrowserTest { |
| protected: |
| ArcSessionManagerTest() {} |
| |
| // MixinBasedInProcessBrowserTest: |
| ~ArcSessionManagerTest() override {} |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| chromeos::MixinBasedInProcessBrowserTest::SetUpCommandLine(command_line); |
| arc::SetArcAvailableCommandLineForTesting(command_line); |
| } |
| |
| void SetUpOnMainThread() override { |
| chromeos::MixinBasedInProcessBrowserTest::SetUpOnMainThread(); |
| user_manager_enabler_ = std::make_unique<user_manager::ScopedUserManager>( |
| std::make_unique<chromeos::FakeChromeUserManager>()); |
| // Init ArcSessionManager for testing. |
| ArcServiceLauncher::Get()->ResetForTesting(); |
| ArcSessionManager::SetUiEnabledForTesting(false); |
| ArcSessionManager::EnableCheckAndroidManagementForTesting(true); |
| ArcSessionManager::Get()->SetArcSessionRunnerForTesting( |
| std::make_unique<ArcSessionRunner>( |
| base::BindRepeating(FakeArcSession::Create))); |
| |
| ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| |
| chromeos::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(true); |
| |
| const AccountId account_id( |
| AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId)); |
| GetFakeUserManager()->AddUser(account_id); |
| GetFakeUserManager()->LoginUser(account_id); |
| |
| // Create test profile. |
| TestingProfile::Builder profile_builder; |
| profile_builder.SetPath(temp_dir_.GetPath().AppendASCII("TestArcProfile")); |
| profile_builder.SetProfileName(kFakeUserName); |
| profile_ = IdentityTestEnvironmentProfileAdaptor:: |
| CreateProfileForIdentityTestEnvironment(profile_builder); |
| |
| identity_test_environment_adaptor_ = |
| std::make_unique<IdentityTestEnvironmentProfileAdaptor>(profile_.get()); |
| |
| // Seed account info properly. |
| identity_test_env()->MakePrimaryAccountAvailable(kFakeUserName); |
| |
| profile()->GetPrefs()->SetBoolean(prefs::kArcSignedIn, true); |
| profile()->GetPrefs()->SetBoolean(prefs::kArcTermsAccepted, true); |
| |
| // Set up ARC for test profile. |
| // Currently, ArcSessionManager is singleton and set up with the original |
| // Profile instance. This re-initializes the ArcServiceLauncher by |
| // overwriting Profile with profile(). |
| // TODO(hidehiko): This way several ArcService instances created with |
| // the original Profile instance on Browser creatuion are kept in the |
| // ArcServiceManager. For proper overwriting, those should be removed. |
| ArcServiceLauncher::Get()->OnPrimaryUserProfilePrepared(profile()); |
| } |
| |
| void TearDownOnMainThread() override { |
| // Explicitly removing the user is required; otherwise ProfileHelper keeps |
| // a dangling pointer to the User. |
| // TODO(nya): Consider removing all users from ProfileHelper in the |
| // destructor of FakeChromeUserManager. |
| const AccountId account_id( |
| AccountId::FromUserEmailGaiaId(kFakeUserName, kFakeGaiaId)); |
| GetFakeUserManager()->RemoveUserFromList(account_id); |
| // Since ArcServiceLauncher is (re-)set up with profile() in |
| // SetUpOnMainThread() it is necessary to Shutdown() before the profile() |
| // is destroyed. ArcServiceLauncher::Shutdown() will be called again on |
| // fixture destruction (because it is initialized with the original Profile |
| // instance in fixture, once), but it should be no op. |
| // TODO(hidehiko): Think about a way to test the code cleanly. |
| ArcServiceLauncher::Get()->Shutdown(); |
| identity_test_environment_adaptor_.reset(); |
| profile_.reset(); |
| base::RunLoop().RunUntilIdle(); |
| user_manager_enabler_.reset(); |
| chromeos::ProfileHelper::SetAlwaysReturnPrimaryUserForTesting(false); |
| chromeos::MixinBasedInProcessBrowserTest::TearDownOnMainThread(); |
| } |
| |
| chromeos::FakeChromeUserManager* GetFakeUserManager() const { |
| return static_cast<chromeos::FakeChromeUserManager*>( |
| user_manager::UserManager::Get()); |
| } |
| |
| void EnableArc() { |
| PrefService* const prefs = profile()->GetPrefs(); |
| prefs->SetBoolean(prefs::kArcEnabled, true); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void set_profile_name(const std::string& username) { |
| profile_->set_profile_name(username); |
| } |
| |
| Profile* profile() { return profile_.get(); } |
| |
| identity::IdentityTestEnvironment* identity_test_env() { |
| return identity_test_environment_adaptor_->identity_test_env(); |
| } |
| |
| private: |
| chromeos::LocalPolicyTestServerMixin local_policy_mixin_{&mixin_host_}; |
| std::unique_ptr<user_manager::ScopedUserManager> user_manager_enabler_; |
| std::unique_ptr<IdentityTestEnvironmentProfileAdaptor> |
| identity_test_environment_adaptor_; |
| base::ScopedTempDir temp_dir_; |
| std::unique_ptr<TestingProfile> profile_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcSessionManagerTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ConsumerAccount) { |
| EnableArc(); |
| identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( |
| kUnmanagedAuthToken, base::Time::Max()); |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, |
| ArcSessionManager::Get()->state()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, WellKnownConsumerAccount) { |
| set_profile_name(kWellKnownConsumerName); |
| EnableArc(); |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, |
| ArcSessionManager::Get()->state()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ManagedChromeAccount) { |
| policy::ProfilePolicyConnector* const connector = |
| policy::ProfilePolicyConnectorFactory::GetForBrowserContext(profile()); |
| connector->OverrideIsManagedForTesting(true); |
| |
| EnableArc(); |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, |
| ArcSessionManager::Get()->state()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ManagedAndroidAccount) { |
| EnableArc(); |
| identity_test_env()->WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( |
| kManagedAuthToken, base::Time::Max()); |
| ArcPlayStoreDisabledWaiter().Wait(); |
| EXPECT_FALSE(IsArcPlayStoreEnabledForProfile(profile())); |
| } |
| |
| // Make sure that ARC is disabled upon entering locked fullscreen mode. |
| IN_PROC_BROWSER_TEST_F(ArcSessionManagerTest, ArcDisabledInLockedFullscreen) { |
| EnableArc(); |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, |
| ArcSessionManager::Get()->state()); |
| |
| const int window_id = extensions::ExtensionTabUtil::GetWindowId(browser()); |
| const char kStateLockedFullscreen[] = |
| "[%u, {\"state\": \"locked-fullscreen\"}]"; |
| |
| auto function = base::MakeRefCounted<extensions::WindowsUpdateFunction>(); |
| scoped_refptr<const extensions::Extension> extension( |
| extensions::ExtensionBuilder("Test") |
| .SetID("pmgljoohajacndjcjlajcopidgnhphcl") |
| .AddPermission("lockWindowFullscreenPrivate") |
| .Build()); |
| function->set_extension(extension.get()); |
| |
| extension_function_test_utils::RunFunctionAndReturnSingleResult( |
| function.get(), base::StringPrintf(kStateLockedFullscreen, window_id), |
| browser()); |
| |
| ASSERT_EQ(ArcSessionManager::State::STOPPED, |
| ArcSessionManager::Get()->state()); |
| } |
| |
| } // namespace arc |