summaryrefslogtreecommitdiff
path: root/chromium/components/update_client/update_engine.h
blob: 2cfe9da04655255b373b1259b1d0c45635865845 (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
// 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_ENGINE_H_
#define COMPONENTS_UPDATE_CLIENT_UPDATE_ENGINE_H_

#include <list>
#include <map>
#include <memory>
#include <string>
#include <vector>

#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "components/update_client/component.h"
#include "components/update_client/crx_downloader.h"
#include "components/update_client/crx_update_item.h"
#include "components/update_client/ping_manager.h"
#include "components/update_client/update_checker.h"
#include "components/update_client/update_client.h"

namespace base {
class TimeTicks;
}  // namespace base

namespace update_client {

class Configurator;
struct UpdateContext;

// Handles updates for a group of components. Updates for different groups
// are run concurrently but within the same group of components, updates are
// applied one at a time.
class UpdateEngine : public base::RefCounted<UpdateEngine> {
 public:
  using Callback = base::OnceCallback<void(Error error)>;
  using NotifyObserversCallback =
      base::Callback<void(UpdateClient::Observer::Events event,
                          const std::string& id)>;
  using CrxDataCallback = UpdateClient::CrxDataCallback;

  UpdateEngine(scoped_refptr<Configurator> config,
               UpdateChecker::Factory update_checker_factory,
               CrxDownloader::Factory crx_downloader_factory,
               scoped_refptr<PingManager> ping_manager,
               const NotifyObserversCallback& notify_observers_callback);

  // Returns true and the state of the component identified by |id|, if the
  // component is found in any update context. Returns false if the component
  // is not found.
  bool GetUpdateState(const std::string& id, CrxUpdateItem* update_state);

  void Update(bool is_foreground,
              const std::vector<std::string>& ids,
              UpdateClient::CrxDataCallback crx_data_callback,
              Callback update_callback);

  void SendUninstallPing(const std::string& id,
                         const base::Version& version,
                         int reason,
                         Callback update_callback);

 private:
  friend class base::RefCounted<UpdateEngine>;
  ~UpdateEngine();

  using UpdateContexts = std::map<std::string, scoped_refptr<UpdateContext>>;

  void UpdateComplete(scoped_refptr<UpdateContext> update_context, Error error);

  void ComponentCheckingForUpdatesStart(
      scoped_refptr<UpdateContext> update_context,
      const std::string& id);
  void ComponentCheckingForUpdatesComplete(
      scoped_refptr<UpdateContext> update_context);
  void UpdateCheckComplete(scoped_refptr<UpdateContext> update_context);

  void DoUpdateCheck(scoped_refptr<UpdateContext> update_context);
  void UpdateCheckDone(scoped_refptr<UpdateContext> update_context,
                       int error,
                       int retry_after_sec);

  void HandleComponent(scoped_refptr<UpdateContext> update_context);
  void HandleComponentComplete(scoped_refptr<UpdateContext> update_context);

  // Returns true if the update engine rejects this update call because it
  // occurs too soon.
  bool IsThrottled(bool is_foreground) const;

  base::ThreadChecker thread_checker_;
  scoped_refptr<Configurator> config_;
  UpdateChecker::Factory update_checker_factory_;
  CrxDownloader::Factory crx_downloader_factory_;
  scoped_refptr<PingManager> ping_manager_;
  std::unique_ptr<PersistedData> metadata_;

  // Called when CRX state changes occur.
  const NotifyObserversCallback notify_observers_callback_;

  // Contains the contexts associated with each update in progress.
  UpdateContexts update_contexts_;

  // Implements a rate limiting mechanism for background update checks. Has the
  // effect of rejecting the update call if the update call occurs before
  // a certain time, which is negotiated with the server as part of the
  // update protocol. See the comments for X-Retry-After header.
  base::TimeTicks throttle_updates_until_;

  DISALLOW_COPY_AND_ASSIGN(UpdateEngine);
};

// Describes a group of components which are installed or updated together.
struct UpdateContext : public base::RefCounted<UpdateContext> {
  UpdateContext(
      scoped_refptr<Configurator> config,
      bool is_foreground,
      const std::vector<std::string>& ids,
      UpdateClient::CrxDataCallback crx_data_callback,
      const UpdateEngine::NotifyObserversCallback& notify_observers_callback,
      UpdateEngine::Callback callback,
      CrxDownloader::Factory crx_downloader_factory);

  scoped_refptr<Configurator> config;

  // True if the component is updated as a result of user interaction.
  bool is_foreground = false;

  // True if the component updates are enabled in this context.
  const bool enabled_component_updates;

  // Contains the ids of all CRXs in this context in the order specified
  // by the caller of |UpdateClient::Update| or |UpdateClient:Install|.
  const std::vector<std::string> ids;

  // Contains the map of ids to components for all the CRX in this context.
  IdToComponentPtrMap components;

  // Called before an update check, when update metadata is needed.
  UpdateEngine::CrxDataCallback crx_data_callback;

  // Called when there is a state change for any update in this context.
  const UpdateEngine::NotifyObserversCallback notify_observers_callback;

  // Called when the all updates associated with this context have completed.
  UpdateEngine::Callback callback;

  // Creates instances of CrxDownloader;
  CrxDownloader::Factory crx_downloader_factory;

  std::unique_ptr<UpdateChecker> update_checker;

  // The time in seconds to wait until doing further update checks.
  int retry_after_sec = 0;

  // Contains the ids of the components to check for updates. It is possible
  // for a component to be uninstalled after it has been added in this context
  // but before an update check is made. When this happens, the component won't
  // have a CrxComponent instance, therefore, it can't be included in an
  // update check.
  std::vector<std::string> components_to_check_for_updates;

  // The error reported by the update checker.
  int update_check_error = 0;

  size_t num_components_ready_to_check = 0;
  size_t num_components_checked = 0;

  // Contains the ids of the components that the state machine must handle.
  base::queue<std::string> component_queue;

  // The time to wait before handling the update for a component.
  // The wait time is proportional with the cost incurred by updating
  // the component. The more time it takes to download and apply the
  // update for the current component, the longer the wait until the engine
  // is handling the next component in the queue.
  base::TimeDelta next_update_delay;

  // The unique session id of this context. The session id is serialized in
  // every protocol request. It is also used as a key in various data stuctures
  // to uniquely identify an update context.
  const std::string session_id;

 private:
  friend class base::RefCounted<UpdateContext>;
  ~UpdateContext();

  DISALLOW_COPY_AND_ASSIGN(UpdateContext);
};

}  // namespace update_client

#endif  // COMPONENTS_UPDATE_CLIENT_UPDATE_ENGINE_H_