chromium/chrome/updater/auto_run_on_os_upgrade_task.cc

// 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)
    :{}

AutoRunOnOsUpgradeTask::~AutoRunOnOsUpgradeTask() = default;

void AutoRunOnOsUpgradeTask::Run(base::OnceClosure callback) {}

void AutoRunOnOsUpgradeTask::RunOnOsUpgradeForApps(
    const std::vector<std::string>& app_ids) {}

#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) {}

bool AutoRunOnOsUpgradeTask::HasOSUpgraded() {}

void AutoRunOnOsUpgradeTask::SetOSUpgraded() {}
#endif  // BUILDFLAG(IS_WIN)

}  // namespace updater