#include "chrome/updater/test/integration_tests_impl.h"
#include <cstdint>
#include <cstdlib>
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <string>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/notreached.h"
#include "base/numerics/checked_math.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/test/bind.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
#include "base/values.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/enterprise_companion/device_management_storage/dm_storage.h"
#include "chrome/updater/activity.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/device_management/dm_policy_builder_for_testing.h"
#include "chrome/updater/external_constants_builder.h"
#include "chrome/updater/external_constants_override.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/prefs.h"
#include "chrome/updater/protos/omaha_settings.pb.h"
#include "chrome/updater/registration_data.h"
#include "chrome/updater/service_proxy_factory.h"
#include "chrome/updater/test/request_matcher.h"
#include "chrome/updater/test/server.h"
#include "chrome/updater/test/test_scope.h"
#include "chrome/updater/test/unit_test_util.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/updater_branding.h"
#include "chrome/updater/updater_scope.h"
#include "chrome/updater/updater_version.h"
#include "chrome/updater/util/util.h"
#include "components/policy/proto/device_management_backend.pb.h"
#include "crypto/secure_hash.h"
#include "crypto/sha2.h"
#include "net/http/http_status_code.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/re2/src/re2/re2.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_WIN)
#include "base/file_version_info_win.h"
#include "base/win/registry.h"
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/test/test_executables.h"
#include "chrome/updater/win/win_constants.h"
#elif BUILDFLAG(IS_LINUX)
#include "chrome/updater/util/linux_util.h"
#include "chrome/updater/util/posix_util.h"
#endif
namespace updater::test {
namespace {
constexpr char kSelfUpdateCRXName[] = …;
#if BUILDFLAG(IS_MAC)
constexpr char kSelfUpdateCRXRun[] = PRODUCT_FULLNAME_STRING "_test.app";
constexpr char kDoNothingCRXName[] = "updater_qualification_app_dmg.crx";
constexpr char kDoNothingCRXRun[] = "updater_qualification_app_dmg.dmg";
#elif BUILDFLAG(IS_WIN)
constexpr char kSelfUpdateCRXRun[] = "UpdaterSetup_test.exe";
constexpr char kDoNothingCRXName[] = "updater_qualification_app_exe.crx";
constexpr char kDoNothingCRXRun[] = "qualification_app.exe";
#elif BUILDFLAG(IS_LINUX)
constexpr char kSelfUpdateCRXRun[] = …;
constexpr char kDoNothingCRXName[] = …;
constexpr char kDoNothingCRXRun[] = …;
#endif
std::string GetHashHex(const base::FilePath& file) { … }
std::string GetUpdateResponseForApp(
const std::string& app_id,
const std::string& install_data_index,
const std::string& codebase,
const base::Version& version,
const base::FilePath& update_file,
const std::string& run_action,
const std::string& arguments,
const std::optional<std::string>& file_hash = std::nullopt,
const std::optional<std::string>& status = std::nullopt) { … }
std::string GetUpdateResponse(const std::vector<std::string>& app_responses) { … }
std::string GetUpdateResponse(const std::string& app_id,
const std::string& install_data_index,
const std::string& codebase,
const base::Version& version,
const base::FilePath& update_file,
const std::string& run_action,
const std::string& arguments,
const std::string& file_hash) { … }
std::string GetUpdateResponse(const std::string& app_id,
const std::string& install_data_index,
const std::string& codebase,
const base::Version& version,
const base::FilePath& update_file,
const std::string& run_action,
const std::string& arguments) { … }
void RunUpdaterWithSwitches(const base::Version& version,
UpdaterScope scope,
const std::vector<std::string>& switches,
std::optional<int> expected_exit_code) { … }
void ExpectUpdateCheckSequence(UpdaterScope scope,
ScopedServer* test_server,
const std::string& app_id,
UpdateService::Priority priority,
int event_type,
const base::Version& from_version,
const base::Version& to_version) { … }
void ExpectUpdateSequence(UpdaterScope scope,
ScopedServer* test_server,
const std::string& app_id,
const std::string& install_data_index,
UpdateService::Priority priority,
int event_type,
const base::Version& from_version,
const base::Version& to_version,
bool do_fault_injection) { … }
void ExpectDeviceManagementRequest(ScopedServer* test_server,
const std::string& request_type,
const std::string& authorization_type,
const std::string& authorization_token,
net::HttpStatusCode response_status,
const std::string& response,
std::optional<GURL> target_url = { … }
}
AppUpdateExpectation::AppUpdateExpectation(
const std::string& args,
const std::string& app_id,
const base::Version& from_version,
const base::Version& to_version,
bool is_install,
bool should_update,
bool allow_rollback,
const std::string& target_version_prefix,
const std::string& target_channel,
const base::FilePath& crx_relative_path,
bool always_serve_crx,
const UpdateService::ErrorCategory error_category,
const int error_code,
const int event_type,
const std::string& custom_app_response,
const std::string& response_status)
: … { … }
AppUpdateExpectation::AppUpdateExpectation(const AppUpdateExpectation&) =
default;
AppUpdateExpectation::~AppUpdateExpectation() = default;
void ExitTestMode(UpdaterScope scope) { … }
int CountDirectoryFiles(const base::FilePath& dir) { … }
void RegisterApp(UpdaterScope scope, const RegistrationRequest& registration) { … }
void RegisterAppByValue(UpdaterScope scope, const base::Value::Dict& value) { … }
void SetGroupPolicies(const base::Value::Dict& values) { … }
void SetMachineManaged(bool is_managed_device) { … }
void ExpectVersionActive(UpdaterScope scope, const std::string& version) { … }
void ExpectVersionNotActive(UpdaterScope scope, const std::string& version) { … }
void Install(UpdaterScope scope, const base::Value::List& switches) { … }
void InstallUpdaterAndApp(UpdaterScope scope,
const std::string& app_id,
const bool is_silent_install,
const std::string& tag,
const std::string& child_window_text_to_find,
const bool always_launch_cmd,
const bool verify_app_logo_loaded,
const bool expect_success,
const bool wait_for_the_installer) { … }
void PrintFile(const base::FilePath& file) { … }
std::vector<base::FilePath> GetUpdaterLogFilesInTmp() { … }
void PrintLog(UpdaterScope scope) { … }
void CopyLog(const base::FilePath& src_dir, const std::string& infix) { … }
void ExpectNoCrashes(UpdaterScope scope) { … }
void ExpectAppsUpdateSequence(UpdaterScope scope,
ScopedServer* test_server,
const base::Value::Dict& request_attributes,
const std::vector<AppUpdateExpectation>& apps) { … }
void RunWake(UpdaterScope scope, int expected_exit_code) { … }
void RunWakeAll(UpdaterScope scope) { … }
void RunWakeActive(UpdaterScope scope, int expected_exit_code) { … }
void RunCrashMe(UpdaterScope scope) { … }
void RunServer(UpdaterScope scope, int expected_exit_code, bool internal) { … }
void CheckForUpdate(UpdaterScope scope, const std::string& app_id) { … }
void Update(UpdaterScope scope,
const std::string& app_id,
const std::string& install_data_index) { … }
void UpdateAll(UpdaterScope scope) { … }
void InstallAppViaService(UpdaterScope scope,
const std::string& appid,
const base::Value::Dict& expected_final_values) { … }
void GetAppStates(UpdaterScope updater_scope,
const base::Value::Dict& expected_app_states) { … }
void DeleteUpdaterDirectory(UpdaterScope scope) { … }
void DeleteActiveUpdaterExecutable(UpdaterScope scope) { … }
void DeleteFile(UpdaterScope , const base::FilePath& path) { … }
void SetupFakeUpdaterLowerVersion(UpdaterScope scope) { … }
void SetupFakeUpdaterHigherVersion(UpdaterScope scope) { … }
void SetExistenceCheckerPath(UpdaterScope scope,
const std::string& app_id,
const base::FilePath& path) { … }
void SetServerStarts(UpdaterScope scope, int value) { … }
void FillLog(UpdaterScope scope) { … }
void ExpectLogRotated(UpdaterScope scope) { … }
void ExpectRegistered(UpdaterScope scope, const std::string& app_id) { … }
void ExpectNotRegistered(UpdaterScope scope, const std::string& app_id) { … }
void ExpectAppTag(UpdaterScope scope,
const std::string& app_id,
const std::string& tag) { … }
void SetAppTag(UpdaterScope scope,
const std::string& app_id,
const std::string& tag) { … }
void Run(UpdaterScope scope, base::CommandLine command_line, int* exit_code) { … }
void ExpectCliResult(base::CommandLine command_line,
bool elevate,
std::optional<std::string> want_stdout,
std::optional<int> want_exit_code) { … }
void SetupRealUpdaterLowerVersion(UpdaterScope scope) { … }
void ExpectPing(UpdaterScope scope,
ScopedServer* test_server,
int event_type,
std::optional<GURL> target_url) { … }
void ExpectAppCommandPing(UpdaterScope scope,
ScopedServer* test_server,
const std::string& appid,
const std::string& appcommandid,
int errorcode,
int eventresult,
int event_type,
const base::Version& version) { … }
void ExpectSelfUpdateSequence(UpdaterScope scope, ScopedServer* test_server) { … }
void ExpectUpdateCheckRequest(UpdaterScope scope, ScopedServer* test_server) { … }
void ExpectUpdateCheckSequence(UpdaterScope scope,
ScopedServer* test_server,
const std::string& app_id,
UpdateService::Priority priority,
const base::Version& from_version,
const base::Version& to_version) { … }
void ExpectUpdateSequence(UpdaterScope scope,
ScopedServer* test_server,
const std::string& app_id,
const std::string& install_data_index,
UpdateService::Priority priority,
const base::Version& from_version,
const base::Version& to_version,
bool do_fault_injection) { … }
void ExpectUpdateSequenceBadHash(UpdaterScope scope,
ScopedServer* test_server,
const std::string& app_id,
const std::string& install_data_index,
UpdateService::Priority priority,
const base::Version& from_version,
const base::Version& to_version) { … }
void ExpectInstallSequence(UpdaterScope scope,
ScopedServer* test_server,
const std::string& app_id,
const std::string& install_data_index,
UpdateService::Priority priority,
const base::Version& from_version,
const base::Version& to_version,
bool do_fault_injection) { … }
void StressUpdateService(UpdaterScope scope) { … }
void CallServiceUpdate(UpdaterScope updater_scope,
const std::string& app_id,
const std::string& install_data_index,
bool same_version_update_allowed) { … }
void RunRecoveryComponent(UpdaterScope scope,
const std::string& app_id,
const base::Version& version) { … }
void SetLastChecked(UpdaterScope updater_scope, const base::Time& time) { … }
void ExpectLastChecked(UpdaterScope updater_scope) { … }
void ExpectLastStarted(UpdaterScope updater_scope) { … }
std::set<base::FilePath::StringType> GetTestProcessNames() { … }
#if BUILDFLAG(IS_WIN)
VersionProcessFilter::VersionProcessFilter()
: this_version_(base::Version(kUpdaterVersion)), older_version_([] {
const std::unique_ptr<FileVersionInfoWin> version_info =
FileVersionInfoWin::CreateFileVersionInfoWin(
GetRealUpdaterLowerVersionPath());
CHECK(version_info);
const base::Version version(
base::UTF16ToUTF8(version_info->file_version()));
CHECK(version.IsValid());
return version;
}()) {}
bool VersionProcessFilter::Includes(const base::ProcessEntry& entry) const {
const base::Process process(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,
false, entry.th32ProcessID));
if (!process.IsValid()) {
return false;
}
DWORD path_len = MAX_PATH;
std::wstring path(path_len, '\0');
if (!::QueryFullProcessImageName(process.Handle(), 0, path.data(),
&path_len)) {
return false;
}
const std::unique_ptr<FileVersionInfoWin> version_info =
FileVersionInfoWin::CreateFileVersionInfoWin(base::FilePath(path));
if (!version_info) {
return false;
}
const base::Version version(base::UTF16ToUTF8(version_info->file_version()));
return version.IsValid() &&
(version == this_version_ || version == older_version_);
}
#endif
void CleanProcesses() { … }
void ExpectCleanProcesses() { … }
#if !BUILDFLAG(IS_WIN)
void RunOfflineInstall(UpdaterScope scope,
bool is_legacy_install,
bool is_silent_install) { … }
void RunOfflineInstallOsNotSupported(UpdaterScope scope,
bool is_legacy_install,
bool is_silent_install) { … }
#endif
void DMPushEnrollmentToken(const std::string& enrollment_token) { … }
void DMDeregisterDevice(UpdaterScope scope) { … }
void DMCleanup(UpdaterScope scope) { … }
void ExpectDeviceManagementRegistrationRequest(
ScopedServer* test_server,
const std::string& enrollment_token,
const std::string& dm_token) { … }
void ExpectDeviceManagementPolicyFetchRequest(
ScopedServer* test_server,
const std::string& dm_token,
const ::wireless_android_enterprise_devicemanagement::
OmahaSettingsClientProto& omaha_settings,
bool first_request,
bool rotate_public_key,
std::optional<GURL> target_url) { … }
void ExpectDeviceManagementPolicyFetchWithNewPublicKeyRequest(
ScopedServer* test_server,
const std::string& dm_token,
const ::wireless_android_enterprise_devicemanagement::
OmahaSettingsClientProto& omaha_settings) { … }
void ExpectDeviceManagementTokenDeletionRequest(ScopedServer* test_server,
const std::string& dm_token,
bool invalidate_token) { … }
void ExpectDeviceManagementPolicyValidationRequest(
ScopedServer* test_server,
const std::string& dm_token) { … }
void ExpectProxyPacScriptRequest(ScopedServer* test_server) { … }
}