Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / dbus / update_engine_client.cc
blobffc7acfbe27efb8cd61db53e1a8480415c5a445c
1 // Copyright (c) 2012 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.
5 #include "chromeos/dbus/update_engine_client.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/string_util.h"
10 #include "dbus/bus.h"
11 #include "dbus/message.h"
12 #include "dbus/object_path.h"
13 #include "dbus/object_proxy.h"
14 #include "third_party/cros_system_api/dbus/service_constants.h"
16 namespace chromeos {
17 namespace {
19 // Returns UPDATE_STATUS_ERROR on error.
20 UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString(
21 const std::string& str) {
22 if (str == "UPDATE_STATUS_IDLE")
23 return UpdateEngineClient::UPDATE_STATUS_IDLE;
24 if (str == "UPDATE_STATUS_CHECKING_FOR_UPDATE")
25 return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
26 if (str == "UPDATE_STATUS_UPDATE_AVAILABLE")
27 return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
28 if (str == "UPDATE_STATUS_DOWNLOADING")
29 return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
30 if (str == "UPDATE_STATUS_VERIFYING")
31 return UpdateEngineClient::UPDATE_STATUS_VERIFYING;
32 if (str == "UPDATE_STATUS_FINALIZING")
33 return UpdateEngineClient::UPDATE_STATUS_FINALIZING;
34 if (str == "UPDATE_STATUS_UPDATED_NEED_REBOOT")
35 return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
36 if (str == "UPDATE_STATUS_REPORTING_ERROR_EVENT")
37 return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
38 return UpdateEngineClient::UPDATE_STATUS_ERROR;
41 // Used in UpdateEngineClient::EmptyUpdateCheckCallback().
42 void EmptyUpdateCheckCallbackBody(
43 UpdateEngineClient::UpdateCheckResult unused_result) {
46 } // namespace
48 // The UpdateEngineClient implementation used in production.
49 class UpdateEngineClientImpl : public UpdateEngineClient {
50 public:
51 explicit UpdateEngineClientImpl(dbus::Bus* bus)
52 : update_engine_proxy_(NULL),
53 last_status_(),
54 weak_ptr_factory_(this) {
55 update_engine_proxy_ = bus->GetObjectProxy(
56 update_engine::kUpdateEngineServiceName,
57 dbus::ObjectPath(update_engine::kUpdateEngineServicePath));
59 // Monitor the D-Bus signal for brightness changes. Only the power
60 // manager knows the actual brightness level. We don't cache the
61 // brightness level in Chrome as it will make things less reliable.
62 update_engine_proxy_->ConnectToSignal(
63 update_engine::kUpdateEngineInterface,
64 update_engine::kStatusUpdate,
65 base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived,
66 weak_ptr_factory_.GetWeakPtr()),
67 base::Bind(&UpdateEngineClientImpl::StatusUpdateConnected,
68 weak_ptr_factory_.GetWeakPtr()));
70 // Get update engine status for the initial status. Update engine won't
71 // send StatusUpdate signal unless there is a status change. If chrome
72 // crashes after UPDATE_STATUS_UPDATED_NEED_REBOOT status is set,
73 // restarted chrome would not get this status. See crbug.com/154104.
74 GetUpdateEngineStatus();
77 virtual ~UpdateEngineClientImpl() {
80 // UpdateEngineClient override.
81 virtual void AddObserver(Observer* observer) OVERRIDE {
82 observers_.AddObserver(observer);
85 // UpdateEngineClient override.
86 virtual void RemoveObserver(Observer* observer) OVERRIDE {
87 observers_.RemoveObserver(observer);
90 // UpdateEngineClient override.
91 virtual bool HasObserver(Observer* observer) OVERRIDE {
92 return observers_.HasObserver(observer);
95 // UpdateEngineClient override.
96 virtual void RequestUpdateCheck(
97 const UpdateCheckCallback& callback) OVERRIDE {
98 dbus::MethodCall method_call(
99 update_engine::kUpdateEngineInterface,
100 update_engine::kAttemptUpdate);
101 dbus::MessageWriter writer(&method_call);
102 writer.AppendString(""); // Unused.
103 writer.AppendString(""); // Unused.
105 VLOG(1) << "Requesting an update check";
106 update_engine_proxy_->CallMethod(
107 &method_call,
108 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
109 base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck,
110 weak_ptr_factory_.GetWeakPtr(),
111 callback));
114 // UpdateEngineClient override.
115 virtual void RebootAfterUpdate() OVERRIDE {
116 dbus::MethodCall method_call(
117 update_engine::kUpdateEngineInterface,
118 update_engine::kRebootIfNeeded);
120 VLOG(1) << "Requesting a reboot";
121 update_engine_proxy_->CallMethod(
122 &method_call,
123 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
124 base::Bind(&UpdateEngineClientImpl::OnRebootAfterUpdate,
125 weak_ptr_factory_.GetWeakPtr()));
128 // UpdateEngineClient override.
129 virtual void SetReleaseTrack(const std::string& track) OVERRIDE {
130 dbus::MethodCall method_call(
131 update_engine::kUpdateEngineInterface,
132 update_engine::kSetTrack);
133 dbus::MessageWriter writer(&method_call);
134 writer.AppendString(track);
136 VLOG(1) << "Requesting to set the release track to " << track;
137 update_engine_proxy_->CallMethod(
138 &method_call,
139 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
140 base::Bind(&UpdateEngineClientImpl::OnSetReleaseTrack,
141 weak_ptr_factory_.GetWeakPtr()));
144 // UpdateEngineClient override.
145 virtual void GetReleaseTrack(
146 const GetReleaseTrackCallback& callback) OVERRIDE {
147 dbus::MethodCall method_call(
148 update_engine::kUpdateEngineInterface,
149 update_engine::kGetTrack);
151 VLOG(1) << "Requesting to get the current release track";
152 update_engine_proxy_->CallMethod(
153 &method_call,
154 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
155 base::Bind(&UpdateEngineClientImpl::OnGetReleaseTrack,
156 weak_ptr_factory_.GetWeakPtr(),
157 callback));
160 // UpdateEngineClient override.
161 virtual Status GetLastStatus() OVERRIDE {
162 return last_status_;
165 private:
166 void GetUpdateEngineStatus() {
167 dbus::MethodCall method_call(
168 update_engine::kUpdateEngineInterface,
169 update_engine::kGetStatus);
170 update_engine_proxy_->CallMethodWithErrorCallback(
171 &method_call,
172 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
173 base::Bind(&UpdateEngineClientImpl::OnGetStatus,
174 weak_ptr_factory_.GetWeakPtr()),
175 base::Bind(&UpdateEngineClientImpl::OnGetStatusError,
176 weak_ptr_factory_.GetWeakPtr()));
179 // Called when a response for RequestUpdateCheck() is received.
180 void OnRequestUpdateCheck(const UpdateCheckCallback& callback,
181 dbus::Response* response) {
182 if (!response) {
183 LOG(ERROR) << "Failed to request update check";
184 callback.Run(UPDATE_RESULT_FAILED);
185 return;
187 callback.Run(UPDATE_RESULT_SUCCESS);
190 // Called when a response for RebootAfterUpdate() is received.
191 void OnRebootAfterUpdate(dbus::Response* response) {
192 if (!response) {
193 LOG(ERROR) << "Failed to request rebooting after update";
194 return;
198 // Called when a response for SetReleaseTrack() is received.
199 void OnSetReleaseTrack(dbus::Response* response) {
200 if (!response) {
201 LOG(ERROR) << "Failed to request setting release track";
202 return;
206 // Called when a response for GetReleaseTrack() is received.
207 void OnGetReleaseTrack(const GetReleaseTrackCallback& callback,
208 dbus::Response* response) {
209 if (!response) {
210 LOG(ERROR) << "Failed to request getting release track";
211 callback.Run("");
212 return;
214 dbus::MessageReader reader(response);
215 std::string release_track;
216 if (!reader.PopString(&release_track)) {
217 LOG(ERROR) << "Incorrect response: " << response->ToString();
218 callback.Run("");
219 return;
221 VLOG(1) << "The current release track received: " << release_track;
222 callback.Run(release_track);
225 // Called when a response for GetStatus is received.
226 void OnGetStatus(dbus::Response* response) {
227 if (!response) {
228 LOG(ERROR) << "Failed to get response for GetStatus request.";
229 return;
232 dbus::MessageReader reader(response);
233 std::string current_operation;
234 Status status;
235 if (!(reader.PopInt64(&status.last_checked_time) &&
236 reader.PopDouble(&status.download_progress) &&
237 reader.PopString(&current_operation) &&
238 reader.PopString(&status.new_version) &&
239 reader.PopInt64(&status.new_size))) {
240 LOG(ERROR) << "GetStatus had incorrect response: "
241 << response->ToString();
242 return;
244 status.status = UpdateStatusFromString(current_operation);
245 last_status_ = status;
246 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
249 // Called when GetStatus call failed.
250 void OnGetStatusError(dbus::ErrorResponse* error) {
251 LOG(ERROR) << "GetStatus request failed with error: " << error->ToString();
254 // Called when a status update signal is received.
255 void StatusUpdateReceived(dbus::Signal* signal) {
256 VLOG(1) << "Status update signal received: " << signal->ToString();
257 dbus::MessageReader reader(signal);
258 int64 last_checked_time = 0;
259 double progress = 0.0;
260 std::string current_operation;
261 std::string new_version;
262 int64_t new_size = 0;
263 if (!(reader.PopInt64(&last_checked_time) &&
264 reader.PopDouble(&progress) &&
265 reader.PopString(&current_operation) &&
266 reader.PopString(&new_version) &&
267 reader.PopInt64(&new_size))) {
268 LOG(ERROR) << "Status changed signal had incorrect parameters: "
269 << signal->ToString();
270 return;
272 Status status;
273 status.last_checked_time = last_checked_time;
274 status.download_progress = progress;
275 status.status = UpdateStatusFromString(current_operation);
276 status.new_version = new_version;
277 status.new_size = new_size;
279 last_status_ = status;
280 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
283 // Called when the status update signal is initially connected.
284 void StatusUpdateConnected(const std::string& interface_name,
285 const std::string& signal_name,
286 bool success) {
287 LOG_IF(WARNING, !success)
288 << "Failed to connect to status updated signal.";
291 dbus::ObjectProxy* update_engine_proxy_;
292 ObserverList<Observer> observers_;
293 Status last_status_;
295 // Note: This should remain the last member so it'll be destroyed and
296 // invalidate its weak pointers before any other members are destroyed.
297 base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_;
299 DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl);
302 // The UpdateEngineClient implementation used on Linux desktop,
303 // which does nothing.
304 class UpdateEngineClientStubImpl : public UpdateEngineClient {
305 // UpdateEngineClient overrides.
306 virtual void AddObserver(Observer* observer) OVERRIDE {}
307 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
308 virtual bool HasObserver(Observer* observer) OVERRIDE { return false; }
310 virtual void RequestUpdateCheck(
311 const UpdateCheckCallback& callback) OVERRIDE {
312 callback.Run(UPDATE_RESULT_NOTIMPLEMENTED);
314 virtual void RebootAfterUpdate() OVERRIDE {}
315 virtual void SetReleaseTrack(const std::string& track) OVERRIDE {}
316 virtual void GetReleaseTrack(
317 const GetReleaseTrackCallback& callback) OVERRIDE {
318 callback.Run("beta-channel");
320 virtual Status GetLastStatus() OVERRIDE { return Status(); }
323 UpdateEngineClient::UpdateEngineClient() {
326 UpdateEngineClient::~UpdateEngineClient() {
329 // static
330 UpdateEngineClient::UpdateCheckCallback
331 UpdateEngineClient::EmptyUpdateCheckCallback() {
332 return base::Bind(&EmptyUpdateCheckCallbackBody);
335 // static
336 UpdateEngineClient* UpdateEngineClient::Create(
337 DBusClientImplementationType type,
338 dbus::Bus* bus) {
339 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
340 return new UpdateEngineClientImpl(bus);
341 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
342 return new UpdateEngineClientStubImpl();
345 } // namespace chromeos