| // 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/chrome_cleaner/components/system_report_component.h" |
| |
| #include <shlobj.h> |
| #include <string> |
| #include <vector> |
| |
| #include "base/files/file_path.h" |
| #include "base/files/file_util.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/lazy_instance.h" |
| #include "base/path_service.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/string_split.h" |
| #include "base/strings/string_util.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_command_line.h" |
| #include "base/test/scoped_path_override.h" |
| #include "base/test/test_reg_util_win.h" |
| #include "base/test/test_timeouts.h" |
| #include "base/win/registry.h" |
| #include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" |
| #include "chrome/chrome_cleaner/constants/uws_id.h" |
| #include "chrome/chrome_cleaner/logging/cleaner_logging_service.h" |
| #include "chrome/chrome_cleaner/logging/logging_service_api.h" |
| #include "chrome/chrome_cleaner/logging/proto/chrome_cleaner_report.pb.h" |
| #include "chrome/chrome_cleaner/os/disk_util.h" |
| #include "chrome/chrome_cleaner/os/file_path_sanitization.h" |
| #include "chrome/chrome_cleaner/os/pre_fetched_paths.h" |
| #include "chrome/chrome_cleaner/os/registry_util.h" |
| #include "chrome/chrome_cleaner/parsers/json_parser/test_json_parser.h" |
| #include "chrome/chrome_cleaner/parsers/parser_utils/command_line_arguments_sanitizer.h" |
| #include "chrome/chrome_cleaner/parsers/shortcut_parser/broker/fake_shortcut_parser.h" |
| #include "chrome/chrome_cleaner/test/test_extensions.h" |
| #include "chrome/chrome_cleaner/test/test_file_util.h" |
| #include "chrome/chrome_cleaner/test/test_pup_data.h" |
| #include "chrome/chrome_cleaner/test/test_util.h" |
| #include "components/chrome_cleaner/public/constants/constants.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace chrome_cleaner { |
| namespace { |
| |
| using google::protobuf::RepeatedPtrField; |
| using InstalledExtension = |
| ChromeCleanerReport::SystemReport::InstalledExtension; |
| using base::WaitableEvent; |
| |
| const int kExtensionIdLength = 32; |
| |
| const wchar_t kRunKeyPath[] = |
| L"software\\microsoft\\windows\\currentversion\\run"; |
| const wchar_t kRunTestName[] = L"test_chrome_cleanup_tool"; |
| const wchar_t kRunTestValue[] = L"chrome_cleanup_tool.exe"; |
| |
| const wchar_t kNameServerKeyPath[] = |
| L"system\\currentcontrolset\\services\\tcpip\\parameters\\interfaces\\" |
| L"fishy"; |
| const wchar_t kNameServerName[] = L"nameserver"; |
| const wchar_t kNameServerValue[] = L"8.8.4.4"; |
| const wchar_t kFakeProgramFolder[] = L"FakeProgram"; |
| const char kFakeProgram[] = "FakeProgram"; |
| const wchar_t kFakeAppDataProgramFolder[] = L"FakeAppDataProgram"; |
| const char kFakeAppDataProgram[] = "FakeAppDataProgram"; |
| |
| const char kExtensionPoliciesNonExistent[] = |
| "software\\policies\\google\\chrome\\"; |
| |
| struct ReportTestData { |
| HKEY hkey; |
| const wchar_t* key_path; |
| const wchar_t* name; |
| const wchar_t* value; |
| }; |
| |
| const ReportTestData kExtensionPolicyEmpty{ |
| HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath, L"test1", L""}; |
| |
| constexpr base::char16 kTestingExtensionId1[] = |
| L"ababababcdcdcdcdefefefefghghghgh"; |
| constexpr base::char16 kTestingExtensionId1WithUpdateUrl[] = |
| L"ababababcdcdcdcdefefefefghghghgh;https://clients2.google.com/service/" |
| L"update2/crx"; |
| constexpr base::char16 kTestingExtensionId2[] = |
| L"aaaabbbbccccddddeeeeffffgggghhhh"; |
| constexpr base::char16 kTestingExtensionId2WithUpdateUrl[] = |
| L"aaaabbbbccccddddeeeeffffgggghhhh;https://clients2.google.com/service/" |
| L"update2/crx"; |
| |
| const ReportTestData extension_policies[] = { |
| {HKEY_LOCAL_MACHINE, kChromePoliciesWhitelistKeyPath, L"test1", |
| kTestingExtensionId1}, |
| {HKEY_CURRENT_USER, kChromePoliciesWhitelistKeyPath, L"test2", |
| kTestingExtensionId1}, |
| {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test3", |
| kTestingExtensionId2WithUpdateUrl}, |
| {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test4", |
| kTestingExtensionId2WithUpdateUrl}, |
| {HKEY_LOCAL_MACHINE, kChromiumPoliciesWhitelistKeyPath, L"test5", |
| kTestingExtensionId1}, |
| {HKEY_CURRENT_USER, kChromiumPoliciesWhitelistKeyPath, L"test6", |
| kTestingExtensionId1}, |
| {HKEY_LOCAL_MACHINE, kChromiumPoliciesForcelistKeyPath, L"test7", |
| kTestingExtensionId2WithUpdateUrl}, |
| {HKEY_CURRENT_USER, kChromiumPoliciesForcelistKeyPath, L"test8", |
| kTestingExtensionId2WithUpdateUrl}, |
| }; |
| |
| const ReportTestData extension_forcelist_policies[] = { |
| {HKEY_LOCAL_MACHINE, kChromePoliciesForcelistKeyPath, L"test1", |
| kTestingExtensionId1WithUpdateUrl}, |
| {HKEY_CURRENT_USER, kChromePoliciesForcelistKeyPath, L"test2", |
| kTestingExtensionId2WithUpdateUrl}, |
| }; |
| |
| const UwSId kFakePupId = 42; |
| |
| const wchar_t kFakeChromeFolderForTests[] = |
| L"google\\chrome\\application\\42.12.34.56"; |
| |
| const char kDefaultExtensionsJsonForTests[] = R"( |
| { |
| "ababababcdcdcdcdefefefefghghghgh" : { |
| "external_update_url": "https://clients2.google.com/service/update2/crx" |
| }, |
| "aaaabbbbccccddddeeeeffffgggghhhh" : { |
| "external_update_url": "https://clients2.google.com/service/update2/crx" |
| } |
| })"; |
| // Don't include the null-terminator in the length. |
| const int kDefaultExtensionsJsonForTestsSize = |
| sizeof(kDefaultExtensionsJsonForTests) - 1; |
| |
| // ExtensionSettings that has two force_installed extensions and two not. |
| const wchar_t kExtensionSettingsJson[] = |
| LR"( |
| { |
| "ababababcdcdcdcdefefefefghghghgh": { |
| "installation_mode": "force_installed", |
| "update_url":"https://clients2.google.com/service/update2/crx" |
| }, |
| "aaaabbbbccccddddeeeeffffgggghhhh": { |
| "installation_mode": "force_installed", |
| "update_url":"https://clients2.google.com/service/update2/crx" |
| }, |
| "extensionwithinstallmodeblockeda": { |
| "installation_mode": "blocked", |
| "update_url":"https://clients2.google.com/service/update2/crx" |
| }, |
| "extensionwithnosettingsabcdefghi": {} |
| })"; |
| |
| const ReportTestData extension_settings_entry = { |
| HKEY_LOCAL_MACHINE, kChromePoliciesKeyPath, L"ExtensionSettings", |
| kExtensionSettingsJson}; |
| |
| const wchar_t kChromeExePathForTests[] = L"google\\chrome\\application"; |
| const wchar_t kMasterPreferencesFileNameForTests[] = L"master_preferences"; |
| const char kMasterPreferencesJsonForTests[] = R"( |
| { |
| "homepage": "http://dev.chromium.org/", |
| "extensions": { |
| "settings": { |
| "ababababcdcdcdcdefefefefghghghgh": { |
| "location": 1, |
| "manifest": { |
| "name": "Test extension" |
| } |
| }, |
| "aaaabbbbccccddddeeeeffffgggghhhh": { |
| "location": 1, |
| "manifest": { |
| "name": "Another one" |
| } |
| } |
| } |
| } |
| })"; |
| |
| const char kSanitizedLnkPath[] = "CSIDL_PROFILE\\appdata\\roaming"; |
| typedef std::map<base::string16, std::vector<base::string16>> |
| ExtensionIdToFileNamesMap; |
| |
| class SystemReportComponentTest : public testing::Test { |
| public: |
| SystemReportComponentTest() : component_(&json_parser_, &shortcut_parser_) {} |
| |
| void SetUp() override { |
| cleaner_logging_service_ = CleanerLoggingService::GetInstance(); |
| cleaner_logging_service_->Initialize(nullptr); |
| cleaner_logging_service_->EnableUploads(true, /*registry_logger=*/nullptr); |
| LoggingServiceAPI::SetInstanceForTesting(cleaner_logging_service_); |
| registry_override_.OverrideRegistry(HKEY_CURRENT_USER); |
| registry_override_.OverrideRegistry(HKEY_LOCAL_MACHINE); |
| |
| base::PathService::Get(CsidlToPathServiceKey(CSIDL_APPDATA), |
| &appdata_file_path_); |
| |
| ASSERT_TRUE(fake_user_data_.CreateUniqueTempDir()); |
| |
| extension_id_to_filenames_map_[kTestingExtensionId1] = {L"file1.test", |
| L"file2.test"}; |
| ASSERT_TRUE(CreateProfileWithExtensionAndFiles( |
| fake_user_data_.GetPath().Append(L"Profile 1"), kTestingExtensionId1, |
| extension_id_to_filenames_map_[kTestingExtensionId1])); |
| |
| extension_id_to_filenames_map_[kTestingExtensionId2] = {L"file1.test"}; |
| ASSERT_TRUE(CreateProfileWithExtensionAndFiles( |
| fake_user_data_.GetPath().Append(L"Profile 2"), kTestingExtensionId2, |
| extension_id_to_filenames_map_[kTestingExtensionId2])); |
| |
| component_.SetUserDataPathForTesting(fake_user_data_.GetPath()); |
| } |
| |
| void TearDown() override { |
| LoggingServiceAPI::SetInstanceForTesting(nullptr); |
| cleaner_logging_service_->Terminate(); |
| } |
| |
| ChromeCleanerReport GetChromeCleanerReport() { |
| ChromeCleanerReport report; |
| CHECK(report.ParseFromString(cleaner_logging_service_->RawReportContent())); |
| return report; |
| } |
| |
| TestJsonParser json_parser_; |
| FakeShortcutParser shortcut_parser_; |
| SystemReportComponent component_; |
| CleanerLoggingService* cleaner_logging_service_ = nullptr; |
| registry_util::RegistryOverrideManager registry_override_; |
| base::FilePath appdata_file_path_; |
| base::ScopedTempDir fake_user_data_; |
| ExtensionIdToFileNamesMap extension_id_to_filenames_map_; |
| }; |
| |
| template <typename Component> |
| bool SomeComponentContainsPath(const RepeatedPtrField<Component>& components, |
| const base::FilePath& path) { |
| const std::string name = path.BaseName().MaybeAsASCII(); |
| const std::string sanitized_path = base::UTF16ToUTF8(SanitizePath(path)); |
| for (const auto component : components) { |
| if (component.name() == name && |
| component.file_information().path() == sanitized_path) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool InstalledProgramCollected( |
| const RepeatedPtrField<ChromeCleanerReport::SystemReport::InstalledProgram>& |
| programs, |
| const std::string& folder_name) { |
| const std::string lower_case_folder_name = base::ToLowerASCII(folder_name); |
| for (const auto& program : programs) { |
| if (program.folder_information().path().find(lower_case_folder_name) != |
| std::string::npos) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool RegistryEntryCollected( |
| const RepeatedPtrField<RegistryValue>& registry_values, |
| const std::string& key_path, |
| const std::string& value_name, |
| const std::string& data) { |
| for (const auto& registry_value : registry_values) { |
| if (StringContainsCaseInsensitive(registry_value.key_path(), key_path) && |
| registry_value.value_name() == value_name && |
| registry_value.data() == data) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool RegistryKeyCollected( |
| const RepeatedPtrField<RegistryValue>& registry_values, |
| const std::string& key_path) { |
| for (const auto& registry_value : registry_values) { |
| if (StringContainsCaseInsensitive(registry_value.key_path(), key_path)) |
| return true; |
| } |
| return false; |
| } |
| |
| // Returns whether |extension_files| contains the expected file information |
| // of |extension_id|. |
| ::testing::AssertionResult ExtensionsReportedWithExpectedFiles( |
| const RepeatedPtrField<InstalledExtension>& reported_extensions, |
| const ExtensionIdToFileNamesMap& extension_id_to_filenames_map) { |
| for (const auto& installed_extension : reported_extensions) { |
| const RepeatedPtrField<FileInformation> extension_files = |
| installed_extension.extension_files(); |
| |
| std::unordered_set<base::string16> expected_files( |
| extension_id_to_filenames_map |
| .at(base::UTF8ToUTF16(installed_extension.extension_id())) |
| .begin(), |
| extension_id_to_filenames_map |
| .at(base::UTF8ToUTF16(installed_extension.extension_id())) |
| .end()); |
| |
| if (static_cast<size_t>(extension_files.size()) != expected_files.size()) |
| return ::testing::AssertionFailure() |
| << "Different number of files than expected for extension " |
| << installed_extension.extension_id(); |
| |
| for (const auto& file : extension_files) { |
| base::string16 file_name = |
| base::FilePath(base::UTF8ToUTF16(file.path())).BaseName().value(); |
| |
| if (expected_files.find(file_name) == expected_files.end()) |
| return ::testing::AssertionFailure() |
| << "file : " << file_name << " not reported for extension " |
| << installed_extension.extension_id(); |
| } |
| } |
| return ::testing::AssertionSuccess(); |
| } |
| |
| // Returns whether |reported_extensions| contains an entry for an extension with |
| // |extension_id| and |install_method|. |
| bool InstalledExtensionReported( |
| const RepeatedPtrField<InstalledExtension>& reported_extensions, |
| const std::wstring& extension_id, |
| ExtensionInstallMethod install_method) { |
| for (const auto& installed_extension : reported_extensions) { |
| if (installed_extension.extension_id() == base::WideToUTF8(extension_id) && |
| installed_extension.install_method() == install_method) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| } // namespace |
| |
| TEST_F(SystemReportComponentTest, PreScan_NoDetailedReport) { |
| component_.PreScan(); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PostScanNoUwS_DetailedReport) { |
| std::vector<UwSId> found_pups; |
| component_.PostScan(found_pups); |
| EXPECT_TRUE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PostScanNonRemovalableUwS_DetailedReport) { |
| TestPUPData test_pup_data; |
| test_pup_data.AddPUP(kFakePupId, PUPData::FLAGS_NONE, nullptr, |
| PUPData::kMaxFilesToRemoveSmallUwS); |
| std::vector<UwSId> found_pups; |
| found_pups.push_back(kFakePupId); |
| component_.PostScan(found_pups); |
| EXPECT_TRUE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PostScanRemovalableUwS_NoDetailedReport) { |
| TestPUPData test_pup_data; |
| test_pup_data.AddPUP(kFakePupId, PUPData::FLAGS_ACTION_REMOVE, nullptr, |
| PUPData::kMaxFilesToRemoveSmallUwS); |
| std::vector<UwSId> found_pups; |
| found_pups.push_back(kFakePupId); |
| component_.PostScan(found_pups); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PreCleanup_NoDetailedReport) { |
| component_.PreCleanup(); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PostCleanup_DetailedReport) { |
| component_.PostCleanup(RESULT_CODE_SUCCESS, nullptr); |
| EXPECT_TRUE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PostCleanup_canceled_NoDetailedReport) { |
| component_.PostCleanup(RESULT_CODE_CANCELED, nullptr); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, PostValidation_NoDetailedReport) { |
| component_.PostValidation(RESULT_CODE_SUCCESS); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, OnClose_NoDetailedReport) { |
| component_.OnClose(RESULT_CODE_SUCCESS); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, DisableUploads) { |
| cleaner_logging_service_->EnableUploads(false, nullptr); |
| |
| component_.CreateFullSystemReport(); |
| EXPECT_FALSE(component_.created_report()); |
| } |
| |
| TEST_F(SystemReportComponentTest, NoRepeatedCollections) { |
| component_.CreateFullSystemReport(); |
| EXPECT_TRUE(component_.created_report()); |
| |
| // Clear the report and ensure it isn't populated again, since |
| // |created_report| is still true. |
| EXPECT_LT(0, GetChromeCleanerReport().system_report().processes_size()); |
| cleaner_logging_service_->Terminate(); |
| cleaner_logging_service_->Initialize(/*registry_logger=*/nullptr); |
| EXPECT_EQ(0, GetChromeCleanerReport().system_report().processes_size()); |
| component_.CreateFullSystemReport(); |
| EXPECT_EQ(0, GetChromeCleanerReport().system_report().processes_size()); |
| } |
| |
| TEST_F(SystemReportComponentTest, DetectFakePrograms) { |
| base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); |
| base::FilePath program_files_dir; |
| ASSERT_TRUE( |
| base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); |
| |
| base::ScopedPathOverride appdata_override(base::DIR_LOCAL_APP_DATA); |
| base::FilePath appdata_dir; |
| ASSERT_TRUE(base::PathService::Get(base::DIR_LOCAL_APP_DATA, &appdata_dir)); |
| |
| // Setup a fake program installation folder. |
| base::FilePath fake_program_dir(program_files_dir.Append(kFakeProgramFolder)); |
| ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_program_dir, nullptr)); |
| ASSERT_TRUE(CreateFileInFolder(fake_program_dir, L"fake.exe")); |
| |
| base::FilePath fake_appdata_dir( |
| appdata_dir.Append(kFakeAppDataProgramFolder)); |
| ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_appdata_dir, nullptr)); |
| ASSERT_TRUE(CreateFileInFolder(fake_appdata_dir, L"fake.exe")); |
| |
| // Setup a fake runonce keys. |
| base::win::RegKey run_once(HKEY_CURRENT_USER, kRunKeyPath, KEY_WRITE); |
| ASSERT_TRUE(run_once.Valid()); |
| ASSERT_EQ(run_once.WriteValue(kRunTestName, kRunTestValue), ERROR_SUCCESS); |
| |
| component_.CreateFullSystemReport(); |
| |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| const auto& system_report = report.system_report(); |
| |
| const base::FilePath module_path = |
| PreFetchedPaths::GetInstance()->GetExecutablePath(); |
| EXPECT_TRUE( |
| SomeComponentContainsPath(system_report.loaded_modules(), module_path)); |
| |
| EXPECT_TRUE( |
| SomeComponentContainsPath(system_report.processes(), module_path)); |
| |
| EXPECT_TRUE(RegistryEntryCollected( |
| system_report.registry_values(), base::UTF16ToASCII(kRunKeyPath), |
| base::UTF16ToASCII(kRunTestName), base::UTF16ToASCII(kRunTestValue))); |
| |
| EXPECT_TRUE(InstalledProgramCollected(system_report.installed_programs(), |
| kFakeProgram)); |
| EXPECT_TRUE(InstalledProgramCollected(system_report.installed_programs(), |
| kFakeAppDataProgram)); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportNameServer) { |
| // Setup a fake key that triggers nameserver check. |
| base::win::RegKey nameserver_key; |
| ASSERT_EQ(ERROR_SUCCESS, |
| nameserver_key.Create(HKEY_LOCAL_MACHINE, kNameServerKeyPath, |
| KEY_ALL_ACCESS)); |
| ASSERT_TRUE(nameserver_key.Valid()); |
| ASSERT_EQ(nameserver_key.WriteValue(kNameServerName, kNameServerValue), |
| ERROR_SUCCESS); |
| |
| component_.CreateFullSystemReport(); |
| |
| EXPECT_TRUE(RegistryEntryCollected( |
| GetChromeCleanerReport().system_report().registry_values(), |
| base::UTF16ToASCII(kNameServerKeyPath), |
| base::UTF16ToASCII(kNameServerName), |
| base::UTF16ToASCII(kNameServerValue))); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportNameServerBadValue) { |
| // Setup a fake key that triggers nameserver check. |
| base::win::RegKey nameserver_key; |
| ASSERT_EQ(ERROR_SUCCESS, |
| nameserver_key.Create(HKEY_LOCAL_MACHINE, kNameServerKeyPath, |
| KEY_ALL_ACCESS)); |
| ASSERT_TRUE(nameserver_key.Valid()); |
| ASSERT_EQ(nameserver_key.WriteValue(kNameServerName, L""), ERROR_SUCCESS); |
| |
| component_.CreateFullSystemReport(); |
| |
| EXPECT_FALSE(RegistryKeyCollected( |
| GetChromeCleanerReport().system_report().registry_values(), |
| base::UTF16ToASCII(kNameServerKeyPath))); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportNameServerNonExistent) { |
| component_.CreateFullSystemReport(); |
| |
| EXPECT_FALSE(RegistryKeyCollected( |
| GetChromeCleanerReport().system_report().registry_values(), |
| base::UTF16ToASCII(kNameServerKeyPath))); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportExtensionPolicies) { |
| for (const auto& extension_policy : extension_policies) { |
| base::win::RegKey policy_key; |
| ASSERT_EQ(ERROR_SUCCESS, |
| policy_key.Create(extension_policy.hkey, |
| extension_policy.key_path, KEY_ALL_ACCESS)); |
| ASSERT_TRUE(policy_key.Valid()); |
| ASSERT_EQ( |
| policy_key.WriteValue(extension_policy.name, extension_policy.value), |
| ERROR_SUCCESS); |
| } |
| |
| component_.CreateFullSystemReport(); |
| |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| const auto& system_report = report.system_report(); |
| for (const auto& extension_policy : extension_policies) { |
| EXPECT_TRUE( |
| RegistryEntryCollected(system_report.registry_values(), |
| base::UTF16ToASCII(extension_policy.key_path), |
| base::UTF16ToASCII(extension_policy.name), |
| base::UTF16ToASCII(extension_policy.value))); |
| } |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportExtensionPoliciesBadValue) { |
| base::win::RegKey policy_key; |
| ASSERT_EQ(ERROR_SUCCESS, |
| policy_key.Create(kExtensionPolicyEmpty.hkey, |
| kExtensionPolicyEmpty.key_path, KEY_ALL_ACCESS)); |
| ASSERT_TRUE(policy_key.Valid()); |
| ASSERT_EQ(policy_key.WriteValue(kExtensionPolicyEmpty.name, |
| kExtensionPolicyEmpty.value), |
| ERROR_SUCCESS); |
| component_.CreateFullSystemReport(); |
| EXPECT_FALSE(RegistryKeyCollected( |
| GetChromeCleanerReport().system_report().registry_values(), |
| base::UTF16ToASCII(kExtensionPolicyEmpty.key_path))); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportExtensionPoliciesNonExistent) { |
| component_.CreateFullSystemReport(); |
| |
| EXPECT_FALSE(RegistryKeyCollected( |
| GetChromeCleanerReport().system_report().registry_values(), |
| kExtensionPoliciesNonExistent)); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportForcelistExtensions) { |
| for (const ReportTestData& policy : extension_forcelist_policies) { |
| base::win::RegKey policy_key; |
| ASSERT_EQ(ERROR_SUCCESS, |
| policy_key.Create(policy.hkey, policy.key_path, KEY_ALL_ACCESS)); |
| ASSERT_TRUE(policy_key.Valid()); |
| ASSERT_EQ(ERROR_SUCCESS, policy_key.WriteValue(policy.name, policy.value)); |
| } |
| |
| base::test::ScopedCommandLine scoped_command_line; |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| |
| for (const ReportTestData& expected : extension_forcelist_policies) { |
| std::wstring policy_value(expected.value); |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), |
| policy_value.substr(0, kExtensionIdLength), |
| ExtensionInstallMethod::POLICY_EXTENSION_FORCELIST)); |
| } |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportDefaultExtensions) { |
| // Set up a fake default extensions JSON file. |
| base::ScopedPathOverride program_files_x86_override( |
| base::DIR_PROGRAM_FILESX86); |
| base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); |
| base::FilePath program_files_dir; |
| ASSERT_TRUE( |
| base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); |
| |
| base::FilePath fake_apps_dir( |
| program_files_dir.Append(kFakeChromeFolderForTests) |
| .Append(L"default_apps")); |
| ASSERT_TRUE(base::CreateDirectoryAndGetError(fake_apps_dir, nullptr)); |
| |
| base::FilePath default_extensions_file = |
| fake_apps_dir.Append(L"external_extensions.json"); |
| CreateFileWithContent(default_extensions_file, kDefaultExtensionsJsonForTests, |
| kDefaultExtensionsJsonForTestsSize); |
| ASSERT_TRUE(base::PathExists(default_extensions_file)); |
| |
| base::test::ScopedCommandLine scoped_command_line; |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| |
| EXPECT_EQ(2, report.system_report().installed_extensions().size()); |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), kTestingExtensionId1, |
| ExtensionInstallMethod::DEFAULT_APPS_EXTENSION)); |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), kTestingExtensionId2, |
| ExtensionInstallMethod::DEFAULT_APPS_EXTENSION)); |
| |
| EXPECT_TRUE(ExtensionsReportedWithExpectedFiles( |
| report.system_report().installed_extensions(), |
| extension_id_to_filenames_map_)); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportExtensionSettings) { |
| // Set up a fake ExtensionSettings registry key. |
| base::win::RegKey settings_key; |
| ASSERT_EQ( |
| ERROR_SUCCESS, |
| settings_key.Create(extension_settings_entry.hkey, |
| extension_settings_entry.key_path, KEY_ALL_ACCESS)); |
| DCHECK(settings_key.Valid()); |
| ASSERT_EQ(ERROR_SUCCESS, |
| settings_key.WriteValue(extension_settings_entry.name, |
| extension_settings_entry.value)); |
| |
| base::test::ScopedCommandLine scoped_command_line; |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), kTestingExtensionId1, |
| ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS)); |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), kTestingExtensionId2, |
| ExtensionInstallMethod::POLICY_EXTENSION_SETTINGS)); |
| |
| EXPECT_TRUE(ExtensionsReportedWithExpectedFiles( |
| report.system_report().installed_extensions(), |
| extension_id_to_filenames_map_)); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportMasterPreferencesExtensions) { |
| // Set up a fake master preferences file |
| base::ScopedPathOverride program_files_x86_override( |
| base::DIR_PROGRAM_FILESX86); |
| base::ScopedPathOverride program_files_override(base::DIR_PROGRAM_FILES); |
| base::FilePath program_files_dir; |
| ASSERT_TRUE( |
| base::PathService::Get(base::DIR_PROGRAM_FILES, &program_files_dir)); |
| |
| base::FilePath chrome_dir(program_files_dir.Append(kChromeExePathForTests)); |
| ASSERT_TRUE(base::CreateDirectoryAndGetError(chrome_dir, nullptr)); |
| |
| base::FilePath master_preferences = |
| chrome_dir.Append(kMasterPreferencesFileNameForTests); |
| CreateFileWithContent(master_preferences, kMasterPreferencesJsonForTests, |
| sizeof(kMasterPreferencesJsonForTests) - 1); |
| ASSERT_TRUE(base::PathExists(master_preferences)); |
| |
| base::test::ScopedCommandLine scoped_command_line; |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| |
| EXPECT_EQ(2, report.system_report().installed_extensions().size()); |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), kTestingExtensionId1, |
| ExtensionInstallMethod::POLICY_MASTER_PREFERENCES)); |
| EXPECT_TRUE(InstalledExtensionReported( |
| report.system_report().installed_extensions(), kTestingExtensionId2, |
| ExtensionInstallMethod::POLICY_MASTER_PREFERENCES)); |
| |
| EXPECT_TRUE(ExtensionsReportedWithExpectedFiles( |
| report.system_report().installed_extensions(), |
| extension_id_to_filenames_map_)); |
| } |
| |
| TEST_F(SystemReportComponentTest, |
| ReportModifiedShortcutWithCommandLineArguments) { |
| const base::string16 kShortcutArguments = |
| L"--some-flag --some-other-scary-flag --flag-with-personal-data=" + |
| appdata_file_path_.value(); |
| const int kArgumentSize = 3; |
| ShortcutInformation shortcut_with_command_line_arguments; |
| shortcut_with_command_line_arguments.lnk_path = appdata_file_path_; |
| shortcut_with_command_line_arguments.target_path = |
| (appdata_file_path_.Append(L"chrome.exe")).value(); |
| shortcut_with_command_line_arguments.command_line_arguments = |
| kShortcutArguments; |
| |
| std::vector<ShortcutInformation> fake_parsed_shortcuts; |
| fake_parsed_shortcuts.push_back(shortcut_with_command_line_arguments); |
| |
| shortcut_parser_.SetShortcutsToReturn(fake_parsed_shortcuts); |
| |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| ASSERT_EQ(report.system_report().shortcut_data().size(), 1); |
| ChromeCleanerReport_SystemReport_ShortcutData shortcut_data = |
| report.system_report().shortcut_data(0); |
| |
| EXPECT_EQ(shortcut_data.lnk_path(), kSanitizedLnkPath); |
| |
| const std::string kSanitizedFakeChromePath = "CSIDL_APPDATA\\chrome.exe"; |
| EXPECT_EQ(shortcut_data.executable_path(), kSanitizedFakeChromePath); |
| |
| ASSERT_EQ(shortcut_data.command_line_arguments().size(), kArgumentSize); |
| EXPECT_EQ( |
| shortcut_data.command_line_arguments(0), |
| base::JoinString({"--flag-with-personal-data=", kSanitizedLnkPath}, "")); |
| EXPECT_EQ(shortcut_data.command_line_arguments(1), "--some-flag"); |
| EXPECT_EQ(shortcut_data.command_line_arguments(2), "--some-other-scary-flag"); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportShortcutWithPersonalSite) { |
| const base::string16 kPersonalSite = |
| L"http://www.somesite.com/user/happy_user"; |
| const std::string kSanitizedPersonalSite = "http://www.somesite.com"; |
| ShortcutInformation shortcut_with_personal_site; |
| shortcut_with_personal_site.lnk_path = appdata_file_path_; |
| shortcut_with_personal_site.target_path = |
| (appdata_file_path_.Append(L"chrome.exe")).value(); |
| shortcut_with_personal_site.command_line_arguments = kPersonalSite; |
| |
| std::vector<ShortcutInformation> fake_parsed_shortcuts; |
| fake_parsed_shortcuts.push_back(shortcut_with_personal_site); |
| shortcut_parser_.SetShortcutsToReturn(fake_parsed_shortcuts); |
| |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| ASSERT_EQ(report.system_report().shortcut_data().size(), 1); |
| ChromeCleanerReport_SystemReport_ShortcutData shortcut_data = |
| report.system_report().shortcut_data(0); |
| |
| ASSERT_EQ(shortcut_data.command_line_arguments().size(), 1); |
| EXPECT_EQ(shortcut_data.lnk_path(), kSanitizedLnkPath); |
| |
| const std::string kSanitizedFakeChromePath = "CSIDL_APPDATA\\chrome.exe"; |
| EXPECT_EQ(shortcut_data.executable_path(), kSanitizedFakeChromePath); |
| |
| ASSERT_EQ(shortcut_data.command_line_arguments().size(), 1); |
| EXPECT_EQ(shortcut_data.command_line_arguments(0), kSanitizedPersonalSite); |
| } |
| |
| TEST_F(SystemReportComponentTest, ReportShortcutWithDifferentTarget) { |
| ShortcutInformation shortcut_with_different_target; |
| shortcut_with_different_target.lnk_path = appdata_file_path_; |
| shortcut_with_different_target.target_path = |
| (appdata_file_path_.Append(L"totallynotuws.exe")).value(); |
| shortcut_with_different_target.command_line_arguments = L""; |
| |
| std::vector<ShortcutInformation> fake_parsed_shortcuts; |
| fake_parsed_shortcuts.push_back(shortcut_with_different_target); |
| shortcut_parser_.SetShortcutsToReturn(fake_parsed_shortcuts); |
| |
| component_.CreateFullSystemReport(); |
| |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| ASSERT_EQ(report.system_report().shortcut_data().size(), 1); |
| ChromeCleanerReport_SystemReport_ShortcutData shortcut_data = |
| report.system_report().shortcut_data(0); |
| |
| EXPECT_EQ(shortcut_data.lnk_path(), kSanitizedLnkPath); |
| |
| const std::string kSanitizedFakeUwSFile = "CSIDL_APPDATA\\totallynotuws.exe"; |
| EXPECT_EQ(shortcut_data.executable_path(), kSanitizedFakeUwSFile); |
| |
| EXPECT_EQ(shortcut_data.command_line_arguments().size(), 0); |
| } |
| |
| TEST_F(SystemReportComponentTest, DoNotReportShortcutWithoutModifications) { |
| ShortcutInformation not_modified_shortcut; |
| not_modified_shortcut.lnk_path = appdata_file_path_; |
| not_modified_shortcut.target_path = |
| (appdata_file_path_.Append(L"chrome.exe")).value(); |
| not_modified_shortcut.command_line_arguments = L""; |
| |
| std::vector<ShortcutInformation> fake_parsed_shortcuts; |
| fake_parsed_shortcuts.push_back(not_modified_shortcut); |
| shortcut_parser_.SetShortcutsToReturn(fake_parsed_shortcuts); |
| |
| component_.CreateFullSystemReport(); |
| ChromeCleanerReport report = GetChromeCleanerReport(); |
| EXPECT_EQ(report.system_report().shortcut_data().size(), 0); |
| } |
| } // namespace chrome_cleaner |