Add type annotations to exif_parser.js.
[chromium-blink-merge.git] / chromeos / dbus / update_engine_client.cc
blob321b2472297cbd22324ab8f60b08af398c3d3288
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 <algorithm>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/macros.h"
13 #include "base/message_loop/message_loop.h"
14 #include "base/strings/string_util.h"
15 #include "chromeos/chromeos_switches.h"
16 #include "dbus/bus.h"
17 #include "dbus/message.h"
18 #include "dbus/object_path.h"
19 #include "dbus/object_proxy.h"
20 #include "third_party/cros_system_api/dbus/service_constants.h"
22 namespace chromeos {
24 namespace {
26 const char kReleaseChannelDev[] = "dev-channel";
27 const char kReleaseChannelBeta[] = "beta-channel";
28 const char kReleaseChannelStable[] = "stable-channel";
30 // List of release channels ordered by stability.
31 const char* kReleaseChannelsList[] = {kReleaseChannelDev,
32 kReleaseChannelBeta,
33 kReleaseChannelStable};
35 // Delay between successive state transitions during AU.
36 const int kStateTransitionDefaultDelayMs = 3000;
38 // Delay between successive notifications about downloading progress
39 // during fake AU.
40 const int kStateTransitionDownloadingDelayMs = 250;
42 // Size of parts of a "new" image which are downloaded each
43 // |kStateTransitionDownloadingDelayMs| during fake AU.
44 const int64_t kDownloadSizeDelta = 1 << 19;
46 // Returns UPDATE_STATUS_ERROR on error.
47 UpdateEngineClient::UpdateStatusOperation UpdateStatusFromString(
48 const std::string& str) {
49 VLOG(1) << "UpdateStatusFromString got " << str << " as input.";
50 if (str == update_engine::kUpdateStatusIdle)
51 return UpdateEngineClient::UPDATE_STATUS_IDLE;
52 if (str == update_engine::kUpdateStatusCheckingForUpdate)
53 return UpdateEngineClient::UPDATE_STATUS_CHECKING_FOR_UPDATE;
54 if (str == update_engine::kUpdateStatusUpdateAvailable)
55 return UpdateEngineClient::UPDATE_STATUS_UPDATE_AVAILABLE;
56 if (str == update_engine::kUpdateStatusDownloading)
57 return UpdateEngineClient::UPDATE_STATUS_DOWNLOADING;
58 if (str == update_engine::kUpdateStatusVerifying)
59 return UpdateEngineClient::UPDATE_STATUS_VERIFYING;
60 if (str == update_engine::kUpdateStatusFinalizing)
61 return UpdateEngineClient::UPDATE_STATUS_FINALIZING;
62 if (str == update_engine::kUpdateStatusUpdatedNeedReboot)
63 return UpdateEngineClient::UPDATE_STATUS_UPDATED_NEED_REBOOT;
64 if (str == update_engine::kUpdateStatusReportingErrorEvent)
65 return UpdateEngineClient::UPDATE_STATUS_REPORTING_ERROR_EVENT;
66 if (str == update_engine::kUpdateStatusAttemptingRollback)
67 return UpdateEngineClient::UPDATE_STATUS_ATTEMPTING_ROLLBACK;
68 return UpdateEngineClient::UPDATE_STATUS_ERROR;
71 // Used in UpdateEngineClient::EmptyUpdateCheckCallback().
72 void EmptyUpdateCheckCallbackBody(
73 UpdateEngineClient::UpdateCheckResult unused_result) {
76 bool IsValidChannel(const std::string& channel) {
77 return channel == kReleaseChannelDev || channel == kReleaseChannelBeta ||
78 channel == kReleaseChannelStable;
81 } // namespace
83 // The UpdateEngineClient implementation used in production.
84 class UpdateEngineClientImpl : public UpdateEngineClient {
85 public:
86 UpdateEngineClientImpl()
87 : update_engine_proxy_(NULL), last_status_(), weak_ptr_factory_(this) {}
89 virtual ~UpdateEngineClientImpl() {
92 // UpdateEngineClient implementation:
93 virtual void AddObserver(Observer* observer) override {
94 observers_.AddObserver(observer);
97 virtual void RemoveObserver(Observer* observer) override {
98 observers_.RemoveObserver(observer);
101 virtual bool HasObserver(const Observer* observer) const override {
102 return observers_.HasObserver(observer);
105 virtual void RequestUpdateCheck(
106 const UpdateCheckCallback& callback) override {
107 dbus::MethodCall method_call(
108 update_engine::kUpdateEngineInterface,
109 update_engine::kAttemptUpdate);
110 dbus::MessageWriter writer(&method_call);
111 writer.AppendString(""); // Unused.
112 writer.AppendString(""); // Unused.
114 VLOG(1) << "Requesting an update check";
115 update_engine_proxy_->CallMethod(
116 &method_call,
117 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
118 base::Bind(&UpdateEngineClientImpl::OnRequestUpdateCheck,
119 weak_ptr_factory_.GetWeakPtr(),
120 callback));
123 virtual void RebootAfterUpdate() override {
124 dbus::MethodCall method_call(
125 update_engine::kUpdateEngineInterface,
126 update_engine::kRebootIfNeeded);
128 VLOG(1) << "Requesting a reboot";
129 update_engine_proxy_->CallMethod(
130 &method_call,
131 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
132 base::Bind(&UpdateEngineClientImpl::OnRebootAfterUpdate,
133 weak_ptr_factory_.GetWeakPtr()));
136 virtual void Rollback() override {
137 VLOG(1) << "Requesting a rollback";
138 dbus::MethodCall method_call(
139 update_engine::kUpdateEngineInterface,
140 update_engine::kAttemptRollback);
141 dbus::MessageWriter writer(&method_call);
142 writer.AppendBool(true /* powerwash */);
144 update_engine_proxy_->CallMethod(
145 &method_call,
146 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
147 base::Bind(&UpdateEngineClientImpl::OnRollback,
148 weak_ptr_factory_.GetWeakPtr()));
152 virtual void CanRollbackCheck(
153 const RollbackCheckCallback& callback) override {
154 dbus::MethodCall method_call(
155 update_engine::kUpdateEngineInterface,
156 update_engine::kCanRollback);
158 VLOG(1) << "Requesting to get rollback availability status";
159 update_engine_proxy_->CallMethod(
160 &method_call,
161 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
162 base::Bind(&UpdateEngineClientImpl::OnCanRollbackCheck,
163 weak_ptr_factory_.GetWeakPtr(),
164 callback));
167 virtual Status GetLastStatus() override {
168 return last_status_;
171 virtual void SetChannel(const std::string& target_channel,
172 bool is_powerwash_allowed) override {
173 if (!IsValidChannel(target_channel)) {
174 LOG(ERROR) << "Invalid channel name: " << target_channel;
175 return;
178 dbus::MethodCall method_call(
179 update_engine::kUpdateEngineInterface,
180 update_engine::kSetChannel);
181 dbus::MessageWriter writer(&method_call);
182 writer.AppendString(target_channel);
183 writer.AppendBool(is_powerwash_allowed);
185 VLOG(1) << "Requesting to set channel: "
186 << "target_channel=" << target_channel << ", "
187 << "is_powerwash_allowed=" << is_powerwash_allowed;
188 update_engine_proxy_->CallMethod(
189 &method_call,
190 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
191 base::Bind(&UpdateEngineClientImpl::OnSetChannel,
192 weak_ptr_factory_.GetWeakPtr()));
195 virtual void GetChannel(bool get_current_channel,
196 const GetChannelCallback& callback) override {
197 dbus::MethodCall method_call(
198 update_engine::kUpdateEngineInterface,
199 update_engine::kGetChannel);
200 dbus::MessageWriter writer(&method_call);
201 writer.AppendBool(get_current_channel);
203 VLOG(1) << "Requesting to get channel, get_current_channel="
204 << get_current_channel;
205 update_engine_proxy_->CallMethod(
206 &method_call,
207 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
208 base::Bind(&UpdateEngineClientImpl::OnGetChannel,
209 weak_ptr_factory_.GetWeakPtr(),
210 callback));
213 protected:
214 virtual void Init(dbus::Bus* bus) override {
215 update_engine_proxy_ = bus->GetObjectProxy(
216 update_engine::kUpdateEngineServiceName,
217 dbus::ObjectPath(update_engine::kUpdateEngineServicePath));
219 // Monitor the D-Bus signal for brightness changes. Only the power
220 // manager knows the actual brightness level. We don't cache the
221 // brightness level in Chrome as it will make things less reliable.
222 update_engine_proxy_->ConnectToSignal(
223 update_engine::kUpdateEngineInterface,
224 update_engine::kStatusUpdate,
225 base::Bind(&UpdateEngineClientImpl::StatusUpdateReceived,
226 weak_ptr_factory_.GetWeakPtr()),
227 base::Bind(&UpdateEngineClientImpl::StatusUpdateConnected,
228 weak_ptr_factory_.GetWeakPtr()));
230 // Get update engine status for the initial status. Update engine won't
231 // send StatusUpdate signal unless there is a status change. If chrome
232 // crashes after UPDATE_STATUS_UPDATED_NEED_REBOOT status is set,
233 // restarted chrome would not get this status. See crbug.com/154104.
234 GetUpdateEngineStatus();
237 private:
238 void GetUpdateEngineStatus() {
239 dbus::MethodCall method_call(
240 update_engine::kUpdateEngineInterface,
241 update_engine::kGetStatus);
242 update_engine_proxy_->CallMethodWithErrorCallback(
243 &method_call,
244 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
245 base::Bind(&UpdateEngineClientImpl::OnGetStatus,
246 weak_ptr_factory_.GetWeakPtr()),
247 base::Bind(&UpdateEngineClientImpl::OnGetStatusError,
248 weak_ptr_factory_.GetWeakPtr()));
251 // Called when a response for RequestUpdateCheck() is received.
252 void OnRequestUpdateCheck(const UpdateCheckCallback& callback,
253 dbus::Response* response) {
254 if (!response) {
255 LOG(ERROR) << "Failed to request update check";
256 callback.Run(UPDATE_RESULT_FAILED);
257 return;
259 callback.Run(UPDATE_RESULT_SUCCESS);
262 // Called when a response for RebootAfterUpdate() is received.
263 void OnRebootAfterUpdate(dbus::Response* response) {
264 if (!response) {
265 LOG(ERROR) << "Failed to request rebooting after update";
266 return;
270 // Called when a response for Rollback() is received.
271 void OnRollback(dbus::Response* response) {
272 if (!response) {
273 LOG(ERROR) << "Failed to rollback";
274 return;
278 // Called when a response for CanRollbackCheck() is received.
279 void OnCanRollbackCheck(const RollbackCheckCallback& callback,
280 dbus::Response* response) {
281 if (!response) {
282 LOG(ERROR) << "Failed to request rollback availability status";
283 callback.Run(false);
284 return;
286 dbus::MessageReader reader(response);
287 bool can_rollback;
288 if (!reader.PopBool(&can_rollback)) {
289 LOG(ERROR) << "Incorrect response: " << response->ToString();
290 callback.Run(false);
291 return;
293 VLOG(1) << "Rollback availability status received: " << can_rollback;
294 callback.Run(can_rollback);
297 // Called when a response for GetStatus is received.
298 void OnGetStatus(dbus::Response* response) {
299 if (!response) {
300 LOG(ERROR) << "Failed to get response for GetStatus request.";
301 return;
304 dbus::MessageReader reader(response);
305 std::string current_operation;
306 Status status;
307 if (!(reader.PopInt64(&status.last_checked_time) &&
308 reader.PopDouble(&status.download_progress) &&
309 reader.PopString(&current_operation) &&
310 reader.PopString(&status.new_version) &&
311 reader.PopInt64(&status.new_size))) {
312 LOG(ERROR) << "GetStatus had incorrect response: "
313 << response->ToString();
314 return;
316 status.status = UpdateStatusFromString(current_operation);
317 last_status_ = status;
318 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
321 // Called when GetStatus call failed.
322 void OnGetStatusError(dbus::ErrorResponse* error) {
323 LOG(ERROR) << "GetStatus request failed with error: "
324 << (error ? error->ToString() : "");
327 // Called when a response for SetReleaseChannel() is received.
328 void OnSetChannel(dbus::Response* response) {
329 if (!response) {
330 LOG(ERROR) << "Failed to request setting channel";
331 return;
333 VLOG(1) << "Succeeded to set channel";
336 // Called when a response for GetChannel() is received.
337 void OnGetChannel(const GetChannelCallback& callback,
338 dbus::Response* response) {
339 if (!response) {
340 LOG(ERROR) << "Failed to request getting channel";
341 callback.Run("");
342 return;
344 dbus::MessageReader reader(response);
345 std::string channel;
346 if (!reader.PopString(&channel)) {
347 LOG(ERROR) << "Incorrect response: " << response->ToString();
348 callback.Run("");
349 return;
351 VLOG(1) << "The channel received: " << channel;
352 callback.Run(channel);
355 // Called when a status update signal is received.
356 void StatusUpdateReceived(dbus::Signal* signal) {
357 VLOG(1) << "Status update signal received: " << signal->ToString();
358 dbus::MessageReader reader(signal);
359 int64 last_checked_time = 0;
360 double progress = 0.0;
361 std::string current_operation;
362 std::string new_version;
363 int64_t new_size = 0;
364 if (!(reader.PopInt64(&last_checked_time) &&
365 reader.PopDouble(&progress) &&
366 reader.PopString(&current_operation) &&
367 reader.PopString(&new_version) &&
368 reader.PopInt64(&new_size))) {
369 LOG(ERROR) << "Status changed signal had incorrect parameters: "
370 << signal->ToString();
371 return;
373 Status status;
374 status.last_checked_time = last_checked_time;
375 status.download_progress = progress;
376 status.status = UpdateStatusFromString(current_operation);
377 status.new_version = new_version;
378 status.new_size = new_size;
380 last_status_ = status;
381 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(status));
384 // Called when the status update signal is initially connected.
385 void StatusUpdateConnected(const std::string& interface_name,
386 const std::string& signal_name,
387 bool success) {
388 LOG_IF(WARNING, !success)
389 << "Failed to connect to status updated signal.";
392 dbus::ObjectProxy* update_engine_proxy_;
393 ObserverList<Observer> observers_;
394 Status last_status_;
396 // Note: This should remain the last member so it'll be destroyed and
397 // invalidate its weak pointers before any other members are destroyed.
398 base::WeakPtrFactory<UpdateEngineClientImpl> weak_ptr_factory_;
400 DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientImpl);
403 // The UpdateEngineClient implementation used on Linux desktop,
404 // which does nothing.
405 class UpdateEngineClientStubImpl : public UpdateEngineClient {
406 public:
407 UpdateEngineClientStubImpl()
408 : current_channel_(kReleaseChannelBeta),
409 target_channel_(kReleaseChannelBeta) {}
411 // UpdateEngineClient implementation:
412 virtual void Init(dbus::Bus* bus) override {}
413 virtual void AddObserver(Observer* observer) override {}
414 virtual void RemoveObserver(Observer* observer) override {}
415 virtual bool HasObserver(const Observer* observer) const override {
416 return false;
419 virtual void RequestUpdateCheck(
420 const UpdateCheckCallback& callback) override {
421 callback.Run(UPDATE_RESULT_NOTIMPLEMENTED);
423 virtual void RebootAfterUpdate() override {}
424 virtual void Rollback() override {}
425 virtual void CanRollbackCheck(
426 const RollbackCheckCallback& callback) override {
427 callback.Run(true);
429 virtual Status GetLastStatus() override { return Status(); }
430 virtual void SetChannel(const std::string& target_channel,
431 bool is_powerwash_allowed) override {
432 VLOG(1) << "Requesting to set channel: "
433 << "target_channel=" << target_channel << ", "
434 << "is_powerwash_allowed=" << is_powerwash_allowed;
435 target_channel_ = target_channel;
437 virtual void GetChannel(bool get_current_channel,
438 const GetChannelCallback& callback) override {
439 VLOG(1) << "Requesting to get channel, get_current_channel="
440 << get_current_channel;
441 if (get_current_channel)
442 callback.Run(current_channel_);
443 else
444 callback.Run(target_channel_);
447 std::string current_channel_;
448 std::string target_channel_;
451 // The UpdateEngineClient implementation used on Linux desktop, which
452 // tries to emulate real update engine client.
453 class UpdateEngineClientFakeImpl : public UpdateEngineClientStubImpl {
454 public:
455 UpdateEngineClientFakeImpl() : weak_factory_(this) {
458 virtual ~UpdateEngineClientFakeImpl() {
461 // UpdateEngineClient implementation:
462 virtual void AddObserver(Observer* observer) override {
463 if (observer)
464 observers_.AddObserver(observer);
467 virtual void RemoveObserver(Observer* observer) override {
468 if (observer)
469 observers_.RemoveObserver(observer);
472 virtual bool HasObserver(const Observer* observer) const override {
473 return observers_.HasObserver(observer);
476 virtual void RequestUpdateCheck(
477 const UpdateCheckCallback& callback) override {
478 if (last_status_.status != UPDATE_STATUS_IDLE) {
479 callback.Run(UPDATE_RESULT_FAILED);
480 return;
482 callback.Run(UPDATE_RESULT_SUCCESS);
483 last_status_.status = UPDATE_STATUS_CHECKING_FOR_UPDATE;
484 last_status_.download_progress = 0.0;
485 last_status_.last_checked_time = 0;
486 last_status_.new_size = 0;
487 base::MessageLoop::current()->PostDelayedTask(
488 FROM_HERE,
489 base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
490 weak_factory_.GetWeakPtr()),
491 base::TimeDelta::FromMilliseconds(kStateTransitionDefaultDelayMs));
494 virtual Status GetLastStatus() override { return last_status_; }
496 private:
497 void StateTransition() {
498 UpdateStatusOperation next_status = UPDATE_STATUS_ERROR;
499 int delay_ms = kStateTransitionDefaultDelayMs;
500 switch (last_status_.status) {
501 case UPDATE_STATUS_ERROR:
502 case UPDATE_STATUS_IDLE:
503 case UPDATE_STATUS_UPDATED_NEED_REBOOT:
504 case UPDATE_STATUS_REPORTING_ERROR_EVENT:
505 case UPDATE_STATUS_ATTEMPTING_ROLLBACK:
506 return;
507 case UPDATE_STATUS_CHECKING_FOR_UPDATE:
508 next_status = UPDATE_STATUS_UPDATE_AVAILABLE;
509 break;
510 case UPDATE_STATUS_UPDATE_AVAILABLE:
511 next_status = UPDATE_STATUS_DOWNLOADING;
512 break;
513 case UPDATE_STATUS_DOWNLOADING:
514 if (last_status_.download_progress >= 1.0) {
515 next_status = UPDATE_STATUS_VERIFYING;
516 } else {
517 next_status = UPDATE_STATUS_DOWNLOADING;
518 last_status_.download_progress += 0.01;
519 last_status_.new_size = kDownloadSizeDelta;
520 delay_ms = kStateTransitionDownloadingDelayMs;
522 break;
523 case UPDATE_STATUS_VERIFYING:
524 next_status = UPDATE_STATUS_FINALIZING;
525 break;
526 case UPDATE_STATUS_FINALIZING:
527 next_status = UPDATE_STATUS_IDLE;
528 break;
530 last_status_.status = next_status;
531 FOR_EACH_OBSERVER(Observer, observers_, UpdateStatusChanged(last_status_));
532 if (last_status_.status != UPDATE_STATUS_IDLE) {
533 base::MessageLoop::current()->PostDelayedTask(
534 FROM_HERE,
535 base::Bind(&UpdateEngineClientFakeImpl::StateTransition,
536 weak_factory_.GetWeakPtr()),
537 base::TimeDelta::FromMilliseconds(delay_ms));
541 ObserverList<Observer> observers_;
542 Status last_status_;
544 base::WeakPtrFactory<UpdateEngineClientFakeImpl> weak_factory_;
546 DISALLOW_COPY_AND_ASSIGN(UpdateEngineClientFakeImpl);
549 UpdateEngineClient::UpdateEngineClient() {
552 UpdateEngineClient::~UpdateEngineClient() {
555 // static
556 UpdateEngineClient::UpdateCheckCallback
557 UpdateEngineClient::EmptyUpdateCheckCallback() {
558 return base::Bind(&EmptyUpdateCheckCallbackBody);
561 // static
562 UpdateEngineClient* UpdateEngineClient::Create(
563 DBusClientImplementationType type) {
564 if (type == REAL_DBUS_CLIENT_IMPLEMENTATION)
565 return new UpdateEngineClientImpl();
566 DCHECK_EQ(STUB_DBUS_CLIENT_IMPLEMENTATION, type);
567 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
568 switches::kTestAutoUpdateUI))
569 return new UpdateEngineClientFakeImpl();
570 else
571 return new UpdateEngineClientStubImpl();
574 // static
575 bool UpdateEngineClient::IsTargetChannelMoreStable(
576 const std::string& current_channel,
577 const std::string& target_channel) {
578 auto cix = std::find(kReleaseChannelsList,
579 kReleaseChannelsList + arraysize(kReleaseChannelsList),
580 current_channel);
581 auto tix = std::find(kReleaseChannelsList,
582 kReleaseChannelsList + arraysize(kReleaseChannelsList),
583 target_channel);
584 return tix > cix;
587 } // namespace chromeos