Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(809)

Side by Side Diff: components/update_client/update_engine.cc

Issue 2835803002: Refactor the UpdateEngine and its actions in the component updater. (Closed)
Patch Set: feedback up to #6 Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « components/update_client/update_engine.h ('k') | components/update_client/utils.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/update_client/update_engine.h" 5 #include "components/update_client/update_engine.h"
6 6
7 #include <utility>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
9 #include "base/location.h" 11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
10 #include "base/stl_util.h" 14 #include "base/stl_util.h"
11 #include "base/threading/thread_task_runner_handle.h" 15 #include "base/threading/thread_task_runner_handle.h"
12 #include "base/time/time.h"
13 #include "components/prefs/pref_service.h" 16 #include "components/prefs/pref_service.h"
14 #include "components/update_client/action_update_check.h" 17 #include "components/update_client/component.h"
15 #include "components/update_client/configurator.h" 18 #include "components/update_client/configurator.h"
16 #include "components/update_client/crx_update_item.h" 19 #include "components/update_client/crx_update_item.h"
17 #include "components/update_client/persisted_data.h" 20 #include "components/update_client/persisted_data.h"
18 #include "components/update_client/update_checker.h" 21 #include "components/update_client/update_checker.h"
19 #include "components/update_client/update_client_errors.h" 22 #include "components/update_client/update_client_errors.h"
23 #include "components/update_client/utils.h"
20 24
21 namespace update_client { 25 namespace update_client {
22 26
23 UpdateContext::UpdateContext( 27 UpdateContext::UpdateContext(
24 const scoped_refptr<Configurator>& config, 28 const scoped_refptr<Configurator>& config,
25 bool is_foreground, 29 bool is_foreground,
26 const std::vector<std::string>& ids, 30 const std::vector<std::string>& ids,
27 const UpdateClient::CrxDataCallback& crx_data_callback, 31 const UpdateClient::CrxDataCallback& crx_data_callback,
28 const UpdateEngine::NotifyObserversCallback& notify_observers_callback, 32 const UpdateEngine::NotifyObserversCallback& notify_observers_callback,
29 const UpdateEngine::Callback& callback, 33 const UpdateEngine::Callback& callback,
30 UpdateChecker::Factory update_checker_factory, 34 CrxDownloader::Factory crx_downloader_factory)
31 CrxDownloader::Factory crx_downloader_factory,
32 PingManager* ping_manager)
33 : config(config), 35 : config(config),
34 is_foreground(is_foreground), 36 is_foreground(is_foreground),
35 enabled_component_updates(config->EnabledComponentUpdates()), 37 enabled_component_updates(config->EnabledComponentUpdates()),
36 ids(ids), 38 ids(ids),
37 crx_data_callback(crx_data_callback), 39 crx_data_callback(crx_data_callback),
38 notify_observers_callback(notify_observers_callback), 40 notify_observers_callback(notify_observers_callback),
39 callback(callback), 41 callback(callback),
40 main_task_runner(base::ThreadTaskRunnerHandle::Get()),
41 blocking_task_runner(config->GetSequencedTaskRunner()), 42 blocking_task_runner(config->GetSequencedTaskRunner()),
42 update_checker_factory(update_checker_factory), 43 crx_downloader_factory(crx_downloader_factory) {
43 crx_downloader_factory(crx_downloader_factory), 44 for (const auto& id : ids)
44 ping_manager(ping_manager), 45 components.insert(
45 retry_after_sec(0) {} 46 std::make_pair(id, base::MakeUnique<Component>(*this, id)));
47 }
46 48
47 UpdateContext::~UpdateContext() {} 49 UpdateContext::~UpdateContext() {}
48 50
49 UpdateEngine::UpdateEngine( 51 UpdateEngine::UpdateEngine(
50 const scoped_refptr<Configurator>& config, 52 const scoped_refptr<Configurator>& config,
51 UpdateChecker::Factory update_checker_factory, 53 UpdateChecker::Factory update_checker_factory,
52 CrxDownloader::Factory crx_downloader_factory, 54 CrxDownloader::Factory crx_downloader_factory,
53 PingManager* ping_manager, 55 PingManager* ping_manager,
54 const NotifyObserversCallback& notify_observers_callback) 56 const NotifyObserversCallback& notify_observers_callback)
55 : config_(config), 57 : config_(config),
56 update_checker_factory_(update_checker_factory), 58 update_checker_factory_(update_checker_factory),
57 crx_downloader_factory_(crx_downloader_factory), 59 crx_downloader_factory_(crx_downloader_factory),
58 ping_manager_(ping_manager), 60 ping_manager_(ping_manager),
59 metadata_(new PersistedData(config->GetPrefService())), 61 metadata_(new PersistedData(config->GetPrefService())),
60 notify_observers_callback_(notify_observers_callback) {} 62 notify_observers_callback_(notify_observers_callback) {}
61 63
62 UpdateEngine::~UpdateEngine() { 64 UpdateEngine::~UpdateEngine() {
63 DCHECK(thread_checker_.CalledOnValidThread()); 65 DCHECK(thread_checker_.CalledOnValidThread());
64 } 66 }
65 67
66 bool UpdateEngine::GetUpdateState(const std::string& id,
67 CrxUpdateItem* update_item) {
68 DCHECK(thread_checker_.CalledOnValidThread());
69 for (const auto* context : update_contexts_) {
70 const auto& update_items = context->update_items;
71 const auto it = update_items.find(id);
72 if (it != update_items.end()) {
73 *update_item = *it->second.get();
74 return true;
75 }
76 }
77 return false;
78 }
79
80 void UpdateEngine::Update( 68 void UpdateEngine::Update(
81 bool is_foreground, 69 bool is_foreground,
82 const std::vector<std::string>& ids, 70 const std::vector<std::string>& ids,
83 const UpdateClient::CrxDataCallback& crx_data_callback, 71 const UpdateClient::CrxDataCallback& crx_data_callback,
84 const Callback& callback) { 72 const Callback& callback) {
85 DCHECK(thread_checker_.CalledOnValidThread()); 73 DCHECK(thread_checker_.CalledOnValidThread());
86 74
87 if (IsThrottled(is_foreground)) { 75 if (IsThrottled(is_foreground)) {
88 base::ThreadTaskRunnerHandle::Get()->PostTask( 76 base::ThreadTaskRunnerHandle::Get()->PostTask(
89 FROM_HERE, base::Bind(callback, Error::RETRY_LATER)); 77 FROM_HERE, base::Bind(callback, Error::RETRY_LATER));
90 return; 78 return;
91 } 79 }
92 80
93 std::unique_ptr<UpdateContext> update_context(new UpdateContext( 81 const auto result = update_contexts_.insert(base::MakeUnique<UpdateContext>(
94 config_, is_foreground, ids, crx_data_callback, 82 config_, is_foreground, ids, crx_data_callback,
95 notify_observers_callback_, callback, update_checker_factory_, 83 notify_observers_callback_, callback, crx_downloader_factory_));
96 crx_downloader_factory_, ping_manager_));
97 84
98 std::unique_ptr<ActionUpdateCheck> update_check_action(new ActionUpdateCheck( 85 DCHECK(result.second);
99 (*update_context->update_checker_factory)(config_, metadata_.get()),
100 config_->GetBrowserVersion(), config_->ExtraRequestParams()));
101 86
102 update_context->current_action = std::move(update_check_action); 87 const auto& it = result.first;
103 update_contexts_.insert(update_context.get()); 88 const auto& update_context = *it;
89 DCHECK(update_context);
104 90
105 update_context->current_action->Run( 91 // Calls out to get the corresponding CrxComponent data for the CRXs in this
106 update_context.get(), 92 // update context.
107 base::Bind(&UpdateEngine::UpdateComplete, base::Unretained(this), 93 DCHECK_EQ(ids.size(), update_context->ids.size());
108 update_context.get())); 94 DCHECK_EQ(update_context->ids.size(), update_context->components.size());
95 std::vector<CrxComponent> crx_components;
96 update_context->crx_data_callback.Run(update_context->ids, &crx_components);
97 DCHECK_EQ(update_context->ids.size(), crx_components.size());
109 98
110 ignore_result(update_context.release()); 99 for (size_t i = 0; i != update_context->ids.size(); ++i) {
100 const auto& id = update_context->ids[i];
101 const auto& crx_component = crx_components[i];
102
103 DCHECK_EQ(id, GetCrxComponentID(crx_component));
104 DCHECK_EQ(1u, update_context->components.count(id));
105 DCHECK(update_context->components.at(id));
106
107 auto& component = *update_context->components.at(id);
108 component.set_on_demand(update_context->is_foreground);
109 component.set_crx_component(crx_component);
110 component.set_previous_version(crx_component.version);
111 component.set_previous_fp(crx_component.fingerprint);
112
113 // Handle |kNew| state. This will transition the components to |kChecking|.
114 component.Handle(base::Bind(&UpdateEngine::ComponentCheckingForUpdatesStart,
115 base::Unretained(this), it,
116 base::ConstRef(component)));
117 }
111 } 118 }
112 119
113 void UpdateEngine::UpdateComplete(UpdateContext* update_context, Error error) { 120 void UpdateEngine::ComponentCheckingForUpdatesStart(
121 const UpdateContextIterator& it,
122 const Component& component) {
114 DCHECK(thread_checker_.CalledOnValidThread()); 123 DCHECK(thread_checker_.CalledOnValidThread());
115 DCHECK(update_contexts_.find(update_context) != update_contexts_.end()); 124
125 const auto& update_context = *it;
126 DCHECK(update_context);
127
128 const auto id = component.id();
129 DCHECK_EQ(1u, update_context->components.count(id));
130 DCHECK(update_context->components.at(id));
131
132 // Handle |kChecking| state.
133 auto& mutable_component = *update_context->components.at(id);
134 mutable_component.Handle(base::Bind(
135 &UpdateEngine::ComponentCheckingForUpdatesComplete,
136 base::Unretained(this), it, base::ConstRef(mutable_component)));
137
138 ++update_context->num_components_ready_to_check;
139 if (update_context->num_components_ready_to_check <
140 update_context->ids.size()) {
141 return;
142 }
143
144 base::ThreadTaskRunnerHandle::Get()->PostTask(
145 FROM_HERE,
146 base::Bind(&UpdateEngine::DoUpdateCheck, base::Unretained(this), it));
147 }
148
149 void UpdateEngine::DoUpdateCheck(const UpdateContextIterator& it) {
150 DCHECK(thread_checker_.CalledOnValidThread());
151
152 auto& update_context = *it;
153 DCHECK(update_context);
154
155 update_context->update_checker =
156 update_checker_factory_(config_, metadata_.get());
157
158 update_context->update_checker->CheckForUpdates(
159 update_context->ids, update_context->components,
160 config_->ExtraRequestParams(), update_context->enabled_component_updates,
161 base::Bind(&UpdateEngine::UpdateCheckDone, base::Unretained(this), it));
162 }
163
164 void UpdateEngine::UpdateCheckDone(const UpdateContextIterator& it,
165 int error,
166 int retry_after_sec) {
167 DCHECK(thread_checker_.CalledOnValidThread());
168
169 auto& update_context = *it;
170 DCHECK(update_context);
171
172 update_context->retry_after_sec = retry_after_sec;
116 173
117 const int throttle_sec(update_context->retry_after_sec); 174 const int throttle_sec(update_context->retry_after_sec);
118 DCHECK_LE(throttle_sec, 24 * 60 * 60); 175 DCHECK_LE(throttle_sec, 24 * 60 * 60);
119 176
120 // Only positive values for throttle_sec are effective. 0 means that no 177 // Only positive values for throttle_sec are effective. 0 means that no
121 // throttling occurs and has the effect of resetting the member. 178 // throttling occurs and has the effect of resetting the member.
122 // Negative values are not trusted and are ignored. 179 // Negative values are not trusted and are ignored.
123 if (throttle_sec >= 0) 180 if (throttle_sec >= 0) {
124 throttle_updates_until_ = 181 throttle_updates_until_ =
125 throttle_sec 182 throttle_sec ? base::TimeTicks::Now() +
126 ? base::TimeTicks::Now() + 183 base::TimeDelta::FromSeconds(throttle_sec)
127 base::TimeDelta::FromSeconds(throttle_sec) 184 : base::TimeTicks();
128 : base::TimeTicks(); 185 }
129 186
130 auto callback = update_context->callback; 187 update_context->update_check_error = error;
131 188
132 update_contexts_.erase(update_context); 189 for (const auto& id : update_context->ids) {
133 delete update_context; 190 DCHECK_EQ(1u, update_context->components.count(id));
191 DCHECK(update_context->components.at(id));
134 192
135 callback.Run(error); 193 auto& component = *update_context->components.at(id);
194 component.UpdateCheckComplete();
195 }
196 }
197
198 void UpdateEngine::ComponentCheckingForUpdatesComplete(
199 const UpdateContextIterator& it,
200 const Component& component) {
201 DCHECK(thread_checker_.CalledOnValidThread());
202
203 const auto& update_context = *it;
204 DCHECK(update_context);
205
206 ++update_context->num_components_checked;
207 if (update_context->num_components_checked < update_context->ids.size()) {
208 return;
209 }
210
211 base::ThreadTaskRunnerHandle::Get()->PostTask(
212 FROM_HERE, base::Bind(&UpdateEngine::UpdateCheckComplete,
213 base::Unretained(this), it));
214 }
215
216 void UpdateEngine::UpdateCheckComplete(const UpdateContextIterator& it) {
217 DCHECK(thread_checker_.CalledOnValidThread());
218
219 const auto& update_context = *it;
220 DCHECK(update_context);
221
222 if (update_context->update_check_error) {
223 base::ThreadTaskRunnerHandle::Get()->PostTask(
224 FROM_HERE,
225 base::Bind(&UpdateEngine::UpdateComplete, base::Unretained(this), it,
226 Error::UPDATE_CHECK_ERROR));
227 return;
228 }
229
230 for (const auto& id : update_context->ids)
231 update_context->component_queue.push(id);
232
233 base::ThreadTaskRunnerHandle::Get()->PostTask(
234 FROM_HERE,
235 base::Bind(&UpdateEngine::HandleComponent, base::Unretained(this), it));
236 }
237
238 void UpdateEngine::HandleComponent(const UpdateContextIterator& it) {
239 DCHECK(thread_checker_.CalledOnValidThread());
240
241 auto& update_context = *it;
242 DCHECK(update_context);
243
244 auto& queue = update_context->component_queue;
245
246 if (queue.empty()) {
247 base::ThreadTaskRunnerHandle::Get()->PostTask(
248 FROM_HERE, base::Bind(&UpdateEngine::UpdateComplete,
249 base::Unretained(this), it, Error::NONE));
250 return;
251 }
252
253 const auto& id = queue.front();
254 DCHECK_EQ(1u, update_context->components.count(id));
255 const auto& component = update_context->components.at(id);
256 DCHECK(component);
257
258 auto& next_update_delay = (*it)->next_update_delay;
259 if (!next_update_delay.is_zero() && component->IsUpdateAvailable()) {
260 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
261 FROM_HERE,
262 base::Bind(&UpdateEngine::HandleComponent, base::Unretained(this), it),
263 next_update_delay);
264
265 next_update_delay = base::TimeDelta();
266
267 notify_observers_callback_.Run(
268 UpdateClient::Observer::Events::COMPONENT_WAIT, id);
269 return;
270 }
271
272 component->Handle(base::Bind(&UpdateEngine::HandleComponentComplete,
273 base::Unretained(this), it));
274 }
275
276 void UpdateEngine::HandleComponentComplete(const UpdateContextIterator& it) {
277 DCHECK(thread_checker_.CalledOnValidThread());
278
279 auto& update_context = *it;
280 DCHECK(update_context);
281
282 auto& queue = update_context->component_queue;
283 DCHECK(!queue.empty());
284
285 const auto& id = queue.front();
286 DCHECK_EQ(1u, update_context->components.count(id));
287 const auto& component = update_context->components.at(id);
288 DCHECK(component);
289
290 if (component->IsHandled()) {
291 (*it)->next_update_delay = component->GetUpdateDuration();
292
293 // Only ping when the server response included an update for this component.
294 if (component->CanPing()) {
295 ping_manager_->SendPing(*component);
296 }
297
298 queue.pop();
299 }
300
301 base::ThreadTaskRunnerHandle::Get()->PostTask(
302 FROM_HERE,
303 base::Bind(&UpdateEngine::HandleComponent, base::Unretained(this), it));
304 }
305
306 void UpdateEngine::UpdateComplete(const UpdateContextIterator& it,
307 Error error) {
308 DCHECK(thread_checker_.CalledOnValidThread());
309
310 auto& update_context = *it;
311 DCHECK(update_context);
312
313 base::ThreadTaskRunnerHandle::Get()->PostTask(
314 FROM_HERE, base::Bind(update_context->callback, error));
315
316 update_contexts_.erase(it);
317 }
318
319 bool UpdateEngine::GetUpdateState(const std::string& id,
320 CrxUpdateItem* update_item) {
321 DCHECK(thread_checker_.CalledOnValidThread());
322 for (const auto& context : update_contexts_) {
323 const auto it = context->components.find(id);
324 if (it != context->components.end()) {
325 *update_item = it->second->GetCrxUpdateItem();
326 return true;
327 }
328 }
329 return false;
136 } 330 }
137 331
138 bool UpdateEngine::IsThrottled(bool is_foreground) const { 332 bool UpdateEngine::IsThrottled(bool is_foreground) const {
333 DCHECK(thread_checker_.CalledOnValidThread());
334
139 if (is_foreground || throttle_updates_until_.is_null()) 335 if (is_foreground || throttle_updates_until_.is_null())
140 return false; 336 return false;
141 337
142 const auto now(base::TimeTicks::Now()); 338 const auto now(base::TimeTicks::Now());
143 339
144 // Throttle the calls in the interval (t - 1 day, t) to limit the effect of 340 // Throttle the calls in the interval (t - 1 day, t) to limit the effect of
145 // unset clocks or clock drift. 341 // unset clocks or clock drift.
146 return throttle_updates_until_ - base::TimeDelta::FromDays(1) < now && 342 return throttle_updates_until_ - base::TimeDelta::FromDays(1) < now &&
147 now < throttle_updates_until_; 343 now < throttle_updates_until_;
148 } 344 }
149 345
346 void UpdateEngine::SendUninstallPing(const std::string& id,
347 const base::Version& version,
348 int reason,
349 const Callback& callback) {
350 DCHECK(thread_checker_.CalledOnValidThread());
351
352 const auto result = update_contexts_.insert(base::MakeUnique<UpdateContext>(
353 config_, false, std::vector<std::string>{id},
354 UpdateClient::CrxDataCallback(), UpdateEngine::NotifyObserversCallback(),
355 callback, nullptr));
356
357 DCHECK(result.second);
358
359 const auto& it = result.first;
360 const auto& update_context = *it;
361 DCHECK(update_context);
362 DCHECK_EQ(1u, update_context->ids.size());
363 DCHECK_EQ(1u, update_context->components.count(id));
364 const auto& component = update_context->components.at(id);
365
366 component->Uninstall(version, reason);
367
368 update_context->component_queue.push(id);
369
370 base::ThreadTaskRunnerHandle::Get()->PostTask(
371 FROM_HERE,
372 base::Bind(&UpdateEngine::HandleComponent, base::Unretained(this), it));
373 }
374
150 } // namespace update_client 375 } // namespace update_client
OLDNEW
« no previous file with comments | « components/update_client/update_engine.h ('k') | components/update_client/utils.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698