blob: 9cb33968f3a54aa7ecc2833460f7f0db61718057 [file] [log] [blame]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_UPDATER_UPDATE_SERVICE_H_
#define CHROME_UPDATER_UPDATE_SERVICE_H_
#include <ostream>
#include <string>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/callback_forward.h"
#include "base/memory/ref_counted.h"
#include "base/version.h"
#include "chrome/updater/enum_traits.h"
#include "chrome/updater/util/util.h"
#include "components/update_client/update_client.h"
namespace updater {
struct RegistrationRequest;
enum class UpdaterScope;
// The UpdateService is the cross-platform core of the updater.
// All functions and callbacks must be called on the same sequence.
class UpdateService : public base::RefCountedThreadSafe<UpdateService> {
public:
// Defines the behavior of the update stack for over-installs.
// Typically, same versions updates are not allowed, in which case, the update
// server replies with `update not available'. But there are cases, such as
// re-installing an application again, when the server may respond with an
// update.
enum class PolicySameVersionUpdate {
// The embedder does not allow over-installs with the same version. In this
// case, the server is expected to return `update not available` when it
// is queried for updates.
kNotAllowed = 0,
// The embedder is capable of handling updates with the same version, and
// the server may respond with such an update.
kAllowed = 1,
};
// Values posted by the completion `callback` as a result of the
// non-blocking invocation of the service functions. These values are not
// present in the telemetry pings.
enum class Result {
// Indicates that the service successfully handled the non-blocking function
// invocation. Returning this value provides no indication regarding the
// outcome of the function, such as whether the updates succeeded or not.
kSuccess = 0,
// The function failed because there is an update in progress. Certain
// service functions can be parallelized but not all functions can run
// concurrently.
kUpdateInProgress = 1,
kUpdateCanceled = 2,
// The function failed because of a throttling policy such as load shedding.
kRetryLater = 3,
// This is a generic result indicating that an error occurred in the service
// such as a task failed to post, or allocation of a resource failed.
kServiceFailed = 4,
// An error handling the update check occurred.
kUpdateCheckFailed = 5,
// This value indicates that required metadata associated with the
// application was not available for any reason.
kAppNotFound = 6,
// A function argument was invalid.
kInvalidArgument = 7,
// This server is not the active server.
kInactive = 8,
// IPC connection to the remote process failed for some reason.
kIPCConnectionFailed = 9,
// Failed to run app installer.
kInstallFailed = 10,
// The service has been stopped, because the system is shutting down, or
// any other reason.
kServiceStopped = 11,
// The request could not be serviced, either because no user has accepted
// the terms of service, or OEM mode is in effect.
kEulaRequiredOrOemMode = 12,
// Update EnumTraits<UpdateService::Result> when adding new values.
};
// Run time errors are organized in specific categories to indicate the
// component where such errors occurred. The category appears as a numeric
// value in the telemetry pings. The values of this enum must be kept stable.
enum class ErrorCategory {
kNone = 0,
kDownload = 1,
kUnpack = 2,
kInstall = 3,
kService = 4,
kUpdateCheck = 5,
// Update EnumTraits<UpdateService::ErrorCategory> when adding new values.
};
struct UpdateState {
// Possible states for updating an app. Add new values at the end of
// the definition, and do not mutate the existing values.
enum class State {
// This value represents the absence of a state. No update request has
// yet been issued.
kUnknown = 0,
// This update has not been started, but has been requested.
kNotStarted = 1,
// The engine began issuing an update check request.
kCheckingForUpdates = 2,
// An update is available.
kUpdateAvailable = 3,
// The engine began downloading an update.
kDownloading = 4,
// The engine began running installation scripts.
kInstalling = 5,
// The engine found and installed an update for this product. The update
// is complete and the state will not change.
kUpdated = 6,
// The engine checked for updates. This product is already up to date.
// No update has been installed for this product. The update is complete
// and the state will not change.
kNoUpdate = 7,
// The engine encountered an error updating this product. The update has
// halted and the state will not change.
kUpdateError = 8,
// Update EnumTraits<UpdateService::UpdateState::State> when adding new
// values.
};
UpdateState();
UpdateState(const UpdateState&);
UpdateState& operator=(const UpdateState&);
UpdateState(UpdateState&&);
UpdateState& operator=(UpdateState&&);
~UpdateState();
std::string app_id;
State state = State::kUnknown;
// The version is initialized only after an update check has completed, and
// an update is available.
base::Version next_version;
int64_t downloaded_bytes = -1; // -1 means that the byte count is unknown.
int64_t total_bytes = -1;
// A value in the range [0, 100] if the install progress is known, or -1
// if the install progress is not available or it could not be computed.
int install_progress = -1;
ErrorCategory error_category = ErrorCategory::kNone;
int error_code = 0;
int extra_code1 = 0;
// Results collected from installer result API. See the definition of
// `update_client::CrxInstaller::Result` for the meaning of the members.
std::string installer_text;
std::string installer_cmd_line;
};
// Urgency of the update service invocation.
enum class Priority {
// The caller has not set a valid priority value.
kUnknown = 0,
// The user is not waiting for this update.
kBackground = 1,
// The user actively requested this update.
kForeground = 2,
};
struct AppState {
AppState();
AppState(const AppState&);
AppState& operator=(const AppState&);
AppState(AppState&&);
AppState& operator=(AppState&&);
~AppState();
std::string app_id;
base::Version version;
base::FilePath version_path;
std::string version_key;
std::string ap;
base::FilePath ap_path;
std::string ap_key;
std::string brand_code;
base::FilePath brand_path;
base::FilePath ecp;
};
using Callback = base::OnceCallback<void(Result)>;
using StateChangeCallback = base::RepeatingCallback<void(const UpdateState&)>;
using InstallerResult = update_client::CrxInstaller::Result;
// Returns the version of the active updater. The version object is invalid
// if an error (including timeout) occurs.
virtual void GetVersion(base::OnceCallback<void(const base::Version&)>) = 0;
// Fetches policies from device management.
virtual void FetchPolicies(base::OnceCallback<void(int)> callback) = 0;
// Registers given request to the updater.
virtual void RegisterApp(const RegistrationRequest& request,
base::OnceCallback<void(int)> callback) = 0;
// Gets state of all registered apps.
virtual void GetAppStates(
base::OnceCallback<void(const std::vector<AppState>&)>) = 0;
// Runs periodic tasks such as checking for uninstallation of registered
// applications or doing background updates for registered applications.
virtual void RunPeriodicTasks(base::OnceClosure callback) = 0;
// DEPRECATED - queries the server for updates, gets an update response, but
// does not download, install, or run any payload. This is intended to
// support the legacy on-demand Omaha interface but it should not be used
// by new code. The parameters are similar to the parameters of `Update`.
virtual void CheckForUpdate(
const std::string& app_id,
Priority priority,
PolicySameVersionUpdate policy_same_version_update,
StateChangeCallback state_update,
Callback callback) = 0;
// Updates specified product. This update may be on-demand.
//
// Args:
// `app_id`: ID of app to update.
// `install_data_index`: Index of the server install data.
// `priority`: Priority for processing this update.
// `policy_same_version_update`: Whether a same-version update is allowed.
// `state_update`: The callback will be invoked every time the update
// changes state when the engine starts. It will be called on the
// sequence used by the update service, so this callback must not block.
// It will not be called again after the update has reached a terminal
// state. It will not be called after the completion `callback` is posted.
// `callback`: Posted after the update stops, successfully or otherwise.
//
// `state_update` arg:
// UpdateState: the new state of this update request.
//
// `callback` arg:
// Result: the final result from the update engine.
virtual void Update(const std::string& app_id,
const std::string& install_data_index,
Priority priority,
PolicySameVersionUpdate policy_same_version_update,
StateChangeCallback state_update,
Callback callback) = 0;
// Initiates an update check for all registered applications. Receives state
// change notifications through the repeating `state_update` callback.
// Calls `callback` once the operation is complete.
virtual void UpdateAll(StateChangeCallback state_update,
Callback callback) = 0;
// Registers and installs an application from the network.
//
// Args:
// `registration`: Registration data about the app.
// `client_install_data`: User provided install data.
// `install_data_index`: Index of the server install data. Effective only
// when `client_install_data` is not set.
// `priority`: Priority for processing this update.
// `state_update`: The callback will be invoked every time the update
// changes state when the engine starts. It will be called on the
// sequence used by the update service, so this callback must not block.
// It will not be called again after the update has reached a terminal
// state. It will not be called after the completion `callback` is posted.
// `callback`: Posted after the update stops, successfully or otherwise.
//
// `state_update` arg:
// UpdateState: the new state of this update request.
//
// `callback` arg:
// Result: the final result from the update engine.
virtual void Install(const RegistrationRequest& registration,
const std::string& client_install_data,
const std::string& install_data_index,
Priority priority,
StateChangeCallback state_update,
Callback callback) = 0;
// Cancels any ongoing installations of the specified product. This does not
// interrupt any product installers that are currently running, but does
// prevent them from being run if they are not yet downloaded.
//
// Args:
// `app_id`: ID of the product to cancel installs of.
virtual void CancelInstalls(const std::string& app_id) = 0;
// Install an app by running its installer.
//
// Args:
// `app_id`: ID of app to install.
// `app_installer`: Offline installer path.
// `arguments`: Arguments to run the installer.
// `install_data`: Server install data extracted from the offline manifest.
// `install_settings`: An optional serialized dictionary to customize the
// installation.
// `state_update` arg:
// UpdateState: the new state of this install request.
//
// `callback` arg:
// Result: the final result from the update engine.
virtual void 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,
StateChangeCallback state_update,
Callback callback) = 0;
protected:
friend class base::RefCountedThreadSafe<UpdateService>;
virtual ~UpdateService() = default;
};
// These specializations must be defined in the `updater` namespace.
template <>
struct EnumTraits<UpdateService::Result> {
using Result = UpdateService::Result;
static constexpr Result first_elem = Result::kSuccess;
static constexpr Result last_elem = Result::kEulaRequiredOrOemMode;
};
template <>
struct EnumTraits<UpdateService::UpdateState::State> {
using State = UpdateService::UpdateState::State;
static constexpr State first_elem = State::kUnknown;
static constexpr State last_elem = State::kUpdateError;
};
template <>
struct EnumTraits<UpdateService::ErrorCategory> {
using ErrorCategory = UpdateService::ErrorCategory;
static constexpr ErrorCategory first_elem = ErrorCategory::kNone;
static constexpr ErrorCategory last_elem = ErrorCategory::kUpdateCheck;
};
std::ostream& operator<<(std::ostream& os,
const UpdateService::UpdateState& update_state);
inline std::ostream& operator<<(
std::ostream& os,
const UpdateService::PolicySameVersionUpdate& policy_same_version_update) {
return os << [&policy_same_version_update] {
switch (policy_same_version_update) {
case UpdateService::PolicySameVersionUpdate::kNotAllowed:
return "not allowed";
case UpdateService::PolicySameVersionUpdate::kAllowed:
return "allowed";
}
}();
}
bool operator==(const UpdateService::UpdateState& lhs,
const UpdateService::UpdateState& rhs);
inline bool operator!=(const UpdateService::UpdateState& lhs,
const UpdateService::UpdateState& rhs) {
return !(lhs == rhs);
}
} // namespace updater
#endif // CHROME_UPDATER_UPDATE_SERVICE_H_