| // Copyright 2021 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 <windows.h> |
| |
| #include <memory> |
| |
| #include "base/base_paths_win.h" |
| #include "base/files/scoped_temp_dir.h" |
| #include "base/json/json_reader.h" |
| #include "base/json/json_writer.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/scoped_path_override.h" |
| #include "chrome/credential_provider/extension/app_inventory_manager.h" |
| #include "chrome/credential_provider/extension/user_device_context.h" |
| #include "chrome/credential_provider/gaiacp/gcpw_strings.h" |
| #include "chrome/credential_provider/gaiacp/mdm_utils.h" |
| #include "chrome/credential_provider/gaiacp/reg_utils.h" |
| #include "chrome/credential_provider/test/gls_runner_test_base.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace credential_provider { |
| |
| namespace testing { |
| |
| class AppInventoryManagerBaseTest : public GlsRunnerTestBase { |
| protected: |
| void SetUp() override; |
| std::wstring CreateUser(); |
| }; |
| |
| void AppInventoryManagerBaseTest::SetUp() { |
| GlsRunnerTestBase::SetUp(); |
| |
| FakesForTesting fakes; |
| fakes.fake_win_http_url_fetcher_creator = |
| fake_http_url_fetcher_factory()->GetCreatorCallback(); |
| AppInventoryManager::Get()->SetFakesForTesting(&fakes); |
| } |
| |
| std::wstring AppInventoryManagerBaseTest::CreateUser() { |
| // Create a fake user associated to a gaia id. |
| CComBSTR sid_str; |
| EXPECT_EQ(S_OK, fake_os_user_manager()->CreateTestOSUser( |
| kDefaultUsername, L"password", L"Full Name", L"comment", |
| base::UTF8ToWide(kDefaultGaiaId), L"user@company.com", |
| &sid_str)); |
| return OLE2W(sid_str); |
| } |
| |
| // Tests user policy fetch by ESA service. |
| // Params: |
| // string : The specified device resource ID. |
| // bool : Whether a valid user sid is present. |
| // bool : Whether app data is present or not. |
| // string : The specified DM token. |
| class AppInventoryManagerTest |
| : public AppInventoryManagerBaseTest, |
| public ::testing::WithParamInterface< |
| std::tuple<const wchar_t*, bool, bool, const wchar_t*>> { |
| public: |
| AppInventoryManagerTest(); |
| |
| protected: |
| extension::TaskCreator app_inventory_task_creator_; |
| }; |
| |
| AppInventoryManagerTest::AppInventoryManagerTest() { |
| app_inventory_task_creator_ = |
| AppInventoryManager::UploadAppInventoryTaskCreator(); |
| } |
| |
| TEST_P(AppInventoryManagerTest, uploadAppInventory) { |
| const std::wstring device_resource_id(std::get<0>(GetParam())); |
| bool has_valid_sid = std::get<1>(GetParam()); |
| bool has_app_data = std::get<2>(GetParam()); |
| const std::wstring dm_token(std::get<3>(GetParam())); |
| |
| const char kAppDisplayName[] = "name"; |
| const char kAppDisplayVersion[] = "version"; |
| const char kAppPublisher[] = "publisher"; |
| const char kAppType[] = "app_type"; |
| |
| const wchar_t kApp1[] = L"app1"; |
| const wchar_t kAppDisplayName1[] = L"appName1"; |
| const wchar_t kAppDisplayVersion1[] = L"appVersion1"; |
| const wchar_t kAppPublisher1[] = L"appPublisher1"; |
| |
| const wchar_t kApp2[] = L"app2"; |
| const wchar_t kAppDisplayName2[] = L"appName2"; |
| const wchar_t kAppDisplayVersion2[] = L"appVersion2"; |
| |
| const wchar_t kApp3[] = L"app3"; |
| const wchar_t kAppDisplayVersion3[] = L"appVersion3"; |
| |
| const wchar_t kInstalledWin32AppsRegistryPath[] = |
| L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; |
| const wchar_t kInstalledWin32AppsRegistryPathWOW6432[] = |
| L"SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"; |
| const wchar_t kDelimiter[] = L"\\"; |
| const wchar_t kAppDisplayNameRegistryKey[] = L"DisplayName"; |
| const wchar_t kAppDisplayVersionRegistryKey[] = L"DisplayVersion"; |
| const wchar_t kAppPublisherRegistryKey[] = L"Publisher"; |
| |
| std::wstring user_sid = L"invalid-user-sid"; |
| if (has_valid_sid) { |
| // Create a fake user associated to a gaia id. |
| CComBSTR sid_str; |
| ASSERT_EQ(S_OK, fake_os_user_manager()->CreateTestOSUser( |
| kDefaultUsername, L"password", L"Full Name", L"comment", |
| base::UTF8ToWide(kDefaultGaiaId), L"user@company.com", |
| &sid_str)); |
| user_sid = OLE2W(sid_str); |
| } |
| |
| if (has_app_data) { |
| // Set valid app data at |
| // SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall. |
| std::wstring app_path_1 = std::wstring(kInstalledWin32AppsRegistryPath) |
| .append(std::wstring(kDelimiter)) |
| .append(kApp1); |
| SetMachineRegString(app_path_1, kAppDisplayNameRegistryKey, |
| kAppDisplayName1); |
| SetMachineRegString(app_path_1, kAppDisplayVersionRegistryKey, |
| kAppDisplayVersion1); |
| SetMachineRegString(app_path_1, kAppPublisherRegistryKey, kAppPublisher1); |
| |
| // Set valid app data at |
| // SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall. |
| std::wstring app_path_2 = |
| std::wstring(kInstalledWin32AppsRegistryPathWOW6432) |
| .append(std::wstring(kDelimiter)) |
| .append(kApp2); |
| SetMachineRegString(app_path_2, kAppDisplayNameRegistryKey, |
| kAppDisplayName2); |
| SetMachineRegString(app_path_2, kAppDisplayVersionRegistryKey, |
| kAppDisplayVersion2); |
| |
| // Set app data without display name. |
| std::wstring app_path_3 = std::wstring(kInstalledWin32AppsRegistryPath) |
| .append(std::wstring(kDelimiter)) |
| .append(kApp3); |
| SetMachineRegString(app_path_3, kAppDisplayVersionRegistryKey, |
| kAppDisplayVersion3); |
| } |
| |
| GURL app_inventory_url = |
| AppInventoryManager::Get()->GetGemServiceUploadAppInventoryUrl(); |
| ASSERT_TRUE(app_inventory_url.is_valid()); |
| |
| base::Value expected_response_value(base::Value::Type::DICTIONARY); |
| expected_response_value.SetStringKey("deviceResourceId", |
| base::WideToUTF8(device_resource_id)); |
| std::string expected_response; |
| base::JSONWriter::Write(expected_response_value, &expected_response); |
| |
| fake_http_url_fetcher_factory()->SetCollectRequestData(true); |
| // Set upload device details server response. |
| fake_http_url_fetcher_factory()->SetFakeResponse( |
| app_inventory_url, FakeWinHttpUrlFetcher::Headers(), expected_response); |
| |
| extension::UserDeviceContext context(device_resource_id, L"", L"", user_sid, |
| dm_token); |
| |
| auto task(app_inventory_task_creator_.Run()); |
| ASSERT_TRUE(task); |
| |
| ASSERT_TRUE(SUCCEEDED(task->SetContext({context}))); |
| HRESULT status = task->Execute(); |
| |
| if (!has_valid_sid || device_resource_id.empty() || dm_token.empty()) { |
| ASSERT_TRUE(FAILED(status)); |
| ASSERT_EQ(fake_http_url_fetcher_factory()->requests_created(), 0uLL); |
| } else { |
| ASSERT_TRUE(SUCCEEDED(status)); |
| ASSERT_EQ(fake_http_url_fetcher_factory()->requests_created(), 1uLL); |
| FakeWinHttpUrlFetcherFactory::RequestData request_data = |
| fake_http_url_fetcher_factory()->GetRequestData(0); |
| |
| absl::optional<base::Value> body_value = |
| base::JSONReader::Read(request_data.body); |
| |
| base::Value request(base::Value::Type::DICTIONARY); |
| |
| request.SetStringKey("device_resource_id", "valid-device-resource-id"); |
| request.SetStringKey("dm_token", "valid-dm-token"); |
| request.SetStringKey("obfuscated_gaia_id", "test-gaia-id"); |
| request.SetStringKey("user_sid", "S-1-4-2"); |
| base::Value app_info_value_list(base::Value::Type::LIST); |
| |
| if (has_app_data) { |
| std::unique_ptr<base::Value> request_dict_1; |
| request_dict_1 = |
| std::make_unique<base::Value>(base::Value::Type::DICTIONARY); |
| request_dict_1->SetStringKey(kAppDisplayName, |
| base::WideToUTF8(kAppDisplayName1)); |
| request_dict_1->SetStringKey(kAppDisplayVersion, |
| base::WideToUTF8(kAppDisplayVersion1)); |
| request_dict_1->SetStringKey(kAppPublisher, |
| base::WideToUTF8(kAppPublisher1)); |
| // WIN_32 |
| request_dict_1->SetIntKey(kAppType, 1); |
| app_info_value_list.Append( |
| base::Value::FromUniquePtrValue(std::move(request_dict_1))); |
| |
| std::unique_ptr<base::Value> request_dict_2; |
| request_dict_2 = |
| std::make_unique<base::Value>(base::Value::Type::DICTIONARY); |
| request_dict_2->SetStringKey(kAppDisplayName, |
| base::WideToUTF8(kAppDisplayName2)); |
| request_dict_2->SetStringKey(kAppDisplayVersion, |
| base::WideToUTF8(kAppDisplayVersion2)); |
| request_dict_2->SetIntKey(kAppType, 1); |
| app_info_value_list.Append( |
| base::Value::FromUniquePtrValue(std::move(request_dict_2))); |
| } |
| |
| request.SetKey("windows_gpcw_app_info", std::move(app_info_value_list)); |
| ASSERT_EQ(body_value.value(), request); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| AppInventoryManagerTest, |
| ::testing::Combine(::testing::Values(L"", L"valid-device-resource-id"), |
| ::testing::Bool(), |
| ::testing::Bool(), |
| ::testing::Values(L"", L"valid-dm-token"))); |
| |
| } // namespace testing |
| } // namespace credential_provider |