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"
8 #include "base/callback.h"
9 #include "base/string_util.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"
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
) {
48 // The UpdateEngineClient implementation used in production.
49 class UpdateEngineClientImpl
: public UpdateEngineClient
{
51 explicit UpdateEngineClientImpl(dbus::Bus
* bus
)
52 : update_engine_proxy_(NULL
),
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(
108 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
109 base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck
,
110 weak_ptr_factory_
.GetWeakPtr(),
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(
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(
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(
154 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT
,
155 base::Bind(&UpdateEngineClientImpl::OnGetReleaseTrack
,
156 weak_ptr_factory_
.GetWeakPtr(),
160 // UpdateEngineClient override.
161 virtual Status
GetLastStatus() OVERRIDE
{
166 void GetUpdateEngineStatus() {
167 dbus::MethodCall
method_call(
168 update_engine::kUpdateEngineInterface
,
169 update_engine::kGetStatus
);
170 update_engine_proxy_
->CallMethodWithErrorCallback(
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
) {
183 LOG(ERROR
) << "Failed to request update check";
184 callback
.Run(UPDATE_RESULT_FAILED
);
187 callback
.Run(UPDATE_RESULT_SUCCESS
);
190 // Called when a response for RebootAfterUpdate() is received.
191 void OnRebootAfterUpdate(dbus::Response
* response
) {
193 LOG(ERROR
) << "Failed to request rebooting after update";
198 // Called when a response for SetReleaseTrack() is received.
199 void OnSetReleaseTrack(dbus::Response
* response
) {
201 LOG(ERROR
) << "Failed to request setting release track";
206 // Called when a response for GetReleaseTrack() is received.
207 void OnGetReleaseTrack(const GetReleaseTrackCallback
& callback
,
208 dbus::Response
* response
) {
210 LOG(ERROR
) << "Failed to request getting release track";
214 dbus::MessageReader
reader(response
);
215 std::string release_track
;
216 if (!reader
.PopString(&release_track
)) {
217 LOG(ERROR
) << "Incorrect response: " << response
->ToString();
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
) {
228 LOG(ERROR
) << "Failed to get response for GetStatus request.";
232 dbus::MessageReader
reader(response
);
233 std::string current_operation
;
235 if (!(reader
.PopInt64(&status
.last_checked_time
) &&
236 reader
.PopDouble(&status
.download_progress
) &&
237 reader
.PopString(¤t_operation
) &&
238 reader
.PopString(&status
.new_version
) &&
239 reader
.PopInt64(&status
.new_size
))) {
240 LOG(ERROR
) << "GetStatus had incorrect response: "
241 << response
->ToString();
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(¤t_operation
) &&
266 reader
.PopString(&new_version
) &&
267 reader
.PopInt64(&new_size
))) {
268 LOG(ERROR
) << "Status changed signal had incorrect parameters: "
269 << signal
->ToString();
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
,
287 LOG_IF(WARNING
, !success
)
288 << "Failed to connect to status updated signal.";
291 dbus::ObjectProxy
* update_engine_proxy_
;
292 ObserverList
<Observer
> observers_
;
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() {
330 UpdateEngineClient::UpdateCheckCallback
331 UpdateEngineClient::EmptyUpdateCheckCallback() {
332 return base::Bind(&EmptyUpdateCheckCallbackBody
);
336 UpdateEngineClient
* UpdateEngineClient::Create(
337 DBusClientImplementationType type
,
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