| // 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 <vector> |
| |
| #include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/macros.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/observer_list.h" |
| #include "base/run_loop.h" |
| #include "chrome/browser/chromeos/arc/arc_optin_uma.h" |
| #include "chrome/browser/chromeos/arc/arc_session_manager.h" |
| #include "chrome/browser/chromeos/arc/optin/arc_terms_of_service_oobe_negotiator.h" |
| #include "chrome/browser/chromeos/arc/test/arc_data_removed_waiter.h" |
| #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen_actor.h" |
| #include "chrome/browser/chromeos/login/screens/arc_terms_of_service_screen_actor_observer.h" |
| #include "chrome/browser/chromeos/login/ui/login_display_host.h" |
| #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" |
| #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h" |
| #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/policy/profile_policy_connector.h" |
| #include "chrome/browser/policy/profile_policy_connector_factory.h" |
| #include "chrome/browser/prefs/pref_service_syncable_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h" |
| #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chromeos/chromeos_switches.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "chromeos/dbus/fake_session_manager_client.h" |
| #include "components/arc/arc_service_manager.h" |
| #include "components/arc/arc_session_runner.h" |
| #include "components/arc/arc_util.h" |
| #include "components/arc/test/fake_arc_session.h" |
| #include "components/prefs/pref_service.h" |
| #include "components/signin/core/account_id/account_id.h" |
| #include "components/sync/model/fake_sync_change_processor.h" |
| #include "components/sync/model/sync_error_factory_mock.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "components/user_manager/user_manager.h" |
| #include "components/user_manager/user_names.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "google_apis/gaia/gaia_constants.h" |
| #include "google_apis/gaia/gaia_urls.h" |
| #include "net/http/http_status_code.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace arc { |
| |
| namespace { |
| |
| class FakeLoginDisplayHost : public chromeos::LoginDisplayHost { |
| public: |
| FakeLoginDisplayHost() { |
| DCHECK(!chromeos::LoginDisplayHost::default_host_); |
| chromeos::LoginDisplayHost::default_host_ = this; |
| } |
| |
| ~FakeLoginDisplayHost() override { |
| DCHECK_EQ(chromeos::LoginDisplayHost::default_host_, this); |
| chromeos::LoginDisplayHost::default_host_ = nullptr; |
| } |
| |
| /// chromeos::LoginDisplayHost: |
| chromeos::LoginDisplay* CreateLoginDisplay( |
| chromeos::LoginDisplay::Delegate* delegate) override { |
| return nullptr; |
| } |
| gfx::NativeWindow GetNativeWindow() const override { return nullptr; } |
| chromeos::OobeUI* GetOobeUI() const override { return nullptr; } |
| chromeos::WebUILoginView* GetWebUILoginView() const override { |
| return nullptr; |
| } |
| void BeforeSessionStart() override {} |
| void Finalize() override {} |
| void OnCompleteLogin() override {} |
| void OpenProxySettings() override {} |
| void SetStatusAreaVisible(bool visible) override {} |
| chromeos::AutoEnrollmentController* GetAutoEnrollmentController() override { |
| return nullptr; |
| } |
| void StartWizard(chromeos::OobeScreen first_screen) override {} |
| chromeos::WizardController* GetWizardController() override { return nullptr; } |
| chromeos::AppLaunchController* GetAppLaunchController() override { |
| return nullptr; |
| } |
| void StartUserAdding(const base::Closure& completion_callback) override {} |
| void CancelUserAdding() override {} |
| void StartSignInScreen(const chromeos::LoginScreenContext& context) override { |
| } |
| void OnPreferencesChanged() override {} |
| void PrewarmAuthentication() override {} |
| void StartAppLaunch(const std::string& app_id, |
| bool diagnostic_mode, |
| bool is_auto_launch) override {} |
| void StartDemoAppLaunch() override {} |
| void StartArcKiosk(const AccountId& account_id) override {} |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FakeLoginDisplayHost); |
| }; |
| |
| } // namespace |
| |
| // Bool parameter is used to implement ArcSessionOobeOptInTest tests for |
| // managed/unmanaged users. To prevent ambiguous testing::Test inheritance |
| // implement derivation here, in base class. |
| class ArcSessionManagerTestBase : public testing::TestWithParam<bool> { |
| public: |
| ArcSessionManagerTestBase() |
| : thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP), |
| user_manager_enabler_(new chromeos::FakeChromeUserManager()) {} |
| ~ArcSessionManagerTestBase() override = default; |
| |
| void SetUp() override { |
| chromeos::DBusThreadManager::GetSetterForTesting()->SetSessionManagerClient( |
| base::MakeUnique<chromeos::FakeSessionManagerClient>()); |
| |
| chromeos::DBusThreadManager::Initialize(); |
| |
| SetArcAvailableCommandLineForTesting( |
| base::CommandLine::ForCurrentProcess()); |
| ArcSessionManager::DisableUIForTesting(); |
| |
| EXPECT_TRUE(temp_dir_.CreateUniqueTempDir()); |
| TestingProfile::Builder profile_builder; |
| profile_builder.SetProfileName("user@gmail.com"); |
| profile_builder.SetPath(temp_dir_.GetPath().AppendASCII("TestArcProfile")); |
| |
| profile_ = profile_builder.Build(); |
| StartPreferenceSyncing(); |
| |
| arc_service_manager_ = base::MakeUnique<ArcServiceManager>(nullptr); |
| arc_session_manager_ = base::MakeUnique<ArcSessionManager>( |
| base::MakeUnique<ArcSessionRunner>(base::Bind(FakeArcSession::Create))); |
| |
| // Check initial conditions. |
| EXPECT_TRUE(arc_session_manager_->IsSessionStopped()); |
| |
| chromeos::WallpaperManager::Initialize(); |
| } |
| |
| void TearDown() override { |
| chromeos::WallpaperManager::Shutdown(); |
| arc_session_manager_.reset(); |
| arc_service_manager_.reset(); |
| chromeos::DBusThreadManager::Shutdown(); |
| } |
| |
| chromeos::FakeChromeUserManager* GetFakeUserManager() const { |
| return static_cast<chromeos::FakeChromeUserManager*>( |
| user_manager::UserManager::Get()); |
| } |
| |
| protected: |
| TestingProfile* profile() { return profile_.get(); } |
| |
| ArcSessionManager* arc_session_manager() { |
| return arc_session_manager_.get(); |
| } |
| |
| bool WaitForDataRemoved(ArcSessionManager::State expected_state) { |
| if (arc_session_manager()->state() != |
| ArcSessionManager::State::REMOVING_DATA_DIR) |
| return false; |
| |
| base::RunLoop().RunUntilIdle(); |
| if (arc_session_manager()->state() != expected_state) |
| return false; |
| |
| return true; |
| } |
| |
| private: |
| void StartPreferenceSyncing() const { |
| PrefServiceSyncableFromProfile(profile_.get()) |
| ->GetSyncableService(syncer::PREFERENCES) |
| ->MergeDataAndStartSyncing( |
| syncer::PREFERENCES, syncer::SyncDataList(), |
| base::MakeUnique<syncer::FakeSyncChangeProcessor>(), |
| base::MakeUnique<syncer::SyncErrorFactoryMock>()); |
| } |
| |
| content::TestBrowserThreadBundle thread_bundle_; |
| std::unique_ptr<TestingProfile> profile_; |
| std::unique_ptr<ArcServiceManager> arc_service_manager_; |
| std::unique_ptr<ArcSessionManager> arc_session_manager_; |
| chromeos::ScopedUserManagerEnabler user_manager_enabler_; |
| base::ScopedTempDir temp_dir_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcSessionManagerTestBase); |
| }; |
| |
| class ArcSessionManagerTest : public ArcSessionManagerTestBase { |
| public: |
| ArcSessionManagerTest() = default; |
| |
| void SetUp() override { |
| ArcSessionManagerTestBase::SetUp(); |
| |
| const AccountId account_id(AccountId::FromUserEmailGaiaId( |
| profile()->GetProfileUserName(), "1234567890")); |
| GetFakeUserManager()->AddUser(account_id); |
| GetFakeUserManager()->LoginUser(account_id); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ArcSessionManagerTest); |
| }; |
| |
| TEST_F(ArcSessionManagerTest, PrefChangeTriggersService) { |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| |
| PrefService* const pref = profile()->GetPrefs(); |
| ASSERT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); |
| |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| |
| ASSERT_TRUE(WaitForDataRemoved(ArcSessionManager::State::STOPPED)); |
| |
| pref->SetBoolean(prefs::kArcEnabled, true); |
| base::RunLoop().RunUntilIdle(); |
| ASSERT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| |
| pref->SetBoolean(prefs::kArcEnabled, false); |
| |
| ASSERT_TRUE(WaitForDataRemoved(ArcSessionManager::State::STOPPED)); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, DisabledForEphemeralDataUsers) { |
| PrefService* const prefs = profile()->GetPrefs(); |
| EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| prefs->SetBoolean(prefs::kArcEnabled, true); |
| |
| chromeos::FakeChromeUserManager* const fake_user_manager = |
| GetFakeUserManager(); |
| |
| fake_user_manager->AddUser(fake_user_manager->GetGuestAccountId()); |
| fake_user_manager->SwitchActiveUser(fake_user_manager->GetGuestAccountId()); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| |
| fake_user_manager->AddUser(user_manager::DemoAccountId()); |
| fake_user_manager->SwitchActiveUser(user_manager::DemoAccountId()); |
| arc_session_manager()->Shutdown(); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| |
| const AccountId public_account_id( |
| AccountId::FromUserEmail("public_user@gmail.com")); |
| fake_user_manager->AddPublicAccountUser(public_account_id); |
| fake_user_manager->SwitchActiveUser(public_account_id); |
| arc_session_manager()->Shutdown(); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| |
| const AccountId not_in_list_account_id( |
| AccountId::FromUserEmail("not_in_list_user@gmail.com")); |
| fake_user_manager->set_ephemeral_users_enabled(true); |
| fake_user_manager->AddUser(not_in_list_account_id); |
| fake_user_manager->SwitchActiveUser(not_in_list_account_id); |
| fake_user_manager->RemoveUserFromList(not_in_list_account_id); |
| arc_session_manager()->Shutdown(); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, BaseWorkflow) { |
| ASSERT_TRUE(arc_session_manager()->IsSessionStopped()); |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null()); |
| EXPECT_TRUE(arc_session_manager()->arc_start_time().is_null()); |
| |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| |
| // By default ARC is not enabled. |
| ASSERT_TRUE(WaitForDataRemoved(ArcSessionManager::State::STOPPED)); |
| |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| base::RunLoop().RunUntilIdle(); |
| |
| // Setting profile and pref initiates a code fetching process. |
| ASSERT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| |
| // TODO(hidehiko): Verify state transition from SHOWING_TERMS_OF_SERVICE -> |
| // CHECKING_ANDROID_MANAGEMENT, when we extract ArcSessionManager. |
| arc_session_manager()->StartArc(); |
| |
| EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null()); |
| EXPECT_FALSE(arc_session_manager()->arc_start_time().is_null()); |
| |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| ASSERT_TRUE(arc_session_manager()->IsSessionRunning()); |
| |
| arc_session_manager()->Shutdown(); |
| ASSERT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| ASSERT_TRUE(arc_session_manager()->IsSessionStopped()); |
| |
| // Send profile and don't provide a code. |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| |
| // Setting profile initiates a code fetching process. |
| ASSERT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| |
| content::BrowserThread::GetBlockingPool()->FlushForTesting(); |
| base::RunLoop().RunUntilIdle(); |
| |
| // UI is disabled in unit tests and this code is unchanged. |
| ASSERT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, CancelFetchingDisablesArc) { |
| PrefService* const pref = profile()->GetPrefs(); |
| |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| pref->SetBoolean(prefs::kArcEnabled, true); |
| base::RunLoop().RunUntilIdle(); |
| |
| ASSERT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| |
| arc_session_manager()->CancelAuthCode(); |
| |
| // Wait until data is removed. |
| ASSERT_TRUE(WaitForDataRemoved(ArcSessionManager::State::STOPPED)); |
| |
| ASSERT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, CloseUIKeepsArcEnabled) { |
| PrefService* const pref = profile()->GetPrefs(); |
| |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| pref->SetBoolean(prefs::kArcEnabled, true); |
| base::RunLoop().RunUntilIdle(); |
| |
| arc_session_manager()->StartArc(); |
| |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| arc_session_manager()->CancelAuthCode(); |
| ASSERT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| ASSERT_TRUE(pref->GetBoolean(prefs::kArcEnabled)); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, EnableDisablesArc) { |
| const PrefService* pref = profile()->GetPrefs(); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| |
| EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); |
| arc_session_manager()->EnableArc(); |
| EXPECT_TRUE(pref->GetBoolean(prefs::kArcEnabled)); |
| arc_session_manager()->DisableArc(); |
| EXPECT_FALSE(pref->GetBoolean(prefs::kArcEnabled)); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, SignInStatus) { |
| PrefService* const prefs = profile()->GetPrefs(); |
| |
| EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null()); |
| EXPECT_TRUE(arc_session_manager()->arc_start_time().is_null()); |
| |
| EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| prefs->SetBoolean(prefs::kArcEnabled, true); |
| |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| EXPECT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| |
| // Emulate to accept the terms of service. |
| prefs->SetBoolean(prefs::kArcTermsAccepted, true); |
| arc_session_manager()->StartArc(); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); |
| EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| EXPECT_FALSE(arc_session_manager()->arc_start_time().is_null()); |
| arc_session_manager()->OnProvisioningFinished(ProvisioningResult::SUCCESS); |
| EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); |
| EXPECT_TRUE(arc_session_manager()->sign_in_start_time().is_null()); |
| |
| // Second start, no fetching code is expected. |
| arc_session_manager()->Shutdown(); |
| EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->IsSessionStopped()); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); |
| |
| // Report failure. |
| arc_session_manager()->OnProvisioningFinished( |
| ProvisioningResult::GMS_NETWORK_ERROR); |
| // On error, UI to send feedback is showing. In that case, |
| // the ARC is still necessary to run on background for gathering the logs. |
| EXPECT_TRUE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->IsSessionRunning()); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, DisabledForDeviceLocalAccount) { |
| PrefService* const prefs = profile()->GetPrefs(); |
| EXPECT_FALSE(prefs->GetBoolean(prefs::kArcSignedIn)); |
| prefs->SetBoolean(prefs::kArcEnabled, true); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| arc_session_manager()->StartArc(); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| // Create device local account and set it as active. |
| const std::string email = "device-local-account@fake-email.com"; |
| TestingProfile::Builder profile_builder; |
| profile_builder.SetProfileName(email); |
| std::unique_ptr<TestingProfile> device_local_profile(profile_builder.Build()); |
| const AccountId account_id(AccountId::FromUserEmail(email)); |
| GetFakeUserManager()->AddPublicAccountUser(account_id); |
| |
| // Remove |profile_| to set the device local account be the primary account. |
| GetFakeUserManager()->RemoveUserFromList( |
| multi_user_util::GetAccountIdFromProfile(profile())); |
| GetFakeUserManager()->LoginUser(account_id); |
| |
| // Check that user without GAIA account can't use ARC. |
| device_local_profile->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| arc_session_manager()->OnPrimaryUserProfilePrepared( |
| device_local_profile.get()); |
| EXPECT_EQ(ArcSessionManager::State::NOT_INITIALIZED, |
| arc_session_manager()->state()); |
| |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, DisabledForNonPrimaryProfile) { |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| arc_session_manager()->StartArc(); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| // Create a second profile and set it as the active profile. |
| const std::string email = "test@example.com"; |
| TestingProfile::Builder profile_builder; |
| profile_builder.SetProfileName(email); |
| std::unique_ptr<TestingProfile> second_profile(profile_builder.Build()); |
| const AccountId account_id(AccountId::FromUserEmail(email)); |
| GetFakeUserManager()->AddUser(account_id); |
| GetFakeUserManager()->SwitchActiveUser(account_id); |
| second_profile->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| |
| // Check that non-primary user can't use Arc. |
| EXPECT_FALSE(chromeos::ProfileHelper::IsPrimaryProfile(second_profile.get())); |
| EXPECT_FALSE(ArcAppListPrefs::Get(second_profile.get())); |
| |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, RemoveDataFolder) { |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, false); |
| // Starting session manager with prefs::kArcEnabled off automatically removes |
| // Android's data folder. |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| EXPECT_TRUE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| EXPECT_EQ(ArcSessionManager::State::REMOVING_DATA_DIR, |
| arc_session_manager()->state()); |
| // Enable ARC. Data is removed asyncronously. At this moment session manager |
| // should be in REMOVING_DATA_DIR state. |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| EXPECT_TRUE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| EXPECT_EQ(ArcSessionManager::State::REMOVING_DATA_DIR, |
| arc_session_manager()->state()); |
| // Wait until data is removed. |
| base::RunLoop().RunUntilIdle(); |
| EXPECT_FALSE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| EXPECT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| arc_session_manager()->StartArc(); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| // Now request to remove data and stop session manager. |
| arc_session_manager()->RemoveArcData(); |
| ASSERT_TRUE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| arc_session_manager()->Shutdown(); |
| base::RunLoop().RunUntilIdle(); |
| // Request should persist. |
| ASSERT_TRUE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| |
| // Emulate next sign-in. Data should be removed first and ARC started after. |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| EXPECT_TRUE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| |
| ASSERT_TRUE( |
| WaitForDataRemoved(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE)); |
| |
| EXPECT_FALSE( |
| profile()->GetPrefs()->GetBoolean(prefs::kArcDataRemoveRequested)); |
| |
| arc_session_manager()->StartArc(); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| arc_session_manager()->Shutdown(); |
| } |
| |
| TEST_F(ArcSessionManagerTest, IgnoreSecondErrorReporting) { |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| arc_session_manager()->StartArc(); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| // Report some failure that does not stop the bridge. |
| arc_session_manager()->OnProvisioningFinished( |
| ProvisioningResult::GMS_SIGN_IN_FAILED); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| // Try to send another error that stops the bridge if sent first. It should |
| // be ignored. |
| arc_session_manager()->OnProvisioningFinished( |
| ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| arc_session_manager()->Shutdown(); |
| } |
| |
| class ArcSessionManagerKioskTest : public ArcSessionManagerTestBase { |
| public: |
| ArcSessionManagerKioskTest() = default; |
| |
| void SetUp() override { |
| ArcSessionManagerTestBase::SetUp(); |
| const AccountId account_id( |
| AccountId::FromUserEmail(profile()->GetProfileUserName())); |
| GetFakeUserManager()->AddArcKioskAppUser(account_id); |
| GetFakeUserManager()->LoginUser(account_id); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ArcSessionManagerKioskTest); |
| }; |
| |
| TEST_F(ArcSessionManagerKioskTest, AuthFailure) { |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| |
| // Replace chrome::AttemptUserExit() for testing. |
| // At the end of test, leave the dangling pointer |terminated|, |
| // assuming the callback is invoked exactly once in OnProvisioningFinished() |
| // and not invoked then, including TearDown(). |
| bool terminated = false; |
| arc_session_manager()->SetAttemptUserExitCallbackForTesting( |
| base::Bind([](bool* terminated) { *terminated = true; }, &terminated)); |
| |
| arc_session_manager()->OnProvisioningFinished( |
| ProvisioningResult::CHROME_SERVER_COMMUNICATION_ERROR); |
| EXPECT_TRUE(terminated); |
| } |
| |
| class ArcSessionOobeOptInTest : public ArcSessionManagerTest { |
| public: |
| ArcSessionOobeOptInTest() = default; |
| |
| protected: |
| void CreateLoginDisplayHost() { |
| fake_login_display_host_ = base::MakeUnique<FakeLoginDisplayHost>(); |
| } |
| |
| void CloseLoginDisplayHost() { fake_login_display_host_.reset(); } |
| |
| void AppendEnableArcOOBEOptInSwitch() { |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| chromeos::switches::kEnableArcOOBEOptIn); |
| } |
| |
| private: |
| std::unique_ptr<FakeLoginDisplayHost> fake_login_display_host_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcSessionOobeOptInTest); |
| }; |
| |
| TEST_F(ArcSessionOobeOptInTest, OobeOptInActive) { |
| // OOBE OptIn is active in case of OOBE is started for new user and ARC OOBE |
| // is enabled by switch. |
| EXPECT_FALSE(ArcSessionManager::IsOobeOptInActive()); |
| GetFakeUserManager()->set_current_user_new(true); |
| EXPECT_FALSE(ArcSessionManager::IsOobeOptInActive()); |
| CreateLoginDisplayHost(); |
| EXPECT_FALSE(ArcSessionManager::IsOobeOptInActive()); |
| |
| AppendEnableArcOOBEOptInSwitch(); |
| GetFakeUserManager()->set_current_user_new(false); |
| CloseLoginDisplayHost(); |
| EXPECT_FALSE(ArcSessionManager::IsOobeOptInActive()); |
| GetFakeUserManager()->set_current_user_new(true); |
| EXPECT_FALSE(ArcSessionManager::IsOobeOptInActive()); |
| CreateLoginDisplayHost(); |
| EXPECT_TRUE(ArcSessionManager::IsOobeOptInActive()); |
| } |
| |
| class ArcSessionOobeOptInNegotiatorTest |
| : public ArcSessionOobeOptInTest, |
| public chromeos::ArcTermsOfServiceScreenActor { |
| public: |
| ArcSessionOobeOptInNegotiatorTest() = default; |
| |
| void SetUp() override { |
| ArcSessionOobeOptInTest::SetUp(); |
| |
| AppendEnableArcOOBEOptInSwitch(); |
| |
| ArcTermsOfServiceOobeNegotiator::SetArcTermsOfServiceScreenActorForTesting( |
| this); |
| |
| GetFakeUserManager()->set_current_user_new(true); |
| |
| CreateLoginDisplayHost(); |
| |
| if (IsManagedUser()) { |
| policy::ProfilePolicyConnector* const connector = |
| policy::ProfilePolicyConnectorFactory::GetForBrowserContext( |
| profile()); |
| connector->OverrideIsManagedForTesting(true); |
| |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kArcEnabled, new base::FundamentalValue(true)); |
| } |
| |
| arc_session_manager()->OnPrimaryUserProfilePrepared(profile()); |
| } |
| |
| void TearDown() override { |
| // Correctly stop service. |
| arc_session_manager()->Shutdown(); |
| |
| ArcTermsOfServiceOobeNegotiator::SetArcTermsOfServiceScreenActorForTesting( |
| nullptr); |
| |
| ArcSessionOobeOptInTest::TearDown(); |
| } |
| |
| protected: |
| bool IsManagedUser() { return GetParam(); } |
| |
| void ReportResult(bool accepted) { |
| for (auto& observer : observer_list_) { |
| if (accepted) |
| observer.OnAccept(); |
| else |
| observer.OnSkip(); |
| } |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void ReportActorDestroyed() { |
| for (auto& observer : observer_list_) |
| observer.OnActorDestroyed(this); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void MaybeWaitForDataRemoved() { |
| // In case of managed user we no need to wait data removal because |
| // ArcSessionManager is initialized with arc.enabled = true already and |
| // request to remove ARC data is not issued. |
| if (IsManagedUser()) |
| return; |
| |
| DCHECK_EQ(ArcSessionManager::State::REMOVING_DATA_DIR, |
| ArcSessionManager::Get()->state()); |
| ArcDataRemovedWaiter().Wait(); |
| } |
| |
| chromeos::ArcTermsOfServiceScreenActor* actor() { return this; } |
| |
| private: |
| // ArcTermsOfServiceScreenActor: |
| void AddObserver( |
| chromeos::ArcTermsOfServiceScreenActorObserver* observer) override { |
| observer_list_.AddObserver(observer); |
| } |
| |
| void RemoveObserver( |
| chromeos::ArcTermsOfServiceScreenActorObserver* observer) override { |
| observer_list_.RemoveObserver(observer); |
| } |
| |
| void Show() override { |
| // To match ArcTermsOfServiceScreenHandler logic where prefs::kArcEnabled is |
| // set to true on showing UI. |
| profile()->GetPrefs()->SetBoolean(prefs::kArcEnabled, true); |
| } |
| |
| void Hide() override {} |
| |
| base::ObserverList<chromeos::ArcTermsOfServiceScreenActorObserver> |
| observer_list_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcSessionOobeOptInNegotiatorTest); |
| }; |
| |
| INSTANTIATE_TEST_CASE_P(ArcSessionOobeOptInNegotiatorTestImpl, |
| ArcSessionOobeOptInNegotiatorTest, |
| ::testing::Values(true, false)); |
| |
| TEST_P(ArcSessionOobeOptInNegotiatorTest, OobeTermsAccepted) { |
| actor()->Show(); |
| MaybeWaitForDataRemoved(); |
| EXPECT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| ReportResult(true); |
| EXPECT_EQ(ArcSessionManager::State::ACTIVE, arc_session_manager()->state()); |
| EXPECT_TRUE(arc_session_manager()->IsArcEnabled()); |
| } |
| |
| TEST_P(ArcSessionOobeOptInNegotiatorTest, OobeTermsRejected) { |
| actor()->Show(); |
| MaybeWaitForDataRemoved(); |
| EXPECT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| ReportResult(false); |
| EXPECT_EQ(ArcSessionManager::State::STOPPED, arc_session_manager()->state()); |
| EXPECT_FALSE(!IsManagedUser() && arc_session_manager()->IsArcEnabled()); |
| } |
| |
| TEST_P(ArcSessionOobeOptInNegotiatorTest, OobeTermsActorDestroyed) { |
| actor()->Show(); |
| MaybeWaitForDataRemoved(); |
| EXPECT_EQ(ArcSessionManager::State::SHOWING_TERMS_OF_SERVICE, |
| arc_session_manager()->state()); |
| CloseLoginDisplayHost(); |
| ReportActorDestroyed(); |
| EXPECT_EQ(ArcSessionManager::State::STOPPED, arc_session_manager()->state()); |
| EXPECT_FALSE(!IsManagedUser() && arc_session_manager()->IsArcEnabled()); |
| } |
| |
| } // namespace arc |