1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
6 #define COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_
12 #include "base/callback_forward.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/version.h"
17 // The UpdateClient class is a facade with a simple interface. The interface
18 // exposes a few APIs to install a CRX or update a group of CRXs.
20 // The difference between a CRX install and a CRX update is relatively minor.
21 // The terminology going forward will use the word "update" to cover both
22 // install and update scenarios, except where details regarding the install
25 // Handling an update consists of a series of actions such as sending an update
26 // check to the server, followed by parsing the server response, identifying
27 // the CRXs that require an update, downloading the differential update if
28 // it is available, unpacking and patching the differential update, then
29 // falling back to trying a similar set of actions using the full update.
30 // At the end of this process, completion pings are sent to the server,
31 // as needed, for the CRXs which had updates.
33 // As a general idea, this code handles the action steps needed to update
34 // a group of components serially, one step at a time. However, concurrent
35 // execution of calls to UpdateClient::Update is possible, therefore,
36 // queuing of updates could happen in some cases. More below.
38 // The UpdateClient class features a subject-observer interface to observe
39 // the CRX state changes during an update.
41 // The threading model for this code assumes that most of the code in the
42 // public interface runs on a SingleThreadTaskRunner.
43 // This task runner corresponds to the browser UI thread in many cases. There
44 // are parts of the installer interface that run on blocking task runners, which
45 // are usually threads in a thread pool.
47 // Using the UpdateClient is relatively easy. This assumes that the client
48 // of this code has already implemented the observer interface as needed, and
49 // can provide an installer, as described below.
51 // scoped_ptr<UpdateClient> update_client(UpdateClientFactory(...));
52 // update_client->AddObserver(&observer);
53 // std::vector<std::string> ids;
54 // ids.push_back(...));
55 // update_client->Update(ids, base::Bind(...), base::Bind(...));
57 // UpdateClient::Update takes two callbacks as parameters. First callback
58 // allows the client of this code to provide an instance of CrxComponent
59 // data structure that specifies additional parameters of the update.
60 // CrxComponent has a CrxInstaller data member, which must be provided by the
61 // callers of this class. The second callback indicates that this non-blocking
62 // call has completed.
64 // There could be several ways of triggering updates for a CRX, user-initiated,
65 // or timer-based. Since the execution of updates is concurrent, the parameters
66 // for the update must be provided right before the update is handled.
67 // Otherwise, the version of the CRX set in the CrxComponent may not be correct.
69 // The UpdateClient public interface includes two functions: Install and
70 // Update. These functions correspond to installing one CRX immediately as a
71 // foreground activity (Install), and updating a group of CRXs silently in the
72 // background (Update). This distinction is important. Background updates are
73 // queued up and their actions run serially, one at a time, for the purpose of
74 // conserving local resources such as CPU, network, and I/O.
75 // On the other hand, installs are never queued up but run concurrently, as
76 // requested by the user.
78 // The update client introduces a runtime constraint regarding interleaving
79 // updates and installs. If installs or updates for a given CRX are in progress,
80 // then installs for the same CRX will fail with a specific error.
82 // Implementation details.
84 // The implementation details below are not relevant to callers of this
85 // code. However, these design notes are relevant to the owners and maintainers
88 // The design for the update client consists of a number of abstractions
89 // such as: task, update engine, update context, and action.
90 // The execution model for these abstractions is simple. They usually expose
91 // a public, non-blocking Run function, and they invoke a callback when
92 // the Run function has completed.
94 // A task is the unit of work for the UpdateClient. A task is associated
95 // with a single call of the Update function. A task represents a group
96 // of CRXs that are updated together.
98 // The UpdateClient is responsible for the queuing of tasks, if queuing is
101 // When the task runs, it calls the update engine to handle the updates for
102 // the CRXs associated with the task. The UpdateEngine is the abstraction
103 // responsible for breaking down the update in a set of discrete steps, which
104 // are implemented as actions, and running the actions.
106 // The UpdateEngine maintains a set of UpdateContext instances. Each of
107 // these instances maintains the update state for all the CRXs belonging to
108 // a given task. The UpdateContext contains a queue of CRX ids.
109 // The UpdateEngine will handle updates for the CRXs in the order they appear
110 // in the queue, until the queue is empty.
112 // The update state for each CRX is maintained in a container of CrxUpdateItem*.
113 // As actions run, each action updates the CRX state, represented by one of
114 // these CrxUpdateItem* instances.
116 // Although the UpdateEngine can and will run update tasks concurrently, the
117 // actions of a task are run sequentially.
119 // The Action is a polymorphic type. There is some code reuse for convenience,
120 // implemented as a mixin. The polymorphic behavior of some of the actions
121 // is achieved using a template method.
123 // State changes of a CRX could generate events, which are observed using a
124 // subject-observer interface.
126 // The actions chain up. In some sense, the actions implement a state machine,
127 // as the CRX undergoes a series of state transitions in the process of
128 // being checked for updates and applying the update.
133 class DictionaryValue
;
137 namespace update_client
{
140 struct CrxUpdateItem
;
143 ERROR_UPDATE_IN_PROGRESS
= 1,
146 // Defines an interface for a generic CRX installer.
147 class CrxInstaller
: public base::RefCountedThreadSafe
<CrxInstaller
> {
149 // Called on the main thread when there was a problem unpacking or
150 // verifying the CRX. |error| is a non-zero value which is only meaningful
152 virtual void OnUpdateError(int error
) = 0;
154 // Called by the update service when a CRX has been unpacked
155 // and it is ready to be installed. |manifest| contains the CRX manifest
156 // as a json dictionary.|unpack_path| contains the temporary directory
157 // with all the unpacked CRX files.
158 // This method may be called from a thread other than the main thread.
159 virtual bool Install(const base::DictionaryValue
& manifest
,
160 const base::FilePath
& unpack_path
) = 0;
162 // Sets |installed_file| to the full path to the installed |file|. |file| is
163 // the filename of the file in this CRX. Returns false if this is
164 // not possible (the file has been removed or modified, or its current
165 // location is unknown). Otherwise, it returns true.
166 virtual bool GetInstalledFile(const std::string
& file
,
167 base::FilePath
* installed_file
) = 0;
169 // Called when a CRX has been unregistered and all versions should
170 // be uninstalled from disk. Returns true if uninstallation is supported,
171 // and false otherwise.
172 virtual bool Uninstall() = 0;
175 friend class base::RefCountedThreadSafe
<CrxInstaller
>;
177 virtual ~CrxInstaller() {}
180 // TODO(sorin): this structure will be refactored soon.
181 struct CrxComponent
{
185 // SHA256 hash of the CRX's public key.
186 std::vector
<uint8_t> pk_hash
;
187 scoped_refptr
<CrxInstaller
> installer
;
189 // The current version if the CRX is updated. Otherwise, "0" or "0.0" if
190 // the CRX is installed.
193 std::string fingerprint
; // Optional.
194 std::string name
; // Optional.
196 // Specifies that the CRX can be background-downloaded in some cases.
197 // The default for this value is |true| and the value can be overriden at
198 // the registration time. This is a temporary change until the issue
199 // crbug/340448 is resolved.
200 bool allow_background_download
;
203 // All methods are safe to call only from the browser's main thread.
206 using CrxDataCallback
=
207 base::Callback
<void(const std::vector
<std::string
>& ids
,
208 std::vector
<CrxComponent
>* components
)>;
209 using CompletionCallback
= base::Callback
<void(int error
)>;
211 // Defines an interface to observe the UpdateClient. It provides
212 // notifications when state changes occur for the service itself or for the
217 // Sent before the update client does an update check.
218 COMPONENT_CHECKING_FOR_UPDATES
,
220 // Sent when there is a new version of a registered CRX. After
221 // the notification is sent the CRX will be downloaded unless the
222 // update client inserts a
223 COMPONENT_UPDATE_FOUND
,
225 // Sent when a CRX is in the update queue but it can't be acted on
226 // right away, because the update client spaces out CRX updates due to a
227 // throttling policy.
230 // Sent after the new CRX has been downloaded but before the install
231 // or the upgrade is attempted.
232 COMPONENT_UPDATE_READY
,
234 // Sent when a CRX has been successfully updated.
237 // Sent when a CRX has not been updated following an update check:
238 // either there was no update available, or the update failed.
239 COMPONENT_NOT_UPDATED
,
241 // Sent when CRX bytes are being downloaded.
242 COMPONENT_UPDATE_DOWNLOADING
,
245 virtual ~Observer() {}
247 // Called by the update client when a state change happens.
248 // If an |id| is specified, then the event is fired on behalf of the
249 // specific CRX. The implementors of this interface are
250 // expected to filter the relevant events based on the id of the CRX.
251 virtual void OnEvent(Events event
, const std::string
& id
) = 0;
254 // Adds an observer for this class. An observer should not be added more
255 // than once. The caller retains the ownership of the observer object.
256 virtual void AddObserver(Observer
* observer
) = 0;
258 // Removes an observer. It is safe for an observer to be removed while
259 // the observers are being notified.
260 virtual void RemoveObserver(Observer
* observer
) = 0;
262 // Installs the specified CRX. Calls back after the install has been handled.
263 // Calls back on |completion_callback| after the update has been handled. The
264 // |error| parameter of the |completion_callback| contains an error code in
265 // the case of a run-time error, or 0 if the Install has been handled
267 virtual void Install(const std::string
& id
,
268 const CrxDataCallback
& crx_data_callback
,
269 const CompletionCallback
& completion_callback
) = 0;
271 // Updates the specified CRXs. Calls back on |crx_data_callback| before the
272 // update is attempted to give the caller the opportunity to provide the
273 // instances of CrxComponent to be used for this update.
274 virtual void Update(const std::vector
<std::string
>& ids
,
275 const CrxDataCallback
& crx_data_callback
,
276 const CompletionCallback
& completion_callback
) = 0;
278 // Returns status details about a CRX update. The function returns true in
279 // case of success and false in case of errors, such as |id| was
280 // invalid or not known.
281 virtual bool GetCrxUpdateState(const std::string
& id
,
282 CrxUpdateItem
* update_item
) const = 0;
284 virtual bool IsUpdating(const std::string
& id
) const = 0;
286 virtual ~UpdateClient() {}
289 // Creates an instance of the update client.
290 // TODO(sorin): make UpdateClient a ref counted type.
291 scoped_ptr
<UpdateClient
> UpdateClientFactory(
292 const scoped_refptr
<Configurator
>& config
);
294 } // namespace update_client
296 #endif // COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_