| // Copyright 2018 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 "chrome/browser/chromeos/login/demo_mode/demo_session.h" |
| |
| #include <list> |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/files/file_path.h" |
| #include "base/macros.h" |
| #include "base/optional.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/browser_process_platform_part.h" |
| #include "chrome/browser/chromeos/login/demo_mode/demo_resources.h" |
| #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" |
| #include "chrome/browser/chromeos/profiles/profile_helper.h" |
| #include "chrome/browser/component_updater/fake_cros_component_manager.h" |
| #include "chrome/browser/prefs/browser_prefs.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/browser_process_platform_part_test_api_chromeos.h" |
| #include "chrome/test/base/scoped_testing_local_state.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "chromeos/dbus/dbus_thread_manager.h" |
| #include "components/language/core/browser/pref_names.h" |
| #include "components/session_manager/core/session_manager.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "components/user_manager/scoped_user_manager.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using component_updater::FakeCrOSComponentManager; |
| |
| namespace chromeos { |
| |
| namespace { |
| |
| constexpr char kOfflineResourcesComponent[] = "demo-mode-resources"; |
| constexpr char kTestDemoModeResourcesMountPoint[] = |
| "/run/imageloader/demo_mode_resources"; |
| |
| void SetBoolean(bool* value) { |
| *value = true; |
| } |
| |
| } // namespace |
| |
| class DemoSessionTest : public testing::Test { |
| public: |
| DemoSessionTest() |
| : browser_process_platform_part_test_api_( |
| g_browser_process->platform_part()) {} |
| ~DemoSessionTest() override = default; |
| |
| void SetUp() override { |
| chromeos::DBusThreadManager::Initialize(); |
| DemoSession::SetDemoConfigForTesting(DemoSession::DemoModeConfig::kOnline); |
| InitializeCrosComponentManager(); |
| session_manager_ = std::make_unique<session_manager::SessionManager>(); |
| } |
| |
| void TearDown() override { |
| DemoSession::ShutDownIfInitialized(); |
| DemoSession::ResetDemoConfigForTesting(); |
| |
| chromeos::DBusThreadManager::Shutdown(); |
| |
| cros_component_manager_ = nullptr; |
| browser_process_platform_part_test_api_.ShutdownCrosComponentManager(); |
| } |
| |
| protected: |
| bool FinishResourcesComponentLoad(const base::FilePath& mount_path) { |
| EXPECT_TRUE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| EXPECT_FALSE( |
| cros_component_manager_->UpdateRequested(kOfflineResourcesComponent)); |
| |
| return cros_component_manager_->FinishLoadRequest( |
| kOfflineResourcesComponent, |
| FakeCrOSComponentManager::ComponentInfo( |
| component_updater::CrOSComponentManager::Error::NONE, |
| base::FilePath("/dev/null"), mount_path)); |
| } |
| |
| void InitializeCrosComponentManager() { |
| auto fake_cros_component_manager = |
| std::make_unique<FakeCrOSComponentManager>(); |
| fake_cros_component_manager->set_queue_load_requests(true); |
| fake_cros_component_manager->set_supported_components( |
| {kOfflineResourcesComponent}); |
| cros_component_manager_ = fake_cros_component_manager.get(); |
| |
| browser_process_platform_part_test_api_.InitializeCrosComponentManager( |
| std::move(fake_cros_component_manager)); |
| } |
| |
| FakeCrOSComponentManager* cros_component_manager_ = nullptr; |
| content::TestBrowserThreadBundle thread_bundle_; |
| std::unique_ptr<session_manager::SessionManager> session_manager_; |
| |
| private: |
| BrowserProcessPlatformPartTestApi browser_process_platform_part_test_api_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DemoSessionTest); |
| }; |
| |
| TEST_F(DemoSessionTest, StartForDeviceInDemoMode) { |
| EXPECT_FALSE(DemoSession::Get()); |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| EXPECT_TRUE(demo_session->started()); |
| EXPECT_FALSE(demo_session->offline_enrolled()); |
| EXPECT_EQ(demo_session, DemoSession::Get()); |
| } |
| |
| TEST_F(DemoSessionTest, StartInitiatesOfflineResourcesLoad) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| } |
| |
| TEST_F(DemoSessionTest, StartForDemoDeviceNotInDemoMode) { |
| DemoSession::SetDemoConfigForTesting(DemoSession::DemoModeConfig::kNone); |
| EXPECT_FALSE(DemoSession::Get()); |
| EXPECT_FALSE(DemoSession::StartIfInDemoMode()); |
| EXPECT_FALSE(DemoSession::Get()); |
| |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| } |
| |
| TEST_F(DemoSessionTest, StartIfInOfflineEnrolledDemoMode) { |
| DemoSession::SetDemoConfigForTesting(DemoSession::DemoModeConfig::kOffline); |
| |
| EXPECT_FALSE(DemoSession::Get()); |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| EXPECT_TRUE(demo_session->started()); |
| EXPECT_TRUE(demo_session->offline_enrolled()); |
| EXPECT_EQ(demo_session, DemoSession::Get()); |
| |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| } |
| |
| TEST_F(DemoSessionTest, PreloadOfflineResourcesIfInDemoMode) { |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| |
| DemoSession* demo_session = DemoSession::Get(); |
| ASSERT_TRUE(demo_session); |
| EXPECT_FALSE(demo_session->started()); |
| EXPECT_FALSE(demo_session->offline_enrolled()); |
| |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| EXPECT_FALSE(demo_session->started()); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| } |
| |
| TEST_F(DemoSessionTest, PreloadOfflineResourcesIfNotInDemoMode) { |
| DemoSession::SetDemoConfigForTesting(DemoSession::DemoModeConfig::kNone); |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| EXPECT_FALSE(DemoSession::Get()); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| } |
| |
| TEST_F(DemoSessionTest, PreloadOfflineResourcesIfInOfflineDemoMode) { |
| DemoSession::SetDemoConfigForTesting(DemoSession::DemoModeConfig::kOffline); |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| |
| DemoSession* demo_session = DemoSession::Get(); |
| ASSERT_TRUE(demo_session); |
| EXPECT_FALSE(demo_session->started()); |
| EXPECT_TRUE(demo_session->offline_enrolled()); |
| |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| } |
| |
| TEST_F(DemoSessionTest, ShutdownResetsInstance) { |
| ASSERT_TRUE(DemoSession::StartIfInDemoMode()); |
| EXPECT_TRUE(DemoSession::Get()); |
| DemoSession::ShutDownIfInitialized(); |
| EXPECT_FALSE(DemoSession::Get()); |
| } |
| |
| TEST_F(DemoSessionTest, ShutdownAfterPreload) { |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| EXPECT_TRUE(DemoSession::Get()); |
| DemoSession::ShutDownIfInitialized(); |
| EXPECT_FALSE(DemoSession::Get()); |
| } |
| |
| TEST_F(DemoSessionTest, StartDemoSessionWhilePreloadingResources) { |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| |
| ASSERT_TRUE(demo_session); |
| EXPECT_TRUE(demo_session->started()); |
| |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| EXPECT_TRUE(demo_session->started()); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| } |
| |
| TEST_F(DemoSessionTest, StartDemoSessionAfterPreloadingResources) { |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| EXPECT_TRUE(demo_session->started()); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| } |
| |
| TEST_F(DemoSessionTest, EnsureOfflineResourcesLoadedAfterStart) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| bool callback_called = false; |
| demo_session->EnsureOfflineResourcesLoaded( |
| base::BindOnce(&SetBoolean, &callback_called)); |
| |
| EXPECT_FALSE(callback_called); |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| EXPECT_TRUE(callback_called); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| } |
| |
| TEST_F(DemoSessionTest, EnsureOfflineResourcesLoadedAfterOfflineResourceLoad) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| bool callback_called = false; |
| demo_session->EnsureOfflineResourcesLoaded( |
| base::BindOnce(&SetBoolean, &callback_called)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| EXPECT_TRUE(callback_called); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| } |
| |
| TEST_F(DemoSessionTest, EnsureOfflineResourcesLoadedAfterPreload) { |
| DemoSession::PreloadOfflineResourcesIfInDemoMode(); |
| |
| DemoSession* demo_session = DemoSession::Get(); |
| ASSERT_TRUE(demo_session); |
| |
| bool callback_called = false; |
| demo_session->EnsureOfflineResourcesLoaded( |
| base::BindOnce(&SetBoolean, &callback_called)); |
| |
| EXPECT_FALSE(callback_called); |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| EXPECT_TRUE(callback_called); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| } |
| |
| TEST_F(DemoSessionTest, MultipleEnsureOfflineResourcesLoaded) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| bool first_callback_called = false; |
| demo_session->EnsureOfflineResourcesLoaded( |
| base::BindOnce(&SetBoolean, &first_callback_called)); |
| |
| bool second_callback_called = false; |
| demo_session->EnsureOfflineResourcesLoaded( |
| base::BindOnce(&SetBoolean, &second_callback_called)); |
| |
| bool third_callback_called = false; |
| demo_session->EnsureOfflineResourcesLoaded( |
| base::BindOnce(&SetBoolean, &third_callback_called)); |
| |
| EXPECT_FALSE(first_callback_called); |
| EXPECT_FALSE(second_callback_called); |
| EXPECT_FALSE(third_callback_called); |
| EXPECT_FALSE(demo_session->resources()->loaded()); |
| |
| const base::FilePath component_mount_point = |
| base::FilePath(kTestDemoModeResourcesMountPoint); |
| ASSERT_TRUE(FinishResourcesComponentLoad(component_mount_point)); |
| EXPECT_FALSE( |
| cros_component_manager_->HasPendingInstall(kOfflineResourcesComponent)); |
| |
| EXPECT_TRUE(first_callback_called); |
| EXPECT_TRUE(second_callback_called); |
| EXPECT_TRUE(third_callback_called); |
| EXPECT_TRUE(demo_session->resources()->loaded()); |
| EXPECT_EQ( |
| component_mount_point.AppendASCII("foo.txt"), |
| demo_session->resources()->GetAbsolutePath(base::FilePath("foo.txt"))); |
| } |
| |
| class DemoSessionLocaleTest : public DemoSessionTest { |
| public: |
| DemoSessionLocaleTest() { |
| auto fake_user_manager = std::make_unique<FakeChromeUserManager>(); |
| user_manager_ = fake_user_manager.get(); |
| scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( |
| std::move(fake_user_manager)); |
| } |
| |
| ~DemoSessionLocaleTest() override = default; |
| |
| void SetUp() override { |
| profile_manager_ = std::make_unique<TestingProfileManager>( |
| TestingBrowserProcess::GetGlobal()); |
| ASSERT_TRUE(profile_manager_->SetUp()); |
| DemoSessionTest::SetUp(); |
| } |
| |
| void TearDown() override { |
| profile_manager_->DeleteAllTestingProfiles(); |
| DemoSessionTest::TearDown(); |
| } |
| |
| protected: |
| // Creates a dummy demo user with a testing profile and logs in. |
| TestingProfile* LoginDemoUser() { |
| const AccountId account_id( |
| AccountId::FromUserEmailGaiaId("demo@test.com", "demo_user")); |
| const user_manager::User* user = |
| user_manager_->AddPublicAccountUser(account_id); |
| |
| auto prefs = |
| std::make_unique<sync_preferences::TestingPrefServiceSyncable>(); |
| RegisterUserProfilePrefs(prefs->registry()); |
| TestingProfile* profile = profile_manager_->CreateTestingProfile( |
| "test-profile", std::move(prefs), base::ASCIIToUTF16("Test profile"), |
| 1 /* avatar_id */, std::string() /* supervised_user_id */, |
| TestingProfile::TestingFactories()); |
| chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting(user, |
| profile); |
| |
| user_manager_->LoginUser(account_id); |
| profile_manager_->SetLoggedIn(true); |
| return profile; |
| } |
| |
| private: |
| FakeChromeUserManager* user_manager_ = nullptr; |
| std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; |
| std::unique_ptr<TestingProfileManager> profile_manager_; |
| |
| DISALLOW_COPY_AND_ASSIGN(DemoSessionLocaleTest); |
| }; |
| |
| TEST_F(DemoSessionLocaleTest, InitializeDefaultLocale) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| TestingProfile* profile = LoginDemoUser(); |
| // When the default locale is empty, verify that it's initialized with the |
| // current locale. |
| constexpr char kCurrentLocale[] = "en-US"; |
| profile->GetPrefs()->SetString(language::prefs::kApplicationLocale, |
| kCurrentLocale); |
| EXPECT_EQ("", TestingBrowserProcess::GetGlobal()->local_state()->GetString( |
| prefs::kDemoModeDefaultLocale)); |
| session_manager_->SetSessionState(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(kCurrentLocale, |
| TestingBrowserProcess::GetGlobal()->local_state()->GetString( |
| prefs::kDemoModeDefaultLocale)); |
| EXPECT_FALSE(profile->requested_locale().has_value()); |
| } |
| |
| TEST_F(DemoSessionLocaleTest, DefaultAndCurrentLocaleDifferent) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| TestingProfile* profile = LoginDemoUser(); |
| // When the default locale is different from the current locale, verify that |
| // reverting to default locale is requested. |
| constexpr char kCurrentLocale[] = "zh-CN"; |
| constexpr char kDefaultLocale[] = "en-US"; |
| profile->GetPrefs()->SetString(language::prefs::kApplicationLocale, |
| kCurrentLocale); |
| TestingBrowserProcess::GetGlobal()->local_state()->SetString( |
| prefs::kDemoModeDefaultLocale, kDefaultLocale); |
| session_manager_->SetSessionState(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(kDefaultLocale, |
| TestingBrowserProcess::GetGlobal()->local_state()->GetString( |
| prefs::kDemoModeDefaultLocale)); |
| EXPECT_EQ(kDefaultLocale, profile->requested_locale().value()); |
| } |
| |
| TEST_F(DemoSessionLocaleTest, DefaultAndCurrentLocaleIdentical) { |
| DemoSession* demo_session = DemoSession::StartIfInDemoMode(); |
| ASSERT_TRUE(demo_session); |
| |
| TestingProfile* profile = LoginDemoUser(); |
| // When the default locale is the same with the current locale, verify that |
| // it's no-op. |
| constexpr char kDefaultLocale[] = "en-US"; |
| profile->GetPrefs()->SetString(language::prefs::kApplicationLocale, |
| kDefaultLocale); |
| TestingBrowserProcess::GetGlobal()->local_state()->SetString( |
| prefs::kDemoModeDefaultLocale, kDefaultLocale); |
| session_manager_->SetSessionState(session_manager::SessionState::ACTIVE); |
| EXPECT_EQ(kDefaultLocale, |
| TestingBrowserProcess::GetGlobal()->local_state()->GetString( |
| prefs::kDemoModeDefaultLocale)); |
| EXPECT_FALSE(profile->requested_locale().has_value()); |
| } |
| |
| } // namespace chromeos |