#include "chrome/updater/update_service_impl_impl.h"
#include <map>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "base/barrier_callback.h"
#include "base/barrier_closure.h"
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/queue.h"
#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file_path.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_string_value_serializer.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/ranges/algorithm.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/bind_post_task.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/version.h"
#include "build/build_config.h"
#include "chrome/updater/auto_run_on_os_upgrade_task.h"
#include "chrome/updater/change_owners_task.h"
#include "chrome/updater/check_for_updates_task.h"
#include "chrome/updater/cleanup_task.h"
#include "chrome/updater/configurator.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/find_unregistered_apps_task.h"
#include "chrome/updater/installer.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/policy/service.h"
#include "chrome/updater/prefs.h"
#include "chrome/updater/registration_data.h"
#include "chrome/updater/remove_uninstalled_apps_task.h"
#include "chrome/updater/update_block_check.h"
#include "chrome/updater/update_service.h"
#include "chrome/updater/update_usage_stats_task.h"
#include "chrome/updater/updater_scope.h"
#include "chrome/updater/updater_version.h"
#include "chrome/updater/util/util.h"
#include "components/prefs/pref_service.h"
#include "components/update_client/crx_update_item.h"
#include "components/update_client/protocol_definition.h"
#include "components/update_client/update_client.h"
#include "components/update_client/update_client_errors.h"
#if BUILDFLAG(IS_MAC)
#include <sys/mount.h>
#endif
#if BUILDFLAG(IS_WIN)
#include <winhttp.h>
#include "base/win/registry.h"
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/ui/l10n_util.h"
#include "chrome/updater/win/ui/resources/resources.grh"
#include "chrome/updater/win/ui/resources/updater_installer_strings.h"
#include "chrome/updater/win/win_constants.h"
#endif
namespace updater {
namespace internal {
UpdateService::Result ToResult(update_client::Error error) { … }
void GetComponents(
scoped_refptr<PolicyService> policy_service,
crx_file::VerifierFormat verifier_format,
scoped_refptr<PersistedData> persisted_data,
const base::flat_map<std::string, std::string>& app_client_install_data,
const base::flat_map<std::string, std::string>& app_install_data_index,
const std::string& install_source,
UpdateService::Priority priority,
bool update_blocked,
UpdateService::PolicySameVersionUpdate policy_same_version_update,
const std::vector<std::string>& ids,
base::OnceCallback<
void(const std::vector<std::optional<update_client::CrxComponent>>&)>
callback) { … }
#if BUILDFLAG(IS_WIN)
namespace {
std::wstring GetTextForUpdateClientInstallError(int error_code) {
#define INSTALL_SWITCH_ENTRY …
switch (error_code) {
INSTALL_SWITCH_ENTRY(update_client::InstallError::NONE);
INSTALL_SWITCH_ENTRY(update_client::InstallError::FINGERPRINT_WRITE_FAILED);
INSTALL_SWITCH_ENTRY(update_client::InstallError::BAD_MANIFEST);
INSTALL_SWITCH_ENTRY(update_client::InstallError::GENERIC_ERROR);
INSTALL_SWITCH_ENTRY(update_client::InstallError::MOVE_FILES_ERROR);
INSTALL_SWITCH_ENTRY(update_client::InstallError::SET_PERMISSIONS_FAILED);
INSTALL_SWITCH_ENTRY(update_client::InstallError::INVALID_VERSION);
INSTALL_SWITCH_ENTRY(update_client::InstallError::VERSION_NOT_UPGRADED);
INSTALL_SWITCH_ENTRY(update_client::InstallError::NO_DIR_COMPONENT_USER);
INSTALL_SWITCH_ENTRY(update_client::InstallError::CLEAN_INSTALL_DIR_FAILED);
INSTALL_SWITCH_ENTRY(
update_client::InstallError::INSTALL_VERIFICATION_FAILED);
INSTALL_SWITCH_ENTRY(update_client::InstallError::MISSING_INSTALL_PARAMS);
INSTALL_SWITCH_ENTRY(update_client::InstallError::LAUNCH_PROCESS_FAILED);
INSTALL_SWITCH_ENTRY(update_client::InstallError::CUSTOM_ERROR_BASE);
default:
return GetLocalizedStringF(IDS_GENERIC_INSTALL_ERROR_BASE,
GetTextForSystemError(error_code));
}
#undef INSTALL_SWITCH_ENTRY
}
std::wstring GetTextForDownloadError(int error) {
#define DOWNLOAD_SWITCH_ENTRY …
switch (error) {
DOWNLOAD_SWITCH_ENTRY(update_client::CrxDownloaderError::NO_URL);
DOWNLOAD_SWITCH_ENTRY(update_client::CrxDownloaderError::NO_HASH);
DOWNLOAD_SWITCH_ENTRY(
update_client::CrxDownloaderError::BITS_TOO_MANY_JOBS);
DOWNLOAD_SWITCH_ENTRY(update_client::CrxDownloaderError::GENERIC_ERROR);
case static_cast<int>(update_client::CrxDownloaderError::BAD_HASH):
return GetLocalizedString(IDS_DOWNLOAD_HASH_MISMATCH_BASE);
default:
return GetLocalizedStringF(IDS_GENERIC_DOWNLOAD_ERROR_BASE,
GetTextForSystemError(error));
}
#undef DOWNLOAD_SWITCH_ENTRY
}
std::wstring GetTextForUnpackError(int error) {
#define UNPACK_SWITCH_ENTRY …
#define UNPACK_CACHING_SWITCH_ENTRY …
switch (error) {
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kInvalidParams);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kInvalidFile);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kUnzipPathError);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kUnzipFailed);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kBadManifest);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kBadExtension);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kIoError);
UNPACK_SWITCH_ENTRY(
update_client::UnpackerError::kDeltaVerificationFailure);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kDeltaBadCommands);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kDeltaUnsupportedCommand);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kDeltaOperationFailure);
UNPACK_SWITCH_ENTRY(
update_client::UnpackerError::kDeltaPatchProcessFailure);
UNPACK_SWITCH_ENTRY(
update_client::UnpackerError::kDeltaMissingExistingFile);
UNPACK_SWITCH_ENTRY(
update_client::UnpackerError::kPuffinMissingPreviousCrx);
UNPACK_SWITCH_ENTRY(update_client::UnpackerError::kCrxCacheNotProvided);
UNPACK_CACHING_SWITCH_ENTRY(
update_client::UnpackerError::kFailedToAddToCache);
UNPACK_CACHING_SWITCH_ENTRY(
update_client::UnpackerError::kFailedToCreateCacheDir);
default:
return GetLocalizedStringF(IDS_GENERIC_UNPACK_ERROR_BASE,
GetTextForSystemError(error));
}
#undef UNPACK_SWITCH_ENTRY
#undef UNPACK_CACHING_SWITCH_ENTRY
}
std::wstring GetTextForServiceError(int error) {
#define SERVICE_SWITCH_ENTRY …
switch (error) {
SERVICE_SWITCH_ENTRY(update_client::ServiceError::SERVICE_WAIT_FAILED);
SERVICE_SWITCH_ENTRY(update_client::ServiceError::UPDATE_DISABLED);
SERVICE_SWITCH_ENTRY(update_client::ServiceError::CHECK_FOR_UPDATE_ONLY);
case static_cast<int>(update_client::ServiceError::CANCELLED):
return GetLocalizedString(IDS_SERVICE_ERROR_CANCELLED_BASE);
default:
return GetLocalizedStringF(IDS_GENERIC_SERVICE_ERROR_BASE,
GetTextForSystemError(error));
}
#undef SERVICE_SWITCH_ENTRY
}
std::wstring GetTextForUpdateCheckError(int error) {
#define UPDATE_CHECK_SWITCH_ENTRY …
switch (error) {
UPDATE_CHECK_SWITCH_ENTRY(
update_client::ProtocolError::RESPONSE_NOT_TRUSTED);
UPDATE_CHECK_SWITCH_ENTRY(update_client::ProtocolError::MISSING_PUBLIC_KEY);
UPDATE_CHECK_SWITCH_ENTRY(update_client::ProtocolError::MISSING_URLS);
UPDATE_CHECK_SWITCH_ENTRY(update_client::ProtocolError::PARSE_FAILED);
UPDATE_CHECK_SWITCH_ENTRY(
update_client::ProtocolError::UPDATE_RESPONSE_NOT_FOUND);
UPDATE_CHECK_SWITCH_ENTRY(update_client::ProtocolError::URL_FETCHER_FAILED);
UPDATE_CHECK_SWITCH_ENTRY(update_client::ProtocolError::INVALID_APPID);
case static_cast<int>(update_client::ProtocolError::UNKNOWN_APPLICATION):
return GetLocalizedString(IDS_UNKNOWN_APPLICATION_BASE);
case static_cast<int>(update_client::ProtocolError::RESTRICTED_APPLICATION):
return GetLocalizedString(IDS_RESTRICTED_RESPONSE_FROM_SERVER_BASE);
case static_cast<int>(update_client::ProtocolError::OS_NOT_SUPPORTED):
return GetLocalizedString(IDS_OS_NOT_SUPPORTED_BASE);
case static_cast<int>(update_client::ProtocolError::HW_NOT_SUPPORTED):
return GetLocalizedString(IDS_HW_NOT_SUPPORTED_BASE);
case static_cast<int>(update_client::ProtocolError::NO_HASH):
return GetLocalizedString(IDS_NO_HASH_BASE);
case static_cast<int>(update_client::ProtocolError::UNSUPPORTED_PROTOCOL):
return GetLocalizedString(IDS_UNSUPPORTED_PROTOCOL_BASE);
case static_cast<int>(update_client::ProtocolError::INTERNAL):
return GetLocalizedString(IDS_INTERNAL_BASE);
case 401:
return GetLocalizedString(IDS_ERROR_HTTPSTATUS_UNAUTHORIZED_BASE);
case 403:
return GetLocalizedString(IDS_ERROR_HTTPSTATUS_FORBIDDEN_BASE);
case 407:
return GetLocalizedString(IDS_ERROR_HTTPSTATUS_PROXY_AUTH_REQUIRED_BASE);
case HRESULT_FROM_WIN32(ERROR_WINHTTP_NAME_NOT_RESOLVED):
return GetLocalizedStringF(IDS_NO_NETWORK_PRESENT_ERROR_BASE,
GetExecutableRelativePath().value());
default:
return GetLocalizedStringF(
IDS_GENERIC_UPDATE_CHECK_ERROR_BASE,
error >= 400 && error < 600
? base::UTF8ToWide(base::StringPrintf("HTTP %d", error))
: GetTextForSystemError(error));
}
#undef UPDATE_CHECK_SWITCH_ENTRY
}
std::wstring GetTextForInstallerError(int error_code) {
#define POLICY_ERROR_SWITCH_ENTRY …
switch (error_code) {
POLICY_ERROR_SWITCH_ENTRY(GOOPDATE_E_APP_INSTALL_DISABLED_BY_POLICY);
POLICY_ERROR_SWITCH_ENTRY(GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY);
POLICY_ERROR_SWITCH_ENTRY(GOOPDATE_E_APP_UPDATE_DISABLED_BY_POLICY_MANUAL);
case GOOPDATEINSTALL_E_FILENAME_INVALID:
return GetLocalizedString(IDS_INVALID_INSTALLER_FILENAME_BASE);
case GOOPDATEINSTALL_E_INSTALLER_FAILED_START:
return GetLocalizedString(IDS_INSTALLER_FAILED_TO_START_BASE);
case GOOPDATEINSTALL_E_INSTALLER_TIMED_OUT:
return GetLocalizedString(IDS_INSTALLER_TIMED_OUT_BASE);
case GOOPDATEINSTALL_E_INSTALL_ALREADY_RUNNING:
return GetLocalizedStringF(
IDS_GENERIC_INSTALLER_ERROR_BASE,
GetTextForSystemError(ERROR_INSTALL_ALREADY_RUNNING));
case ERROR_SUCCESS_REBOOT_INITIATED:
case ERROR_SUCCESS_REBOOT_REQUIRED:
case ERROR_SUCCESS_RESTART_REQUIRED:
return GetLocalizedStringF(IDS_INSTALL_REBOOT_BASE,
GetTextForSystemError(error_code));
default:
return GetLocalizedStringF(IDS_GENERIC_INSTALLER_ERROR_BASE,
GetTextForSystemError(error_code));
}
#undef POLICY_ERROR_SWITCH_ENTRY
}
}
std::string GetInstallerText(UpdateService::ErrorCategory error_category,
int error_code,
int extra_code) {
if (!error_code) {
return {};
}
return base::WideToUTF8(base::StrCat(
{[&] {
switch (error_category) {
case UpdateService::ErrorCategory::kInstall:
return GetTextForUpdateClientInstallError(error_code);
case UpdateService::ErrorCategory::kDownload:
return GetTextForDownloadError(error_code);
case UpdateService::ErrorCategory::kUnpack:
return GetTextForUnpackError(error_code);
case UpdateService::ErrorCategory::kService:
return GetTextForServiceError(error_code);
case UpdateService::ErrorCategory::kUpdateCheck:
return GetTextForUpdateCheckError(error_code);
case UpdateService::ErrorCategory::kInstaller:
return GetTextForInstallerError(error_code);
default:
LOG(ERROR) << "Unknown error category: " << error_category;
return std::wstring();
}
}(),
[&] {
if (!extra_code) {
return std::wstring();
}
return base::StrCat(
{L"\n", GetLocalizedStringF(IDS_EXTRA_CODE_BASE,
base::ASCIIToWide(base::StringPrintf(
"%#x", extra_code)))});
}()}));
}
#endif
base::Version GetRegisteredInstallerVersion(const std::string& app_id) { … }
}
namespace {
constexpr base::flat_map<std::string, std::string> kEmptyFlatMap;
update_client::Callback MakeUpdateClientCallback(
base::OnceCallback<void(UpdateService::Result)> callback) { … }
UpdateService::UpdateState::State ToUpdateState(
update_client::ComponentState component_state) { … }
UpdateService::ErrorCategory ToErrorCategory(
update_client::ErrorCategory error_category) { … }
update_client::UpdateClient::CrxStateChangeCallback
MakeUpdateClientCrxStateChangeCallback(
scoped_refptr<update_client::Configurator> config,
scoped_refptr<PersistedData> persisted_data,
const bool new_install,
base::RepeatingCallback<void(const UpdateService::UpdateState&)> callback) { … }
bool IsPathOnReadOnlyMount(const base::FilePath& path) { … }
}
UpdateServiceImplImpl::UpdateServiceImplImpl(scoped_refptr<Configurator> config)
: … { … }
void UpdateServiceImplImpl::GetVersion(
base::OnceCallback<void(const base::Version&)> callback) { … }
void UpdateServiceImplImpl::FetchPolicies(
base::OnceCallback<void(int)> callback) { … }
void UpdateServiceImplImpl::RegisterApp(
const RegistrationRequest& request,
base::OnceCallback<void(int)> callback) { … }
void UpdateServiceImplImpl::GetAppStates(
base::OnceCallback<void(const std::vector<AppState>&)> callback) { … }
void UpdateServiceImplImpl::RunPeriodicTasks(base::OnceClosure callback) { … }
void UpdateServiceImplImpl::TaskStart() { … }
void UpdateServiceImplImpl::TaskDone() { … }
void UpdateServiceImplImpl::ForceInstall(
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
void UpdateServiceImplImpl::CheckForUpdate(
const std::string& app_id,
Priority priority,
PolicySameVersionUpdate policy_same_version_update,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
void UpdateServiceImplImpl::Update(
const std::string& app_id,
const std::string& install_data_index,
Priority priority,
PolicySameVersionUpdate policy_same_version_update,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
void UpdateServiceImplImpl::UpdateAll(
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
void UpdateServiceImplImpl::Install(
const RegistrationRequest& registration,
const std::string& client_install_data,
const std::string& install_data_index,
Priority priority,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
void UpdateServiceImplImpl::CancelInstalls(const std::string& app_id) { … }
void UpdateServiceImplImpl::RunInstaller(
const std::string& app_id,
const base::FilePath& installer_path,
const std::string& install_args,
const std::string& install_data,
const std::string& install_settings,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
bool UpdateServiceImplImpl::IsUpdateDisabledByPolicy(const std::string& app_id,
Priority priority,
bool is_install,
int& policy) { … }
void UpdateServiceImplImpl::HandleUpdateDisabledByPolicy(
const std::string& app_id,
int policy,
bool is_install,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback) { … }
void UpdateServiceImplImpl::OnShouldBlockCheckForUpdateForMeteredNetwork(
const std::string& app_id,
Priority priority,
PolicySameVersionUpdate policy_same_version_update,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback,
bool update_blocked) { … }
void UpdateServiceImplImpl::OnShouldBlockUpdateForMeteredNetwork(
const std::vector<std::string>& app_ids,
const base::flat_map<std::string, std::string>& app_client_install_data,
const base::flat_map<std::string, std::string>& app_install_data_index,
Priority priority,
PolicySameVersionUpdate policy_same_version_update,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback,
bool update_blocked) { … }
void UpdateServiceImplImpl::OnShouldBlockForceInstallForMeteredNetwork(
const std::vector<std::string>& app_ids,
const base::flat_map<std::string, std::string>& app_client_install_data,
const base::flat_map<std::string, std::string>& app_install_data_index,
PolicySameVersionUpdate policy_same_version_update,
base::RepeatingCallback<void(const UpdateState&)> state_update,
base::OnceCallback<void(Result)> callback,
bool update_blocked) { … }
UpdateServiceImplImpl::~UpdateServiceImplImpl() { … }
}