blob: 3dc567d933bb8e19e7faa986902643373343df67 [file] [log] [blame]
sorin52ac0882015-01-24 01:15:001// Copyright 2014 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.
4
5#include "components/update_client/update_client.h"
6
sorin9797aba2015-04-17 17:15:037#include <algorithm>
8#include <queue>
9#include <set>
10#include <utility>
11#include <vector>
12
13#include "base/bind.h"
14#include "base/bind_helpers.h"
15#include "base/callback.h"
sorin9797aba2015-04-17 17:15:0316#include "base/location.h"
17#include "base/logging.h"
18#include "base/macros.h"
19#include "base/observer_list.h"
20#include "base/sequenced_task_runner.h"
21#include "base/single_thread_task_runner.h"
sorin9797aba2015-04-17 17:15:0322#include "base/threading/sequenced_worker_pool.h"
23#include "base/threading/thread_checker.h"
gab7966d312016-05-11 20:35:0124#include "base/threading/thread_task_runner_handle.h"
wafflesd2d9a332016-04-09 01:59:5725#include "components/prefs/pref_registry_simple.h"
sorin9797aba2015-04-17 17:15:0326#include "components/update_client/configurator.h"
sorin52ac0882015-01-24 01:15:0027#include "components/update_client/crx_update_item.h"
wafflesd2d9a332016-04-09 01:59:5728#include "components/update_client/persisted_data.h"
sorin9797aba2015-04-17 17:15:0329#include "components/update_client/ping_manager.h"
30#include "components/update_client/task_update.h"
31#include "components/update_client/update_checker.h"
sorin7b8650522016-11-02 18:23:4132#include "components/update_client/update_client_errors.h"
sorin9797aba2015-04-17 17:15:0333#include "components/update_client/update_client_internal.h"
34#include "components/update_client/update_engine.h"
35#include "components/update_client/update_response.h"
36#include "components/update_client/utils.h"
37#include "url/gurl.h"
sorin52ac0882015-01-24 01:15:0038
39namespace update_client {
40
41CrxUpdateItem::CrxUpdateItem()
sorin9797aba2015-04-17 17:15:0342 : state(State::kNew),
sorin52ac0882015-01-24 01:15:0043 on_demand(false),
44 diff_update_failed(false),
45 error_category(0),
46 error_code(0),
47 extra_code1(0),
48 diff_error_category(0),
49 diff_error_code(0),
50 diff_extra_code1(0) {
51}
52
vmpstrb6449d512016-02-25 23:55:4053CrxUpdateItem::CrxUpdateItem(const CrxUpdateItem& other) = default;
54
sorin52ac0882015-01-24 01:15:0055CrxUpdateItem::~CrxUpdateItem() {
56}
57
sorinfccbf2d2016-04-04 20:34:3458CrxComponent::CrxComponent()
sorincb4e5e92016-08-02 21:48:4059 : allows_background_download(true),
60 requires_network_encryption(true),
61 supports_group_policy_enable_component_updates(false) {}
sorin52ac0882015-01-24 01:15:0062
vmpstrb6449d512016-02-25 23:55:4063CrxComponent::CrxComponent(const CrxComponent& other) = default;
64
sorin52ac0882015-01-24 01:15:0065CrxComponent::~CrxComponent() {
66}
67
sorin7c717622015-05-26 19:59:0968// It is important that an instance of the UpdateClient binds an unretained
69// pointer to itself. Otherwise, a life time circular dependency between this
70// instance and its inner members prevents the destruction of this instance.
71// Using unretained references is allowed in this case since the life time of
72// the UpdateClient instance exceeds the life time of its inner members,
73// including any thread objects that might execute callbacks bound to it.
sorin9797aba2015-04-17 17:15:0374UpdateClientImpl::UpdateClientImpl(
75 const scoped_refptr<Configurator>& config,
dchengd0fc6aa92016-04-22 18:03:1276 std::unique_ptr<PingManager> ping_manager,
sorin9797aba2015-04-17 17:15:0377 UpdateChecker::Factory update_checker_factory,
78 CrxDownloader::Factory crx_downloader_factory)
sorinecaad3e2015-11-13 19:15:5279 : is_stopped_(false),
80 config_(config),
dcheng51ace48a2015-12-26 22:45:1781 ping_manager_(std::move(ping_manager)),
sorin9797aba2015-04-17 17:15:0382 update_engine_(
83 new UpdateEngine(config,
84 update_checker_factory,
85 crx_downloader_factory,
86 ping_manager_.get(),
87 base::Bind(&UpdateClientImpl::NotifyObservers,
sorinecaad3e2015-11-13 19:15:5288 base::Unretained(this)))) {}
sorin9797aba2015-04-17 17:15:0389
90UpdateClientImpl::~UpdateClientImpl() {
91 DCHECK(thread_checker_.CalledOnValidThread());
sorinb318cc84a2015-10-30 23:19:5192
sorinecaad3e2015-11-13 19:15:5293 DCHECK(task_queue_.empty());
94 DCHECK(tasks_.empty());
sorinb318cc84a2015-10-30 23:19:5195
sorin9797aba2015-04-17 17:15:0396 config_ = nullptr;
97}
98
99void UpdateClientImpl::Install(const std::string& id,
100 const CrxDataCallback& crx_data_callback,
sorin842703b2016-11-02 23:59:23101 const Callback& callback) {
sorin9797aba2015-04-17 17:15:03102 DCHECK(thread_checker_.CalledOnValidThread());
103
sorin08d153c2015-10-30 00:04:20104 if (IsUpdating(id)) {
sorin842703b2016-11-02 23:59:23105 callback.Run(Error::UPDATE_IN_PROGRESS);
sorin9797aba2015-04-17 17:15:03106 return;
107 }
108
109 std::vector<std::string> ids;
110 ids.push_back(id);
111
sorin842703b2016-11-02 23:59:23112 // Partially applies |callback| to OnTaskComplete, so this argument is
113 // available when the task completes, along with the task itself.
dchengd0fc6aa92016-04-22 18:03:12114 std::unique_ptr<TaskUpdate> task(new TaskUpdate(
sorin842703b2016-11-02 23:59:23115 update_engine_.get(), true, ids, crx_data_callback,
116 base::Bind(&UpdateClientImpl::OnTaskComplete, this, callback)));
sorin9797aba2015-04-17 17:15:03117
sorin08d153c2015-10-30 00:04:20118 // Install tasks are run concurrently and never queued up.
dcheng51ace48a2015-12-26 22:45:17119 RunTask(std::move(task));
sorin9797aba2015-04-17 17:15:03120}
121
122void UpdateClientImpl::Update(const std::vector<std::string>& ids,
123 const CrxDataCallback& crx_data_callback,
sorin842703b2016-11-02 23:59:23124 const Callback& callback) {
sorin9797aba2015-04-17 17:15:03125 DCHECK(thread_checker_.CalledOnValidThread());
126
dchengd0fc6aa92016-04-22 18:03:12127 std::unique_ptr<TaskUpdate> task(new TaskUpdate(
sorin842703b2016-11-02 23:59:23128 update_engine_.get(), false, ids, crx_data_callback,
129 base::Bind(&UpdateClientImpl::OnTaskComplete, this, callback)));
sorin7c717622015-05-26 19:59:09130
sorin08d153c2015-10-30 00:04:20131 // If no other tasks are running at the moment, run this update task.
132 // Otherwise, queue the task up.
sorin9797aba2015-04-17 17:15:03133 if (tasks_.empty()) {
dcheng51ace48a2015-12-26 22:45:17134 RunTask(std::move(task));
sorin9797aba2015-04-17 17:15:03135 } else {
136 task_queue_.push(task.release());
137 }
138}
139
dchengd0fc6aa92016-04-22 18:03:12140void UpdateClientImpl::RunTask(std::unique_ptr<Task> task) {
sorin9797aba2015-04-17 17:15:03141 DCHECK(thread_checker_.CalledOnValidThread());
142 base::ThreadTaskRunnerHandle::Get()->PostTask(
sorinb318cc84a2015-10-30 23:19:51143 FROM_HERE, base::Bind(&Task::Run, base::Unretained(task.get())));
144 tasks_.insert(task.release());
sorin9797aba2015-04-17 17:15:03145}
146
sorin842703b2016-11-02 23:59:23147void UpdateClientImpl::OnTaskComplete(const Callback& callback,
148 Task* task,
149 Error error) {
sorin9797aba2015-04-17 17:15:03150 DCHECK(thread_checker_.CalledOnValidThread());
151 DCHECK(task);
152
sorin842703b2016-11-02 23:59:23153 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
154 base::Bind(callback, error));
sorin9797aba2015-04-17 17:15:03155
sorinecaad3e2015-11-13 19:15:52156 // Remove the task from the set of the running tasks. Only tasks handled by
157 // the update engine can be in this data structure.
sorin9797aba2015-04-17 17:15:03158 tasks_.erase(task);
sorinecaad3e2015-11-13 19:15:52159
160 // Delete the completed task. A task can be completed because the update
161 // engine has run it or because it has been canceled but never run.
sorin9797aba2015-04-17 17:15:03162 delete task;
163
sorinecaad3e2015-11-13 19:15:52164 if (is_stopped_)
165 return;
166
sorin08d153c2015-10-30 00:04:20167 // Pick up a task from the queue if the queue has pending tasks and no other
168 // task is running.
169 if (tasks_.empty() && !task_queue_.empty()) {
dchengd0fc6aa92016-04-22 18:03:12170 RunTask(std::unique_ptr<Task>(task_queue_.front()));
sorin9797aba2015-04-17 17:15:03171 task_queue_.pop();
172 }
173}
174
175void UpdateClientImpl::AddObserver(Observer* observer) {
176 DCHECK(thread_checker_.CalledOnValidThread());
177 observer_list_.AddObserver(observer);
178}
179
180void UpdateClientImpl::RemoveObserver(Observer* observer) {
181 DCHECK(thread_checker_.CalledOnValidThread());
182 observer_list_.RemoveObserver(observer);
183}
184
185void UpdateClientImpl::NotifyObservers(Observer::Events event,
186 const std::string& id) {
187 DCHECK(thread_checker_.CalledOnValidThread());
ericwilligersff2af332016-10-19 00:16:50188 for (auto& observer : observer_list_)
189 observer.OnEvent(event, id);
sorin9797aba2015-04-17 17:15:03190}
191
192bool UpdateClientImpl::GetCrxUpdateState(const std::string& id,
193 CrxUpdateItem* update_item) const {
194 return update_engine_->GetUpdateState(id, update_item);
195}
196
197bool UpdateClientImpl::IsUpdating(const std::string& id) const {
sorin08d153c2015-10-30 00:04:20198 DCHECK(thread_checker_.CalledOnValidThread());
199
vmpstr2de366b2016-07-20 21:35:48200 for (const auto* task : tasks_) {
sorin08d153c2015-10-30 00:04:20201 const auto ids(task->GetIds());
sorinbc7df002015-11-05 00:50:47202 if (std::find(ids.begin(), ids.end(), id) != ids.end()) {
sorin08d153c2015-10-30 00:04:20203 return true;
204 }
205 }
206
207 return false;
sorin9797aba2015-04-17 17:15:03208}
209
sorinecaad3e2015-11-13 19:15:52210void UpdateClientImpl::Stop() {
211 DCHECK(thread_checker_.CalledOnValidThread());
212
213 is_stopped_ = true;
214
215 // In the current implementation it is sufficient to cancel the pending
216 // tasks only. The tasks that are run by the update engine will stop
217 // making progress naturally, as the main task runner stops running task
218 // actions. Upon the browser shutdown, the resources employed by the active
219 // tasks will leak, as the operating system kills the thread associated with
220 // the update engine task runner. Further refactoring may be needed in this
221 // area, to cancel the running tasks by canceling the current action update.
222 // This behavior would be expected, correct, and result in no resource leaks
223 // in all cases, in shutdown or not.
224 //
225 // Cancel the pending tasks. These tasks are safe to cancel and delete since
226 // they have not picked up by the update engine, and not shared with any
227 // task runner yet.
228 while (!task_queue_.empty()) {
vmpstr2de366b2016-07-20 21:35:48229 auto* task(task_queue_.front());
sorinecaad3e2015-11-13 19:15:52230 task_queue_.pop();
231 task->Cancel();
232 }
233}
234
sorin805aa03112016-01-14 23:01:31235void UpdateClientImpl::SendUninstallPing(const std::string& id,
pwnalldb0b72412016-08-19 21:39:12236 const base::Version& version,
sorin805aa03112016-01-14 23:01:31237 int reason) {
238 DCHECK(thread_checker_.CalledOnValidThread());
239
240 // The implementation of PingManager::SendPing contains a self-deleting
241 // object responsible for sending the ping.
242 CrxUpdateItem item;
243 item.state = CrxUpdateItem::State::kUninstalled;
244 item.id = id;
245 item.previous_version = version;
246 item.next_version = base::Version("0");
247 item.extra_code1 = reason;
248
249 ping_manager_->SendPing(&item);
250}
251
sorin7c717622015-05-26 19:59:09252scoped_refptr<UpdateClient> UpdateClientFactory(
sorin9797aba2015-04-17 17:15:03253 const scoped_refptr<Configurator>& config) {
dchengd0fc6aa92016-04-22 18:03:12254 std::unique_ptr<PingManager> ping_manager(new PingManager(config));
dcheng51ace48a2015-12-26 22:45:17255 return new UpdateClientImpl(config, std::move(ping_manager),
sorin7c717622015-05-26 19:59:09256 &UpdateChecker::Create, &CrxDownloader::Create);
sorin9797aba2015-04-17 17:15:03257}
258
wafflesd2d9a332016-04-09 01:59:57259void RegisterPrefs(PrefRegistrySimple* registry) {
260 PersistedData::RegisterPrefs(registry);
261}
262
sorin52ac0882015-01-24 01:15:00263} // namespace update_client