OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_client.h" | 5 #include "components/update_client/update_client.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <queue> | 8 #include <queue> |
9 #include <set> | 9 #include <set> |
10 #include <utility> | 10 #include <utility> |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 UpdateClientImpl::~UpdateClientImpl() { | 82 UpdateClientImpl::~UpdateClientImpl() { |
83 DCHECK(thread_checker_.CalledOnValidThread()); | 83 DCHECK(thread_checker_.CalledOnValidThread()); |
84 config_ = nullptr; | 84 config_ = nullptr; |
85 } | 85 } |
86 | 86 |
87 void UpdateClientImpl::Install(const std::string& id, | 87 void UpdateClientImpl::Install(const std::string& id, |
88 const CrxDataCallback& crx_data_callback, | 88 const CrxDataCallback& crx_data_callback, |
89 const CompletionCallback& completion_callback) { | 89 const CompletionCallback& completion_callback) { |
90 DCHECK(thread_checker_.CalledOnValidThread()); | 90 DCHECK(thread_checker_.CalledOnValidThread()); |
91 | 91 |
92 if (update_engine_->IsUpdating(id)) { | 92 if (IsUpdating(id)) { |
93 completion_callback.Run(Error::ERROR_UPDATE_IN_PROGRESS); | 93 completion_callback.Run(Error::ERROR_UPDATE_IN_PROGRESS); |
94 return; | 94 return; |
95 } | 95 } |
96 | 96 |
97 std::vector<std::string> ids; | 97 std::vector<std::string> ids; |
98 ids.push_back(id); | 98 ids.push_back(id); |
99 | 99 |
100 // Partially applies |completion_callback| to OnTaskComplete, so this | 100 // Partially applies |completion_callback| to OnTaskComplete, so this |
101 // argument is available when the task completes, along with the task itself. | 101 // argument is available when the task completes, along with the task itself. |
102 const auto callback = | 102 const auto callback = |
103 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback); | 103 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback); |
104 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), true, ids, | 104 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), true, ids, |
105 crx_data_callback, callback)); | 105 crx_data_callback, callback)); |
106 | 106 |
| 107 // Install tasks are run concurrently and never queued up. |
107 auto it = tasks_.insert(task.release()).first; | 108 auto it = tasks_.insert(task.release()).first; |
108 RunTask(*it); | 109 RunTask(*it); |
109 } | 110 } |
110 | 111 |
111 void UpdateClientImpl::Update(const std::vector<std::string>& ids, | 112 void UpdateClientImpl::Update(const std::vector<std::string>& ids, |
112 const CrxDataCallback& crx_data_callback, | 113 const CrxDataCallback& crx_data_callback, |
113 const CompletionCallback& completion_callback) { | 114 const CompletionCallback& completion_callback) { |
114 DCHECK(thread_checker_.CalledOnValidThread()); | 115 DCHECK(thread_checker_.CalledOnValidThread()); |
115 | 116 |
116 const auto callback = | 117 const auto callback = |
117 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback); | 118 base::Bind(&UpdateClientImpl::OnTaskComplete, this, completion_callback); |
118 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), false, ids, | 119 scoped_ptr<TaskUpdate> task(new TaskUpdate(update_engine_.get(), false, ids, |
119 crx_data_callback, callback)); | 120 crx_data_callback, callback)); |
120 | 121 |
| 122 // If no other tasks are running at the moment, run this update task. |
| 123 // Otherwise, queue the task up. |
121 if (tasks_.empty()) { | 124 if (tasks_.empty()) { |
122 auto it = tasks_.insert(task.release()).first; | 125 auto it = tasks_.insert(task.release()).first; |
123 RunTask(*it); | 126 RunTask(*it); |
124 } else { | 127 } else { |
125 task_queue_.push(task.release()); | 128 task_queue_.push(task.release()); |
126 } | 129 } |
127 } | 130 } |
128 | 131 |
129 void UpdateClientImpl::RunTask(Task* task) { | 132 void UpdateClientImpl::RunTask(Task* task) { |
130 DCHECK(thread_checker_.CalledOnValidThread()); | 133 DCHECK(thread_checker_.CalledOnValidThread()); |
131 base::ThreadTaskRunnerHandle::Get()->PostTask( | 134 base::ThreadTaskRunnerHandle::Get()->PostTask( |
132 FROM_HERE, base::Bind(&Task::Run, base::Unretained(task))); | 135 FROM_HERE, base::Bind(&Task::Run, base::Unretained(task))); |
133 } | 136 } |
134 | 137 |
135 void UpdateClientImpl::OnTaskComplete( | 138 void UpdateClientImpl::OnTaskComplete( |
136 const CompletionCallback& completion_callback, | 139 const CompletionCallback& completion_callback, |
137 Task* task, | 140 Task* task, |
138 int error) { | 141 int error) { |
139 DCHECK(thread_checker_.CalledOnValidThread()); | 142 DCHECK(thread_checker_.CalledOnValidThread()); |
140 DCHECK(task); | 143 DCHECK(task); |
141 | 144 |
142 base::ThreadTaskRunnerHandle::Get()->PostTask( | 145 base::ThreadTaskRunnerHandle::Get()->PostTask( |
143 FROM_HERE, base::Bind(completion_callback, error)); | 146 FROM_HERE, base::Bind(completion_callback, error)); |
144 | 147 |
145 tasks_.erase(task); | 148 tasks_.erase(task); |
146 delete task; | 149 delete task; |
147 | 150 |
148 if (!task_queue_.empty()) { | 151 // Pick up a task from the queue if the queue has pending tasks and no other |
| 152 // task is running. |
| 153 if (tasks_.empty() && !task_queue_.empty()) { |
149 RunTask(task_queue_.front()); | 154 RunTask(task_queue_.front()); |
150 task_queue_.pop(); | 155 task_queue_.pop(); |
151 } | 156 } |
152 } | 157 } |
153 | 158 |
154 void UpdateClientImpl::AddObserver(Observer* observer) { | 159 void UpdateClientImpl::AddObserver(Observer* observer) { |
155 DCHECK(thread_checker_.CalledOnValidThread()); | 160 DCHECK(thread_checker_.CalledOnValidThread()); |
156 observer_list_.AddObserver(observer); | 161 observer_list_.AddObserver(observer); |
157 } | 162 } |
158 | 163 |
159 void UpdateClientImpl::RemoveObserver(Observer* observer) { | 164 void UpdateClientImpl::RemoveObserver(Observer* observer) { |
160 DCHECK(thread_checker_.CalledOnValidThread()); | 165 DCHECK(thread_checker_.CalledOnValidThread()); |
161 observer_list_.RemoveObserver(observer); | 166 observer_list_.RemoveObserver(observer); |
162 } | 167 } |
163 | 168 |
164 void UpdateClientImpl::NotifyObservers(Observer::Events event, | 169 void UpdateClientImpl::NotifyObservers(Observer::Events event, |
165 const std::string& id) { | 170 const std::string& id) { |
166 DCHECK(thread_checker_.CalledOnValidThread()); | 171 DCHECK(thread_checker_.CalledOnValidThread()); |
167 FOR_EACH_OBSERVER(Observer, observer_list_, OnEvent(event, id)); | 172 FOR_EACH_OBSERVER(Observer, observer_list_, OnEvent(event, id)); |
168 } | 173 } |
169 | 174 |
170 bool UpdateClientImpl::GetCrxUpdateState(const std::string& id, | 175 bool UpdateClientImpl::GetCrxUpdateState(const std::string& id, |
171 CrxUpdateItem* update_item) const { | 176 CrxUpdateItem* update_item) const { |
172 return update_engine_->GetUpdateState(id, update_item); | 177 return update_engine_->GetUpdateState(id, update_item); |
173 } | 178 } |
174 | 179 |
175 bool UpdateClientImpl::IsUpdating(const std::string& id) const { | 180 bool UpdateClientImpl::IsUpdating(const std::string& id) const { |
176 return update_engine_->IsUpdating(id); | 181 DCHECK(thread_checker_.CalledOnValidThread()); |
| 182 |
| 183 for (const auto& task : tasks_) { |
| 184 const auto ids(task->GetIds()); |
| 185 if (std::find(std::begin(ids), std::end(ids), id) != std::end(ids)) { |
| 186 return true; |
| 187 } |
| 188 } |
| 189 |
| 190 return false; |
177 } | 191 } |
178 | 192 |
179 scoped_refptr<UpdateClient> UpdateClientFactory( | 193 scoped_refptr<UpdateClient> UpdateClientFactory( |
180 const scoped_refptr<Configurator>& config) { | 194 const scoped_refptr<Configurator>& config) { |
181 scoped_ptr<PingManager> ping_manager(new PingManager(*config)); | 195 scoped_ptr<PingManager> ping_manager(new PingManager(*config)); |
182 return new UpdateClientImpl(config, ping_manager.Pass(), | 196 return new UpdateClientImpl(config, ping_manager.Pass(), |
183 &UpdateChecker::Create, &CrxDownloader::Create); | 197 &UpdateChecker::Create, &CrxDownloader::Create); |
184 } | 198 } |
185 | 199 |
186 } // namespace update_client | 200 } // namespace update_client |
OLD | NEW |