blob: e6d770646c7544fbf58bfabc83c702b05cd5f2f4 [file] [log] [blame]
// Copyright 2021 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/updater_scope.h"
#include <optional>
#include "base/command_line.h"
#include "base/path_service.h"
#include "build/build_config.h"
#include "chrome/updater/constants.h"
#include "chrome/updater/util/util.h"
#if BUILDFLAG(IS_WIN)
#include "chrome/updater/tag.h"
#include "chrome/updater/util/win_util.h"
#endif
namespace updater {
namespace {
bool IsSystemProcessForCommandLine(const base::CommandLine& command_line) {
return command_line.HasSwitch(kSystemSwitch);
}
} // namespace
std::optional<tagging::NeedsAdmin> NeedsAdminFromTagArgs(
const std::optional<tagging::TagArgs> tag_args) {
if (!tag_args) {
return {};
}
if (!tag_args->apps.empty()) {
return tag_args->apps.front().needs_admin;
}
if (tag_args->runtime_mode) {
return tag_args->runtime_mode->needs_admin;
}
return {};
}
bool IsPrefersForCommandLine(const base::CommandLine& command_line) {
#if BUILDFLAG(IS_WIN)
std::optional<tagging::NeedsAdmin> needs_admin =
NeedsAdminFromTagArgs(GetTagArgsForCommandLine(command_line).tag_args);
return needs_admin ? *needs_admin == tagging::NeedsAdmin::kPrefers : false;
#else
return false;
#endif
}
UpdaterScope GetUpdaterScopeForCommandLine(
const base::CommandLine& command_line) {
#if BUILDFLAG(IS_WIN)
if (IsSystemProcessForCommandLine(command_line)) {
return UpdaterScope::kSystem;
}
// Assume only one app is present since bundles are not supported.
std::optional<tagging::NeedsAdmin> needs_admin =
NeedsAdminFromTagArgs(GetTagArgsForCommandLine(command_line).tag_args);
if (needs_admin) {
switch (*needs_admin) {
case tagging::NeedsAdmin::kYes:
return UpdaterScope::kSystem;
case tagging::NeedsAdmin::kNo:
return UpdaterScope::kUser;
case tagging::NeedsAdmin::kPrefers:
return command_line.HasSwitch(kCmdLinePrefersUser)
? UpdaterScope::kUser
: UpdaterScope::kSystem;
}
}
// The legacy updater could launch the shim without specifying the scope
// explicitly. This includes command line switches: '/healthcheck', '/regsvc',
// '/regserver', and '/ping'. In this case, choose system scope if this
// program is run as a system shim.
std::optional<base::FilePath> system_shim_path =
GetGoogleUpdateExePath(UpdaterScope::kSystem);
base::FilePath exe_path;
if (system_shim_path && base::PathService::Get(base::FILE_EXE, &exe_path) &&
system_shim_path->DirName().IsParent(exe_path)) {
return UpdaterScope::kSystem;
}
return UpdaterScope::kUser;
#else
return IsSystemProcessForCommandLine(command_line) ? UpdaterScope::kSystem
: UpdaterScope::kUser;
#endif
}
UpdaterScope GetUpdaterScope() {
return GetUpdaterScopeForCommandLine(*base::CommandLine::ForCurrentProcess());
}
bool IsSystemInstall() {
return IsSystemInstall(GetUpdaterScope());
}
bool IsSystemInstall(UpdaterScope scope) {
return scope == UpdaterScope::kSystem;
}
} // namespace updater