| // 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/conflicts/third_party_conflicts_manager_win.h" |
| |
| #include <utility> |
| |
| #include "base/base_paths.h" |
| #include "base/bind.h" |
| #include "base/bind_helpers.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/optional.h" |
| #include "base/path_service.h" |
| #include "base/run_loop.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/threading/sequenced_task_runner_handle.h" |
| #include "base/win/windows_version.h" |
| #include "chrome/browser/conflicts/module_info_win.h" |
| #include "chrome/browser/conflicts/proto/module_list.pb.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/test/base/scoped_testing_local_state.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| class ThirdPartyConflictsManagerTest : public testing::Test, |
| public ModuleDatabaseEventSource { |
| public: |
| ThirdPartyConflictsManagerTest() |
| : scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {} |
| |
| void SetUp() override { |
| ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); |
| |
| scoped_feature_list_.InitWithFeatures( |
| // Enabled features. |
| {features::kIncompatibleApplicationsWarning, |
| features::kThirdPartyModulesBlocking}, |
| // Disabled features. |
| {}); |
| } |
| |
| // Returns the path to the module list. |
| base::FilePath GetModuleListPath() const { |
| return scoped_temp_dir_.GetPath().Append(L"ModuleList.bin"); |
| } |
| |
| // Writes an empty serialized ModuleList proto to |GetModuleListPath()|. |
| void CreateModuleList() { |
| chrome::conflicts::ModuleList module_list; |
| // Include an empty blacklist and whitelist. |
| module_list.mutable_blacklist(); |
| module_list.mutable_whitelist(); |
| |
| std::string contents; |
| ASSERT_TRUE(module_list.SerializeToString(&contents)); |
| ASSERT_EQ(base::WriteFile(GetModuleListPath(), contents.data(), |
| static_cast<int>(contents.size())), |
| static_cast<int>(contents.size())); |
| } |
| |
| void OnManagerInitializationComplete( |
| base::Closure quit_closure, |
| ThirdPartyConflictsManager::State final_state) { |
| final_state_ = final_state; |
| std::move(quit_closure).Run(); |
| } |
| |
| const base::Optional<ThirdPartyConflictsManager::State>& final_state() { |
| return final_state_; |
| } |
| |
| // ModuleDatabaseEventSource: |
| void AddObserver(ModuleDatabaseObserver* observer) override {} |
| void RemoveObserver(ModuleDatabaseObserver* observer) override {} |
| |
| private: |
| content::TestBrowserThreadBundle test_browser_thread_bundle_; |
| ScopedTestingLocalState scoped_testing_local_state_; |
| |
| // Temp directory used to host module list. |
| base::ScopedTempDir scoped_temp_dir_; |
| |
| base::test::ScopedFeatureList scoped_feature_list_; |
| |
| base::Optional<ThirdPartyConflictsManager::State> final_state_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ThirdPartyConflictsManagerTest); |
| }; |
| |
| std::pair<ModuleInfoKey, ModuleInfoData> CreateExeModuleInfo() { |
| base::FilePath exe_path; |
| base::PathService::Get(base::FILE_EXE, &exe_path); |
| |
| std::pair<ModuleInfoKey, ModuleInfoData> module_info( |
| std::piecewise_construct, |
| std::forward_as_tuple(std::move(exe_path), 0, 0), |
| std::forward_as_tuple()); |
| |
| module_info.second.inspection_result = |
| base::make_optional<ModuleInspectionResult>(); |
| |
| return module_info; |
| } |
| |
| TEST_F(ThirdPartyConflictsManagerTest, InitializeUpdaters) { |
| ThirdPartyConflictsManager third_party_conflicts_manager(this); |
| |
| // The ThirdPartyConflictsManager class looks for the certificate info of the |
| // current exe via the ModuleDatabaseObserver interface. |
| auto exe_module_info = CreateExeModuleInfo(); |
| third_party_conflicts_manager.OnNewModuleFound(exe_module_info.first, |
| exe_module_info.second); |
| |
| third_party_conflicts_manager.OnModuleDatabaseIdle(); |
| ASSERT_NO_FATAL_FAILURE(CreateModuleList()); |
| third_party_conflicts_manager.LoadModuleList(GetModuleListPath()); |
| |
| base::RunLoop run_loop; |
| third_party_conflicts_manager.ForceInitialization(base::BindRepeating( |
| &ThirdPartyConflictsManagerTest::OnManagerInitializationComplete, |
| base::Unretained(this), run_loop.QuitClosure())); |
| |
| run_loop.Run(); |
| |
| ASSERT_TRUE(final_state().has_value()); |
| |
| const auto kExpectedFinalState = |
| base::win::GetVersion() >= base::win::VERSION_WIN10 |
| ? ThirdPartyConflictsManager::State::kWarningAndBlockingInitialized |
| : ThirdPartyConflictsManager::State::kBlockingInitialized; |
| EXPECT_EQ(final_state().value(), kExpectedFinalState); |
| } |
| |
| TEST_F(ThirdPartyConflictsManagerTest, InvalidModuleList) { |
| ThirdPartyConflictsManager third_party_conflicts_manager(this); |
| |
| third_party_conflicts_manager.OnModuleDatabaseIdle(); |
| |
| // Pass in an empty path which will ensure that the deserialization will fail. |
| third_party_conflicts_manager.LoadModuleList(GetModuleListPath()); |
| |
| base::RunLoop run_loop; |
| third_party_conflicts_manager.ForceInitialization(base::BindRepeating( |
| &ThirdPartyConflictsManagerTest::OnManagerInitializationComplete, |
| base::Unretained(this), run_loop.QuitClosure())); |
| |
| run_loop.Run(); |
| |
| ASSERT_TRUE(final_state().has_value()); |
| EXPECT_EQ(final_state().value(), |
| ThirdPartyConflictsManager::State::kModuleListInvalidFailure); |
| } |
| |
| TEST_F(ThirdPartyConflictsManagerTest, DestroyManager) { |
| auto third_party_conflicts_manager = |
| std::make_unique<ThirdPartyConflictsManager>(this); |
| |
| third_party_conflicts_manager->OnModuleDatabaseIdle(); |
| ASSERT_NO_FATAL_FAILURE(CreateModuleList()); |
| third_party_conflicts_manager->LoadModuleList(GetModuleListPath()); |
| |
| base::RunLoop run_loop; |
| third_party_conflicts_manager->ForceInitialization(base::BindRepeating( |
| &ThirdPartyConflictsManagerTest::OnManagerInitializationComplete, |
| base::Unretained(this), run_loop.QuitClosure())); |
| |
| // Delete the instance while it is initializing. |
| third_party_conflicts_manager = nullptr; |
| run_loop.Run(); |
| |
| ASSERT_TRUE(final_state().has_value()); |
| EXPECT_EQ(final_state().value(), |
| ThirdPartyConflictsManager::State::kDestroyed); |
| } |