123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526 |
- // Copyright 2015 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
- #define COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
- #include <stdint.h>
- #include <map>
- #include <memory>
- #include <string>
- #include <vector>
- #include "base/callback_forward.h"
- #include "base/memory/ref_counted.h"
- #include "base/version.h"
- #include "components/crx_file/crx_verifier.h"
- #include "components/update_client/update_client_errors.h"
- #include "third_party/abseil-cpp/absl/types/optional.h"
- // The UpdateClient class is a facade with a simple interface. The interface
- // exposes a few APIs to install a CRX or update a group of CRXs.
- //
- // The difference between a CRX install and a CRX update is relatively minor.
- // The terminology going forward will use the word "update" to cover both
- // install and update scenarios, except where details regarding the install
- // case are relevant.
- //
- // Handling an update consists of a series of actions such as sending an update
- // check to the server, followed by parsing the server response, identifying
- // the CRXs that require an update, downloading the differential update if
- // it is available, unpacking and patching the differential update, then
- // falling back to trying a similar set of actions using the full update.
- // At the end of this process, completion pings are sent to the server,
- // as needed, for the CRXs which had updates.
- //
- // As a general idea, this code handles the action steps needed to update
- // a group of components serially, one step at a time. However, concurrent
- // execution of calls to UpdateClient::Update is possible, therefore,
- // queuing of updates could happen in some cases. More below.
- //
- // The UpdateClient class features a subject-observer interface to observe
- // the CRX state changes during an update.
- //
- // The threading model for this code assumes that most of the code in the
- // public interface runs on a SingleThreadTaskRunner.
- // This task runner corresponds to the browser UI thread in many cases. There
- // are parts of the installer interface that run on blocking task runners, which
- // are usually threads in a thread pool.
- //
- // Using the UpdateClient is relatively easy. This assumes that the client
- // of this code has already implemented the observer interface as needed, and
- // can provide an installer, as described below.
- //
- // std::unique_ptr<UpdateClient> update_client(UpdateClientFactory(...));
- // update_client->AddObserver(&observer);
- // std::vector<std::string> ids;
- // ids.push_back(...));
- // update_client->Update(ids, base::BindOnce(...), base::BindOnce(...));
- //
- // UpdateClient::Update takes two callbacks as parameters. First callback
- // allows the client of this code to provide an instance of CrxComponent
- // data structure that specifies additional parameters of the update.
- // CrxComponent has a CrxInstaller data member, which must be provided by the
- // callers of this class. The second callback indicates that this non-blocking
- // call has completed.
- //
- // There could be several ways of triggering updates for a CRX, user-initiated,
- // or timer-based. Since the execution of updates is concurrent, the parameters
- // for the update must be provided right before the update is handled.
- // Otherwise, the version of the CRX set in the CrxComponent may not be correct.
- //
- // The UpdateClient public interface includes two functions: Install and
- // Update. These functions correspond to installing one CRX immediately as a
- // foreground activity (Install), and updating a group of CRXs silently in the
- // background (Update). This distinction is important. Background updates are
- // queued up and their actions run serially, one at a time, for the purpose of
- // conserving local resources such as CPU, network, and I/O.
- // On the other hand, installs are never queued up but run concurrently, as
- // requested by the user.
- //
- // The update client introduces a runtime constraint regarding interleaving
- // updates and installs. If installs or updates for a given CRX are in progress,
- // then installs for the same CRX will fail with a specific error.
- //
- // Implementation details.
- //
- // The implementation details below are not relevant to callers of this
- // code. However, these design notes are relevant to the owners and maintainers
- // of this module.
- //
- // The design for the update client consists of a number of abstractions
- // such as: task, update engine, update context, and action.
- // The execution model for these abstractions is simple. They usually expose
- // a public, non-blocking Run function, and they invoke a callback when
- // the Run function has completed.
- //
- // A task is the unit of work for the UpdateClient. A task is associated
- // with a single call of the Update function. A task represents a group
- // of CRXs that are updated together.
- //
- // The UpdateClient is responsible for the queuing of tasks, if queuing is
- // needed.
- //
- // When the task runs, it calls the update engine to handle the updates for
- // the CRXs associated with the task. The UpdateEngine is the abstraction
- // responsible for breaking down the update in a set of discrete steps, which
- // are implemented as actions, and running the actions.
- //
- // The UpdateEngine maintains a set of UpdateContext instances. Each of
- // these instances maintains the update state for all the CRXs belonging to
- // a given task. The UpdateContext contains a queue of CRX ids.
- // The UpdateEngine will handle updates for the CRXs in the order they appear
- // in the queue, until the queue is empty.
- //
- // The update state for each CRX is maintained in a container of CrxUpdateItem*.
- // As actions run, each action updates the CRX state, represented by one of
- // these CrxUpdateItem* instances.
- //
- // Although the UpdateEngine can and will run update tasks concurrently, the
- // actions of a task are run sequentially.
- //
- // The Action is a polymorphic type. There is some code reuse for convenience,
- // implemented as a mixin. The polymorphic behavior of some of the actions
- // is achieved using a template method.
- //
- // State changes of a CRX could generate events, which are observed using a
- // subject-observer interface.
- //
- // The actions chain up. In some sense, the actions implement a state machine,
- // as the CRX undergoes a series of state transitions in the process of
- // being checked for updates and applying the update.
- class PrefRegistrySimple;
- namespace base {
- class FilePath;
- }
- namespace crx_file {
- enum class VerifierFormat;
- }
- namespace update_client {
- class Configurator;
- enum class Error;
- struct CrxUpdateItem;
- enum class ComponentState {
- kNew,
- kChecking,
- kCanUpdate,
- kDownloadingDiff,
- kDownloading,
- kDownloaded,
- kUpdatingDiff,
- kUpdating,
- kUpdated,
- kUpToDate,
- kUpdateError,
- kUninstalled,
- kRegistration,
- kRun,
- kLastStatus
- };
- // Defines an interface for a generic CRX installer.
- class CrxInstaller : public base::RefCountedThreadSafe<CrxInstaller> {
- public:
- // Contains the result of the Install operation.
- struct Result {
- Result() = default;
- explicit Result(int error, int extended_error = 0)
- : error(error), extended_error(extended_error) {}
- explicit Result(InstallError error, int extended_error = 0)
- : error(static_cast<int>(error)), extended_error(extended_error) {}
- int error = 0; // 0 indicates that install has been successful.
- int extended_error = 0;
- // Localized text displayed to the user, if applicable.
- std::string installer_text;
- // Shell command run at the end of the install, if applicable. This string
- // must be escaped to be a command line.
- std::string installer_cmd_line;
- };
- struct InstallParams {
- InstallParams(const std::string& run,
- const std::string& arguments,
- const std::string& server_install_data);
- std::string run;
- std::string arguments;
- std::string server_install_data;
- };
- using ProgressCallback = base::RepeatingCallback<void(int progress)>;
- using Callback = base::OnceCallback<void(const Result& result)>;
- // Called on the main thread when there was a problem unpacking or
- // verifying the CRX. |error| is a non-zero value which is only meaningful
- // to the caller.
- virtual void OnUpdateError(int error) = 0;
- // Called by the update service when a CRX has been unpacked
- // and it is ready to be installed. This method may be called from a
- // sequence other than the main sequence.
- // |unpack_path| contains the temporary directory with all the unpacked CRX
- // files.
- // |pubkey| contains the public key of the CRX in the PEM format, without the
- // header and the footer.
- // |install_params| is an optional parameter which provides the name and the
- // arguments for a binary program which is invoked as part of the install or
- // update flows.
- // |progress_callback| reports installer progress. This callback must be run
- // directly instead of posting it.
- // |callback| must be the last callback invoked and it indicates that the
- // install flow has completed.
- virtual void Install(const base::FilePath& unpack_path,
- const std::string& public_key,
- std::unique_ptr<InstallParams> install_params,
- ProgressCallback progress_callback,
- Callback callback) = 0;
- // Sets |installed_file| to the full path to the installed |file|. |file| is
- // the filename of the file in this CRX. Returns false if this is
- // not possible (the file has been removed or modified, or its current
- // location is unknown). Otherwise, it returns true.
- virtual bool GetInstalledFile(const std::string& file,
- base::FilePath* installed_file) = 0;
- // Called when a CRX has been unregistered and all versions should
- // be uninstalled from disk. Returns true if uninstallation is supported,
- // and false otherwise.
- virtual bool Uninstall() = 0;
- protected:
- friend class base::RefCountedThreadSafe<CrxInstaller>;
- virtual ~CrxInstaller() = default;
- };
- // Defines an interface to handle |action| elements in the update response.
- // The current implementation only handles run actions bound to a CRX, meaning
- // that such CRX is unpacked and an executable file, contained inside the CRX,
- // is run, then the results of the invocation are collected by the callback.
- class ActionHandler : public base::RefCountedThreadSafe<ActionHandler> {
- public:
- using Callback =
- base::OnceCallback<void(bool succeeded, int error_code, int extra_code1)>;
- virtual void Handle(const base::FilePath& action,
- const std::string& session_id,
- Callback callback) = 0;
- protected:
- friend class base::RefCountedThreadSafe<ActionHandler>;
- virtual ~ActionHandler() = default;
- };
- // A dictionary of installer-specific, arbitrary name-value pairs, which
- // may be used in the update checks requests.
- using InstallerAttributes = std::map<std::string, std::string>;
- struct CrxComponent {
- CrxComponent();
- CrxComponent(const CrxComponent& other);
- ~CrxComponent();
- // Optional SHA256 hash of the CRX's public key. If not supplied, the
- // unpacker can accept any CRX for this app, provided that the CRX meets the
- // VerifierFormat requirements specified by the service's configurator.
- // Callers that know or need a specific developer signature on acceptable CRX
- // files must provide this.
- std::vector<uint8_t> pk_hash;
- scoped_refptr<CrxInstaller> installer;
- scoped_refptr<ActionHandler> action_handler;
- std::string app_id;
- // The current version if the CRX is updated. Otherwise, "0" or "0.0" if
- // the CRX is installed.
- base::Version version;
- // Optional. This additional parameter ("ap") is sent to the server, which
- // often uses it to distinguish between variants of the software that were
- // chosen at install time.
- std::string ap;
- // If nonempty, the brand is an uppercase 4-letter string that describes the
- // flavor, branding, or provenance of the software.
- std::string brand;
- // If populated, the `install_data_index` is sent to the update server as part
- // of the `data` element. The server will provide corresponding installer data
- // in the update response. This data is then provided to the installer when
- // running it.
- std::string install_data_index;
- std::string fingerprint; // Optional.
- std::string name; // Optional.
- // Optional.
- // Valid values for the name part of an attribute match
- // ^[-_a-zA-Z0-9]{1,256}$ and valid values the value part of an attribute
- // match ^[-.,;+_=$a-zA-Z0-9]{0,256}$ .
- InstallerAttributes installer_attributes;
- // Specifies that the CRX can be background-downloaded in some cases.
- // The default for this value is |true|.
- bool allows_background_download = true;
- // Specifies that the update checks and pings associated with this component
- // require confidentiality. The default for this value is |true|. As a side
- // note, the confidentiality of the downloads is enforced by the server,
- // which only returns secure download URLs in this case.
- bool requires_network_encryption = true;
- // Specifies the strength of package validation required for the item.
- crx_file::VerifierFormat crx_format_requirement =
- crx_file::VerifierFormat::CRX3_WITH_PUBLISHER_PROOF;
- // True if and only if this item may be updated.
- bool updates_enabled = true;
- // Reasons why this component/extension is disabled.
- std::vector<int> disabled_reasons;
- // Information about where the component/extension was installed from.
- // For extension, this information is set from the update service, which
- // gets the install source from the update URL.
- std::string install_source;
- // Information about where the component/extension was loaded from.
- // For extensions, this information is inferred from the extension
- // registry.
- std::string install_location;
- // Information about the channel to send to the update server when updating
- // the component. This optional field is typically populated by policy and is
- // only populated on managed devices.
- std::string channel;
- // A version prefix sent to the server in the case of version pinning. The
- // server should not respond with an update to a version that does not match
- // this prefix. If no prefix is specified, the client will accept any version.
- std::string target_version_prefix;
- // An indicator sent to the server to advise whether it may perform a version
- // downgrade of this item.
- bool rollback_allowed = false;
- // An indicator sent to the server to advise whether it may perform an
- // over-install on this item.
- bool same_version_update_allowed = false;
- };
- // Called when a non-blocking call of UpdateClient completes.
- using Callback = base::OnceCallback<void(Error error)>;
- // All methods are safe to call only from the browser's main thread. Once an
- // instance of this class is created, the reference to it must be released
- // only after the thread pools of the browser process have been destroyed and
- // the browser process has gone single-threaded.
- class UpdateClient : public base::RefCountedThreadSafe<UpdateClient> {
- public:
- // Returns `CrxComponent` instances corresponding to the component ids
- // passed as an argument to the callback. The order of components in the input
- // and output vectors must match. If the instance of the `CrxComponent` is not
- // available for some reason, implementors of the callback must not skip
- // skip the component, and instead, they must insert a `nullopt` value in
- // the output vector.
- using CrxDataCallback =
- base::OnceCallback<std::vector<absl::optional<CrxComponent>>(
- const std::vector<std::string>& ids)>;
- // Called when state changes occur during an Install or Update call.
- using CrxStateChangeCallback =
- base::RepeatingCallback<void(CrxUpdateItem item)>;
- // Defines an interface to observe the UpdateClient. It provides
- // notifications when state changes occur for the service itself or for the
- // registered CRXs.
- class Observer {
- public:
- enum class Events {
- // Sent before the update client does an update check.
- COMPONENT_CHECKING_FOR_UPDATES = 1,
- // Sent when there is a new version of a registered CRX. The CRX will be
- // downloaded after the notification unless the update client inserts
- // a wait because of a throttling policy.
- COMPONENT_UPDATE_FOUND,
- // Sent when a CRX is in the update queue but it can't be acted on
- // right away, because the update client spaces out CRX updates due to a
- // throttling policy.
- COMPONENT_WAIT,
- // Sent after the new CRX has been downloaded but before the install
- // or the upgrade is attempted.
- COMPONENT_UPDATE_READY,
- // Sent when a CRX has been successfully updated.
- COMPONENT_UPDATED,
- // Sent when a CRX has not been updated because there was no update
- // available for this component.
- COMPONENT_ALREADY_UP_TO_DATE,
- // Sent when an error ocurred during an update for any reason, including
- // the update check itself failed, or the download of the update payload
- // failed, or applying the update failed.
- COMPONENT_UPDATE_ERROR,
- // Sent when CRX bytes are being downloaded.
- COMPONENT_UPDATE_DOWNLOADING,
- // Sent when install progress is received from the CRX installer.
- COMPONENT_UPDATE_UPDATING,
- };
- virtual ~Observer() = default;
- // Called by the update client when a state change happens.
- // If an |id| is specified, then the event is fired on behalf of the
- // specific CRX. The implementors of this interface are
- // expected to filter the relevant events based on the id of the CRX.
- virtual void OnEvent(Events event, const std::string& id) = 0;
- };
- // Adds an observer for this class. An observer should not be added more
- // than once. The caller retains the ownership of the observer object.
- virtual void AddObserver(Observer* observer) = 0;
- // Removes an observer. It is safe for an observer to be removed while
- // the observers are being notified.
- virtual void RemoveObserver(Observer* observer) = 0;
- // Installs the specified CRX. Calls back on |callback| after the
- // update has been handled. Provides state change notifications through
- // invocations of the optional |crx_state_change_callback| callback.
- // The |error| parameter of the |callback| contains an error code in the case
- // of a run-time error, or 0 if the install has been handled successfully.
- // Overlapping calls of this function are executed concurrently, as long as
- // the id parameter is different, meaning that installs of different
- // components are parallelized.
- // The |Install| function is intended to be used for foreground installs of
- // one CRX. These cases are usually associated with on-demand install
- // scenarios, which are triggered by user actions. Installs are never
- // queued up.
- // Returns a closure that can be called to cancel the installation.
- virtual base::RepeatingClosure Install(
- const std::string& id,
- CrxDataCallback crx_data_callback,
- CrxStateChangeCallback crx_state_change_callback,
- Callback callback) = 0;
- // Updates the specified CRXs. Calls back on |crx_data_callback| before the
- // update is attempted to give the caller the opportunity to provide the
- // instances of CrxComponent to be used for this update. Provides state change
- // notifications through invocations of the optional
- // |crx_state_change_callback| callback.
- // The |Update| function is intended to be used for background updates of
- // several CRXs. Overlapping calls to this function result in a queuing
- // behavior, and the execution of each call is serialized. In addition,
- // updates are always queued up when installs are running. The |is_foreground|
- // parameter must be set to true if the invocation of this function is a
- // result of a user initiated update.
- virtual void Update(const std::vector<std::string>& ids,
- CrxDataCallback crx_data_callback,
- CrxStateChangeCallback crx_state_change_callback,
- bool is_foreground,
- Callback callback) = 0;
- // Sends an uninstall ping for `crx_component`. `reason` is sent to the server
- // to indicate the cause of the uninstallation. The current implementation of
- // this function only sends a best-effort ping. It has no other side effects
- // regarding installs or updates done through an instance of this class.
- virtual void SendUninstallPing(const CrxComponent& crx_component,
- int reason,
- Callback callback) = 0;
- // Returns status details about a CRX update. The function returns true in
- // case of success and false in case of errors, such as |id| was
- // invalid or not known.
- virtual bool GetCrxUpdateState(const std::string& id,
- CrxUpdateItem* update_item) const = 0;
- // Returns true if the |id| is found in any running task.
- virtual bool IsUpdating(const std::string& id) const = 0;
- // Cancels the queued updates and makes a best effort to stop updates in
- // progress as soon as possible. Some updates may not be stopped, in which
- // case, the updates will run to completion. Calling this function has no
- // effect if updates are not currently executed or queued up.
- virtual void Stop() = 0;
- protected:
- friend class base::RefCountedThreadSafe<UpdateClient>;
- virtual ~UpdateClient() = default;
- };
- // Creates an instance of the update client.
- scoped_refptr<UpdateClient> UpdateClientFactory(
- scoped_refptr<Configurator> config);
- // This must be called prior to the construction of any Configurator that
- // contains a PrefService.
- void RegisterPrefs(PrefRegistrySimple* registry);
- // This must be called prior to the construction of any Configurator that
- // needs access to local user profiles.
- // This function is mostly used for ExtensionUpdater, which requires update
- // info from user profiles.
- void RegisterProfilePrefs(PrefRegistrySimple* registry);
- } // namespace update_client
- #endif // COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
|