Add default implementations for AppWindowRegistry::Observer notifications.
[chromium-blink-merge.git] / chromeos / dbus / update_engine_client.cc
blobe9f68f8f02a63908117507740c24d71f51addfd3
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/command_line.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/strings/string_util.h"
12 #include "chromeos/chromeos_switches.h"
13 #include "dbus/bus.h"
14 #include "dbus/message.h"
15 #include "dbus/object_path.h"
16 #include "dbus/object_proxy.h"
17 #include "third_party/cros_system_api/dbus/service_constants.h"
19 namespace chromeos {
21 namespace {
23 const char kReleaseChannelDev[] = "dev-channel";
24 const char kReleaseChannelBeta[] = "beta-channel";
25 const char kReleaseChannelStable[] = "stable-channel";
27 // Delay between successive state transitions during AU.
28 const int kStateTransitionDefaultDelayMs = 3000;
30 // Delay between successive notifications about downloading progress
31 // during fake AU.
32 const int kStateTransitionDownloadingDelayMs = 250;
34 // Size of parts of a "new" image which are downloaded each
35 // |kStateTransitionDownloadingDelayMs| during fake AU.
36 const int64_t kDownloadSizeDelta = 1 << 19;
38 // Returns UPDATE_STATUS_ERROR on error.
39 UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString(
40 const std::string& str) {
41 if (str == update_engine::kUpdateStatusIdle)
42 return UpdateEngineClient::UPDATE_STATUS_IDLE;
43 if (str == update_engine::kUpdateStatusCheckingForUpdate)
44 return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
45 if (str == update_engine::kUpdateStatusUpdateAvailable)
46 return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
47 if (str == update_engine::kUpdateStatusDownloading)
48 return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
49 if (str == update_engine::kUpdateStatusVerifying)
50 return UpdateEngineClient::UPDATE_STATUS_VERIFYING;
51 if (str == update_engine::kUpdateStatusFinalizing)
52 return UpdateEngineClient::UPDATE_STATUS_FINALIZING;
53 if (str == update_engine::kUpdateStatusUpdatedNeedReboot)
54 return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
55 if (str == update_engine::kUpdateStatusReportingErrorEvent)
56 return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
57 return UpdateEngineClient::UPDATE_STATUS_ERROR;
60 // Used in UpdateEngineClient::EmptyUpdateCheckCallback().
61 void EmptyUpdateCheckCallbackBody(
62 UpdateEngineClient::UpdateCheckResult unused_result) {
65 bool IsValidChannel(const std::string& channel) {
66 return channel == kReleaseChannelDev ||
67 channel == kReleaseChannelBeta ||
68 channel == kReleaseChannelStable;
71 } // namespace
73 // The UpdateEngineClient implementation used in production.
74 class UpdateEngineClientImpl : public UpdateEngineClient {
75 public:
76 UpdateEngineClientImpl()
77 : update_engine_proxy_(NULL), last_status_(), weak_ptr_factory_(this) {}
79 virtual ~UpdateEngineClientImpl() {
82 // UpdateEngineClient implementation:
83 virtual void AddObserver(Observer* observer) OVERRIDE {
84 observers_.AddObserver(observer);
87 virtual void RemoveObserver(Observer* observer) OVERRIDE {
88 observers_.RemoveObserver(observer);
91 virtual bool HasObserver(Observer* observer) OVERRIDE {
92 return observers_.HasObserver(observer);
95 virtual void RequestUpdateCheck(
96 const UpdateCheckCallback& callback) OVERRIDE {
97 dbus::MethodCall method_call(
98 update_engine::kUpdateEngineInterface,
99 update_engine::kAttemptUpdate);
100 dbus::MessageWriter writer(&method_call);
101 writer.AppendString(""); // Unused.
102 writer.AppendString(""); // Unused.
104 VLOG(1) << "Requesting an update check";
105 update_engine_proxy_->CallMethod(
106 &method_call,
107 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
108 base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck,
109 weak_ptr_factory_.GetWeakPtr(),
110 callback));
113 virtual void RebootAfterUpdate() OVERRIDE {
114 dbus::MethodCall method_call(
115 update_engine::kUpdateEngineInterface,
116 update_engine::kRebootIfNeeded);
118 VLOG(1) << "Requesting a reboot";
119 update_engine_proxy_->CallMethod(
120 &method_call,
121 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
122 base::Bind(&UpdateEngineClientImpl::OnRebootAfterUpdate,
123 weak_ptr_factory_.GetWeakPtr()));
126 virtual void Rollback() OVERRIDE {
127 VLOG(1) << "Requesting a rollback";
128 dbus::MethodCall method_call(
129 update_engine::kUpdateEngineInterface,
130 update_engine::kAttemptRollback);
131 dbus::MessageWriter writer(&method_call);
132 writer.AppendBool(true /* powerwash */);
134 update_engine_proxy_->CallMethod(
135 &method_call,
136 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
137 base::Bind(&UpdateEngineClientImpl::OnRollback,
138 weak_ptr_factory_.GetWeakPtr()));
142 virtual void CanRollbackCheck(
143 const RollbackCheckCallback& callback) OVERRIDE {
144 dbus::MethodCall method_call(
145 update_engine::kUpdateEngineInterface,
146 update_engine::kCanRollback);
148 VLOG(1) << "Requesting to get rollback availability status";
149 update_engine_proxy_->CallMethod(
150 &method_call,
151 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
152 base::Bind(&UpdateEngineClientImpl::OnCanRollbackCheck,
153 weak_ptr_factory_.GetWeakPtr(),
154 callback));
157 virtual Status GetLastStatus() OVERRIDE {
158 return last_status_;
161 virtual void SetChannel(const std::string& target_channel,
162 bool is_powerwash_allowed) OVERRIDE {
163 if (!IsValidChannel(target_channel)) {
164 LOG(ERROR) << "Invalid channel name: " << target_channel;
165 return;
168 dbus::MethodCall method_call(
169 update_engine::kUpdateEngineInterface,
170 update_engine::kSetChannel);
171 dbus::MessageWriter writer(&method_call);
172 writer.AppendString(target_channel);
173 writer.AppendBool(is_powerwash_allowed);
175 VLOG(1) << "Requesting to set channel: "
176 << "target_channel=" << target_channel << ", "
177 << "is_powerwash_allowed=" << is_powerwash_allowed;
178 update_engine_proxy_->CallMethod(
179 &method_call,
180 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
181 base::Bind(&UpdateEngineClientImpl::OnSetChannel,
182 weak_ptr_factory_.GetWeakPtr()));
185 virtual void GetChannel(bool get_current_channel,
186 const GetChannelCallback& callback) OVERRIDE {
187 dbus::MethodCall method_call(
188 update_engine::kUpdateEngineInterface,
189 update_engine::kGetChannel);
190 dbus::MessageWriter writer(&method_call);
191 writer.AppendBool(get_current_channel);
193 VLOG(1) << "Requesting to get channel, get_current_channel="
194 << get_current_channel;
195 update_engine_proxy_->CallMethod(
196 &method_call,
197 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
198 base::Bind(&UpdateEngineClientImpl::OnGetChannel,
199 weak_ptr_factory_.GetWeakPtr(),
200 callback));
203 protected:
204 virtual void Init(dbus::Bus* bus) OVERRIDE {
205 update_engine_proxy_ = bus->GetObjectProxy(
206 update_engine::kUpdateEngineServiceName,
207 dbus::ObjectPath(update_engine::kUpdateEngineServicePath));
209 // Monitor the D-Bus signal for brightness changes. Only the power
210 // manager knows the actual brightness level. We don't cache the
211 // brightness level in Chrome as it will make things less reliable.
212 update_engine_proxy_->ConnectToSignal(
213 update_engine::kUpdateEngineInterface,
214 update_engine::kStatusUpdate,
215 base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived,
216 weak_ptr_factory_.GetWeakPtr()),
217 base::Bind(&UpdateEngineClientImpl::StatusUpdateConnected,
218 weak_ptr_factory_.GetWeakPtr()));
220 // Get update engine status for the initial status. Update engine won't
221 // send StatusUpdate signal unless there is a status change. If chrome
222 // crashes after UPDATE_STATUS_UPDATED_NEED_REBOOT status is set,
223 // restarted chrome would not get this status. See crbug.com/154104.
224 GetUpdateEngineStatus();
227 private:
228 void GetUpdateEngineStatus() {
229 dbus::MethodCall method_call(
230 update_engine::kUpdateEngineInterface,
231 update_engine::kGetStatus);
232 update_engine_proxy_->CallMethodWithErrorCallback(
233 &method_call,
234 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
235 base::Bind(&UpdateEngineClientImpl::OnGetStatus,
236 weak_ptr_factory_.GetWeakPtr()),
237 base::Bind(&UpdateEngineClientImpl::OnGetStatusError,
238 weak_ptr_factory_.GetWeakPtr()));
241 // Called when a response for RequestUpdateCheck() is received.
242 void OnRequestUpdateCheck(const UpdateCheckCallback& callback,
243 dbus::Response* response) {
244 if (!response) {
245 LOG(ERROR) << "Failed to request update check";
246 callback.Run(UPDATE_RESULT_FAILED);
247 return;
249 callback.Run(UPDATE_RESULT_SUCCESS);
252 // Called when a response for RebootAfterUpdate() is received.
253 void OnRebootAfterUpdate(dbus::Response* response) {
254 if (!response) {
255 LOG(ERROR) << "Failed to request rebooting after update";
256 return;
260 // Called when a response for Rollback() is received.
261 void OnRollback(dbus::Response* response) {
262 if (!response) {
263 LOG(ERROR) << "Failed to rollback";
264 return;
268 // Called when a response for CanRollbackCheck() is received.
269 void OnCanRollbackCheck(const RollbackCheckCallback& callback,
270 dbus::Response* response) {
271 if (!response) {
272 LOG(ERROR) << "Failed to request rollback availability status";
273 callback.Run(false);
274 return;
276 dbus::MessageReader reader(response);
277 bool can_rollback;
278 if (!reader.PopBool(&can_rollback)) {
279 LOG(ERROR) << "Incorrect response: " << response->ToString();
280 callback.Run(false);
281 return;
283 VLOG(1) << "Rollback availability status received: " << can_rollback;
284 callback.Run(can_rollback);
287 // Called when a response for GetStatus is received.
288 void OnGetStatus(dbus::Response* response) {
289 if (!response) {
290 LOG(ERROR) << "Failed to get response for GetStatus request.";
291 return;
294 dbus::MessageReader reader(response);
295 std::string current_operation;
296 Status status;
297 if (!(reader.PopInt64(&status.last_checked_time) &&
298 reader.PopDouble(&status.download_progress) &&
299 reader.PopString(&current_operation) &&
300 reader.PopString(&status.new_version) &&
301 reader.PopInt64(&status.new_size))) {
302 LOG(ERROR) << "GetStatus had incorrect response: "
303 << response->ToString();
304 return;
306 status.status = UpdateStatusFromString(current_operation);
307 last_status_ = status;
308 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
311 // Called when GetStatus call failed.
312 void OnGetStatusError(dbus::ErrorResponse* error) {
313 LOG(ERROR) << "GetStatus request failed with error: "
314 << (error ? error->ToString() : "");
317 // Called when a response for SetReleaseChannel() is received.
318 void OnSetChannel(dbus::Response* response) {
319 if (!response) {
320 LOG(ERROR) << "Failed to request setting channel";
321 return;
323 VLOG(1) << "Succeeded to set channel";
326 // Called when a response for GetChannel() is received.
327 void OnGetChannel(const GetChannelCallback& callback,
328 dbus::Response* response) {
329 if (!response) {
330 LOG(ERROR) << "Failed to request getting channel";
331 callback.Run("");
332 return;
334 dbus::MessageReader reader(response);
335 std::string channel;
336 if (!reader.PopString(&channel)) {
337 LOG(ERROR) << "Incorrect response: " << response->ToString();
338 callback.Run("");
339 return;
341 VLOG(1) << "The channel received: " << channel;
342 callback.Run(channel);
345 // Called when a status update signal is received.
346 void StatusUpdateReceived(dbus::Signal* signal) {
347 VLOG(1) << "Status update signal received: " << signal->ToString();
348 dbus::MessageReader reader(signal);
349 int64 last_checked_time = 0;
350 double progress = 0.0;
351 std::string current_operation;
352 std::string new_version;
353 int64_t new_size = 0;
354 if (!(reader.PopInt64(&last_checked_time) &&
355 reader.PopDouble(&progress) &&
356 reader.PopString(&current_operation) &&
357 reader.PopString(&new_version) &&
358 reader.PopInt64(&new_size))) {
359 LOG(ERROR) << "Status changed signal had incorrect parameters: "
360 << signal->ToString();
361 return;
363 Status status;
364 status.last_checked_time = last_checked_time;
365 status.download_progress = progress;
366 status.status = UpdateStatusFromString(current_operation);
367 status.new_version = new_version;
368 status.new_size = new_size;
370 last_status_ = status;
371 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
374 // Called when the status update signal is initially connected.
375 void StatusUpdateConnected(const std::string& interface_name,
376 const std::string& signal_name,
377 bool success) {
378 LOG_IF(WARNING, !success)
379 << "Failed to connect to status updated signal.";
382 dbus::ObjectProxy* update_engine_proxy_;
383 ObserverList<Observer> observers_;
384 Status last_status_;
386 // Note: This should remain the last member so it'll be destroyed and
387 // invalidate its weak pointers before any other members are destroyed.
388 base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_;
390 DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl);
393 // The UpdateEngineClient implementation used on Linux desktop,
394 // which does nothing.
395 class UpdateEngineClientStubImpl : public UpdateEngineClient {
396 // UpdateEngineClient implementation:
397 virtual void Init(dbus::Bus* bus) OVERRIDE {}
398 virtual void AddObserver(Observer* observer) OVERRIDE {}
399 virtual void RemoveObserver(Observer* observer) OVERRIDE {}
400 virtual bool HasObserver(Observer* observer) OVERRIDE { return false; }
402 virtual void RequestUpdateCheck(
403 const UpdateCheckCallback& callback) OVERRIDE {
404 callback.Run(UPDATE_RESULT_NOTIMPLEMENTED);
406 virtual void RebootAfterUpdate() OVERRIDE {}
407 virtual void Rollback() OVERRIDE {}
408 virtual void CanRollbackCheck(
409 const RollbackCheckCallback& callback) OVERRIDE {
410 callback.Run(true);
412 virtual Status GetLastStatus() OVERRIDE { return Status(); }
413 virtual void SetChannel(const std::string& target_channel,
414 bool is_powerwash_allowed) OVERRIDE {
415 VLOG(1) << "Requesting to set channel: "
416 << "target_channel=" << target_channel << ", "
417 << "is_powerwash_allowed=" << is_powerwash_allowed;
419 virtual void GetChannel(bool get_current_channel,
420 const GetChannelCallback& callback) OVERRIDE {
421 VLOG(1) << "Requesting to get channel, get_current_channel="
422 << get_current_channel;
423 callback.Run(kReleaseChannelBeta);
427 // The UpdateEngineClient implementation used on Linux desktop, which
428 // tries to emulate real update engine client.
429 class UpdateEngineClientFakeImpl : public UpdateEngineClientStubImpl {
430 public:
431 UpdateEngineClientFakeImpl() : weak_factory_(this) {
434 virtual ~UpdateEngineClientFakeImpl() {
437 // UpdateEngineClient implementation:
438 virtual void AddObserver(Observer* observer) OVERRIDE {
439 if (observer)
440 observers_.AddObserver(observer);
443 virtual void RemoveObserver(Observer* observer) OVERRIDE {
444 if (observer)
445 observers_.RemoveObserver(observer);
448 virtual bool HasObserver(Observer* observer) OVERRIDE {
449 return observers_.HasObserver(observer);
452 virtual void RequestUpdateCheck(
453 const UpdateCheckCallback& callback) OVERRIDE {
454 if (last_status_.status != UPDATE_STATUS_IDLE) {
455 callback.Run(UPDATE_RESULT_FAILED);
456 return;
458 callback.Run(UPDATE_RESULT_SUCCESS);
459 last_status_.status = UPDATE_STATUS_CHECKING_FOR_UPDATE;
460 last_status_.download_progress = 0.0;
461 last_status_.last_checked_time = 0;
462 last_status_.new_size = 0;
463 base::MessageLoop::current()->PostDelayedTask(
464 FROM_HERE,
465 base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
466 weak_factory_.GetWeakPtr()),
467 base::TimeDelta::FromMilliseconds(kStateTransitionDefaultDelayMs));
470 virtual Status GetLastStatus() OVERRIDE { return last_status_; }
472 private:
473 void StateTransition() {
474 UpdateStatusOperation next_status = UPDATE_STATUS_ERROR;
475 int delay_ms = kStateTransitionDefaultDelayMs;
476 switch (last_status_.status) {
477 case UPDATE_STATUS_ERROR:
478 case UPDATE_STATUS_IDLE:
479 case UPDATE_STATUS_UPDATED_NEED_REBOOT:
480 case UPDATE_STATUS_REPORTING_ERROR_EVENT:
481 return;
482 case UPDATE_STATUS_CHECKING_FOR_UPDATE:
483 next_status = UPDATE_STATUS_UPDATE_AVAILABLE;
484 break;
485 case UPDATE_STATUS_UPDATE_AVAILABLE:
486 next_status = UPDATE_STATUS_DOWNLOADING;
487 break;
488 case UPDATE_STATUS_DOWNLOADING:
489 if (last_status_.download_progress >= 1.0) {
490 next_status = UPDATE_STATUS_VERIFYING;
491 } else {
492 next_status = UPDATE_STATUS_DOWNLOADING;
493 last_status_.download_progress += 0.01;
494 last_status_.new_size = kDownloadSizeDelta;
495 delay_ms = kStateTransitionDownloadingDelayMs;
497 break;
498 case UPDATE_STATUS_VERIFYING:
499 next_status = UPDATE_STATUS_FINALIZING;
500 break;
501 case UPDATE_STATUS_FINALIZING:
502 next_status = UPDATE_STATUS_IDLE;
503 break;
505 last_status_.status = next_status;
506 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(last_status_));
507 if (last_status_.status != UPDATE_STATUS_IDLE) {
508 base::MessageLoop::current()->PostDelayedTask(
509 FROM_HERE,
510 base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
511 weak_factory_.GetWeakPtr()),
512 base::TimeDelta::FromMilliseconds(delay_ms));
516 ObserverList<Observer> observers_;
517 Status last_status_;
519 base::WeakPtrFactory<UpdateEngineClientFakeImpl> weak_factory_;
521 DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientFakeImpl);
524 UpdateEngineClient::UpdateEngineClient() {
527 UpdateEngineClient::~UpdateEngineClient() {
530 // static
531 UpdateEngineClient::UpdateCheckCallback
532 UpdateEngineClient::EmptyUpdateCheckCallback() {
533 return base::Bind(&EmptyUpdateCheckCallbackBody);
536 // static
537 UpdateEngineClient* UpdateEngineClient::Create(
538 DBusClientImplementationType type) {
539 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
540 return new UpdateEngineClientImpl();
541 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
542 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kTestAutoUpdateUI))
543 return new UpdateEngineClientFakeImpl();
544 else
545 return new UpdateEngineClientStubImpl();
548 } // namespace chromeos