// Copyright 2015 The Chromium Authors // 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 <optional> #include <string> #include <vector> #include "base/functional/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" // 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. // // Most of the code in the public interface runs on a SequencedTaskRunner. This // task runner corresponds to the browser UI thread but it can be any other // sequenced task runner. There are parts of the installer interface that run // on blocking task runners, which are usually sequences managed by the thread // pool. // // Using the UpdateClient requires creating an instance, adding observers, and // providing an installer instance, as shown 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 { … }; // Defines an interface for a generic CRX installer. class CrxInstaller : public base::RefCountedThreadSafe<CrxInstaller> { … }; // 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> { … }; // A dictionary of installer-specific, arbitrary name-value pairs, which // may be used in the update checks requests. InstallerAttributes; struct CrxComponent { … }; // Called when a non-blocking call of UpdateClient completes. Callback; // 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> { … }; // 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_