summaryrefslogtreecommitdiff
path: root/chromium/components/update_client/update_client.h
blob: d068a5654bf29104df086c5f9c4f5ae9b98f3fc1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
// 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/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.
//
// 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::Bind(...), base::Bind(...));
//
// 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 DictionaryValue;
class FilePath;
}

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,
  kLastStatus
};

// Called when a non-blocking call in this module completes.
using Callback = base::Callback<void(Error error)>;

// Defines an interface for a generic CRX installer.
class CrxInstaller : public base::RefCountedThreadSafe<CrxInstaller> {
 public:
  // Contains the result of the Install operation.
  struct Result {
    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;
  };

  // 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. |manifest| contains the CRX manifest
  // as a json dictionary.|unpack_path| contains the temporary directory
  // with all the unpacked CRX files.
  // This method may be called from a thread other than the main thread.
  virtual Result Install(const base::DictionaryValue& manifest,
                         const base::FilePath& unpack_path) = 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() {}
};

// 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>;

// TODO(sorin): this structure will be refactored soon.
struct CrxComponent {
  CrxComponent();
  CrxComponent(const CrxComponent& other);
  ~CrxComponent();

  // SHA256 hash of the CRX's public key.
  std::vector<uint8_t> pk_hash;
  scoped_refptr<CrxInstaller> installer;

  // The current version if the CRX is updated. Otherwise, "0" or "0.0" if
  // the CRX is installed.
  base::Version version;

  std::string fingerprint;  // Optional.
  std::string name;         // Optional.
  std::vector<std::string> handled_mime_types;

  // 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;

  // 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 if the component allows enabling or disabling updates by group policy.
  // This member should be set to |false| for data, non-binary components, such
  // as CRLSet, Supervised User Whitelists, STH Set, Origin Trials, and File
  // Type Policies.
  bool supports_group_policy_enable_component_updates;
};

// 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::RefCounted<UpdateClient> {
 public:
  using CrxDataCallback =
      base::Callback<void(const std::vector<std::string>& ids,
                          std::vector<CrxComponent>* components)>;

  // 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. After
      // the notification is sent the CRX will be downloaded unless the
      // update client inserts a
      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 following an update check:
      // either there was no update available, or the update failed.
      COMPONENT_NOT_UPDATED,

      // Sent when CRX bytes are being downloaded.
      COMPONENT_UPDATE_DOWNLOADING,
    };

    virtual ~Observer() {}

    // 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. 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.
  virtual void Install(const std::string& id,
                       const CrxDataCallback& crx_data_callback,
                       const 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. 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.
  virtual void Update(const std::vector<std::string>& ids,
                      const CrxDataCallback& crx_data_callback,
                      const Callback& callback) = 0;

  // Sends an uninstall ping for the CRX identified by |id| and |version|. The
  // |reason| parameter is defined by the caller. The current implementation of
  // this function only sends a best-effort, fire-and-forget ping. It has no
  // other side effects regarding installs or updates done through an instance
  // of this class.
  virtual void SendUninstallPing(const std::string& id,
                                 const base::Version& version,
                                 int reason,
                                 const 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::RefCounted<UpdateClient>;

  virtual ~UpdateClient() {}
};

// Creates an instance of the update client.
scoped_refptr<UpdateClient> UpdateClientFactory(
    const scoped_refptr<Configurator>& config);

// This must be called prior to the construction of any Configurator that
// contains a PrefService.
void RegisterPrefs(PrefRegistrySimple* registry);

}  // namespace update_client

#endif  // COMPONENTS_UPDATE_CLIENT_UPDATE_CLIENT_H_