[go: nahoru, domu]

blob: 94147e48327195fbe9837ecc1ebfd8f8723e8e5b [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/updater/auto_run_on_os_upgrade_task.h"
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/process/launch.h"
#include "base/ranges/algorithm.h"
#include "base/sequence_checker.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/thread_pool.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/persisted_data.h"
#include "chrome/updater/util/util.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "chrome/updater/util/win_util.h"
#include "chrome/updater/win/app_command_runner.h"
#include "chrome/updater/win/win_constants.h"
#endif
namespace updater {
AutoRunOnOsUpgradeTask::AutoRunOnOsUpgradeTask(
UpdaterScope scope,
scoped_refptr<PersistedData> persisted_data)
: scope_(scope), persisted_data_(persisted_data) {}
AutoRunOnOsUpgradeTask::~AutoRunOnOsUpgradeTask() = default;
void AutoRunOnOsUpgradeTask::Run(base::OnceClosure callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!HasOSUpgraded()) {
std::move(callback).Run();
return;
}
base::ThreadPool::PostTaskAndReply(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&AutoRunOnOsUpgradeTask::RunOnOsUpgradeForApps, this,
persisted_data_->GetAppIds()),
base::BindOnce(&AutoRunOnOsUpgradeTask::SetOSUpgraded, this)
.Then(std::move(callback)));
}
void AutoRunOnOsUpgradeTask::RunOnOsUpgradeForApps(
const std::vector<std::string>& app_ids) {
base::ranges::for_each(
app_ids, [&](const auto& app_id) { RunOnOsUpgradeForApp(app_id); });
}
#if BUILDFLAG(IS_WIN)
namespace {
// Returns an OS upgrade string in the format
// `{previous_os_version}-{current_os_version}`. For example,
// "9.0.1200.0.0-10.0.19042.0.0".
std::string GetOSUpgradeVersionsString(
const OSVERSIONINFOEX& previous_os_version,
const OSVERSIONINFOEX& current_os_version) {
std::string os_upgrade_string;
for (const auto& version : {previous_os_version, current_os_version}) {
os_upgrade_string += base::StringPrintf(
"%lu.%lu.%lu.%u.%u%s", version.dwMajorVersion, version.dwMinorVersion,
version.dwBuildNumber, version.wServicePackMajor,
version.wServicePackMinor, os_upgrade_string.empty() ? "-" : "");
}
return os_upgrade_string;
}
} // namespace
size_t AutoRunOnOsUpgradeTask::RunOnOsUpgradeForApp(const std::string& app_id) {
size_t number_of_successful_tasks = 0;
base::ranges::for_each(
AppCommandRunner::LoadAutoRunOnOsUpgradeAppCommands(
scope_, base::SysUTF8ToWide(app_id)),
[&](const auto& app_command_runner) {
base::Process process;
if (FAILED(app_command_runner.Run(
{base::SysUTF8ToWide(os_upgrade_string_)}, process))) {
return;
}
VLOG(1) << "Successfully launched OS upgrade task with PID: "
<< process.Pid() << ": " << os_upgrade_string_;
++number_of_successful_tasks;
});
return number_of_successful_tasks;
}
bool AutoRunOnOsUpgradeTask::HasOSUpgraded() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
const std::optional<OSVERSIONINFOEX> previous_os_version =
persisted_data_->GetLastOSVersion();
if (!previous_os_version) {
// Initialize the OS version.
persisted_data_->SetLastOSVersion();
return false;
}
if (!CompareOSVersions(previous_os_version.value(), VER_GREATER)) {
return false;
}
if (const std::optional<OSVERSIONINFOEX> current_os_version = GetOSVersion();
current_os_version) {
os_upgrade_string_ = GetOSUpgradeVersionsString(previous_os_version.value(),
current_os_version.value());
}
return true;
}
void AutoRunOnOsUpgradeTask::SetOSUpgraded() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// Save the current OS as the old OS version.
persisted_data_->SetLastOSVersion();
}
#else // BUILDFLAG(IS_WIN)
size_t AutoRunOnOsUpgradeTask::RunOnOsUpgradeForApp(const std::string& app_id) {
return 0;
}
bool AutoRunOnOsUpgradeTask::HasOSUpgraded() {
return false;
}
void AutoRunOnOsUpgradeTask::SetOSUpgraded() {}
#endif // BUILDFLAG(IS_WIN)
} // namespace updater